Added automatic image resizing functionality.

Greatly improved the browser responsiveness when loading the preview images.
This commit is contained in:
Sebastian Tschan 2012-02-12 01:01:27 +09:00
parent c4a615a58c
commit e39278b08f
8 changed files with 279 additions and 66 deletions

View File

@ -20,8 +20,10 @@
Aborted uploads can be resumed with browsers supporting the Blob API.
* **Chunked uploads:**
Large files can be uploaded in smaller chunks with browsers supporting the Blob API.
* **Automatic image resizing:**
Images can be automatically resized with browsers supporting the required JS APIs.
* **Preview images:**
A preview of image files can be displayed before uploading with browsers supporting the required HTML5 APIs.
A preview of image files can be displayed before uploading with browsers supporting the required JS APIs.
* **No browser plugins (e.g. Adobe Flash) required:**
The implementation is based on open standards like HTML5 and JavaScript and requires no additional browser plugins.
* **Graceful fallback for legacy browsers:**

View File

@ -40,6 +40,16 @@
background: url(../img/progressbar.gif) !important;
filter: none;
}
.fileupload-loading {
position: absolute;
left: 50%;
width: 128px;
height: 0;
background: url(../img/loading.gif) center no-repeat;
}
.fileupload-processing .fileupload-loading {
height: 128px;
}
/* Fix for IE 6: */
*html .fileinput-button {

BIN
img/loading.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,7 +1,7 @@
<!DOCTYPE HTML>
<!--
/*
* jQuery File Upload Plugin Demo 6.2
* jQuery File Upload Plugin Demo 6.4
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
@ -92,6 +92,8 @@
</div>
</div>
</div>
<!-- The loading indicator is shown during image processing -->
<div class="fileupload-loading"></div>
<br>
<!-- The table listing the files available for upload/download -->
<table class="table table-striped"><tbody class="files" data-toggle="modal-gallery" data-target="#modal-gallery"></tbody></table>
@ -194,9 +196,12 @@ var fileUploadErrors = {
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="js/vendor/jquery.ui.widget.js"></script>
<!-- The Templates and Load Image plugins are included for the FileUpload user interface -->
<!-- The Templates plugin is included to render the upload/download listings -->
<script src="http://blueimp.github.com/JavaScript-Templates/tmpl.min.js"></script>
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
<script src="http://blueimp.github.com/JavaScript-Load-Image/load-image.min.js"></script>
<!-- The Canvas to Blob plugin is included for image resizing functionality -->
<script src="http://blueimp.github.com/JavaScript-Canvas-to-Blob/canvas-to-blob.min.js"></script>
<!-- Bootstrap JS and Bootstrap Image Gallery are not required, but included for the demo -->
<script src="http://blueimp.github.com/cdn/js/bootstrap.min.js"></script>
<script src="http://blueimp.github.com/Bootstrap-Image-Gallery/bootstrap-image-gallery.min.js"></script>
@ -204,6 +209,8 @@ var fileUploadErrors = {
<script src="js/jquery.iframe-transport.js"></script>
<!-- The basic File Upload plugin -->
<script src="js/jquery.fileupload.js"></script>
<!-- The File Upload image processing plugin -->
<script src="js/jquery.fileupload-ip.js"></script>
<!-- The File Upload user interface plugin -->
<script src="js/jquery.fileupload-ui.js"></script>
<!-- The main application script -->

158
js/jquery.fileupload-ip.js vendored Normal file
View File

@ -0,0 +1,158 @@
/*
* jQuery File Upload Image Processing Plugin 1.0
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2012, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
*/
/*jslint nomen: true, unparam: true, regexp: true */
/*global define, window, document */
(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
define([
'jquery',
'./load-image.js',
'./canvas-to-blob.js',
'./jquery.fileupload.js'
], factory);
} else {
// Browser globals:
factory(
window.jQuery,
window.loadImage,
window.canvasToBlob
);
}
}(function ($, loadImage, canvasToBlob) {
'use strict';
// The File Upload IP version extends the basic fileupload widget
// with image processing functionality:
$.widget('blueimpIP.fileupload', $.blueimp.fileupload, {
options: {
// The regular expression to define which image files are to be
// resized, given that the browser supports the operation:
resizeSourceFileTypes: /^image\/(gif|jpeg|png)$/,
// The maximum file size of images that are to be resized:
resizeSourceMaxFileSize: 20000000, // 20MB
// The maximum width of the resized images:
resizeMaxWidth: undefined,
// The maximum height of the resized images:
resizeMaxHeight: undefined,
// The minimum width of the resized images:
resizeMinWidth: undefined,
// The minimum height of the resized images:
resizeMinHeight: undefined,
// The add callback is invoked as soon as files are added to the fileupload
// widget (via file input selection, drag & drop or add API call).
// See the basic file upload widget for more information:
add: function (e, data) {
$(this).fileupload('resize', data).done(function () {
data.submit();
});
}
},
// Resizes the image file at the given index and stores the created blob
// at the original position of the files list, returns a Promise object:
_resizeImage: function (files, index) {
var that = this,
options = this.options,
file = files[index],
deferred = $.Deferred(),
canvas,
blob;
loadImage(
file,
function (img) {
var width = img.width,
height = img.height;
canvas = loadImage.scale(img, {
maxWidth: options.resizeMaxWidth,
maxHeight: options.resizeMaxHeight,
minWidth: options.resizeMinWidth,
minHeight: options.resizeMinHeight,
canvas: true
});
if (width !== canvas.width || height !== canvas.height) {
canvasToBlob(canvas, function (blob) {
if (!blob.name) {
if (file.type === blob.type) {
blob.name = file.name;
} else if (file.name) {
blob.name = file.name.replace(
/\..+$/,
'.' + blob.type.substr(6)
);
}
}
files[index] = blob;
deferred.resolve();
}, file);
} else {
deferred.resolve();
}
}
);
return deferred.promise();
},
// Resizes the images given as files property of the data parameter,
// returns a Promise object that allows to bind a done handler, which
// will be invoked after processing all images is done:
resize: function (data) {
var that = this,
options = $.extend({}, this.options, data),
resizeAll = $.type(options.resizeSourceMaxFileSize) !== 'number';
$.each(data.files, function (index, file) {
if (that._resizeSupport &&
(options.resizeMaxWidth || options.resizeMaxHeight ||
options.resizeMinWidth || options.resizeMinHeight) &&
(resizeAll || file.size < options.resizeSourceMaxFileSize) &&
options.resizeSourceFileTypes.test(file.type)) {
that._processing += 1;
if (that._processing === 1) {
that.element.addClass('fileupload-processing');
}
that._processingQueue = that._processingQueue.pipe(function () {
var deferred = $.Deferred();
that._resizeImage(
data.files,
index
).done(function () {
that._processing -= 1;
if (that._processing === 0) {
that.element
.removeClass('fileupload-processing');
}
deferred.resolve();
});
return deferred.promise();
});
}
});
return this._processingQueue;
},
_create: function () {
$.blueimp.fileupload.prototype._create.call(this);
this._processing = 0;
this._processingQueue = $.Deferred().resolveWith(this).promise();
this._resizeSupport = canvasToBlob(
document.createElement('canvas'),
$.noop
);
}
});
}));

