Upgrade filebrowser; minor fixes relevant to the upgrade.
[redakcja.git] / 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 (file)
index 0000000..9cc3d3f
--- /dev/null
@@ -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();
+    }
+  });
+});