瀏覽代碼

Fix #20, #21: Various enhancements to file preview

Kartik Visweswaran 10 年之前
父節點
當前提交
729ec7cc1f
共有 4 個文件被更改,包括 55 次插入30 次删除
  1. 5 2
      CHANGE.md
  2. 22 9
      README.md
  3. 28 19
      js/fileinput.js
  4. 0 0
      js/fileinput.min.js

+ 5 - 2
CHANGE.md

@@ -1,13 +1,16 @@
 version 2.1.0
 =============
-**Date:** 08-Aug-2014
+**Date:** 11-Aug-2014
 
 1. (enh #16, #17): Added exception handling for trapping FileReader API errors
 2. New configuration property added: `maxFilesCount`. Defaults to `0` which means unlimited.
 3. New configurable error messages added: `msgFilesTooMany`, `msgFileNotFound`, `msgFileNotReadable`, `msgFilePreviewAborted`, and `msgFilePreviewError`.
 4. Enhanced plugin to improve browser performance when loading and previewing multiple image files.
 5. (enh #18): Better validation for older browsers (not supporting HTML5) to degrade to normal file input.
-6. Other minor bug fixes.
+6. (enh #20): Fix `fileloaded` event to increment `previewId` and enhance to return file index.
+7. (enh #21): Enhance multiple file upload and preview performance using setTimeout.
+8. (enh #21): Enhance loading progress message and message templates for multiple file uploads.
+9. Other minor bug fixes.
 
 version 2.0.0
 =============

+ 22 - 9
README.md

@@ -32,7 +32,7 @@ An enhanced HTML 5 file input for Bootstrap 3.x with file preview for images and
 11. Upload action defaults to form submit. Supports an upload route/server action parameter for custom ajax based upload.
 12. Triggers JQuery events for advanced development. Events currently available are `filereset`, `fileclear`, `filecleared`, `fileloaded`, and `fileerror`.
 13. Disabled and readonly file input support.
-14. Size of the entire plugin is less than 6KB if gzipped. The minified assets are less than 16KB (about 13KB for the minified JS and 3KB for the minified CSS).
+14. Size of the entire plugin is less than 6KB if gzipped. The minified assets are less than 19KB (about 16KB for the minified JS and 3KB for the minified CSS).
 
 ## Demo
 
@@ -397,13 +397,18 @@ where:
 _string_ the css class for the error message to be displayed in the preview window when the file size exceeds `maxSize`. Defaults to `file-error-message`.
 
 #### msgLoading
-_string_ the message displayed when the files are getting read and loaded for preview. Defaults to `Loading …`.
+_string_ the message displayed when the files are getting read and loaded for preview. Defaults to `Loading  file {index} of {files} …`.
+
+- `{index}`: the sequence number of the current file being loaded.
+- `{files}`: the total number of files selected for upload.
 
 #### msgProgress
-_string_ the progress message displayed as each file is loaded for preview. Defaults to `Loaded {percent}% of {file}`. The following variables will be replaced:
+_string_ the progress message displayed as each file is loaded for preview. Defaults to `Loading file {index} of {files} - {name} - {percent}% completed.`. The following variables will be replaced:
 
+- `{index}`: the sequence number of the current file being loaded.
+- `{files}`: the total number of files selected for upload.
 - `{percent}`: the percentage of file read and loaded.
-- `{file}`: the name of the file being loaded.
+- `{name}`: the name of the current file being loaded.
 
 #### msgSelected
 _string_ the progress message displayed in caption window when multiple (more than one) files are selected. Defaults to `{n} files selected`. The following variables will be replaced:
@@ -467,23 +472,31 @@ $('#input-id').on('filecleared', function(event) {
 
 #### fileerror
 This event is triggered when a client validation error is encountered for an uploaded file. 
-Additional parameters available are: `file` (FileReader instance) and `previewId` the 
-identifier for the preview file container.
+Additional parameters available are: 
+
+- `file`: the FileReader instance 
+- `previewId`: the identifier for the preview file container.
+- `index`: the zero-based sequential index of the loaded file in the preview list
 
 **Example:**
 ```js
-$('#input-id').on('fileerror', function(event, file, previewId) {
+$('#input-id').on('fileerror', function(event, file, previewId, index) {
     console.log("fileerror");
 });
 ```
 
 #### fileloaded
 This event is triggered after a file is loaded in the preview. Additional parameters available 
-are: `file` (FileReader instance) and `previewId` the identifier for the preview file container.
+are: 
+
+- `file`: the FileReader instance 
+- `previewId`: the identifier for the preview file container.
+- `index`: the zero-based sequential index of the loaded file in the preview list
+
 
 **Example:**
 ```js
-$('#input-id').on('fileloaded', function(event, file, previewId) {
+$('#input-id').on('fileloaded', function(event, file, previewId, index) {
     console.log("fileloaded");
 });
 ```

+ 28 - 19
js/fileinput.js

@@ -187,7 +187,7 @@
         listen: function () {
             var self = this;
             self.$element.on('change', $.proxy(self.change, self));
-            self.$btnFile.on('click', function(ev) {
+            self.$btnFile.on('click', function (ev) {
                 self.$captionContainer.focus();
             });
             $(self.$element[0].form).on('reset', $.proxy(self.reset, self));
@@ -289,12 +289,12 @@
             self.$container.find(".kv-fileinput-caption").removeClass("file-caption-disabled");
             self.$container.find(".btn-file, .fileinput-remove, .kv-fileinput-upload").removeAttr("disabled");
         },
-        hideFileIcon: function() {
+        hideFileIcon: function () {
             if (this.overwriteInitial) {
                 this.$captionContainer.find('.kv-caption-icon').hide();
             }
         },
-        showFileIcon: function() {
+        showFileIcon: function () {
             this.$captionContainer.find('.kv-caption-icon').show();
         },
         resetErrors: function (fade) {
@@ -305,7 +305,7 @@
                 $error.remove();
             }
         },
-        showError: function (msg, file, previewId) {
+        showError: function (msg, file, previewId, index) {
             var self = this, $error = self.$previewContainer.find('.kv-fileinput-error');
             if (isEmpty($error.attr('class'))) {
                 self.$previewContainer.append(
@@ -316,7 +316,7 @@
             }
             $error.hide();
             $error.fadeIn(800);
-            self.$element.trigger('fileerror', [file, previewId]);
+            self.$element.trigger('fileerror', [file, previewId, index]);
             self.$element.val('');
             return true;
         },
@@ -360,25 +360,25 @@
                 $container = self.$previewContainer, $status = self.$previewStatus, msgLoading = self.msgLoading,
                 msgProgress = self.msgProgress, msgSelected = self.msgSelected, fileType = self.previewFileType,
                 wrapLen = parseInt(self.wrapTextLength), wrapInd = self.wrapIndicator,
-                previewId = "preview-" + uniqId();
+                previewInitId = "preview-" + uniqId(), numFiles = files.length;
 
             function readFile(i) {
-                if (i >= files.length) {
+                if (i >= numFiles) {
                     $container.removeClass('loading');
                     $status.html('');
                     return;
                 }
-                previewId += "-" + i;
+                var previewId = previewInitId + "-" + i;
                 var file = files[i], caption = file.name, isImg = isImageFile(file.type, file.name),
                     isTxt = isTextFile(file.type, file.name), fileSize = (file.size ? file.size : 0) / 1000;
                 fileSize = fileSize.toFixed(2);
                 if (self.maxFileSize > 0 && fileSize > self.maxFileSize) {
                     var msg = self.msgSizeTooLarge.replace('{name}', caption).replace('{size}', fileSize).replace('{maxSize}', self.maxFileSize);
-                    self.isError = self.showError(msg, file, previewId);
+                    self.isError = self.showError(msg, file, previewId, i);
                     return;
                 }
                 if ($preview.length > 0 && (fileType == "any" ? (isImg || isTxt) : (fileType == "text" ? isTxt : isImg)) && typeof FileReader !== "undefined") {
-                    $status.html(msgLoading);
+                    $status.html(msgLoading.replace('{index}', i + 1).replace('{files}', numFiles));
                     $container.addClass('loading');
                     reader.onerror = function (evt) {
                         self.errorHandler(evt, caption);
@@ -400,14 +400,22 @@
                         $preview.append("\n" + content);
                     };
                     reader.onloadend = function (e) {
-                        setTimeout(readFile(i + 1), 1000);
-                        $el.trigger('fileloaded', [file, previewId]);
+                        var msg = msgProgress.replace('{index}', i + 1).replace('{files}', numFiles).replace('{percent}', 100).replace('{file}', file.name);
+                        setTimeout(function () {
+                            $status.html(msg);
+                        }, 1000);
+                        setTimeout(function () {
+                            readFile(i + 1)
+                        }, 1500);
+                        $el.trigger('fileloaded', [file, previewId, i]);
                     };
                     reader.onprogress = function (data) {
                         if (data.lengthComputable) {
                             var progress = parseInt(((data.loaded / data.total) * 100), 10);
-                            var msg = msgProgress.replace('{percent}', progress).replace('{file}', file.name);
-                            $status.html(msg);
+                            var msg = msgProgress.replace('{index}', i + 1).replace('{files}', numFiles).replace('{percent}', progress).replace('{file}', file.name);
+                            setTimeout(function () {
+                                $status.html(msg);
+                            }, 1000);
                         }
                     };
                     if (isTxt) {
@@ -417,10 +425,11 @@
                     }
                 } else {
                     $preview.append("\n" + self.previewOtherTemplate.replace("{previewId}", previewId).replace("{caption}", caption));
-                    $el.trigger('fileloaded', [file, previewId]);
+                    $el.trigger('fileloaded', [file, previewId, i]);
                     setTimeout(readFile(i + 1), 1000);
                 }
             }
+
             readFile(0);
         },
         change: function (e) {
@@ -446,7 +455,7 @@
             var total = tfiles.length;
             if (self.maxFilesCount > 0 && total > self.maxFilesCount) {
                 var msg = self.msgFilesTooMany.replace('{m}', self.maxFilesCount).replace('{n}', total);
-                self.isError = self.showError(msg, null, null);
+                self.isError = self.showError(msg, null, null, null);
                 self.$container.removeClass('file-input-new');
                 return;
             }
@@ -462,7 +471,7 @@
             self.$container.removeClass('file-input-new');
             $el.trigger('fileselect', [numFiles, label]);
         },
-        initBrowse: function($container) {
+        initBrowse: function ($container) {
             var self = this;
             self.$btnFile = $container.find('.btn-file');
             self.$btnFile.append(self.$element);
@@ -597,8 +606,8 @@
         msgFilePreviewAborted: 'File preview aborted for "{name}".',
         msgFilePreviewError: 'An error occurred while reading the file "{name}".',
         msgErrorClass: 'file-error-message',
-        msgLoading: 'Loading …',
-        msgProgress: 'Loaded {percent}% of {file}',
+        msgLoading: 'Loading  file {index} of {files} …',
+        msgProgress: 'Loading file {index} of {files} - {name} - {percent}% completed.',
         msgSelected: '{n} files selected',
         previewFileType: 'image',
         wrapTextLength: 250,

文件差異過大導致無法顯示
+ 0 - 0
js/fileinput.min.js


部分文件因文件數量過多而無法顯示