RuoYi 6 роки тому
батько
коміт
ec71a50a5e

+ 0 - 4463
src/main/resources/static/js/plugins/fileinput/fileinput.js

@@ -1,4463 +0,0 @@
-/*!
- * bootstrap-fileinput v4.4.9
- * http://plugins.krajee.com/file-input
- *
- * Author: Kartik Visweswaran
- * Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com
- *
- * Licensed under the BSD 3-Clause
- * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
- */
-(function (factory) {
-    "use strict";
-    //noinspection JSUnresolvedVariable
-    if (typeof define === 'function' && define.amd) { // jshint ignore:line
-        // AMD. Register as an anonymous module.
-        define(['jquery'], factory); // jshint ignore:line
-    } else { // noinspection JSUnresolvedVariable
-        if (typeof module === 'object' && module.exports) { // jshint ignore:line
-            // Node/CommonJS
-            // noinspection JSUnresolvedVariable
-            module.exports = factory(require('jquery')); // jshint ignore:line
-        } else {
-            // Browser globals
-            factory(window.jQuery);
-        }
-    }
-}(function ($) {
-    "use strict";
-
-    $.fn.fileinputLocales = {};
-    $.fn.fileinputThemes = {};
-
-    String.prototype.setTokens = function (replacePairs) {
-        var str = this.toString(), key, re;
-        for (key in replacePairs) {
-            if (replacePairs.hasOwnProperty(key)) {
-                re = new RegExp("\{" + key + "\}", "g");
-                str = str.replace(re, replacePairs[key]);
-            }
-        }
-        return str;
-    };
-
-    var $h, FileInput;
-
-    // fileinput helper object for all global variables and internal helper methods
-    //noinspection JSUnresolvedVariable
-    $h = {
-        FRAMES: '.kv-preview-thumb',
-        SORT_CSS: 'file-sortable',
-        OBJECT_PARAMS: '<param name="controller" value="true" />\n' +
-        '<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="quality" value="high" />\n',
-        DEFAULT_PREVIEW: '<div class="file-preview-other">\n' +
-        '<span class="{previewFileIconClass}">{previewFileIcon}</span>\n' +
-        '</div>',
-        MODAL_ID: 'kvFileinputModal',
-        MODAL_EVENTS: ['show', 'shown', 'hide', 'hidden', 'loaded'],
-        objUrl: window.URL || window.webkitURL,
-        compare: function (input, str, exact) {
-            return input !== undefined && (exact ? input === str : input.match(str));
-        },
-        isIE: function (ver) {
-            // check for IE versions < 11
-            if (navigator.appName !== 'Microsoft Internet Explorer') {
-                return false;
-            }
-            if (ver === 10) {
-                return new RegExp('msie\\s' + ver, 'i').test(navigator.userAgent);
-            }
-            var div = document.createElement("div"), status;
-            div.innerHTML = "<!--[if IE " + ver + "]> <i></i> <![endif]-->";
-            status = div.getElementsByTagName("i").length;
-            document.body.appendChild(div);
-            div.parentNode.removeChild(div);
-            return status;
-        },
-        canAssignFilesToInput: function () {
-            var input = document.createElement('input');
-            try {
-                input.type = "file";
-                input.files = null;
-                return true;
-            } catch (err) {
-                return false;
-            }
-        },
-        getDragDropFolders: function (items) {
-            var i, item, len = items.length, folders = 0;
-            if (len > 0 && items[0].webkitGetAsEntry()) {
-                for (i = 0; i < len; i++) {
-                    item = items[i].webkitGetAsEntry();
-                    if (item && item.isDirectory) {
-                        folders++;
-                    }
-                }
-            }
-            return folders;
-        },
-        initModal: function ($modal) {
-            var $body = $('body');
-            if ($body.length) {
-                $modal.appendTo($body);
-            }
-        },
-        isEmpty: function (value, trim) {
-            return value === undefined || value === null || value.length === 0 || (trim && $.trim(value) === '');
-        },
-        isArray: function (a) {
-            return Array.isArray(a) || Object.prototype.toString.call(a) === '[object Array]';
-        },
-        ifSet: function (needle, haystack, def) {
-            def = def || '';
-            return (haystack && typeof haystack === 'object' && needle in haystack) ? haystack[needle] : def;
-        },
-        cleanArray: function (arr) {
-            if (!(arr instanceof Array)) {
-                arr = [];
-            }
-            return arr.filter(function (e) {
-                return (e !== undefined && e !== null);
-            });
-        },
-        spliceArray: function (arr, index, reverseOrder) {
-            var i, j = 0, out = [], newArr;
-            if (!(arr instanceof Array)) {
-                return [];
-            }
-            newArr = $.extend(true, [], arr);
-            if (reverseOrder) {
-                newArr.reverse();
-            }
-            for (i = 0; i < newArr.length; i++) {
-                if (i !== index) {
-                    out[j] = newArr[i];
-                    j++;
-                }
-            }
-            if (reverseOrder) {
-                out.reverse();
-            }
-            return out;
-        },
-        getNum: function (num, def) {
-            def = def || 0;
-            if (typeof num === "number") {
-                return num;
-            }
-            if (typeof num === "string") {
-                num = parseFloat(num);
-            }
-            return isNaN(num) ? def : num;
-        },
-        hasFileAPISupport: function () {
-            return !!(window.File && window.FileReader);
-        },
-        hasDragDropSupport: function () {
-            var div = document.createElement('div');
-            /** @namespace div.draggable */
-            /** @namespace div.ondragstart */
-            /** @namespace div.ondrop */
-            return !$h.isIE(9) &&
-                (div.draggable !== undefined || (div.ondragstart !== undefined && div.ondrop !== undefined));
-        },
-        hasFileUploadSupport: function () {
-            return $h.hasFileAPISupport() && window.FormData;
-        },
-        hasBlobSupport: function () {
-            try {
-                return !!window.Blob && Boolean(new Blob());
-            } catch (e) {
-                return false;
-            }
-        },
-        hasArrayBufferViewSupport: function () {
-            try {
-                return new Blob([new Uint8Array(100)]).size === 100;
-            } catch (e) {
-                return false;
-            }
-        },
-        dataURI2Blob: function (dataURI) {
-            //noinspection JSUnresolvedVariable
-            var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder ||
-                window.MSBlobBuilder, canBlob = $h.hasBlobSupport(), byteStr, arrayBuffer, intArray, i, mimeStr, bb,
-                canProceed = (canBlob || BlobBuilder) && window.atob && window.ArrayBuffer && window.Uint8Array;
-            if (!canProceed) {
-                return null;
-            }
-            if (dataURI.split(',')[0].indexOf('base64') >= 0) {
-                byteStr = atob(dataURI.split(',')[1]);
-            } else {
-                byteStr = decodeURIComponent(dataURI.split(',')[1]);
-            }
-            arrayBuffer = new ArrayBuffer(byteStr.length);
-            intArray = new Uint8Array(arrayBuffer);
-            for (i = 0; i < byteStr.length; i += 1) {
-                intArray[i] = byteStr.charCodeAt(i);
-            }
-            mimeStr = dataURI.split(',')[0].split(':')[1].split(';')[0];
-            if (canBlob) {
-                return new Blob([$h.hasArrayBufferViewSupport() ? intArray : arrayBuffer], {type: mimeStr});
-            }
-            bb = new BlobBuilder();
-            bb.append(arrayBuffer);
-            return bb.getBlob(mimeStr);
-        },
-        arrayBuffer2String: function (buffer) {
-            //noinspection JSUnresolvedVariable
-            if (window.TextDecoder) {
-                // noinspection JSUnresolvedFunction
-                return new TextDecoder("utf-8").decode(buffer);
-            }
-            var array = Array.prototype.slice.apply(new Uint8Array(buffer)), out = '', i = 0, len, c, char2, char3;
-            len = array.length;
-            while (i < len) {
-                c = array[i++];
-                switch (c >> 4) { // jshint ignore:line
-                    case 0:
-                    case 1:
-                    case 2:
-                    case 3:
-                    case 4:
-                    case 5:
-                    case 6:
-                    case 7:
-                        // 0xxxxxxx
-                        out += String.fromCharCode(c);
-                        break;
-                    case 12:
-                    case 13:
-                        // 110x xxxx   10xx xxxx
-                        char2 = array[i++];
-                        out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); // jshint ignore:line
-                        break;
-                    case 14:
-                        // 1110 xxxx  10xx xxxx  10xx xxxx
-                        char2 = array[i++];
-                        char3 = array[i++];
-                        out += String.fromCharCode(((c & 0x0F) << 12) | // jshint ignore:line
-                            ((char2 & 0x3F) << 6) |  // jshint ignore:line
-                            ((char3 & 0x3F) << 0)); // jshint ignore:line
-                        break;
-                }
-            }
-            return out;
-        },
-        isHtml: function (str) {
-            var a = document.createElement('div');
-            a.innerHTML = str;
-            for (var c = a.childNodes, i = c.length; i--;) {
-                if (c[i].nodeType === 1) {
-                    return true;
-                }
-            }
-            return false;
-        },
-        isSvg: function (str) {
-            return str.match(/^\s*<\?xml/i) && (str.match(/<!DOCTYPE svg/i) || str.match(/<svg/i));
-        },
-        getMimeType: function (signature, contents, type) {
-            switch (signature) {
-                case "ffd8ffe0":
-                case "ffd8ffe1":
-                case "ffd8ffe2":
-                    return 'image/jpeg';
-                case '89504E47':
-                    return 'image/png';
-                case '47494638':
-                    return 'image/gif';
-                case '49492a00':
-                    return 'image/tiff';
-                case '52494646':
-                    return 'image/webp';
-                case '66747970':
-                    return 'video/3gp';
-                case '4f676753':
-                    return 'video/ogg';
-                case '1a45dfa3':
-                    return 'video/mkv';
-                case '000001ba':
-                case '000001b3':
-                    return 'video/mpeg';
-                case '3026b275':
-                    return 'video/wmv';
-                case '25504446':
-                    return 'application/pdf';
-                case '25215053':
-                    return 'application/ps';
-                case '504b0304':
-                case '504b0506':
-                case '504b0508':
-                    return 'application/zip';
-                case '377abcaf':
-                    return 'application/7z';
-                case '75737461':
-                    return 'application/tar';
-                case '7801730d':
-                    return 'application/dmg';
-                default:
-                    switch (signature.substring(0, 6)) {
-                        case '435753':
-                            return 'application/x-shockwave-flash';
-                        case '494433':
-                            return 'audio/mp3';
-                        case '425a68':
-                            return 'application/bzip';
-                        default:
-                            switch (signature.substring(0, 4)) {
-                                case '424d':
-                                    return 'image/bmp';
-                                case 'fffb':
-                                    return 'audio/mp3';
-                                case '4d5a':
-                                    return 'application/exe';
-                                case '1f9d':
-                                case '1fa0':
-                                    return 'application/zip';
-                                case '1f8b':
-                                    return 'application/gzip';
-                                default:
-                                    return contents && !contents.match(/[^\u0000-\u007f]/) ? 'application/text-plain' : type;
-                            }
-                    }
-            }
-        },
-        addCss: function ($el, css) {
-            $el.removeClass(css).addClass(css);
-        },
-        getElement: function (options, param, value) {
-            return ($h.isEmpty(options) || $h.isEmpty(options[param])) ? value : $(options[param]);
-        },
-        uniqId: function () {
-            return Math.round(new Date().getTime()) + '_' + Math.round(Math.random() * 100);
-        },
-        htmlEncode: function (str) {
-            return str.replace(/&/g, '&amp;')
-                .replace(/</g, '&lt;')
-                .replace(/>/g, '&gt;')
-                .replace(/"/g, '&quot;')
-                .replace(/'/g, '&apos;');
-        },
-        replaceTags: function (str, tags) {
-            var out = str;
-            if (!tags) {
-                return out;
-            }
-            $.each(tags, function (key, value) {
-                if (typeof value === "function") {
-                    value = value();
-                }
-                out = out.split(key).join(value);
-            });
-            return out;
-        },
-        cleanMemory: function ($thumb) {
-            var data = $thumb.is('img') ? $thumb.attr('src') : $thumb.find('source').attr('src');
-            /** @namespace $h.objUrl.revokeObjectURL */
-            $h.objUrl.revokeObjectURL(data);
-        },
-        findFileName: function (filePath) {
-            var sepIndex = filePath.lastIndexOf('/');
-            if (sepIndex === -1) {
-                sepIndex = filePath.lastIndexOf('\\');
-            }
-            return filePath.split(filePath.substring(sepIndex, sepIndex + 1)).pop();
-        },
-        checkFullScreen: function () {
-            //noinspection JSUnresolvedVariable
-            return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement ||
-                document.msFullscreenElement;
-        },
-        toggleFullScreen: function (maximize) {
-            var doc = document, de = doc.documentElement;
-            if (de && maximize && !$h.checkFullScreen()) {
-                /** @namespace document.requestFullscreen */
-                /** @namespace document.msRequestFullscreen */
-                /** @namespace document.mozRequestFullScreen */
-                /** @namespace document.webkitRequestFullscreen */
-                /** @namespace Element.ALLOW_KEYBOARD_INPUT */
-                if (de.requestFullscreen) {
-                    de.requestFullscreen();
-                } else if (de.msRequestFullscreen) {
-                    de.msRequestFullscreen();
-                } else if (de.mozRequestFullScreen) {
-                    de.mozRequestFullScreen();
-                } else if (de.webkitRequestFullscreen) {
-                    de.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
-                }
-            } else {
-                /** @namespace document.exitFullscreen */
-                /** @namespace document.msExitFullscreen */
-                /** @namespace document.mozCancelFullScreen */
-                /** @namespace document.webkitExitFullscreen */
-                if (doc.exitFullscreen) {
-                    doc.exitFullscreen();
-                } else if (doc.msExitFullscreen) {
-                    doc.msExitFullscreen();
-                } else if (doc.mozCancelFullScreen) {
-                    doc.mozCancelFullScreen();
-                } else if (doc.webkitExitFullscreen) {
-                    doc.webkitExitFullscreen();
-                }
-            }
-        },
-        moveArray: function (arr, oldIndex, newIndex, reverseOrder) {
-            var newArr = $.extend(true, [], arr);
-            if (reverseOrder) {
-                newArr.reverse();
-            }
-            if (newIndex >= newArr.length) {
-                var k = newIndex - newArr.length;
-                while ((k--) + 1) {
-                    newArr.push(undefined);
-                }
-            }
-            newArr.splice(newIndex, 0, newArr.splice(oldIndex, 1)[0]);
-            if (reverseOrder) {
-                newArr.reverse();
-            }
-            return newArr;
-        },
-        cleanZoomCache: function ($el) {
-            var $cache = $el.closest('.kv-zoom-cache-theme');
-            if (!$cache.length) {
-                $cache = $el.closest('.kv-zoom-cache');
-            }
-            $cache.remove();
-        },
-        setOrientation: function (buffer, callback) {
-            var scanner = new DataView(buffer), idx = 0, value = 1, // Non-rotated is the default
-                maxBytes, uInt16, exifLength;
-            if (scanner.getUint16(idx) !== 0xFFD8 || buffer.length < 2) { // not a proper JPEG
-                if (callback) {
-                    callback();
-                }
-                return;
-            }
-            idx += 2;
-            maxBytes = scanner.byteLength;
-            while (idx < maxBytes - 2) {
-                uInt16 = scanner.getUint16(idx);
-                idx += 2;
-                switch (uInt16) {
-                    case 0xFFE1: // Start of EXIF
-                        exifLength = scanner.getUint16(idx);
-                        maxBytes = exifLength - idx;
-                        idx += 2;
-                        break;
-                    case 0x0112: // Orientation tag
-                        value = scanner.getUint16(idx + 6, false);
-                        maxBytes = 0; // Stop scanning
-                        break;
-                }
-            }
-            if (callback) {
-                callback(value);
-            }
-        },
-        validateOrientation: function (file, callback) {
-            if (!window.FileReader || !window.DataView) {
-                return; // skip orientation if pre-requisite libraries not supported by browser
-            }
-            var reader = new FileReader(), buffer;
-            reader.onloadend = function () {
-                buffer = reader.result;
-                $h.setOrientation(buffer, callback);
-            };
-            reader.readAsArrayBuffer(file);
-        },
-        adjustOrientedImage: function ($img, isZoom) {
-            var offsetContTop, offsetTop, newTop;
-            if (!$img.hasClass('is-portrait-gt4')) {
-                return;
-            }
-            if (isZoom) {
-                $img.css({width: $img.parent().height()});
-                return;
-            } else {
-                $img.css({height: 'auto', width: $img.height()});
-            }
-            offsetContTop = $img.parent().offset().top;
-            offsetTop = $img.offset().top;
-            newTop = offsetContTop - offsetTop;
-            $img.css('margin-top', newTop);
-        },
-        closeButton: function (css) {
-            css = css ? 'close ' + css : 'close';
-            return '<button type="button" class="' + css + '" aria-label="Close">\n' +
-                '  <span aria-hidden="true">&times;</span>\n' +
-                '</button>';
-        }
-    };
-    FileInput = function (element, options) {
-        var self = this;
-        self.$element = $(element);
-        self.$parent = self.$element.parent();
-        if (!self._validate()) {
-            return;
-        }
-        self.isPreviewable = $h.hasFileAPISupport();
-        self.isIE9 = $h.isIE(9);
-        self.isIE10 = $h.isIE(10);
-        if (self.isPreviewable || self.isIE9) {
-            self._init(options);
-            self._listen();
-        }
-        self.$element.removeClass('file-loading');
-    };
-    //noinspection JSUnusedGlobalSymbols
-    FileInput.prototype = {
-        constructor: FileInput,
-        _cleanup: function () {
-            var self = this;
-            self.reader = null;
-            self.formdata = {};
-            self.uploadCount = 0;
-            self.uploadStatus = {};
-            self.uploadLog = [];
-            self.uploadAsyncCount = 0;
-            self.loadedImages = [];
-            self.totalImagesCount = 0;
-            self.ajaxRequests = [];
-            self.clearStack();
-            self.fileBatchCompleted = true;
-            if (!self.isPreviewable) {
-                self.showPreview = false;
-            }
-            self.isError = false;
-            self.ajaxAborted = false;
-            self.cancelling = false;
-        },
-        _init: function (options, refreshMode) {
-            var self = this, f, $el = self.$element, $cont, t, tmp;
-            self.options = options;
-            $.each(options, function (key, value) {
-                switch (key) {
-                    case 'minFileCount':
-                    case 'maxFileCount':
-                    case 'minFileSize':
-                    case 'maxFileSize':
-                    case 'maxFilePreviewSize':
-                    case 'resizeImageQuality':
-                    case 'resizeIfSizeMoreThan':
-                    case 'progressUploadThreshold':
-                    case 'initialPreviewCount':
-                    case 'zoomModalHeight':
-                    case 'minImageHeight':
-                    case 'maxImageHeight':
-                    case 'minImageWidth':
-                    case 'maxImageWidth':
-                        self[key] = $h.getNum(value);
-                        break;
-                    default:
-                        self[key] = value;
-                        break;
-                }
-            });
-            if (self.rtl) { // swap buttons for rtl
-                tmp = self.previewZoomButtonIcons.prev;
-                self.previewZoomButtonIcons.prev = self.previewZoomButtonIcons.next;
-                self.previewZoomButtonIcons.next = tmp;
-            }
-            if (!refreshMode) {
-                self._cleanup();
-            }
-            self.$form = $el.closest('form');
-            self._initTemplateDefaults();
-            self.uploadFileAttr = !$h.isEmpty($el.attr('name')) ? $el.attr('name') : 'file_data';
-            t = self._getLayoutTemplate('progress');
-            self.progressTemplate = t.replace('{class}', self.progressClass);
-            self.progressCompleteTemplate = t.replace('{class}', self.progressCompleteClass);
-            self.progressErrorTemplate = t.replace('{class}', self.progressErrorClass);
-            self.isDisabled = $el.attr('disabled') || $el.attr('readonly');
-            if (self.isDisabled) {
-                $el.attr('disabled', true);
-            }
-            self.isAjaxUpload = $h.hasFileUploadSupport() && !$h.isEmpty(self.uploadUrl);
-            self.dropZoneEnabled = $h.hasDragDropSupport() && self.dropZoneEnabled;
-            if (!self.isAjaxUpload) {
-                self.dropZoneEnabled = self.dropZoneEnabled && $h.canAssignFilesToInput();
-            }
-            self.isClickable = self.browseOnZoneClick && self.showPreview &&
-                (self.dropZoneEnabled || !$h.isEmpty(self.defaultPreviewContent));
-            self.slug = typeof options.slugCallback === "function" ? options.slugCallback : self._slugDefault;
-            self.mainTemplate = self.showCaption ? self._getLayoutTemplate('main1') : self._getLayoutTemplate('main2');
-            self.captionTemplate = self._getLayoutTemplate('caption');
-            self.previewGenericTemplate = self._getPreviewTemplate('generic');
-            if (!self.imageCanvas && self.resizeImage && (self.maxImageWidth || self.maxImageHeight)) {
-                self.imageCanvas = document.createElement('canvas');
-                self.imageCanvasContext = self.imageCanvas.getContext('2d');
-            }
-            if ($h.isEmpty($el.attr('id'))) {
-                $el.attr('id', $h.uniqId());
-            }
-            self.namespace = '.fileinput_' + $el.attr('id').replace(/-/g, '_');
-            if (self.$container === undefined) {
-                self.$container = self._createContainer();
-            } else {
-                self._refreshContainer();
-            }
-            $cont = self.$container;
-            self.$dropZone = $cont.find('.file-drop-zone');
-            self.$progress = $cont.find('.kv-upload-progress');
-            self.$btnUpload = $cont.find('.fileinput-upload');
-            self.$captionContainer = $h.getElement(options, 'elCaptionContainer', $cont.find('.file-caption'));
-            self.$caption = $h.getElement(options, 'elCaptionText', $cont.find('.file-caption-name'));
-            if (!$h.isEmpty(self.msgPlaceholder)) {
-                f = $el.attr('multiple') ? self.filePlural : self.fileSingle;
-                self.$caption.attr('placeholder', self.msgPlaceholder.replace('{files}', f));
-            }
-            self.$captionIcon = self.$captionContainer.find('.file-caption-icon');
-            self.$previewContainer = $h.getElement(options, 'elPreviewContainer', $cont.find('.file-preview'));
-            self.$preview = $h.getElement(options, 'elPreviewImage', $cont.find('.file-preview-thumbnails'));
-            self.$previewStatus = $h.getElement(options, 'elPreviewStatus', $cont.find('.file-preview-status'));
-            self.$errorContainer = $h.getElement(options, 'elErrorContainer', self.$previewContainer.find('.kv-fileinput-error'));
-            self._validateDisabled();
-            if (!$h.isEmpty(self.msgErrorClass)) {
-                $h.addCss(self.$errorContainer, self.msgErrorClass);
-            }
-            if (!refreshMode) {
-                self.$errorContainer.hide();
-                self.previewInitId = "preview-" + $h.uniqId();
-                self._initPreviewCache();
-                self._initPreview(true);
-                self._initPreviewActions();
-                if (self.$parent.hasClass('file-loading')) {
-                    self.$container.insertBefore(self.$parent);
-                    self.$parent.remove();
-                }
-            } else {
-                if (!self._errorsExist()) {
-                    self.$errorContainer.hide();
-                }
-            }
-            self._setFileDropZoneTitle();
-            if ($el.attr('disabled')) {
-                self.disable();
-            }
-            self._initZoom();
-            if (self.hideThumbnailContent) {
-                $h.addCss(self.$preview, 'hide-content');
-            }
-        },
-        _initTemplateDefaults: function () {
-            var self = this, tMain1, tMain2, tPreview, tFileIcon, tClose, tCaption, tBtnDefault, tBtnLink, tBtnBrowse,
-                tModalMain, tModal, tProgress, tSize, tFooter, tActions, tActionDelete, tActionUpload, tActionDownload,
-                tActionZoom, tActionDrag, tIndicator, tTagBef, tTagBef1, tTagBef2, tTagAft, tGeneric, tHtml, tImage,
-                tText, tOffice, tGdocs, tVideo, tAudio, tFlash, tObject, tPdf, tOther, tStyle, tZoomCache, vDefaultDim;
-            tMain1 = '{preview}\n' +
-                '<div class="kv-upload-progress kv-hidden"></div><div class="clearfix"></div>\n' +
-                '<div class="input-group {class}">\n' +
-                '  {caption}\n' +
-                '<div class="input-group-btn input-group-append">\n' +
-                '      {remove}\n' +
-                '      {cancel}\n' +
-                '      {upload}\n' +
-                '      {browse}\n' +
-                '    </div>\n' +
-                '</div>';
-            tMain2 = '{preview}\n<div class="kv-upload-progress kv-hidden"></div>\n<div class="clearfix"></div>\n{remove}\n{cancel}\n{upload}\n{browse}\n';
-            tPreview = '<div class="file-preview {class}">\n' +
-                '    {close}' +
-                '    <div class="{dropClass}">\n' +
-                '    <div class="file-preview-thumbnails">\n' +
-                '    </div>\n' +
-                '    <div class="clearfix"></div>' +
-                '    <div class="file-preview-status text-center text-success"></div>\n' +
-                '    <div class="kv-fileinput-error"></div>\n' +
-                '    </div>\n' +
-                '</div>';
-            tClose = $h.closeButton('fileinput-remove');
-            tFileIcon = '<i class="glyphicon glyphicon-file"></i>';
-            // noinspection HtmlUnknownAttribute
-            tCaption = '<div class="file-caption form-control {class}" tabindex="500">\n' +
-                '  <span class="file-caption-icon"></span>\n' +
-                '  <input class="file-caption-name" onkeydown="return false;" onpaste="return false;">\n' +
-                '</div>';
-            //noinspection HtmlUnknownAttribute
-            tBtnDefault = '<button type="{type}" tabindex="500" title="{title}" class="{css}" ' +
-                '{status}>{icon} {label}</button>';
-            //noinspection HtmlUnknownAttribute
-            tBtnLink = '<a href="{href}" tabindex="500" title="{title}" class="{css}" {status}>{icon} {label}</a>';
-            //noinspection HtmlUnknownAttribute
-            tBtnBrowse = '<div tabindex="500" class="{css}" {status}>{icon} {label}</div>';
-            tModalMain = '<div id="' + $h.MODAL_ID + '" class="file-zoom-dialog modal fade" ' +
-                'tabindex="-1" aria-labelledby="' + $h.MODAL_ID + 'Label"></div>';
-            tModal = '<div class="modal-dialog modal-lg{rtl}" role="document">\n' +
-                '  <div class="modal-content">\n' +
-                '    <div class="modal-header">\n' +
-                '      <h5 class="modal-title">{heading}</h5>\n' +
-                '      <span class="kv-zoom-title"></span>\n' +
-                '      <div class="kv-zoom-actions">{toggleheader}{fullscreen}{borderless}{close}</div>\n' +
-                '    </div>\n' +
-                '    <div class="modal-body">\n' +
-                '      <div class="floating-buttons"></div>\n' +
-                '      <div class="kv-zoom-body file-zoom-content {zoomFrameClass}"></div>\n' + '{prev} {next}\n' +
-                '    </div>\n' +
-                '  </div>\n' +
-                '</div>\n';
-            tProgress = '<div class="progress">\n' +
-                '    <div class="{class}" role="progressbar"' +
-                ' aria-valuenow="{percent}" aria-valuemin="0" aria-valuemax="100" style="width:{percent}%;">\n' +
-                '        {status}\n' +
-                '     </div>\n' +
-                '</div>';
-            tSize = ' <samp>({sizeText})</samp>';
-            tFooter = '<div class="file-thumbnail-footer">\n' +
-                '    <div class="file-footer-caption" title="{caption}">\n' +
-                '        <div class="file-caption-info">{caption}</div>\n' +
-                '        <div class="file-size-info">{size}</div>\n' +
-                '    </div>\n' +
-                '    {progress}\n{indicator}\n{actions}\n' +
-                '</div>';
-            tActions = '<div class="file-actions">\n' +
-                '    <div class="file-footer-buttons">\n' +
-                '        {download} {upload} {delete} {zoom} {other}' +
-                '    </div>\n' +
-                '</div>\n' +
-                '{drag}\n' +
-                '<div class="clearfix"></div>';
-            //noinspection HtmlUnknownAttribute
-            tActionDelete = '<button type="button" class="kv-file-remove {removeClass}" ' +
-                'title="{removeTitle}" {dataUrl}{dataKey}>{removeIcon}</button>\n';
-            tActionUpload = '<button type="button" class="kv-file-upload {uploadClass}" title="{uploadTitle}">' +
-                '{uploadIcon}</button>';
-            tActionDownload = '<a class="kv-file-download {downloadClass}" title="{downloadTitle}" ' +
-                'href="{downloadUrl}" download="{caption}" target="_blank">{downloadIcon}</a>';
-            tActionZoom = '<button type="button" class="kv-file-zoom {zoomClass}" ' +
-                'title="{zoomTitle}">{zoomIcon}</button>';
-            tActionDrag = '<span class="file-drag-handle {dragClass}" title="{dragTitle}">{dragIcon}</span>';
-            tIndicator = '<div class="file-upload-indicator" title="{indicatorTitle}">{indicator}</div>';
-            tTagBef = '<div class="file-preview-frame {frameClass}" id="{previewId}" data-fileindex="{fileindex}"' +
-                ' data-template="{template}"';
-            tTagBef1 = tTagBef + '><div class="kv-file-content">\n';
-            tTagBef2 = tTagBef + ' title="{caption}"><div class="kv-file-content">\n';
-            tTagAft = '</div>{footer}\n</div>\n';
-            tGeneric = '{content}\n';
-            tStyle = ' {style}';
-            tHtml = '<div class="kv-preview-data file-preview-html" title="{caption}"' + tStyle + '>{data}</div>\n';
-            tImage = '<img src="{data}" class="file-preview-image kv-preview-data" title="{caption}" ' +
-                'alt="{caption}"' + tStyle + '>\n';
-            tText = '<textarea class="kv-preview-data file-preview-text" title="{caption}" readonly' + tStyle + '>' +
-                '{data}</textarea>\n';
-            tOffice = '<iframe class="kv-preview-data file-preview-office" ' +
-                'src="https://view.officeapps.live.com/op/embed.aspx?src={data}"' + tStyle + '></iframe>';
-            tGdocs = '<iframe class="kv-preview-data file-preview-gdocs" ' +
-                'src="https://docs.google.com/gview?url={data}&embedded=true"' + tStyle + '></iframe>';
-            tVideo = '<video class="kv-preview-data file-preview-video" controls' + tStyle + '>\n' +
-                '<source src="{data}" type="{type}">\n' + $h.DEFAULT_PREVIEW + '\n</video>\n';
-            tAudio = '<!--suppress ALL --><audio class="kv-preview-data file-preview-audio" controls' + tStyle + '>\n<source src="{data}" ' +
-                'type="{type}">\n' + $h.DEFAULT_PREVIEW + '\n</audio>\n';
-            tFlash = '<embed class="kv-preview-data file-preview-flash" src="{data}" type="application/x-shockwave-flash"' + tStyle + '>\n';
-            tPdf = '<embed class="kv-preview-data file-preview-pdf" src="{data}" type="application/pdf"' + tStyle + '>\n';
-            tObject = '<object class="kv-preview-data file-preview-object file-object {typeCss}" ' +
-                'data="{data}" type="{type}"' + tStyle + '>\n' + '<param name="movie" value="{caption}" />\n' +
-                $h.OBJECT_PARAMS + ' ' + $h.DEFAULT_PREVIEW + '\n</object>\n';
-            tOther = '<div class="kv-preview-data file-preview-other-frame"' + tStyle + '>\n' + $h.DEFAULT_PREVIEW + '\n</div>\n';
-            tZoomCache = '<div class="kv-zoom-cache" style="display:none">{zoomContent}</div>';
-            vDefaultDim = {width: "100%", height: "100%", 'min-height': "480px"};
-            self.defaults = {
-                layoutTemplates: {
-                    main1: tMain1,
-                    main2: tMain2,
-                    preview: tPreview,
-                    close: tClose,
-                    fileIcon: tFileIcon,
-                    caption: tCaption,
-                    modalMain: tModalMain,
-                    modal: tModal,
-                    progress: tProgress,
-                    size: tSize,
-                    footer: tFooter,
-                    indicator: tIndicator,
-                    actions: tActions,
-                    actionDelete: tActionDelete,
-                    actionUpload: tActionUpload,
-                    actionDownload: tActionDownload,
-                    actionZoom: tActionZoom,
-                    actionDrag: tActionDrag,
-                    btnDefault: tBtnDefault,
-                    btnLink: tBtnLink,
-                    btnBrowse: tBtnBrowse,
-                    zoomCache: tZoomCache
-                },
-                previewMarkupTags: {
-                    tagBefore1: tTagBef1,
-                    tagBefore2: tTagBef2,
-                    tagAfter: tTagAft
-                },
-                previewContentTemplates: {
-                    generic: tGeneric,
-                    html: tHtml,
-                    image: tImage,
-                    text: tText,
-                    office: tOffice,
-                    gdocs: tGdocs,
-                    video: tVideo,
-                    audio: tAudio,
-                    flash: tFlash,
-                    object: tObject,
-                    pdf: tPdf,
-                    other: tOther
-                },
-                allowedPreviewTypes: ['image', 'html', 'text', 'video', 'audio', 'flash', 'pdf', 'object'],
-                previewTemplates: {},
-                previewSettings: {
-                    image: {width: "auto", height: "auto", 'max-width': "100%", 'max-height': "100%"},
-                    html: {width: "213px", height: "160px"},
-                    text: {width: "213px", height: "160px"},
-                    office: {width: "213px", height: "160px"},
-                    gdocs: {width: "213px", height: "160px"},
-                    video: {width: "213px", height: "160px"},
-                    audio: {width: "100%", height: "30px"},
-                    flash: {width: "213px", height: "160px"},
-                    object: {width: "213px", height: "160px"},
-                    pdf: {width: "213px", height: "160px"},
-                    other: {width: "213px", height: "160px"}
-                },
-                previewSettingsSmall: {
-                    image: {width: "auto", height: "auto", 'max-width': "100%", 'max-height': "100%"},
-                    html: {width: "100%", height: "160px"},
-                    text: {width: "100%", height: "160px"},
-                    office: {width: "100%", height: "160px"},
-                    gdocs: {width: "100%", height: "160px"},
-                    video: {width: "100%", height: "auto"},
-                    audio: {width: "100%", height: "30px"},
-                    flash: {width: "100%", height: "auto"},
-                    object: {width: "100%", height: "auto"},
-                    pdf: {width: "100%", height: "160px"},
-                    other: {width: "100%", height: "160px"}
-                },
-                previewZoomSettings: {
-                    image: {width: "auto", height: "auto", 'max-width': "100%", 'max-height': "100%"},
-                    html: vDefaultDim,
-                    text: vDefaultDim,
-                    office: {width: "100%", height: "100%", 'max-width': "100%", 'min-height': "480px"},
-                    gdocs: {width: "100%", height: "100%", 'max-width': "100%", 'min-height': "480px"},
-                    video: {width: "auto", height: "100%", 'max-width': "100%"},
-                    audio: {width: "100%", height: "30px"},
-                    flash: {width: "auto", height: "480px"},
-                    object: {width: "auto", height: "100%", 'max-width': "100%", 'min-height': "480px"},
-                    pdf: vDefaultDim,
-                    other: {width: "auto", height: "100%", 'min-height': "480px"}
-                },
-                fileTypeSettings: {
-                    image: function (vType, vName) {
-                        return ($h.compare(vType, 'image.*') && !$h.compare(vType, /(tiff?|wmf)$/i) ||
-                            $h.compare(vName, /\.(gif|png|jpe?g)$/i));
-                    },
-                    html: function (vType, vName) {
-                        return $h.compare(vType, 'text/html') || $h.compare(vName, /\.(htm|html)$/i);
-                    },
-                    office: function (vType, vName) {
-                        return $h.compare(vType, /(word|excel|powerpoint|office)$/i) ||
-                            $h.compare(vName, /\.(docx?|xlsx?|pptx?|pps|potx?)$/i);
-                    },
-                    gdocs: function (vType, vName) {
-                        return $h.compare(vType, /(word|excel|powerpoint|office|iwork-pages|tiff?)$/i) ||
-                            $h.compare(vName, /\.(docx?|xlsx?|pptx?|pps|potx?|rtf|ods|odt|pages|ai|dxf|ttf|tiff?|wmf|e?ps)$/i);
-                    },
-                    text: function (vType, vName) {
-                        return $h.compare(vType, 'text.*') || $h.compare(vName, /\.(xml|javascript)$/i) ||
-                            $h.compare(vName, /\.(txt|md|csv|nfo|ini|json|php|js|css)$/i);
-                    },
-                    video: function (vType, vName) {
-                        return $h.compare(vType, 'video.*') && ($h.compare(vType, /(ogg|mp4|mp?g|mov|webm|3gp)$/i) ||
-                            $h.compare(vName, /\.(og?|mp4|webm|mp?g|mov|3gp)$/i));
-                    },
-                    audio: function (vType, vName) {
-                        return $h.compare(vType, 'audio.*') && ($h.compare(vName, /(ogg|mp3|mp?g|wav)$/i) ||
-                            $h.compare(vName, /\.(og?|mp3|mp?g|wav)$/i));
-                    },
-                    flash: function (vType, vName) {
-                        return $h.compare(vType, 'application/x-shockwave-flash', true) || $h.compare(vName, /\.(swf)$/i);
-                    },
-                    pdf: function (vType, vName) {
-                        return $h.compare(vType, 'application/pdf', true) || $h.compare(vName, /\.(pdf)$/i);
-                    },
-                    object: function () {
-                        return true;
-                    },
-                    other: function () {
-                        return true;
-                    }
-                },
-                fileActionSettings: {
-                    showRemove: true,
-                    showUpload: true,
-                    showDownload: true,
-                    showZoom: true,
-                    showDrag: true,
-                    removeIcon: '<i class="glyphicon glyphicon-trash"></i>',
-                    removeClass: 'btn btn-sm btn-kv btn-default btn-outline-secondary',
-                    removeErrorClass: 'btn btn-sm btn-kv btn-danger',
-                    removeTitle: 'Remove file',
-                    uploadIcon: '<i class="glyphicon glyphicon-upload"></i>',
-                    uploadClass: 'btn btn-sm btn-kv btn-default btn-outline-secondary',
-                    uploadTitle: 'Upload file',
-                    uploadRetryIcon: '<i class="glyphicon glyphicon-repeat"></i>',
-                    uploadRetryTitle: 'Retry upload',
-                    downloadIcon: '<i class="glyphicon glyphicon-download"></i>',
-                    downloadClass: 'btn btn-sm btn-kv btn-default btn-outline-secondary',
-                    downloadTitle: 'Download file',
-                    zoomIcon: '<i class="glyphicon glyphicon-zoom-in"></i>',
-                    zoomClass: 'btn btn-sm btn-kv btn-default btn-outline-secondary',
-                    zoomTitle: 'View Details',
-                    dragIcon: '<i class="glyphicon glyphicon-move"></i>',
-                    dragClass: 'text-info',
-                    dragTitle: 'Move / Rearrange',
-                    dragSettings: {},
-                    indicatorNew: '<i class="glyphicon glyphicon-plus-sign text-warning"></i>',
-                    indicatorSuccess: '<i class="glyphicon glyphicon-ok-sign text-success"></i>',
-                    indicatorError: '<i class="glyphicon glyphicon-exclamation-sign text-danger"></i>',
-                    indicatorLoading: '<i class="glyphicon glyphicon-hourglass text-muted"></i>',
-                    indicatorNewTitle: 'Not uploaded yet',
-                    indicatorSuccessTitle: 'Uploaded',
-                    indicatorErrorTitle: 'Upload Error',
-                    indicatorLoadingTitle: 'Uploading ...'
-                }
-            };
-            $.each(self.defaults, function (key, setting) {
-                if (key === 'allowedPreviewTypes') {
-                    if (self.allowedPreviewTypes === undefined) {
-                        self.allowedPreviewTypes = setting;
-                    }
-                    return;
-                }
-                self[key] = $.extend(true, {}, setting, self[key]);
-            });
-            self._initPreviewTemplates();
-        },
-        _initPreviewTemplates: function () {
-            var self = this, cfg = self.defaults, tags = self.previewMarkupTags, tagBef, tagAft = tags.tagAfter;
-            $.each(cfg.previewContentTemplates, function (key, value) {
-                if ($h.isEmpty(self.previewTemplates[key])) {
-                    tagBef = tags.tagBefore2;
-                    if (key === 'generic' || key === 'image' || key === 'html' || key === 'text') {
-                        tagBef = tags.tagBefore1;
-                    }
-                    self.previewTemplates[key] = tagBef + value + tagAft;
-                }
-            });
-        },
-        _initPreviewCache: function () {
-            var self = this;
-            self.previewCache = {
-                data: {},
-                init: function () {
-                    var content = self.initialPreview;
-                    if (content.length > 0 && !$h.isArray(content)) {
-                        content = content.split(self.initialPreviewDelimiter);
-                    }
-                    self.previewCache.data = {
-                        content: content,
-                        config: self.initialPreviewConfig,
-                        tags: self.initialPreviewThumbTags
-                    };
-                },
-                count: function () {
-                    return !!self.previewCache.data && !!self.previewCache.data.content ?
-                        self.previewCache.data.content.length : 0;
-                },
-                get: function (i, isDisabled) {
-                    var ind = 'init_' + i, data = self.previewCache.data, config = data.config[i],
-                        content = data.content[i], previewId = self.previewInitId + '-' + ind, out, $tmp, cat, ftr,
-                        fname, ftype, frameClass, asData = $h.ifSet('previewAsData', config, self.initialPreviewAsData),
-                        parseTemplate = function (cat, dat, fn, ft, id, ftr, ind, fc, t) {
-                            fc = ' file-preview-initial ' + $h.SORT_CSS + (fc ? ' ' + fc : '');
-                            return self._generatePreviewTemplate(cat, dat, fn, ft, id, false, null, fc, ftr, ind, t);
-                        };
-                    if (!content) {
-                        return '';
-                    }
-                    isDisabled = isDisabled === undefined ? true : isDisabled;
-                    cat = $h.ifSet('type', config, self.initialPreviewFileType || 'generic');
-                    fname = $h.ifSet('filename', config, $h.ifSet('caption', config));
-                    ftype = $h.ifSet('filetype', config, cat);
-                    ftr = self.previewCache.footer(i, isDisabled, (config && config.size || null));
-                    frameClass = $h.ifSet('frameClass', config);
-                    if (asData) {
-                        out = parseTemplate(cat, content, fname, ftype, previewId, ftr, ind, frameClass);
-                    } else {
-                        out = parseTemplate('generic', content, fname, ftype, previewId, ftr, ind, frameClass, cat)
-                            .setTokens({'content': data.content[i]});
-                    }
-                    if (data.tags.length && data.tags[i]) {
-                        out = $h.replaceTags(out, data.tags[i]);
-                    }
-                    /** @namespace config.frameAttr */
-                    if (!$h.isEmpty(config) && !$h.isEmpty(config.frameAttr)) {
-                        $tmp = $(document.createElement('div')).html(out);
-                        $tmp.find('.file-preview-initial').attr(config.frameAttr);
-                        out = $tmp.html();
-                        $tmp.remove();
-                    }
-                    return out;
-                },
-                add: function (content, config, tags, append) {
-                    var data = self.previewCache.data, index;
-                    if (!$h.isArray(content)) {
-                        content = content.split(self.initialPreviewDelimiter);
-                    }
-                    if (append) {
-                        index = data.content.push(content) - 1;
-                        data.config[index] = config;
-                        data.tags[index] = tags;
-                    } else {
-                        index = content.length - 1;
-                        data.content = content;
-                        data.config = config;
-                        data.tags = tags;
-                    }
-                    self.previewCache.data = data;
-                    return index;
-                },
-                set: function (content, config, tags, append) {
-                    var data = self.previewCache.data, i, chk;
-                    if (!content || !content.length) {
-                        return;
-                    }
-                    if (!$h.isArray(content)) {
-                        content = content.split(self.initialPreviewDelimiter);
-                    }
-                    chk = content.filter(function (n) {
-                        return n !== null;
-                    });
-                    if (!chk.length) {
-                        return;
-                    }
-                    if (data.content === undefined) {
-                        data.content = [];
-                    }
-                    if (data.config === undefined) {
-                        data.config = [];
-                    }
-                    if (data.tags === undefined) {
-                        data.tags = [];
-                    }
-                    if (append) {
-                        for (i = 0; i < content.length; i++) {
-                            if (content[i]) {
-                                data.content.push(content[i]);
-                            }
-                        }
-                        for (i = 0; i < config.length; i++) {
-                            if (config[i]) {
-                                data.config.push(config[i]);
-                            }
-                        }
-                        for (i = 0; i < tags.length; i++) {
-                            if (tags[i]) {
-                                data.tags.push(tags[i]);
-                            }
-                        }
-                    } else {
-                        data.content = content;
-                        data.config = config;
-                        data.tags = tags;
-                    }
-                    self.previewCache.data = data;
-                },
-                unset: function (index) {
-                    var chk = self.previewCache.count(), rev = self.reversePreviewOrder;
-                    if (!chk) {
-                        return;
-                    }
-                    if (chk === 1) {
-                        self.previewCache.data.content = [];
-                        self.previewCache.data.config = [];
-                        self.previewCache.data.tags = [];
-                        self.initialPreview = [];
-                        self.initialPreviewConfig = [];
-                        self.initialPreviewThumbTags = [];
-                        return;
-                    }
-                    self.previewCache.data.content = $h.spliceArray(self.previewCache.data.content, index, rev);
-                    self.previewCache.data.config = $h.spliceArray(self.previewCache.data.config, index, rev);
-                    self.previewCache.data.tags = $h.spliceArray(self.previewCache.data.tags, index, rev);
-                },
-                out: function () {
-                    var html = '', caption, len = self.previewCache.count(), i, content;
-                    if (len === 0) {
-                        return {content: '', caption: ''};
-                    }
-                    for (i = 0; i < len; i++) {
-                        content = self.previewCache.get(i);
-                        html = self.reversePreviewOrder ? (content + html) : (html + content);
-                    }
-                    caption = self._getMsgSelected(len);
-                    return {content: html, caption: caption};
-                },
-                footer: function (i, isDisabled, size) {
-                    var data = self.previewCache.data || {};
-                    if ($h.isEmpty(data.content)) {
-                        return '';
-                    }
-                    if ($h.isEmpty(data.config) || $h.isEmpty(data.config[i])) {
-                        data.config[i] = {};
-                    }
-                    isDisabled = isDisabled === undefined ? true : isDisabled;
-                    var config = data.config[i], caption = $h.ifSet('caption', config), a,
-                        width = $h.ifSet('width', config, 'auto'), url = $h.ifSet('url', config, false),
-                        key = $h.ifSet('key', config, null), fs = self.fileActionSettings,
-                        initPreviewShowDel = self.initialPreviewShowDelete || false,
-                        dUrl = config.downloadUrl || self.initialPreviewDownloadUrl || '',
-                        dFil = config.filename || config.caption || '',
-                        initPreviewShowDwl = !!(dUrl),
-                        sDel = $h.ifSet('showRemove', config, $h.ifSet('showRemove', fs, initPreviewShowDel)),
-                        sDwl = $h.ifSet('showDownload', config, $h.ifSet('showDownload', fs, initPreviewShowDwl)),
-                        sZm = $h.ifSet('showZoom', config, $h.ifSet('showZoom', fs, true)),
-                        sDrg = $h.ifSet('showDrag', config, $h.ifSet('showDrag', fs, true)),
-                        dis = (url === false) && isDisabled;
-                    sDwl = sDwl && config.downloadUrl !== false && !!dUrl;
-                    a = self._renderFileActions(false, sDwl, sDel, sZm, sDrg, dis, url, key, true, dUrl, dFil);
-                    return self._getLayoutTemplate('footer').setTokens({
-                        'progress': self._renderThumbProgress(),
-                        'actions': a,
-                        'caption': caption,
-                        'size': self._getSize(size),
-                        'width': width,
-                        'indicator': ''
-                    });
-                }
-            };
-            self.previewCache.init();
-        },
-        _handler: function ($el, event, callback) {
-            var self = this, ns = self.namespace, ev = event.split(' ').join(ns + ' ') + ns;
-            if (!$el || !$el.length) {
-                return;
-            }
-            $el.off(ev).on(ev, callback);
-        },
-        _log: function (msg) {
-            var self = this, id = self.$element.attr('id');
-            if (id) {
-                msg = '"' + id + '": ' + msg;
-            }
-            if (typeof window.console.log !== "undefined") {
-                window.console.log(msg);
-            } else {
-                window.alert(msg);
-            }
-        },
-        _validate: function () {
-            var self = this, status = self.$element.attr('type') === 'file';
-            if (!status) {
-                self._log('The input "type" must be set to "file" for initializing the "bootstrap-fileinput" plugin.');
-            }
-            return status;
-        },
-        _errorsExist: function () {
-            var self = this, $err, $errList = self.$errorContainer.find('li');
-            if ($errList.length) {
-                return true;
-            }
-            $err = $(document.createElement('div')).html(self.$errorContainer.html());
-            $err.find('.kv-error-close').remove();
-            $err.find('ul').remove();
-            return !!$.trim($err.text()).length;
-        },
-        _errorHandler: function (evt, caption) {
-            var self = this, err = evt.target.error, showError = function (msg) {
-                self._showError(msg.replace('{name}', caption));
-            };
-            /** @namespace err.NOT_FOUND_ERR */
-            /** @namespace err.SECURITY_ERR */
-            /** @namespace err.NOT_READABLE_ERR */
-            if (err.code === err.NOT_FOUND_ERR) {
-                showError(self.msgFileNotFound);
-            } else if (err.code === err.SECURITY_ERR) {
-                showError(self.msgFileSecured);
-            } else if (err.code === err.NOT_READABLE_ERR) {
-                showError(self.msgFileNotReadable);
-            } else if (err.code === err.ABORT_ERR) {
-                showError(self.msgFilePreviewAborted);
-            } else {
-                showError(self.msgFilePreviewError);
-            }
-        },
-        _addError: function (msg) {
-            var self = this, $error = self.$errorContainer;
-            if (msg && $error.length) {
-                $error.html(self.errorCloseButton + msg);
-                self._handler($error.find('.kv-error-close'), 'click', function () {
-                    setTimeout(function () {
-                        if (self.showPreview && !self.getFrames().length) {
-                            self.clear();
-                        }
-                        $error.fadeOut('slow');
-                    }, 10);
-                });
-            }
-        },
-        _setValidationError: function (css) {
-            var self = this;
-            css = (css ? css + ' ' : '') + 'has-error';
-            self.$container.removeClass(css).addClass('has-error');
-            $h.addCss(self.$captionContainer, 'is-invalid');
-        },
-        _resetErrors: function (fade) {
-            var self = this, $error = self.$errorContainer;
-            self.isError = false;
-            self.$container.removeClass('has-error');
-            self.$captionContainer.removeClass('is-invalid');
-            $error.html('');
-            if (fade) {
-                $error.fadeOut('slow');
-            } else {
-                $error.hide();
-            }
-        },
-        _showFolderError: function (folders) {
-            var self = this, $error = self.$errorContainer, msg;
-            if (!folders) {
-                return;
-            }
-            if (!self.isAjaxUpload) {
-                self._clearFileInput();
-            }
-            msg = self.msgFoldersNotAllowed.replace('{n}', folders);
-            self._addError(msg);
-            self._setValidationError();
-            $error.fadeIn(800);
-            self._raise('filefoldererror', [folders, msg]);
-        },
-        _showUploadError: function (msg, params, event) {
-            var self = this, $error = self.$errorContainer, ev = event || 'fileuploaderror', e = params && params.id ?
-                '<li data-file-id="' + params.id + '">' + msg + '</li>' : '<li>' + msg + '</li>';
-            if ($error.find('ul').length === 0) {
-                self._addError('<ul>' + e + '</ul>');
-            } else {
-                $error.find('ul').append(e);
-            }
-            $error.fadeIn(800);
-            self._raise(ev, [params, msg]);
-            self._setValidationError('file-input-new');
-            return true;
-        },
-        _showError: function (msg, params, event) {
-            var self = this, $error = self.$errorContainer, ev = event || 'fileerror';
-            params = params || {};
-            params.reader = self.reader;
-            self._addError(msg);
-            $error.fadeIn(800);
-            self._raise(ev, [params, msg]);
-            if (!self.isAjaxUpload) {
-                self._clearFileInput();
-            }
-            self._setValidationError('file-input-new');
-            self.$btnUpload.attr('disabled', true);
-            return true;
-        },
-        _noFilesError: function (params) {
-            var self = this, label = self.minFileCount > 1 ? self.filePlural : self.fileSingle,
-                msg = self.msgFilesTooLess.replace('{n}', self.minFileCount).replace('{files}', label),
-                $error = self.$errorContainer;
-            self._addError(msg);
-            self.isError = true;
-            self._updateFileDetails(0);
-            $error.fadeIn(800);
-            self._raise('fileerror', [params, msg]);
-            self._clearFileInput();
-            self._setValidationError();
-        },
-        _parseError: function (operation, jqXHR, errorThrown, fileName) {
-            /** @namespace jqXHR.responseJSON */
-            var self = this, errMsg = $.trim(errorThrown + ''), textPre,
-                text = jqXHR.responseJSON !== undefined && jqXHR.responseJSON.error !== undefined ?
-                    jqXHR.responseJSON.error : jqXHR.responseText;
-            if (self.cancelling && self.msgUploadAborted) {
-                errMsg = self.msgUploadAborted;
-            }
-            if (self.showAjaxErrorDetails && text) {
-                text = $.trim(text.replace(/\n\s*\n/g, '\n'));
-                textPre = text.length ? '<pre>' + text + '</pre>' : '';
-                errMsg += errMsg ? textPre : text;
-            }
-            if (!errMsg) {
-                errMsg = self.msgAjaxError.replace('{operation}', operation);
-            }
-            self.cancelling = false;
-            return fileName ? '<b>' + fileName + ': </b>' + errMsg : errMsg;
-        },
-        _parseFileType: function (type, name) {
-            var self = this, isValid, vType, cat, i, types = self.allowedPreviewTypes || [];
-            if (type === 'application/text-plain') {
-                return 'text';
-            }
-            for (i = 0; i < types.length; i++) {
-                cat = types[i];
-                isValid = self.fileTypeSettings[cat];
-                vType = isValid(type, name) ? cat : '';
-                if (!$h.isEmpty(vType)) {
-                    return vType;
-                }
-            }
-            return 'other';
-        },
-        _getPreviewIcon: function (fname) {
-            var self = this, ext, out = null;
-            if (fname && fname.indexOf('.') > -1) {
-                ext = fname.split('.').pop();
-                if (self.previewFileIconSettings) {
-                    out = self.previewFileIconSettings[ext] || self.previewFileIconSettings[ext.toLowerCase()] || null;
-                }
-                if (self.previewFileExtSettings) {
-                    $.each(self.previewFileExtSettings, function (key, func) {
-                        if (self.previewFileIconSettings[key] && func(ext)) {
-                            out = self.previewFileIconSettings[key];
-                            //noinspection UnnecessaryReturnStatementJS
-                            return;
-                        }
-                    });
-                }
-            }
-            return out;
-        },
-        _parseFilePreviewIcon: function (content, fname) {
-            var self = this, icn = self._getPreviewIcon(fname) || self.previewFileIcon, out = content;
-            if (out.indexOf('{previewFileIcon}') > -1) {
-                out = out.setTokens({'previewFileIconClass': self.previewFileIconClass, 'previewFileIcon': icn});
-            }
-            return out;
-        },
-        _raise: function (event, params) {
-            var self = this, e = $.Event(event);
-            if (params !== undefined) {
-                self.$element.trigger(e, params);
-            } else {
-                self.$element.trigger(e);
-            }
-            if (e.isDefaultPrevented() || e.result === false) {
-                return false;
-            }
-            switch (event) {
-                // ignore these events
-                case 'filebatchuploadcomplete':
-                case 'filebatchuploadsuccess':
-                case 'fileuploaded':
-                case 'fileclear':
-                case 'filecleared':
-                case 'filereset':
-                case 'fileerror':
-                case 'filefoldererror':
-                case 'fileuploaderror':
-                case 'filebatchuploaderror':
-                case 'filedeleteerror':
-                case 'filecustomerror':
-                case 'filesuccessremove':
-                    break;
-                // receive data response via `filecustomerror` event`
-                default:
-                    if (!self.ajaxAborted) {
-                        self.ajaxAborted = e.result;
-                    }
-                    break;
-            }
-            return true;
-        },
-        _listenFullScreen: function (isFullScreen) {
-            var self = this, $modal = self.$modal, $btnFull, $btnBord;
-            if (!$modal || !$modal.length) {
-                return;
-            }
-            $btnFull = $modal && $modal.find('.btn-fullscreen');
-            $btnBord = $modal && $modal.find('.btn-borderless');
-            if (!$btnFull.length || !$btnBord.length) {
-                return;
-            }
-            $btnFull.removeClass('active').attr('aria-pressed', 'false');
-            $btnBord.removeClass('active').attr('aria-pressed', 'false');
-            if (isFullScreen) {
-                $btnFull.addClass('active').attr('aria-pressed', 'true');
-            } else {
-                $btnBord.addClass('active').attr('aria-pressed', 'true');
-            }
-            if ($modal.hasClass('file-zoom-fullscreen')) {
-                self._maximizeZoomDialog();
-            } else {
-                if (isFullScreen) {
-                    self._maximizeZoomDialog();
-                } else {
-                    $btnBord.removeClass('active').attr('aria-pressed', 'false');
-                }
-            }
-        },
-        _listen: function () {
-            var self = this, $el = self.$element, $form = self.$form, $cont = self.$container, fullScreenEvents;
-            self._handler($el, 'click', function(e) {
-                if ($el.hasClass('file-no-browse')) {
-                    if ($el.data('zoneClicked')) {
-                        $el.data('zoneClicked', false);
-                    } else {
-                        e.preventDefault();
-                    }
-                }
-            });
-            self._handler($el, 'change', $.proxy(self._change, self));
-            if (self.showBrowse) {
-                self._handler(self.$btnFile, 'click', $.proxy(self._browse, self));
-            }
-            self._handler($cont.find('.fileinput-remove:not([disabled])'), 'click', $.proxy(self.clear, self));
-            self._handler($cont.find('.fileinput-cancel'), 'click', $.proxy(self.cancel, self));
-            self._initDragDrop();
-            self._handler($form, 'reset', $.proxy(self.clear, self));
-            if (!self.isAjaxUpload) {
-                self._handler($form, 'submit', $.proxy(self._submitForm, self));
-            }
-            self._handler(self.$container.find('.fileinput-upload'), 'click', $.proxy(self._uploadClick, self));
-            self._handler($(window), 'resize', function () {
-                self._listenFullScreen(screen.width === window.innerWidth && screen.height === window.innerHeight);
-            });
-            fullScreenEvents = 'webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange';
-            self._handler($(document), fullScreenEvents, function () {
-                self._listenFullScreen($h.checkFullScreen());
-            });
-            self._autoFitContent();
-            self._initClickable();
-            self._refreshPreview();
-        },
-        _autoFitContent: function () {
-            var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
-                self = this, config = width < 400 ? (self.previewSettingsSmall || self.defaults.previewSettingsSmall) :
-                (self.previewSettings || self.defaults.previewSettings), sel;
-            $.each(config, function (cat, settings) {
-                sel = '.file-preview-frame .file-preview-' + cat;
-                self.$preview.find(sel + '.kv-preview-data,' + sel + ' .kv-preview-data').css(settings);
-            });
-        },
-        _scanDroppedItems: function (item, files, path) {
-            path = path || "";
-            var self = this, i, dirReader, readDir, errorHandler = function (e) {
-                self._log('Error scanning dropped files!');
-                self._log(e);
-            };
-            if (item.isFile) {
-                item.file(function (file) {
-                    files.push(file);
-                }, errorHandler);
-            } else {
-                if (item.isDirectory) {
-                    dirReader = item.createReader();
-                    readDir = function () {
-                        dirReader.readEntries(function (entries) {
-                            if (entries && entries.length > 0) {
-                                for (i = 0; i < entries.length; i++) {
-                                    self._scanDroppedItems(entries[i], files, path + item.name + "/");
-                                }
-                                // recursively call readDir() again, since browser can only handle first 100 entries.
-                                readDir();
-                            }
-                            return null;
-                        }, errorHandler);
-                    };
-                    readDir();
-                }
-            }
-
-        },
-        _initDragDrop: function () {
-            var self = this, $zone = self.$dropZone;
-            if (self.dropZoneEnabled && self.showPreview) {
-                self._handler($zone, 'dragenter dragover', $.proxy(self._zoneDragEnter, self));
-                self._handler($zone, 'dragleave', $.proxy(self._zoneDragLeave, self));
-                self._handler($zone, 'drop', $.proxy(self._zoneDrop, self));
-                self._handler($(document), 'dragenter dragover drop', self._zoneDragDropInit);
-            }
-        },
-        _zoneDragDropInit: function (e) {
-            e.stopPropagation();
-            e.preventDefault();
-        },
-        _zoneDragEnter: function (e) {
-            var self = this, hasFiles = $.inArray('Files', e.originalEvent.dataTransfer.types) > -1;
-            self._zoneDragDropInit(e);
-            if (self.isDisabled || !hasFiles) {
-                e.originalEvent.dataTransfer.effectAllowed = 'none';
-                e.originalEvent.dataTransfer.dropEffect = 'none';
-                return;
-            }
-            $h.addCss(self.$dropZone, 'file-highlighted');
-        },
-        _zoneDragLeave: function (e) {
-            var self = this;
-            self._zoneDragDropInit(e);
-            if (self.isDisabled) {
-                return;
-            }
-            self.$dropZone.removeClass('file-highlighted');
-        },
-        _zoneDrop: function (e) {
-            /** @namespace e.originalEvent.dataTransfer */
-            var self = this, i, $el = self.$element, dataTransfer = e.originalEvent.dataTransfer,
-                files = dataTransfer.files, items = dataTransfer.items, folders = $h.getDragDropFolders(items),
-                processFiles = function () {
-                    if (!self.isAjaxUpload) {
-                        self.changeTriggered = true;
-                        $el.get(0).files = files;
-                        setTimeout(function () {
-                            self.changeTriggered = false;
-                            $el.trigger('change' + self.namespace);
-                        }, 10);
-                    } else {
-                        self._change(e, files);
-                    }
-                    self.$dropZone.removeClass('file-highlighted');
-                };
-            e.preventDefault();
-            if (self.isDisabled || $h.isEmpty(files)) {
-                return;
-            }
-            if (folders > 0) {
-                if (!self.isAjaxUpload) {
-                    self._showFolderError(folders);
-                    return;
-                }
-                files = [];
-                for (i = 0; i < items.length; i++) {
-                    var item = items[i].webkitGetAsEntry();
-                    if (item) {
-                        self._scanDroppedItems(item, files);
-                    }
-                }
-                setTimeout(function () {
-                    processFiles();
-                }, 500);
-            } else {
-                processFiles();
-            }
-        },
-        _uploadClick: function (e) {
-            var self = this, $btn = self.$container.find('.fileinput-upload'), $form,
-                isEnabled = !$btn.hasClass('disabled') && $h.isEmpty($btn.attr('disabled'));
-            if (e && e.isDefaultPrevented()) {
-                return;
-            }
-            if (!self.isAjaxUpload) {
-                if (isEnabled && $btn.attr('type') !== 'submit') {
-                    $form = $btn.closest('form');
-                    // downgrade to normal form submit if possible
-                    if ($form.length) {
-                        $form.trigger('submit');
-                    }
-                    e.preventDefault();
-                }
-                return;
-            }
-            e.preventDefault();
-            if (isEnabled) {
-                self.upload();
-            }
-        },
-        _submitForm: function () {
-            var self = this;
-            return self._isFileSelectionValid() && !self._abort({});
-        },
-        _clearPreview: function () {
-            var self = this, $p = self.$preview,
-                $thumbs = self.showUploadedThumbs ? self.getFrames(':not(.file-preview-success)') : self.getFrames();
-            $thumbs.each(function () {
-                var $thumb = $(this);
-                $thumb.remove();
-                $h.cleanZoomCache($p.find('#zoom-' + $thumb.attr('id')));
-            });
-            if (!self.getFrames().length || !self.showPreview) {
-                self._resetUpload();
-            }
-            self._validateDefaultPreview();
-        },
-        _initSortable: function () {
-            var self = this, $el = self.$preview, settings, selector = '.' + $h.SORT_CSS,
-                rev = self.reversePreviewOrder;
-            if (!window.KvSortable || $el.find(selector).length === 0) {
-                return;
-            }
-            //noinspection JSUnusedGlobalSymbols
-            settings = {
-                handle: '.drag-handle-init',
-                dataIdAttr: 'data-preview-id',
-                scroll: false,
-                draggable: selector,
-                onSort: function (e) {
-                    var oldIndex = e.oldIndex, newIndex = e.newIndex, i = 0;
-                    self.initialPreview = $h.moveArray(self.initialPreview, oldIndex, newIndex, rev);
-                    self.initialPreviewConfig = $h.moveArray(self.initialPreviewConfig, oldIndex, newIndex, rev);
-                    self.previewCache.init();
-                    self.getFrames('.file-preview-initial').each(function () {
-                        $(this).attr('data-fileindex', 'init_' + i);
-                        i++;
-                    });
-                    self._raise('filesorted', {
-                        previewId: $(e.item).attr('id'),
-                        'oldIndex': oldIndex,
-                        'newIndex': newIndex,
-                        stack: self.initialPreviewConfig
-                    });
-                }
-            };
-            if ($el.data('kvsortable')) {
-                $el.kvsortable('destroy');
-            }
-            $.extend(true, settings, self.fileActionSettings.dragSettings);
-            $el.kvsortable(settings);
-        },
-        _setPreviewContent: function (content) {
-            var self = this;
-            self.$preview.html(content);
-            self._autoFitContent();
-        },
-        _initPreview: function (isInit) {
-            var self = this, cap = self.initialCaption || '', out;
-            if (!self.previewCache.count()) {
-                self._clearPreview();
-                if (isInit) {
-                    self._setCaption(cap);
-                } else {
-                    self._initCaption();
-                }
-                return;
-            }
-            out = self.previewCache.out();
-            cap = isInit && self.initialCaption ? self.initialCaption : out.caption;
-            self._setPreviewContent(out.content);
-            self._setInitThumbAttr();
-            self._setCaption(cap);
-            self._initSortable();
-            if (!$h.isEmpty(out.content)) {
-                self.$container.removeClass('file-input-new');
-            }
-        },
-        _getZoomButton: function (type) {
-            var self = this, label = self.previewZoomButtonIcons[type], css = self.previewZoomButtonClasses[type],
-                title = ' title="' + (self.previewZoomButtonTitles[type] || '') + '" ',
-                params = title + (type === 'close' ? ' data-dismiss="modal" aria-hidden="true"' : '');
-            if (type === 'fullscreen' || type === 'borderless' || type === 'toggleheader') {
-                params += ' data-toggle="button" aria-pressed="false" autocomplete="off"';
-            }
-            return '<button type="button" class="' + css + ' btn-' + type + '"' + params + '>' + label + '</button>';
-        },
-        _getModalContent: function () {
-            var self = this;
-            return self._getLayoutTemplate('modal').setTokens({
-                'rtl': self.rtl ? ' kv-rtl' : '',
-                'zoomFrameClass': self.frameClass,
-                'heading': self.msgZoomModalHeading,
-                'prev': self._getZoomButton('prev'),
-                'next': self._getZoomButton('next'),
-                'toggleheader': self._getZoomButton('toggleheader'),
-                'fullscreen': self._getZoomButton('fullscreen'),
-                'borderless': self._getZoomButton('borderless'),
-                'close': self._getZoomButton('close')
-            });
-        },
-        _listenModalEvent: function (event) {
-            var self = this, $modal = self.$modal, getParams = function (e) {
-                return {
-                    sourceEvent: e,
-                    previewId: $modal.data('previewId'),
-                    modal: $modal
-                };
-            };
-            $modal.on(event + '.bs.modal', function (e) {
-                var $btnFull = $modal.find('.btn-fullscreen'), $btnBord = $modal.find('.btn-borderless');
-                self._raise('filezoom' + event, getParams(e));
-                if (event === 'shown') {
-                    $btnBord.removeClass('active').attr('aria-pressed', 'false');
-                    $btnFull.removeClass('active').attr('aria-pressed', 'false');
-                    if ($modal.hasClass('file-zoom-fullscreen')) {
-                        self._maximizeZoomDialog();
-                        if ($h.checkFullScreen()) {
-                            $btnFull.addClass('active').attr('aria-pressed', 'true');
-                        } else {
-                            $btnBord.addClass('active').attr('aria-pressed', 'true');
-                        }
-                    }
-                }
-            });
-        },
-        _initZoom: function () {
-            var self = this, $dialog, modalMain = self._getLayoutTemplate('modalMain'), modalId = '#' + $h.MODAL_ID;
-            if (!self.showPreview) {
-                return;
-            }
-            self.$modal = $(modalId);
-            if (!self.$modal || !self.$modal.length) {
-                $dialog = $(document.createElement('div')).html(modalMain).insertAfter(self.$container);
-                self.$modal = $(modalId).insertBefore($dialog);
-                $dialog.remove();
-            }
-            $h.initModal(self.$modal);
-            self.$modal.html(self._getModalContent());
-            $.each($h.MODAL_EVENTS, function (key, event) {
-                self._listenModalEvent(event);
-            });
-        },
-        _initZoomButtons: function () {
-            var self = this, previewId = self.$modal.data('previewId') || '', $first, $last,
-                thumbs = self.getFrames().toArray(), len = thumbs.length, $prev = self.$modal.find('.btn-prev'),
-                $next = self.$modal.find('.btn-next');
-            if (thumbs.length < 2) {
-                $prev.hide();
-                $next.hide();
-                return;
-            } else {
-                $prev.show();
-                $next.show();
-            }
-            if (!len) {
-                return;
-            }
-            $first = $(thumbs[0]);
-            $last = $(thumbs[len - 1]);
-            $prev.removeAttr('disabled');
-            $next.removeAttr('disabled');
-            if ($first.length && $first.attr('id') === previewId) {
-                $prev.attr('disabled', true);
-            }
-            if ($last.length && $last.attr('id') === previewId) {
-                $next.attr('disabled', true);
-            }
-        },
-        _maximizeZoomDialog: function () {
-            var self = this, $modal = self.$modal, $head = $modal.find('.modal-header:visible'),
-                $foot = $modal.find('.modal-footer:visible'), $body = $modal.find('.modal-body'),
-                h = $(window).height(), diff = 0;
-            $modal.addClass('file-zoom-fullscreen');
-            if ($head && $head.length) {
-                h -= $head.outerHeight(true);
-            }
-            if ($foot && $foot.length) {
-                h -= $foot.outerHeight(true);
-            }
-            if ($body && $body.length) {
-                diff = $body.outerHeight(true) - $body.height();
-                h -= diff;
-            }
-            $modal.find('.kv-zoom-body').height(h);
-        },
-        _resizeZoomDialog: function (fullScreen) {
-            var self = this, $modal = self.$modal, $btnFull = $modal.find('.btn-fullscreen'),
-                $btnBord = $modal.find('.btn-borderless');
-            if ($modal.hasClass('file-zoom-fullscreen')) {
-                $h.toggleFullScreen(false);
-                if (!fullScreen) {
-                    if (!$btnFull.hasClass('active')) {
-                        $modal.removeClass('file-zoom-fullscreen');
-                        self.$modal.find('.kv-zoom-body').css('height', self.zoomModalHeight);
-                    } else {
-                        $btnFull.removeClass('active').attr('aria-pressed', 'false');
-                    }
-                } else {
-                    if (!$btnFull.hasClass('active')) {
-                        $modal.removeClass('file-zoom-fullscreen');
-                        self._resizeZoomDialog(true);
-                        if ($btnBord.hasClass('active')) {
-                            $btnBord.removeClass('active').attr('aria-pressed', 'false');
-                        }
-                    }
-                }
-            } else {
-                if (!fullScreen) {
-                    self._maximizeZoomDialog();
-                    return;
-                }
-                $h.toggleFullScreen(true);
-            }
-            $modal.focus();
-        },
-        _setZoomContent: function ($frame, animate) {
-            var self = this, $content, tmplt, body, title, $body, $dataEl, config, pid = $frame.attr('id'),
-                $modal = self.$modal, $prev = $modal.find('.btn-prev'), $next = $modal.find('.btn-next'), $tmp,
-                $btnFull = $modal.find('.btn-fullscreen'), $btnBord = $modal.find('.btn-borderless'), cap, size,
-                $btnTogh = $modal.find('.btn-toggleheader'), $zoomPreview = self.$preview.find('#zoom-' + pid);
-            tmplt = $zoomPreview.attr('data-template') || 'generic';
-            $content = $zoomPreview.find('.kv-file-content');
-            body = $content.length ? $content.html() : '';
-            cap = $frame.data('caption') || '';
-            size = $frame.data('size') || '';
-            title = cap + ' ' + size;
-            $modal.find('.kv-zoom-title').attr('title', $('<div/>').html(title).text()).html(title);
-            $body = $modal.find('.kv-zoom-body');
-            $modal.removeClass('kv-single-content');
-            if (animate) {
-                $tmp = $body.addClass('file-thumb-loading').clone().insertAfter($body);
-                $body.html(body).hide();
-                $tmp.fadeOut('fast', function () {
-                    $body.fadeIn('fast', function () {
-                        $body.removeClass('file-thumb-loading');
-                    });
-                    $tmp.remove();
-                });
-            } else {
-                $body.html(body);
-            }
-            config = self.previewZoomSettings[tmplt];
-            if (config) {
-                $dataEl = $body.find('.kv-preview-data');
-                $h.addCss($dataEl, 'file-zoom-detail');
-                $.each(config, function (key, value) {
-                    $dataEl.css(key, value);
-                    if (($dataEl.attr('width') && key === 'width') || ($dataEl.attr('height') && key === 'height')) {
-                        $dataEl.removeAttr(key);
-                    }
-                });
-            }
-            $modal.data('previewId', pid);
-            var $img = $body.find('img');
-            if ($img.length) {
-                $h.adjustOrientedImage($img, true);
-            }
-            self._handler($prev, 'click', function () {
-                self._zoomSlideShow('prev', pid);
-            });
-            self._handler($next, 'click', function () {
-                self._zoomSlideShow('next', pid);
-            });
-            self._handler($btnFull, 'click', function () {
-                self._resizeZoomDialog(true);
-            });
-            self._handler($btnBord, 'click', function () {
-                self._resizeZoomDialog(false);
-            });
-            self._handler($btnTogh, 'click', function () {
-                var $header = $modal.find('.modal-header'), $floatBar = $modal.find('.modal-body .floating-buttons'),
-                    ht, $actions = $header.find('.kv-zoom-actions'), resize = function (height) {
-                        var $body = self.$modal.find('.kv-zoom-body'), h = self.zoomModalHeight;
-                        if ($modal.hasClass('file-zoom-fullscreen')) {
-                            h = $body.outerHeight(true);
-                            if (!height) {
-                                h = h - $header.outerHeight(true);
-                            }
-                        }
-                        $body.css('height', height ? h + height : h);
-                    };
-                if ($header.is(':visible')) {
-                    ht = $header.outerHeight(true);
-                    $header.slideUp('slow', function () {
-                        $actions.find('.btn').appendTo($floatBar);
-                        resize(ht);
-                    });
-                } else {
-                    $floatBar.find('.btn').appendTo($actions);
-                    $header.slideDown('slow', function () {
-                        resize();
-                    });
-                }
-                $modal.focus();
-            });
-            self._handler($modal, 'keydown', function (e) {
-                var key = e.which || e.keyCode;
-                if (key === 37 && !$prev.attr('disabled')) {
-                    self._zoomSlideShow('prev', pid);
-                }
-                if (key === 39 && !$next.attr('disabled')) {
-                    self._zoomSlideShow('next', pid);
-                }
-            });
-        },
-        _zoomPreview: function ($btn) {
-            var self = this, $frame, $modal = self.$modal;
-            if (!$btn.length) {
-                throw 'Cannot zoom to detailed preview!';
-            }
-            $h.initModal($modal);
-            $modal.html(self._getModalContent());
-            $frame = $btn.closest($h.FRAMES);
-            self._setZoomContent($frame);
-            $modal.modal('show');
-            self._initZoomButtons();
-        },
-        _zoomSlideShow: function (dir, previewId) {
-            var self = this, $btn = self.$modal.find('.kv-zoom-actions .btn-' + dir), $targFrame, i,
-                thumbs = self.getFrames().toArray(), len = thumbs.length, out;
-            if ($btn.attr('disabled')) {
-                return;
-            }
-            for (i = 0; i < len; i++) {
-                if ($(thumbs[i]).attr('id') === previewId) {
-                    out = dir === 'prev' ? i - 1 : i + 1;
-                    break;
-                }
-            }
-            if (out < 0 || out >= len || !thumbs[out]) {
-                return;
-            }
-            $targFrame = $(thumbs[out]);
-            if ($targFrame.length) {
-                self._setZoomContent($targFrame, true);
-            }
-            self._initZoomButtons();
-            self._raise('filezoom' + dir, {'previewId': previewId, modal: self.$modal});
-        },
-        _initZoomButton: function () {
-            var self = this;
-            self.$preview.find('.kv-file-zoom').each(function () {
-                var $el = $(this);
-                self._handler($el, 'click', function () {
-                    self._zoomPreview($el);
-                });
-            });
-        },
-        _inputFileCount: function() {
-            return this.$element.get(0).files.length;
-        },
-        _refreshPreview: function() {
-            var self = this, files;
-            if (!self._inputFileCount() || !self.showPreview || !self.isPreviewable) {
-                return;
-            }
-            if (self.isAjaxUpload) {
-                files = self.getFileStack();
-                self.filestack = [];
-                if (files.length) {
-                    self._clearFileInput();
-                } else {
-                    files = self.$element.get(0).files;
-                }
-            } else {
-                files = self.$element.get(0).files;
-            }
-            if (files && files.length) {
-                self.readFiles(files);
-                self._setFileDropZoneTitle();
-            }
-        },
-        _clearObjects: function ($el) {
-            $el.find('video audio').each(function () {
-                this.pause();
-                $(this).remove();
-            });
-            $el.find('img object div').each(function () {
-                $(this).remove();
-            });
-        },
-        _clearFileInput: function () {
-            var self = this, $el = self.$element, $srcFrm, $tmpFrm, $tmpEl;
-            if (!self._inputFileCount()) {
-                return;
-            }
-            $srcFrm = $el.closest('form');
-            $tmpFrm = $(document.createElement('form'));
-            $tmpEl = $(document.createElement('div'));
-            $el.before($tmpEl);
-            if ($srcFrm.length) {
-                $srcFrm.after($tmpFrm);
-            } else {
-                $tmpEl.after($tmpFrm);
-            }
-            $tmpFrm.append($el).trigger('reset');
-            $tmpEl.before($el).remove();
-            $tmpFrm.remove();
-        },
-        _resetUpload: function () {
-            var self = this;
-            self.uploadCache = {content: [], config: [], tags: [], append: true};
-            self.uploadCount = 0;
-            self.uploadStatus = {};
-            self.uploadLog = [];
-            self.uploadAsyncCount = 0;
-            self.loadedImages = [];
-            self.totalImagesCount = 0;
-            self.$btnUpload.removeAttr('disabled');
-            self._setProgress(0);
-            self.$progress.hide();
-            self._resetErrors(false);
-            self.ajaxAborted = false;
-            self.ajaxRequests = [];
-            self._resetCanvas();
-            self.cacheInitialPreview = {};
-            if (self.overwriteInitial) {
-                self.initialPreview = [];
-                self.initialPreviewConfig = [];
-                self.initialPreviewThumbTags = [];
-                self.previewCache.data = {
-                    content: [],
-                    config: [],
-                    tags: []
-                };
-            }
-        },
-        _resetCanvas: function () {
-            var self = this;
-            if (self.canvas && self.imageCanvasContext) {
-                self.imageCanvasContext.clearRect(0, 0, self.canvas.width, self.canvas.height);
-            }
-        },
-        _hasInitialPreview: function () {
-            var self = this;
-            return !self.overwriteInitial && self.previewCache.count();
-        },
-        _resetPreview: function () {
-            var self = this, out, cap;
-            if (self.previewCache.count()) {
-                out = self.previewCache.out();
-                self._setPreviewContent(out.content);
-                self._setInitThumbAttr();
-                cap = self.initialCaption ? self.initialCaption : out.caption;
-                self._setCaption(cap);
-            } else {
-                self._clearPreview();
-                self._initCaption();
-            }
-            if (self.showPreview) {
-                self._initZoom();
-                self._initSortable();
-            }
-        },
-        _clearDefaultPreview: function () {
-            var self = this;
-            self.$preview.find('.file-default-preview').remove();
-        },
-        _validateDefaultPreview: function () {
-            var self = this;
-            if (!self.showPreview || $h.isEmpty(self.defaultPreviewContent)) {
-                return;
-            }
-            self._setPreviewContent('<div class="file-default-preview">' + self.defaultPreviewContent + '</div>');
-            self.$container.removeClass('file-input-new');
-            self._initClickable();
-        },
-        _resetPreviewThumbs: function (isAjax) {
-            var self = this, out;
-            if (isAjax) {
-                self._clearPreview();
-                self.clearStack();
-                return;
-            }
-            if (self._hasInitialPreview()) {
-                out = self.previewCache.out();
-                self._setPreviewContent(out.content);
-                self._setInitThumbAttr();
-                self._setCaption(out.caption);
-                self._initPreviewActions();
-            } else {
-                self._clearPreview();
-            }
-        },
-        _getLayoutTemplate: function (t) {
-            var self = this, template = self.layoutTemplates[t];
-            if ($h.isEmpty(self.customLayoutTags)) {
-                return template;
-            }
-            return $h.replaceTags(template, self.customLayoutTags);
-        },
-        _getPreviewTemplate: function (t) {
-            var self = this, template = self.previewTemplates[t];
-            if ($h.isEmpty(self.customPreviewTags)) {
-                return template;
-            }
-            return $h.replaceTags(template, self.customPreviewTags);
-        },
-        _getOutData: function (jqXHR, responseData, filesData) {
-            var self = this;
-            jqXHR = jqXHR || {};
-            responseData = responseData || {};
-            filesData = filesData || self.filestack.slice(0) || {};
-            return {
-                form: self.formdata,
-                files: filesData,
-                filenames: self.filenames,
-                filescount: self.getFilesCount(),
-                extra: self._getExtraData(),
-                response: responseData,
-                reader: self.reader,
-                jqXHR: jqXHR
-            };
-        },
-        _getMsgSelected: function (n) {
-            var self = this, strFiles = n === 1 ? self.fileSingle : self.filePlural;
-            return n > 0 ? self.msgSelected.replace('{n}', n).replace('{files}', strFiles) : self.msgNoFilesSelected;
-        },
-        _getFrame: function (id) {
-            var self = this, $frame = $('#' + id);
-            if (!$frame.length) {
-                self._log('Invalid thumb frame with id: "' + id + '".');
-                return null;
-            }
-            return $frame;
-        },
-        _getThumbs: function (css) {
-            css = css || '';
-            return this.getFrames(':not(.file-preview-initial)' + css);
-        },
-        _getExtraData: function (previewId, index) {
-            var self = this, data = self.uploadExtraData;
-            if (typeof self.uploadExtraData === "function") {
-                data = self.uploadExtraData(previewId, index);
-            }
-            return data;
-        },
-        _initXhr: function (xhrobj, previewId, fileCount) {
-            var self = this;
-            if (xhrobj.upload) {
-                xhrobj.upload.addEventListener('progress', function (event) {
-                    var pct = 0, total = event.total, position = event.loaded || event.position;
-                    /** @namespace event.lengthComputable */
-                    if (event.lengthComputable) {
-                        pct = Math.floor(position / total * 100);
-                    }
-                    if (previewId) {
-                        self._setAsyncUploadStatus(previewId, pct, fileCount);
-                    } else {
-                        self._setProgress(pct);
-                    }
-                }, false);
-            }
-            return xhrobj;
-        },
-        _initAjaxSettings: function () {
-            var self = this;
-            self._ajaxSettings = $.extend(true, {}, self.ajaxSettings);
-            self._ajaxDeleteSettings = $.extend(true, {}, self.ajaxDeleteSettings);
-        },
-        _mergeAjaxCallback: function (funcName, srcFunc, type) {
-            var self = this, settings = self._ajaxSettings, flag = self.mergeAjaxCallbacks, targFunc;
-            if (type === 'delete') {
-                settings = self._ajaxDeleteSettings;
-                flag = self.mergeAjaxDeleteCallbacks;
-            }
-            targFunc = settings[funcName];
-            if (flag && typeof targFunc === "function") {
-                if (flag === 'before') {
-                    settings[funcName] = function () {
-                        targFunc.apply(this, arguments);
-                        srcFunc.apply(this, arguments);
-                    };
-                } else {
-                    settings[funcName] = function () {
-                        srcFunc.apply(this, arguments);
-                        targFunc.apply(this, arguments);
-                    };
-                }
-            } else {
-                settings[funcName] = srcFunc;
-            }
-        },
-        _ajaxSubmit: function (fnBefore, fnSuccess, fnComplete, fnError, previewId, index) {
-            var self = this, settings;
-            if (!self._raise('filepreajax', [previewId, index])) {
-                return;
-            }
-            self._uploadExtra(previewId, index);
-            self._initAjaxSettings();
-            self._mergeAjaxCallback('beforeSend', fnBefore);
-            self._mergeAjaxCallback('success', fnSuccess);
-            self._mergeAjaxCallback('complete', fnComplete);
-            self._mergeAjaxCallback('error', fnError);
-            settings = $.extend(true, {}, {
-                xhr: function () {
-                    var xhrobj = $.ajaxSettings.xhr();
-                    return self._initXhr(xhrobj, previewId, self.getFileStack().length);
-                },
-                url: index && self.uploadUrlThumb ? self.uploadUrlThumb : self.uploadUrl,
-                type: 'POST',
-                dataType: 'json',
-                data: self.formdata,
-                cache: false,
-                processData: false,
-                contentType: false
-            }, self._ajaxSettings);
-            self.ajaxRequests.push($.ajax(settings));
-        },
-        _mergeArray: function (prop, content) {
-            var self = this, arr1 = $h.cleanArray(self[prop]), arr2 = $h.cleanArray(content);
-            self[prop] = arr1.concat(arr2);
-        },
-        _initUploadSuccess: function (out, $thumb, allFiles) {
-            var self = this, append, data, index, $div, $newCache, content, config, tags, i;
-            if (!self.showPreview || typeof out !== 'object' || $.isEmptyObject(out)) {
-                return;
-            }
-            if (out.initialPreview !== undefined && out.initialPreview.length > 0) {
-                self.hasInitData = true;
-                content = out.initialPreview || [];
-                config = out.initialPreviewConfig || [];
-                tags = out.initialPreviewThumbTags || [];
-                append = out.append === undefined || out.append;
-                if (content.length > 0 && !$h.isArray(content)) {
-                    content = content.split(self.initialPreviewDelimiter);
-                }
-                self._mergeArray('initialPreview', content);
-                self._mergeArray('initialPreviewConfig', config);
-                self._mergeArray('initialPreviewThumbTags', tags);
-                if ($thumb !== undefined) {
-                    if (!allFiles) {
-                        index = self.previewCache.add(content, config[0], tags[0], append);
-                        data = self.previewCache.get(index, false);
-                        $div = $(document.createElement('div')).html(data).hide().insertAfter($thumb);
-                        $newCache = $div.find('.kv-zoom-cache');
-                        if ($newCache && $newCache.length) {
-                            $newCache.insertAfter($thumb);
-                        }
-                        $thumb.fadeOut('slow', function () {
-                            var $newThumb = $div.find('.file-preview-frame');
-                            if ($newThumb && $newThumb.length) {
-                                $newThumb.insertBefore($thumb).fadeIn('slow').css('display:inline-block');
-                            }
-                            self._initPreviewActions();
-                            self._clearFileInput();
-                            $h.cleanZoomCache(self.$preview.find('#zoom-' + $thumb.attr('id')));
-                            $thumb.remove();
-                            $div.remove();
-                            self._initSortable();
-                        });
-                    } else {
-                        i = $thumb.attr('data-fileindex');
-                        self.uploadCache.content[i] = content[0];
-                        self.uploadCache.config[i] = config[0] || [];
-                        self.uploadCache.tags[i] = tags[0] || [];
-                        self.uploadCache.append = append;
-                    }
-                } else {
-                    self.previewCache.set(content, config, tags, append);
-                    self._initPreview();
-                    self._initPreviewActions();
-                }
-            }
-        },
-        _initSuccessThumbs: function () {
-            var self = this;
-            if (!self.showPreview) {
-                return;
-            }
-            self._getThumbs($h.FRAMES + '.file-preview-success').each(function () {
-                var $thumb = $(this), $preview = self.$preview, $remove = $thumb.find('.kv-file-remove');
-                $remove.removeAttr('disabled');
-                self._handler($remove, 'click', function () {
-                    var id = $thumb.attr('id'),
-                        out = self._raise('filesuccessremove', [id, $thumb.attr('data-fileindex')]);
-                    $h.cleanMemory($thumb);
-                    if (out === false) {
-                        return;
-                    }
-                    $thumb.fadeOut('slow', function () {
-                        $h.cleanZoomCache($preview.find('#zoom-' + id));
-                        $thumb.remove();
-                        if (!self.getFrames().length) {
-                            self.reset();
-                        }
-                    });
-                });
-            });
-        },
-        _checkAsyncComplete: function () {
-            var self = this, previewId, i;
-            for (i = 0; i < self.filestack.length; i++) {
-                if (self.filestack[i]) {
-                    previewId = self.previewInitId + "-" + i;
-                    if ($.inArray(previewId, self.uploadLog) === -1) {
-                        return false;
-                    }
-                }
-            }
-            return (self.uploadAsyncCount === self.uploadLog.length);
-        },
-        _uploadExtra: function (previewId, index) {
-            var self = this, data = self._getExtraData(previewId, index);
-            if (data.length === 0) {
-                return;
-            }
-            $.each(data, function (key, value) {
-                self.formdata.append(key, value);
-            });
-        },
-        _uploadSingle: function (i, isBatch) {
-            var self = this, total = self.getFileStack().length, formdata = new FormData(), outData,
-                previewId = self.previewInitId + "-" + i, $thumb, chkComplete, $btnUpload, $btnDelete,
-                hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData), uploadFailed,
-                $prog = $('#' + previewId).find('.file-thumb-progress'), fnBefore, fnSuccess, fnComplete, fnError,
-                updateUploadLog, params = {id: previewId, index: i};
-            self.formdata = formdata;
-            if (self.showPreview) {
-                $thumb = $('#' + previewId + ':not(.file-preview-initial)');
-                $btnUpload = $thumb.find('.kv-file-upload');
-                $btnDelete = $thumb.find('.kv-file-remove');
-                $prog.show();
-            }
-            if (total === 0 || !hasPostData || ($btnUpload && $btnUpload.hasClass('disabled')) || self._abort(params)) {
-                return;
-            }
-            updateUploadLog = function (i, previewId) {
-                if (!uploadFailed) {
-                    self.updateStack(i, undefined);
-                }
-                self.uploadLog.push(previewId);
-                if (self._checkAsyncComplete()) {
-                    self.fileBatchCompleted = true;
-                }
-            };
-            chkComplete = function () {
-                var u = self.uploadCache, $initThumbs, i, j, len = 0, data = self.cacheInitialPreview;
-                if (!self.fileBatchCompleted) {
-                    return;
-                }
-                if (data && data.content) {
-                    len = data.content.length;
-                }
-                setTimeout(function () {
-                    var triggerReset = self.getFileStack(true).length === 0;
-                    if (self.showPreview) {
-                        self.previewCache.set(u.content, u.config, u.tags, u.append);
-                        if (len) {
-                            for (i = 0; i < u.content.length; i++) {
-                                j = i + len;
-                                data.content[j] = u.content[i];
-                                //noinspection JSUnresolvedVariable
-                                if (data.config.length) {
-                                    data.config[j] = u.config[i];
-                                }
-                                if (data.tags.length) {
-                                    data.tags[j] = u.tags[i];
-                                }
-                            }
-                            self.initialPreview = $h.cleanArray(data.content);
-                            self.initialPreviewConfig = $h.cleanArray(data.config);
-                            self.initialPreviewThumbTags = $h.cleanArray(data.tags);
-                        } else {
-                            self.initialPreview = u.content;
-                            self.initialPreviewConfig = u.config;
-                            self.initialPreviewThumbTags = u.tags;
-                        }
-                        self.cacheInitialPreview = {};
-                        if (self.hasInitData) {
-                            self._initPreview();
-                            self._initPreviewActions();
-                        }
-                    }
-                    self.unlock(triggerReset);
-                    if (triggerReset) {
-                        self._clearFileInput();
-                    }
-                    $initThumbs = self.$preview.find('.file-preview-initial');
-                    if (self.uploadAsync && $initThumbs.length) {
-                        $h.addCss($initThumbs, $h.SORT_CSS);
-                        self._initSortable();
-                    }
-                    self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
-                    self.uploadCount = 0;
-                    self.uploadStatus = {};
-                    self.uploadLog = [];
-                    self._setProgress(101);
-                    self.ajaxAborted = false;
-                }, 100);
-            };
-            fnBefore = function (jqXHR) {
-                outData = self._getOutData(jqXHR);
-                self.fileBatchCompleted = false;
-                if (!isBatch) {
-                    self.ajaxAborted = false;
-                }
-                if (self.showPreview) {
-                    if (!$thumb.hasClass('file-preview-success')) {
-                        self._setThumbStatus($thumb, 'Loading');
-                        $h.addCss($thumb, 'file-uploading');
-                    }
-                    $btnUpload.attr('disabled', true);
-                    $btnDelete.attr('disabled', true);
-                }
-                if (!isBatch) {
-                    self.lock();
-                }
-                self._raise('filepreupload', [outData, previewId, i]);
-                $.extend(true, params, outData);
-                if (self._abort(params)) {
-                    jqXHR.abort();
-                    if (!isBatch) {
-                        self._setThumbStatus($thumb, 'New');
-                        $thumb.removeClass('file-uploading');
-                        $btnUpload.removeAttr('disabled');
-                        $btnDelete.removeAttr('disabled');
-                        self.unlock();
-                    }
-                    self._setProgressCancelled();
-                }
-            };
-            fnSuccess = function (data, textStatus, jqXHR) {
-                var pid = self.showPreview && $thumb.attr('id') ? $thumb.attr('id') : previewId;
-                outData = self._getOutData(jqXHR, data);
-                $.extend(true, params, outData);
-                setTimeout(function () {
-                    if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
-                        if (self.showPreview) {
-                            self._setThumbStatus($thumb, 'Success');
-                            $btnUpload.hide();
-                            self._initUploadSuccess(data, $thumb, isBatch);
-                            self._setProgress(101, $prog);
-                        }
-                        self._raise('fileuploaded', [outData, pid, i]);
-                        if (!isBatch) {
-                            self.updateStack(i, undefined);
-                        } else {
-                            updateUploadLog(i, pid);
-                        }
-                    } else {
-                        uploadFailed = true;
-                        self._showUploadError(data.error, params);
-                        self._setPreviewError($thumb, i, self.filestack[i], self.retryErrorUploads);
-                        if (!self.retryErrorUploads) {
-                            $btnUpload.hide();
-                        }
-                        if (isBatch) {
-                            updateUploadLog(i, pid);
-                        }
-                        self._setProgress(101, $('#' + pid).find('.file-thumb-progress'), self.msgUploadError);
-                    }
-                }, 100);
-            };
-            fnComplete = function () {
-                setTimeout(function () {
-                    if (self.showPreview) {
-                        $btnUpload.removeAttr('disabled');
-                        $btnDelete.removeAttr('disabled');
-                        $thumb.removeClass('file-uploading');
-                    }
-                    if (!isBatch) {
-                        self.unlock(false);
-                        self._clearFileInput();
-                    } else {
-                        chkComplete();
-                    }
-                    self._initSuccessThumbs();
-                }, 100);
-            };
-            fnError = function (jqXHR, textStatus, errorThrown) {
-                var op = self.ajaxOperations.uploadThumb,
-                    errMsg = self._parseError(op, jqXHR, errorThrown, (isBatch && self.filestack[i].name ? self.filestack[i].name : null));
-                uploadFailed = true;
-                setTimeout(function () {
-                    if (isBatch) {
-                        updateUploadLog(i, previewId);
-                    }
-                    self.uploadStatus[previewId] = 100;
-                    self._setPreviewError($thumb, i, self.filestack[i], self.retryErrorUploads);
-                    if (!self.retryErrorUploads) {
-                        $btnUpload.hide();
-                    }
-                    $.extend(true, params, self._getOutData(jqXHR));
-                    self._setProgress(101, $prog, self.msgAjaxProgressError.replace('{operation}', op));
-                    self._setProgress(101, $('#' + previewId).find('.file-thumb-progress'), self.msgUploadError);
-                    self._showUploadError(errMsg, params);
-                }, 100);
-            };
-            formdata.append(self.uploadFileAttr, self.filestack[i], self.filenames[i]);
-            formdata.append('file_id', i);
-            self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError, previewId, i);
-        },
-        _uploadBatch: function () {
-            var self = this, files = self.filestack, total = files.length, params = {}, fnBefore, fnSuccess, fnError,
-                fnComplete, hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData),
-                setAllUploaded;
-            self.formdata = new FormData();
-            if (total === 0 || !hasPostData || self._abort(params)) {
-                return;
-            }
-            setAllUploaded = function () {
-                $.each(files, function (key) {
-                    self.updateStack(key, undefined);
-                });
-                self._clearFileInput();
-            };
-            fnBefore = function (jqXHR) {
-                self.lock();
-                var outData = self._getOutData(jqXHR);
-                self.ajaxAborted = false;
-                if (self.showPreview) {
-                    self._getThumbs().each(function () {
-                        var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload'),
-                            $btnDelete = $thumb.find('.kv-file-remove');
-                        if (!$thumb.hasClass('file-preview-success')) {
-                            self._setThumbStatus($thumb, 'Loading');
-                            $h.addCss($thumb, 'file-uploading');
-                        }
-                        $btnUpload.attr('disabled', true);
-                        $btnDelete.attr('disabled', true);
-                    });
-                }
-                self._raise('filebatchpreupload', [outData]);
-                if (self._abort(outData)) {
-                    jqXHR.abort();
-                    self._getThumbs().each(function () {
-                        var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload'),
-                            $btnDelete = $thumb.find('.kv-file-remove');
-                        if ($thumb.hasClass('file-preview-loading')) {
-                            self._setThumbStatus($thumb, 'New');
-                            $thumb.removeClass('file-uploading');
-                        }
-                        $btnUpload.removeAttr('disabled');
-                        $btnDelete.removeAttr('disabled');
-                    });
-                    self._setProgressCancelled();
-                }
-            };
-            fnSuccess = function (data, textStatus, jqXHR) {
-                /** @namespace data.errorkeys */
-                var outData = self._getOutData(jqXHR, data), key = 0,
-                    $thumbs = self._getThumbs(':not(.file-preview-success)'),
-                    keys = $h.isEmpty(data) || $h.isEmpty(data.errorkeys) ? [] : data.errorkeys;
-
-                if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
-                    self._raise('filebatchuploadsuccess', [outData]);
-                    setAllUploaded();
-                    if (self.showPreview) {
-                        $thumbs.each(function () {
-                            var $thumb = $(this);
-                            self._setThumbStatus($thumb, 'Success');
-                            $thumb.removeClass('file-uploading');
-                            $thumb.find('.kv-file-upload').hide().removeAttr('disabled');
-                        });
-                        self._initUploadSuccess(data);
-                    } else {
-                        self.reset();
-                    }
-                    self._setProgress(101);
-                } else {
-                    if (self.showPreview) {
-                        $thumbs.each(function () {
-                            var $thumb = $(this), i = $thumb.attr('data-fileindex');
-                            $thumb.removeClass('file-uploading');
-                            $thumb.find('.kv-file-upload').removeAttr('disabled');
-                            $thumb.find('.kv-file-remove').removeAttr('disabled');
-                            if (keys.length === 0 || $.inArray(key, keys) !== -1) {
-                                self._setPreviewError($thumb, i, self.filestack[i], self.retryErrorUploads);
-                                if (!self.retryErrorUploads) {
-                                    $thumb.find('.kv-file-upload').hide();
-                                    self.updateStack(i, undefined);
-                                }
-                            } else {
-                                $thumb.find('.kv-file-upload').hide();
-                                self._setThumbStatus($thumb, 'Success');
-                                self.updateStack(i, undefined);
-                            }
-                            if (!$thumb.hasClass('file-preview-error') || self.retryErrorUploads) {
-                                key++;
-                            }
-                        });
-                        self._initUploadSuccess(data);
-                    }
-                    self._showUploadError(data.error, outData, 'filebatchuploaderror');
-                    self._setProgress(101, self.$progress, self.msgUploadError);
-                }
-            };
-            fnComplete = function () {
-                self.unlock();
-                self._initSuccessThumbs();
-                self._clearFileInput();
-                self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
-            };
-            fnError = function (jqXHR, textStatus, errorThrown) {
-                var outData = self._getOutData(jqXHR), op = self.ajaxOperations.uploadBatch,
-                    errMsg = self._parseError(op, jqXHR, errorThrown);
-                self._showUploadError(errMsg, outData, 'filebatchuploaderror');
-                self.uploadFileCount = total - 1;
-                if (!self.showPreview) {
-                    return;
-                }
-                self._getThumbs().each(function () {
-                    var $thumb = $(this), key = $thumb.attr('data-fileindex');
-                    $thumb.removeClass('file-uploading');
-                    if (self.filestack[key] !== undefined) {
-                        self._setPreviewError($thumb);
-                    }
-                });
-                self._getThumbs().removeClass('file-uploading');
-                self._getThumbs(' .kv-file-upload').removeAttr('disabled');
-                self._getThumbs(' .kv-file-delete').removeAttr('disabled');
-                self._setProgress(101, self.$progress, self.msgAjaxProgressError.replace('{operation}', op));
-            };
-            $.each(files, function (key, data) {
-                if (!$h.isEmpty(files[key])) {
-                    self.formdata.append(self.uploadFileAttr, data, self.filenames[key]);
-                }
-            });
-            self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
-        },
-        _uploadExtraOnly: function () {
-            var self = this, params = {}, fnBefore, fnSuccess, fnComplete, fnError;
-            self.formdata = new FormData();
-            if (self._abort(params)) {
-                return;
-            }
-            fnBefore = function (jqXHR) {
-                self.lock();
-                var outData = self._getOutData(jqXHR);
-                self._raise('filebatchpreupload', [outData]);
-                self._setProgress(50);
-                params.data = outData;
-                params.xhr = jqXHR;
-                if (self._abort(params)) {
-                    jqXHR.abort();
-                    self._setProgressCancelled();
-                }
-            };
-            fnSuccess = function (data, textStatus, jqXHR) {
-                var outData = self._getOutData(jqXHR, data);
-                if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
-                    self._raise('filebatchuploadsuccess', [outData]);
-                    self._clearFileInput();
-                    self._initUploadSuccess(data);
-                    self._setProgress(101);
-                } else {
-                    self._showUploadError(data.error, outData, 'filebatchuploaderror');
-                }
-            };
-            fnComplete = function () {
-                self.unlock();
-                self._clearFileInput();
-                self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
-            };
-            fnError = function (jqXHR, textStatus, errorThrown) {
-                var outData = self._getOutData(jqXHR), op = self.ajaxOperations.uploadExtra,
-                    errMsg = self._parseError(op, jqXHR, errorThrown);
-                params.data = outData;
-                self._showUploadError(errMsg, outData, 'filebatchuploaderror');
-                self._setProgress(101, self.$progress, self.msgAjaxProgressError.replace('{operation}', op));
-            };
-            self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
-        },
-        _deleteFileIndex: function ($frame) {
-            var self = this, ind = $frame.attr('data-fileindex'), rev = self.reversePreviewOrder;
-            if (ind.substring(0, 5) === 'init_') {
-                ind = parseInt(ind.replace('init_', ''));
-                self.initialPreview = $h.spliceArray(self.initialPreview, ind, rev);
-                self.initialPreviewConfig = $h.spliceArray(self.initialPreviewConfig, ind, rev);
-                self.initialPreviewThumbTags = $h.spliceArray(self.initialPreviewThumbTags, ind, rev);
-                self.getFrames().each(function () {
-                    var $nFrame = $(this), nInd = $nFrame.attr('data-fileindex');
-                    if (nInd.substring(0, 5) === 'init_') {
-                        nInd = parseInt(nInd.replace('init_', ''));
-                        if (nInd > ind) {
-                            nInd--;
-                            $nFrame.attr('data-fileindex', 'init_' + nInd);
-                        }
-                    }
-                });
-                if (self.uploadAsync) {
-                    self.cacheInitialPreview = self.getPreview();
-                }
-            }
-        },
-        _initFileActions: function () {
-            var self = this, $preview = self.$preview;
-            if (!self.showPreview) {
-                return;
-            }
-            self._initZoomButton();
-            self.getFrames(' .kv-file-remove').each(function () {
-                var $el = $(this), $frame = $el.closest($h.FRAMES), hasError, id = $frame.attr('id'),
-                    ind = $frame.attr('data-fileindex'), n, cap, status;
-                self._handler($el, 'click', function () {
-                    status = self._raise('filepreremove', [id, ind]);
-                    if (status === false || !self._validateMinCount()) {
-                        return false;
-                    }
-                    hasError = $frame.hasClass('file-preview-error');
-                    $h.cleanMemory($frame);
-                    $frame.fadeOut('slow', function () {
-                        $h.cleanZoomCache($preview.find('#zoom-' + id));
-                        self.updateStack(ind, undefined);
-                        self._clearObjects($frame);
-                        $frame.remove();
-                        if (id && hasError) {
-                            self.$errorContainer.find('li[data-file-id="' + id + '"]').fadeOut('fast', function () {
-                                $(this).remove();
-                                if (!self._errorsExist()) {
-                                    self._resetErrors();
-                                }
-                            });
-                        }
-                        self._clearFileInput();
-                        var filestack = self.getFileStack(true), chk = self.previewCache.count(),
-                            len = filestack.length, hasThumb = self.showPreview && self.getFrames().length;
-                        if (len === 0 && chk === 0 && !hasThumb) {
-                            self.reset();
-                        } else {
-                            n = chk + len;
-                            cap = n > 1 ? self._getMsgSelected(n) : (filestack[0] ? self._getFileNames()[0] : '');
-                            self._setCaption(cap);
-                        }
-                        self._raise('fileremoved', [id, ind]);
-                    });
-                });
-            });
-            self.getFrames(' .kv-file-upload').each(function () {
-                var $el = $(this);
-                self._handler($el, 'click', function () {
-                    var $frame = $el.closest($h.FRAMES), ind = $frame.attr('data-fileindex');
-                    self.$progress.hide();
-                    if ($frame.hasClass('file-preview-error') && !self.retryErrorUploads) {
-                        return;
-                    }
-                    self._uploadSingle(ind, false);
-                });
-            });
-        },
-        _initPreviewActions: function () {
-            var self = this, $preview = self.$preview, deleteExtraData = self.deleteExtraData || {},
-                btnRemove = $h.FRAMES + ' .kv-file-remove', settings = self.fileActionSettings,
-                origClass = settings.removeClass, errClass = settings.removeErrorClass,
-                resetProgress = function () {
-                    var hasFiles = self.isAjaxUpload ? self.previewCache.count() : self._inputFileCount();
-                    if (!$preview.find($h.FRAMES).length && !hasFiles) {
-                        self._setCaption('');
-                        self.reset();
-                        self.initialCaption = '';
-                    }
-                };
-            self._initZoomButton();
-            $preview.find(btnRemove).each(function () {
-                var $el = $(this), vUrl = $el.data('url') || self.deleteUrl, vKey = $el.data('key'),
-                    fnBefore, fnSuccess, fnError;
-                if ($h.isEmpty(vUrl) || vKey === undefined) {
-                    return;
-                }
-                var $frame = $el.closest($h.FRAMES), cache = self.previewCache.data,
-                    settings, params, index = $frame.attr('data-fileindex'), config, extraData;
-                index = parseInt(index.replace('init_', ''));
-                config = $h.isEmpty(cache.config) && $h.isEmpty(cache.config[index]) ? null : cache.config[index];
-                extraData = $h.isEmpty(config) || $h.isEmpty(config.extra) ? deleteExtraData : config.extra;
-                if (typeof extraData === "function") {
-                    extraData = extraData();
-                }
-                params = {id: $el.attr('id'), key: vKey, extra: extraData};
-                fnBefore = function (jqXHR) {
-                    self.ajaxAborted = false;
-                    self._raise('filepredelete', [vKey, jqXHR, extraData]);
-                    if (self._abort()) {
-                        jqXHR.abort();
-                    } else {
-                        $el.removeClass(errClass);
-                        $h.addCss($frame, 'file-uploading');
-                        $h.addCss($el, 'disabled ' + origClass);
-                    }
-                };
-                fnSuccess = function (data, textStatus, jqXHR) {
-                    var n, cap;
-                    if (!$h.isEmpty(data) && !$h.isEmpty(data.error)) {
-                        params.jqXHR = jqXHR;
-                        params.response = data;
-                        self._showError(data.error, params, 'filedeleteerror');
-                        $frame.removeClass('file-uploading');
-                        $el.removeClass('disabled ' + origClass).addClass(errClass);
-                        resetProgress();
-                        return;
-                    }
-                    $frame.removeClass('file-uploading').addClass('file-deleted');
-                    $frame.fadeOut('slow', function () {
-                        index = parseInt(($frame.attr('data-fileindex')).replace('init_', ''));
-                        self.previewCache.unset(index);
-                        self._deleteFileIndex($frame);
-                        n = self.previewCache.count();
-                        cap = n > 0 ? self._getMsgSelected(n) : '';
-                        self._setCaption(cap);
-                        self._raise('filedeleted', [vKey, jqXHR, extraData]);
-                        $h.cleanZoomCache($preview.find('#zoom-' + $frame.attr('id')));
-                        self._clearObjects($frame);
-                        $frame.remove();
-                        resetProgress();
-                    });
-                };
-                fnError = function (jqXHR, textStatus, errorThrown) {
-                    var op = self.ajaxOperations.deleteThumb, errMsg = self._parseError(op, jqXHR, errorThrown);
-                    params.jqXHR = jqXHR;
-                    params.response = {};
-                    self._showError(errMsg, params, 'filedeleteerror');
-                    $frame.removeClass('file-uploading');
-                    $el.removeClass('disabled ' + origClass).addClass(errClass);
-                    resetProgress();
-                };
-                self._initAjaxSettings();
-                self._mergeAjaxCallback('beforeSend', fnBefore, 'delete');
-                self._mergeAjaxCallback('success', fnSuccess, 'delete');
-                self._mergeAjaxCallback('error', fnError, 'delete');
-                settings = $.extend(true, {}, {
-                    url: vUrl,
-                    type: 'POST',
-                    dataType: 'json',
-                    data: $.extend(true, {}, {key: vKey}, extraData)
-                }, self._ajaxDeleteSettings);
-                self._handler($el, 'click', function () {
-                    if (!self._validateMinCount()) {
-                        return false;
-                    }
-                    self.ajaxAborted = false;
-                    self._raise('filebeforedelete', [vKey, extraData]);
-                    //noinspection JSUnresolvedVariable,JSHint
-                    if (self.ajaxAborted instanceof Promise) {
-                        self.ajaxAborted.then(function (result) {
-                            if (!result) {
-                                $.ajax(settings);
-                            }
-                        });
-                    } else {
-                        if (!self.ajaxAborted) {
-                            $.ajax(settings);
-                        }
-                    }
-                });
-            });
-        },
-        _hideFileIcon: function () {
-            var self = this;
-            if (self.overwriteInitial) {
-                self.$captionContainer.removeClass('icon-visible');
-            }
-        },
-        _showFileIcon: function () {
-            var self = this;
-            $h.addCss(self.$captionContainer, 'icon-visible');
-        },
-        _getSize: function (bytes) {
-            var self = this, size = parseFloat(bytes), i, func = self.fileSizeGetter, sizes, out;
-            if (!$.isNumeric(bytes) || !$.isNumeric(size)) {
-                return '';
-            }
-            if (typeof func === 'function') {
-                out = func(size);
-            } else {
-                if (size === 0) {
-                    out = '0.00 B';
-                } else {
-                    i = Math.floor(Math.log(size) / Math.log(1024));
-                    sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
-                    out = (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + sizes[i];
-                }
-            }
-            return self._getLayoutTemplate('size').replace('{sizeText}', out);
-        },
-        _generatePreviewTemplate: function (cat, data, fname, ftype, previewId, isError, size, frameClass, foot, ind, templ) {
-            var self = this, caption = self.slug(fname), prevContent, zoomContent = '', styleAttribs = '',
-                screenW = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
-                config = screenW < 400 ? (self.previewSettingsSmall[cat] || self.defaults.previewSettingsSmall[cat]) :
-                    (self.previewSettings[cat] || self.defaults.previewSettings[cat]),
-                footer = foot || self._renderFileFooter(caption, size, 'auto', isError),
-                hasIconSetting = self._getPreviewIcon(fname), typeCss = 'type-default',
-                forcePrevIcon = hasIconSetting && self.preferIconicPreview,
-                forceZoomIcon = hasIconSetting && self.preferIconicZoomPreview, getContent;
-            if (config) {
-                $.each(config, function (key, val) {
-                    styleAttribs += key + ':' + val + ';';
-                });
-            }
-            getContent = function (c, d, zoom, frameCss) {
-                var id = zoom ? 'zoom-' + previewId : previewId, tmplt = self._getPreviewTemplate(c),
-                    css = (frameClass || '') + ' ' + frameCss;
-                if (self.frameClass) {
-                    css = self.frameClass + ' ' + css;
-                }
-                if (zoom) {
-                    css = css.replace(' ' + $h.SORT_CSS, '');
-                }
-                tmplt = self._parseFilePreviewIcon(tmplt, fname);
-                if (c === 'text') {
-                    d = $h.htmlEncode(d);
-                }
-                if (cat === 'object' && !ftype) {
-                    $.each(self.defaults.fileTypeSettings, function (key, func) {
-                        if (key === 'object' || key === 'other') {
-                            return;
-                        }
-                        if (func(fname, ftype)) {
-                            typeCss = 'type-' + key;
-                        }
-                    });
-                }
-                return tmplt.setTokens({
-                    'previewId': id,
-                    'caption': caption,
-                    'frameClass': css,
-                    'type': ftype,
-                    'fileindex': ind,
-                    'typeCss': typeCss,
-                    'footer': footer,
-                    'data': d,
-                    'template': templ || cat,
-                    'style': styleAttribs ? 'style="' + styleAttribs + '"' : ''
-                });
-            };
-            ind = ind || previewId.slice(previewId.lastIndexOf('-') + 1);
-            if (self.fileActionSettings.showZoom) {
-                zoomContent = getContent((forceZoomIcon ? 'other' : cat), data, true, 'kv-zoom-thumb');
-            }
-            zoomContent = '\n' + self._getLayoutTemplate('zoomCache').replace('{zoomContent}', zoomContent);
-            prevContent = getContent((forcePrevIcon ? 'other' : cat), data, false, 'kv-preview-thumb');
-            return prevContent + zoomContent;
-        },
-        _addToPreview: function ($preview, content) {
-            var self = this;
-            return self.reversePreviewOrder ? $preview.prepend(content) : $preview.append(content);
-        },
-        _previewDefault: function (file, previewId, isDisabled) {
-            var self = this, $preview = self.$preview;
-            if (!self.showPreview) {
-                return;
-            }
-            var fname = file ? file.name : '', ftype = file ? file.type : '', content, size = file.size || 0,
-                caption = self.slug(fname), isError = isDisabled === true && !self.isAjaxUpload,
-                data = $h.objUrl.createObjectURL(file);
-            self._clearDefaultPreview();
-            content = self._generatePreviewTemplate('other', data, fname, ftype, previewId, isError, size);
-            self._addToPreview($preview, content);
-            self._setThumbAttr(previewId, caption, size);
-            if (isDisabled === true && self.isAjaxUpload) {
-                self._setThumbStatus($('#' + previewId), 'Error');
-            }
-        },
-        _previewFile: function (i, file, theFile, previewId, data, fileInfo) {
-            if (!this.showPreview) {
-                return;
-            }
-            var self = this, fname = file ? file.name : '', ftype = fileInfo.type, caption = fileInfo.name,
-                cat = self._parseFileType(ftype, fname), types = self.allowedPreviewTypes, content,
-                mimes = self.allowedPreviewMimeTypes, $preview = self.$preview, fsize = file.size || 0,
-                chkTypes = types && types.indexOf(cat) >= 0, chkMimes = mimes && mimes.indexOf(ftype) !== -1,
-                iData = (cat === 'text' || cat === 'html' || cat === 'image') ? theFile.target.result : data;
-            /** @namespace window.DOMPurify */
-            if (cat === 'html' && self.purifyHtml && window.DOMPurify) {
-                iData = window.DOMPurify.sanitize(iData);
-            }
-            if (chkTypes || chkMimes) {
-                content = self._generatePreviewTemplate(cat, iData, fname, ftype, previewId, false, fsize);
-                self._clearDefaultPreview();
-                self._addToPreview($preview, content);
-                var $img = $preview.find('#' + previewId + ' img');
-                if ($img.length && self.autoOrientImage) {
-                    $h.validateOrientation(file, function (value) {
-                        if (!value) {
-                            self._validateImage(previewId, caption, ftype, fsize, iData);
-                            return;
-                        }
-                        var $zoomImg = $preview.find('#zoom-' + previewId + ' img'), css = 'rotate-' + value;
-                        if (value > 4) {
-                            css += ($img.width() > $img.height() ? ' is-portrait-gt4' : ' is-landscape-gt4');
-                        }
-                        $h.addCss($img, css);
-                        $h.addCss($zoomImg, css);
-                        self._raise('fileimageoriented', {'$img': $img, 'file': file});
-                        self._validateImage(previewId, caption, ftype, fsize, iData);
-                        $h.adjustOrientedImage($img);
-                    });
-                } else {
-                    self._validateImage(previewId, caption, ftype, fsize, iData);
-                }
-            } else {
-                self._previewDefault(file, previewId);
-            }
-            self._setThumbAttr(previewId, caption, fsize);
-            self._initSortable();
-        },
-        _setThumbAttr: function (id, caption, size) {
-            var self = this, $frame = $('#' + id);
-            if ($frame.length) {
-                size = size && size > 0 ? self._getSize(size) : '';
-                $frame.data({'caption': caption, 'size': size});
-            }
-        },
-        _setInitThumbAttr: function () {
-            var self = this, data = self.previewCache.data, len = self.previewCache.count(), config,
-                caption, size, previewId;
-            if (len === 0) {
-                return;
-            }
-            for (var i = 0; i < len; i++) {
-                config = data.config[i];
-                previewId = self.previewInitId + '-' + 'init_' + i;
-                caption = $h.ifSet('caption', config, $h.ifSet('filename', config));
-                size = $h.ifSet('size', config);
-                self._setThumbAttr(previewId, caption, size);
-            }
-        },
-        _slugDefault: function (text) {
-            return $h.isEmpty(text) ? '' : String(text).replace(/[\[\]\/\{}:;#%=\(\)\*\+\?\\\^\$\|<>&"']/g, '_');
-        },
-        _updateFileDetails: function (numFiles) {
-            var self = this, $el = self.$element, fileStack = self.getFileStack(),
-                name = ($h.isIE(9) && $h.findFileName($el.val())) ||
-                    ($el[0].files[0] && $el[0].files[0].name) || (fileStack.length && fileStack[0].name) || '',
-                label = self.slug(name), n = self.isAjaxUpload ? fileStack.length : numFiles,
-                nFiles = self.previewCache.count() + n, log = n === 1 ? label : self._getMsgSelected(nFiles);
-            if (self.isError) {
-                self.$previewContainer.removeClass('file-thumb-loading');
-                self.$previewStatus.html('');
-                self.$captionContainer.removeClass('icon-visible');
-            } else {
-                self._showFileIcon();
-            }
-            self._setCaption(log, self.isError);
-            self.$container.removeClass('file-input-new file-input-ajax-new');
-            if (arguments.length === 1) {
-                self._raise('fileselect', [numFiles, label]);
-            }
-            if (self.previewCache.count()) {
-                self._initPreviewActions();
-            }
-        },
-        _setThumbStatus: function ($thumb, status) {
-            var self = this;
-            if (!self.showPreview) {
-                return;
-            }
-            var icon = 'indicator' + status, msg = icon + 'Title',
-                css = 'file-preview-' + status.toLowerCase(),
-                $indicator = $thumb.find('.file-upload-indicator'),
-                config = self.fileActionSettings;
-            $thumb.removeClass('file-preview-success file-preview-error file-preview-loading');
-            if (status === 'Success') {
-                $thumb.find('.file-drag-handle').remove();
-            }
-            $indicator.html(config[icon]);
-            $indicator.attr('title', config[msg]);
-            $thumb.addClass(css);
-            if (status === 'Error' && !self.retryErrorUploads) {
-                $thumb.find('.kv-file-upload').attr('disabled', true);
-            }
-        },
-        _setProgressCancelled: function () {
-            var self = this;
-            self._setProgress(101, self.$progress, self.msgCancelled);
-        },
-        _setProgress: function (p, $el, error) {
-            var self = this, pct = Math.min(p, 100), out, pctLimit = self.progressUploadThreshold,
-                t = p <= 100 ? self.progressTemplate : self.progressCompleteTemplate,
-                template = pct < 100 ? self.progressTemplate : (error ? self.progressErrorTemplate : t);
-            $el = $el || self.$progress;
-            if (!$h.isEmpty(template)) {
-                if (pctLimit && pct > pctLimit && p <= 100) {
-                    out = template.setTokens({'percent': pctLimit, 'status': self.msgUploadThreshold});
-                } else {
-                    out = template.setTokens({'percent': pct, 'status': (p > 100 ? self.msgUploadEnd : pct + '%')});
-                }
-                $el.html(out);
-                if (error) {
-                    $el.find('[role="progressbar"]').html(error);
-                }
-            }
-        },
-        _setFileDropZoneTitle: function () {
-            var self = this, $zone = self.$container.find('.file-drop-zone'), title = self.dropZoneTitle, strFiles;
-            if (self.isClickable) {
-                strFiles = $h.isEmpty(self.$element.attr('multiple')) ? self.fileSingle : self.filePlural;
-                title += self.dropZoneClickTitle.replace('{files}', strFiles);
-            }
-            $zone.find('.' + self.dropZoneTitleClass).remove();
-            if (!self.showPreview || $zone.length === 0 || self.getFileStack().length > 0 || !self.dropZoneEnabled ||
-                (!self.isAjaxUpload && self.$element.files)) {
-                return;
-            }
-            if ($zone.find($h.FRAMES).length === 0 && $h.isEmpty(self.defaultPreviewContent)) {
-                $zone.prepend('<div class="' + self.dropZoneTitleClass + '">' + title + '</div>');
-            }
-            self.$container.removeClass('file-input-new');
-            $h.addCss(self.$container, 'file-input-ajax-new');
-        },
-        _setAsyncUploadStatus: function (previewId, pct, total) {
-            var self = this, sum = 0;
-            self._setProgress(pct, $('#' + previewId).find('.file-thumb-progress'));
-            self.uploadStatus[previewId] = pct;
-            $.each(self.uploadStatus, function (key, value) {
-                sum += value;
-            });
-            self._setProgress(Math.floor(sum / total));
-        },
-        _validateMinCount: function () {
-            var self = this, len = self.isAjaxUpload ? self.getFileStack().length : self._inputFileCount();
-            if (self.validateInitialCount && self.minFileCount > 0 && self._getFileCount(len - 1) < self.minFileCount) {
-                self._noFilesError({});
-                return false;
-            }
-            return true;
-        },
-        _getFileCount: function (fileCount) {
-            var self = this, addCount = 0;
-            if (self.validateInitialCount && !self.overwriteInitial) {
-                addCount = self.previewCache.count();
-                fileCount += addCount;
-            }
-            return fileCount;
-        },
-        _getFileId: function (file) {
-            var self = this, custom = self.generateFileId, relativePath;
-            if (typeof custom === 'function') {
-                return custom(file, event);
-            }
-            if (!file) {
-                return null;
-            }
-            /** @namespace file.webkitRelativePath */
-            relativePath = String(file.webkitRelativePath || file.fileName || file.name || null);
-            if (!relativePath) {
-                return null;
-            }
-            return (file.size + '-' + relativePath.replace(/[^0-9a-zA-Z_-]/img, ''));
-        },
-        _getFileName: function (file) {
-            return file && file.name ? this.slug(file.name) : undefined;
-        },
-        _getFileIds: function (skipNull) {
-            var self = this;
-            return self.fileids.filter(function (n) {
-                return (skipNull ? n !== undefined : n !== undefined && n !== null);
-            });
-        },
-        _getFileNames: function (skipNull) {
-            var self = this;
-            return self.filenames.filter(function (n) {
-                return (skipNull ? n !== undefined : n !== undefined && n !== null);
-            });
-        },
-        _setPreviewError: function ($thumb, i, val, repeat) {
-            var self = this;
-            if (i !== undefined) {
-                self.updateStack(i, val);
-            }
-            if (!self.showPreview) {
-                return;
-            }
-            if (self.removeFromPreviewOnError && !repeat) {
-                $thumb.remove();
-                return;
-            } else {
-                self._setThumbStatus($thumb, 'Error');
-            }
-            self._refreshUploadButton($thumb, repeat);
-        },
-        _refreshUploadButton: function ($thumb, repeat) {
-            var self = this, $btn = $thumb.find('.kv-file-upload'), cfg = self.fileActionSettings,
-                icon = cfg.uploadIcon, title = cfg.uploadTitle;
-            if (!$btn.length) {
-                return;
-            }
-            if (repeat) {
-                icon = cfg.uploadRetryIcon;
-                title = cfg.uploadRetryTitle;
-            }
-            $btn.attr('title', title).html(icon);
-        },
-        _checkDimensions: function (i, chk, $img, $thumb, fname, type, params) {
-            var self = this, msg, dim, tag = chk === 'Small' ? 'min' : 'max', limit = self[tag + 'Image' + type],
-                $imgEl, isValid;
-            if ($h.isEmpty(limit) || !$img.length) {
-                return;
-            }
-            $imgEl = $img[0];
-            dim = (type === 'Width') ? $imgEl.naturalWidth || $imgEl.width : $imgEl.naturalHeight || $imgEl.height;
-            isValid = chk === 'Small' ? dim >= limit : dim <= limit;
-            if (isValid) {
-                return;
-            }
-            msg = self['msgImage' + type + chk].setTokens({'name': fname, 'size': limit});
-            self._showUploadError(msg, params);
-            self._setPreviewError($thumb, i, null);
-        },
-        _validateImage: function (previewId, fname, ftype, fsize, iData) {
-            var self = this, $preview = self.$preview, params, w1, w2, $thumb = $preview.find("#" + previewId),
-                i = $thumb.attr('data-fileindex'), $img = $thumb.find('img'), exifObject;
-            fname = fname || 'Untitled';
-            $img.one('load', function () {
-                w1 = $thumb.width();
-                w2 = $preview.width();
-                if (w1 > w2) {
-                    $img.css('width', '100%');
-                }
-                params = {ind: i, id: previewId};
-                self._checkDimensions(i, 'Small', $img, $thumb, fname, 'Width', params);
-                self._checkDimensions(i, 'Small', $img, $thumb, fname, 'Height', params);
-                if (!self.resizeImage) {
-                    self._checkDimensions(i, 'Large', $img, $thumb, fname, 'Width', params);
-                    self._checkDimensions(i, 'Large', $img, $thumb, fname, 'Height', params);
-                }
-                self._raise('fileimageloaded', [previewId]);
-                try {
-                    exifObject = window.piexif ? window.piexif.load(iData) : null;
-                } catch (err) {
-                    exifObject = null;
-                }
-                self.loadedImages.push({
-                    ind: i,
-                    img: $img,
-                    thumb: $thumb,
-                    pid: previewId,
-                    typ: ftype,
-                    siz: fsize,
-                    validated: false,
-                    imgData: iData,
-                    exifObj: exifObject
-                });
-                $thumb.data('exif', exifObject);
-                self._validateAllImages();
-            }).one('error', function () {
-                self._raise('fileimageloaderror', [previewId]);
-            }).each(function () {
-                if (this.complete) {
-                    $(this).trigger('load');
-                } else {
-                    if (this.error) {
-                        $(this).trigger('error');
-                    }
-                }
-            });
-        },
-        _validateAllImages: function () {
-            var self = this, i, counter = {val: 0}, numImgs = self.loadedImages.length, config,
-                fsize, minSize = self.resizeIfSizeMoreThan;
-            if (numImgs !== self.totalImagesCount) {
-                return;
-            }
-            self._raise('fileimagesloaded');
-            if (!self.resizeImage) {
-                return;
-            }
-            for (i = 0; i < self.loadedImages.length; i++) {
-                config = self.loadedImages[i];
-                if (config.validated) {
-                    continue;
-                }
-                fsize = config.siz;
-                if (fsize && fsize > minSize * 1000) {
-                    self._getResizedImage(config, counter, numImgs);
-                }
-                self.loadedImages[i].validated = true;
-            }
-        },
-        _getResizedImage: function (config, counter, numImgs) {
-            var self = this, img = $(config.img)[0], width = img.naturalWidth, height = img.naturalHeight, blob,
-                ratio = 1, maxWidth = self.maxImageWidth || width, maxHeight = self.maxImageHeight || height,
-                isValidImage = !!(width && height), chkWidth, chkHeight, canvas = self.imageCanvas, dataURI,
-                context = self.imageCanvasContext, type = config.typ, pid = config.pid, ind = config.ind,
-                $thumb = config.thumb, throwError, msg, exifObj = config.exifObj, exifStr;
-            throwError = function (msg, params, ev) {
-                if (self.isAjaxUpload) {
-                    self._showUploadError(msg, params, ev);
-                } else {
-                    self._showError(msg, params, ev);
-                }
-                self._setPreviewError($thumb, ind);
-            };
-            if (!self.filestack[ind] || !isValidImage || (width <= maxWidth && height <= maxHeight)) {
-                if (isValidImage && self.filestack[ind]) {
-                    self._raise('fileimageresized', [pid, ind]);
-                }
-                counter.val++;
-                if (counter.val === numImgs) {
-                    self._raise('fileimagesresized');
-                }
-                if (!isValidImage) {
-                    throwError(self.msgImageResizeError, {id: pid, 'index': ind}, 'fileimageresizeerror');
-                    return;
-                }
-            }
-            type = type || self.resizeDefaultImageType;
-            chkWidth = width > maxWidth;
-            chkHeight = height > maxHeight;
-            if (self.resizePreference === 'width') {
-                ratio = chkWidth ? maxWidth / width : (chkHeight ? maxHeight / height : 1);
-            } else {
-                ratio = chkHeight ? maxHeight / height : (chkWidth ? maxWidth / width : 1);
-            }
-            self._resetCanvas();
-            width *= ratio;
-            height *= ratio;
-            canvas.width = width;
-            canvas.height = height;
-            try {
-                context.drawImage(img, 0, 0, width, height);
-                dataURI = canvas.toDataURL(type, self.resizeQuality);
-                if (exifObj) {
-                    exifStr = window.piexif.dump(exifObj);
-                    dataURI = window.piexif.insert(exifStr, dataURI);
-                }
-                blob = $h.dataURI2Blob(dataURI);
-                self.filestack[ind] = blob;
-                self._raise('fileimageresized', [pid, ind]);
-                counter.val++;
-                if (counter.val === numImgs) {
-                    self._raise('fileimagesresized', [undefined, undefined]);
-                }
-                if (!(blob instanceof Blob)) {
-                    throwError(self.msgImageResizeError, {id: pid, 'index': ind}, 'fileimageresizeerror');
-                }
-            }
-            catch (err) {
-                counter.val++;
-                if (counter.val === numImgs) {
-                    self._raise('fileimagesresized', [undefined, undefined]);
-                }
-                msg = self.msgImageResizeException.replace('{errors}', err.message);
-                throwError(msg, {id: pid, 'index': ind}, 'fileimageresizeexception');
-            }
-        },
-        _initBrowse: function ($container) {
-            var self = this, $el = self.$element;
-            if (self.showBrowse) {
-                self.$btnFile = $container.find('.btn-file').append($el);
-            } else {
-                $el.appendTo($container).attr('tabindex', -1);
-                $h.addCss($el, 'file-no-browse');
-            }
-        },
-        _initClickable: function () {
-            var self = this, $zone;
-            if (!self.isClickable) {
-                return;
-            }
-            $zone = self.isAjaxUpload ? self.$dropZone : self.$preview.find('.file-default-preview');
-            $h.addCss($zone, 'clickable');
-            $zone.attr('tabindex', -1);
-            self._handler($zone, 'click', function (e) {
-                var $tar = $(e.target), $el = self.$element;
-                if (!$(self.elErrorContainer + ':visible').length &&
-                    (!$tar.parents('.file-preview-thumbnails').length || $tar.parents('.file-default-preview').length)) {
-                    self.$element.data('zoneClicked', true).trigger('click');
-                    $zone.blur();
-                }
-            });
-        },
-        _initCaption: function () {
-            var self = this, cap = self.initialCaption || '';
-            if (self.overwriteInitial || $h.isEmpty(cap)) {
-                self.$caption.val('');
-                return false;
-            }
-            self._setCaption(cap);
-            return true;
-        },
-        _setCaption: function (content, isError) {
-            var self = this, title, out, icon, n, cap, stack = self.getFileStack();
-            if (!self.$caption.length) {
-                return;
-            }
-            self.$captionContainer.removeClass('icon-visible');
-            if (isError) {
-                title = $('<div>' + self.msgValidationError + '</div>').text();
-                n = stack.length;
-                if (n) {
-                    cap = n === 1 && stack[0] ? self._getFileNames()[0] : self._getMsgSelected(n);
-                } else {
-                    cap = self._getMsgSelected(self.msgNo);
-                }
-                out = $h.isEmpty(content) ? cap : content;
-                icon = '<span class="' + self.msgValidationErrorClass + '">' + self.msgValidationErrorIcon + '</span>';
-            } else {
-                if ($h.isEmpty(content)) {
-                    return;
-                }
-                title = $('<div>' + content + '</div>').text();
-                out = title;
-                icon = self._getLayoutTemplate('fileIcon');
-            }
-            self.$captionContainer.addClass('icon-visible');
-            self.$caption.attr('title', title).val(out);
-            self.$captionIcon.html(icon);
-        },
-        _createContainer: function () {
-            var self = this, attribs = {"class": 'file-input file-input-new' + (self.rtl ? ' kv-rtl' : '')},
-                $container = $(document.createElement("div")).attr(attribs).html(self._renderMain());
-            $container.insertBefore(self.$element);
-            self._initBrowse($container);
-            if (self.theme) {
-                $container.addClass('theme-' + self.theme);
-            }
-            return $container;
-        },
-        _refreshContainer: function () {
-            var self = this, $container = self.$container, $el = self.$element;
-            $el.insertAfter($container);
-            $container.html(self._renderMain());
-            self._initBrowse($container);
-            self._validateDisabled();
-        },
-        _validateDisabled: function () {
-            var self = this;
-            self.$caption.attr({readonly: self.isDisabled});
-        },
-        _renderMain: function () {
-            var self = this,
-                dropCss = self.dropZoneEnabled ? ' file-drop-zone' : 'file-drop-disabled',
-                close = !self.showClose ? '' : self._getLayoutTemplate('close'),
-                preview = !self.showPreview ? '' : self._getLayoutTemplate('preview')
-                    .setTokens({'class': self.previewClass, 'dropClass': dropCss}),
-                css = self.isDisabled ? self.captionClass + ' file-caption-disabled' : self.captionClass,
-                caption = self.captionTemplate.setTokens({'class': css + ' kv-fileinput-caption'});
-            return self.mainTemplate.setTokens({
-                'class': self.mainClass + (!self.showBrowse && self.showCaption ? ' no-browse' : ''),
-                'preview': preview,
-                'close': close,
-                'caption': caption,
-                'upload': self._renderButton('upload'),
-                'remove': self._renderButton('remove'),
-                'cancel': self._renderButton('cancel'),
-                'browse': self._renderButton('browse')
-            });
-
-        },
-        _renderButton: function (type) {
-            var self = this, tmplt = self._getLayoutTemplate('btnDefault'), css = self[type + 'Class'],
-                title = self[type + 'Title'], icon = self[type + 'Icon'], label = self[type + 'Label'],
-                status = self.isDisabled ? ' disabled' : '', btnType = 'button';
-            switch (type) {
-                case 'remove':
-                    if (!self.showRemove) {
-                        return '';
-                    }
-                    break;
-                case 'cancel':
-                    if (!self.showCancel) {
-                        return '';
-                    }
-                    css += ' kv-hidden';
-                    break;
-                case 'upload':
-                    if (!self.showUpload) {
-                        return '';
-                    }
-                    if (self.isAjaxUpload && !self.isDisabled) {
-                        tmplt = self._getLayoutTemplate('btnLink').replace('{href}', self.uploadUrl);
-                    } else {
-                        btnType = 'submit';
-                    }
-                    break;
-                case 'browse':
-                    if (!self.showBrowse) {
-                        return '';
-                    }
-                    tmplt = self._getLayoutTemplate('btnBrowse');
-                    break;
-                default:
-                    return '';
-            }
-
-            css += type === 'browse' ? ' btn-file' : ' fileinput-' + type + ' fileinput-' + type + '-button';
-            if (!$h.isEmpty(label)) {
-                label = ' <span class="' + self.buttonLabelClass + '">' + label + '</span>';
-            }
-            return tmplt.setTokens({
-                'type': btnType, 'css': css, 'title': title, 'status': status, 'icon': icon, 'label': label
-            });
-        },
-        _renderThumbProgress: function () {
-            var self = this;
-            return '<div class="file-thumb-progress kv-hidden">' +
-                self.progressTemplate.setTokens({'percent': '0', 'status': self.msgUploadBegin}) +
-                '</div>';
-        },
-        _renderFileFooter: function (caption, size, width, isError) {
-            var self = this, config = self.fileActionSettings, rem = config.showRemove, drg = config.showDrag,
-                upl = config.showUpload, zoom = config.showZoom, out,
-                template = self._getLayoutTemplate('footer'), tInd = self._getLayoutTemplate('indicator'),
-                ind = isError ? config.indicatorError : config.indicatorNew,
-                title = isError ? config.indicatorErrorTitle : config.indicatorNewTitle,
-                indicator = tInd.setTokens({'indicator': ind, 'indicatorTitle': title});
-            size = self._getSize(size);
-            if (self.isAjaxUpload) {
-                out = template.setTokens({
-                    'actions': self._renderFileActions(upl, false, rem, zoom, drg, false, false, false),
-                    'caption': caption,
-                    'size': size,
-                    'width': width,
-                    'progress': self._renderThumbProgress(),
-                    'indicator': indicator
-                });
-            } else {
-                out = template.setTokens({
-                    'actions': self._renderFileActions(false, false, false, zoom, drg, false, false, false),
-                    'caption': caption,
-                    'size': size,
-                    'width': width,
-                    'progress': '',
-                    'indicator': indicator
-                });
-            }
-            out = $h.replaceTags(out, self.previewThumbTags);
-            return out;
-        },
-        _renderFileActions: function (showUpl, showDwn, showDel, showZoom, showDrag, disabled, url, key, isInit, dUrl, dFile) {
-            if (!showUpl && !showDwn && !showDel && !showZoom && !showDrag) {
-                return '';
-            }
-            var self = this, vUrl = url === false ? '' : ' data-url="' + url + '"',
-                vKey = key === false ? '' : ' data-key="' + key + '"', btnDelete = '', btnUpload = '', btnDownload = '',
-                btnZoom = '', btnDrag = '', css, template = self._getLayoutTemplate('actions'),
-                config = self.fileActionSettings,
-                otherButtons = self.otherActionButtons.setTokens({'dataKey': vKey, 'key': key}),
-                removeClass = disabled ? config.removeClass + ' disabled' : config.removeClass;
-            if (showDel) {
-                btnDelete = self._getLayoutTemplate('actionDelete').setTokens({
-                    'removeClass': removeClass,
-                    'removeIcon': config.removeIcon,
-                    'removeTitle': config.removeTitle,
-                    'dataUrl': vUrl,
-                    'dataKey': vKey,
-                    'key': key
-                });
-            }
-            if (showUpl) {
-                btnUpload = self._getLayoutTemplate('actionUpload').setTokens({
-                    'uploadClass': config.uploadClass,
-                    'uploadIcon': config.uploadIcon,
-                    'uploadTitle': config.uploadTitle
-                });
-            }
-            if (showDwn) {
-                btnDownload = self._getLayoutTemplate('actionDownload').setTokens({
-                    'downloadClass': config.downloadClass,
-                    'downloadIcon': config.downloadIcon,
-                    'downloadTitle': config.downloadTitle,
-                    'downloadUrl': dUrl || self.initialPreviewDownloadUrl
-                });
-                btnDownload = btnDownload.setTokens({'filename': dFile, 'key': key});
-            }
-            if (showZoom) {
-                btnZoom = self._getLayoutTemplate('actionZoom').setTokens({
-                    'zoomClass': config.zoomClass,
-                    'zoomIcon': config.zoomIcon,
-                    'zoomTitle': config.zoomTitle
-                });
-            }
-            if (showDrag && isInit) {
-                css = 'drag-handle-init ' + config.dragClass;
-                btnDrag = self._getLayoutTemplate('actionDrag').setTokens({
-                    'dragClass': css,
-                    'dragTitle': config.dragTitle,
-                    'dragIcon': config.dragIcon
-                });
-            }
-            return template.setTokens({
-                'delete': btnDelete,
-                'upload': btnUpload,
-                'download': btnDownload,
-                'zoom': btnZoom,
-                'drag': btnDrag,
-                'other': otherButtons
-            });
-        },
-        _browse: function (e) {
-            var self = this;
-            self._raise('filebrowse');
-            if (e && e.isDefaultPrevented()) {
-                return;
-            }
-            if (self.isError && !self.isAjaxUpload) {
-                self.clear();
-            }
-            self.$captionContainer.focus();
-        },
-        _filterDuplicate: function (file, files, fileIds) {
-            var self = this, fileId = self._getFileId(file);
-
-            if (fileId && fileIds && fileIds.indexOf(fileId) > -1) {
-                return;
-            }
-            if (!fileIds) {
-                fileIds = [];
-            }
-            files.push(file);
-            fileIds.push(fileId);
-        },
-        _change: function (e) {
-            var self = this;
-            if (self.changeTriggered) {
-                return;
-            }
-            var $el = self.$element, isDragDrop = arguments.length > 1, isAjaxUpload = self.isAjaxUpload,
-                tfiles = [], files = isDragDrop ? arguments[1] : $el.get(0).files, total,
-                maxCount = !isAjaxUpload && $h.isEmpty($el.attr('multiple')) ? 1 : self.maxFileCount,
-                len, ctr = self.filestack.length, isSingleUpload = $h.isEmpty($el.attr('multiple')),
-                flagSingle = (isSingleUpload && ctr > 0), fileIds = self._getFileIds(),
-                throwError = function (mesg, file, previewId, index) {
-                    var p1 = $.extend(true, {}, self._getOutData({}, {}, files), {id: previewId, index: index}),
-                        p2 = {id: previewId, index: index, file: file, files: files};
-                    return isAjaxUpload ? self._showUploadError(mesg, p1) : self._showError(mesg, p2);
-                },
-                maxCountCheck = function (n, m) {
-                    var msg = self.msgFilesTooMany.replace('{m}', m).replace('{n}', n);
-                    self.isError = throwError(msg, null, null, null);
-                    self.$captionContainer.removeClass('icon-visible');
-                    self._setCaption('', true);
-                    self.$container.removeClass('file-input-new file-input-ajax-new');
-                };
-            self.reader = null;
-            self._resetUpload();
-            self._hideFileIcon();
-            if (self.dropZoneEnabled) {
-                self.$container.find('.file-drop-zone .' + self.dropZoneTitleClass).remove();
-            }
-            if (isAjaxUpload) {
-                $.each(files, function (vKey, vFile) {
-                    self._filterDuplicate(vFile, tfiles, fileIds);
-                });
-            } else {
-                if (e.target && e.target.files === undefined) {
-                    files = e.target.value ? [{name: e.target.value.replace(/^.+\\/, '')}] : [];
-                } else {
-                    files = e.target.files || {};
-                }
-                tfiles = files;
-            }
-            if ($h.isEmpty(tfiles) || tfiles.length === 0) {
-                if (!isAjaxUpload) {
-                    self.clear();
-                }
-                self._raise('fileselectnone');
-                return;
-            }
-            self._resetErrors();
-            len = tfiles.length;
-            total = self._getFileCount(isAjaxUpload ? (self.getFileStack().length + len) : len);
-            if (maxCount > 0 && total > maxCount) {
-                if (!self.autoReplace || len > maxCount) {
-                    maxCountCheck((self.autoReplace && len > maxCount ? len : total), maxCount);
-                    return;
-                }
-                if (total > maxCount) {
-                    self._resetPreviewThumbs(isAjaxUpload);
-                }
-            } else {
-                if (!isAjaxUpload || flagSingle) {
-                    self._resetPreviewThumbs(false);
-                    if (flagSingle) {
-                        self.clearStack();
-                    }
-                } else {
-                    if (isAjaxUpload && ctr === 0 && (!self.previewCache.count() || self.overwriteInitial)) {
-                        self._resetPreviewThumbs(true);
-                    }
-                }
-            }
-            if (self.isPreviewable) {
-                self.readFiles(tfiles);
-            } else {
-                self._updateFileDetails(1);
-            }
-        },
-        _abort: function (params) {
-            var self = this, data;
-            if (self.ajaxAborted && typeof self.ajaxAborted === "object" && self.ajaxAborted.message !== undefined) {
-                data = $.extend(true, {}, self._getOutData(), params);
-                data.abortData = self.ajaxAborted.data || {};
-                data.abortMessage = self.ajaxAborted.message;
-                self._setProgress(101, self.$progress, self.msgCancelled);
-                self._showUploadError(self.ajaxAborted.message, data, 'filecustomerror');
-                self.cancel();
-                return true;
-            }
-            return !!self.ajaxAborted;
-        },
-        _resetFileStack: function () {
-            var self = this, i = 0, newstack = [], newnames = [], newids = [];
-            self._getThumbs().each(function () {
-                var $thumb = $(this), ind = $thumb.attr('data-fileindex'), file = self.filestack[ind],
-                    pid = $thumb.attr('id');
-                if (ind === '-1' || ind === -1) {
-                    return;
-                }
-                if (file !== undefined) {
-                    newstack[i] = file;
-                    newnames[i] = self._getFileName(file);
-                    newids[i] = self._getFileId(file);
-                    $thumb.attr({'id': self.previewInitId + '-' + i, 'data-fileindex': i});
-                    i++;
-                } else {
-                    $thumb.attr({'id': 'uploaded-' + $h.uniqId(), 'data-fileindex': '-1'});
-                }
-                self.$preview.find('#zoom-' + pid).attr({
-                    'id': 'zoom-' + $thumb.attr('id'),
-                    'data-fileindex': $thumb.attr('data-fileindex')
-                });
-            });
-            self.filestack = newstack;
-            self.filenames = newnames;
-            self.fileids = newids;
-        },
-        _isFileSelectionValid: function (cnt) {
-            var self = this;
-            cnt = cnt || 0;
-            if (self.required && !self.getFilesCount()) {
-                self.$errorContainer.html('');
-                self._showUploadError(self.msgFileRequired);
-                return false;
-            }
-            if (self.minFileCount > 0 && self._getFileCount(cnt) < self.minFileCount) {
-                self._noFilesError({});
-                return false;
-            }
-            return true;
-        },
-        clearStack: function () {
-            var self = this;
-            self.filestack = [];
-            self.filenames = [];
-            self.fileids = [];
-            return self.$element;
-        },
-        updateStack: function (i, file) {
-            var self = this;
-            self.filestack[i] = file;
-            self.filenames[i] = self._getFileName(file);
-            self.fileids[i] = file && self._getFileId(file) || null;
-            return self.$element;
-        },
-        addToStack: function (file) {
-            var self = this;
-            self.filestack.push(file);
-            self.filenames.push(self._getFileName(file));
-            self.fileids.push(self._getFileId(file));
-            return self.$element;
-        },
-        getFileStack: function (skipNull) {
-            var self = this;
-            return self.filestack.filter(function (n) {
-                return (skipNull ? n !== undefined : n !== undefined && n !== null);
-            });
-        },
-        getFilesCount: function () {
-            var self = this, len = self.isAjaxUpload ? self.getFileStack().length : self._inputFileCount();
-            return self._getFileCount(len);
-        },
-        readFiles: function (files) {
-            this.reader = new FileReader();
-            var self = this, $el = self.$element, $preview = self.$preview, reader = self.reader,
-                $container = self.$previewContainer, $status = self.$previewStatus, msgLoading = self.msgLoading,
-                msgProgress = self.msgProgress, previewInitId = self.previewInitId, numFiles = files.length,
-                settings = self.fileTypeSettings, ctr = self.filestack.length, readFile,
-                fileTypes = self.allowedFileTypes, typLen = fileTypes ? fileTypes.length : 0,
-                fileExt = self.allowedFileExtensions, strExt = $h.isEmpty(fileExt) ? '' : fileExt.join(', '),
-                maxPreviewSize = self.maxFilePreviewSize && parseFloat(self.maxFilePreviewSize),
-                canPreview = $preview.length && (!maxPreviewSize || isNaN(maxPreviewSize)),
-                throwError = function (msg, file, previewId, index) {
-                    var p1 = $.extend(true, {}, self._getOutData({}, {}, files), {id: previewId, index: index}),
-                        p2 = {id: previewId, index: index, file: file, files: files}, $thumb;
-                    self._previewDefault(file, previewId, true);
-                    if (self.isAjaxUpload) {
-                        self.addToStack(undefined);
-                        setTimeout(function () {
-                            readFile(index + 1);
-                        }, 100);
-                    } else {
-                        numFiles = 0;
-                    }
-                    self._initFileActions();
-                    $thumb = $('#' + previewId);
-                    $thumb.find('.kv-file-upload').hide();
-                    if (self.removeFromPreviewOnError) {
-                        $thumb.remove();
-                    }
-                    self.isError = self.isAjaxUpload ? self._showUploadError(msg, p1) : self._showError(msg, p2);
-                    self._updateFileDetails(numFiles);
-                };
-
-            self.loadedImages = [];
-            self.totalImagesCount = 0;
-
-            $.each(files, function (key, file) {
-                var func = self.fileTypeSettings.image;
-                if (func && func(file.type)) {
-                    self.totalImagesCount++;
-                }
-            });
-            readFile = function (i) {
-                if ($h.isEmpty($el.attr('multiple'))) {
-                    numFiles = 1;
-                }
-                if (i >= numFiles) {
-                    if (self.isAjaxUpload && self.filestack.length > 0) {
-                        self._raise('filebatchselected', [self.getFileStack()]);
-                    } else {
-                        self._raise('filebatchselected', [files]);
-                    }
-                    $container.removeClass('file-thumb-loading');
-                    $status.html('');
-                    return;
-                }
-                var node = ctr + i, previewId = previewInitId + "-" + node, file = files[i], fSizeKB, j, msg,
-                    fnText = settings.text, fnImage = settings.image, fnHtml = settings.html, typ, chk, typ1, typ2,
-                    caption = file && file.name ? self.slug(file.name) : '', fileSize = (file && file.size || 0) / 1000,
-                    fileExtExpr = '', previewData = file ? $h.objUrl.createObjectURL(file) : null, fileCount = 0, strTypes = '',
-                    func, knownTypes = 0, isText, isHtml, isImage, txtFlag, processFileLoaded = function () {
-                        var msg = msgProgress.setTokens({
-                            'index': i + 1,
-                            'files': numFiles,
-                            'percent': 50,
-                            'name': caption
-                        });
-                        setTimeout(function () {
-                            $status.html(msg);
-                            self._updateFileDetails(numFiles);
-                            readFile(i + 1);
-                        }, 100);
-                        self._raise('fileloaded', [file, previewId, i, reader]);
-                    };
-                if (!file) {
-                    return;
-                }
-                if (typLen > 0) {
-                    for (j = 0; j < typLen; j++) {
-                        typ1 = fileTypes[j];
-                        typ2 = self.msgFileTypes[typ1] || typ1;
-                        strTypes += j === 0 ? typ2 : ', ' + typ2;
-                    }
-                }
-                if (caption === false) {
-                    readFile(i + 1);
-                    return;
-                }
-                if (caption.length === 0) {
-                    msg = self.msgInvalidFileName.replace('{name}', $h.htmlEncode(file.name));
-                    throwError(msg, file, previewId, i);
-                    return;
-                }
-                if (!$h.isEmpty(fileExt)) {
-                    fileExtExpr = new RegExp('\\.(' + fileExt.join('|') + ')$', 'i');
-                }
-                fSizeKB = fileSize.toFixed(2);
-                if (self.maxFileSize > 0 && fileSize > self.maxFileSize) {
-                    msg = self.msgSizeTooLarge.setTokens({
-                        'name': caption,
-                        'size': fSizeKB,
-                        'maxSize': self.maxFileSize
-                    });
-                    throwError(msg, file, previewId, i);
-                    return;
-                }
-                if (self.minFileSize !== null && fileSize <= $h.getNum(self.minFileSize)) {
-                    msg = self.msgSizeTooSmall.setTokens({
-                        'name': caption,
-                        'size': fSizeKB,
-                        'minSize': self.minFileSize
-                    });
-                    throwError(msg, file, previewId, i);
-                    return;
-                }
-                if (!$h.isEmpty(fileTypes) && $h.isArray(fileTypes)) {
-                    for (j = 0; j < fileTypes.length; j += 1) {
-                        typ = fileTypes[j];
-                        func = settings[typ];
-                        fileCount += !func || (typeof func !== 'function') ? 0 : (func(file.type, file.name) ? 1 : 0);
-                    }
-                    if (fileCount === 0) {
-                        msg = self.msgInvalidFileType.setTokens({'name': caption, 'types': strTypes});
-                        throwError(msg, file, previewId, i);
-                        return;
-                    }
-                }
-                if (fileCount === 0 && !$h.isEmpty(fileExt) && $h.isArray(fileExt) && !$h.isEmpty(fileExtExpr)) {
-                    chk = $h.compare(caption, fileExtExpr);
-                    fileCount += $h.isEmpty(chk) ? 0 : chk.length;
-                    if (fileCount === 0) {
-                        msg = self.msgInvalidFileExtension.setTokens({'name': caption, 'extensions': strExt});
-                        throwError(msg, file, previewId, i);
-                        return;
-                    }
-                }
-                if (!self.showPreview) {
-                    if (self.isAjaxUpload) {
-                        self.addToStack(file);
-                    }
-                    setTimeout(function () {
-                        readFile(i + 1);
-                        self._updateFileDetails(numFiles);
-                    }, 100);
-                    self._raise('fileloaded', [file, previewId, i, reader]);
-                    return;
-                }
-                if (!canPreview && fileSize > maxPreviewSize) {
-                    self.addToStack(file);
-                    $container.addClass('file-thumb-loading');
-                    self._previewDefault(file, previewId);
-                    self._initFileActions();
-                    self._updateFileDetails(numFiles);
-                    readFile(i + 1);
-                    return;
-                }
-                if ($preview.length && FileReader !== undefined) {
-                    isText = fnText(file.type, caption);
-                    isHtml = fnHtml(file.type, caption);
-                    isImage = fnImage(file.type, caption);
-                    $status.html(msgLoading.replace('{index}', i + 1).replace('{files}', numFiles));
-                    $container.addClass('file-thumb-loading');
-                    reader.onerror = function (evt) {
-                        self._errorHandler(evt, caption);
-                    };
-                    reader.onload = function (theFile) {
-                        var hex, fileInfo, uint, byte, bytes = [], contents, mime, readTextImage = function (textFlag) {
-                            var newReader = new FileReader();
-                            newReader.onerror = function (theFileNew) {
-                                self._errorHandler(theFileNew, caption);
-                            };
-                            newReader.onload = function (theFileNew) {
-                                self._previewFile(i, file, theFileNew, previewId, previewData, fileInfo);
-                                self._initFileActions();
-                                processFileLoaded();
-                            };
-                            if (textFlag) {
-                                newReader.readAsText(file, self.textEncoding);
-                            } else {
-                                newReader.readAsDataURL(file);
-                            }
-                        };
-                        fileInfo = {'name': caption, 'type': file.type};
-                        $.each(settings, function (key, func) {
-                            if (key !== 'object' && key !== 'other' && func(file.type, caption)) {
-                                knownTypes++;
-                            }
-                        });
-                        if (knownTypes === 0) {// auto detect mime types from content if no known file types detected
-                            uint = new Uint8Array(theFile.target.result);
-                            for (j = 0; j < uint.length; j++) {
-                                byte = uint[j].toString(16);
-                                bytes.push(byte);
-                            }
-                            hex = bytes.join('').toLowerCase().substring(0, 8);
-                            mime = $h.getMimeType(hex, '', '');
-                            if ($h.isEmpty(mime)) { // look for ascii text content
-                                contents = $h.arrayBuffer2String(reader.result);
-                                mime = $h.isSvg(contents) ? 'image/svg+xml' : $h.getMimeType(hex, contents, file.type);
-                            }
-                            fileInfo = {'name': caption, 'type': mime};
-                            isText = fnText(mime, '');
-                            isHtml = fnHtml(mime, '');
-                            isImage = fnImage(mime, '');
-                            txtFlag = isText || isHtml;
-                            if (txtFlag || isImage) {
-                                readTextImage(txtFlag);
-                                return;
-                            }
-                        }
-                        self._previewFile(i, file, theFile, previewId, previewData, fileInfo);
-                        self._initFileActions();
-                        processFileLoaded();
-                    };
-                    reader.onprogress = function (data) {
-                        if (data.lengthComputable) {
-                            var fact = (data.loaded / data.total) * 100, progress = Math.ceil(fact);
-                            msg = msgProgress.setTokens({
-                                'index': i + 1,
-                                'files': numFiles,
-                                'percent': progress,
-                                'name': caption
-                            });
-                            setTimeout(function () {
-                                $status.html(msg);
-                            }, 100);
-                        }
-                    };
-
-                    if (isText || isHtml) {
-                        reader.readAsText(file, self.textEncoding);
-                    } else {
-                        if (isImage) {
-                            reader.readAsDataURL(file);
-                        } else {
-                            reader.readAsArrayBuffer(file);
-                        }
-                    }
-                } else {
-                    self._previewDefault(file, previewId);
-                    setTimeout(function () {
-                        readFile(i + 1);
-                        self._updateFileDetails(numFiles);
-                    }, 100);
-                    self._raise('fileloaded', [file, previewId, i, reader]);
-                }
-                self.addToStack(file);
-            };
-
-            readFile(0);
-            self._updateFileDetails(numFiles, false);
-        },
-        lock: function () {
-            var self = this;
-            self._resetErrors();
-            self.disable();
-            if (self.showRemove) {
-                self.$container.find('.fileinput-remove').hide();
-            }
-            if (self.showCancel) {
-                self.$container.find('.fileinput-cancel').show();
-            }
-            self._raise('filelock', [self.filestack, self._getExtraData()]);
-            return self.$element;
-        },
-        unlock: function (reset) {
-            var self = this;
-            if (reset === undefined) {
-                reset = true;
-            }
-            self.enable();
-            if (self.showCancel) {
-                self.$container.find('.fileinput-cancel').hide();
-            }
-            if (self.showRemove) {
-                self.$container.find('.fileinput-remove').show();
-            }
-            if (reset) {
-                self._resetFileStack();
-            }
-            self._raise('fileunlock', [self.filestack, self._getExtraData()]);
-            return self.$element;
-        },
-        cancel: function () {
-            var self = this, xhr = self.ajaxRequests, len = xhr.length, i;
-            if (len > 0) {
-                for (i = 0; i < len; i += 1) {
-                    self.cancelling = true;
-                    xhr[i].abort();
-                }
-            }
-            self._setProgressCancelled();
-            self._getThumbs().each(function () {
-                var $thumb = $(this), ind = $thumb.attr('data-fileindex');
-                $thumb.removeClass('file-uploading');
-                if (self.filestack[ind] !== undefined) {
-                    $thumb.find('.kv-file-upload').removeClass('disabled').removeAttr('disabled');
-                    $thumb.find('.kv-file-remove').removeClass('disabled').removeAttr('disabled');
-                }
-                self.unlock();
-            });
-            return self.$element;
-        },
-        clear: function () {
-            var self = this, cap;
-            if (!self._raise('fileclear')) {
-                return;
-            }
-            self.$btnUpload.removeAttr('disabled');
-            self._getThumbs().find('video,audio,img').each(function () {
-                $h.cleanMemory($(this));
-            });
-            self._clearFileInput();
-            self._resetUpload();
-            self.clearStack();
-            self._resetErrors(true);
-            if (self._hasInitialPreview()) {
-                self._showFileIcon();
-                self._resetPreview();
-                self._initPreviewActions();
-                self.$container.removeClass('file-input-new');
-            } else {
-                self._getThumbs().each(function () {
-                    self._clearObjects($(this));
-                });
-                if (self.isAjaxUpload) {
-                    self.previewCache.data = {};
-                }
-                self.$preview.html('');
-                cap = (!self.overwriteInitial && self.initialCaption.length > 0) ? self.initialCaption : '';
-                self.$caption.attr('title', '').val(cap);
-                $h.addCss(self.$container, 'file-input-new');
-                self._validateDefaultPreview();
-            }
-            if (self.$container.find($h.FRAMES).length === 0) {
-                if (!self._initCaption()) {
-                    self.$captionContainer.removeClass('icon-visible');
-                }
-            }
-            self._hideFileIcon();
-            self._raise('filecleared');
-            self.$captionContainer.focus();
-            self._setFileDropZoneTitle();
-            return self.$element;
-        },
-        reset: function () {
-            var self = this;
-            if (!self._raise('filereset')) {
-                return;
-            }
-            self._resetPreview();
-            self.$container.find('.fileinput-filename').text('');
-            $h.addCss(self.$container, 'file-input-new');
-            if (self.getFrames().length || self.dropZoneEnabled) {
-                self.$container.removeClass('file-input-new');
-            }
-            self.clearStack();
-            self.formdata = {};
-            self._setFileDropZoneTitle();
-            return self.$element;
-        },
-        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(".fileinput-remove, .fileinput-upload, .file-preview-frame button")
-                .attr("disabled", true);
-            $h.addCss(self.$container.find('.btn-file'), 'disabled');
-            self._initDragDrop();
-            return self.$element;
-        },
-        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(".fileinput-remove, .fileinput-upload, .file-preview-frame button")
-                .removeAttr("disabled");
-            self.$container.find('.btn-file').removeClass('disabled');
-            self._initDragDrop();
-            return self.$element;
-        },
-        upload: function () {
-            var self = this, totLen = self.getFileStack().length, i, outData, len,
-                hasExtraData = !$.isEmptyObject(self._getExtraData());
-            if (!self.isAjaxUpload || self.isDisabled || !self._isFileSelectionValid(totLen)) {
-                return;
-            }
-            self._resetUpload();
-            if (totLen === 0 && !hasExtraData) {
-                self._showUploadError(self.msgUploadEmpty);
-                return;
-            }
-            self.$progress.show();
-            self.uploadCount = 0;
-            self.uploadStatus = {};
-            self.uploadLog = [];
-            self.lock();
-            self._setProgress(2);
-            if (totLen === 0 && hasExtraData) {
-                self._uploadExtraOnly();
-                return;
-            }
-            len = self.filestack.length;
-            self.hasInitData = false;
-            if (self.uploadAsync) {
-                outData = self._getOutData();
-                self._raise('filebatchpreupload', [outData]);
-                self.fileBatchCompleted = false;
-                self.uploadCache = {content: [], config: [], tags: [], append: true};
-                self.uploadAsyncCount = self.getFileStack().length;
-                for (i = 0; i < len; i++) {
-                    self.uploadCache.content[i] = null;
-                    self.uploadCache.config[i] = null;
-                    self.uploadCache.tags[i] = null;
-                }
-                self.$preview.find('.file-preview-initial').removeClass($h.SORT_CSS);
-                self._initSortable();
-                self.cacheInitialPreview = self.getPreview();
-
-                for (i = 0; i < len; i++) {
-                    if (self.filestack[i]) {
-                        self._uploadSingle(i, true);
-                    }
-                }
-                return;
-            }
-            self._uploadBatch();
-            return self.$element;
-        },
-        destroy: function () {
-            var self = this, $form = self.$form, $cont = self.$container, $el = self.$element, ns = self.namespace;
-            $(document).off(ns);
-            $(window).off(ns);
-            if ($form && $form.length) {
-                $form.off(ns);
-            }
-            if (self.isAjaxUpload) {
-                self._clearFileInput();
-            }
-            self._cleanup();
-            self._initPreviewCache();
-            $el.insertBefore($cont).off(ns).removeData();
-            $cont.off().remove();
-            return $el;
-        },
-        refresh: function (options) {
-            var self = this, $el = self.$element;
-            if (typeof options !== 'object' || $h.isEmpty(options)) {
-                options = self.options;
-            } else {
-                options = $.extend(true, {}, self.options, options);
-            }
-            self._init(options, true);
-            self._listen();        
-            return $el;
-        },
-        zoom: function (frameId) {
-            var self = this, $frame = self._getFrame(frameId), $modal = self.$modal;
-            if (!$frame) {
-                return;
-            }
-            $h.initModal($modal);
-            $modal.html(self._getModalContent());
-            self._setZoomContent($frame);
-            $modal.modal('show');
-            self._initZoomButtons();
-        },
-        getExif: function (frameId) {
-            var self = this, $frame = self._getFrame(frameId);
-            return $frame && $frame.data('exif') || null;
-        },
-        getFrames: function (cssFilter) {
-            var self = this, $frames;
-            cssFilter = cssFilter || '';
-            $frames = self.$preview.find($h.FRAMES + cssFilter);
-            if (self.reversePreviewOrder) {
-                $frames = $($frames.get().reverse());
-            }
-            return $frames;
-        },
-        getPreview: function () {
-            var self = this;
-            return {
-                content: self.initialPreview,
-                config: self.initialPreviewConfig,
-                tags: self.initialPreviewThumbTags
-            };
-        }
-    };
-
-    $.fn.fileinput = function (option) {
-        if (!$h.hasFileAPISupport() && !$h.isIE(9)) {
-            return;
-        }
-        var args = Array.apply(null, arguments), retvals = [];
-        args.shift();
-        this.each(function () {
-            var self = $(this), data = self.data('fileinput'), options = typeof option === 'object' && option,
-                theme = options.theme || self.data('theme'), l = {}, t = {},
-                lang = options.language || self.data('language') || $.fn.fileinput.defaults.language || 'en', opt;
-            if (!data) {
-                if (theme) {
-                    t = $.fn.fileinputThemes[theme] || {};
-                }
-                if (lang !== 'en' && !$h.isEmpty($.fn.fileinputLocales[lang])) {
-                    l = $.fn.fileinputLocales[lang] || {};
-                }
-                opt = $.extend(true, {}, $.fn.fileinput.defaults, t, $.fn.fileinputLocales.en, l, options, self.data());
-                data = new FileInput(this, opt);
-                self.data('fileinput', data);
-            }
-
-            if (typeof option === 'string') {
-                retvals.push(data[option].apply(data, args));
-            }
-        });
-        switch (retvals.length) {
-            case 0:
-                return this;
-            case 1:
-                return retvals[0];
-            default:
-                return retvals;
-        }
-    };
-
-    $.fn.fileinput.defaults = {
-        language: 'en',
-        showCaption: true,
-        showBrowse: true,
-        showPreview: true,
-        showRemove: true,
-        showUpload: true,
-        showCancel: true,
-        showClose: true,
-        showUploadedThumbs: true,
-        browseOnZoneClick: false,
-        autoReplace: false,
-        autoOrientImage: true, // for JPEG images based on EXIF orientation tag
-        required: false,
-        rtl: false,
-        hideThumbnailContent: false,
-        generateFileId: null,
-        previewClass: '',
-        captionClass: '',
-        frameClass: 'krajee-default',
-        mainClass: 'file-caption-main',
-        mainTemplate: null,
-        purifyHtml: true,
-        fileSizeGetter: null,
-        initialCaption: '',
-        initialPreview: [],
-        initialPreviewDelimiter: '*$$*',
-        initialPreviewAsData: false,
-        initialPreviewFileType: 'image',
-        initialPreviewConfig: [],
-        initialPreviewThumbTags: [],
-        previewThumbTags: {},
-        initialPreviewShowDelete: true,
-        initialPreviewDownloadUrl: '',
-        removeFromPreviewOnError: false,
-        deleteUrl: '',
-        deleteExtraData: {},
-        overwriteInitial: true,
-        previewZoomButtonIcons: {
-            prev: '<i class="glyphicon glyphicon-triangle-left"></i>',
-            next: '<i class="glyphicon glyphicon-triangle-right"></i>',
-            toggleheader: '<i class="glyphicon glyphicon-resize-vertical"></i>',
-            fullscreen: '<i class="glyphicon glyphicon-fullscreen"></i>',
-            borderless: '<i class="glyphicon glyphicon-resize-full"></i>',
-            close: '<i class="glyphicon glyphicon-remove"></i>'
-        },
-        previewZoomButtonClasses: {
-            prev: 'btn btn-navigate',
-            next: 'btn btn-navigate',
-            toggleheader: 'btn btn-sm btn-kv btn-default btn-outline-secondary',
-            fullscreen: 'btn btn-sm btn-kv btn-default btn-outline-secondary',
-            borderless: 'btn btn-sm btn-kv btn-default btn-outline-secondary',
-            close: 'btn btn-sm btn-kv btn-default btn-outline-secondary'
-        },
-        preferIconicPreview: false,
-        preferIconicZoomPreview: false,
-        allowedPreviewTypes: undefined,
-        allowedPreviewMimeTypes: null,
-        allowedFileTypes: null,
-        allowedFileExtensions: null,
-        defaultPreviewContent: null,
-        customLayoutTags: {},
-        customPreviewTags: {},
-        previewFileIcon: '<i class="glyphicon glyphicon-file"></i>',
-        previewFileIconClass: 'file-other-icon',
-        previewFileIconSettings: {},
-        previewFileExtSettings: {},
-        buttonLabelClass: 'hidden-xs',
-        browseIcon: '<i class="glyphicon glyphicon-folder-open"></i>&nbsp;',
-        browseClass: 'btn btn-primary',
-        removeIcon: '<i class="glyphicon glyphicon-trash"></i>',
-        removeClass: 'btn btn-default btn-secondary',
-        cancelIcon: '<i class="glyphicon glyphicon-ban-circle"></i>',
-        cancelClass: 'btn btn-default btn-secondary',
-        uploadIcon: '<i class="glyphicon glyphicon-upload"></i>',
-        uploadClass: 'btn btn-default btn-secondary',
-        uploadUrl: null,
-        uploadUrlThumb: null,
-        uploadAsync: true,
-        uploadExtraData: {},
-        zoomModalHeight: 480,
-        minImageWidth: null,
-        minImageHeight: null,
-        maxImageWidth: null,
-        maxImageHeight: null,
-        resizeImage: false,
-        resizePreference: 'width',
-        resizeQuality: 0.92,
-        resizeDefaultImageType: 'image/jpeg',
-        resizeIfSizeMoreThan: 0, // in KB
-        minFileSize: 0,
-        maxFileSize: 0,
-        maxFilePreviewSize: 25600, // 25 MB
-        minFileCount: 0,
-        maxFileCount: 0,
-        validateInitialCount: false,
-        msgValidationErrorClass: 'text-danger',
-        msgValidationErrorIcon: '<i class="glyphicon glyphicon-exclamation-sign"></i> ',
-        msgErrorClass: 'file-error-message',
-        progressThumbClass: "progress-bar bg-success progress-bar-success progress-bar-striped active",
-        progressClass: "progress-bar bg-success progress-bar-success progress-bar-striped active",
-        progressCompleteClass: "progress-bar bg-success progress-bar-success",
-        progressErrorClass: "progress-bar bg-danger progress-bar-danger",
-        progressUploadThreshold: 99,
-        previewFileType: 'image',
-        elCaptionContainer: null,
-        elCaptionText: null,
-        elPreviewContainer: null,
-        elPreviewImage: null,
-        elPreviewStatus: null,
-        elErrorContainer: null,
-        errorCloseButton: $h.closeButton('kv-error-close'),
-        slugCallback: null,
-        dropZoneEnabled: true,
-        dropZoneTitleClass: 'file-drop-zone-title',
-        fileActionSettings: {},
-        otherActionButtons: '',
-        textEncoding: 'UTF-8',
-        ajaxSettings: {},
-        ajaxDeleteSettings: {},
-        showAjaxErrorDetails: true,
-        mergeAjaxCallbacks: false,
-        mergeAjaxDeleteCallbacks: false,
-        retryErrorUploads: true,
-        reversePreviewOrder: false
-    };
-
-    $.fn.fileinputLocales.en = {
-        fileSingle: 'file',
-        filePlural: 'files',
-        browseLabel: 'Browse &hellip;',
-        removeLabel: 'Remove',
-        removeTitle: 'Clear selected files',
-        cancelLabel: 'Cancel',
-        cancelTitle: 'Abort ongoing upload',
-        uploadLabel: 'Upload',
-        uploadTitle: 'Upload selected files',
-        msgNo: 'No',
-        msgNoFilesSelected: 'No files selected',
-        msgCancelled: 'Cancelled',
-        msgPlaceholder: 'Select {files}...',
-        msgZoomModalHeading: 'Detailed Preview',
-        msgFileRequired: 'You must select a file to upload.',
-        msgSizeTooSmall: 'File "{name}" (<b>{size} KB</b>) is too small and must be larger than <b>{minSize} KB</b>.',
-        msgSizeTooLarge: 'File "{name}" (<b>{size} KB</b>) exceeds maximum allowed upload size of <b>{maxSize} KB</b>.',
-        msgFilesTooLess: 'You must select at least <b>{n}</b> {files} to upload.',
-        msgFilesTooMany: 'Number of files selected for upload <b>({n})</b> exceeds maximum allowed limit of <b>{m}</b>.',
-        msgFileNotFound: 'File "{name}" not found!',
-        msgFileSecured: 'Security restrictions prevent reading the file "{name}".',
-        msgFileNotReadable: 'File "{name}" is not readable.',
-        msgFilePreviewAborted: 'File preview aborted for "{name}".',
-        msgFilePreviewError: 'An error occurred while reading the file "{name}".',
-        msgInvalidFileName: 'Invalid or unsupported characters in file name "{name}".',
-        msgInvalidFileType: 'Invalid type for file "{name}". Only "{types}" files are supported.',
-        msgInvalidFileExtension: 'Invalid extension for file "{name}". Only "{extensions}" files are supported.',
-        msgFileTypes: {
-            'image': 'image',
-            'html': 'HTML',
-            'text': 'text',
-            'video': 'video',
-            'audio': 'audio',
-            'flash': 'flash',
-            'pdf': 'PDF',
-            'object': 'object'
-        },
-        msgUploadAborted: 'The file upload was aborted',
-        msgUploadThreshold: 'Processing...',
-        msgUploadBegin: 'Initializing...',
-        msgUploadEnd: 'Done',
-        msgUploadEmpty: 'No valid data available for upload.',
-        msgUploadError: 'Error',
-        msgValidationError: 'Validation Error',
-        msgLoading: 'Loading file {index} of {files} &hellip;',
-        msgProgress: 'Loading file {index} of {files} - {name} - {percent}% completed.',
-        msgSelected: '{n} {files} selected',
-        msgFoldersNotAllowed: 'Drag & drop files only! {n} folder(s) dropped were skipped.',
-        msgImageWidthSmall: 'Width of image file "{name}" must be at least {size} px.',
-        msgImageHeightSmall: 'Height of image file "{name}" must be at least {size} px.',
-        msgImageWidthLarge: 'Width of image file "{name}" cannot exceed {size} px.',
-        msgImageHeightLarge: 'Height of image file "{name}" cannot exceed {size} px.',
-        msgImageResizeError: 'Could not get the image dimensions to resize.',
-        msgImageResizeException: 'Error while resizing the image.<pre>{errors}</pre>',
-        msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
-        msgAjaxProgressError: '{operation} failed',
-        ajaxOperations: {
-            deleteThumb: 'file delete',
-            uploadThumb: 'file upload',
-            uploadBatch: 'batch file upload',
-            uploadExtra: 'form data upload'
-        },
-        dropZoneTitle: 'Drag & drop files here &hellip;',
-        dropZoneClickTitle: '<br>(or click to select {files})',
-        previewZoomButtonTitles: {
-            prev: 'View previous file',
-            next: 'View next file',
-            toggleheader: 'Toggle header',
-            fullscreen: 'Toggle full screen',
-            borderless: 'Toggle borderless mode',
-            close: 'Close detailed preview'
-        }
-    };
-
-    $.fn.fileinput.Constructor = FileInput;
-
-    /**
-     * Convert automatically file inputs with class 'file' into a bootstrap fileinput control.
-     */
-    $(document).ready(function () {
-        var $input = $('input.file[type=file]');
-        if ($input.length) {
-            $input.fileinput();
-        }
-    });
-}));

Різницю між файлами не показано, бо вона завелика
+ 0 - 9
src/main/resources/static/js/plugins/fileinput/fileinput.min.js


+ 0 - 100
src/main/resources/static/js/plugins/fileinput/locales/zh.js

@@ -1,100 +0,0 @@
-/*!
- * FileInput Chinese Translations
- *
- * This file must be loaded after 'fileinput.js'. Patterns in braces '{}', or
- * any HTML markup tags in the messages must not be converted or translated.
- *
- * @see http://github.com/kartik-v/bootstrap-fileinput
- * @author kangqf <kangqingfei@gmail.com>
- *
- * NOTE: this file must be saved in UTF-8 encoding.
- */
-(function ($) {
-    "use strict";
-
-    $.fn.fileinputLocales['zh'] = {
-        fileSingle: '文件',
-        filePlural: '个文件',
-        browseLabel: '选择 &hellip;',
-        removeLabel: '移除',
-        removeTitle: '清除选中文件',
-        cancelLabel: '取消',
-        cancelTitle: '取消进行中的上传',
-        uploadLabel: '上传',
-        uploadTitle: '上传选中文件',
-        msgNo: '没有',
-        msgNoFilesSelected: '未选择文件',
-        msgCancelled: '取消',
-        msgPlaceholder: '选择 {files}...',
-        msgZoomModalHeading: '详细预览',
-        msgFileRequired: '必须选择一个文件上传.',
-        msgSizeTooSmall: '文件 "{name}" (<b>{size} KB</b>) 必须大于限定大小 <b>{minSize} KB</b>.',
-        msgSizeTooLarge: '文件 "{name}" (<b>{size} KB</b>) 超过了允许大小 <b>{maxSize} KB</b>.',
-        msgFilesTooLess: '你必须选择最少 <b>{n}</b> {files} 来上传. ',
-        msgFilesTooMany: '选择的上传文件个数 <b>({n})</b> 超出最大文件的限制个数 <b>{m}</b>.',
-        msgFileNotFound: '文件 "{name}" 未找到!',
-        msgFileSecured: '安全限制,为了防止读取文件 "{name}".',
-        msgFileNotReadable: '文件 "{name}" 不可读.',
-        msgFilePreviewAborted: '取消 "{name}" 的预览.',
-        msgFilePreviewError: '读取 "{name}" 时出现了一个错误.',
-        msgInvalidFileName: '文件名 "{name}" 包含非法字符.',
-        msgInvalidFileType: '不正确的类型 "{name}". 只支持 "{types}" 类型的文件.',
-        msgInvalidFileExtension: '不正确的文件扩展名 "{name}". 只支持 "{extensions}" 的文件扩展名.',
-        msgFileTypes: {
-            'image': 'image',
-            'html': 'HTML',
-            'text': 'text',
-            'video': 'video',
-            'audio': 'audio',
-            'flash': 'flash',
-            'pdf': 'PDF',
-            'object': 'object'
-        },
-        msgUploadAborted: '该文件上传被中止',
-        msgUploadThreshold: '处理中...',
-        msgUploadBegin: '正在初始化...',
-        msgUploadEnd: '完成',
-        msgUploadEmpty: '无效的文件上传.',
-        msgUploadError: '上传出错',
-        msgValidationError: '验证错误',
-        msgLoading: '加载第 {index} 文件 共 {files} &hellip;',
-        msgProgress: '加载第 {index} 文件 共 {files} - {name} - {percent}% 完成.',
-        msgSelected: '{n} {files} 选中',
-        msgFoldersNotAllowed: '只支持拖拽文件! 跳过 {n} 拖拽的文件夹.',
-        msgImageWidthSmall: '图像文件的"{name}"的宽度必须是至少{size}像素.',
-        msgImageHeightSmall: '图像文件的"{name}"的高度必须至少为{size}像素.',
-        msgImageWidthLarge: '图像文件"{name}"的宽度不能超过{size}像素.',
-        msgImageHeightLarge: '图像文件"{name}"的高度不能超过{size}像素.',
-        msgImageResizeError: '无法获取的图像尺寸调整。',
-        msgImageResizeException: '调整图像大小时发生错误。<pre>{errors}</pre>',
-        msgAjaxError: '{operation} 发生错误. 请重试!',
-        msgAjaxProgressError: '{operation} 失败',
-        ajaxOperations: {
-            deleteThumb: '删除文件',
-            uploadThumb: '上传文件',
-            uploadBatch: '批量上传',
-            uploadExtra: '表单数据上传'
-        },
-        dropZoneTitle: '拖拽文件到这里 &hellip;<br>支持多文件同时上传',
-        dropZoneClickTitle: '<br>(或点击{files}按钮选择文件)',
-        fileActionSettings: {
-            removeTitle: '删除文件',
-            uploadTitle: '上传文件',
-            uploadRetryTitle: '重试',
-            zoomTitle: '查看详情',
-            dragTitle: '移动 / 重置',
-            indicatorNewTitle: '没有上传',
-            indicatorSuccessTitle: '上传',
-            indicatorErrorTitle: '上传错误',
-            indicatorLoadingTitle: '上传 ...'
-        },
-        previewZoomButtonTitles: {
-            prev: '预览上一个文件',
-            next: '预览下一个文件',
-            toggleheader: '缩放',
-            fullscreen: '全屏',
-            borderless: '无边界模式',
-            close: '关闭当前预览'
-        }
-    };
-})(window.jQuery);

+ 0 - 2471
src/main/resources/static/js/plugins/fileinput/plugins/piexif.js

@@ -1,2471 +0,0 @@
-/* piexifjs
-
-The MIT License (MIT)
-
-Copyright (c) 2014, 2015 hMatoba(https://github.com/hMatoba)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-(function () {
-    "use strict";
-    var that = {};
-    that.version = "1.03";
-
-    that.remove = function (jpeg) {
-        var b64 = false;
-        if (jpeg.slice(0, 2) == "\xff\xd8") {
-        } else if (jpeg.slice(0, 23) == "data:image/jpeg;base64," || jpeg.slice(0, 22) == "data:image/jpg;base64,") {
-            jpeg = atob(jpeg.split(",")[1]);
-            b64 = true;
-        } else {
-            throw ("Given data is not jpeg.");
-        }
-        
-        var segments = splitIntoSegments(jpeg);
-        if (segments[1].slice(0, 2) == "\xff\xe1" && 
-               segments[1].slice(4, 10) == "Exif\x00\x00") {
-            segments = [segments[0]].concat(segments.slice(2));
-        } else if (segments[2].slice(0, 2) == "\xff\xe1" &&
-                   segments[2].slice(4, 10) == "Exif\x00\x00") {
-            segments = segments.slice(0, 2).concat(segments.slice(3));
-        } else {
-            throw("Exif not found.");
-        }
-        
-        var new_data = segments.join("");
-        if (b64) {
-            new_data = "data:image/jpeg;base64," + btoa(new_data);
-        }
-
-        return new_data;
-    };
-
-
-    that.insert = function (exif, jpeg) {
-        var b64 = false;
-        if (exif.slice(0, 6) != "\x45\x78\x69\x66\x00\x00") {
-            throw ("Given data is not exif.");
-        }
-        if (jpeg.slice(0, 2) == "\xff\xd8") {
-        } else if (jpeg.slice(0, 23) == "data:image/jpeg;base64," || jpeg.slice(0, 22) == "data:image/jpg;base64,") {
-            jpeg = atob(jpeg.split(",")[1]);
-            b64 = true;
-        } else {
-            throw ("Given data is not jpeg.");
-        }
-
-        var exifStr = "\xff\xe1" + pack(">H", [exif.length + 2]) + exif;
-        var segments = splitIntoSegments(jpeg);
-        var new_data = mergeSegments(segments, exifStr);
-        if (b64) {
-            new_data = "data:image/jpeg;base64," + btoa(new_data);
-        }
-
-        return new_data;
-    };
-
-
-    that.load = function (data) {
-        var input_data;
-        if (typeof (data) == "string") {
-            if (data.slice(0, 2) == "\xff\xd8") {
-                input_data = data;
-            } else if (data.slice(0, 23) == "data:image/jpeg;base64," || data.slice(0, 22) == "data:image/jpg;base64,") {
-                input_data = atob(data.split(",")[1]);
-            } else if (data.slice(0, 4) == "Exif") {
-                input_data = data.slice(6);
-            } else {
-                throw ("'load' gots invalid file data.");
-            }
-        } else {
-            throw ("'load' gots invalid type argument.");
-        }
-
-        var exifDict = {};
-        var exif_dict = {
-            "0th": {},
-            "Exif": {},
-            "GPS": {},
-            "Interop": {},
-            "1st": {},
-            "thumbnail": null
-        };
-        var exifReader = new ExifReader(input_data);
-        if (exifReader.tiftag === null) {
-            return exif_dict;
-        }
-
-        if (exifReader.tiftag.slice(0, 2) == "\x49\x49") {
-            exifReader.endian_mark = "<";
-        } else {
-            exifReader.endian_mark = ">";
-        }
-
-        var pointer = unpack(exifReader.endian_mark + "L",
-            exifReader.tiftag.slice(4, 8))[0];
-        exif_dict["0th"] = exifReader.get_ifd(pointer, "0th");
-
-        var first_ifd_pointer = exif_dict["0th"]["first_ifd_pointer"];
-        delete exif_dict["0th"]["first_ifd_pointer"];
-
-        if (34665 in exif_dict["0th"]) {
-            pointer = exif_dict["0th"][34665];
-            exif_dict["Exif"] = exifReader.get_ifd(pointer, "Exif");
-        }
-        if (34853 in exif_dict["0th"]) {
-            pointer = exif_dict["0th"][34853];
-            exif_dict["GPS"] = exifReader.get_ifd(pointer, "GPS");
-        }
-        if (40965 in exif_dict["Exif"]) {
-            pointer = exif_dict["Exif"][40965];
-            exif_dict["Interop"] = exifReader.get_ifd(pointer, "Interop");
-        }
-        if (first_ifd_pointer != "\x00\x00\x00\x00") {
-            pointer = unpack(exifReader.endian_mark + "L",
-                first_ifd_pointer)[0];
-            exif_dict["1st"] = exifReader.get_ifd(pointer, "1st");
-            if ((513 in exif_dict["1st"]) && (514 in exif_dict["1st"])) {
-                var end = exif_dict["1st"][513] + exif_dict["1st"][514];
-                var thumb = exifReader.tiftag.slice(exif_dict["1st"][513], end);
-                exif_dict["thumbnail"] = thumb;
-            }
-        }
-
-        return exif_dict;
-    };
-
-
-    that.dump = function (exif_dict_original) {
-        var TIFF_HEADER_LENGTH = 8;
-
-        var exif_dict = copy(exif_dict_original);
-        var header = "Exif\x00\x00\x4d\x4d\x00\x2a\x00\x00\x00\x08";
-        var exif_is = false;
-        var gps_is = false;
-        var interop_is = false;
-        var first_is = false;
-
-        var zeroth_ifd,
-            exif_ifd,
-            interop_ifd,
-            gps_ifd,
-            first_ifd;
-        
-        if ("0th" in exif_dict) {
-            zeroth_ifd = exif_dict["0th"];
-        } else {
-            zeroth_ifd = {};
-        }
-        
-        if ((("Exif" in exif_dict) && (Object.keys(exif_dict["Exif"]).length)) ||
-            (("Interop" in exif_dict) && (Object.keys(exif_dict["Interop"]).length))) {
-            zeroth_ifd[34665] = 1;
-            exif_is = true;
-            exif_ifd = exif_dict["Exif"];
-            if (("Interop" in exif_dict) && Object.keys(exif_dict["Interop"]).length) {
-                exif_ifd[40965] = 1;
-                interop_is = true;
-                interop_ifd = exif_dict["Interop"];
-            } else if (Object.keys(exif_ifd).indexOf(that.ExifIFD.InteroperabilityTag.toString()) > -1) {
-                delete exif_ifd[40965];
-            }
-        } else if (Object.keys(zeroth_ifd).indexOf(that.ImageIFD.ExifTag.toString()) > -1) {
-            delete zeroth_ifd[34665];
-        }
-
-        if (("GPS" in exif_dict) && (Object.keys(exif_dict["GPS"]).length)) {
-            zeroth_ifd[that.ImageIFD.GPSTag] = 1;
-            gps_is = true;
-            gps_ifd = exif_dict["GPS"];
-        } else if (Object.keys(zeroth_ifd).indexOf(that.ImageIFD.GPSTag.toString()) > -1) {
-            delete zeroth_ifd[that.ImageIFD.GPSTag];
-        }
-        
-        if (("1st" in exif_dict) &&
-            ("thumbnail" in exif_dict) &&
-            (exif_dict["thumbnail"] != null)) {
-            first_is = true;
-            exif_dict["1st"][513] = 1;
-            exif_dict["1st"][514] = 1;
-            first_ifd = exif_dict["1st"];
-        }
-        
-        var zeroth_set = _dict_to_bytes(zeroth_ifd, "0th", 0);
-        var zeroth_length = (zeroth_set[0].length + exif_is * 12 + gps_is * 12 + 4 +
-            zeroth_set[1].length);
-
-        var exif_set,
-            exif_bytes = "",
-            exif_length = 0,
-            gps_set,
-            gps_bytes = "",
-            gps_length = 0,
-            interop_set,
-            interop_bytes = "",
-            interop_length = 0,
-            first_set,
-            first_bytes = "",
-            thumbnail;
-        if (exif_is) {
-            exif_set = _dict_to_bytes(exif_ifd, "Exif", zeroth_length);
-            exif_length = exif_set[0].length + interop_is * 12 + exif_set[1].length;
-        }
-        if (gps_is) {
-            gps_set = _dict_to_bytes(gps_ifd, "GPS", zeroth_length + exif_length);
-            gps_bytes = gps_set.join("");
-            gps_length = gps_bytes.length;
-        }
-        if (interop_is) {
-            var offset = zeroth_length + exif_length + gps_length;
-            interop_set = _dict_to_bytes(interop_ifd, "Interop", offset);
-            interop_bytes = interop_set.join("");
-            interop_length = interop_bytes.length;
-        }
-        if (first_is) {
-            var offset = zeroth_length + exif_length + gps_length + interop_length;
-            first_set = _dict_to_bytes(first_ifd, "1st", offset);
-            thumbnail = _get_thumbnail(exif_dict["thumbnail"]);
-            if (thumbnail.length > 64000) {
-                throw ("Given thumbnail is too large. max 64kB");
-            }
-        }
-
-        var exif_pointer = "",
-            gps_pointer = "",
-            interop_pointer = "",
-            first_ifd_pointer = "\x00\x00\x00\x00";
-        if (exif_is) {
-            var pointer_value = TIFF_HEADER_LENGTH + zeroth_length;
-            var pointer_str = pack(">L", [pointer_value]);
-            var key = 34665;
-            var key_str = pack(">H", [key]);
-            var type_str = pack(">H", [TYPES["Long"]]);
-            var length_str = pack(">L", [1]);
-            exif_pointer = key_str + type_str + length_str + pointer_str;
-        }
-        if (gps_is) {
-            var pointer_value = TIFF_HEADER_LENGTH + zeroth_length + exif_length;
-            var pointer_str = pack(">L", [pointer_value]);
-            var key = 34853;
-            var key_str = pack(">H", [key]);
-            var type_str = pack(">H", [TYPES["Long"]]);
-            var length_str = pack(">L", [1]);
-            gps_pointer = key_str + type_str + length_str + pointer_str;
-        }
-        if (interop_is) {
-            var pointer_value = (TIFF_HEADER_LENGTH +
-                zeroth_length + exif_length + gps_length);
-            var pointer_str = pack(">L", [pointer_value]);
-            var key = 40965;
-            var key_str = pack(">H", [key]);
-            var type_str = pack(">H", [TYPES["Long"]]);
-            var length_str = pack(">L", [1]);
-            interop_pointer = key_str + type_str + length_str + pointer_str;
-        }
-        if (first_is) {
-            var pointer_value = (TIFF_HEADER_LENGTH + zeroth_length +
-                exif_length + gps_length + interop_length);
-            first_ifd_pointer = pack(">L", [pointer_value]);
-            var thumbnail_pointer = (pointer_value + first_set[0].length + 24 +
-                4 + first_set[1].length);
-            var thumbnail_p_bytes = ("\x02\x01\x00\x04\x00\x00\x00\x01" +
-                pack(">L", [thumbnail_pointer]));
-            var thumbnail_length_bytes = ("\x02\x02\x00\x04\x00\x00\x00\x01" +
-                pack(">L", [thumbnail.length]));
-            first_bytes = (first_set[0] + thumbnail_p_bytes +
-                thumbnail_length_bytes + "\x00\x00\x00\x00" +
-                first_set[1] + thumbnail);
-        }
-
-        var zeroth_bytes = (zeroth_set[0] + exif_pointer + gps_pointer +
-            first_ifd_pointer + zeroth_set[1]);
-        if (exif_is) {
-            exif_bytes = exif_set[0] + interop_pointer + exif_set[1];
-        }
-
-        return (header + zeroth_bytes + exif_bytes + gps_bytes +
-            interop_bytes + first_bytes);
-    };
-
-
-    function copy(obj) {
-        return JSON.parse(JSON.stringify(obj));
-    }
-
-
-    function _get_thumbnail(jpeg) {
-        var segments = splitIntoSegments(jpeg);
-        while (("\xff\xe0" <= segments[1].slice(0, 2)) && (segments[1].slice(0, 2) <= "\xff\xef")) {
-            segments = [segments[0]].concat(segments.slice(2));
-        }
-        return segments.join("");
-    }
-
-
-    function _pack_byte(array) {
-        return pack(">" + nStr("B", array.length), array);
-    }
-
-
-    function _pack_short(array) {
-        return pack(">" + nStr("H", array.length), array);
-    }
-
-
-    function _pack_long(array) {
-        return pack(">" + nStr("L", array.length), array);
-    }
-
-
-    function _value_to_bytes(raw_value, value_type, offset) {
-        var four_bytes_over = "";
-        var value_str = "";
-        var length,
-            new_value,
-            num,
-            den;
-
-        if (value_type == "Byte") {
-            length = raw_value.length;
-            if (length <= 4) {
-                value_str = (_pack_byte(raw_value) +
-                    nStr("\x00", 4 - length));
-            } else {
-                value_str = pack(">L", [offset]);
-                four_bytes_over = _pack_byte(raw_value);
-            }
-        } else if (value_type == "Short") {
-            length = raw_value.length;
-            if (length <= 2) {
-                value_str = (_pack_short(raw_value) +
-                    nStr("\x00\x00", 2 - length));
-            } else {
-                value_str = pack(">L", [offset]);
-                four_bytes_over = _pack_short(raw_value);
-            }
-        } else if (value_type == "Long") {
-            length = raw_value.length;
-            if (length <= 1) {
-                value_str = _pack_long(raw_value);
-            } else {
-                value_str = pack(">L", [offset]);
-                four_bytes_over = _pack_long(raw_value);
-            }
-        } else if (value_type == "Ascii") {
-            new_value = raw_value + "\x00";
-            length = new_value.length;
-            if (length > 4) {
-                value_str = pack(">L", [offset]);
-                four_bytes_over = new_value;
-            } else {
-                value_str = new_value + nStr("\x00", 4 - length);
-            }
-        } else if (value_type == "Rational") {
-            if (typeof (raw_value[0]) == "number") {
-                length = 1;
-                num = raw_value[0];
-                den = raw_value[1];
-                new_value = pack(">L", [num]) + pack(">L", [den]);
-            } else {
-                length = raw_value.length;
-                new_value = "";
-                for (var n = 0; n < length; n++) {
-                    num = raw_value[n][0];
-                    den = raw_value[n][1];
-                    new_value += (pack(">L", [num]) +
-                        pack(">L", [den]));
-                }
-            }
-            value_str = pack(">L", [offset]);
-            four_bytes_over = new_value;
-        } else if (value_type == "SRational") {
-            if (typeof (raw_value[0]) == "number") {
-                length = 1;
-                num = raw_value[0];
-                den = raw_value[1];
-                new_value = pack(">l", [num]) + pack(">l", [den]);
-            } else {
-                length = raw_value.length;
-                new_value = "";
-                for (var n = 0; n < length; n++) {
-                    num = raw_value[n][0];
-                    den = raw_value[n][1];
-                    new_value += (pack(">l", [num]) +
-                        pack(">l", [den]));
-                }
-            }
-            value_str = pack(">L", [offset]);
-            four_bytes_over = new_value;
-        } else if (value_type == "Undefined") {
-            length = raw_value.length;
-            if (length > 4) {
-                value_str = pack(">L", [offset]);
-                four_bytes_over = raw_value;
-            } else {
-                value_str = raw_value + nStr("\x00", 4 - length);
-            }
-        }
-
-        var length_str = pack(">L", [length]);
-
-        return [length_str, value_str, four_bytes_over];
-    }
-
-    function _dict_to_bytes(ifd_dict, ifd, ifd_offset) {
-        var TIFF_HEADER_LENGTH = 8;
-        var tag_count = Object.keys(ifd_dict).length;
-        var entry_header = pack(">H", [tag_count]);
-        var entries_length;
-        if (["0th", "1st"].indexOf(ifd) > -1) {
-            entries_length = 2 + tag_count * 12 + 4;
-        } else {
-            entries_length = 2 + tag_count * 12;
-        }
-        var entries = "";
-        var values = "";
-        var key;
-
-        for (var key in ifd_dict) {
-            if (typeof (key) == "string") {
-                key = parseInt(key);
-            }
-            if ((ifd == "0th") && ([34665, 34853].indexOf(key) > -1)) {
-                continue;
-            } else if ((ifd == "Exif") && (key == 40965)) {
-                continue;
-            } else if ((ifd == "1st") && ([513, 514].indexOf(key) > -1)) {
-                continue;
-            }
-
-            var raw_value = ifd_dict[key];
-            var key_str = pack(">H", [key]);
-            var value_type = TAGS[ifd][key]["type"];
-            var type_str = pack(">H", [TYPES[value_type]]);
-
-            if (typeof (raw_value) == "number") {
-                raw_value = [raw_value];
-            }
-            var offset = TIFF_HEADER_LENGTH + entries_length + ifd_offset + values.length;
-            var b = _value_to_bytes(raw_value, value_type, offset);
-            var length_str = b[0];
-            var value_str = b[1];
-            var four_bytes_over = b[2];
-
-            entries += key_str + type_str + length_str + value_str;
-            values += four_bytes_over;
-        }
-
-        return [entry_header + entries, values];
-    }
-
-
-
-    function ExifReader(data) {
-        var segments,
-            app1;
-        if (data.slice(0, 2) == "\xff\xd8") { // JPEG
-            segments = splitIntoSegments(data);
-            app1 = getExifSeg(segments);
-            if (app1) {
-                this.tiftag = app1.slice(10);
-            } else {
-                this.tiftag = null;
-            }
-        } else if (["\x49\x49", "\x4d\x4d"].indexOf(data.slice(0, 2)) > -1) { // TIFF
-            this.tiftag = data;
-        } else if (data.slice(0, 4) == "Exif") { // Exif
-            this.tiftag = data.slice(6);
-        } else {
-            throw ("Given file is neither JPEG nor TIFF.");
-        }
-    }
-
-    ExifReader.prototype = {
-        get_ifd: function (pointer, ifd_name) {
-            var ifd_dict = {};
-            var tag_count = unpack(this.endian_mark + "H",
-                this.tiftag.slice(pointer, pointer + 2))[0];
-            var offset = pointer + 2;
-            var t;
-            if (["0th", "1st"].indexOf(ifd_name) > -1) {
-                t = "Image";
-            } else {
-                t = ifd_name;
-            }
-
-            for (var x = 0; x < tag_count; x++) {
-                pointer = offset + 12 * x;
-                var tag = unpack(this.endian_mark + "H",
-                    this.tiftag.slice(pointer, pointer + 2))[0];
-                var value_type = unpack(this.endian_mark + "H",
-                    this.tiftag.slice(pointer + 2, pointer + 4))[0];
-                var value_num = unpack(this.endian_mark + "L",
-                    this.tiftag.slice(pointer + 4, pointer + 8))[0];
-                var value = this.tiftag.slice(pointer + 8, pointer + 12);
-
-                var v_set = [value_type, value_num, value];
-                if (tag in TAGS[t]) {
-                    ifd_dict[tag] = this.convert_value(v_set);
-                }
-            }
-
-            if (ifd_name == "0th") {
-                pointer = offset + 12 * tag_count;
-                ifd_dict["first_ifd_pointer"] = this.tiftag.slice(pointer, pointer + 4);
-            }
-
-            return ifd_dict;
-        },
-
-        convert_value: function (val) {
-            var data = null;
-            var t = val[0];
-            var length = val[1];
-            var value = val[2];
-            var pointer;
-
-            if (t == 1) { // BYTE
-                if (length > 4) {
-                    pointer = unpack(this.endian_mark + "L", value)[0];
-                    data = unpack(this.endian_mark + nStr("B", length),
-                        this.tiftag.slice(pointer, pointer + length));
-                } else {
-                    data = unpack(this.endian_mark + nStr("B", length), value.slice(0, length));
-                }
-            } else if (t == 2) { // ASCII
-                if (length > 4) {
-                    pointer = unpack(this.endian_mark + "L", value)[0];
-                    data = this.tiftag.slice(pointer, pointer + length - 1);
-                } else {
-                    data = value.slice(0, length - 1);
-                }
-            } else if (t == 3) { // SHORT
-                if (length > 2) {
-                    pointer = unpack(this.endian_mark + "L", value)[0];
-                    data = unpack(this.endian_mark + nStr("H", length),
-                        this.tiftag.slice(pointer, pointer + length * 2));
-                } else {
-                    data = unpack(this.endian_mark + nStr("H", length),
-                        value.slice(0, length * 2));
-                }
-            } else if (t == 4) { // LONG
-                if (length > 1) {
-                    pointer = unpack(this.endian_mark + "L", value)[0];
-                    data = unpack(this.endian_mark + nStr("L", length),
-                        this.tiftag.slice(pointer, pointer + length * 4));
-                } else {
-                    data = unpack(this.endian_mark + nStr("L", length),
-                        value);
-                }
-            } else if (t == 5) { // RATIONAL
-                pointer = unpack(this.endian_mark + "L", value)[0];
-                if (length > 1) {
-                    data = [];
-                    for (var x = 0; x < length; x++) {
-                        data.push([unpack(this.endian_mark + "L",
-                                this.tiftag.slice(pointer + x * 8, pointer + 4 + x * 8))[0],
-                                   unpack(this.endian_mark + "L",
-                                this.tiftag.slice(pointer + 4 + x * 8, pointer + 8 + x * 8))[0]
-                                   ]);
-                    }
-                } else {
-                    data = [unpack(this.endian_mark + "L",
-                            this.tiftag.slice(pointer, pointer + 4))[0],
-                            unpack(this.endian_mark + "L",
-                            this.tiftag.slice(pointer + 4, pointer + 8))[0]
-                            ];
-                }
-            } else if (t == 7) { // UNDEFINED BYTES
-                if (length > 4) {
-                    pointer = unpack(this.endian_mark + "L", value)[0];
-                    data = this.tiftag.slice(pointer, pointer + length);
-                } else {
-                    data = value.slice(0, length);
-                }
-            } else if (t == 10) { // SRATIONAL
-                pointer = unpack(this.endian_mark + "L", value)[0];
-                if (length > 1) {
-                    data = [];
-                    for (var x = 0; x < length; x++) {
-                        data.push([unpack(this.endian_mark + "l",
-                                this.tiftag.slice(pointer + x * 8, pointer + 4 + x * 8))[0],
-                                   unpack(this.endian_mark + "l",
-                                this.tiftag.slice(pointer + 4 + x * 8, pointer + 8 + x * 8))[0]
-                                  ]);
-                    }
-                } else {
-                    data = [unpack(this.endian_mark + "l",
-                            this.tiftag.slice(pointer, pointer + 4))[0],
-                            unpack(this.endian_mark + "l",
-                            this.tiftag.slice(pointer + 4, pointer + 8))[0]
-                           ];
-                }
-            } else {
-                throw ("Exif might be wrong. Got incorrect value " +
-                    "type to decode. type:" + t);
-            }
-
-            if ((data instanceof Array) && (data.length == 1)) {
-                return data[0];
-            } else {
-                return data;
-            }
-        },
-    };
-
-
-    if (typeof window !== "undefined" && typeof window.btoa === "function") {
-        var btoa = window.btoa;
-    }
-    if (typeof btoa === "undefined") {
-        var btoa = function (input) {        var output = "";
-            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
-            var i = 0;
-            var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-
-            while (i < input.length) {
-
-                chr1 = input.charCodeAt(i++);
-                chr2 = input.charCodeAt(i++);
-                chr3 = input.charCodeAt(i++);
-
-                enc1 = chr1 >> 2;
-                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
-                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
-                enc4 = chr3 & 63;
-
-                if (isNaN(chr2)) {
-                    enc3 = enc4 = 64;
-                } else if (isNaN(chr3)) {
-                    enc4 = 64;
-                }
-
-                output = output +
-                keyStr.charAt(enc1) + keyStr.charAt(enc2) +
-                keyStr.charAt(enc3) + keyStr.charAt(enc4);
-
-            }
-
-            return output;
-        };
-    }
-    
-    
-    if (typeof window !== "undefined" && typeof window.atob === "function") {
-        var atob = window.atob;
-    }
-    if (typeof atob === "undefined") {
-        var atob = function (input) {
-            var output = "";
-            var chr1, chr2, chr3;
-            var enc1, enc2, enc3, enc4;
-            var i = 0;
-            var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-
-            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
-
-            while (i < input.length) {
-
-                enc1 = keyStr.indexOf(input.charAt(i++));
-                enc2 = keyStr.indexOf(input.charAt(i++));
-                enc3 = keyStr.indexOf(input.charAt(i++));
-                enc4 = keyStr.indexOf(input.charAt(i++));
-
-                chr1 = (enc1 << 2) | (enc2 >> 4);
-                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
-                chr3 = ((enc3 & 3) << 6) | enc4;
-
-                output = output + String.fromCharCode(chr1);
-
-                if (enc3 != 64) {
-                    output = output + String.fromCharCode(chr2);
-                }
-                if (enc4 != 64) {
-                    output = output + String.fromCharCode(chr3);
-                }
-
-            }
-
-            return output;
-        };
-    }
-
-
-    function getImageSize(imageArray) {
-        var segments = slice2Segments(imageArray);
-        var seg,
-            width,
-            height,
-            SOF = [192, 193, 194, 195, 197, 198, 199, 201, 202, 203, 205, 206, 207];
-
-        for (var x = 0; x < segments.length; x++) {
-            seg = segments[x];
-            if (SOF.indexOf(seg[1]) >= 0) {
-                height = seg[5] * 256 + seg[6];
-                width = seg[7] * 256 + seg[8];
-                break;
-            }
-        }
-        return [width, height];
-    }
-
-
-    function pack(mark, array) {
-        if (!(array instanceof Array)) {
-            throw ("'pack' error. Got invalid type argument.");
-        }
-        if ((mark.length - 1) != array.length) {
-            throw ("'pack' error. " + (mark.length - 1) + " marks, " + array.length + " elements.");
-        }
-
-        var littleEndian;
-        if (mark[0] == "<") {
-            littleEndian = true;
-        } else if (mark[0] == ">") {
-            littleEndian = false;
-        } else {
-            throw ("");
-        }
-        var packed = "";
-        var p = 1;
-        var val = null;
-        var c = null;
-        var valStr = null;
-
-        while (c = mark[p]) {
-            if (c.toLowerCase() == "b") {
-                val = array[p - 1];
-                if ((c == "b") && (val < 0)) {
-                    val += 0x100;
-                }
-                if ((val > 0xff) || (val < 0)) {
-                    throw ("'pack' error.");
-                } else {
-                    valStr = String.fromCharCode(val);
-                }
-            } else if (c == "H") {
-                val = array[p - 1];
-                if ((val > 0xffff) || (val < 0)) {
-                    throw ("'pack' error.");
-                } else {
-                    valStr = String.fromCharCode(Math.floor((val % 0x10000) / 0x100)) +
-                        String.fromCharCode(val % 0x100);
-                    if (littleEndian) {
-                        valStr = valStr.split("").reverse().join("");
-                    }
-                }
-            } else if (c.toLowerCase() == "l") {
-                val = array[p - 1];
-                if ((c == "l") && (val < 0)) {
-                    val += 0x100000000;
-                }
-                if ((val > 0xffffffff) || (val < 0)) {
-                    throw ("'pack' error.");
-                } else {
-                    valStr = String.fromCharCode(Math.floor(val / 0x1000000)) +
-                        String.fromCharCode(Math.floor((val % 0x1000000) / 0x10000)) +
-                        String.fromCharCode(Math.floor((val % 0x10000) / 0x100)) +
-                        String.fromCharCode(val % 0x100);
-                    if (littleEndian) {
-                        valStr = valStr.split("").reverse().join("");
-                    }
-                }
-            } else {
-                throw ("'pack' error.");
-            }
-
-            packed += valStr;
-            p += 1;
-        }
-
-        return packed;
-    }
-
-    function unpack(mark, str) {
-        if (typeof (str) != "string") {
-            throw ("'unpack' error. Got invalid type argument.");
-        }
-        var l = 0;
-        for (var markPointer = 1; markPointer < mark.length; markPointer++) {
-            if (mark[markPointer].toLowerCase() == "b") {
-                l += 1;
-            } else if (mark[markPointer].toLowerCase() == "h") {
-                l += 2;
-            } else if (mark[markPointer].toLowerCase() == "l") {
-                l += 4;
-            } else {
-                throw ("'unpack' error. Got invalid mark.");
-            }
-        }
-
-        if (l != str.length) {
-            throw ("'unpack' error. Mismatch between symbol and string length. " + l + ":" + str.length);
-        }
-
-        var littleEndian;
-        if (mark[0] == "<") {
-            littleEndian = true;
-        } else if (mark[0] == ">") {
-            littleEndian = false;
-        } else {
-            throw ("'unpack' error.");
-        }
-        var unpacked = [];
-        var strPointer = 0;
-        var p = 1;
-        var val = null;
-        var c = null;
-        var length = null;
-        var sliced = "";
-
-        while (c = mark[p]) {
-            if (c.toLowerCase() == "b") {
-                length = 1;
-                sliced = str.slice(strPointer, strPointer + length);
-                val = sliced.charCodeAt(0);
-                if ((c == "b") && (val >= 0x80)) {
-                    val -= 0x100;
-                }
-            } else if (c == "H") {
-                length = 2;
-                sliced = str.slice(strPointer, strPointer + length);
-                if (littleEndian) {
-                    sliced = sliced.split("").reverse().join("");
-                }
-                val = sliced.charCodeAt(0) * 0x100 +
-                    sliced.charCodeAt(1);
-            } else if (c.toLowerCase() == "l") {
-                length = 4;
-                sliced = str.slice(strPointer, strPointer + length);
-                if (littleEndian) {
-                    sliced = sliced.split("").reverse().join("");
-                }
-                val = sliced.charCodeAt(0) * 0x1000000 +
-                    sliced.charCodeAt(1) * 0x10000 +
-                    sliced.charCodeAt(2) * 0x100 +
-                    sliced.charCodeAt(3);
-                if ((c == "l") && (val >= 0x80000000)) {
-                    val -= 0x100000000;
-                }
-            } else {
-                throw ("'unpack' error. " + c);
-            }
-
-            unpacked.push(val);
-            strPointer += length;
-            p += 1;
-        }
-
-        return unpacked;
-    }
-
-    function nStr(ch, num) {
-        var str = "";
-        for (var i = 0; i < num; i++) {
-            str += ch;
-        }
-        return str;
-    }
-
-    function splitIntoSegments(data) {
-        if (data.slice(0, 2) != "\xff\xd8") {
-            throw ("Given data isn't JPEG.");
-        }
-
-        var head = 2;
-        var segments = ["\xff\xd8"];
-        while (true) {
-            if (data.slice(head, head + 2) == "\xff\xda") {
-                segments.push(data.slice(head));
-                break;
-            } else {
-                var length = unpack(">H", data.slice(head + 2, head + 4))[0];
-                var endPoint = head + length + 2;
-                segments.push(data.slice(head, endPoint));
-                head = endPoint;
-            }
-
-            if (head >= data.length) {
-                throw ("Wrong JPEG data.");
-            }
-        }
-        return segments;
-    }
-
-
-    function getExifSeg(segments) {
-        var seg;
-        for (var i = 0; i < segments.length; i++) {
-            seg = segments[i];
-            if (seg.slice(0, 2) == "\xff\xe1" &&
-                   seg.slice(4, 10) == "Exif\x00\x00") {
-                return seg;
-            }
-        }
-        return null;
-    }
-
-
-    function mergeSegments(segments, exif) {
-        
-        if (segments[1].slice(0, 2) == "\xff\xe0" &&
-            (segments[2].slice(0, 2) == "\xff\xe1" &&
-             segments[2].slice(4, 10) == "Exif\x00\x00")) {
-            if (exif) {
-                segments[2] = exif;
-                segments = ["\xff\xd8"].concat(segments.slice(2));
-            } else if (exif == null) {
-                segments = segments.slice(0, 2).concat(segments.slice(3));
-            } else {
-                segments = segments.slice(0).concat(segments.slice(2));
-            }
-        } else if (segments[1].slice(0, 2) == "\xff\xe0") {
-            if (exif) {
-                segments[1] = exif;
-            }
-        } else if (segments[1].slice(0, 2) == "\xff\xe1" &&
-                   segments[1].slice(4, 10) == "Exif\x00\x00") {
-            if (exif) {
-                segments[1] = exif;
-            } else if (exif == null) {
-                segments = segments.slice(0).concat(segments.slice(2));
-            }
-        } else {
-            if (exif) {
-                segments = [segments[0], exif].concat(segments.slice(1));
-            }
-        }
-        
-        return segments.join("");
-    }
-
-
-    function toHex(str) {
-        var hexStr = "";
-        for (var i = 0; i < str.length; i++) {
-            var h = str.charCodeAt(i);
-            var hex = ((h < 10) ? "0" : "") + h.toString(16);
-            hexStr += hex + " ";
-        }
-        return hexStr;
-    }
-
-
-    var TYPES = {
-        "Byte": 1,
-        "Ascii": 2,
-        "Short": 3,
-        "Long": 4,
-        "Rational": 5,
-        "Undefined": 7,
-        "SLong": 9,
-        "SRational": 10
-    };
-
-
-    var TAGS = {
-        'Image': {
-            11: {
-                'name': 'ProcessingSoftware',
-                'type': 'Ascii'
-            },
-            254: {
-                'name': 'NewSubfileType',
-                'type': 'Long'
-            },
-            255: {
-                'name': 'SubfileType',
-                'type': 'Short'
-            },
-            256: {
-                'name': 'ImageWidth',
-                'type': 'Long'
-            },
-            257: {
-                'name': 'ImageLength',
-                'type': 'Long'
-            },
-            258: {
-                'name': 'BitsPerSample',
-                'type': 'Short'
-            },
-            259: {
-                'name': 'Compression',
-                'type': 'Short'
-            },
-            262: {
-                'name': 'PhotometricInterpretation',
-                'type': 'Short'
-            },
-            263: {
-                'name': 'Threshholding',
-                'type': 'Short'
-            },
-            264: {
-                'name': 'CellWidth',
-                'type': 'Short'
-            },
-            265: {
-                'name': 'CellLength',
-                'type': 'Short'
-            },
-            266: {
-                'name': 'FillOrder',
-                'type': 'Short'
-            },
-            269: {
-                'name': 'DocumentName',
-                'type': 'Ascii'
-            },
-            270: {
-                'name': 'ImageDescription',
-                'type': 'Ascii'
-            },
-            271: {
-                'name': 'Make',
-                'type': 'Ascii'
-            },
-            272: {
-                'name': 'Model',
-                'type': 'Ascii'
-            },
-            273: {
-                'name': 'StripOffsets',
-                'type': 'Long'
-            },
-            274: {
-                'name': 'Orientation',
-                'type': 'Short'
-            },
-            277: {
-                'name': 'SamplesPerPixel',
-                'type': 'Short'
-            },
-            278: {
-                'name': 'RowsPerStrip',
-                'type': 'Long'
-            },
-            279: {
-                'name': 'StripByteCounts',
-                'type': 'Long'
-            },
-            282: {
-                'name': 'XResolution',
-                'type': 'Rational'
-            },
-            283: {
-                'name': 'YResolution',
-                'type': 'Rational'
-            },
-            284: {
-                'name': 'PlanarConfiguration',
-                'type': 'Short'
-            },
-            290: {
-                'name': 'GrayResponseUnit',
-                'type': 'Short'
-            },
-            291: {
-                'name': 'GrayResponseCurve',
-                'type': 'Short'
-            },
-            292: {
-                'name': 'T4Options',
-                'type': 'Long'
-            },
-            293: {
-                'name': 'T6Options',
-                'type': 'Long'
-            },
-            296: {
-                'name': 'ResolutionUnit',
-                'type': 'Short'
-            },
-            301: {
-                'name': 'TransferFunction',
-                'type': 'Short'
-            },
-            305: {
-                'name': 'Software',
-                'type': 'Ascii'
-            },
-            306: {
-                'name': 'DateTime',
-                'type': 'Ascii'
-            },
-            315: {
-                'name': 'Artist',
-                'type': 'Ascii'
-            },
-            316: {
-                'name': 'HostComputer',
-                'type': 'Ascii'
-            },
-            317: {
-                'name': 'Predictor',
-                'type': 'Short'
-            },
-            318: {
-                'name': 'WhitePoint',
-                'type': 'Rational'
-            },
-            319: {
-                'name': 'PrimaryChromaticities',
-                'type': 'Rational'
-            },
-            320: {
-                'name': 'ColorMap',
-                'type': 'Short'
-            },
-            321: {
-                'name': 'HalftoneHints',
-                'type': 'Short'
-            },
-            322: {
-                'name': 'TileWidth',
-                'type': 'Short'
-            },
-            323: {
-                'name': 'TileLength',
-                'type': 'Short'
-            },
-            324: {
-                'name': 'TileOffsets',
-                'type': 'Short'
-            },
-            325: {
-                'name': 'TileByteCounts',
-                'type': 'Short'
-            },
-            330: {
-                'name': 'SubIFDs',
-                'type': 'Long'
-            },
-            332: {
-                'name': 'InkSet',
-                'type': 'Short'
-            },
-            333: {
-                'name': 'InkNames',
-                'type': 'Ascii'
-            },
-            334: {
-                'name': 'NumberOfInks',
-                'type': 'Short'
-            },
-            336: {
-                'name': 'DotRange',
-                'type': 'Byte'
-            },
-            337: {
-                'name': 'TargetPrinter',
-                'type': 'Ascii'
-            },
-            338: {
-                'name': 'ExtraSamples',
-                'type': 'Short'
-            },
-            339: {
-                'name': 'SampleFormat',
-                'type': 'Short'
-            },
-            340: {
-                'name': 'SMinSampleValue',
-                'type': 'Short'
-            },
-            341: {
-                'name': 'SMaxSampleValue',
-                'type': 'Short'
-            },
-            342: {
-                'name': 'TransferRange',
-                'type': 'Short'
-            },
-            343: {
-                'name': 'ClipPath',
-                'type': 'Byte'
-            },
-            344: {
-                'name': 'XClipPathUnits',
-                'type': 'Long'
-            },
-            345: {
-                'name': 'YClipPathUnits',
-                'type': 'Long'
-            },
-            346: {
-                'name': 'Indexed',
-                'type': 'Short'
-            },
-            347: {
-                'name': 'JPEGTables',
-                'type': 'Undefined'
-            },
-            351: {
-                'name': 'OPIProxy',
-                'type': 'Short'
-            },
-            512: {
-                'name': 'JPEGProc',
-                'type': 'Long'
-            },
-            513: {
-                'name': 'JPEGInterchangeFormat',
-                'type': 'Long'
-            },
-            514: {
-                'name': 'JPEGInterchangeFormatLength',
-                'type': 'Long'
-            },
-            515: {
-                'name': 'JPEGRestartInterval',
-                'type': 'Short'
-            },
-            517: {
-                'name': 'JPEGLosslessPredictors',
-                'type': 'Short'
-            },
-            518: {
-                'name': 'JPEGPointTransforms',
-                'type': 'Short'
-            },
-            519: {
-                'name': 'JPEGQTables',
-                'type': 'Long'
-            },
-            520: {
-                'name': 'JPEGDCTables',
-                'type': 'Long'
-            },
-            521: {
-                'name': 'JPEGACTables',
-                'type': 'Long'
-            },
-            529: {
-                'name': 'YCbCrCoefficients',
-                'type': 'Rational'
-            },
-            530: {
-                'name': 'YCbCrSubSampling',
-                'type': 'Short'
-            },
-            531: {
-                'name': 'YCbCrPositioning',
-                'type': 'Short'
-            },
-            532: {
-                'name': 'ReferenceBlackWhite',
-                'type': 'Rational'
-            },
-            700: {
-                'name': 'XMLPacket',
-                'type': 'Byte'
-            },
-            18246: {
-                'name': 'Rating',
-                'type': 'Short'
-            },
-            18249: {
-                'name': 'RatingPercent',
-                'type': 'Short'
-            },
-            32781: {
-                'name': 'ImageID',
-                'type': 'Ascii'
-            },
-            33421: {
-                'name': 'CFARepeatPatternDim',
-                'type': 'Short'
-            },
-            33422: {
-                'name': 'CFAPattern',
-                'type': 'Byte'
-            },
-            33423: {
-                'name': 'BatteryLevel',
-                'type': 'Rational'
-            },
-            33432: {
-                'name': 'Copyright',
-                'type': 'Ascii'
-            },
-            33434: {
-                'name': 'ExposureTime',
-                'type': 'Rational'
-            },
-            34377: {
-                'name': 'ImageResources',
-                'type': 'Byte'
-            },
-            34665: {
-                'name': 'ExifTag',
-                'type': 'Long'
-            },
-            34675: {
-                'name': 'InterColorProfile',
-                'type': 'Undefined'
-            },
-            34853: {
-                'name': 'GPSTag',
-                'type': 'Long'
-            },
-            34857: {
-                'name': 'Interlace',
-                'type': 'Short'
-            },
-            34858: {
-                'name': 'TimeZoneOffset',
-                'type': 'Long'
-            },
-            34859: {
-                'name': 'SelfTimerMode',
-                'type': 'Short'
-            },
-            37387: {
-                'name': 'FlashEnergy',
-                'type': 'Rational'
-            },
-            37388: {
-                'name': 'SpatialFrequencyResponse',
-                'type': 'Undefined'
-            },
-            37389: {
-                'name': 'Noise',
-                'type': 'Undefined'
-            },
-            37390: {
-                'name': 'FocalPlaneXResolution',
-                'type': 'Rational'
-            },
-            37391: {
-                'name': 'FocalPlaneYResolution',
-                'type': 'Rational'
-            },
-            37392: {
-                'name': 'FocalPlaneResolutionUnit',
-                'type': 'Short'
-            },
-            37393: {
-                'name': 'ImageNumber',
-                'type': 'Long'
-            },
-            37394: {
-                'name': 'SecurityClassification',
-                'type': 'Ascii'
-            },
-            37395: {
-                'name': 'ImageHistory',
-                'type': 'Ascii'
-            },
-            37397: {
-                'name': 'ExposureIndex',
-                'type': 'Rational'
-            },
-            37398: {
-                'name': 'TIFFEPStandardID',
-                'type': 'Byte'
-            },
-            37399: {
-                'name': 'SensingMethod',
-                'type': 'Short'
-            },
-            40091: {
-                'name': 'XPTitle',
-                'type': 'Byte'
-            },
-            40092: {
-                'name': 'XPComment',
-                'type': 'Byte'
-            },
-            40093: {
-                'name': 'XPAuthor',
-                'type': 'Byte'
-            },
-            40094: {
-                'name': 'XPKeywords',
-                'type': 'Byte'
-            },
-            40095: {
-                'name': 'XPSubject',
-                'type': 'Byte'
-            },
-            50341: {
-                'name': 'PrintImageMatching',
-                'type': 'Undefined'
-            },
-            50706: {
-                'name': 'DNGVersion',
-                'type': 'Byte'
-            },
-            50707: {
-                'name': 'DNGBackwardVersion',
-                'type': 'Byte'
-            },
-            50708: {
-                'name': 'UniqueCameraModel',
-                'type': 'Ascii'
-            },
-            50709: {
-                'name': 'LocalizedCameraModel',
-                'type': 'Byte'
-            },
-            50710: {
-                'name': 'CFAPlaneColor',
-                'type': 'Byte'
-            },
-            50711: {
-                'name': 'CFALayout',
-                'type': 'Short'
-            },
-            50712: {
-                'name': 'LinearizationTable',
-                'type': 'Short'
-            },
-            50713: {
-                'name': 'BlackLevelRepeatDim',
-                'type': 'Short'
-            },
-            50714: {
-                'name': 'BlackLevel',
-                'type': 'Rational'
-            },
-            50715: {
-                'name': 'BlackLevelDeltaH',
-                'type': 'SRational'
-            },
-            50716: {
-                'name': 'BlackLevelDeltaV',
-                'type': 'SRational'
-            },
-            50717: {
-                'name': 'WhiteLevel',
-                'type': 'Short'
-            },
-            50718: {
-                'name': 'DefaultScale',
-                'type': 'Rational'
-            },
-            50719: {
-                'name': 'DefaultCropOrigin',
-                'type': 'Short'
-            },
-            50720: {
-                'name': 'DefaultCropSize',
-                'type': 'Short'
-            },
-            50721: {
-                'name': 'ColorMatrix1',
-                'type': 'SRational'
-            },
-            50722: {
-                'name': 'ColorMatrix2',
-                'type': 'SRational'
-            },
-            50723: {
-                'name': 'CameraCalibration1',
-                'type': 'SRational'
-            },
-            50724: {
-                'name': 'CameraCalibration2',
-                'type': 'SRational'
-            },
-            50725: {
-                'name': 'ReductionMatrix1',
-                'type': 'SRational'
-            },
-            50726: {
-                'name': 'ReductionMatrix2',
-                'type': 'SRational'
-            },
-            50727: {
-                'name': 'AnalogBalance',
-                'type': 'Rational'
-            },
-            50728: {
-                'name': 'AsShotNeutral',
-                'type': 'Short'
-            },
-            50729: {
-                'name': 'AsShotWhiteXY',
-                'type': 'Rational'
-            },
-            50730: {
-                'name': 'BaselineExposure',
-                'type': 'SRational'
-            },
-            50731: {
-                'name': 'BaselineNoise',
-                'type': 'Rational'
-            },
-            50732: {
-                'name': 'BaselineSharpness',
-                'type': 'Rational'
-            },
-            50733: {
-                'name': 'BayerGreenSplit',
-                'type': 'Long'
-            },
-            50734: {
-                'name': 'LinearResponseLimit',
-                'type': 'Rational'
-            },
-            50735: {
-                'name': 'CameraSerialNumber',
-                'type': 'Ascii'
-            },
-            50736: {
-                'name': 'LensInfo',
-                'type': 'Rational'
-            },
-            50737: {
-                'name': 'ChromaBlurRadius',
-                'type': 'Rational'
-            },
-            50738: {
-                'name': 'AntiAliasStrength',
-                'type': 'Rational'
-            },
-            50739: {
-                'name': 'ShadowScale',
-                'type': 'SRational'
-            },
-            50740: {
-                'name': 'DNGPrivateData',
-                'type': 'Byte'
-            },
-            50741: {
-                'name': 'MakerNoteSafety',
-                'type': 'Short'
-            },
-            50778: {
-                'name': 'CalibrationIlluminant1',
-                'type': 'Short'
-            },
-            50779: {
-                'name': 'CalibrationIlluminant2',
-                'type': 'Short'
-            },
-            50780: {
-                'name': 'BestQualityScale',
-                'type': 'Rational'
-            },
-            50781: {
-                'name': 'RawDataUniqueID',
-                'type': 'Byte'
-            },
-            50827: {
-                'name': 'OriginalRawFileName',
-                'type': 'Byte'
-            },
-            50828: {
-                'name': 'OriginalRawFileData',
-                'type': 'Undefined'
-            },
-            50829: {
-                'name': 'ActiveArea',
-                'type': 'Short'
-            },
-            50830: {
-                'name': 'MaskedAreas',
-                'type': 'Short'
-            },
-            50831: {
-                'name': 'AsShotICCProfile',
-                'type': 'Undefined'
-            },
-            50832: {
-                'name': 'AsShotPreProfileMatrix',
-                'type': 'SRational'
-            },
-            50833: {
-                'name': 'CurrentICCProfile',
-                'type': 'Undefined'
-            },
-            50834: {
-                'name': 'CurrentPreProfileMatrix',
-                'type': 'SRational'
-            },
-            50879: {
-                'name': 'ColorimetricReference',
-                'type': 'Short'
-            },
-            50931: {
-                'name': 'CameraCalibrationSignature',
-                'type': 'Byte'
-            },
-            50932: {
-                'name': 'ProfileCalibrationSignature',
-                'type': 'Byte'
-            },
-            50934: {
-                'name': 'AsShotProfileName',
-                'type': 'Byte'
-            },
-            50935: {
-                'name': 'NoiseReductionApplied',
-                'type': 'Rational'
-            },
-            50936: {
-                'name': 'ProfileName',
-                'type': 'Byte'
-            },
-            50937: {
-                'name': 'ProfileHueSatMapDims',
-                'type': 'Long'
-            },
-            50938: {
-                'name': 'ProfileHueSatMapData1',
-                'type': 'Float'
-            },
-            50939: {
-                'name': 'ProfileHueSatMapData2',
-                'type': 'Float'
-            },
-            50940: {
-                'name': 'ProfileToneCurve',
-                'type': 'Float'
-            },
-            50941: {
-                'name': 'ProfileEmbedPolicy',
-                'type': 'Long'
-            },
-            50942: {
-                'name': 'ProfileCopyright',
-                'type': 'Byte'
-            },
-            50964: {
-                'name': 'ForwardMatrix1',
-                'type': 'SRational'
-            },
-            50965: {
-                'name': 'ForwardMatrix2',
-                'type': 'SRational'
-            },
-            50966: {
-                'name': 'PreviewApplicationName',
-                'type': 'Byte'
-            },
-            50967: {
-                'name': 'PreviewApplicationVersion',
-                'type': 'Byte'
-            },
-            50968: {
-                'name': 'PreviewSettingsName',
-                'type': 'Byte'
-            },
-            50969: {
-                'name': 'PreviewSettingsDigest',
-                'type': 'Byte'
-            },
-            50970: {
-                'name': 'PreviewColorSpace',
-                'type': 'Long'
-            },
-            50971: {
-                'name': 'PreviewDateTime',
-                'type': 'Ascii'
-            },
-            50972: {
-                'name': 'RawImageDigest',
-                'type': 'Undefined'
-            },
-            50973: {
-                'name': 'OriginalRawFileDigest',
-                'type': 'Undefined'
-            },
-            50974: {
-                'name': 'SubTileBlockSize',
-                'type': 'Long'
-            },
-            50975: {
-                'name': 'RowInterleaveFactor',
-                'type': 'Long'
-            },
-            50981: {
-                'name': 'ProfileLookTableDims',
-                'type': 'Long'
-            },
-            50982: {
-                'name': 'ProfileLookTableData',
-                'type': 'Float'
-            },
-            51008: {
-                'name': 'OpcodeList1',
-                'type': 'Undefined'
-            },
-            51009: {
-                'name': 'OpcodeList2',
-                'type': 'Undefined'
-            },
-            51022: {
-                'name': 'OpcodeList3',
-                'type': 'Undefined'
-            }
-        },
-        'Exif': {
-            33434: {
-                'name': 'ExposureTime',
-                'type': 'Rational'
-            },
-            33437: {
-                'name': 'FNumber',
-                'type': 'Rational'
-            },
-            34850: {
-                'name': 'ExposureProgram',
-                'type': 'Short'
-            },
-            34852: {
-                'name': 'SpectralSensitivity',
-                'type': 'Ascii'
-            },
-            34855: {
-                'name': 'ISOSpeedRatings',
-                'type': 'Short'
-            },
-            34856: {
-                'name': 'OECF',
-                'type': 'Undefined'
-            },
-            34864: {
-                'name': 'SensitivityType',
-                'type': 'Short'
-            },
-            34865: {
-                'name': 'StandardOutputSensitivity',
-                'type': 'Long'
-            },
-            34866: {
-                'name': 'RecommendedExposureIndex',
-                'type': 'Long'
-            },
-            34867: {
-                'name': 'ISOSpeed',
-                'type': 'Long'
-            },
-            34868: {
-                'name': 'ISOSpeedLatitudeyyy',
-                'type': 'Long'
-            },
-            34869: {
-                'name': 'ISOSpeedLatitudezzz',
-                'type': 'Long'
-            },
-            36864: {
-                'name': 'ExifVersion',
-                'type': 'Undefined'
-            },
-            36867: {
-                'name': 'DateTimeOriginal',
-                'type': 'Ascii'
-            },
-            36868: {
-                'name': 'DateTimeDigitized',
-                'type': 'Ascii'
-            },
-            37121: {
-                'name': 'ComponentsConfiguration',
-                'type': 'Undefined'
-            },
-            37122: {
-                'name': 'CompressedBitsPerPixel',
-                'type': 'Rational'
-            },
-            37377: {
-                'name': 'ShutterSpeedValue',
-                'type': 'SRational'
-            },
-            37378: {
-                'name': 'ApertureValue',
-                'type': 'Rational'
-            },
-            37379: {
-                'name': 'BrightnessValue',
-                'type': 'SRational'
-            },
-            37380: {
-                'name': 'ExposureBiasValue',
-                'type': 'SRational'
-            },
-            37381: {
-                'name': 'MaxApertureValue',
-                'type': 'Rational'
-            },
-            37382: {
-                'name': 'SubjectDistance',
-                'type': 'Rational'
-            },
-            37383: {
-                'name': 'MeteringMode',
-                'type': 'Short'
-            },
-            37384: {
-                'name': 'LightSource',
-                'type': 'Short'
-            },
-            37385: {
-                'name': 'Flash',
-                'type': 'Short'
-            },
-            37386: {
-                'name': 'FocalLength',
-                'type': 'Rational'
-            },
-            37396: {
-                'name': 'SubjectArea',
-                'type': 'Short'
-            },
-            37500: {
-                'name': 'MakerNote',
-                'type': 'Undefined'
-            },
-            37510: {
-                'name': 'UserComment',
-                'type': 'Ascii'
-            },
-            37520: {
-                'name': 'SubSecTime',
-                'type': 'Ascii'
-            },
-            37521: {
-                'name': 'SubSecTimeOriginal',
-                'type': 'Ascii'
-            },
-            37522: {
-                'name': 'SubSecTimeDigitized',
-                'type': 'Ascii'
-            },
-            40960: {
-                'name': 'FlashpixVersion',
-                'type': 'Undefined'
-            },
-            40961: {
-                'name': 'ColorSpace',
-                'type': 'Short'
-            },
-            40962: {
-                'name': 'PixelXDimension',
-                'type': 'Long'
-            },
-            40963: {
-                'name': 'PixelYDimension',
-                'type': 'Long'
-            },
-            40964: {
-                'name': 'RelatedSoundFile',
-                'type': 'Ascii'
-            },
-            40965: {
-                'name': 'InteroperabilityTag',
-                'type': 'Long'
-            },
-            41483: {
-                'name': 'FlashEnergy',
-                'type': 'Rational'
-            },
-            41484: {
-                'name': 'SpatialFrequencyResponse',
-                'type': 'Undefined'
-            },
-            41486: {
-                'name': 'FocalPlaneXResolution',
-                'type': 'Rational'
-            },
-            41487: {
-                'name': 'FocalPlaneYResolution',
-                'type': 'Rational'
-            },
-            41488: {
-                'name': 'FocalPlaneResolutionUnit',
-                'type': 'Short'
-            },
-            41492: {
-                'name': 'SubjectLocation',
-                'type': 'Short'
-            },
-            41493: {
-                'name': 'ExposureIndex',
-                'type': 'Rational'
-            },
-            41495: {
-                'name': 'SensingMethod',
-                'type': 'Short'
-            },
-            41728: {
-                'name': 'FileSource',
-                'type': 'Undefined'
-            },
-            41729: {
-                'name': 'SceneType',
-                'type': 'Undefined'
-            },
-            41730: {
-                'name': 'CFAPattern',
-                'type': 'Undefined'
-            },
-            41985: {
-                'name': 'CustomRendered',
-                'type': 'Short'
-            },
-            41986: {
-                'name': 'ExposureMode',
-                'type': 'Short'
-            },
-            41987: {
-                'name': 'WhiteBalance',
-                'type': 'Short'
-            },
-            41988: {
-                'name': 'DigitalZoomRatio',
-                'type': 'Rational'
-            },
-            41989: {
-                'name': 'FocalLengthIn35mmFilm',
-                'type': 'Short'
-            },
-            41990: {
-                'name': 'SceneCaptureType',
-                'type': 'Short'
-            },
-            41991: {
-                'name': 'GainControl',
-                'type': 'Short'
-            },
-            41992: {
-                'name': 'Contrast',
-                'type': 'Short'
-            },
-            41993: {
-                'name': 'Saturation',
-                'type': 'Short'
-            },
-            41994: {
-                'name': 'Sharpness',
-                'type': 'Short'
-            },
-            41995: {
-                'name': 'DeviceSettingDescription',
-                'type': 'Undefined'
-            },
-            41996: {
-                'name': 'SubjectDistanceRange',
-                'type': 'Short'
-            },
-            42016: {
-                'name': 'ImageUniqueID',
-                'type': 'Ascii'
-            },
-            42032: {
-                'name': 'CameraOwnerName',
-                'type': 'Ascii'
-            },
-            42033: {
-                'name': 'BodySerialNumber',
-                'type': 'Ascii'
-            },
-            42034: {
-                'name': 'LensSpecification',
-                'type': 'Rational'
-            },
-            42035: {
-                'name': 'LensMake',
-                'type': 'Ascii'
-            },
-            42036: {
-                'name': 'LensModel',
-                'type': 'Ascii'
-            },
-            42037: {
-                'name': 'LensSerialNumber',
-                'type': 'Ascii'
-            },
-            42240: {
-                'name': 'Gamma',
-                'type': 'Rational'
-            }
-        },
-        'GPS': {
-            0: {
-                'name': 'GPSVersionID',
-                'type': 'Byte'
-            },
-            1: {
-                'name': 'GPSLatitudeRef',
-                'type': 'Ascii'
-            },
-            2: {
-                'name': 'GPSLatitude',
-                'type': 'Rational'
-            },
-            3: {
-                'name': 'GPSLongitudeRef',
-                'type': 'Ascii'
-            },
-            4: {
-                'name': 'GPSLongitude',
-                'type': 'Rational'
-            },
-            5: {
-                'name': 'GPSAltitudeRef',
-                'type': 'Byte'
-            },
-            6: {
-                'name': 'GPSAltitude',
-                'type': 'Rational'
-            },
-            7: {
-                'name': 'GPSTimeStamp',
-                'type': 'Rational'
-            },
-            8: {
-                'name': 'GPSSatellites',
-                'type': 'Ascii'
-            },
-            9: {
-                'name': 'GPSStatus',
-                'type': 'Ascii'
-            },
-            10: {
-                'name': 'GPSMeasureMode',
-                'type': 'Ascii'
-            },
-            11: {
-                'name': 'GPSDOP',
-                'type': 'Rational'
-            },
-            12: {
-                'name': 'GPSSpeedRef',
-                'type': 'Ascii'
-            },
-            13: {
-                'name': 'GPSSpeed',
-                'type': 'Rational'
-            },
-            14: {
-                'name': 'GPSTrackRef',
-                'type': 'Ascii'
-            },
-            15: {
-                'name': 'GPSTrack',
-                'type': 'Rational'
-            },
-            16: {
-                'name': 'GPSImgDirectionRef',
-                'type': 'Ascii'
-            },
-            17: {
-                'name': 'GPSImgDirection',
-                'type': 'Rational'
-            },
-            18: {
-                'name': 'GPSMapDatum',
-                'type': 'Ascii'
-            },
-            19: {
-                'name': 'GPSDestLatitudeRef',
-                'type': 'Ascii'
-            },
-            20: {
-                'name': 'GPSDestLatitude',
-                'type': 'Rational'
-            },
-            21: {
-                'name': 'GPSDestLongitudeRef',
-                'type': 'Ascii'
-            },
-            22: {
-                'name': 'GPSDestLongitude',
-                'type': 'Rational'
-            },
-            23: {
-                'name': 'GPSDestBearingRef',
-                'type': 'Ascii'
-            },
-            24: {
-                'name': 'GPSDestBearing',
-                'type': 'Rational'
-            },
-            25: {
-                'name': 'GPSDestDistanceRef',
-                'type': 'Ascii'
-            },
-            26: {
-                'name': 'GPSDestDistance',
-                'type': 'Rational'
-            },
-            27: {
-                'name': 'GPSProcessingMethod',
-                'type': 'Undefined'
-            },
-            28: {
-                'name': 'GPSAreaInformation',
-                'type': 'Undefined'
-            },
-            29: {
-                'name': 'GPSDateStamp',
-                'type': 'Ascii'
-            },
-            30: {
-                'name': 'GPSDifferential',
-                'type': 'Short'
-            },
-            31: {
-                'name': 'GPSHPositioningError',
-                'type': 'Rational'
-            }
-        },
-        'Interop': {
-            1: {
-                'name': 'InteroperabilityIndex',
-                'type': 'Ascii'
-            }
-        },
-    };
-    TAGS["0th"] = TAGS["Image"];
-    TAGS["1st"] = TAGS["Image"];
-    that.TAGS = TAGS;
-
-    
-    that.ImageIFD = {
-        ProcessingSoftware:11,
-        NewSubfileType:254,
-        SubfileType:255,
-        ImageWidth:256,
-        ImageLength:257,
-        BitsPerSample:258,
-        Compression:259,
-        PhotometricInterpretation:262,
-        Threshholding:263,
-        CellWidth:264,
-        CellLength:265,
-        FillOrder:266,
-        DocumentName:269,
-        ImageDescription:270,
-        Make:271,
-        Model:272,
-        StripOffsets:273,
-        Orientation:274,
-        SamplesPerPixel:277,
-        RowsPerStrip:278,
-        StripByteCounts:279,
-        XResolution:282,
-        YResolution:283,
-        PlanarConfiguration:284,
-        GrayResponseUnit:290,
-        GrayResponseCurve:291,
-        T4Options:292,
-        T6Options:293,
-        ResolutionUnit:296,
-        TransferFunction:301,
-        Software:305,
-        DateTime:306,
-        Artist:315,
-        HostComputer:316,
-        Predictor:317,
-        WhitePoint:318,
-        PrimaryChromaticities:319,
-        ColorMap:320,
-        HalftoneHints:321,
-        TileWidth:322,
-        TileLength:323,
-        TileOffsets:324,
-        TileByteCounts:325,
-        SubIFDs:330,
-        InkSet:332,
-        InkNames:333,
-        NumberOfInks:334,
-        DotRange:336,
-        TargetPrinter:337,
-        ExtraSamples:338,
-        SampleFormat:339,
-        SMinSampleValue:340,
-        SMaxSampleValue:341,
-        TransferRange:342,
-        ClipPath:343,
-        XClipPathUnits:344,
-        YClipPathUnits:345,
-        Indexed:346,
-        JPEGTables:347,
-        OPIProxy:351,
-        JPEGProc:512,
-        JPEGInterchangeFormat:513,
-        JPEGInterchangeFormatLength:514,
-        JPEGRestartInterval:515,
-        JPEGLosslessPredictors:517,
-        JPEGPointTransforms:518,
-        JPEGQTables:519,
-        JPEGDCTables:520,
-        JPEGACTables:521,
-        YCbCrCoefficients:529,
-        YCbCrSubSampling:530,
-        YCbCrPositioning:531,
-        ReferenceBlackWhite:532,
-        XMLPacket:700,
-        Rating:18246,
-        RatingPercent:18249,
-        ImageID:32781,
-        CFARepeatPatternDim:33421,
-        CFAPattern:33422,
-        BatteryLevel:33423,
-        Copyright:33432,
-        ExposureTime:33434,
-        ImageResources:34377,
-        ExifTag:34665,
-        InterColorProfile:34675,
-        GPSTag:34853,
-        Interlace:34857,
-        TimeZoneOffset:34858,
-        SelfTimerMode:34859,
-        FlashEnergy:37387,
-        SpatialFrequencyResponse:37388,
-        Noise:37389,
-        FocalPlaneXResolution:37390,
-        FocalPlaneYResolution:37391,
-        FocalPlaneResolutionUnit:37392,
-        ImageNumber:37393,
-        SecurityClassification:37394,
-        ImageHistory:37395,
-        ExposureIndex:37397,
-        TIFFEPStandardID:37398,
-        SensingMethod:37399,
-        XPTitle:40091,
-        XPComment:40092,
-        XPAuthor:40093,
-        XPKeywords:40094,
-        XPSubject:40095,
-        PrintImageMatching:50341,
-        DNGVersion:50706,
-        DNGBackwardVersion:50707,
-        UniqueCameraModel:50708,
-        LocalizedCameraModel:50709,
-        CFAPlaneColor:50710,
-        CFALayout:50711,
-        LinearizationTable:50712,
-        BlackLevelRepeatDim:50713,
-        BlackLevel:50714,
-        BlackLevelDeltaH:50715,
-        BlackLevelDeltaV:50716,
-        WhiteLevel:50717,
-        DefaultScale:50718,
-        DefaultCropOrigin:50719,
-        DefaultCropSize:50720,
-        ColorMatrix1:50721,
-        ColorMatrix2:50722,
-        CameraCalibration1:50723,
-        CameraCalibration2:50724,
-        ReductionMatrix1:50725,
-        ReductionMatrix2:50726,
-        AnalogBalance:50727,
-        AsShotNeutral:50728,
-        AsShotWhiteXY:50729,
-        BaselineExposure:50730,
-        BaselineNoise:50731,
-        BaselineSharpness:50732,
-        BayerGreenSplit:50733,
-        LinearResponseLimit:50734,
-        CameraSerialNumber:50735,
-        LensInfo:50736,
-        ChromaBlurRadius:50737,
-        AntiAliasStrength:50738,
-        ShadowScale:50739,
-        DNGPrivateData:50740,
-        MakerNoteSafety:50741,
-        CalibrationIlluminant1:50778,
-        CalibrationIlluminant2:50779,
-        BestQualityScale:50780,
-        RawDataUniqueID:50781,
-        OriginalRawFileName:50827,
-        OriginalRawFileData:50828,
-        ActiveArea:50829,
-        MaskedAreas:50830,
-        AsShotICCProfile:50831,
-        AsShotPreProfileMatrix:50832,
-        CurrentICCProfile:50833,
-        CurrentPreProfileMatrix:50834,
-        ColorimetricReference:50879,
-        CameraCalibrationSignature:50931,
-        ProfileCalibrationSignature:50932,
-        AsShotProfileName:50934,
-        NoiseReductionApplied:50935,
-        ProfileName:50936,
-        ProfileHueSatMapDims:50937,
-        ProfileHueSatMapData1:50938,
-        ProfileHueSatMapData2:50939,
-        ProfileToneCurve:50940,
-        ProfileEmbedPolicy:50941,
-        ProfileCopyright:50942,
-        ForwardMatrix1:50964,
-        ForwardMatrix2:50965,
-        PreviewApplicationName:50966,
-        PreviewApplicationVersion:50967,
-        PreviewSettingsName:50968,
-        PreviewSettingsDigest:50969,
-        PreviewColorSpace:50970,
-        PreviewDateTime:50971,
-        RawImageDigest:50972,
-        OriginalRawFileDigest:50973,
-        SubTileBlockSize:50974,
-        RowInterleaveFactor:50975,
-        ProfileLookTableDims:50981,
-        ProfileLookTableData:50982,
-        OpcodeList1:51008,
-        OpcodeList2:51009,
-        OpcodeList3:51022,
-        NoiseProfile:51041,
-    };
-
-    
-    that.ExifIFD = {
-        ExposureTime:33434,
-        FNumber:33437,
-        ExposureProgram:34850,
-        SpectralSensitivity:34852,
-        ISOSpeedRatings:34855,
-        OECF:34856,
-        SensitivityType:34864,
-        StandardOutputSensitivity:34865,
-        RecommendedExposureIndex:34866,
-        ISOSpeed:34867,
-        ISOSpeedLatitudeyyy:34868,
-        ISOSpeedLatitudezzz:34869,
-        ExifVersion:36864,
-        DateTimeOriginal:36867,
-        DateTimeDigitized:36868,
-        ComponentsConfiguration:37121,
-        CompressedBitsPerPixel:37122,
-        ShutterSpeedValue:37377,
-        ApertureValue:37378,
-        BrightnessValue:37379,
-        ExposureBiasValue:37380,
-        MaxApertureValue:37381,
-        SubjectDistance:37382,
-        MeteringMode:37383,
-        LightSource:37384,
-        Flash:37385,
-        FocalLength:37386,
-        SubjectArea:37396,
-        MakerNote:37500,
-        UserComment:37510,
-        SubSecTime:37520,
-        SubSecTimeOriginal:37521,
-        SubSecTimeDigitized:37522,
-        FlashpixVersion:40960,
-        ColorSpace:40961,
-        PixelXDimension:40962,
-        PixelYDimension:40963,
-        RelatedSoundFile:40964,
-        InteroperabilityTag:40965,
-        FlashEnergy:41483,
-        SpatialFrequencyResponse:41484,
-        FocalPlaneXResolution:41486,
-        FocalPlaneYResolution:41487,
-        FocalPlaneResolutionUnit:41488,
-        SubjectLocation:41492,
-        ExposureIndex:41493,
-        SensingMethod:41495,
-        FileSource:41728,
-        SceneType:41729,
-        CFAPattern:41730,
-        CustomRendered:41985,
-        ExposureMode:41986,
-        WhiteBalance:41987,
-        DigitalZoomRatio:41988,
-        FocalLengthIn35mmFilm:41989,
-        SceneCaptureType:41990,
-        GainControl:41991,
-        Contrast:41992,
-        Saturation:41993,
-        Sharpness:41994,
-        DeviceSettingDescription:41995,
-        SubjectDistanceRange:41996,
-        ImageUniqueID:42016,
-        CameraOwnerName:42032,
-        BodySerialNumber:42033,
-        LensSpecification:42034,
-        LensMake:42035,
-        LensModel:42036,
-        LensSerialNumber:42037,
-        Gamma:42240,
-    };
-
-
-    that.GPSIFD = {
-        GPSVersionID:0,
-        GPSLatitudeRef:1,
-        GPSLatitude:2,
-        GPSLongitudeRef:3,
-        GPSLongitude:4,
-        GPSAltitudeRef:5,
-        GPSAltitude:6,
-        GPSTimeStamp:7,
-        GPSSatellites:8,
-        GPSStatus:9,
-        GPSMeasureMode:10,
-        GPSDOP:11,
-        GPSSpeedRef:12,
-        GPSSpeed:13,
-        GPSTrackRef:14,
-        GPSTrack:15,
-        GPSImgDirectionRef:16,
-        GPSImgDirection:17,
-        GPSMapDatum:18,
-        GPSDestLatitudeRef:19,
-        GPSDestLatitude:20,
-        GPSDestLongitudeRef:21,
-        GPSDestLongitude:22,
-        GPSDestBearingRef:23,
-        GPSDestBearing:24,
-        GPSDestDistanceRef:25,
-        GPSDestDistance:26,
-        GPSProcessingMethod:27,
-        GPSAreaInformation:28,
-        GPSDateStamp:29,
-        GPSDifferential:30,
-        GPSHPositioningError:31,
-    };
-
-
-    that.InteropIFD = {
-        InteroperabilityIndex:1,
-    };
-
-    that.GPSHelper = {
-        degToDmsRational:function (degFloat) {
-            var minFloat = degFloat % 1 * 60;
-            var secFloat = minFloat % 1 * 60;
-            var deg = Math.floor(degFloat);
-            var min = Math.floor(minFloat);
-            var sec = Math.round(secFloat * 100);
-
-            return [[deg, 1], [min, 1], [sec, 100]];
-        }
-    };
-    
-    
-    if (typeof exports !== 'undefined') {
-        if (typeof module !== 'undefined' && module.exports) {
-            exports = module.exports = that;
-        }
-        exports.piexif = that;
-    } else {
-        window.piexif = that;
-    }
-
-})();

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
src/main/resources/static/js/plugins/fileinput/plugins/piexif.min.js


+ 0 - 812
src/main/resources/static/js/plugins/fileinput/plugins/purify.js

@@ -1,812 +0,0 @@
-;(function(factory) {
-    'use strict';
-    /* global window: false, define: false, module: false */
-    var root = typeof window === 'undefined' ? null : window;
-
-    if (typeof define === 'function' && define.amd) {
-        define(function(){ return factory(root); });
-    } else if (typeof module !== 'undefined') {
-        module.exports = factory(root);
-    } else {
-        root.DOMPurify = factory(root);
-    }
-}(function factory(window) {
-    'use strict';
-
-    var DOMPurify = function(window) {
-        return factory(window);
-    };
-
-    /**
-     * Version label, exposed for easier checks
-     * if DOMPurify is up to date or not
-     */
-    DOMPurify.version = '0.7.4';
-
-    if (!window || !window.document || window.document.nodeType !== 9) {
-        // not running in a browser, provide a factory function
-        // so that you can pass your own Window
-        DOMPurify.isSupported = false;
-        return DOMPurify;
-    }
-
-    var document = window.document;
-    var originalDocument = document;
-    var DocumentFragment = window.DocumentFragment;
-    var HTMLTemplateElement = window.HTMLTemplateElement;
-    var NodeFilter = window.NodeFilter;
-    var NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap;
-    var Text = window.Text;
-    var Comment = window.Comment;
-    var DOMParser = window.DOMParser;
-
-    // As per issue #47, the web-components registry is inherited by a
-    // new document created via createHTMLDocument. As per the spec
-    // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
-    // a new empty registry is used when creating a template contents owner
-    // document, so we use that as our parent document to ensure nothing
-    // is inherited.
-    if (typeof HTMLTemplateElement === 'function') {
-        var template = document.createElement('template');
-        if (template.content && template.content.ownerDocument) {
-            document = template.content.ownerDocument;
-        }
-    }
-    var implementation = document.implementation;
-    var createNodeIterator = document.createNodeIterator;
-    var getElementsByTagName = document.getElementsByTagName;
-    var createDocumentFragment = document.createDocumentFragment;
-    var importNode = originalDocument.importNode;
-
-    var hooks = {};
-
-    /**
-     * Expose whether this browser supports running the full DOMPurify.
-     */
-    DOMPurify.isSupported =
-        typeof implementation.createHTMLDocument !== 'undefined' &&
-        document.documentMode !== 9;
-
-    /* Add properties to a lookup table */
-    var _addToSet = function(set, array) {
-        var l = array.length;
-        while (l--) {
-            if (typeof array[l] === 'string') {
-                array[l] = array[l].toLowerCase();
-            }
-            set[array[l]] = true;
-        }
-        return set;
-    };
-
-    /* Shallow clone an object */
-    var _cloneObj = function(object) {
-        var newObject = {};
-        var property;
-        for (property in object) {
-            if (object.hasOwnProperty(property)) {
-                newObject[property] = object[property];
-            }
-        }
-        return newObject;
-    };
-
-    /**
-     * We consider the elements and attributes below to be safe. Ideally
-     * don't add any new ones but feel free to remove unwanted ones.
-     */
-
-    /* allowed element names */
-    var ALLOWED_TAGS = null;
-    var DEFAULT_ALLOWED_TAGS = _addToSet({}, [
-
-        // HTML
-        'a','abbr','acronym','address','area','article','aside','audio','b',
-        'bdi','bdo','big','blink','blockquote','body','br','button','canvas',
-        'caption','center','cite','code','col','colgroup','content','data',
-        'datalist','dd','decorator','del','details','dfn','dir','div','dl','dt',
-        'element','em','fieldset','figcaption','figure','font','footer','form',
-        'h1','h2','h3','h4','h5','h6','head','header','hgroup','hr','html','i',
-        'img','input','ins','kbd','label','legend','li','main','map','mark',
-        'marquee','menu','menuitem','meter','nav','nobr','ol','optgroup',
-        'option','output','p','pre','progress','q','rp','rt','ruby','s','samp',
-        'section','select','shadow','small','source','spacer','span','strike',
-        'strong','style','sub','summary','sup','table','tbody','td','template',
-        'textarea','tfoot','th','thead','time','tr','track','tt','u','ul','var',
-        'video','wbr',
-
-        // SVG
-        'svg','altglyph','altglyphdef','altglyphitem','animatecolor',
-        'animatemotion','animatetransform','circle','clippath','defs','desc',
-        'ellipse','filter','font','g','glyph','glyphref','hkern','image','line',
-        'lineargradient','marker','mask','metadata','mpath','path','pattern',
-        'polygon','polyline','radialgradient','rect','stop','switch','symbol',
-        'text','textpath','title','tref','tspan','view','vkern',
-
-        // SVG Filters
-        'feBlend','feColorMatrix','feComponentTransfer','feComposite',
-        'feConvolveMatrix','feDiffuseLighting','feDisplacementMap',
-        'feFlood','feFuncA','feFuncB','feFuncG','feFuncR','feGaussianBlur',
-        'feMerge','feMergeNode','feMorphology','feOffset',
-        'feSpecularLighting','feTile','feTurbulence',
-
-        //MathML
-        'math','menclose','merror','mfenced','mfrac','mglyph','mi','mlabeledtr',
-        'mmuliscripts','mn','mo','mover','mpadded','mphantom','mroot','mrow',
-        'ms','mpspace','msqrt','mystyle','msub','msup','msubsup','mtable','mtd',
-        'mtext','mtr','munder','munderover',
-
-        //Text
-        '#text'
-    ]);
-
-    /* Allowed attribute names */
-    var ALLOWED_ATTR = null;
-    var DEFAULT_ALLOWED_ATTR = _addToSet({}, [
-
-        // HTML
-        'accept','action','align','alt','autocomplete','background','bgcolor',
-        'border','cellpadding','cellspacing','checked','cite','class','clear','color',
-        'cols','colspan','coords','datetime','default','dir','disabled',
-        'download','enctype','face','for','headers','height','hidden','high','href',
-        'hreflang','id','ismap','label','lang','list','loop', 'low','max',
-        'maxlength','media','method','min','multiple','name','noshade','novalidate',
-        'nowrap','open','optimum','pattern','placeholder','poster','preload','pubdate',
-        'radiogroup','readonly','rel','required','rev','reversed','rows',
-        'rowspan','spellcheck','scope','selected','shape','size','span',
-        'srclang','start','src','step','style','summary','tabindex','title',
-        'type','usemap','valign','value','width','xmlns',
-
-        // SVG
-        'accent-height','accumulate','additivive','alignment-baseline',
-        'ascent','attributename','attributetype','azimuth','basefrequency',
-        'baseline-shift','begin','bias','by','clip','clip-path','clip-rule',
-        'color','color-interpolation','color-interpolation-filters','color-profile',
-        'color-rendering','cx','cy','d','dx','dy','diffuseconstant','direction',
-        'display','divisor','dur','edgemode','elevation','end','fill','fill-opacity',
-        'fill-rule','filter','flood-color','flood-opacity','font-family','font-size',
-        'font-size-adjust','font-stretch','font-style','font-variant','font-weight',
-        'fx', 'fy','g1','g2','glyph-name','glyphref','gradientunits','gradienttransform',
-        'image-rendering','in','in2','k','k1','k2','k3','k4','kerning','keypoints',
-        'keysplines','keytimes','lengthadjust','letter-spacing','kernelmatrix',
-        'kernelunitlength','lighting-color','local','marker-end','marker-mid',
-        'marker-start','markerheight','markerunits','markerwidth','maskcontentunits',
-        'maskunits','max','mask','mode','min','numoctaves','offset','operator',
-        'opacity','order','orient','orientation','origin','overflow','paint-order',
-        'path','pathlength','patterncontentunits','patterntransform','patternunits',
-        'points','preservealpha','r','rx','ry','radius','refx','refy','repeatcount',
-        'repeatdur','restart','result','rotate','scale','seed','shape-rendering',
-        'specularconstant','specularexponent','spreadmethod','stddeviation','stitchtiles',
-        'stop-color','stop-opacity','stroke-dasharray','stroke-dashoffset','stroke-linecap',
-        'stroke-linejoin','stroke-miterlimit','stroke-opacity','stroke','stroke-width',
-        'surfacescale','targetx','targety','transform','text-anchor','text-decoration',
-        'text-rendering','textlength','u1','u2','unicode','values','viewbox',
-        'visibility','vert-adv-y','vert-origin-x','vert-origin-y','word-spacing',
-        'wrap','writing-mode','xchannelselector','ychannelselector','x','x1','x2',
-        'y','y1','y2','z','zoomandpan',
-
-        // MathML
-        'accent','accentunder','bevelled','close','columnsalign','columnlines',
-        'columnspan','denomalign','depth','display','displaystyle','fence',
-        'frame','largeop','length','linethickness','lspace','lquote',
-        'mathbackground','mathcolor','mathsize','mathvariant','maxsize',
-        'minsize','movablelimits','notation','numalign','open','rowalign',
-        'rowlines','rowspacing','rowspan','rspace','rquote','scriptlevel',
-        'scriptminsize','scriptsizemultiplier','selection','separator',
-        'separators','stretchy','subscriptshift','supscriptshift','symmetric',
-        'voffset',
-
-        // XML
-        'xlink:href','xml:id','xlink:title','xml:space','xmlns:xlink'
-    ]);
-
-    /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
-    var FORBID_TAGS = null;
-
-    /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
-    var FORBID_ATTR = null;
-
-    /* Decide if custom data attributes are okay */
-    var ALLOW_DATA_ATTR = true;
-
-    /* Decide if unknown protocols are okay */
-    var ALLOW_UNKNOWN_PROTOCOLS = false;
-
-    /* Output should be safe for jQuery's $() factory? */
-    var SAFE_FOR_JQUERY = false;
-
-    /* Output should be safe for common template engines.
-     * This means, DOMPurify removes data attributes, mustaches and ERB
-     */
-    var SAFE_FOR_TEMPLATES = false;
-
-    /* Specify template detection regex for SAFE_FOR_TEMPLATES mode */
-    var MUSTACHE_EXPR = /\{\{[\s\S]*|[\s\S]*\}\}/gm;
-    var ERB_EXPR = /<%[\s\S]*|[\s\S]*%>/gm;
-
-    /* Decide if document with <html>... should be returned */
-    var WHOLE_DOCUMENT = false;
-
-    /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html string.
-     * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
-     */
-    var RETURN_DOM = false;
-
-    /* Decide if a DOM `DocumentFragment` should be returned, instead of a html string */
-    var RETURN_DOM_FRAGMENT = false;
-
-    /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM
-     * `Node` is imported into the current `Document`. If this flag is not enabled the
-     * `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by
-     * DOMPurify. */
-    var RETURN_DOM_IMPORT = false;
-
-    /* Output should be free from DOM clobbering attacks? */
-    var SANITIZE_DOM = true;
-
-    /* Keep element content when removing element? */
-    var KEEP_CONTENT = true;
-
-    /* Tags to ignore content of when KEEP_CONTENT is true */
-    var FORBID_CONTENTS = _addToSet({}, [
-        'audio', 'head', 'math', 'script', 'style', 'svg', 'video'
-    ]);
-
-    /* Tags that are safe for data: URIs */
-    var DATA_URI_TAGS = _addToSet({}, [
-        'audio', 'video', 'img', 'source'
-    ]);
-
-    /* Attributes safe for values like "javascript:" */
-    var URI_SAFE_ATTRIBUTES = _addToSet({}, [
-        'alt','class','for','id','label','name','pattern','placeholder',
-        'summary','title','value','style','xmlns'
-    ]);
-
-    /* Keep a reference to config to pass to hooks */
-    var CONFIG = null;
-
-    /* Ideally, do not touch anything below this line */
-    /* ______________________________________________ */
-
-    var formElement = document.createElement('form');
-
-    /**
-     * _parseConfig
-     *
-     * @param  optional config literal
-     */
-    var _parseConfig = function(cfg) {
-        /* Shield configuration object from tampering */
-        if (typeof cfg !== 'object') {
-            cfg = {};
-        }
-
-        /* Set configuration parameters */
-        ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ?
-            _addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
-        ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ?
-            _addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
-        FORBID_TAGS = 'FORBID_TAGS' in cfg ?
-            _addToSet({}, cfg.FORBID_TAGS) : {};
-        FORBID_ATTR = 'FORBID_ATTR' in cfg ?
-            _addToSet({}, cfg.FORBID_ATTR) : {};
-        ALLOW_DATA_ATTR     = cfg.ALLOW_DATA_ATTR     !== false; // Default true
-        ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
-        SAFE_FOR_JQUERY     = cfg.SAFE_FOR_JQUERY     ||  false; // Default false
-        SAFE_FOR_TEMPLATES  = cfg.SAFE_FOR_TEMPLATES  ||  false; // Default false
-        WHOLE_DOCUMENT      = cfg.WHOLE_DOCUMENT      ||  false; // Default false
-        RETURN_DOM          = cfg.RETURN_DOM          ||  false; // Default false
-        RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT ||  false; // Default false
-        RETURN_DOM_IMPORT   = cfg.RETURN_DOM_IMPORT   ||  false; // Default false
-        SANITIZE_DOM        = cfg.SANITIZE_DOM        !== false; // Default true
-        KEEP_CONTENT        = cfg.KEEP_CONTENT        !== false; // Default true
-
-        if (SAFE_FOR_TEMPLATES) {
-            ALLOW_DATA_ATTR = false;
-        }
-
-        if (RETURN_DOM_FRAGMENT) {
-            RETURN_DOM = true;
-        }
-
-        /* Merge configuration parameters */
-        if (cfg.ADD_TAGS) {
-            if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
-                ALLOWED_TAGS = _cloneObj(ALLOWED_TAGS);
-            }
-            _addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
-        }
-        if (cfg.ADD_ATTR) {
-            if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
-                ALLOWED_ATTR = _cloneObj(ALLOWED_ATTR);
-            }
-            _addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
-        }
-
-        /* Add #text in case KEEP_CONTENT is set to true */
-        if (KEEP_CONTENT) { ALLOWED_TAGS['#text'] = true; }
-
-        // Prevent further manipulation of configuration.
-        // Not available in IE8, Safari 5, etc.
-        if (Object && 'freeze' in Object) { Object.freeze(cfg); }
-
-        CONFIG = cfg;
-    };
-
-   /**
-     * _forceRemove
-     *
-     * @param  a DOM node
-     */
-    var _forceRemove = function(node) {
-        try {
-            node.parentNode.removeChild(node);
-        } catch (e) {
-            node.outerHTML = '';
-        }
-    };
-
-   /**
-     * _initDocument
-     *
-     * @param  a string of dirty markup
-     * @return a DOM, filled with the dirty markup
-     */
-    var _initDocument = function(dirty) {
-        /* Create a HTML document using DOMParser */
-        var doc, body;
-        try {
-            doc = new DOMParser().parseFromString(dirty, 'text/html');
-        } catch (e) {}
-
-        /* Some browsers throw, some browsers return null for the code above
-           DOMParser with text/html support is only in very recent browsers. */
-        if (!doc) {
-            doc = implementation.createHTMLDocument('');
-            body = doc.body;
-            body.parentNode.removeChild(body.parentNode.firstElementChild);
-            body.outerHTML = dirty;
-        }
-
-        /* Work on whole document or just its body */
-        if (typeof doc.getElementsByTagName === 'function') {
-            return doc.getElementsByTagName(
-                WHOLE_DOCUMENT ? 'html' : 'body')[0];
-        }
-        return getElementsByTagName.call(doc,
-            WHOLE_DOCUMENT ? 'html' : 'body')[0];
-    };
-
-    /**
-     * _createIterator
-     *
-     * @param  document/fragment to create iterator for
-     * @return iterator instance
-     */
-    var _createIterator = function(root) {
-        return createNodeIterator.call(root.ownerDocument || root,
-            root,
-            NodeFilter.SHOW_ELEMENT
-            | NodeFilter.SHOW_COMMENT
-            | NodeFilter.SHOW_TEXT,
-            function() { return NodeFilter.FILTER_ACCEPT; },
-            false
-        );
-    };
-
-    /**
-     * _isClobbered
-     *
-     * @param  element to check for clobbering attacks
-     * @return true if clobbered, false if safe
-     */
-    var _isClobbered = function(elm) {
-        if (elm instanceof Text || elm instanceof Comment) {
-            return false;
-        }
-        if (  typeof elm.nodeName !== 'string'
-           || typeof elm.textContent !== 'string'
-           || typeof elm.removeChild !== 'function'
-           || !(elm.attributes instanceof NamedNodeMap)
-           || typeof elm.removeAttribute !== 'function'
-           || typeof elm.setAttribute !== 'function'
-        ) {
-            return true;
-        }
-        return false;
-    };
-
-    /**
-     * _sanitizeElements
-     *
-     * @protect nodeName
-     * @protect textContent
-     * @protect removeChild
-     *
-     * @param   node to check for permission to exist
-     * @return  true if node was killed, false if left alive
-     */
-    var _sanitizeElements = function(currentNode) {
-        var tagName, content;
-        /* Execute a hook if present */
-        _executeHook('beforeSanitizeElements', currentNode, null);
-
-        /* Check if element is clobbered or can clobber */
-        if (_isClobbered(currentNode)) {
-            _forceRemove(currentNode);
-            return true;
-        }
-
-        /* Now let's check the element's type and name */
-        tagName = currentNode.nodeName.toLowerCase();
-
-        /* Execute a hook if present */
-        _executeHook('uponSanitizeElement', currentNode, {
-            tagName: tagName
-        });
-
-        /* Remove element if anything forbids its presence */
-        if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
-            /* Keep content except for black-listed elements */
-            if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]
-                    && typeof currentNode.insertAdjacentHTML === 'function') {
-                try {
-                    currentNode.insertAdjacentHTML('AfterEnd', currentNode.innerHTML);
-                } catch (e) {}
-            }
-            _forceRemove(currentNode);
-            return true;
-        }
-
-        /* Convert markup to cover jQuery behavior */
-        if (SAFE_FOR_JQUERY && !currentNode.firstElementChild &&
-                (!currentNode.content || !currentNode.content.firstElementChild)) {
-            currentNode.innerHTML = currentNode.textContent.replace(/</g, '&lt;');
-        }
-
-        /* Sanitize element content to be template-safe */
-        if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
-            /* Get the element's text content */
-            content = currentNode.textContent;
-            content = content.replace(MUSTACHE_EXPR, ' ');
-            content = content.replace(ERB_EXPR, ' ');
-            currentNode.textContent = content;
-        }
-
-        /* Execute a hook if present */
-        _executeHook('afterSanitizeElements', currentNode, null);
-
-        return false;
-    };
-
-    var DATA_ATTR = /^data-[\w.\u00B7-\uFFFF-]/;
-    var IS_ALLOWED_URI = /^(?:(?:(?:f|ht)tps?|mailto|tel):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
-    var IS_SCRIPT_OR_DATA = /^(?:\w+script|data):/i;
-    /* This needs to be extensive thanks to Webkit/Blink's behavior */
-    var ATTR_WHITESPACE = /[\x00-\x20\xA0\u1680\u180E\u2000-\u2029\u205f\u3000]/g;
-
-    /**
-     * _sanitizeAttributes
-     *
-     * @protect attributes
-     * @protect nodeName
-     * @protect removeAttribute
-     * @protect setAttribute
-     *
-     * @param   node to sanitize
-     * @return  void
-     */
-    var _sanitizeAttributes = function(currentNode) {
-        var attr, name, value, lcName, idAttr, attributes, hookEvent, l;
-        /* Execute a hook if present */
-        _executeHook('beforeSanitizeAttributes', currentNode, null);
-
-        attributes = currentNode.attributes;
-
-        /* Check if we have attributes; if not we might have a text node */
-        if (!attributes) { return; }
-
-        hookEvent = {
-            attrName: '',
-            attrValue: '',
-            keepAttr: true
-        };
-        l = attributes.length;
-
-        /* Go backwards over all attributes; safely remove bad ones */
-        while (l--) {
-            attr = attributes[l];
-            name = attr.name;
-            value = attr.value;
-            lcName = name.toLowerCase();
-
-            /* Execute a hook if present */
-            hookEvent.attrName = lcName;
-            hookEvent.attrValue = value;
-            hookEvent.keepAttr = true;
-            _executeHook('uponSanitizeAttribute', currentNode, hookEvent );
-            value = hookEvent.attrValue;
-
-            /* Remove attribute */
-            // Safari (iOS + Mac), last tested v8.0.5, crashes if you try to
-            // remove a "name" attribute from an <img> tag that has an "id"
-            // attribute at the time.
-            if (lcName === 'name'  &&
-                    currentNode.nodeName === 'IMG' && attributes.id) {
-                idAttr = attributes.id;
-                attributes = Array.prototype.slice.apply(attributes);
-                currentNode.removeAttribute('id');
-                currentNode.removeAttribute(name);
-                if (attributes.indexOf(idAttr) > l) {
-                    currentNode.setAttribute('id', idAttr.value);
-                }
-            } else {
-                // This avoids a crash in Safari v9.0 with double-ids.
-                // The trick is to first set the id to be empty and then to
-                // remove the attriubute
-                if (name === 'id') {
-                    currentNode.setAttribute(name, '');
-                }
-                currentNode.removeAttribute(name);
-            }
-
-            /* Did the hooks approve of the attribute? */
-            if (!hookEvent.keepAttr) {
-                continue;
-            }
-
-            /* Make sure attribute cannot clobber */
-            if (SANITIZE_DOM &&
-                    (lcName === 'id' || lcName === 'name') &&
-                    (value in window || value in document || value in formElement)) {
-                continue;
-            }
-
-            /* Sanitize attribute content to be template-safe */
-            if (SAFE_FOR_TEMPLATES) {
-                value = value.replace(MUSTACHE_EXPR, ' ');
-                value = value.replace(ERB_EXPR, ' ');
-            }
-
-            if (
-                /* Check the name is permitted */
-                (ALLOWED_ATTR[lcName] && !FORBID_ATTR[lcName] && (
-                  /* Check no script, data or unknown possibly unsafe URI
-                     unless we know URI values are safe for that attribute */
-                  URI_SAFE_ATTRIBUTES[lcName] ||
-                  IS_ALLOWED_URI.test(value.replace(ATTR_WHITESPACE,'')) ||
-                  /* Keep image data URIs alive if src is allowed */
-                  (lcName === 'src' && value.indexOf('data:') === 0 &&
-                   DATA_URI_TAGS[currentNode.nodeName.toLowerCase()])
-                )) ||
-                /* Allow potentially valid data-* attributes:
-                 * At least one character after "-" (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
-                 * XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
-                 * We don't need to check the value; it's always URI safe.
-                 */
-                 (ALLOW_DATA_ATTR && DATA_ATTR.test(lcName)) ||
-                 /* Allow unknown protocols:
-                  * This provides support for links that are handled by protocol handlers which may be unknown
-                  * ahead of time, e.g. fb:, spotify:
-                  */
-                 (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA.test(value.replace(ATTR_WHITESPACE,'')))
-            ) {
-                /* Handle invalid data-* attribute set by try-catching it */
-                try {
-                    currentNode.setAttribute(name, value);
-                } catch (e) {}
-            }
-        }
-
-        /* Execute a hook if present */
-        _executeHook('afterSanitizeAttributes', currentNode, null);
-    };
-
-    /**
-     * _sanitizeShadowDOM
-     *
-     * @param  fragment to iterate over recursively
-     * @return void
-     */
-    var _sanitizeShadowDOM = function(fragment) {
-        var shadowNode;
-        var shadowIterator = _createIterator(fragment);
-
-        /* Execute a hook if present */
-        _executeHook('beforeSanitizeShadowDOM', fragment, null);
-
-        while ( (shadowNode = shadowIterator.nextNode()) ) {
-            /* Execute a hook if present */
-            _executeHook('uponSanitizeShadowNode', shadowNode, null);
-
-            /* Sanitize tags and elements */
-            if (_sanitizeElements(shadowNode)) {
-                continue;
-            }
-
-            /* Deep shadow DOM detected */
-            if (shadowNode.content instanceof DocumentFragment) {
-                _sanitizeShadowDOM(shadowNode.content);
-            }
-
-            /* Check attributes, sanitize if necessary */
-            _sanitizeAttributes(shadowNode);
-        }
-
-        /* Execute a hook if present */
-        _executeHook('afterSanitizeShadowDOM', fragment, null);
-    };
-
-    /**
-     * _executeHook
-     * Execute user configurable hooks
-     *
-     * @param  {String} entryPoint  Name of the hook's entry point
-     * @param  {Node} currentNode
-     */
-    var _executeHook = function(entryPoint, currentNode, data) {
-        if (!hooks[entryPoint]) { return; }
-
-        hooks[entryPoint].forEach(function(hook) {
-            hook.call(DOMPurify, currentNode, data, CONFIG);
-        });
-    };
-
-    /**
-     * sanitize
-     * Public method providing core sanitation functionality
-     *
-     * @param {String} dirty string
-     * @param {Object} configuration object
-     */
-    DOMPurify.sanitize = function(dirty, cfg) {
-        var body, currentNode, oldNode, nodeIterator, returnNode;
-        /* Make sure we have a string to sanitize.
-           DO NOT return early, as this will return the wrong type if
-           the user has requested a DOM object rather than a string */
-        if (!dirty) {
-            dirty = '';
-        }
-
-        /* Stringify, in case dirty is an object */
-        if (typeof dirty !== 'string') {
-            if (typeof dirty.toString !== 'function') {
-                throw new TypeError('toString is not a function');
-            } else {
-                dirty = dirty.toString();
-            }
-        }
-
-        /* Check we can run. Otherwise fall back or ignore */
-        if (!DOMPurify.isSupported) {
-            if (typeof window.toStaticHTML === 'object'
-                || typeof window.toStaticHTML === 'function') {
-                return window.toStaticHTML(dirty);
-            }
-            return dirty;
-        }
-
-        /* Assign config vars */
-        _parseConfig(cfg);
-
-        /* Exit directly if we have nothing to do */
-        if (!RETURN_DOM && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
-            return dirty;
-        }
-
-        /* Initialize the document to work on */
-        body = _initDocument(dirty);
-
-        /* Check we have a DOM node from the data */
-        if (!body) {
-            return RETURN_DOM ? null : '';
-        }
-
-        /* Get node iterator */
-        nodeIterator = _createIterator(body);
-
-        /* Now start iterating over the created document */
-        while ( (currentNode = nodeIterator.nextNode()) ) {
-
-            /* Fix IE's strange behavior with manipulated textNodes #89 */
-            if (currentNode.nodeType === 3 && currentNode === oldNode) {
-                continue;
-            }
-
-            /* Sanitize tags and elements */
-            if (_sanitizeElements(currentNode)) {
-                continue;
-            }
-
-            /* Shadow DOM detected, sanitize it */
-            if (currentNode.content instanceof DocumentFragment) {
-                _sanitizeShadowDOM(currentNode.content);
-            }
-
-            /* Check attributes, sanitize if necessary */
-            _sanitizeAttributes(currentNode);
-
-            oldNode = currentNode;
-        }
-
-        /* Return sanitized string or DOM */
-        if (RETURN_DOM) {
-
-            if (RETURN_DOM_FRAGMENT) {
-                returnNode = createDocumentFragment.call(body.ownerDocument);
-
-                while (body.firstChild) {
-                    returnNode.appendChild(body.firstChild);
-                }
-            } else {
-                returnNode = body;
-            }
-
-            if (RETURN_DOM_IMPORT) {
-                /* adoptNode() is not used because internal state is not reset
-                   (e.g. the past names map of a HTMLFormElement), this is safe
-                   in theory but we would rather not risk another attack vector.
-                   The state that is cloned by importNode() is explicitly defined
-                   by the specs. */
-                returnNode = importNode.call(originalDocument, returnNode, true);
-            }
-
-            return returnNode;
-        }
-
-        return WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
-    };
-
-    /**
-     * addHook
-     * Public method to add DOMPurify hooks
-     *
-     * @param {String} entryPoint
-     * @param {Function} hookFunction
-     */
-    DOMPurify.addHook = function(entryPoint, hookFunction) {
-        if (typeof hookFunction !== 'function') { return; }
-        hooks[entryPoint] = hooks[entryPoint] || [];
-        hooks[entryPoint].push(hookFunction);
-    };
-
-    /**
-     * removeHook
-     * Public method to remove a DOMPurify hook at a given entryPoint
-     * (pops it from the stack of hooks if more are present)
-     *
-     * @param {String} entryPoint
-     * @return void
-     */
-    DOMPurify.removeHook = function(entryPoint) {
-        if (hooks[entryPoint]) {
-            hooks[entryPoint].pop();
-        }
-    };
-
-    /**
-     * removeHooks
-     * Public method to remove all DOMPurify hooks at a given entryPoint
-     *
-     * @param  {String} entryPoint
-     * @return void
-     */
-    DOMPurify.removeHooks = function(entryPoint) {
-        if (hooks[entryPoint]) {
-            hooks[entryPoint] = [];
-        }
-    };
-
-    /**
-     * removeAllHooks
-     * Public method to remove all DOMPurify hooks
-     *
-     * @return void
-     */
-    DOMPurify.removeAllHooks = function() {
-        hooks = [];
-    };
-
-    return DOMPurify;
-}));

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
src/main/resources/static/js/plugins/fileinput/plugins/purify.min.js


+ 0 - 1590
src/main/resources/static/js/plugins/fileinput/plugins/sortable.js

@@ -1,1590 +0,0 @@
-/**!
- * KvSortable
- * @author	RubaXa   <trash@rubaxa.org>
- * @license MIT
- *
- * Changed kvsortable plugin naming to prevent conflict with JQuery UI Sortable
- * @author Kartik Visweswaran
- */
-
-(function kvsortableModule(factory) {
-	"use strict";
-
-	if (typeof define === "function" && define.amd) {
-		define(factory);
-	}
-	else if (typeof module != "undefined" && typeof module.exports != "undefined") {
-		module.exports = factory();
-	}
-	else {
-		/* jshint sub:true */
-		window["KvSortable"] = factory();
-	}
-})(function kvsortableFactory() {
-	"use strict";
-
-	if (typeof window === "undefined" || !window.document) {
-		return function kvsortableError() {
-			throw new Error("KvSortable.js requires a window with a document");
-		};
-	}
-
-	var dragEl,
-		parentEl,
-		ghostEl,
-		cloneEl,
-		rootEl,
-		nextEl,
-		lastDownEl,
-
-		scrollEl,
-		scrollParentEl,
-		scrollCustomFn,
-
-		lastEl,
-		lastCSS,
-		lastParentCSS,
-
-		oldIndex,
-		newIndex,
-
-		activeGroup,
-		putKvSortable,
-
-		autoScroll = {},
-
-		tapEvt,
-		touchEvt,
-
-		moved,
-
-		/** @const */
-		R_SPACE = /\s+/g,
-		R_FLOAT = /left|right|inline/,
-
-		expando = 'KvSortable' + (new Date).getTime(),
-
-		win = window,
-		document = win.document,
-		parseInt = win.parseInt,
-		setTimeout = win.setTimeout,
-
-		$ = win.jQuery || win.Zepto,
-		Polymer = win.Polymer,
-
-		captureMode = false,
-		passiveMode = false,
-
-		supportDraggable = ('draggable' in document.createElement('div')),
-		supportCssPointerEvents = (function (el) {
-			// false when IE11
-			if (!!navigator.userAgent.match(/(?:Trident.*rv[ :]?11\.|msie)/i)) {
-				return false;
-			}
-			el = document.createElement('x');
-			el.style.cssText = 'pointer-events:auto';
-			return el.style.pointerEvents === 'auto';
-		})(),
-
-		_silent = false,
-
-		abs = Math.abs,
-		min = Math.min,
-
-		savedInputChecked = [],
-		touchDragOverListeners = [],
-
-		_autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl) {
-			// Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
-			if (rootEl && options.scroll) {
-				var _this = rootEl[expando],
-					el,
-					rect,
-					sens = options.scrollSensitivity,
-					speed = options.scrollSpeed,
-
-					x = evt.clientX,
-					y = evt.clientY,
-
-					winWidth = window.innerWidth,
-					winHeight = window.innerHeight,
-
-					vx,
-					vy,
-
-					scrollOffsetX,
-					scrollOffsetY
-				;
-
-				// Delect scrollEl
-				if (scrollParentEl !== rootEl) {
-					scrollEl = options.scroll;
-					scrollParentEl = rootEl;
-					scrollCustomFn = options.scrollFn;
-
-					if (scrollEl === true) {
-						scrollEl = rootEl;
-
-						do {
-							if ((scrollEl.offsetWidth < scrollEl.scrollWidth) ||
-								(scrollEl.offsetHeight < scrollEl.scrollHeight)
-							) {
-								break;
-							}
-							/* jshint boss:true */
-						} while (scrollEl = scrollEl.parentNode);
-					}
-				}
-
-				if (scrollEl) {
-					el = scrollEl;
-					rect = scrollEl.getBoundingClientRect();
-					vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens);
-					vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens);
-				}
-
-
-				if (!(vx || vy)) {
-					vx = (winWidth - x <= sens) - (x <= sens);
-					vy = (winHeight - y <= sens) - (y <= sens);
-
-					/* jshint expr:true */
-					(vx || vy) && (el = win);
-				}
-
-
-				if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) {
-					autoScroll.el = el;
-					autoScroll.vx = vx;
-					autoScroll.vy = vy;
-
-					clearInterval(autoScroll.pid);
-
-					if (el) {
-						autoScroll.pid = setInterval(function () {
-							scrollOffsetY = vy ? vy * speed : 0;
-							scrollOffsetX = vx ? vx * speed : 0;
-
-							if ('function' === typeof(scrollCustomFn)) {
-								return scrollCustomFn.call(_this, scrollOffsetX, scrollOffsetY, evt);
-							}
-
-							if (el === win) {
-								win.scrollTo(win.pageXOffset + scrollOffsetX, win.pageYOffset + scrollOffsetY);
-							} else {
-								el.scrollTop += scrollOffsetY;
-								el.scrollLeft += scrollOffsetX;
-							}
-						}, 24);
-					}
-				}
-			}
-		}, 30),
-
-		_prepareGroup = function (options) {
-			function toFn(value, pull) {
-				if (value === void 0 || value === true) {
-					value = group.name;
-				}
-
-				if (typeof value === 'function') {
-					return value;
-				} else {
-					return function (to, from) {
-						var fromGroup = from.options.group.name;
-
-						return pull
-							? value
-							: value && (value.join
-								? value.indexOf(fromGroup) > -1
-								: (fromGroup == value)
-							);
-					};
-				}
-			}
-
-			var group = {};
-			var originalGroup = options.group;
-
-			if (!originalGroup || typeof originalGroup != 'object') {
-				originalGroup = {name: originalGroup};
-			}
-
-			group.name = originalGroup.name;
-			group.checkPull = toFn(originalGroup.pull, true);
-			group.checkPut = toFn(originalGroup.put);
-			group.revertClone = originalGroup.revertClone;
-
-			options.group = group;
-		}
-	;
-
-	// Detect support a passive mode
-	try {
-		window.addEventListener('test', null, Object.defineProperty({}, 'passive', {
-			get: function () {
-				// `false`, because everything starts to work incorrectly and instead of d'n'd,
-				// begins the page has scrolled.
-				passiveMode = false;
-				captureMode = {
-					capture: false,
-					passive: passiveMode
-				};
-			}
-		}));
-	} catch (err) {}
-
-	/**
-	 * @class  KvSortable
-	 * @param  {HTMLElement}  el
-	 * @param  {Object}       [options]
-	 */
-	function KvSortable(el, options) {
-		if (!(el && el.nodeType && el.nodeType === 1)) {
-			throw 'KvSortable: `el` must be HTMLElement, and not ' + {}.toString.call(el);
-		}
-
-		this.el = el; // root element
-		this.options = options = _extend({}, options);
-
-
-		// Export instance
-		el[expando] = this;
-
-		// Default options
-		var defaults = {
-			group: Math.random(),
-			sort: true,
-			disabled: false,
-			store: null,
-			handle: null,
-			scroll: true,
-			scrollSensitivity: 30,
-			scrollSpeed: 10,
-			draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*',
-			ghostClass: 'kvsortable-ghost',
-			chosenClass: 'kvsortable-chosen',
-			dragClass: 'kvsortable-drag',
-			ignore: 'a, img',
-			filter: null,
-			preventOnFilter: true,
-			animation: 0,
-			setData: function (dataTransfer, dragEl) {
-				dataTransfer.setData('Text', dragEl.textContent);
-			},
-			dropBubble: false,
-			dragoverBubble: false,
-			dataIdAttr: 'data-id',
-			delay: 0,
-			forceFallback: false,
-			fallbackClass: 'kvsortable-fallback',
-			fallbackOnBody: false,
-			fallbackTolerance: 0,
-			fallbackOffset: {x: 0, y: 0},
-			supportPointer: KvSortable.supportPointer !== false
-		};
-
-
-		// Set default options
-		for (var name in defaults) {
-			!(name in options) && (options[name] = defaults[name]);
-		}
-
-		_prepareGroup(options);
-
-		// Bind all private methods
-		for (var fn in this) {
-			if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
-				this[fn] = this[fn].bind(this);
-			}
-		}
-
-		// Setup drag mode
-		this.nativeDraggable = options.forceFallback ? false : supportDraggable;
-
-		// Bind events
-		_on(el, 'mousedown', this._onTapStart);
-		_on(el, 'touchstart', this._onTapStart);
-		options.supportPointer && _on(el, 'pointerdown', this._onTapStart);
-
-		if (this.nativeDraggable) {
-			_on(el, 'dragover', this);
-			_on(el, 'dragenter', this);
-		}
-
-		touchDragOverListeners.push(this._onDragOver);
-
-		// Restore sorting
-		options.store && this.sort(options.store.get(this));
-	}
-
-
-	KvSortable.prototype = /** @lends KvSortable.prototype */ {
-		constructor: KvSortable,
-
-		_onTapStart: function (/** Event|TouchEvent */evt) {
-			var _this = this,
-				el = this.el,
-				options = this.options,
-				preventOnFilter = options.preventOnFilter,
-				type = evt.type,
-				touch = evt.touches && evt.touches[0],
-				target = (touch || evt).target,
-				originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0]) || target,
-				filter = options.filter,
-				startIndex;
-
-			_saveInputCheckedState(el);
-
-
-			// Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
-			if (dragEl) {
-				return;
-			}
-
-			if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) {
-				return; // only left button or enabled
-			}
-
-			// cancel dnd if original target is content editable
-			if (originalTarget.isContentEditable) {
-				return;
-			}
-
-			target = _closest(target, options.draggable, el);
-
-			if (!target) {
-				return;
-			}
-
-			if (lastDownEl === target) {
-				// Ignoring duplicate `down`
-				return;
-			}
-
-			// Get the index of the dragged element within its parent
-			startIndex = _index(target, options.draggable);
-
-			// Check filter
-			if (typeof filter === 'function') {
-				if (filter.call(this, evt, target, this)) {
-					_dispatchEvent(_this, originalTarget, 'filter', target, el, el, startIndex);
-					preventOnFilter && evt.preventDefault();
-					return; // cancel dnd
-				}
-			}
-			else if (filter) {
-				filter = filter.split(',').some(function (criteria) {
-					criteria = _closest(originalTarget, criteria.trim(), el);
-
-					if (criteria) {
-						_dispatchEvent(_this, criteria, 'filter', target, el, el, startIndex);
-						return true;
-					}
-				});
-
-				if (filter) {
-					preventOnFilter && evt.preventDefault();
-					return; // cancel dnd
-				}
-			}
-
-			if (options.handle && !_closest(originalTarget, options.handle, el)) {
-				return;
-			}
-
-			// Prepare `dragstart`
-			this._prepareDragStart(evt, touch, target, startIndex);
-		},
-
-		_prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target, /** Number */startIndex) {
-			var _this = this,
-				el = _this.el,
-				options = _this.options,
-				ownerDocument = el.ownerDocument,
-				dragStartFn;
-
-			if (target && !dragEl && (target.parentNode === el)) {
-				tapEvt = evt;
-
-				rootEl = el;
-				dragEl = target;
-				parentEl = dragEl.parentNode;
-				nextEl = dragEl.nextSibling;
-				lastDownEl = target;
-				activeGroup = options.group;
-				oldIndex = startIndex;
-
-				this._lastX = (touch || evt).clientX;
-				this._lastY = (touch || evt).clientY;
-
-				dragEl.style['will-change'] = 'all';
-
-				dragStartFn = function () {
-					// Delayed drag has been triggered
-					// we can re-enable the events: touchmove/mousemove
-					_this._disableDelayedDrag();
-
-					// Make the element draggable
-					dragEl.draggable = _this.nativeDraggable;
-
-					// Chosen item
-					_toggleClass(dragEl, options.chosenClass, true);
-
-					// Bind the events: dragstart/dragend
-					_this._triggerDragStart(evt, touch);
-
-					// Drag start event
-					_dispatchEvent(_this, rootEl, 'choose', dragEl, rootEl, rootEl, oldIndex);
-				};
-
-				// Disable "draggable"
-				options.ignore.split(',').forEach(function (criteria) {
-					_find(dragEl, criteria.trim(), _disableDraggable);
-				});
-
-				_on(ownerDocument, 'mouseup', _this._onDrop);
-				_on(ownerDocument, 'touchend', _this._onDrop);
-				_on(ownerDocument, 'touchcancel', _this._onDrop);
-				_on(ownerDocument, 'selectstart', _this);
-				options.supportPointer && _on(ownerDocument, 'pointercancel', _this._onDrop);
-
-				if (options.delay) {
-					// If the user moves the pointer or let go the click or touch
-					// before the delay has been reached:
-					// disable the delayed drag
-					_on(ownerDocument, 'mouseup', _this._disableDelayedDrag);
-					_on(ownerDocument, 'touchend', _this._disableDelayedDrag);
-					_on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);
-					_on(ownerDocument, 'mousemove', _this._disableDelayedDrag);
-					_on(ownerDocument, 'touchmove', _this._disableDelayedDrag);
-					options.supportPointer && _on(ownerDocument, 'pointermove', _this._disableDelayedDrag);
-
-					_this._dragStartTimer = setTimeout(dragStartFn, options.delay);
-				} else {
-					dragStartFn();
-				}
-
-
-			}
-		},
-
-		_disableDelayedDrag: function () {
-			var ownerDocument = this.el.ownerDocument;
-
-			clearTimeout(this._dragStartTimer);
-			_off(ownerDocument, 'mouseup', this._disableDelayedDrag);
-			_off(ownerDocument, 'touchend', this._disableDelayedDrag);
-			_off(ownerDocument, 'touchcancel', this._disableDelayedDrag);
-			_off(ownerDocument, 'mousemove', this._disableDelayedDrag);
-			_off(ownerDocument, 'touchmove', this._disableDelayedDrag);
-			_off(ownerDocument, 'pointermove', this._disableDelayedDrag);
-		},
-
-		_triggerDragStart: function (/** Event */evt, /** Touch */touch) {
-			touch = touch || (evt.pointerType == 'touch' ? evt : null);
-
-			if (touch) {
-				// Touch device support
-				tapEvt = {
-					target: dragEl,
-					clientX: touch.clientX,
-					clientY: touch.clientY
-				};
-
-				this._onDragStart(tapEvt, 'touch');
-			}
-			else if (!this.nativeDraggable) {
-				this._onDragStart(tapEvt, true);
-			}
-			else {
-				_on(dragEl, 'dragend', this);
-				_on(rootEl, 'dragstart', this._onDragStart);
-			}
-
-			try {
-				if (document.selection) {
-					// Timeout neccessary for IE9
-					_nextTick(function () {
-						document.selection.empty();
-					});
-				} else {
-					window.getSelection().removeAllRanges();
-				}
-			} catch (err) {
-			}
-		},
-
-		_dragStarted: function () {
-			if (rootEl && dragEl) {
-				var options = this.options;
-
-				// Apply effect
-				_toggleClass(dragEl, options.ghostClass, true);
-				_toggleClass(dragEl, options.dragClass, false);
-
-				KvSortable.active = this;
-
-				// Drag start event
-				_dispatchEvent(this, rootEl, 'start', dragEl, rootEl, rootEl, oldIndex);
-			} else {
-				this._nulling();
-			}
-		},
-
-		_emulateDragOver: function () {
-			if (touchEvt) {
-				if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) {
-					return;
-				}
-
-				this._lastX = touchEvt.clientX;
-				this._lastY = touchEvt.clientY;
-
-				if (!supportCssPointerEvents) {
-					_css(ghostEl, 'display', 'none');
-				}
-
-				var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
-				var parent = target;
-				var i = touchDragOverListeners.length;
-
-				if (target && target.shadowRoot) {
-					target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
-					parent = target;
-				}
-
-				if (parent) {
-					do {
-						if (parent[expando]) {
-							while (i--) {
-								touchDragOverListeners[i]({
-									clientX: touchEvt.clientX,
-									clientY: touchEvt.clientY,
-									target: target,
-									rootEl: parent
-								});
-							}
-
-							break;
-						}
-
-						target = parent; // store last element
-					}
-					/* jshint boss:true */
-					while (parent = parent.parentNode);
-				}
-
-				if (!supportCssPointerEvents) {
-					_css(ghostEl, 'display', '');
-				}
-			}
-		},
-
-
-		_onTouchMove: function (/**TouchEvent*/evt) {
-			if (tapEvt) {
-				var	options = this.options,
-					fallbackTolerance = options.fallbackTolerance,
-					fallbackOffset = options.fallbackOffset,
-					touch = evt.touches ? evt.touches[0] : evt,
-					dx = (touch.clientX - tapEvt.clientX) + fallbackOffset.x,
-					dy = (touch.clientY - tapEvt.clientY) + fallbackOffset.y,
-					translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)';
-
-				// only set the status to dragging, when we are actually dragging
-				if (!KvSortable.active) {
-					if (fallbackTolerance &&
-						min(abs(touch.clientX - this._lastX), abs(touch.clientY - this._lastY)) < fallbackTolerance
-					) {
-						return;
-					}
-
-					this._dragStarted();
-				}
-
-				// as well as creating the ghost element on the document body
-				this._appendGhost();
-
-				moved = true;
-				touchEvt = touch;
-
-				_css(ghostEl, 'webkitTransform', translate3d);
-				_css(ghostEl, 'mozTransform', translate3d);
-				_css(ghostEl, 'msTransform', translate3d);
-				_css(ghostEl, 'transform', translate3d);
-
-				evt.preventDefault();
-			}
-		},
-
-		_appendGhost: function () {
-			if (!ghostEl) {
-				var rect = dragEl.getBoundingClientRect(),
-					css = _css(dragEl),
-					options = this.options,
-					ghostRect;
-
-				ghostEl = dragEl.cloneNode(true);
-
-				_toggleClass(ghostEl, options.ghostClass, false);
-				_toggleClass(ghostEl, options.fallbackClass, true);
-				_toggleClass(ghostEl, options.dragClass, true);
-
-				_css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10));
-				_css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10));
-				_css(ghostEl, 'width', rect.width);
-				_css(ghostEl, 'height', rect.height);
-				_css(ghostEl, 'opacity', '0.8');
-				_css(ghostEl, 'position', 'fixed');
-				_css(ghostEl, 'zIndex', '100000');
-				_css(ghostEl, 'pointerEvents', 'none');
-
-				options.fallbackOnBody && document.body.appendChild(ghostEl) || rootEl.appendChild(ghostEl);
-
-				// Fixing dimensions.
-				ghostRect = ghostEl.getBoundingClientRect();
-				_css(ghostEl, 'width', rect.width * 2 - ghostRect.width);
-				_css(ghostEl, 'height', rect.height * 2 - ghostRect.height);
-			}
-		},
-
-		_onDragStart: function (/**Event*/evt, /**boolean*/useFallback) {
-			var _this = this;
-			var dataTransfer = evt.dataTransfer;
-			var options = _this.options;
-
-			_this._offUpEvents();
-
-			if (activeGroup.checkPull(_this, _this, dragEl, evt)) {
-				cloneEl = _clone(dragEl);
-
-				cloneEl.draggable = false;
-				cloneEl.style['will-change'] = '';
-
-				_css(cloneEl, 'display', 'none');
-				_toggleClass(cloneEl, _this.options.chosenClass, false);
-
-				// #1143: IFrame support workaround
-				_this._cloneId = _nextTick(function () {
-					rootEl.insertBefore(cloneEl, dragEl);
-					_dispatchEvent(_this, rootEl, 'clone', dragEl);
-				});
-			}
-
-			_toggleClass(dragEl, options.dragClass, true);
-
-			if (useFallback) {
-				if (useFallback === 'touch') {
-					// Bind touch events
-					_on(document, 'touchmove', _this._onTouchMove);
-					_on(document, 'touchend', _this._onDrop);
-					_on(document, 'touchcancel', _this._onDrop);
-
-					if (options.supportPointer) {
-						_on(document, 'pointermove', _this._onTouchMove);
-						_on(document, 'pointerup', _this._onDrop);
-					}
-				} else {
-					// Old brwoser
-					_on(document, 'mousemove', _this._onTouchMove);
-					_on(document, 'mouseup', _this._onDrop);
-				}
-
-				_this._loopId = setInterval(_this._emulateDragOver, 50);
-			}
-			else {
-				if (dataTransfer) {
-					dataTransfer.effectAllowed = 'move';
-					options.setData && options.setData.call(_this, dataTransfer, dragEl);
-				}
-
-				_on(document, 'drop', _this);
-
-				// #1143: Бывает элемент с IFrame внутри блокирует `drop`,
-				// поэтому если вызвался `mouseover`, значит надо отменять весь d'n'd.
-				// Breaking Chrome 62+
-				// _on(document, 'mouseover', _this);
-
-				_this._dragStartId = _nextTick(_this._dragStarted);
-			}
-		},
-
-		_onDragOver: function (/**Event*/evt) {
-			var el = this.el,
-				target,
-				dragRect,
-				targetRect,
-				revert,
-				options = this.options,
-				group = options.group,
-				activeKvSortable = KvSortable.active,
-				isOwner = (activeGroup === group),
-				isMovingBetweenKvSortable = false,
-				canSort = options.sort;
-
-			if (evt.preventDefault !== void 0) {
-				evt.preventDefault();
-				!options.dragoverBubble && evt.stopPropagation();
-			}
-
-			if (dragEl.animated) {
-				return;
-			}
-
-			moved = true;
-
-			if (activeKvSortable && !options.disabled &&
-				(isOwner
-					? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
-					: (
-						putKvSortable === this ||
-						(
-							(activeKvSortable.lastPullMode = activeGroup.checkPull(this, activeKvSortable, dragEl, evt)) &&
-							group.checkPut(this, activeKvSortable, dragEl, evt)
-						)
-					)
-				) &&
-				(evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback
-			) {
-				// Smart auto-scrolling
-				_autoScroll(evt, options, this.el);
-
-				if (_silent) {
-					return;
-				}
-
-				target = _closest(evt.target, options.draggable, el);
-				dragRect = dragEl.getBoundingClientRect();
-
-				if (putKvSortable !== this) {
-					putKvSortable = this;
-					isMovingBetweenKvSortable = true;
-				}
-
-				if (revert) {
-					_cloneHide(activeKvSortable, true);
-					parentEl = rootEl; // actualization
-
-					if (cloneEl || nextEl) {
-						rootEl.insertBefore(dragEl, cloneEl || nextEl);
-					}
-					else if (!canSort) {
-						rootEl.appendChild(dragEl);
-					}
-
-					return;
-				}
-
-
-				if ((el.children.length === 0) || (el.children[0] === ghostEl) ||
-					(el === evt.target) && (_ghostIsLast(el, evt))
-				) {
-					//assign target only if condition is true
-					if (el.children.length !== 0 && el.children[0] !== ghostEl && el === evt.target) {
-						target = el.lastElementChild;
-					}
-
-					if (target) {
-						if (target.animated) {
-							return;
-						}
-
-						targetRect = target.getBoundingClientRect();
-					}
-
-					_cloneHide(activeKvSortable, isOwner);
-
-					if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt) !== false) {
-						if (!dragEl.contains(el)) {
-							el.appendChild(dragEl);
-							parentEl = el; // actualization
-						}
-
-						this._animate(dragRect, dragEl);
-						target && this._animate(targetRect, target);
-					}
-				}
-				else if (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0)) {
-					if (lastEl !== target) {
-						lastEl = target;
-						lastCSS = _css(target);
-						lastParentCSS = _css(target.parentNode);
-					}
-
-					targetRect = target.getBoundingClientRect();
-
-					var width = targetRect.right - targetRect.left,
-						height = targetRect.bottom - targetRect.top,
-						floating = R_FLOAT.test(lastCSS.cssFloat + lastCSS.display)
-							|| (lastParentCSS.display == 'flex' && lastParentCSS['flex-direction'].indexOf('row') === 0),
-						isWide = (target.offsetWidth > dragEl.offsetWidth),
-						isLong = (target.offsetHeight > dragEl.offsetHeight),
-						halfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5,
-						nextSibling = target.nextElementSibling,
-						after = false
-					;
-
-					if (floating) {
-						var elTop = dragEl.offsetTop,
-							tgTop = target.offsetTop;
-
-						if (elTop === tgTop) {
-							after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide;
-						}
-						else if (target.previousElementSibling === dragEl || dragEl.previousElementSibling === target) {
-							after = (evt.clientY - targetRect.top) / height > 0.5;
-						} else {
-							after = tgTop > elTop;
-						}
-						} else if (!isMovingBetweenKvSortable) {
-						after = (nextSibling !== dragEl) && !isLong || halfway && isLong;
-					}
-
-					var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after);
-
-					if (moveVector !== false) {
-						if (moveVector === 1 || moveVector === -1) {
-							after = (moveVector === 1);
-						}
-
-						_silent = true;
-						setTimeout(_unsilent, 30);
-
-						_cloneHide(activeKvSortable, isOwner);
-
-						if (!dragEl.contains(el)) {
-							if (after && !nextSibling) {
-								el.appendChild(dragEl);
-							} else {
-								target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
-							}
-						}
-
-						parentEl = dragEl.parentNode; // actualization
-
-						this._animate(dragRect, dragEl);
-						this._animate(targetRect, target);
-					}
-				}
-			}
-		},
-
-		_animate: function (prevRect, target) {
-			var ms = this.options.animation;
-
-			if (ms) {
-				var currentRect = target.getBoundingClientRect();
-
-				if (prevRect.nodeType === 1) {
-					prevRect = prevRect.getBoundingClientRect();
-				}
-
-				_css(target, 'transition', 'none');
-				_css(target, 'transform', 'translate3d('
-					+ (prevRect.left - currentRect.left) + 'px,'
-					+ (prevRect.top - currentRect.top) + 'px,0)'
-				);
-
-				target.offsetWidth; // repaint
-
-				_css(target, 'transition', 'all ' + ms + 'ms');
-				_css(target, 'transform', 'translate3d(0,0,0)');
-
-				clearTimeout(target.animated);
-				target.animated = setTimeout(function () {
-					_css(target, 'transition', '');
-					_css(target, 'transform', '');
-					target.animated = false;
-				}, ms);
-			}
-		},
-
-		_offUpEvents: function () {
-			var ownerDocument = this.el.ownerDocument;
-
-			_off(document, 'touchmove', this._onTouchMove);
-			_off(document, 'pointermove', this._onTouchMove);
-			_off(ownerDocument, 'mouseup', this._onDrop);
-			_off(ownerDocument, 'touchend', this._onDrop);
-			_off(ownerDocument, 'pointerup', this._onDrop);
-			_off(ownerDocument, 'touchcancel', this._onDrop);
-			_off(ownerDocument, 'pointercancel', this._onDrop);
-			_off(ownerDocument, 'selectstart', this);
-		},
-
-		_onDrop: function (/**Event*/evt) {
-			var el = this.el,
-				options = this.options;
-
-			clearInterval(this._loopId);
-			clearInterval(autoScroll.pid);
-			clearTimeout(this._dragStartTimer);
-
-			_cancelNextTick(this._cloneId);
-			_cancelNextTick(this._dragStartId);
-
-			// Unbind events
-			_off(document, 'mouseover', this);
-			_off(document, 'mousemove', this._onTouchMove);
-
-			if (this.nativeDraggable) {
-				_off(document, 'drop', this);
-				_off(el, 'dragstart', this._onDragStart);
-			}
-
-			this._offUpEvents();
-
-			if (evt) {
-				if (moved) {
-					evt.preventDefault();
-					!options.dropBubble && evt.stopPropagation();
-				}
-
-				ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl);
-
-				if (rootEl === parentEl || KvSortable.active.lastPullMode !== 'clone') {
-					// Remove clone
-					cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl);
-				}
-
-				if (dragEl) {
-					if (this.nativeDraggable) {
-						_off(dragEl, 'dragend', this);
-					}
-
-					_disableDraggable(dragEl);
-					dragEl.style['will-change'] = '';
-
-					// Remove class's
-					_toggleClass(dragEl, this.options.ghostClass, false);
-					_toggleClass(dragEl, this.options.chosenClass, false);
-
-					// Drag stop event
-					_dispatchEvent(this, rootEl, 'unchoose', dragEl, parentEl, rootEl, oldIndex);
-
-					if (rootEl !== parentEl) {
-						newIndex = _index(dragEl, options.draggable);
-
-						if (newIndex >= 0) {
-							// Add event
-							_dispatchEvent(null, parentEl, 'add', dragEl, parentEl, rootEl, oldIndex, newIndex);
-
-							// Remove event
-							_dispatchEvent(this, rootEl, 'remove', dragEl, parentEl, rootEl, oldIndex, newIndex);
-
-							// drag from one list and drop into another
-							_dispatchEvent(null, parentEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
-							_dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
-						}
-					}
-					else {
-						if (dragEl.nextSibling !== nextEl) {
-							// Get the index of the dragged element within its parent
-							newIndex = _index(dragEl, options.draggable);
-
-							if (newIndex >= 0) {
-								// drag & drop within the same list
-								_dispatchEvent(this, rootEl, 'update', dragEl, parentEl, rootEl, oldIndex, newIndex);
-								_dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
-							}
-						}
-					}
-
-					if (KvSortable.active) {
-						/* jshint eqnull:true */
-						if (newIndex == null || newIndex === -1) {
-							newIndex = oldIndex;
-						}
-
-						_dispatchEvent(this, rootEl, 'end', dragEl, parentEl, rootEl, oldIndex, newIndex);
-
-						// Save sorting
-						this.save();
-					}
-				}
-
-			}
-
-			this._nulling();
-		},
-
-		_nulling: function() {
-			rootEl =
-			dragEl =
-			parentEl =
-			ghostEl =
-			nextEl =
-			cloneEl =
-			lastDownEl =
-
-			scrollEl =
-			scrollParentEl =
-
-			tapEvt =
-			touchEvt =
-
-			moved =
-			newIndex =
-
-			lastEl =
-			lastCSS =
-
-			putKvSortable =
-			activeGroup =
-			KvSortable.active = null;
-
-			savedInputChecked.forEach(function (el) {
-				el.checked = true;
-			});
-			savedInputChecked.length = 0;
-		},
-
-		handleEvent: function (/**Event*/evt) {
-			switch (evt.type) {
-				case 'drop':
-				case 'dragend':
-					this._onDrop(evt);
-					break;
-
-				case 'dragover':
-				case 'dragenter':
-					if (dragEl) {
-						this._onDragOver(evt);
-						_globalDragOver(evt);
-					}
-					break;
-
-				case 'mouseover':
-					this._onDrop(evt);
-					break;
-
-				case 'selectstart':
-					evt.preventDefault();
-					break;
-			}
-		},
-
-
-		/**
-		 * Serializes the item into an array of string.
-		 * @returns {String[]}
-		 */
-		toArray: function () {
-			var order = [],
-				el,
-				children = this.el.children,
-				i = 0,
-				n = children.length,
-				options = this.options;
-
-			for (; i < n; i++) {
-				el = children[i];
-				if (_closest(el, options.draggable, this.el)) {
-					order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
-				}
-			}
-
-			return order;
-		},
-
-
-		/**
-		 * Sorts the elements according to the array.
-		 * @param  {String[]}  order  order of the items
-		 */
-		sort: function (order) {
-			var items = {}, rootEl = this.el;
-
-			this.toArray().forEach(function (id, i) {
-				var el = rootEl.children[i];
-
-				if (_closest(el, this.options.draggable, rootEl)) {
-					items[id] = el;
-				}
-			}, this);
-
-			order.forEach(function (id) {
-				if (items[id]) {
-					rootEl.removeChild(items[id]);
-					rootEl.appendChild(items[id]);
-				}
-			});
-		},
-
-
-		/**
-		 * Save the current sorting
-		 */
-		save: function () {
-			var store = this.options.store;
-			store && store.set(this);
-		},
-
-
-		/**
-		 * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
-		 * @param   {HTMLElement}  el
-		 * @param   {String}       [selector]  default: `options.draggable`
-		 * @returns {HTMLElement|null}
-		 */
-		closest: function (el, selector) {
-			return _closest(el, selector || this.options.draggable, this.el);
-		},
-
-
-		/**
-		 * Set/get option
-		 * @param   {string} name
-		 * @param   {*}      [value]
-		 * @returns {*}
-		 */
-		option: function (name, value) {
-			var options = this.options;
-
-			if (value === void 0) {
-				return options[name];
-			} else {
-				options[name] = value;
-
-				if (name === 'group') {
-					_prepareGroup(options);
-				}
-			}
-		},
-
-
-		/**
-		 * Destroy
-		 */
-		destroy: function () {
-			var el = this.el;
-
-			el[expando] = null;
-
-			_off(el, 'mousedown', this._onTapStart);
-			_off(el, 'touchstart', this._onTapStart);
-			_off(el, 'pointerdown', this._onTapStart);
-
-			if (this.nativeDraggable) {
-				_off(el, 'dragover', this);
-				_off(el, 'dragenter', this);
-			}
-
-			// Remove draggable attributes
-			Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {
-				el.removeAttribute('draggable');
-			});
-
-			touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1);
-
-			this._onDrop();
-
-			this.el = el = null;
-		}
-	};
-
-
-	function _cloneHide(kvsortable, state) {
-		if (kvsortable.lastPullMode !== 'clone') {
-			state = true;
-		}
-
-		if (cloneEl && (cloneEl.state !== state)) {
-			_css(cloneEl, 'display', state ? 'none' : '');
-
-			if (!state) {
-				if (cloneEl.state) {
-					if (kvsortable.options.group.revertClone) {
-						rootEl.insertBefore(cloneEl, nextEl);
-						kvsortable._animate(dragEl, cloneEl);
-					} else {
-						rootEl.insertBefore(cloneEl, dragEl);
-					}
-				}
-			}
-
-			cloneEl.state = state;
-		}
-	}
-
-
-	function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) {
-		if (el) {
-			ctx = ctx || document;
-
-			do {
-				if ((selector === '>*' && el.parentNode === ctx) || _matches(el, selector)) {
-					return el;
-				}
-				/* jshint boss:true */
-			} while (el = _getParentOrHost(el));
-		}
-
-		return null;
-	}
-
-
-	function _getParentOrHost(el) {
-		var parent = el.host;
-
-		return (parent && parent.nodeType) ? parent : el.parentNode;
-	}
-
-
-	function _globalDragOver(/**Event*/evt) {
-		if (evt.dataTransfer) {
-			evt.dataTransfer.dropEffect = 'move';
-		}
-		evt.preventDefault();
-	}
-
-
-	function _on(el, event, fn) {
-		el.addEventListener(event, fn, captureMode);
-	}
-
-
-	function _off(el, event, fn) {
-		el.removeEventListener(event, fn, captureMode);
-	}
-
-
-	function _toggleClass(el, name, state) {
-		if (el) {
-			if (el.classList) {
-				el.classList[state ? 'add' : 'remove'](name);
-			}
-			else {
-				var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');
-				el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');
-			}
-		}
-	}
-
-
-	function _css(el, prop, val) {
-		var style = el && el.style;
-
-		if (style) {
-			if (val === void 0) {
-				if (document.defaultView && document.defaultView.getComputedStyle) {
-					val = document.defaultView.getComputedStyle(el, '');
-				}
-				else if (el.currentStyle) {
-					val = el.currentStyle;
-				}
-
-				return prop === void 0 ? val : val[prop];
-			}
-			else {
-				if (!(prop in style)) {
-					prop = '-webkit-' + prop;
-				}
-
-				style[prop] = val + (typeof val === 'string' ? '' : 'px');
-			}
-		}
-	}
-
-
-	function _find(ctx, tagName, iterator) {
-		if (ctx) {
-			var list = ctx.getElementsByTagName(tagName), i = 0, n = list.length;
-
-			if (iterator) {
-				for (; i < n; i++) {
-					iterator(list[i], i);
-				}
-			}
-
-			return list;
-		}
-
-		return [];
-	}
-
-
-
-	function _dispatchEvent(kvsortable, rootEl, name, targetEl, toEl, fromEl, startIndex, newIndex) {
-		kvsortable = (kvsortable || rootEl[expando]);
-
-		var evt = document.createEvent('Event'),
-			options = kvsortable.options,
-			onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1);
-
-		evt.initEvent(name, true, true);
-
-		evt.to = toEl || rootEl;
-		evt.from = fromEl || rootEl;
-		evt.item = targetEl || rootEl;
-		evt.clone = cloneEl;
-
-		evt.oldIndex = startIndex;
-		evt.newIndex = newIndex;
-
-		rootEl.dispatchEvent(evt);
-
-		if (options[onName]) {
-			options[onName].call(kvsortable, evt);
-		}
-	}
-
-
-	function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvt, willInsertAfter) {
-		var evt,
-			kvsortable = fromEl[expando],
-			onMoveFn = kvsortable.options.onMove,
-			retVal;
-
-		evt = document.createEvent('Event');
-		evt.initEvent('move', true, true);
-
-		evt.to = toEl;
-		evt.from = fromEl;
-		evt.dragged = dragEl;
-		evt.draggedRect = dragRect;
-		evt.related = targetEl || toEl;
-		evt.relatedRect = targetRect || toEl.getBoundingClientRect();
-		evt.willInsertAfter = willInsertAfter;
-
-		fromEl.dispatchEvent(evt);
-
-		if (onMoveFn) {
-			retVal = onMoveFn.call(kvsortable, evt, originalEvt);
-		}
-
-		return retVal;
-	}
-
-
-	function _disableDraggable(el) {
-		el.draggable = false;
-	}
-
-
-	function _unsilent() {
-		_silent = false;
-	}
-
-
-	/** @returns {HTMLElement|false} */
-	function _ghostIsLast(el, evt) {
-		var lastEl = el.lastElementChild,
-			rect = lastEl.getBoundingClientRect();
-
-		// 5 — min delta
-		// abs — нельзя добавлять, а то глюки при наведении сверху
-		return (evt.clientY - (rect.top + rect.height) > 5) ||
-			(evt.clientX - (rect.left + rect.width) > 5);
-	}
-
-
-	/**
-	 * Generate id
-	 * @param   {HTMLElement} el
-	 * @returns {String}
-	 * @private
-	 */
-	function _generateId(el) {
-		var str = el.tagName + el.className + el.src + el.href + el.textContent,
-			i = str.length,
-			sum = 0;
-
-		while (i--) {
-			sum += str.charCodeAt(i);
-		}
-
-		return sum.toString(36);
-	}
-
-	/**
-	 * Returns the index of an element within its parent for a selected set of
-	 * elements
-	 * @param  {HTMLElement} el
-	 * @param  {selector} selector
-	 * @return {number}
-	 */
-	function _index(el, selector) {
-		var index = 0;
-
-		if (!el || !el.parentNode) {
-			return -1;
-		}
-
-		while (el && (el = el.previousElementSibling)) {
-			if ((el.nodeName.toUpperCase() !== 'TEMPLATE') && (selector === '>*' || _matches(el, selector))) {
-				index++;
-			}
-		}
-
-		return index;
-	}
-
-	function _matches(/**HTMLElement*/el, /**String*/selector) {
-		if (el) {
-			selector = selector.split('.');
-
-			var tag = selector.shift().toUpperCase(),
-				re = new RegExp('\\s(' + selector.join('|') + ')(?=\\s)', 'g');
-
-			return (
-				(tag === '' || el.nodeName.toUpperCase() == tag) &&
-				(!selector.length || ((' ' + el.className + ' ').match(re) || []).length == selector.length)
-			);
-		}
-
-		return false;
-	}
-
-	function _throttle(callback, ms) {
-		var args, _this;
-
-		return function () {
-			if (args === void 0) {
-				args = arguments;
-				_this = this;
-
-				setTimeout(function () {
-					if (args.length === 1) {
-						callback.call(_this, args[0]);
-					} else {
-						callback.apply(_this, args);
-					}
-
-					args = void 0;
-				}, ms);
-			}
-		};
-	}
-
-	function _extend(dst, src) {
-		if (dst && src) {
-			for (var key in src) {
-				if (src.hasOwnProperty(key)) {
-					dst[key] = src[key];
-				}
-			}
-		}
-
-		return dst;
-	}
-
-	function _clone(el) {
-		if (Polymer && Polymer.dom) {
-			return Polymer.dom(el).cloneNode(true);
-		}
-		else if ($) {
-			return $(el).clone(true)[0];
-		}
-		else {
-			return el.cloneNode(true);
-		}
-	}
-
-	function _saveInputCheckedState(root) {
-		var inputs = root.getElementsByTagName('input');
-		var idx = inputs.length;
-
-		while (idx--) {
-			var el = inputs[idx];
-			el.checked && savedInputChecked.push(el);
-		}
-	}
-
-	function _nextTick(fn) {
-		return setTimeout(fn, 0);
-	}
-
-	function _cancelNextTick(id) {
-		return clearTimeout(id);
-	}
-
-	// Fixed #973:
-	_on(document, 'touchmove', function (evt) {
-		if (KvSortable.active) {
-			evt.preventDefault();
-		}
-	});
-
-	// Export utils
-	KvSortable.utils = {
-		on: _on,
-		off: _off,
-		css: _css,
-		find: _find,
-		is: function (el, selector) {
-			return !!_closest(el, selector, el);
-		},
-		extend: _extend,
-		throttle: _throttle,
-		closest: _closest,
-		toggleClass: _toggleClass,
-		clone: _clone,
-		index: _index,
-		nextTick: _nextTick,
-		cancelNextTick: _cancelNextTick
-	};
-
-
-	/**
-	 * Create kvsortable instance
-	 * @param {HTMLElement}  el
-	 * @param {Object}      [options]
-	 */
-	KvSortable.create = function (el, options) {
-		return new KvSortable(el, options);
-	};
-
-
-	// Export
-	KvSortable.version = '1.7.0';
-	return KvSortable;
-});
-/**
- * jQuery plugin for KvSortable
- */
-(function (factory) {
-    "use strict";
-
-    if (typeof define === "function" && define.amd) {
-        define(["jquery"], factory);
-    }
-    else {
-        /* jshint sub:true */
-        factory(jQuery);
-    }
-})(function ($) {
-    "use strict";
-    $.fn.kvsortable = function (options) {
-        var retVal,
-            args = arguments;
-
-        this.each(function () {
-            var $el = $(this), kvsortable = $el.data('kvsortable');
-
-            if (!kvsortable && (options instanceof Object || !options)) {
-                kvsortable = new KvSortable(this, options);
-                $el.data('kvsortable', kvsortable);
-            }
-
-            if (kvsortable) {
-                if (options === 'widget') {
-                    retVal = kvsortable;
-                }
-                else if (options === 'destroy') {
-                    kvsortable.destroy();
-                    $el.removeData('kvsortable');
-                }
-                else if (typeof kvsortable[options] === 'function') {
-                    retVal = kvsortable[options].apply(kvsortable, [].slice.call(args, 1));
-                }
-                else if (options in kvsortable.options) {
-                    retVal = kvsortable.option.apply(kvsortable, args);
-                }
-            }
-        });
-
-        return (retVal === void 0) ? this : retVal;
-    };
-});

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
src/main/resources/static/js/plugins/fileinput/plugins/sortable.min.js


+ 2 - 2
src/main/resources/templates/main.html

@@ -106,9 +106,9 @@
 										        <li>修复批量生成代码异常问题</li>
 										        <li>修复定时器保存失败问题</li>
 										        <li>修复热部署转换问题</li>
-												<li>支持查询&统一样式(菜单管理,部门管理</li>
+												<li>支持查询菜单管理,部门管理</li>
 												<li>大多数功能支持时间查询</li>
-												<li>去掉自定义导出注解column列变更为自动匹配</li>
+												<li>自定义导出注解自动匹配column</li>
 												<li>新增任务执行策略</li>
 												<li>操作详细动态显示类型</li>
 												<li>支持动态回显字典数据</li>

Деякі файли не було показано, через те що забагато файлів було змінено