View File

@ -1,5 +1,5 @@
/*
* jQuery File Upload User Interface Plugin 6.3
* jQuery File Upload User Interface Plugin 6.4
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
@ -16,18 +16,26 @@
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
define(['jquery', 'tmpl', 'loadImage', './jquery.fileupload.js'], factory);
define([
'jquery',
'./tmpl.js',
'./load-image.js',
'./jquery.fileupload-ip.js'
], factory);
} else {
// Browser globals:
factory(window.jQuery, window.tmpl, window.loadImage);
factory(
window.jQuery,
window.tmpl,
window.loadImage
);
}
}(function ($, tmpl, loadImage) {
'use strict';
// The UI version extends the basic fileupload widget and adds
// a complete user interface based on the given upload/download
// templates.
$.widget('blueimpUI.fileupload', $.blueimp.fileupload, {
// The UI version extends the IP (image processing) version and adds
// complete user interface interaction:
$.widget('blueimpUI.fileupload', $.blueimpIP.fileupload, {
options: {
// By default, files added to the widget are uploaded as soon
@ -46,9 +54,9 @@
acceptFileTypes: /.+$/i,
// The regular expression to define for which files a preview
// image is shown, matched against the file type:
previewFileTypes: /^image\/(gif|jpeg|png)$/,
// The maximum file size for preview images:
previewMaxFileSize: 5000000, // 5MB
previewSourceFileTypes: /^image\/(gif|jpeg|png)$/,
// The maximum file size of images that are to be displayed as preview:
previewSourceMaxFileSize: 5000000, // 5MB
// The maximum width of the preview images:
previewMaxWidth: 80,
// The maximum height of the preview images:
@ -66,25 +74,28 @@
// See the basic file upload widget for more information:
add: function (e, data) {
var that = $(this).data('fileupload'),
options = that.options,
files = data.files;
that._adjustMaxNumberOfFiles(-files.length);
data.isAdjusted = true;
data.files.valid = data.isValidated = that._validate(files);
data.context = that._renderUpload(files)
.appendTo(that._files)
.data('data', data);
// Force reflow:
that._reflow = $.support.transition && data.context[0].offsetWidth;
that._transitionCallback(
data.context.addClass('in'),
function (node) {
if ((that._trigger('added', e, data) !== false) &&
(that.options.autoUpload || data.autoUpload) &&
data.isValidated) {
data.submit();
$(this).fileupload('resize', data).done(data, function () {
that._adjustMaxNumberOfFiles(-files.length);
data.isAdjusted = true;
data.files.valid = data.isValidated = that._validate(files);
data.context = that._renderUpload(files)
.appendTo(that._files)
.data('data', data);
// Force reflow:
that._reflow = $.support.transition && data.context[0].offsetWidth;
that._transitionCallback(
data.context.addClass('in'),
function (node) {
if ((that._trigger('added', e, data) !== false) &&
(options.autoUpload || data.autoUpload) &&
data.isValidated) {
data.submit();
}
}
}
);
);
});
},
// Callback for the start of each file upload request:
send: function (e, data) {
@ -358,33 +369,53 @@
})).children();
},
_renderPreview: function (file, node, callback) {
var that = this,
options = this.options;
loadImage(
file,
function (img) {
node.append(img);
// Force reflow:
that._reflow = $.support.transition &&
node[0].offsetWidth;
that._transitionCallback(
node.addClass('in'),
callback || $.noop
);
},
{
maxWidth: options.previewMaxWidth,
maxHeight: options.previewMaxHeight,
canvas: options.previewAsCanvas
}
);
},
_renderUpload: function (files) {
var that = this,
options = this.options,
nodes = this._renderTemplate(options.uploadTemplate, files);
nodes.find('.preview span').each(function (index, node) {
var file = files[index];
if (options.previewFileTypes.test(file.type) &&
(!options.previewMaxFileSize ||
file.size < options.previewMaxFileSize)) {
loadImage(
files[index],
function (img) {
$(node).append(img);
// Force reflow:
that._reflow = $.support.transition &&
node.offsetWidth;
$(node).addClass('in');
},
{
maxWidth: options.previewMaxWidth,
maxHeight: options.previewMaxHeight,
canvas: options.previewAsCanvas
}
);
}
});
return nodes;
options = this.options;
return this._renderTemplate(options.uploadTemplate, files)
.each(function (index, element) {
var file = files[index],
node = $(element),
previewNode = node.find('.preview span'),
hasPreview = previewNode.length &&
($.type(options.previewSourceMaxFileSize) !== 'number' ||
file.size < options.previewSourceMaxFileSize) &&
options.previewSourceFileTypes.test(file.type);
if (hasPreview) {
that._processingQueue = that._processingQueue.pipe(function () {
var deferred = $.Deferred();
that._renderPreview(
file,
previewNode,
deferred.resolve
);
return deferred.promise();
});
}
});
},
_renderDownload: function (files) {
@ -485,7 +516,7 @@
},
_initEventHandlers: function () {
$.blueimp.fileupload.prototype._initEventHandlers.call(this);
$.blueimpIP.fileupload.prototype._initEventHandlers.call(this);
var eventData = {fileupload: this};
this._files
.delegate(
@ -515,7 +546,7 @@
.undelegate('.start button', 'click.' + this.options.namespace)
.undelegate('.cancel button', 'click.' + this.options.namespace)
.undelegate('.delete button', 'click.' + this.options.namespace);
$.blueimp.fileupload.prototype._destroyEventHandlers.call(this);
$.blueimpIP.fileupload.prototype._destroyEventHandlers.call(this);
},
_enableFileInputButton: function () {
@ -544,16 +575,16 @@
_create: function () {
this._initFiles();
$.blueimp.fileupload.prototype._create.call(this);
$.blueimpIP.fileupload.prototype._create.call(this);
this._initTemplates();
},
destroy: function () {
$.blueimp.fileupload.prototype.destroy.call(this);
$.blueimpIP.fileupload.prototype.destroy.call(this);
},
enable: function () {
$.blueimp.fileupload.prototype.enable.call(this);
$.blueimpIP.fileupload.prototype.enable.call(this);
this.element.find('input, button').prop('disabled', false);
this._enableFileInputButton();
},
@ -561,7 +592,7 @@
disable: function () {
this.element.find('input, button').prop('disabled', true);
this._disableFileInputButton();
$.blueimp.fileupload.prototype.disable.call(this);
$.blueimpIP.fileupload.prototype.disable.call(this);
}
});

View File

@ -1,5 +1,5 @@
/*
* jQuery File Upload Plugin JS Example 6.3
* jQuery File Upload Plugin JS Example 6.4
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
@ -23,7 +23,9 @@ $(function () {
$('#fileupload').fileupload('option', {
url: '//jquery-file-upload.appspot.com/',
maxFileSize: 5000000,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
resizeMaxWidth: 1920,
resizeMaxHeight: 1200
});
// Upload server status check for browsers with CORS support:
if ($.ajaxSettings.xhr().withCredentials !== undefined) {

View File

@ -1,6 +1,6 @@
{
"name": "blueimp-file-upload",
"version": "6.3.0",
"version": "6.4.0",
"title": "jQuery File Upload",
"description": "File Upload widget with multiple file selection, drag&drop support, progress bar and preview images for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.",
"keywords": [
@ -49,14 +49,17 @@
"dependencies": {
"jquery": ">=1.6",
"jquery.ui.widget": ">=1.8",
"blueimp-tmpl": ">=1.0.2",
"blueimp-load-image": ">=1.1.4",
"blueimp-tmpl": ">=1.0.2"
"blueimp-canvas-to-blob": ">=1.0.1"
},
"files": [
"js/jquery.iframe-transport.js",
"js/jquery.fileupload.js",
"js/jquery.fileupload-ip.js",
"js/jquery.fileupload-ui.js",
"css/jquery.fileupload-ui.css",
"img/progressbar.gif"
"img/progressbar.gif",
"img/loading.gif"
]
}