فهرست منبع

Update to release v4.1.6 fixes #136 and fixes #137

Kartik Visweswaran 10 سال پیش
والد
کامیت
953ce08597
8فایلهای تغییر یافته به همراه263 افزوده شده و 197 حذف شده
  1. 9 0
      CHANGE.md
  2. 53 7
      README.md
  3. 1 1
      bower.json
  4. 1 1
      css/fileinput.css
  5. 1 1
      css/fileinput.min.css
  6. 1 1
      examples/index.html
  7. 196 185
      js/fileinput.js
  8. 1 1
      js/fileinput.min.js

+ 9 - 0
CHANGE.md

@@ -1,3 +1,12 @@
+version 4.1.6
+=============
+**Date:** 16-Jan-2015
+
+1. (enh #124): Allow submission of extra data even if no files are selected.
+2. (enh #131): Allow empty values in extra data to be submitted.
+3. (enh #136):Create new upload method that can be called externally.
+4. (enh #137): Trigger new events - `filedisabled` and `fileenabled`.
+
 version 4.1.5
 =============
 **Date:** 12-Jan-2015

+ 53 - 7
README.md

@@ -7,7 +7,7 @@ The plugin incorporates a simple HTML markup with enhanced CSS styling of a HTML
 
 ![File Input Screenshot](https://lh3.googleusercontent.com/-3FiEmc_okc4/VBw_d2LBAJI/AAAAAAAAAL8/KbVj5X9Dus0/w596-h454-no/FileInput.jpg)
 
-> NOTE: The latest version of the plugin v4.1.5 has been released. Refer the [CHANGE LOG](https://github.com/kartik-v/bootstrap-fileinput/blob/master/CHANGE.md) for details. 
+> NOTE: The latest version of the plugin v4.1.6 has been released. Refer the [CHANGE LOG](https://github.com/kartik-v/bootstrap-fileinput/blob/master/CHANGE.md) for details. 
 
 ## Features  
 
@@ -1131,6 +1131,24 @@ $('#input-id').on('filebatchuploadcomplete', function(event, files, extra) {
 });
 ```
 
+#### filedisabled
+This event is triggered when the file input widget is disabled (prevents any modification) using the `disable` method.
+
+```js
+$('#input-id').on('filedisabled', function(event) {
+    console.log('File disabled.');
+});
+```
+
+#### fileenabled
+This event is triggered when the file input widget is enabled (allows modification) using the `enable` method.
+
+```js
+$('#input-id').on('fileenabled', function(event) {
+    console.log('File enabled.');
+});
+```
+
 ### Plugin Methods
 The plugin supports these methods:
 
@@ -1152,12 +1170,6 @@ Reset the file input.
 $('#input-id').fileinput('reset');
 ```
 
-#### clear
-Clear the file input.
-```js
-$('#input-id').fileinput('clear');
-```
-
 #### refresh
 Refreshes the file input plugin based on options provided. You can supply an array of plugin options as a parameter.
 ```js
@@ -1169,6 +1181,40 @@ $('#input-id').fileinput('refresh');
 $('#input-id').fileinput('refresh', {browseLabel: 'Select...', removeLabel: 'Delete'});
 ```
 
+#### clear
+Clear the file input and all files from preview.
+```js
+$('#input-id').fileinput('clear');
+```
+
+#### upload
+Trigger ajax upload of the files that are selected. Applicable only if `uploadUrl` is set.
+
+```js
+$('#input-id').fileinput('upload');
+```
+
+#### cancel
+Cancel an ongoing ajax upload of the files.
+
+```js
+$('#input-id').fileinput('cancel');
+```
+
+#### lock
+Locks the file input by disabling all actions/buttons except a cancel button to abort ongoing AJAX requests (for ajax uploads only).
+
+```js
+$('#input-id').fileinput('lock');
+```
+
+#### unlock
+Unlocks and enables the file input back again by reversing the outcome of the `lock` action.
+
+```js
+$('#input-id').fileinput('unlock');
+```
+
 ## License
 
 **bootstrap-fileinput** is released under the BSD 3-Clause License. See the bundled `LICENSE.md` for details.

+ 1 - 1
bower.json

@@ -1,6 +1,6 @@
 {
     "name": "bootstrap-fileinput",
-    "version": "4.1.5",
+    "version": "4.1.6",
     "homepage": "https://github.com/kartik-v/bootstrap-fileinput",
     "authors": [
         "Kartik Visweswaran <[email protected]>"

+ 1 - 1
css/fileinput.css

@@ -1,7 +1,7 @@
 /*!
  * @copyright Copyright &copy; Kartik Visweswaran, Krajee.com, 2015
  * @package bootstrap-fileinput
- * @version 4.1.5
+ * @version 4.1.6
  *
  * File input styling for Bootstrap 3.0
  * Built for Yii Framework 2.0

+ 1 - 1
css/fileinput.min.css

@@ -1,7 +1,7 @@
 /*!
  * @copyright Copyright &copy; Kartik Visweswaran, Krajee.com, 2015
  * @package bootstrap-fileinput
- * @version 4.1.5
+ * @version 4.1.6
  *
  * File input styling for Bootstrap 3.0
  * Built for Yii Framework 2.0

+ 1 - 1
examples/index.html

@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<!-- release v4.1.5, copyright 2015 Kartik Visweswaran -->
+<!-- release v4.1.6, copyright 2015 Kartik Visweswaran -->
 <html lang="en">
     <head>
         <meta charset="UTF-8"/>

+ 196 - 185
js/fileinput.js

@@ -1,6 +1,6 @@
 /*!
  * @copyright Copyright &copy; Kartik Visweswaran, Krajee.com, 2015
- * @version 4.1.5
+ * @version 4.1.6
  *
  * File input styled for Bootstrap 3.0 that utilizes HTML5 File Input's advanced 
  * features including the FileReader API. 
@@ -16,7 +16,7 @@
  * For more Yii related demos visit http://demos.krajee.com
  */
 (function ($) {
-    var isIE = function(ver) {
+    var isIE = function (ver) {
             var div = document.createElement("div"), status;
             div.innerHTML = "<!--[if IE " + ver + "]><i></i><![endif]-->";
             status = (div.getElementsByTagName("i").length == 1);
@@ -27,14 +27,14 @@
         hasFileAPISupport = function () {
             return window.File && window.FileReader;
         },
-        hasDragDropSupport = function() {
+        hasDragDropSupport = function () {
             var $div = document.createElement('div');
             return !isIE(9) && (('draggable' in $div) || ('ondragstart' in $div && 'ondrop' in $div));
         },
         hasFileUploadSupport = function () {
             return hasFileAPISupport && window.FormData;
         },
-        addCss = function($el, css) {
+        addCss = function ($el, css) {
             $el.removeClass(css).addClass(css);
         },
         STYLE_SETTING = 'style="width:{width};height:{height};"',
@@ -42,7 +42,7 @@
             '      <param name="allowFullScreen" value="true" />\n' +
             '      <param name="allowScriptAccess" value="always" />\n' +
             '      <param name="autoPlay" value="false" />\n' +
-            '      <param name="autoStart" value="false" />\n'+
+            '      <param name="autoStart" value="false" />\n' +
             '      <param name="quality" value="high" />\n',
         DEFAULT_PREVIEW = '<div class="file-preview-other">\n' +
             '       <i class="glyphicon glyphicon-file"></i>\n' +
@@ -111,7 +111,7 @@
         '     </div>\n' +
         '</div>',
         footer: '<div class="file-thumbnail-footer">\n' +
-        '    <div class="file-caption-name" style="width:{width}">{caption}</div>\n' +
+        '    <div class="file-caption-name">{caption}</div>\n' +
         '    {actions}\n' +
         '</div>',
         actions: '<div class="file-actions">\n' +
@@ -189,13 +189,13 @@
         other: {width: "160px", height: "160px"}
     };
     var defaultFileTypeSettings = {
-        image: function(vType, vName) {
+        image: function (vType, vName) {
             return (typeof vType !== "undefined") ? vType.match('image.*') : vName.match(/\.(gif|png|jpe?g)$/i);
         },
-        html: function(vType, vName) {
+        html: function (vType, vName) {
             return (typeof vType !== "undefined") ? vType == 'text/html' : vName.match(/\.(htm|html)$/i);
         },
-        text: function(vType, vName) {
+        text: function (vType, vName) {
             return typeof vType !== "undefined" && vType.match('text.*') || vName.match(/\.(txt|md|csv|nfo|php|ini)$/i);
         },
         video: function (vType, vName) {
@@ -233,7 +233,7 @@
         uniqId = function () {
             return Math.round(new Date().getTime() + (Math.random() * 100));
         },
-        htmlEncode = function(str) {
+        htmlEncode = function (str) {
             return String(str)
                 .replace(/&/g, '&amp;')
                 .replace(/"/g, '&quot;')
@@ -293,7 +293,8 @@
             self.$previewContainer = getElement(options, 'elPreviewContainer', self.$container.find('.file-preview'));
             self.$preview = getElement(options, 'elPreviewImage', self.$container.find('.file-preview-thumbnails'));
             self.$previewStatus = getElement(options, 'elPreviewStatus', self.$container.find('.file-preview-status'));
-            self.$errorContainer = getElement(options, 'elErrorContainer', self.$previewContainer.find('.kv-fileinput-error'));
+            self.$errorContainer = getElement(options, 'elErrorContainer',
+                self.$previewContainer.find('.kv-fileinput-error'));
             if (!isEmpty(self.msgErrorClass)) {
                 addCss(self.$errorContainer, self.msgErrorClass);
             }
@@ -316,7 +317,7 @@
             self.$element.removeClass('file-loading');
             self.setEllipsis();
         },
-        raise: function(event) {
+        raise: function (event) {
             var self = this;
             if (arguments.length > 1) {
                 self.$element.trigger(event, arguments[1]);
@@ -324,11 +325,11 @@
                 self.$element.trigger(event);
             }
         },
-        getLayoutTemplate: function(t) {
+        getLayoutTemplate: function (t) {
             var self = this;
             return isSet(t, self.layoutTemplates) ? self.layoutTemplates[t] : defaultLayoutTemplates[t];
         },
-        getPreviewTemplate: function(t) {
+        getPreviewTemplate: function (t) {
             var self = this;
             return isSet(t, self.previewTemplates) ? self.previewTemplates[t] : defaultPreviewTemplates[t];
         },
@@ -345,21 +346,21 @@
                 jqXHR: jqXHR
             };
         },
-        setEllipsis: function() {
+        setEllipsis: function () {
             var self = this, $ellipsis = self.$captionContainer.find('.file-caption-ellipsis'), $cap = self.$caption,
                 $div = $cap.clone().css('height', 'auto').hide();
             self.$captionContainer.parent().before($div);
             if ($div.outerWidth() > $cap.outerWidth()) {
-               $ellipsis.show();
+                $ellipsis.show();
             } else {
-               $ellipsis.hide();
+                $ellipsis.hide();
             }
             $div.remove();
         },
         listen: function () {
             var self = this, $el = self.$element, $cap = self.$captionContainer, $btnFile = self.$btnFile;
             $el.on('change', $.proxy(self.change, self));
-            $(window).on('resize', function() {
+            $(window).on('resize', function () {
                 self.setEllipsis();
             });
             $btnFile.off('click').on('click', function (ev) {
@@ -379,49 +380,54 @@
             if (!self.isUploadable) {
                 return;
             }
-            self.$container.find('.kv-fileinput-upload').off('click').on('click', function(e) {
+            self.$container.find('.kv-fileinput-upload').off('click').on('click', function (e) {
                 if (!self.isUploadable) {
                     return;
                 }
                 e.preventDefault();
-                var totLen = self.getFileStack().length;
-                if (self.isDisabled || $(this).hasClass('disabled') || !isEmpty($(this).attr('disabled')) || totLen == 0) {
-                    return;
-                }
-                self.resetUpload();
-                self.$progress.removeClass('hide');
-                self.uploadCount = 0;
-                self.uploadPercent = 0;
-                var i, len = self.filestack.length, template = self.getLayoutTemplate('progress');
-                self.lock();
-                self.setProgress(0);
-                if ((self.uploadAsync || totLen == 1) && self.showPreview) {
-                    var outData = self.getOutData();
-                    self.raise('filebatchpreupload', [outData]);
-                    for (i = 0; i < len; i++) {
-                        if (self.filestack[i] !== undefined) {
-                            self.upload(i, self.filestack, true);
-                        }
-                    }
-                    setTimeout(function() {
-                        $(document).ajaxStop(function() {
-                            self.setProgress(100);
-                            self.$preview.find('file-preview-frame').removeClass('file-loading');
-                            self.unlock();
-                            self.clearFileInput();
-                            self.raise('filebatchuploadcomplete', [self.filestack, self.getExtraData()]);
-                        });
-                    }, 100);
-                    return;
+                if (!$(this).hasClass('disabled') && isEmpty($(this).attr('disabled'))) {
+                    self.upload();
                 }
-                self.uploadBatch();
             });
         },
-        setProgress: function(percent) {
+        setProgress: function (percent) {
             var self = this, template = self.getLayoutTemplate('progress'), pct = Math.min(percent, 100);
             self.$progress.html(template.replace(/\{percent\}/g, pct));
         },
-        lock: function() {
+        upload: function () {
+            var self = this, totLen = self.getFileStack().length;
+            if (!self.isUploadable || self.isDisabled || totLen == 0) {
+                return;
+            }
+            self.resetUpload();
+            self.$progress.removeClass('hide');
+            self.uploadCount = 0;
+            self.uploadPercent = 0;
+            var i, len = self.filestack.length, template = self.getLayoutTemplate('progress');
+            self.lock();
+            self.setProgress(0);
+            if ((self.uploadAsync || totLen == 1) && self.showPreview) {
+                var outData = self.getOutData();
+                self.raise('filebatchpreupload', [outData]);
+                for (i = 0; i < len; i++) {
+                    if (self.filestack[i] !== undefined) {
+                        self.uploadSingle(i, self.filestack, true);
+                    }
+                }
+                setTimeout(function () {
+                    $(document).ajaxStop(function () {
+                        self.setProgress(100);
+                        self.$preview.find('file-preview-frame').removeClass('file-loading');
+                        self.unlock();
+                        self.clearFileInput();
+                        self.raise('filebatchuploadcomplete', [self.filestack, self.getExtraData()]);
+                    });
+                }, 100);
+                return;
+            }
+            self.uploadBatch();
+        },
+        lock: function () {
             var self = this;
             self.resetErrors();
             self.disable();
@@ -433,7 +439,7 @@
             }
             self.raise('filelock', [self.filestack, self.getExtraData()]);
         },
-        unlock: function() {
+        unlock: function () {
             var self = this;
             self.enable();
             if (self.showCancel) {
@@ -455,7 +461,7 @@
             self.listen();
             self.setFileDropZoneTitle();
         },
-        initDragDrop: function() {
+        initDragDrop: function () {
             var self = this, $zone = self.$container.find('.file-drop-zone');
             $zone.off('dragenter dragover drop');
             $(document).off('dragenter dragover drop');
@@ -488,12 +494,11 @@
                 e.preventDefault();
             });
         },
-        setFileDropZoneTitle: function() {
+        setFileDropZoneTitle: function () {
             var self = this, $zone = self.$container.find('.file-drop-zone');
             $zone.find('.' + self.dropZoneTitleClass).remove();
             if (!self.isUploadable || !self.showPreview ||
-                $zone.length == 0 || self.getFileStack().length > 0 ||
-                !self.dropZoneEnabled) {
+                $zone.length == 0 || self.getFileStack().length > 0 || !self.dropZoneEnabled) {
                 return;
             }
             if ($zone.find('.file-preview-frame').length == 0) {
@@ -502,13 +507,13 @@
             self.$container.removeClass('file-input-new');
             addCss(self.$container, 'file-input-ajax-new');
         },
-        initFileActions: function() {
+        initFileActions: function () {
             var self = this;
-            self.$preview.find('.kv-file-remove').each(function() {
+            self.$preview.find('.kv-file-remove').each(function () {
                 var $el = $(this), $frame = $el.closest('.file-preview-frame'),
                     ind = $frame.attr('data-fileindex');
-                $el.off('click').on('click', function() {
-                    $frame.fadeOut('slow', function() {
+                $el.off('click').on('click', function () {
+                    $frame.fadeOut('slow', function () {
                         self.filestack[ind] = undefined;
                         self.clearObjects($frame);
                         $frame.remove();
@@ -525,16 +530,16 @@
                     });
                 });
             });
-            self.$preview.find('.kv-file-upload').each(function() {
+            self.$preview.find('.kv-file-upload').each(function () {
                 var $el = $(this);
-                $el.off('click').on('click', function() {
+                $el.off('click').on('click', function () {
                     var $frame = $el.closest('.file-preview-frame'),
                         ind = $frame.attr('data-fileindex');
-                    self.upload(ind, self.filestack);
+                    self.uploadSingle(ind, self.filestack);
                 });
             });
         },
-        renderInitFileFooter: function(i) {
+        renderInitFileFooter: function (i) {
             var self = this, hasConfig = self.initialPreviewConfig.length > 0,
                 template = self.getLayoutTemplate('footer');
             if (hasConfig && !isEmpty(self.initialPreviewConfig[i])) {
@@ -544,27 +549,30 @@
                     url = ('url' in config) ? config.url : false,
                     key = ('key' in config) ? config.key : null,
                     disabled = url === false ? true : false,
-                    actions = self.initialPreviewShowDelete ? self.renderFileActions(false, true, disabled, url, key) : '',
+                    actions = self.initialPreviewShowDelete ? self.renderFileActions(false, true, disabled, url,
+                        key) : '',
                     footer = template.replace(/\{actions\}/g, actions);
                 return footer.replace(/\{caption\}/g, caption).replace(/\{width\}/g, width)
                     .replace(/\{indicator\}/g, '').replace(/\{indicatorTitle\}/g, '');
             }
             return '';
         },
-        renderFileFooter: function(caption, width) {
+        renderFileFooter: function (caption, width) {
             var self = this, config = self.fileActionSettings,
                 template = self.getLayoutTemplate('footer');
             if (self.isUploadable) {
                 var footer = template.replace(/\{actions\}/g, self.renderFileActions(true, true, false, false, false));
                 return footer.replace(/\{caption\}/g, caption).replace(/\{width\}/g, width)
-                    .replace(/\{indicator\}/g, config.indicatorNew).replace(/\{indicatorTitle\}/g, config.indicatorNewTitle);
+                    .replace(/\{indicator\}/g, config.indicatorNew).replace(/\{indicatorTitle\}/g,
+                    config.indicatorNewTitle);
             } else {
-                return template.replace(/\{actions\}/g, '').replace(/\{caption\}/g, caption).replace(/\{width\}/g, width)
+                return template.replace(/\{actions\}/g, '').replace(/\{caption\}/g, caption).replace(/\{width\}/g,
+                    width)
                     .replace(/\{indicator\}/g, '').replace(/\{indicatorTitle\}/g, '');
             }
             return '';
         },
-        renderFileActions: function(showUpload, showDelete, disabled, url, key) {
+        renderFileActions: function (showUpload, showDelete, disabled, url, key) {
             if (!showUpload && !showDelete) {
                 return '';
             }
@@ -594,7 +602,7 @@
                 .replace(/\{upload\}/g, btnUpload)
                 .replace(/\{other\}/g, otherActionButtons);
         },
-        getInitialPreview: function(template, content, i) {
+        getInitialPreview: function (template, content, i) {
             var self = this, ind = 'init_' + i,
                 previewId = self.previewInitId + '-' + ind;
             footer = self.renderInitFileFooter(i, false);
@@ -639,44 +647,44 @@
             self.setCaption(caption);
             self.$container.removeClass('file-input-new');
         },
-        initPreviewDeletes: function() {
+        initPreviewDeletes: function () {
             var self = this,
-                resetProgress = function() {
+                resetProgress = function () {
                     if (self.$preview.find('.kv-file-remove').length == 0) {
                         self.reset();
                     }
                 };
-            self.$preview.find('.kv-file-remove').each(function() {
+            self.$preview.find('.kv-file-remove').each(function () {
                 var $el = $(this), $frame = $el.closest('.file-preview-frame'),
                     vUrl = $el.attr('data-url'), vKey = $el.attr('data-key'),
                     $content = $(self.initialPreviewContent);
                 if (vUrl === undefined || vKey === undefined) {
                     return;
                 }
-                $el.off('click').on('click', function() {
+                $el.off('click').on('click', function () {
                     $.ajax({
                         url: vUrl,
                         type: 'POST',
                         dataType: 'json',
                         data: {key: vKey},
-                        beforeSend: function(jqXHR) {
+                        beforeSend: function (jqXHR) {
                             addCss($frame, 'file-uploading');
                             addCss($el, 'disabled');
                             self.raise('filepredelete', [vKey, jqXHR]);
                         },
-                        success: function(data, textStatus, jqXHR) {
-                            if(typeof data.error === 'undefined') {
+                        success: function (data, textStatus, jqXHR) {
+                            if (typeof data.error === 'undefined') {
                                 self.raise('filedeleted', [vKey, jqXHR]);
                             } else {
                                 self.showError(data.error, null, $el.attr('id'), key, 'filedeleteerror', jqXHR);
                                 resetProgress();
                             }
                             $frame.removeClass('file-uploading').addClass('file-deleted');
-                            $frame.fadeOut('slow', function() {
+                            $frame.fadeOut('slow', function () {
                                 self.clearObjects($frame);
                                 $frame.remove();
                                 var $content = $(document.createElement('div')).html(self.original.preview);
-                                $content.find('.file-preview-frame').each(function() {
+                                $content.find('.file-preview-frame').each(function () {
                                     var $el = $(this);
                                     if ($el.find('.kv-file-remove').attr('data-key') == vKey) {
                                         $el.remove();
@@ -696,7 +704,7 @@
                                 resetProgress();
                             });
                         },
-                        error: function(jqXHR, textStatus, errorThrown) {
+                        error: function (jqXHR, textStatus, errorThrown) {
                             self.showError(errorThrown, null, $el.attr('id'), key, 'filedeleteerror', jqXHR);
                             $frame.removeClass('file-uploading');
                             resetProgress();
@@ -705,18 +713,18 @@
                 });
             });
         },
-        clearObjects: function($el) {
-            $el.find('video audio').each(function() {
+        clearObjects: function ($el) {
+            $el.find('video audio').each(function () {
                 this.pause();
                 delete(this);
                 $(this).remove();
             });
-            $el.find('img object div').each(function() {
+            $el.find('img object div').each(function () {
                 delete(this);
                 $(this).remove();
             });
         },
-        clearFileInput: function() {
+        clearFileInput: function () {
             var self = this, $el = self.$element;
             if (isEmpty($el.val())) {
                 return;
@@ -741,7 +749,7 @@
                 $el.val('');
             }
         },
-        resetUpload: function() {
+        resetUpload: function () {
             var self = this;
             self.uploadCount = 0;
             self.uploadPercent = 0;
@@ -751,13 +759,13 @@
             self.resetErrors(false);
             self.ajaxRequests = [];
         },
-        cancel: function() {
+        cancel: function () {
             var self = this, xhr = self.ajaxRequests, len = xhr.length;
             if (len > 0) {
                 for (i = 0; i < len; i++) {
                     xhr[i].abort();
                 }
-                self.$preview.find('file-preview-frame').each(function() {
+                self.$preview.find('file-preview-frame').each(function () {
                     $thumb = $(this), ind = $thumb.attr('data-fileindex');
                     $thumb.removeClass('file-uploading');
                     if (self.filestack[ind] !== undefined) {
@@ -795,7 +803,7 @@
                 self.initPreviewDeletes();
                 self.$container.removeClass('file-input-new');
             } else {
-                self.$preview.find('.file-preview-frame').each(function() {
+                self.$preview.find('.file-preview-frame').each(function () {
                     self.clearObjects($(this));
                 });
                 self.$preview.html('');
@@ -836,44 +844,44 @@
             self.filestack = [];
             self.formdata = {};
         },
-        disable: function (e) {
+        disable: function () {
             var self = this;
             self.isDisabled = true;
+            self.raise('filedisabled');
             self.$element.attr('disabled', 'disabled');
             self.$container.find(".kv-fileinput-caption").addClass("file-caption-disabled");
             self.$container.find(".btn-file, .fileinput-remove, .kv-fileinput-upload").attr("disabled", true);
             self.initDragDrop();
         },
-        enable: function (e) {
+        enable: function () {
             var self = this;
             self.isDisabled = false;
+            self.raise('fileenabled');
             self.$element.removeAttr('disabled');
             self.$container.find(".kv-fileinput-caption").removeClass("file-caption-disabled");
             self.$container.find(".btn-file, .fileinput-remove, .kv-fileinput-upload").removeAttr("disabled");
             self.initDragDrop();
         },
-        getExtraData: function() {
+        getExtraData: function () {
             var self = this, data = self.uploadExtraData;
             if (typeof(self.uploadExtraData) == "function") {
                 data = self.uploadExtraData();
             }
             return data;
         },
-        uploadExtra: function(fd) {
+        uploadExtra: function () {
             var self = this, data = self.getExtraData();
             if (data.length == 0) {
                 return;
             }
-            $.each(data, function(key, value) {
-                if (!isEmpty(key) && !isEmpty(value)) {
-                    fd.append(key, value);
-                }
+            $.each(data, function (key, value) {
+                self.formdata.append(key, value);
             });
         },
-        initXhr: function(xhrobj, factor) {
+        initXhr: function (xhrobj, factor) {
             var self = this;
             if (xhrobj.upload) {
-                xhrobj.upload.addEventListener('progress', function(event) {
+                xhrobj.upload.addEventListener('progress', function (event) {
                     var pct = 0, position = event.loaded || event.position, total = event.total;
                     if (event.lengthComputable) {
                         pct = Math.ceil(position / total * factor);
@@ -884,16 +892,35 @@
             }
             return xhrobj;
         },
-        upload: function(i, files) {
+        ajaxSubmit: function (fnBefore, fnSuccess, fnComplete, fnError) {
+            var self = this;
+            self.uploadExtra();
+            self.ajaxRequests.push($.ajax({
+                xhr: function () {
+                    var xhrobj = $.ajaxSettings.xhr();
+                    return self.initXhr(xhrobj, 98);
+                },
+                url: self.uploadUrl,
+                type: 'POST',
+                dataType: 'json',
+                data: self.formdata,
+                cache: false,
+                processData: false,
+                contentType: false,
+                beforeSend: fnBefore,
+                success: fnSuccess,
+                complete: fnComplete,
+                error: fnError
+            }));
+        },
+        uploadSingle: function (i, files) {
             var self = this, total = self.getFileStack().length, formdata = new FormData(),
                 previewId = self.previewInitId + "-" + i, $thumb = $('#' + previewId),
                 $btnUpload = $thumb.find('.kv-file-upload'), $btnDelete = $thumb.find('.kv-file-remove'),
-                $indicator = $thumb.find('.file-upload-indicator'), config = self.fileActionSettings;
+                $indicator = $thumb.find('.file-upload-indicator'), config = self.fileActionSettings,
+                hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData);
             self.formdata = formdata;
-            if (total == 0) {
-                return;
-            }
-            if ($btnUpload.hasClass('disabled')) {
+            if (total == 0 || !hasPostData || $btnUpload.hasClass('disabled')) {
                 return;
             }
             var percent,
@@ -902,37 +929,22 @@
                     $indicator.html(config[icon]);
                     $indicator.attr('title', config[msg]);
                 },
-                updateProgress = function() {
+                updateProgress = function () {
                     if (!allFiles || total == 0 || self.uploadPercent >= 100) {
                         return;
                     }
                     self.uploadCount++;
-                    var pct = 80 + Math.ceil(self.uploadCount * 20/total);
+                    var pct = 80 + Math.ceil(self.uploadCount * 20 / total);
                     self.uploadPercent = Math.max(pct, self.uploadPercent);
                     self.setProgress(self.uploadPercent);
                     self.initPreviewDeletes();
                 },
-                resetActions = function() {
+                resetActions = function () {
                     $btnUpload.removeAttr('disabled');
                     $btnDelete.removeAttr('disabled');
                     $thumb.removeClass('file-uploading');
-                };
-            formdata.append(self.uploadFileAttr, files[i]);
-            formdata.append('file_id', i);
-            self.uploadExtra(formdata);
-            self.ajaxRequests.push($.ajax({
-                xhr: function() {
-                    var xhrobj = $.ajaxSettings.xhr();
-                    return self.initXhr(xhrobj, 80);
                 },
-                url: self.uploadUrl,
-                type: 'POST',
-                dataType: 'json',
-                data: formdata,
-                cache: false,
-                processData: false,
-                contentType: false,
-                beforeSend: function(jqXHR) {
+                fnBefore = function (jqXHR) {
                     var outData = self.getOutData(jqXHR);
                     setIndicator('indicatorLoading', 'indicatorLoadingTitle');
                     addCss($thumb, 'file-uploading');
@@ -943,10 +955,10 @@
                     }
                     self.raise('filepreupload', [outData, previewId, i])
                 },
-                success: function(data, textStatus, jqXHR) {
+                fnSuccess = function (data, textStatus, jqXHR) {
                     var outData = self.getOutData(jqXHR, data);
-                    setTimeout(function() {
-                        if(typeof data.error === 'undefined') {
+                    setTimeout(function () {
+                        if (typeof data.error === 'undefined') {
                             setIndicator('indicatorSuccess', 'indicatorSuccessTitle');
                             $btnUpload.hide();
                             $btnDelete.hide();
@@ -958,8 +970,8 @@
                         }
                     }, 100);
                 },
-                complete: function() {
-                    setTimeout(function() {
+                fnComplete = function () {
+                    setTimeout(function () {
                         updateProgress();
                         resetActions();
                     }, 100);
@@ -967,7 +979,7 @@
                         self.unlock();
                     }
                 },
-                error: function(jqXHR, textStatus, errorThrown) {
+                fnError = function (jqXHR, textStatus, errorThrown) {
                     setIndicator('indicatorError', 'indicatorErrorTitle');
                     var outData = self.getOutData(jqXHR);
                     if (allFiles) {
@@ -976,13 +988,16 @@
                     } else {
                         self.showUploadError(errorThrown, outData, previewId, i);
                     }
-                }
-            }));
+                };
+            formdata.append(self.uploadFileAttr, files[i]);
+            formdata.append('file_id', i);
+            self.ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
         },
-        uploadBatch: function() {
-            var self = this, files = self.filestack, total = files.length, formdata = new FormData();
+        uploadBatch: function () {
+            var self = this, files = self.filestack, total = files.length, formdata = new FormData(),
+                hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData);
             self.formdata = formdata;
-            if (total == 0) {
+            if (total == 0 || !hasPostData) {
                 return;
             }
             var config = self.fileActionSettings,
@@ -999,37 +1014,19 @@
                     $btnUpload.removeAttr('disabled');
                     $btnDelete.removeAttr('disabled');
                 },
-                setAllUploaded = function() {
-                    $.each(files, function(key, data) {
+                setAllUploaded = function () {
+                    $.each(files, function (key, data) {
                         self.filestack[key] = undefined;
                     });
                     self.clearFileInput();
-                };
-            $.each(files, function(key, data) {
-                if (files[key] !== undefined) {
-                    formdata.append(self.uploadFileAttr, files[key]);
-                }
-            });
-            self.uploadExtra(formdata);
-            self.ajaxRequests.push($.ajax({
-                xhr: function() {
-                    var xhrobj = $.ajaxSettings.xhr();
-                    return self.initXhr(xhrobj, 98);
                 },
-                url: self.uploadUrl,
-                type: 'POST',
-                dataType: 'json',
-                data: formdata,
-                cache: false,
-                processData: false,
-                contentType: false,
-                beforeSend: function(jqXHR) {
+                fnBefore = function (jqXHR) {
                     self.lock();
                     var outData = self.getOutData(jqXHR);
                     if (!self.showPreview) {
                         return;
                     }
-                    self.$preview.find('.file-preview-frame').each(function() {
+                    self.$preview.find('.file-preview-frame').each(function () {
                         var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload'), $btnDelete = $thumb.find('.kv-file-remove');
                         addCss($thumb, 'file-uploading');
                         $btnUpload.attr('disabled', true);
@@ -1037,16 +1034,16 @@
                     });
                     self.raise('filebatchpreupload', [outData]);
                 },
-                success: function(data, textStatus, jqXHR) {
+                fnSuccess = function (data, textStatus, jqXHR) {
                     var outData = self.getOutData(jqXHR, data);
                     var keys = isEmpty(data.errorkeys) ? [] : data.errorkeys;
-                    if(typeof data.error === 'undefined' || isEmpty(data.error)) {
+                    if (typeof data.error === 'undefined' || isEmpty(data.error)) {
                         self.raise('filebatchuploadsuccess', [outData]);
                         setAllUploaded();
                         if (self.showPreview) {
                             self.$preview.find('.kv-file-upload').hide();
                             self.$preview.find('.kv-file-remove').hide();
-                            self.$preview.find('.file-preview-frame').each(function() {
+                            self.$preview.find('.file-preview-frame').each(function () {
                                 var $thumb = $(this), key = $thumb.attr('data-fileindex');
                                 setIndicator(key, 'indicatorSuccess', 'indicatorSuccessTitle');
                                 enableActions(key);
@@ -1055,7 +1052,7 @@
                             self.reset();
                         }
                     } else {
-                        self.$preview.find('.file-preview-frame').each(function() {
+                        self.$preview.find('.file-preview-frame').each(function () {
                             var $thumb = $(this), key = $thumb.attr('data-fileindex');
                             enableActions(key);
                             if (keys.length == 0) {
@@ -1074,21 +1071,26 @@
                         self.showUploadError(data.error, outData, null, null, 'filebatchuploaderror');
                     }
                 },
-                complete: function () {
+                fnComplete = function () {
                     self.setProgress(100);
                     self.unlock();
                     self.raise('filebatchuploadcomplete', [self.filestack, self.getExtraData()]);
                     self.clearFileInput();
                 },
-                error: function(jqXHR, textStatus, errorThrown) {
+                fnError = function (jqXHR, textStatus, errorThrown) {
                     var outData = self.getOutData(jqXHR);
                     self.showUploadError(errorThrown, outData, null, null, 'filebatchuploaderror');
                     self.uploadFileCount = total - 1;
                     self.$preview.find('.file-preview-frame').removeClass('file-uploading');
                     self.$preview.find('.file-preview-frame kv-file-upload').removeAttr('disabled');
                     self.$preview.find('.file-preview-frame kv-file-delete').removeAttr('disabled');
+                };
+            $.each(files, function (key, data) {
+                if (files[key] !== undefined) {
+                    self.formdata.append(self.uploadFileAttr, files[key]);
                 }
-            }));
+            });
+            self.ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
         },
         hideFileIcon: function () {
             if (this.overwriteInitial) {
@@ -1152,7 +1154,7 @@
                     self.addError(self.msgFilePreviewError.replace(/\{name\}/g, caption));
             }
         },
-        parseFileType: function(file) {
+        parseFileType: function (file) {
             var isValid, vType;
             for (var i = 0; i < defaultPreviewTypes.length; i++) {
                 cat = defaultPreviewTypes[i];
@@ -1164,7 +1166,7 @@
             }
             return 'other';
         },
-        previewDefault: function(file, previewId) {
+        previewDefault: function (file, previewId) {
             var self = this;
             if (!self.showPreview) {
                 return;
@@ -1192,21 +1194,23 @@
                 .replace(/\{type\}/g, file.type)
                 .replace(/\{data\}/g, data)
                 .replace(/\{footer\}/g, footer));
-            $obj.on('load', function(e) {
+            $obj.on('load', function (e) {
                 vUrl.revokeObjectURL($obj.attr('data'));
             });
         },
-        previewFile: function(file, theFile, previewId, data) {
+        previewFile: function (file, theFile, previewId, data) {
             var self = this;
             if (!self.showPreview) {
                 return;
             }
             var cat = self.parseFileType(file), caption = self.slug(file.name), data, obj, content,
                 types = self.allowedPreviewTypes, mimes = self.allowedPreviewMimeTypes, fType = file.type,
-                template = isSet(cat, self.previewTemplates) ? self.previewTemplates[cat] : defaultPreviewTemplates[cat],
+                template = isSet(cat,
+                    self.previewTemplates) ? self.previewTemplates[cat] : defaultPreviewTemplates[cat],
                 config = isSet(cat, self.previewSettings) ? self.previewSettings[cat] : defaultPreviewSettings[cat],
                 wrapLen = parseInt(self.wrapTextLength), wrapInd = self.wrapIndicator, $preview = self.$preview,
-                chkTypes = types.indexOf(cat) >=0, chkMimes = isEmpty(mimes) || (!isEmpty(mimes) && isSet(file.type, mimes)),
+                chkTypes = types.indexOf(cat) >= 0, chkMimes = isEmpty(mimes) || (!isEmpty(mimes) && isSet(file.type,
+                        mimes)),
                 footer = self.renderFileFooter(caption, config.width),
                 ind = previewId.slice(previewId.lastIndexOf('-') + 1);
             if (chkTypes && chkMimes) {
@@ -1246,11 +1250,13 @@
             }
         },
         slugDefault: function (text) {
-            return isEmpty(text) ? '' : text.split(/(\\|\/)/g).pop().replace(/[^\w-.\\\/ ]+/g,'');
+            return isEmpty(text) ? '' : text.split(/(\\|\/)/g).pop().replace(/[^\w-.\\\/ ]+/g, '');
         },
-        getFileStack: function() {
+        getFileStack: function () {
             var size = 0, self = this;
-            return self.filestack.filter(function(n){ return n != undefined });
+            return self.filestack.filter(function (n) {
+                return n != undefined
+            });
         },
         readFiles: function (files) {
             this.reader = new FileReader();
@@ -1261,11 +1267,13 @@
                 previewInitId = self.previewInitId, numFiles = files.length, settings = self.fileTypeSettings,
                 isText = isSet('text', settings) ? settings['text'] : defaultFileTypeSettings['text'],
                 ctr = self.filestack.length,
-                throwError = function(msg, file, previewId, index) {
+                throwError = function (msg, file, previewId, index) {
                     self.previewDefault(file, previewId, true);
                     var outData = self.getOutData({}, {}, files);
-                    return self.isUploadable ? self.showUploadError(msg, outData, previewId, index) : self.showError(msg, file, previewId, index);
+                    return self.isUploadable ? self.showUploadError(msg, outData, previewId,
+                        index) : self.showError(msg, file, previewId, index);
                 };
+
             function readFile(i) {
                 if (isEmpty($el.attr('multiple'))) {
                     numFiles = 1;
@@ -1305,7 +1313,8 @@
                     chk = caption.match(fileExtExpr);
                     fileCount += isEmpty(chk) ? 0 : chk.length;
                     if (fileCount == 0) {
-                        msg = self.msgInvalidFileExtension.replace(/\{name\}/g, caption).replace(/\{extensions\}/g, strExt);
+                        msg = self.msgInvalidFileExtension.replace(/\{name\}/g, caption).replace(/\{extensions\}/g,
+                            strExt);
                         self.isError = throwError(msg, file, previewId, i);
                         return;
                     }
@@ -1358,7 +1367,7 @@
                     }
                 } else {
                     self.previewDefault(file, previewId);
-                    setTimeout(function() {
+                    setTimeout(function () {
                         readFile(i + 1);
                         self.updateFileDetails(numFiles);
                     }, 100);
@@ -1366,10 +1375,11 @@
                 }
                 self.filestack.push(file);
             }
+
             readFile(0);
             self.updateFileDetails(numFiles, false);
         },
-        updateFileDetails: function(numFiles) {
+        updateFileDetails: function (numFiles) {
             var self = this, msgSelected = self.msgSelected, $el = self.$element, fileStack = self.getFileStack(),
                 name = $el.val() || (fileStack.length && fileStack[0].name) || '', label = self.slug(name),
                 n = self.isUploadable ? fileStack.length : numFiles;
@@ -1397,13 +1407,14 @@
                 numFiles = !isEmpty(files) ? (files.length + self.initialPreviewCount) : 1, tfiles,
                 ctr = self.filestack.length, isAjaxUpload = (self.isUploadable && ctr != 0),
                 isSingleUpload = isEmpty($el.attr('multiple')),
-                throwError = function(msg, file, previewId, index) {
+                throwError = function (msg, file, previewId, index) {
                     var outData = self.getOutData({}, {}, files);
-                    return self.isUploadable ? self.showUploadError(msg, outData, previewId, index) : self.showError(msg, file, previewId, index);
+                    return self.isUploadable ? self.showUploadError(msg, outData, previewId,
+                        index) : self.showError(msg, file, previewId, index);
                 };
             self.resetUpload();
             self.hideFileIcon();
-            self.$container.find('.file-drop-zone .' + self.dropZoneTitleClass).remove(); 
+            self.$container.find('.file-drop-zone .' + self.dropZoneTitleClass).remove();
             if (isDragDrop) {
                 tfiles = files;
             } else {
@@ -1432,7 +1443,7 @@
                 if (isSingleUpload && ctr > 0) {
                     self.filestack = [];
                 }
-            } 
+            }
             var total = self.isUploadable ? self.getFileStack().length + tfiles.length : tfiles.length;
             if (self.maxFileCount > 0 && total > self.maxFileCount) {
                 var msg = self.msgFilesTooMany.replace(/\{m\}/g, self.maxFileCount).replace(/\{n\}/g, total);
@@ -1450,14 +1461,14 @@
             }
             self.reader = null;
         },
-        autoSizeImage: function(previewId) {
+        autoSizeImage: function (previewId) {
             var self = this, $preview = self.$preview,
                 $thumb = $preview.find("#" + previewId),
                 $img = $thumb.find('img');
             if (!$img.length) {
                 return;
             }
-            $img.on('load', function() {
+            $img.on('load', function () {
                 var w1 = $thumb.width(), w2 = $preview.width();
                 if (w1 > w2) {
                     $img.css('width', '100%');
@@ -1471,7 +1482,7 @@
                 self.raise('fileimageloaded', previewId);
             });
         },
-        setCaption: function(content) {
+        setCaption: function (content) {
             var self = this, title = $('<div>' + content + '</div>').text(),
                 icon = self.getLayoutTemplate('icon'),
                 out = icon + title;
@@ -1502,7 +1513,7 @@
             self.initBrowse($container);
         },
         renderMain: function () {
-            var self = this, dropCss = (self.isUploadable && self.dropZoneEnabled) ? ' file-drop-zone' : '';;
+            var self = this, dropCss = (self.isUploadable && self.dropZoneEnabled) ? ' file-drop-zone' : '';
             var preview = self.showPreview ? self.getLayoutTemplate('preview')
                 .replace(/\{class\}/g, self.previewClass)
                 .replace(/\{dropClass\}/g, dropCss)

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
js/fileinput.min.js


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است