Browse Source

Fix #157: Upload progress bar styling enhancements

Kartik Visweswaran 10 years ago
parent
commit
63c6b89a9e
4 changed files with 155 additions and 128 deletions
  1. 6 1
      CHANGE.md
  2. 10 1
      README.md
  3. 139 126
      js/fileinput.js
  4. 0 0
      js/fileinput.min.js

+ 6 - 1
CHANGE.md

@@ -1,6 +1,6 @@
 version 4.1.7
 =============
-**Date**: 31-Jan-2015
+**Date**: 02-Feb-2015
 
 1. (enh #149): Custom tags support for layoutTemplates and previewTemplates (new properties `customLayoutTags` and `customPreviewTags` included).
 2. (enh #151): New `filebatchselected` event triggered after every batch of files are selected.
@@ -9,6 +9,11 @@ version 4.1.7
 5. (enh #154): Code cleanup and restructure for JS lint changes (using JSHint Code cleanup library).
 6. (enh #155): Allow display of long file names without spaces/word breaks.
 7. (enh #156): Fix reset of file stack for various upload modes (single, batch async and batch sync).
+8. (enh #157): Upload progress bar styling enhancements.
+    - Allow upload progress bar css class to be configurable 
+    - Create and allow two different styles/css classes for progress bar
+       - `progressClass`: styling for progress bar when upload is in process
+       - `progressCompleteClass`: styling for progress bar when upload is complete
 
 version 4.1.6
 =============

+ 10 - 1
README.md

@@ -284,6 +284,10 @@ The `preview` and `caption` templates can understand the following special tags
 
 - `{class}`: the CSS class as set in the `mainClass`, `captionClass` or `previewClass` properties.
 
+Similarly, the `progress` layout template can understand the following special tags which will be replaced:
+
+- `{class}`: the CSS class as set in the `progressClass` or `progressCompleteClass` properties.
+
 The `layoutTemplates` if not set will default to:
 
 ```js
@@ -329,7 +333,7 @@ The `layoutTemplates` if not set will default to:
         '  </div>\n' +
         '</div>',
     progress: '<div class="progress">\n' +
-        '    <div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" aria-valuenow="{percent}" aria-valuemin="0" aria-valuemax="100" style="width:{percent}%;">\n' +
+        '    <div class="{class}" role="progressbar" aria-valuenow="{percent}" aria-valuemin="0" aria-valuemax="100" style="width:{percent}%;">\n' +
         '        {percent}%\n' +
         '     </div>\n' +
         '</div>',
@@ -784,6 +788,11 @@ _string_ the progress message displayed in caption window when multiple (more th
 
 - `{n}`: the number of files selected.
 
+#### progressClass
+_string_ the upload progress bar CSS class to be applied when AJAX upload is in process (applicable only for ajax uploads). Defaults to `progress-bar progress-bar-success progress-bar-striped active`. 
+
+#### progressCompleteClass
+_string_ the upload progress bar CSS class to be applied when AJAX upload is complete. Defaults to `progress-bar progress-bar-success`. 
 
 #### previewFileType
 _string_ the type of files that are to be displayed in the preview window. Defaults to `image`. Can be one of the following:

+ 139 - 126
js/fileinput.js

@@ -17,14 +17,14 @@
  */
 (function ($) {
     "use strict";
-    String.prototype.replaceAll = function (from, to) {
+    String.prototype.repl = function (from, to) {
         return this.split(from).join(to);
     };
     var isIE = function (ver) {
             var div = document.createElement("div"), status;
             div.innerHTML = "<!--[if IE " + ver + "]><i></i><![endif]-->";
-            document.body.appendChild(div);
             status = (div.getElementsByTagName("i").length === 1);
+            document.body.appendChild(div);
             div.parentNode.removeChild(div);
             return status;
         },
@@ -108,7 +108,7 @@
             '  </div>\n' +
             '</div>',
         tProgress = '<div class="progress">\n' +
-            '    <div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar"' +
+            '    <div class="{class}" role="progressbar"' +
             ' aria-valuenow="{percent}" aria-valuemin="0" aria-valuemax="100" style="width:{percent}%;">\n' +
             '        {percent}%\n' +
             '     </div>\n' +
@@ -261,11 +261,11 @@
             return Math.round(new Date().getTime() + (Math.random() * 100));
         },
         htmlEncode = function (str) {
-            return String(str).replaceAll('&', '&amp;')
-                .replaceAll('"', '&quot;')
-                .replaceAll("'", '&#39;')
-                .replaceAll('<', '&lt;')
-                .replaceAll('>', '&gt;');
+            return String(str).repl('&', '&amp;')
+                .repl('"', '&quot;')
+                .repl("'", '&#39;')
+                .repl('<', '&lt;')
+                .repl('>', '&gt;');
         },
         replaceTags = function (str, tags) {
             var out = str;
@@ -273,7 +273,7 @@
                 if (typeof value === "function") {
                     value = value();
                 }
-                out = out.replaceAll(key, value);
+                out = out.repl(key, value);
             });
             return out;
         },
@@ -291,8 +291,7 @@
     FileInput.prototype = {
         constructor: FileInput,
         init: function (options) {
-            var self = this, $el = self.$element, content;
-            self.locked = false;
+            var self = this, $el = self.$element, content, t;
             $.each(options, function (key, value) {
                 self[key] = value;
             });
@@ -351,6 +350,9 @@
             self.uploadCount = 0;
             self.uploadPercent = 0;
             self.$element.removeClass('file-loading');
+            t = self.getLayoutTemplate('progress');
+            self.progressTemplate = t.replace('{class}', self.progressClass);
+            self.progressCompleteTemplate = t.replace('{class}', self.progressCompleteClass);
             self.setEllipsis();
         },
         raise: function (event, params) {
@@ -435,8 +437,9 @@
             });
         },
         setProgress: function (p) {
-            var self = this, template = self.getLayoutTemplate('progress'), pct = Math.min(p, 100);
-            self.$progress.html(template.replaceAll('{percent}', pct));
+            var self = this, pct = Math.min(p, 100),
+                template = pct < 100 ? self.progressTemplate : self.progressCompleteTemplate;
+            self.$progress.html(template.repl('{percent}', pct));
         },
         upload: function () {
             var self = this, totLen = self.getFileStack().length,
@@ -459,18 +462,6 @@
                         self.uploadSingle(i, self.filestack, true);
                     }
                 }
-                setTimeout(function () {
-                    $(document).off('.kvfileinput').on('ajaxStop.kvfileinput', function () {
-                        if (!self.locked) {
-                            return;
-                        }
-                        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();
@@ -485,11 +476,13 @@
             if (self.showCancel) {
                 self.$container.find('.fileinput-cancel').removeClass('hide');
             }
-            self.locked = true;
             self.raise('filelock', [self.filestack, self.getExtraData()]);
         },
-        unlock: function () {
+        unlock: function (reset) {
             var self = this;
+            if (reset === undefined) {
+                reset = true;
+            }
             self.enable();
             if (self.showCancel) {
                 addCss(self.$container.find('.fileinput-cancel'), 'hide');
@@ -497,8 +490,9 @@
             if (self.showRemove) {
                 self.$container.find('.fileinput-remove').removeClass('hide');
             }
-            self.resetFileStack();
-            self.locked = false;
+            if (reset) {
+                self.resetFileStack();
+            }
             self.raise('fileunlock', [self.filestack, self.getExtraData()]);
         },
         resetFileStack: function () {
@@ -506,16 +500,19 @@
             self.$preview.find('.file-preview-frame').each(function () {
                 var $thumb = $(this), ind = $thumb.attr('data-fileindex'),
                     file = self.filestack[ind];
+                if (ind == -1) {
+                    return;
+                }
                 if (file !== undefined) {
                     newstack[i] = file;
                     $thumb.attr({
                         'id': self.previewInitId + '-' + i,
                         'data-fileindex': i
                     });
-                    i = i + 1;
+                    i += 1;
                 } else {
                     $thumb.attr({
-                        'id': $thumb.attr('id') + '-1',
+                        'id': 'uploaded-' + uniqId(),
                         'data-fileindex': '-1'
                     });
                 }
@@ -595,7 +592,7 @@
                             self.reset();
                         } else {
                             n = self.initialPreviewCount + len;
-                            cap = n > 1 ? self.msgSelected.replaceAll('{n}', n) : filestack[0].name;
+                            cap = n > 1 ? self.msgSelected.repl('{n}', n) : filestack[0].name;
                             self.setCaption(cap);
                         }
                     });
@@ -606,7 +603,7 @@
                 $el.off('click').on('click', function () {
                     var $frame = $el.closest('.file-preview-frame'),
                         ind = $frame.attr('data-fileindex');
-                    self.uploadSingle(ind, self.filestack);
+                    self.uploadSingle(ind, self.filestack, false);
                 });
             });
         },
@@ -622,25 +619,25 @@
                 key = isSet('key', config) ? config.key : null,
                 disabled = (url === false),
                 actions = self.initialPreviewShowDelete ? self.renderFileActions(false, true, disabled, url, key) : '',
-                footer = template.replaceAll('{actions}', actions);
-            return footer.replaceAll('{caption}', caption).replaceAll('{width}', width)
-                .replaceAll('{indicator}', '').replaceAll('{indicatorTitle}', '');
+                footer = template.repl('{actions}', actions);
+            return footer.repl('{caption}', caption).repl('{width}', width)
+                .repl('{indicator}', '').repl('{indicatorTitle}', '');
         },
         renderFileFooter: function (caption, width) {
             var self = this, config = self.fileActionSettings, footer,
                 template = self.getLayoutTemplate('footer');
             if (self.isUploadable) {
-                footer = template.replaceAll('{actions}', self.renderFileActions(true, true, false, false, false));
-                return footer.replaceAll('{caption}', caption)
-                    .replaceAll('{width}', width)
-                    .replaceAll('{indicator}', config.indicatorNew)
-                    .replaceAll('{indicatorTitle}', config.indicatorNewTitle);
-            }
-            return template.replaceAll('{actions}', '')
-                .replaceAll('{caption}', caption)
-                .replaceAll('{width}', width)
-                .replaceAll('{indicator}', '')
-                .replaceAll('{indicatorTitle}', '');
+                footer = template.repl('{actions}', self.renderFileActions(true, true, false, false, false));
+                return footer.repl('{caption}', caption)
+                    .repl('{width}', width)
+                    .repl('{indicator}', config.indicatorNew)
+                    .repl('{indicatorTitle}', config.indicatorNewTitle);
+            }
+            return template.repl('{actions}', '')
+                .repl('{caption}', caption)
+                .repl('{width}', width)
+                .repl('{indicator}', '')
+                .repl('{indicatorTitle}', '');
         },
         renderFileActions: function (showUpload, showDelete, disabled, url, key) {
             if (!showUpload && !showDelete) {
@@ -652,47 +649,47 @@
                 btnDelete = self.getLayoutTemplate('actionDelete'),
                 btnUpload = '',
                 template = self.getLayoutTemplate('actions'),
-                otherActionButtons = self.otherActionButtons.replaceAll('{dataKey}', vKey),
+                otherActionButtons = self.otherActionButtons.repl('{dataKey}', vKey),
                 config = self.fileActionSettings,
                 removeClass = disabled ? config.removeClass + ' disabled' : config.removeClass;
             btnDelete = btnDelete
-                .replaceAll('{removeClass}', removeClass)
-                .replaceAll('{removeIcon}', config.removeIcon)
-                .replaceAll('{removeTitle}', config.removeTitle)
-                .replaceAll('{dataUrl}', vUrl)
-                .replaceAll('{dataKey}', vKey);
+                .repl('{removeClass}', removeClass)
+                .repl('{removeIcon}', config.removeIcon)
+                .repl('{removeTitle}', config.removeTitle)
+                .repl('{dataUrl}', vUrl)
+                .repl('{dataKey}', vKey);
             if (showUpload) {
                 btnUpload = self.getLayoutTemplate('actionUpload')
-                    .replaceAll('{uploadClass}', config.uploadClass)
-                    .replaceAll('{uploadIcon}', config.uploadIcon)
-                    .replaceAll('{uploadTitle}', config.uploadTitle);
+                    .repl('{uploadClass}', config.uploadClass)
+                    .repl('{uploadIcon}', config.uploadIcon)
+                    .repl('{uploadTitle}', config.uploadTitle);
             }
             return template
-                .replaceAll('{delete}', btnDelete)
-                .replaceAll('{upload}', btnUpload)
-                .replaceAll('{other}', otherActionButtons);
+                .repl('{delete}', btnDelete)
+                .repl('{upload}', btnUpload)
+                .repl('{other}', otherActionButtons);
         },
         getInitialPreview: function (template, content, i) {
             var self = this, ind = 'init_' + i,
                 previewId = self.previewInitId + '-' + ind,
                 footer = self.renderInitFileFooter(i, false);
             return template
-                .replaceAll('{previewId}', previewId)
-                .replaceAll('{frameClass}', ' file-preview-initial')
-                .replaceAll('{fileindex}', ind)
-                .replaceAll('{content}', content)
-                .replaceAll('{footer}', footer);
+                .repl('{previewId}', previewId)
+                .repl('{frameClass}', ' file-preview-initial')
+                .repl('{fileindex}', ind)
+                .repl('{content}', content)
+                .repl('{footer}', footer);
         },
         initPreview: function () {
             var self = this, html = '', content = self.initialPreview, len = self.initialPreviewCount,
                 cap = self.initialCaption.length, i, fileList,
-                caption = (cap > 0) ? self.initialCaption : self.msgSelected.replaceAll('{n}', len);
+                caption = (cap > 0) ? self.initialCaption : self.msgSelected.repl('{n}', len);
             if (isArray(content) && len > 0) {
                 for (i = 0; i < len; i += 1) {
                     html += self.getInitialPreview(self.previewGenericTemplate, content[i], i);
                 }
                 if (len > 1 && cap === 0) {
-                    caption = self.msgSelected.replaceAll('{n}', len);
+                    caption = self.msgSelected.repl('{n}', len);
                 }
             } else {
                 if (len > 0) {
@@ -701,7 +698,7 @@
                         html += self.getInitialPreview(self.previewGenericTemplate, fileList[i], i);
                     }
                     if (len > 1 && cap === 0) {
-                        caption = self.msgSelected.replaceAll('{n}', len);
+                        caption = self.msgSelected.repl('{n}', len);
                     }
                 } else {
                     if (cap > 0) {
@@ -765,7 +762,7 @@
                                 }
                                 var caption = self.initialCaption;
                                 if (self.initialCaption.length === 0) {
-                                    caption = self.msgSelected.replaceAll('{n}', self.initialPreviewCount);
+                                    caption = self.msgSelected.repl('{n}', self.initialPreviewCount);
                                 }
                                 self.original.preview = $content.html();
                                 self.setCaption(caption);
@@ -843,7 +840,6 @@
                 }
                 self.unlock();
             });
-            self.locked = false;
         },
         clear: function (trig) {
             var self = this, cap;
@@ -983,7 +979,7 @@
         },
         uploadSingle: function (i, files, allFiles) {
             var self = this, total = self.getFileStack().length, formdata = new FormData(), outData,
-                previewId = self.previewInitId + "-" + i, $thumb = $('#' + previewId), cap, pct,
+                previewId = self.previewInitId + "-" + i, $thumb = $('#' + previewId), cap, pct, chkComplete,
                 $btnUpload = $thumb.find('.kv-file-upload'), $btnDelete = $thumb.find('.kv-file-remove'),
                 $indicator = $thumb.find('.file-upload-indicator'), config = self.fileActionSettings,
                 hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData),
@@ -992,7 +988,16 @@
             if (total === 0 || !hasPostData || $btnUpload.hasClass('disabled')) {
                 return;
             }
-            allFiles = allFiles || false;
+            chkComplete = function () {
+                var $thumbs = self.$preview.find('.file-preview-frame.file-uploading'), chk = $thumbs.length;
+                if (chk > 0) {
+                    return;
+                }
+                self.setProgress(100);
+                self.unlock();
+                self.clearFileInput();
+                self.raise('filebatchuploadcomplete', [self.filestack, self.getExtraData()]);
+            };
             setIndicator = function (icon, msg) {
                 $indicator.html(config[icon]);
                 $indicator.attr('title', config[msg]);
@@ -1031,6 +1036,9 @@
                         $btnUpload.hide();
                         $btnDelete.hide();
                         self.filestack[i] = undefined;
+                        if (!allFiles) {
+                            self.resetFileStack();
+                        }
                         self.raise('fileuploaded', [outData, previewId, i]);
                     } else {
                         setIndicator('indicatorError', 'indicatorErrorTitle');
@@ -1042,10 +1050,12 @@
                 setTimeout(function () {
                     updateProgress();
                     resetActions();
+                    if (!allFiles) {
+                        self.unlock(false);
+                    } else {
+                        chkComplete();
+                    }
                 }, 100);
-                if (!allFiles) {
-                    self.unlock();
-                }
             };
             fnError = function (jqXHR, textStatus, errorThrown) {
                 setIndicator('indicatorError', 'indicatorErrorTitle');
@@ -1218,19 +1228,19 @@
             var self = this, err = evt.target.error;
             switch (err.code) {
                 case err.NOT_FOUND_ERR:
-                    self.addError(self.msgFileNotFound.replaceAll('{name}', caption));
+                    self.addError(self.msgFileNotFound.repl('{name}', caption));
                     break;
                 case err.SECURITY_ERR:
-                    self.addError(self.msgFileSecured.replaceAll('{name}', caption));
+                    self.addError(self.msgFileSecured.repl('{name}', caption));
                     break;
                 case err.NOT_READABLE_ERR:
-                    self.addError(self.msgFileNotReadable.replaceAll('{name}', caption));
+                    self.addError(self.msgFileNotReadable.repl('{name}', caption));
                     break;
                 case err.ABORT_ERR:
-                    self.addError(self.msgFilePreviewAborted.replaceAll('{name}', caption));
+                    self.addError(self.msgFilePreviewAborted.repl('{name}', caption));
                     break;
                 default:
-                    self.addError(self.msgFilePreviewError.replaceAll('{name}', caption));
+                    self.addError(self.msgFilePreviewError.repl('{name}', caption));
             }
         },
         parseFileType: function (file) {
@@ -1260,15 +1270,15 @@
                 footer += '<div class="file-other-error text-danger"><i class="glyphicon glyphicon-exclamation-sign"></i></div>';
             }
             self.$preview.append("\n" + previewOtherTemplate
-                .replaceAll('{previewId}', previewId)
-                .replaceAll('{frameClass}', frameClass)
-                .replaceAll('{fileindex}', ind)
-                .replaceAll('{caption}', self.slug(file.name))
-                .replaceAll('{width}', config.width)
-                .replaceAll('{height}', config.height)
-                .replaceAll('{type}', file.type)
-                .replaceAll('{data}', data)
-                .replaceAll('{footer}', footer));
+                .repl('{previewId}', previewId)
+                .repl('{frameClass}', frameClass)
+                .repl('{fileindex}', ind)
+                .repl('{caption}', self.slug(file.name))
+                .repl('{width}', config.width)
+                .repl('{height}', config.height)
+                .repl('{type}', file.type)
+                .repl('{data}', data)
+                .repl('{footer}', footer));
             $obj.on('load', function () {
                 objUrl.revokeObjectURL($obj.attr('data'));
             });
@@ -1293,26 +1303,26 @@
                     if (strText.length > wrapLen) {
                         id = 'text-' + uniqId();
                         height = window.innerHeight * 0.75;
-                        modal = self.getLayoutTemplate('modal').replaceAll('{id}', id)
-                            .replaceAll('{title}', caption)
-                            .replaceAll('{height}', height)
-                            .replaceAll('{body}', strText);
+                        modal = self.getLayoutTemplate('modal').repl('{id}', id)
+                            .repl('{title}', caption)
+                            .repl('{height}', height)
+                            .repl('{body}', strText);
                         wrapInd = wrapInd
-                            .replaceAll('{title}', caption)
-                            .replaceAll('{dialog}', "$('#" + id + "').modal('show')");
+                            .repl('{title}', caption)
+                            .repl('{dialog}', "$('#" + id + "').modal('show')");
                         strText = strText.substring(0, (wrapLen - 1)) + wrapInd;
                     }
-                    content = tmplt.replaceAll('{previewId}', previewId).replaceAll('{caption}', caption)
-                        .replaceAll('{frameClass}', '')
-                        .replaceAll('{type}', file.type).replaceAll('{width}', config.width)
-                        .replaceAll('{height}', config.height).replaceAll('{data}', strText)
-                        .replaceAll('{footer}', footer).replaceAll('{fileindex}', ind) + modal;
+                    content = tmplt.repl('{previewId}', previewId).repl('{caption}', caption)
+                        .repl('{frameClass}', '')
+                        .repl('{type}', file.type).repl('{width}', config.width)
+                        .repl('{height}', config.height).repl('{data}', strText)
+                        .repl('{footer}', footer).repl('{fileindex}', ind) + modal;
                 } else {
-                    content = tmplt.replaceAll('{previewId}', previewId).replaceAll('{caption}', caption)
-                        .replaceAll('{frameClass}', '')
-                        .replaceAll('{type}', file.type).replaceAll('{data}', data)
-                        .replaceAll('{width}', config.width).replaceAll('{height}', config.height)
-                        .replaceAll('{footer}', footer).replaceAll('{fileindex}', ind);
+                    content = tmplt.repl('{previewId}', previewId).repl('{caption}', caption)
+                        .repl('{frameClass}', '')
+                        .repl('{type}', file.type).repl('{data}', data)
+                        .repl('{width}', config.width).repl('{height}', config.height)
+                        .repl('{footer}', footer).repl('{fileindex}', ind);
                 }
                 self.$preview.append("\n" + content);
                 self.autoSizeImage(previewId);
@@ -1362,9 +1372,9 @@
                 }
                 fileSize = fileSize.toFixed(2);
                 if (self.maxFileSize > 0 && fileSize > self.maxFileSize) {
-                    msg = self.msgSizeTooLarge.replaceAll('{name}', caption)
-                        .replaceAll('{size}', fileSize)
-                        .replaceAll('{maxSize}', self.maxFileSize);
+                    msg = self.msgSizeTooLarge.repl('{name}', caption)
+                        .repl('{size}', fileSize)
+                        .repl('{maxSize}', self.maxFileSize);
                     self.isError = throwError(msg, file, previewId, i);
                     return;
                 }
@@ -1376,7 +1386,7 @@
                         fileCount += isEmpty(chk) ? 0 : chk.length;
                     }
                     if (fileCount === 0) {
-                        msg = self.msgInvalidFileType.replaceAll('{name}', caption).replaceAll('{types}', strTypes);
+                        msg = self.msgInvalidFileType.repl('{name}', caption).repl('{types}', strTypes);
                         self.isError = throwError(msg, file, previewId, i);
                         return;
                     }
@@ -1385,7 +1395,7 @@
                     chk = caption.match(fileExtExpr);
                     fileCount += isEmpty(chk) ? 0 : chk.length;
                     if (fileCount === 0) {
-                        msg = self.msgInvalidFileExtension.replaceAll('{name}', caption).replaceAll('{extensions}',
+                        msg = self.msgInvalidFileExtension.repl('{name}', caption).repl('{extensions}',
                             strExt);
                         self.isError = throwError(msg, file, previewId, i);
                         return;
@@ -1398,7 +1408,7 @@
                     return;
                 }
                 if ($preview.length > 0 && FileReader !== undefined) {
-                    $status.html(msgLoading.replaceAll('{index}', i + 1).replaceAll('{files}', numFiles));
+                    $status.html(msgLoading.repl('{index}', i + 1).repl('{files}', numFiles));
                     $container.addClass('loading');
                     reader.onerror = function (evt) {
                         self.errorHandler(evt, caption);
@@ -1409,8 +1419,8 @@
                     };
                     reader.onloadend = function () {
                         msg = msgProgress
-                            .replaceAll('{index}', i + 1).replaceAll('{files}', numFiles)
-                            .replaceAll('{percent}', 50).replaceAll('{name}', caption);
+                            .repl('{index}', i + 1).repl('{files}', numFiles)
+                            .repl('{percent}', 50).repl('{name}', caption);
                         setTimeout(function () {
                             $status.html(msg);
                             objUrl.revokeObjectURL(previewData);
@@ -1424,8 +1434,8 @@
                     reader.onprogress = function (data) {
                         if (data.lengthComputable) {
                             var fact = (data.loaded / data.total) * 100, progress = Math.ceil(fact);
-                            msg = msgProgress.replaceAll('{index}', i + 1).replaceAll('{files}', numFiles)
-                                .replaceAll('{percent}', progress).replaceAll('{name}', caption);
+                            msg = msgProgress.repl('{index}', i + 1).repl('{files}', numFiles)
+                                .repl('{percent}', progress).repl('{name}', caption);
                             setTimeout(function () {
                                 $status.html(msg);
                             }, 100);
@@ -1456,7 +1466,7 @@
                 name = $el.val() || (fileStack.length && fileStack[0].name) || '', label = self.slug(name),
                 n = self.isUploadable ? fileStack.length : numFiles,
                 nFiles = self.initialPreviewCount + n,
-                log = n > 1 ? msgSelected.replaceAll('{n}', nFiles) : label;
+                log = n > 1 ? msgSelected.repl('{n}', nFiles) : label;
             if (self.isError) {
                 self.$previewContainer.removeClass('loading');
                 self.$previewStatus.html('');
@@ -1516,7 +1526,7 @@
             }
             total = self.isUploadable ? self.getFileStack().length + tfiles.length : tfiles.length;
             if (self.maxFileCount > 0 && total > self.maxFileCount) {
-                msg = self.msgFilesTooMany.replaceAll('{m}', self.maxFileCount).replaceAll('{n}', total);
+                msg = self.msgFilesTooMany.repl('{m}', self.maxFileCount).repl('{n}', total);
                 self.isError = throwError(msg, null, null, null);
                 self.$captionContainer.find('.kv-caption-icon').hide();
                 self.$caption.html(self.msgValidationError);
@@ -1592,17 +1602,17 @@
         },
         renderMain: function () {
             var self = this, dropCss = (self.isUploadable && self.dropZoneEnabled) ? ' file-drop-zone' : '',
-                preview = self.showPreview ? self.getLayoutTemplate('preview').replaceAll('{class}', self.previewClass)
-                    .replaceAll('{dropClass}', dropCss) : '',
+                preview = self.showPreview ? self.getLayoutTemplate('preview').repl('{class}', self.previewClass)
+                    .repl('{dropClass}', dropCss) : '',
                 css = self.isDisabled ? self.captionClass + ' file-caption-disabled' : self.captionClass,
-                caption = self.captionTemplate.replaceAll('{class}', css + ' kv-fileinput-caption');
-            return self.mainTemplate.replaceAll('{class}', self.mainClass)
-                .replaceAll('{preview}', preview)
-                .replaceAll('{caption}', caption)
-                .replaceAll('{upload}', self.renderUpload())
-                .replaceAll('{remove}', self.renderRemove())
-                .replaceAll('{cancel}', self.renderCancel())
-                .replaceAll('{browse}', self.renderBrowse());
+                caption = self.captionTemplate.repl('{class}', css + ' kv-fileinput-caption');
+            return self.mainTemplate.repl('{class}', self.mainClass)
+                .repl('{preview}', preview)
+                .repl('{caption}', caption)
+                .repl('{upload}', self.renderUpload())
+                .repl('{remove}', self.renderRemove())
+                .repl('{cancel}', self.renderCancel())
+                .repl('{browse}', self.renderBrowse());
         },
         renderBrowse: function () {
             var self = this, css = self.browseClass + ' btn-file', status = '';
@@ -1645,6 +1655,7 @@
         }
     };
 
+    //FileInput plugin definition
     $.fn.fileinput = function (option) {
         if (!hasFileAPISupport() && !isIE(9)) {
             return;
@@ -1729,6 +1740,8 @@
         msgLoading: 'Loading  file {index} of {files} &hellip;',
         msgProgress: 'Loading file {index} of {files} - {name} - {percent}% completed.',
         msgSelected: '{n} files selected',
+        progressClass: "progress-bar progress-bar-success progress-bar-striped active",
+        progressCompleteClass: "progress-bar progress-bar-success",
         previewFileType: 'image',
         wrapTextLength: 250,
         wrapIndicator: ' <span class="wrap-indicator" title="{title}" onclick="{dialog}">[&hellip;]</span>',

File diff suppressed because it is too large
+ 0 - 0
js/fileinput.min.js


Some files were not shown because too many files changed in this diff