Blame | Letzte Änderung | Log anzeigen | RSS feed
/** jQuery File Upload User Interface Plugin 5.0.17* https://github.com/blueimp/jQuery-File-Upload** Copyright 2010, Sebastian Tschan* https://blueimp.net** Licensed under the MIT license:* http://creativecommons.org/licenses/MIT/*//*jslint nomen: true, unparam: true, regexp: true *//*global window, document, URL, webkitURL, FileReader, jQuery */(function ($) {'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, {options: {// By default, files added to the widget are uploaded as soon// as the user clicks on the start buttons. To enable automatic// uploads, set the following option to true:autoUpload: false,// The following option limits the number of files that are// allowed to be uploaded using this widget:maxNumberOfFiles: undefined,// The maximum allowed file size:maxFileSize: undefined,// The minimum allowed file size:minFileSize: 1,// The regular expression for allowed file types, matches// against either file type or file name: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 width of the preview images:previewMaxWidth: 80,// The maximum height of the preview images:previewMaxHeight: 80,// By default, preview images are displayed as canvas elements// if supported by the browser. Set the following option to false// to always display preview images as img elements:previewAsCanvas: true,// The file upload template that is given as first argument to the// jQuery.tmpl method to render the file uploads:uploadTemplate: $('#template-upload'),// The file download template, that is given as first argument to the// jQuery.tmpl method to render the file downloads:downloadTemplate: $('#template-download'),// The expected data type of the upload response, sets the dataType// option of the $.ajax upload requests:dataType: 'json',// 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) {var that = $(this).data('fileupload');that._adjustMaxNumberOfFiles(-data.files.length);data.isAdjusted = true;data.isValidated = that._validate(data.files);data.context = that._renderUpload(data.files).appendTo($(this).find('.files')).fadeIn(function () {// Fix for IE7 and lower:$(this).show();}).data('data', data);if ((that.options.autoUpload || data.autoUpload) &&data.isValidated) {data.jqXHR = data.submit();}},// Callback for the start of each file upload request:send: function (e, data) {if (!data.isValidated) {var that = $(this).data('fileupload');if (!data.isAdjusted) {that._adjustMaxNumberOfFiles(-data.files.length);}if (!that._validate(data.files)) {return false;}}if (data.context && data.dataType &&data.dataType.substr(0, 6) === 'iframe') {// Iframe Transport does not support progress events.// In lack of an indeterminate progress bar, we set// the progress to 100%, showing the full animated bar:data.context.find('.ui-progressbar').progressbar('value',parseInt(100, 10));}},// Callback for successful uploads:done: function (e, data) {var that = $(this).data('fileupload');if (data.context) {data.context.each(function (index) {var file = ($.isArray(data.result) &&data.result[index]) || {error: 'emptyResult'};if (file.error) {that._adjustMaxNumberOfFiles(1);}$(this).fadeOut(function () {that._renderDownload([file]).css('display', 'none').replaceAll(this).fadeIn(function () {// Fix for IE7 and lower:$(this).show();});});});} else {that._renderDownload(data.result).css('display', 'none').appendTo($(this).find('.files')).fadeIn(function () {// Fix for IE7 and lower:$(this).show();});}},// Callback for failed (abort or error) uploads:fail: function (e, data) {var that = $(this).data('fileupload');that._adjustMaxNumberOfFiles(data.files.length);if (data.context) {data.context.each(function (index) {$(this).fadeOut(function () {if (data.errorThrown !== 'abort') {var file = data.files[index];file.error = file.error || data.errorThrown|| true;that._renderDownload([file]).css('display', 'none').replaceAll(this).fadeIn(function () {// Fix for IE7 and lower:$(this).show();});} else {data.context.remove();}});});} else if (data.errorThrown !== 'abort') {that._adjustMaxNumberOfFiles(-data.files.length);data.context = that._renderUpload(data.files).css('display', 'none').appendTo($(this).find('.files')).fadeIn(function () {// Fix for IE7 and lower:$(this).show();}).data('data', data);}},// Callback for upload progress events:progress: function (e, data) {if (data.context) {data.context.find('.ui-progressbar').progressbar('value',parseInt(data.loaded / data.total * 100, 10));}},// Callback for global upload progress events:progressall: function (e, data) {$(this).find('.fileupload-progressbar').progressbar('value',parseInt(data.loaded / data.total * 100, 10));},// Callback for uploads start, equivalent to the global ajaxStart event:start: function () {$(this).find('.fileupload-progressbar').progressbar('value', 0).fadeIn();},// Callback for uploads stop, equivalent to the global ajaxStop event:stop: function () {$(this).find('.fileupload-progressbar').fadeOut();},// Callback for file deletion:destroy: function (e, data) {var that = $(this).data('fileupload');if (data.url) {$.ajax(data).success(function () {that._adjustMaxNumberOfFiles(1);$(this).fadeOut(function () {$(this).remove();});});} else {that._adjustMaxNumberOfFiles(1);data.context.fadeOut(function () {$(this).remove();});}}},// Scales the given image (img HTML element)// using the given options.// Returns a canvas object if the canvas option is true// and the browser supports canvas, else the scaled image:_scaleImage: function (img, options) {options = options || {};var canvas = document.createElement('canvas'),scale = Math.min((options.maxWidth || img.width) / img.width,(options.maxHeight || img.height) / img.height);if (scale >= 1) {scale = Math.max((options.minWidth || img.width) / img.width,(options.minHeight || img.height) / img.height);}img.width = parseInt(img.width * scale, 10);img.height = parseInt(img.height * scale, 10);if (!options.canvas || !canvas.getContext) {return img;}canvas.width = img.width;canvas.height = img.height;canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);return canvas;},_createObjectURL: function (file) {var undef = 'undefined',urlAPI = (typeof window.createObjectURL !== undef && window) ||(typeof URL !== undef && URL) ||(typeof webkitURL !== undef && webkitURL);return urlAPI ? urlAPI.createObjectURL(file) : false;},_revokeObjectURL: function (url) {var undef = 'undefined',urlAPI = (typeof window.revokeObjectURL !== undef && window) ||(typeof URL !== undef && URL) ||(typeof webkitURL !== undef && webkitURL);return urlAPI ? urlAPI.revokeObjectURL(url) : false;},// Loads a given File object via FileReader interface,// invokes the callback with a data url:_loadFile: function (file, callback) {if (typeof FileReader !== 'undefined' &&FileReader.prototype.readAsDataURL) {var fileReader = new FileReader();fileReader.onload = function (e) {callback(e.target.result);};fileReader.readAsDataURL(file);return true;}return false;},// Loads an image for a given File object.// Invokes the callback with an img or optional canvas// element (if supported by the browser) as parameter:_loadImage: function (file, callback, options) {var that = this,url,img;if (!options || !options.fileTypes ||options.fileTypes.test(file.type)) {url = this._createObjectURL(file);img = $('<img>').bind('load', function () {$(this).unbind('load');that._revokeObjectURL(url);callback(that._scaleImage(img[0], options));});if (url) {img.prop('src', url);return true;} else {return this._loadFile(file, function (url) {img.prop('src', url);});}}return false;},// Link handler, that allows to download files// by drag & drop of the links to the desktop:_enableDragToDesktop: function () {var link = $(this),url = link.prop('href'),name = decodeURIComponent(url.split('/').pop()).replace(/:/g, '-'),type = 'application/octet-stream';link.bind('dragstart', function (e) {try {e.originalEvent.dataTransfer.setData('DownloadURL',[type, name, url].join(':'));} catch (err) {}});},_adjustMaxNumberOfFiles: function (operand) {if (typeof this.options.maxNumberOfFiles === 'number') {this.options.maxNumberOfFiles += operand;if (this.options.maxNumberOfFiles < 1) {this._disableFileInputButton();} else {this._enableFileInputButton();}}},_formatFileSize: function (file) {if (typeof file.size !== 'number') {return '';}if (file.size >= 1000000000) {return (file.size / 1000000000).toFixed(2) + ' GB';}if (file.size >= 1000000) {return (file.size / 1000000).toFixed(2) + ' MB';}return (file.size / 1000).toFixed(2) + ' KB';},_hasError: function (file) {if (file.error) {return file.error;}// The number of added files is subtracted from// maxNumberOfFiles before validation, so we check if// maxNumberOfFiles is below 0 (instead of below 1):if (this.options.maxNumberOfFiles < 0) {return 'maxNumberOfFiles';}// Files are accepted if either the file type or the file name// matches against the acceptFileTypes regular expression, as// only browsers with support for the File API report the type:if (!(this.options.acceptFileTypes.test(file.type) ||this.options.acceptFileTypes.test(file.name))) {return 'acceptFileTypes';}if (this.options.maxFileSize &&file.size > this.options.maxFileSize) {return 'maxFileSize';}if (typeof file.size === 'number' &&file.size < this.options.minFileSize) {return 'minFileSize';}return null;},_validate: function (files) {var that = this,valid = !!files.length;$.each(files, function (index, file) {file.error = that._hasError(file);if (file.error) {valid = false;}});return valid;},_uploadTemplateHelper: function (file) {file.sizef = this._formatFileSize(file);return file;},_renderUploadTemplate: function (files) {var that = this;return $.tmpl(this.options.uploadTemplate,$.map(files, function (file) {return that._uploadTemplateHelper(file);}));},_renderUpload: function (files) {var that = this,options = this.options,tmpl = this._renderUploadTemplate(files),isValidated = this._validate(files);if (!(tmpl instanceof $)) {return $();}tmpl.css('display', 'none');// .slice(1).remove().end().first() removes all but the first// element and selects only the first for the jQuery collection:tmpl.find('.progress div').slice(isValidated ? 1 : 0).remove().end().first().progressbar();tmpl.find('.start button').slice(this.options.autoUpload || !isValidated ? 0 : 1).remove().end().first().button({text: false,icons: {primary: 'ui-icon-circle-arrow-e'}});tmpl.find('.cancel button').slice(1).remove().end().first().button({text: false,icons: {primary: 'ui-icon-cancel'}});tmpl.find('.preview').each(function (index, node) {that._loadImage(files[index],function (img) {$(img).hide().appendTo(node).fadeIn();},{maxWidth: options.previewMaxWidth,maxHeight: options.previewMaxHeight,fileTypes: options.previewFileTypes,canvas: options.previewAsCanvas});});return tmpl;},_downloadTemplateHelper: function (file) {file.sizef = this._formatFileSize(file);return file;},_renderDownloadTemplate: function (files) {var that = this;return $.tmpl(this.options.downloadTemplate,$.map(files, function (file) {return that._downloadTemplateHelper(file);}));},_renderDownload: function (files) {var tmpl = this._renderDownloadTemplate(files);if (!(tmpl instanceof $)) {return $();}tmpl.css('display', 'none');tmpl.find('.delete button').button({text: false,icons: {primary: 'ui-icon-trash'}});tmpl.find('a').each(this._enableDragToDesktop);return tmpl;},_startHandler: function (e) {e.preventDefault();var tmpl = $(this).closest('.template-upload'),data = tmpl.data('data');if (data && data.submit && !data.jqXHR) {data.jqXHR = data.submit();$(this).fadeOut();}},_cancelHandler: function (e) {e.preventDefault();var tmpl = $(this).closest('.template-upload'),data = tmpl.data('data') || {};if (!data.jqXHR) {data.errorThrown = 'abort';e.data.fileupload._trigger('fail', e, data);} else {data.jqXHR.abort();}},_deleteHandler: function (e) {e.preventDefault();var button = $(this);e.data.fileupload._trigger('destroy', e, {context: button.closest('.template-download'),url: button.attr('data-url'),type: button.attr('data-type'),dataType: e.data.fileupload.options.dataType});},_initEventHandlers: function () {$.blueimp.fileupload.prototype._initEventHandlers.call(this);var filesList = this.element.find('.files'),eventData = {fileupload: this};filesList.find('.start button').live('click.' + this.options.namespace,eventData,this._startHandler);filesList.find('.cancel button').live('click.' + this.options.namespace,eventData,this._cancelHandler);filesList.find('.delete button').live('click.' + this.options.namespace,eventData,this._deleteHandler);},_destroyEventHandlers: function () {var filesList = this.element.find('.files');filesList.find('.start button').die('click.' + this.options.namespace);filesList.find('.cancel button').die('click.' + this.options.namespace);filesList.find('.delete button').die('click.' + this.options.namespace);$.blueimp.fileupload.prototype._destroyEventHandlers.call(this);},_initFileUploadButtonBar: function () {var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'),filesList = this.element.find('.files'),ns = this.options.namespace;fileUploadButtonBar.addClass('ui-widget-header ui-corner-top');this.element.find('.fileinput-button').each(function () {var fileInput = $(this).find('input:file').detach();$(this).button({icons: {primary: 'ui-icon-plusthick'}}).append(fileInput);});fileUploadButtonBar.find('.start').button({icons: {primary: 'ui-icon-circle-arrow-e'}}).bind('click.' + ns, function (e) {e.preventDefault();filesList.find('.start button').click();});fileUploadButtonBar.find('.cancel').button({icons: {primary: 'ui-icon-cancel'}}).bind('click.' + ns, function (e) {e.preventDefault();filesList.find('.cancel button').click();});fileUploadButtonBar.find('.delete').button({icons: {primary: 'ui-icon-trash'}}).bind('click.' + ns, function (e) {e.preventDefault();filesList.find('.delete button').click();});},_destroyFileUploadButtonBar: function () {this.element.find('.fileupload-buttonbar').removeClass('ui-widget-header ui-corner-top');this.element.find('.fileinput-button').each(function () {var fileInput = $(this).find('input:file').detach();$(this).button('destroy').append(fileInput);});this.element.find('.fileupload-buttonbar button').unbind('click.' + this.options.namespace).button('destroy');},_enableFileInputButton: function () {this.element.find('.fileinput-button input:file:disabled').each(function () {var fileInput = $(this),button = fileInput.parent();fileInput.detach().prop('disabled', false);button.button('enable').append(fileInput);});},_disableFileInputButton: function () {this.element.find('.fileinput-button input:file:enabled').each(function () {var fileInput = $(this),button = fileInput.parent();fileInput.detach().prop('disabled', true);button.button('disable').append(fileInput);});},_initTemplates: function () {// Handle cases where the templates are defined// after the widget library has been included:if (this.options.uploadTemplate instanceof $ &&!this.options.uploadTemplate.length) {this.options.uploadTemplate = $(this.options.uploadTemplate.selector);}if (this.options.downloadTemplate instanceof $ &&!this.options.downloadTemplate.length) {this.options.downloadTemplate = $(this.options.downloadTemplate.selector);}},_create: function () {$.blueimp.fileupload.prototype._create.call(this);this._initTemplates();this.element.addClass('ui-widget');this._initFileUploadButtonBar();this.element.find('.fileupload-content').addClass('ui-widget-content ui-corner-bottom');this.element.find('.fileupload-progressbar').hide().progressbar();},destroy: function () {this.element.find('.fileupload-progressbar').progressbar('destroy');this.element.find('.fileupload-content').removeClass('ui-widget-content ui-corner-bottom');this._destroyFileUploadButtonBar();this.element.removeClass('ui-widget');$.blueimp.fileupload.prototype.destroy.call(this);},enable: function () {$.blueimp.fileupload.prototype.enable.call(this);this.element.find(':ui-button').not('.fileinput-button').button('enable');this._enableFileInputButton();},disable: function () {this.element.find(':ui-button').not('.fileinput-button').button('disable');this._disableFileInputButton();$.blueimp.fileupload.prototype.disable.call(this);}});}(jQuery));