Revision 1513 | Blame | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed
/** jQuery File Upload User Interface Plugin* https://github.com/blueimp/jQuery-File-Upload** Copyright 2010, Sebastian Tschan* https://blueimp.net** Licensed under the MIT license:* https://opensource.org/licenses/MIT*//* global define, require */(function (factory) {'use strict';if (typeof define === 'function' && define.amd) {// Register as an anonymous AMD module:define(['jquery','blueimp-tmpl','./jquery.fileupload-image','./jquery.fileupload-audio','./jquery.fileupload-video','./jquery.fileupload-validate'], factory);} else if (typeof exports === 'object') {// Node/CommonJS:factory(require('jquery'),require('blueimp-tmpl'),require('./jquery.fileupload-image'),require('./jquery.fileupload-audio'),require('./jquery.fileupload-video'),require('./jquery.fileupload-validate'));} else {// Browser globals:factory(window.jQuery, window.tmpl);}})(function ($, tmpl) {'use strict';$.blueimp.fileupload.prototype._specialOptions.push('filesContainer','uploadTemplateId','downloadTemplateId');// The UI version extends the file upload widget// and adds complete user interface interaction:$.widget('blueimp.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 class to show/hide UI elements:showElementClass: 'in',// The ID of the upload template:uploadTemplateId: 'template-upload',// The ID of the download template:downloadTemplateId: 'template-download',// The container for the list of files. If undefined, it is set to// an element with class "files" inside of the widget element:filesContainer: undefined,// By default, files are appended to the files container.// Set the following option to true, to prepend files instead:prependFiles: false,// The expected data type of the upload response, sets the dataType// option of the $.ajax upload requests:dataType: 'json',// Error and info messages:messages: {unknownError: 'Unknown error'},// Function returning the current number of files,// used by the maxNumberOfFiles validation:getNumberOfFiles: function () {return this.filesContainer.children().not('.processing').length;},// Callback to retrieve the list of files from the server response:getFilesFromResponse: function (data) {if (data.result && $.isArray(data.result.files)) {return data.result.files;}return [];},// 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) {if (e.isDefaultPrevented()) {return false;}var $this = $(this),that = $this.data('blueimp-fileupload') || $this.data('fileupload'),options = that.options;data.context = that._renderUpload(data.files).data('data', data).addClass('processing');options.filesContainer[options.prependFiles ? 'prepend' : 'append'](data.context);that._forceReflow(data.context);that._transition(data.context);data.process(function () {return $this.fileupload('process', data);}).always(function () {data.context.each(function (index) {$(this).find('.size').text(that._formatFileSize(data.files[index].size));}).removeClass('processing');that._renderPreviews(data);}).done(function () {data.context.find('.edit,.start').prop('disabled', false);if (that._trigger('added', e, data) !== false &&(options.autoUpload || data.autoUpload) &&data.autoUpload !== false) {data.submit();}}).fail(function () {if (data.files.error) {data.context.each(function (index) {var error = data.files[index].error;if (error) {$(this).find('.error').text(error);}});}});},// Callback for the start of each file upload request:send: function (e, data) {if (e.isDefaultPrevented()) {return false;}var that =$(this).data('blueimp-fileupload') || $(this).data('fileupload');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('.progress').addClass(!$.support.transition && 'progress-animated').attr('aria-valuenow', 100).children().first().css('width', '100%');}return that._trigger('sent', e, data);},// Callback for successful uploads:done: function (e, data) {if (e.isDefaultPrevented()) {return false;}var that =$(this).data('blueimp-fileupload') || $(this).data('fileupload'),getFilesFromResponse =data.getFilesFromResponse || that.options.getFilesFromResponse,files = getFilesFromResponse(data),template,deferred;if (data.context) {data.context.each(function (index) {var file = files[index] || { error: 'Empty file upload result' };deferred = that._addFinishedDeferreds();that._transition($(this)).done(function () {var node = $(this);template = that._renderDownload([file]).replaceAll(node);that._forceReflow(template);that._transition(template).done(function () {data.context = $(this);that._trigger('completed', e, data);that._trigger('finished', e, data);deferred.resolve();});});});} else {template = that._renderDownload(files)[that.options.prependFiles ? 'prependTo' : 'appendTo'](that.options.filesContainer);that._forceReflow(template);deferred = that._addFinishedDeferreds();that._transition(template).done(function () {data.context = $(this);that._trigger('completed', e, data);that._trigger('finished', e, data);deferred.resolve();});}},// Callback for failed (abort or error) uploads:fail: function (e, data) {if (e.isDefaultPrevented()) {return false;}var that =$(this).data('blueimp-fileupload') || $(this).data('fileupload'),template,deferred;if (data.context) {data.context.each(function (index) {if (data.errorThrown !== 'abort') {var file = data.files[index];file.error =file.error || data.errorThrown || data.i18n('unknownError');deferred = that._addFinishedDeferreds();that._transition($(this)).done(function () {var node = $(this);template = that._renderDownload([file]).replaceAll(node);that._forceReflow(template);that._transition(template).done(function () {data.context = $(this);that._trigger('failed', e, data);that._trigger('finished', e, data);deferred.resolve();});});} else {deferred = that._addFinishedDeferreds();that._transition($(this)).done(function () {$(this).remove();that._trigger('failed', e, data);that._trigger('finished', e, data);deferred.resolve();});}});} else if (data.errorThrown !== 'abort') {data.context = that._renderUpload(data.files)[that.options.prependFiles ? 'prependTo' : 'appendTo'](that.options.filesContainer).data('data', data);that._forceReflow(data.context);deferred = that._addFinishedDeferreds();that._transition(data.context).done(function () {data.context = $(this);that._trigger('failed', e, data);that._trigger('finished', e, data);deferred.resolve();});} else {that._trigger('failed', e, data);that._trigger('finished', e, data);that._addFinishedDeferreds().resolve();}},// Callback for upload progress events:progress: function (e, data) {if (e.isDefaultPrevented()) {return false;}var progress = Math.floor((data.loaded / data.total) * 100);if (data.context) {data.context.each(function () {$(this).find('.progress').attr('aria-valuenow', progress).children().first().css('width', progress + '%');});}},// Callback for global upload progress events:progressall: function (e, data) {if (e.isDefaultPrevented()) {return false;}var $this = $(this),progress = Math.floor((data.loaded / data.total) * 100),globalProgressNode = $this.find('.fileupload-progress'),extendedProgressNode = globalProgressNode.find('.progress-extended');if (extendedProgressNode.length) {extendedProgressNode.html(($this.data('blueimp-fileupload') || $this.data('fileupload'))._renderExtendedProgress(data));}globalProgressNode.find('.progress').attr('aria-valuenow', progress).children().first().css('width', progress + '%');},// Callback for uploads start, equivalent to the global ajaxStart event:start: function (e) {if (e.isDefaultPrevented()) {return false;}var that =$(this).data('blueimp-fileupload') || $(this).data('fileupload');that._resetFinishedDeferreds();that._transition($(this).find('.fileupload-progress')).done(function () {that._trigger('started', e);});},// Callback for uploads stop, equivalent to the global ajaxStop event:stop: function (e) {if (e.isDefaultPrevented()) {return false;}var that =$(this).data('blueimp-fileupload') || $(this).data('fileupload'),deferred = that._addFinishedDeferreds();$.when.apply($, that._getFinishedDeferreds()).done(function () {that._trigger('stopped', e);});that._transition($(this).find('.fileupload-progress')).done(function () {$(this).find('.progress').attr('aria-valuenow', '0').children().first().css('width', '0%');$(this).find('.progress-extended').html(' ');deferred.resolve();});},processstart: function (e) {if (e.isDefaultPrevented()) {return false;}$(this).addClass('fileupload-processing');},processstop: function (e) {if (e.isDefaultPrevented()) {return false;}$(this).removeClass('fileupload-processing');},// Callback for file deletion:destroy: function (e, data) {if (e.isDefaultPrevented()) {return false;}var that =$(this).data('blueimp-fileupload') || $(this).data('fileupload'),removeNode = function () {that._transition(data.context).done(function () {$(this).remove();that._trigger('destroyed', e, data);});};if (data.url) {data.dataType = data.dataType || that.options.dataType;$.ajax(data).done(removeNode).fail(function () {that._trigger('destroyfailed', e, data);});} else {removeNode();}}},_resetFinishedDeferreds: function () {this._finishedUploads = [];},_addFinishedDeferreds: function (deferred) {// eslint-disable-next-line new-capvar promise = deferred || $.Deferred();this._finishedUploads.push(promise);return promise;},_getFinishedDeferreds: function () {return this._finishedUploads;},// 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 = link.prop('download'),type = 'application/octet-stream';link.on('dragstart', function (e) {try {e.originalEvent.dataTransfer.setData('DownloadURL',[type, name, url].join(':'));} catch (ignore) {// Ignore exceptions}});},_formatFileSize: function (bytes) {if (typeof bytes !== 'number') {return '';}if (bytes >= 1000000000) {return (bytes / 1000000000).toFixed(2) + ' GB';}if (bytes >= 1000000) {return (bytes / 1000000).toFixed(2) + ' MB';}return (bytes / 1000).toFixed(2) + ' KB';},_formatBitrate: function (bits) {if (typeof bits !== 'number') {return '';}if (bits >= 1000000000) {return (bits / 1000000000).toFixed(2) + ' Gbit/s';}if (bits >= 1000000) {return (bits / 1000000).toFixed(2) + ' Mbit/s';}if (bits >= 1000) {return (bits / 1000).toFixed(2) + ' kbit/s';}return bits.toFixed(2) + ' bit/s';},_formatTime: function (seconds) {var date = new Date(seconds * 1000),days = Math.floor(seconds / 86400);days = days ? days + 'd ' : '';return (days +('0' + date.getUTCHours()).slice(-2) +':' +('0' + date.getUTCMinutes()).slice(-2) +':' +('0' + date.getUTCSeconds()).slice(-2));},_formatPercentage: function (floatValue) {return (floatValue * 100).toFixed(2) + ' %';},_renderExtendedProgress: function (data) {return (this._formatBitrate(data.bitrate) +' | ' +this._formatTime(((data.total - data.loaded) * 8) / data.bitrate) +' | ' +this._formatPercentage(data.loaded / data.total) +' | ' +this._formatFileSize(data.loaded) +' / ' +this._formatFileSize(data.total));},_renderTemplate: function (func, files) {if (!func) {return $();}var result = func({files: files,formatFileSize: this._formatFileSize,options: this.options});if (result instanceof $) {return result;}return $(this.options.templatesContainer).html(result).children();},_renderPreviews: function (data) {data.context.find('.preview').each(function (index, elm) {$(elm).empty().append(data.files[index].preview);});},_renderUpload: function (files) {return this._renderTemplate(this.options.uploadTemplate, files);},_renderDownload: function (files) {return this._renderTemplate(this.options.downloadTemplate, files).find('a[download]').each(this._enableDragToDesktop).end();},_editHandler: function (e) {e.preventDefault();if (!this.options.edit) return;var that = this,button = $(e.currentTarget),template = button.closest('.template-upload'),data = template.data('data'),index = button.data().index;this.options.edit(data.files[index]).then(function (file) {if (!file) return;data.files[index] = file;data.context.addClass('processing');template.find('.edit,.start').prop('disabled', true);$(that.element).fileupload('process', data).always(function () {template.find('.size').text(that._formatFileSize(data.files[index].size));data.context.removeClass('processing');that._renderPreviews(data);}).done(function () {template.find('.edit,.start').prop('disabled', false);}).fail(function () {template.find('.edit').prop('disabled', false);var error = data.files[index].error;if (error) {template.find('.error').text(error);}});});},_startHandler: function (e) {e.preventDefault();var button = $(e.currentTarget),template = button.closest('.template-upload'),data = template.data('data');button.prop('disabled', true);if (data && data.submit) {data.submit();}},_cancelHandler: function (e) {e.preventDefault();var template = $(e.currentTarget).closest('.template-upload,.template-download'),data = template.data('data') || {};data.context = data.context || template;if (data.abort) {data.abort();} else {data.errorThrown = 'abort';this._trigger('fail', e, data);}},_deleteHandler: function (e) {e.preventDefault();var button = $(e.currentTarget);this._trigger('destroy',e,$.extend({context: button.closest('.template-download'),type: 'DELETE'},button.data()));},_forceReflow: function (node) {return $.support.transition && node.length && node[0].offsetWidth;},_transition: function (node) {// eslint-disable-next-line new-capvar dfd = $.Deferred();if ($.support.transition &&node.hasClass('fade') &&node.is(':visible')) {var transitionEndHandler = function (e) {// Make sure we don't respond to other transition events// in the container element, e.g. from button elements:if (e.target === node[0]) {node.off($.support.transition.end, transitionEndHandler);dfd.resolveWith(node);}};node.on($.support.transition.end, transitionEndHandler).toggleClass(this.options.showElementClass);} else {node.toggleClass(this.options.showElementClass);dfd.resolveWith(node);}return dfd;},_initButtonBarEventHandlers: function () {var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'),filesList = this.options.filesContainer;this._on(fileUploadButtonBar.find('.start'), {click: function (e) {e.preventDefault();filesList.find('.start').trigger('click');}});this._on(fileUploadButtonBar.find('.cancel'), {click: function (e) {e.preventDefault();filesList.find('.cancel').trigger('click');}});this._on(fileUploadButtonBar.find('.delete'), {click: function (e) {e.preventDefault();filesList.find('.toggle:checked').closest('.template-download').find('.delete').trigger('click');fileUploadButtonBar.find('.toggle').prop('checked', false);}});this._on(fileUploadButtonBar.find('.toggle'), {change: function (e) {filesList.find('.toggle').prop('checked', $(e.currentTarget).is(':checked'));}});},_destroyButtonBarEventHandlers: function () {this._off(this.element.find('.fileupload-buttonbar').find('.start, .cancel, .delete'),'click');this._off(this.element.find('.fileupload-buttonbar .toggle'), 'change.');},_initEventHandlers: function () {this._super();this._on(this.options.filesContainer, {'click .edit': this._editHandler,'click .start': this._startHandler,'click .cancel': this._cancelHandler,'click .delete': this._deleteHandler});this._initButtonBarEventHandlers();},_destroyEventHandlers: function () {this._destroyButtonBarEventHandlers();this._off(this.options.filesContainer, 'click');this._super();},_enableFileInputButton: function () {this.element.find('.fileinput-button input').prop('disabled', false).parent().removeClass('disabled');},_disableFileInputButton: function () {this.element.find('.fileinput-button input').prop('disabled', true).parent().addClass('disabled');},_initTemplates: function () {var options = this.options;options.templatesContainer = this.document[0].createElement(options.filesContainer.prop('nodeName'));if (tmpl) {if (options.uploadTemplateId) {options.uploadTemplate = tmpl(options.uploadTemplateId);}if (options.downloadTemplateId) {options.downloadTemplate = tmpl(options.downloadTemplateId);}}},_initFilesContainer: function () {var options = this.options;if (options.filesContainer === undefined) {options.filesContainer = this.element.find('.files');} else if (!(options.filesContainer instanceof $)) {options.filesContainer = $(options.filesContainer);}},_initSpecialOptions: function () {this._super();this._initFilesContainer();this._initTemplates();},_create: function () {this._super();this._resetFinishedDeferreds();if (!$.support.fileInput) {this._disableFileInputButton();}},enable: function () {var wasDisabled = false;if (this.options.disabled) {wasDisabled = true;}this._super();if (wasDisabled) {this.element.find('input, button').prop('disabled', false);this._enableFileInputButton();}},disable: function () {if (!this.options.disabled) {this.element.find('input, button').prop('disabled', true);this._disableFileInputButton();}this._super();}});});