X-Git-Url: https://git.mdrn.pl/redakcja.git/blobdiff_plain/8b04ced586931e1dd6b4759c2b972a01d877fe03..f067862049a3be1faa5ff1a2535ea6362cea23de:/src/fileupload/static/lib/jQuery-File-Upload-10.32.0/js/jquery.fileupload-ui.js diff --git a/src/fileupload/static/lib/jQuery-File-Upload-10.32.0/js/jquery.fileupload-ui.js b/src/fileupload/static/lib/jQuery-File-Upload-10.32.0/js/jquery.fileupload-ui.js new file mode 100644 index 00000000..9cc3d3fd --- /dev/null +++ b/src/fileupload/static/lib/jQuery-File-Upload-10.32.0/js/jquery.fileupload-ui.js @@ -0,0 +1,759 @@ +/* + * 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-cap + var 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-cap + var 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(); + } + }); +});