Your IP : 216.73.216.85


Current Path : /home/smartconb/www/armencom33/media/com_jce/editor/js/
Upload File :
Current File : /home/smartconb/www/armencom33/media/com_jce/editor/js/filebrowser.min.js

/* jce - 2.9.82 | 2024-11-20 | https://www.joomlacontenteditor.net | Source: https://github.com/widgetfactory/jce | Copyright (C) 2006 - 2024 Ryan Demmer. All rights reserved | GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html */
!function() {
    "use strict";
    var $;
    !function($, Wf) {
        function Tree(element, options) {
            this.element = element, this.options = $.extend({
                collapseTree: !1,
                charLength: !1
            }, options), this._init();
        }
        var scrollEvents = "click.scroll mousedown.scroll wheel.scroll mousewheel.scroll keyup.scroll touchmove.scroll";
        Tree.prototype = {
            _trigger: function(ev, args) {
                $(this.element).trigger("tree:" + ev, args);
            },
            _init: function() {
                var self = this;
                this.element && (this._trigger("init", function() {
                    self.nodeEvents();
                }), $(this.element).on(scrollEvents, function() {
                    $(this).stop();
                }));
            },
            nodeEvents: function(parent) {
                var self = this;
                parent = parent || this.element, $("ul:first", parent).attr({
                    role: "tree"
                }).addClass("uk-tree").children("li").attr("aria-level", 1), $(".uk-tree", parent).on("click", function(e) {
                    var n = e.target, p = $(n).parents("li").get(0);
                    e.preventDefault(), e.stopPropagation(), $(n).hasClass("uk-icon") && (n = n.parentNode), 
                    $(n).hasClass("uk-tree-toggle") ? self.toggleNode(e, p) : self._trigger("nodeclick", [ e, p ]), 
                    $(self.element).find(".uk-tree-active").removeClass("uk-tree-active"), 
                    $(p).addClass("uk-tree-active");
                }), $("li", parent).attr({
                    role: "treeitem"
                }).attr("aria-expanded", function() {
                    return !!$(this).hasClass("uk-tree-open");
                }).attr("aria-level", function(i, v) {
                    if (!v) return parseFloat($(this.parentNode.parentNode).attr("aria-level")) + 1;
                }), $("li", parent).find(".uk-tree-row").attr("role", "presentation").prepend('<span class="uk-tree-toggle" role="presentation"><i class="uk-icon uk-icon-caret-right"></i><i class="uk-icon uk-icon-caret-down"></i></span>'), 
                $("li", parent).not(".uk-tree-root").find(".uk-tree-icon").attr("role", "presentation").append('<i class="uk-icon uk-icon-folder"></i><i class="uk-icon uk-icon-folder-open"></i>');
            },
            _hasNodes: function(parent) {
                "string" == $.type(parent) && (parent = this._findParent(parent));
                parent = $("li", parent);
                return 1 < parent.length || 1 == parent.length && !$(parent).is(":empty");
            },
            _isNode: function(id, parent) {
                return !!this._findNode(id, parent).length;
            },
            _getNode: function(parent) {
                return "string" === $.type(parent) && (parent = this._findParent(parent)), 
                $(".uk-tree-node", parent);
            },
            _resetNodes: function() {
                $("li", this.element).removeClass("uk-tree-open");
            },
            renameNode: function(id, name) {
                var parent = Wf.String.dirname(id), parent = this._findNode(id, parent);
                $(parent).attr("data-id", name), $("a:first .uk-tree-text", parent).text(Wf.String.basename(name)), 
                $('li[data-id^="' + this._escape(encodeURI(id)) + '"]', parent).each(function(n) {
                    var nt = $(n).attr("data-id");
                    $(n).attr("data-id", nt.replace(id, name));
                });
            },
            removeNode: function(id) {
                var parent = Wf.String.dirname(id), id = this._findNode(id, parent), parent = $(id).parent("ul");
                $(id).remove(), parent && !this._hasNodes(parent) && $(parent).remove();
            },
            sortNodes: function(parent) {
                var p = $(parent).parent(), list = (parent = $(parent).detach(), 
                $("li", parent).map(function() {
                    return {
                        value: $(".uk-tree-text", this).attr("title"),
                        element: this
                    };
                }).get());
                list.sort(function(a, b) {
                    a = a.value || "", b = b.value || "";
                    return a.localeCompare(b);
                }), $.each(list, function(i, item) {
                    $(parent).append(item.element);
                }), $(p).append(parent);
            },
            createNode: function(nodes, parent, sortNodes) {
                var ul, self = this;
                nodes.length && (parent = parent || Wf.String.dirname($(nodes[0]).attr("data-id") || $(nodes[0]).attr("id")), 
                "string" == $.type(parent) && (parent = this._findParent(parent)), 
                nodes = $.grep(nodes, function(node) {
                    return 0 === self._findNode(node.id, parent).length;
                }), $(this.element).find(".uk-tree-active").removeClass("uk-tree-active"), 
                nodes && nodes.length ? ((ul = $(".uk-tree-node:first", parent) || null).length || (ul = document.createElement("ul"), 
                $(ul).attr({
                    role: "group"
                }).addClass("uk-tree-node").append('<li role="treeitem" aria-expanded="false"></li>'), 
                $(parent).append(ul)), $.each(nodes, function(i, node) {
                    var name, title, url, html;
                    self._isNode(node.id, parent) ? self.toggleNodeState(parent, 1) : (title = node.name || node.id, 
                    name = Wf.String.decode(title), title = Wf.String.encode(title), 
                    url = node.url || "#", node.class || (node.class = "folder"), 
                    html = '<li data-id="' + self._escape(encodeURI(node.id)) + '" class="' + node.class + '" role="treeitem" aria-level="' + parseFloat($(parent).attr("aria-level")) + '1" aria-label="' + title + '">', 
                    html += '<div class="uk-tree-row">', 0 <= node.class.indexOf("folder") && (html += '<span class="uk-tree-toggle" role="presentation"> <i class="uk-icon uk-icon-caret-right"></i> <i class="uk-icon uk-icon-caret-down"></i></span>'), 
                    html += '<a href="' + url + '" title="' + title + '"><span class="uk-tree-icon">', 
                    0 <= node.class.indexOf("folder") ? html += '<i role="presentation" class="uk-icon uk-icon-folder"></i><i role="presentation" class="uk-icon uk-icon-folder-open"></i>' : html += '<i role="presentation" class="uk-icon uk-icon-file-text"></i>', 
                    html = html + '</span><span class="uk-tree-text uk-margin-small-left uk-text-truncate" title="' + title + '">' + name + "</span></a></div></li>", 
                    $(ul).append(html), self.toggleNodeState(parent, 1), self._trigger("nodecreate"));
                }), !1 !== sortNodes && 1 < $(ul).children().length && self.sortNodes(ul)) : this.toggleNodeState(parent, 1));
            },
            _findParent: function(el) {
                return "string" === $.type(el) ? $('li[data-id="' + this._encode(el) + '"]:first', this.element) : $(el).parents("li:first");
            },
            _findNode: function(id, parent) {
                return parent && "/" !== parent || (parent = this.element), "string" === $.type(parent) && (parent = this._findParent(parent)), 
                id = id.replace(/^\/|\/$/, ""), $(parent).find('li[data-id="' + this._escape(this._encode(id)) + '"]:first');
            },
            toggleLoader: function(node) {
                $(node).toggleClass("uk-tree-loading");
            },
            _collapseNodes: function(ex) {
                var self = this, parent = (ex || this._resetNodes(), $(ex).parent());
                $("li", parent).each(function(i, el) {
                    el !== ex && $(el).parent() !== parent && (self.toggleNodeState(el, 0), 
                    el = self._getNode(el), $(el).addClass("uk-tree-hide"));
                });
            },
            toggleNodeState: function(node, state) {
                state ? $(node).addClass("uk-tree-open").attr("aria-expanded", !0) : $(node).removeClass("uk-tree-open").attr("aria-expanded", !1), 
                state && !$(node).hasClass("uk-tree-root") && (state = $(".uk-tree-node", node), 
                $(node).hasClass("uk-tree-open") ? $(state).removeClass("uk-tree-hide") : $(state).addClass("uk-tree-hide"));
            },
            toggleNode: function(e, node) {
                if (e.shiftKey) return this._trigger("nodeload", node);
                e = this._getNode(node);
                e.length ? ($(e).toggleClass("uk-tree-hide"), this.toggleNodeState(node, !$(e).hasClass("uk-tree-hide"))) : $(node).hasClass("uk-tree-open") ? this.toggleNodeState(node, 0) : this._trigger("nodeload", node), 
                this.options.collapseTree && this._collapseNodes(node);
            },
            refreshNode: function(node) {
                node = this._findParent(node);
                return this._trigger("nodeload", node);
            },
            _encode: function(s) {
                try {
                    s = decodeURIComponent(s);
                } catch (e) {}
                return encodeURIComponent(s).replace(/%2F/gi, "/");
            },
            _escape: function(s) {
                return s.replace(/'/g, "%27");
            },
            scrollTo: function(id) {
                var padding, top, el = this.element, id = this._findNode(id);
                $(id).length && (padding = parseInt($(id).css("padding-left"), 10) + parseInt($(this.element).css("padding-left"), 10), 
                padding = $(id).get(0).offsetLeft - padding, top = $(id).get(0).offsetTop - ($(".uk-tree-row", id).outerHeight() + 2), 
                $(el).find(".uk-tree-active").removeClass("uk-tree-active"), $(el).animate({
                    scrollLeft: Math.round(padding)
                }, 500).animate({
                    scrollTop: Math.round(top)
                }, 1500, function() {
                    $(this).off(scrollEvents);
                }), $(id).addClass("uk-tree-active"));
            }
        }, $.fn.tree = function(options) {
            var inst = new Tree(this, options);
            return $(this).on("tree:createnode", function(e, node, parent, sortNodes) {
                inst.createNode(node = "string" == typeof node ? [ node ] : node, parent, sortNodes);
            }), $(this).on("tree:removenode", function(e, node) {
                inst.removeNode(node);
            }), $(this).on("tree:renamenode", function(e, node, name) {
                inst.renameNode(node, name);
            }), $(this).on("tree:togglenode", function(e, ev, node) {
                inst.toggleNode(ev, node);
            }), $(this).on("tree:togglenodestate", function(e, node, state) {
                inst.toggleNodeState(node, state);
            }), $(this).on("tree:toggleloader", function(e, node) {
                inst.toggleLoader(node);
            }), $(this).on("tree:refreshnode", function(e, node) {
                inst.refreshNode(node);
            }), $(this).on("tree:scroll", function(e, id) {
                inst.scrollTo(id);
            }), $(this).on("tree:init", function(e) {
                inst.nodeEvents();
            }), this;
        };
    }(jQuery, Wf), function($, window) {
        var counter = 0, mime = {
            jpeg: "image/jpeg",
            jpg: "image/jpeg",
            png: "image/png",
            gif: "image/gif",
            tif: "image/tiff",
            tiff: "image/tiff",
            webp: "image/webp"
        };
        function uid() {
            for (var guid = new Date().getTime().toString(32), i = 0; i < 5; i++) guid += Math.floor(65535 * Math.random()).toString(32);
            return "wf_" + guid + (counter++).toString(32);
        }
        function cancel(e) {
            e.preventDefault(), e.stopImmediatePropagation();
        }
        function Transport(options) {
            this.options = $.extend({
                callback: $.noop,
                headers: {},
                multipart: {},
                data_name: "file"
            }, options);
        }
        function Uploader(options) {
            this.events = [], this.options = $.extend({
                container: "body",
                multiple: !0,
                input_name: "file",
                drop_target: null,
                upload_button: null,
                filetypes: "*",
                max_size: 1024,
                data: {}
            }, options), this.files = [];
            options = [];
            return 1 < this.options.filetypes.length && (options = $.map(this.options.filetypes.split(","), function(val) {
                return "." + val;
            })), this.input = $('<input type="file" accept="' + options.join(",") + '" />'), 
            $(this.input).addClass("wf-uploader-element"), $(this.input).prop("multiple", this.options.multiple), 
            this;
        }
        Transport.prototype = {
            upload: function(file) {
                this.file = file, this.transport = new XMLHttpRequest(), this.xhr();
            },
            error: function(status, text) {
                (0, this.options.callback)("error", {
                    message: text || "The server returned an invalid JSON response.",
                    file: this.file,
                    code: status || 500
                });
            },
            response: function(data) {
                var r, callback = this.options.callback;
                if (data) {
                    try {
                        r = $.parseJSON(data);
                    } catch (e) {
                        return -1 !== data.indexOf("{") && (data = "The server returned an invalid JSON response."), 
                        this.error(500, data), !1;
                    }
                    if (r.error) return this.error(r.error.code, r.error.message), 
                    !1;
                    r.file = this.file, callback("uploadcomplete", r), this.file = null;
                } else this.error();
            },
            xhr: function() {
                var self = this, xhr = this.transport, o = this.options, callback = o.callback, formData = new FormData(), file = this.file;
                xhr.upload && (xhr.upload.onprogress = function(e) {
                    e.lengthComputable && (file.loaded = Math.min(file.size, e.loaded), 
                    callback("progress", file));
                }), xhr.onreadystatechange = function() {
                    4 === xhr.readyState && (200 === xhr.status ? (file.loaded = file.size, 
                    callback("progress", file), formData = null, self.response(xhr.responseText)) : self.error(xhr.status), 
                    xhr.onreadystatechange = $.noop, xhr = null);
                }, xhr.open("post", o.url, !0), $.each(o.headers, function(name, value) {
                    xhr.setRequestHeader(name, value);
                }), xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"), 
                $.each(o.multipart, function(name, value) {
                    "object" === $.type(value) ? formData.append(value.name, value.value) : formData.append(name, value);
                }), file.data && $.each(file.data, function(name, value) {
                    "object" === $.type(value) ? formData.append(value.name, value.value) : formData.append(name, value);
                }), formData.append("method", "upload"), formData.append("id", uid()), 
                formData.append(o.data_name, file), xhr.send(formData);
            },
            cleanup: function() {
                var file = this.file;
                return file && file.input && $(file.input).parent('form[target="wf_upload_iframe"]').remove(), 
                !1;
            },
            abort: function() {
                this.transport.abort(), this.transport.onreadystatechange = $.noop, 
                this.transport = null, this.cleanup();
            }
        }, Uploader.prototype = {
            _events: [],
            files: [],
            on: function(event, fn) {
                return $(document).on("upload:" + event, fn), this._events.push(event), 
                this;
            },
            fire: function(event) {
                return $(document).trigger("upload:" + event, Array.prototype.slice.call(arguments, 1)), 
                this;
            },
            init: function() {
                var btn, self = this, o = this.options;
                return o.drop_target && ($(o.drop_target).on("dragover", function(e) {
                    var dataTransfer = e.originalEvent.dataTransfer;
                    self.fire("dragover"), dataTransfer.dropEffect = "copy", cancel(e);
                }), $(o.drop_target).on("dragstart dragenter dragleave dragend", function(e) {
                    self.fire(e.type), cancel(e);
                }), $(o.drop_target).on("drop", function(e) {
                    var dataTransfer = e.originalEvent.dataTransfer;
                    self.fire("drop"), dataTransfer && dataTransfer.files && dataTransfer.files.length && ($.each(dataTransfer.files, function(i, file) {
                        self.addFile(file);
                    }), cancel(e)), !o.upload_button && self.files.length && self.start(), 
                    cancel(e);
                })), o.browse_button && (btn = o.browse_button, $(btn).addClass("wf-uploader-button").wrap('<div class="wf-uploader-container"></div>'), 
                $(this.input).on("change", function() {
                    var name;
                    this.files ? $.each(this.files, function(i, file) {
                        self.addFile(file);
                    }) : (name = this.value.replace(/\\/g, "/").replace(/\/(.+)$/, "$1"), 
                    self.addFile({
                        name: name,
                        input: this
                    }), $(this).hide().clone(!0).insertAfter(this).show()), !o.upload_button && self.files.length && self.start();
                }), $(this.input).clone(!0).insertAfter(btn)), self.fire("init"), 
                this;
            },
            addFile: function(file) {
                if (file && file.name) {
                    var name = file.name, ext = name.substring(name.length, name.lastIndexOf(".") + 1);
                    if (/\.(php|php(3|4|5)|phtml|pl|py|jsp|asp|htm|html|shtml|sh|cgi)\./i.test(file.name)) return this.fire("error", {
                        code: 800,
                        message: "FILE_INVALID_ERROR",
                        file: file
                    }), !1;
                    if ("*" !== this.options.filetypes) if (!1 === new RegExp("^(" + this.options.filetypes.split(",").join("|") + ")$", "i").test(ext)) return this.fire("error", {
                        code: 601,
                        message: "FILE_EXTENSION_ERROR",
                        file: file
                    }), !1;
                    return file.size && parseInt(file.size, 10) > 1024 * parseInt(this.options.max_size, 10) ? (this.fire("error", {
                        code: 600,
                        message: "FILE_SIZE_ERROR",
                        file: file
                    }), !1) : (file.id = uid(), file.extension = ext, file.mimetype = file.type || (/(jpg|jpeg|bmp|tiff|tif|gif|png|webp)/.test(ext) ? mime[ext] : "text/plain"), 
                    name = name.replace(/\\/g, "/").replace(/\/+/g, "/"), file.filename = name.split("/").pop(), 
                    this.fire("fileadded", file), this.fileExists(file) ? (this.fire("error", {
                        code: 700,
                        message: "FILE_EXISTS_ERROR",
                        file: file
                    }), !1) : void this.files.push(file));
                }
            },
            removeFile: function(file) {
                this.fire("fileremoved", file);
                file = this.getFileIndex(file);
                return -1 !== file && this.files.splice(file, 1), this;
            },
            getFileIndex: function(file) {
                for (var files = this.files, len = files.length, i = 0; i < len; i++) if (files[i] && files[i].id === file.id) return i;
                return -1;
            },
            fileExists: function(file) {
                for (var files = this.files, len = files.length, i = 0; i < len; i++) if (files[i] && files[i].filename === file.filename) return !0;
                return !1;
            },
            updateFile: function(file, property) {
                var self = this, i = this.getFileIndex(file);
                return -1 !== i && $.each(property, function(name, value) {
                    !1 === /^(size|type|element)$/.test(name) && (self.files[i][name] = value);
                }), this;
            },
            renameFile: function(file, name) {
                return this.updateFile(file, {
                    filename: name
                });
            },
            upload: function(file, success, error) {
                var data, self = this, o = this.options, o = ("object" === $.type(o.data) && (data = $.extend({
                    name: file.filename || ""
                }, o.data)), "array" === $.type(o.data) && (data = $.merge([ {
                    name: "name",
                    value: file.filename || ""
                } ], o.data)), {
                    url: o.url,
                    data_name: o.input_name,
                    multipart: data,
                    callback: function(ev, args) {
                        self.fire(ev, args), "uploadcomplete" !== ev && "error" !== ev || (self.transport = null, 
                        ("uploadcomplete" === ev ? success : error)(args));
                    }
                });
                return this.transport = new Transport(o), this.transport.upload(file), 
                this;
            },
            uploadFilesInBlocks: function(files, blockSize) {
                var self = this;
                function uploadFile(file) {
                    return new Promise((resolve, reject) => {
                        self.fire("uploadstart", file), self.upload(file, function(response) {
                            resolve(response), self.removeFile(file);
                        }, function(error) {
                            reject(error);
                        });
                    });
                }
                !function uploadNextBlock() {
                    var currentBlockSize;
                    0 === files.length ? self.fire("allcomplete") : (currentBlockSize = Math.min(blockSize, files.length), 
                    currentBlockSize = files.slice(0, currentBlockSize).map(uploadFile), 
                    Promise.all(currentBlockSize).then(() => {
                        setTimeout(uploadNextBlock, 500);
                    }).catch(error => {
                        console.error("An error occurred while uploading:", error);
                    }));
                }();
            },
            start: function() {
                return this.uploadFilesInBlocks(this.files, 5), this;
            },
            clear: function() {
                return this.files = [], $(this.element).val("").siblings(".wf-uploader-element").remove(), 
                this;
            },
            stop: function() {
                return this.transport && (this.transport.abort(), this.fire("abort")), 
                this;
            },
            destroy: function() {
                return this.transport && (this.transport.cleanup(), this.transport = null), 
                this.clear(), this.fire("destroy"), $.each(this._events, function(i, ev) {
                    $(document).off("upload:" + ev);
                }), this;
            }
        }, window.Uploader = Uploader;
    }(jQuery, window), function($, Wf) {
        function UploadWidget(element, options) {
            this.element = element || $("<div></div>"), this.uploader = {}, this.errors = 0, 
            this.uploading = !1, this.options = $.extend({
                field: $("input[name=file]:first"),
                max_size: !1,
                limit: 0,
                filetypes: "*",
                insert: !0,
                buttons: {},
                websafe_mode: "utf-8",
                browse_button: "#upload-browse",
                upload_button: "#upload-start",
                drop_target: "#upload-body"
            }, options), this.init();
        }
        UploadWidget.prototype = {
            FILE_SIZE_ERROR: 600,
            FILE_EXTENSION_ERROR: 601,
            FILE_EXISTS_ERROR: 700,
            FILE_INVALID_ERROR: 800,
            _trigger: function(ev, args) {
                $(this.element).trigger("uploadwidget:" + ev.toLowerCase(), args);
            },
            init: function() {
                this.uploader instanceof Uploader && this.uploader.destroy(), $(this.options.field).remove(), 
                this._createUploader();
            },
            _createUploader: function() {
                var self = this;
                $.support.xhr2 || $(this.element).addClass("wf-uploader-html4"), 
                this.uploader = new Uploader(this.options), this.uploader.on("init", function() {
                    self._createDragDrop(), self._trigger("init");
                }), this.uploader.on("fileadded", function(e, file) {
                    self._createQueue(file), self._trigger("fileadded", file);
                }), this.uploader.on("uploadstart", function(e, file) {
                    self._onStart(file);
                }), this.uploader.on("allcomplete", function() {
                    self._onAllComplete();
                }), this.uploader.on("uploadcomplete", function(e, o) {
                    self._onComplete(o);
                }), this.uploader.on("dragover", function(e, o) {
                    $(self.options.drop_target).addClass("wf-upload-dragover");
                }), this.uploader.on("dragleave", function(e, o) {
                    $(self.options.drop_target).removeClass("wf-upload-dragover");
                }), this.uploader.on("drop", function(e, o) {
                    $(self.options.drop_target).removeClass("wf-upload-dragover");
                }), this.uploader.on("close", function(e, o) {
                    self.close();
                }), this.uploader.on("error", function(up, error) {
                    var file = error.file;
                    "string" == typeof error && (error = {
                        message: error,
                        code: 500
                    }), file && (error.code < 600 ? $(file.element).removeClass("queue-item-loading").addClass("queue-item-error") : $(file.element).remove(), 
                    self._showError(error, file)), self.errors++;
                }), this.uploader.on("fileremoved", function(file) {}), this.uploader.on("progress", function(o, file) {
                    self._onProgress(file);
                }), this.uploader.init();
            },
            _showError: function(error, file) {
                var self = this, msg = (error = $.extend({
                    message: "",
                    code: 500
                }, error), "array" === $.type(error.message) && (error.message = error.message.join("\n")), 
                error.message = $("<textarea></textarea>").html(error.message).text(), 
                error.message.replace(/[^a-z_ ]/gi, "").replace(/\s+/g, "_").toLowerCase()), details = "", msg = Wf.translate(msg, error.message);
                if (msg = (msg = msg.replace(/<br[\s\/]+?>/gi, "")).replace("%s", file.name), 
                error.details) details = "<br />" + error.details; else {
                    switch (error.code) {
                      case self.FILE_EXTENSION_ERROR:
                      case self.FILE_INVALID_ERROR:
                      case self.FILE_EXISTS_ERROR:
                        details = details.replace("%s", file.name);
                        break;

                      case self.FILE_SIZE_ERROR:
                        details = details.replace(/%([fsm])/g, function($0, $1) {
                            switch ($1) {
                              case "f":
                                return file.name;

                              case "s":
                                return Wf.String.formatSize(file.size);

                              case "m":
                                return Wf.String.formatSize(1024 * self.options.max_size);
                            }
                        });
                    }
                    details && (msg += "<br />" + details);
                }
                error.code < 600 ? ($(".uk-progress", file.element).hide(), $('<div class="uk-alert uk-alert-danger uk-width-1-1 uk-text-center"></div>').html(msg).appendTo(file.element)) : (Wf.Modal.alert(msg), 
                this.errors--);
            },
            _onStart: function(file) {
                this._trigger("uploadstart", file), $(file.element).addClass("queue-item-loading").find('input[type="text"]').prop("disabled", !0);
            },
            _isError: function(err) {
                return !!err && (!$.isArray(err) || err.length);
            },
            _onComplete: function(o) {
                var file = o.file, item = ($(file.element).removeClass("queue-item-loading").addClass("queue-item-complete"), 
                {
                    name: file.name
                });
                o.result.files && o.result.files.length && (o = o.result.files[0] || {}, 
                $.extend(item, o.file || o)), this._trigger("filecomplete", [ file, item ]);
            },
            _onAllComplete: function() {
                this.uploading = !1, this._trigger("uploadcomplete", this.getErrorCount());
            },
            _setProgress: function(el, percent) {
                $(".uk-progress-bar", el).css("width", percent + "%").attr("aria-valuenow", percent + "%").text(percent + "%");
            },
            _onProgress: function(file) {
                var percent;
                file.size && (percent = Math.floor(file.loaded / file.size * 100), 
                file.size === file.loaded && (percent = 100), this._setProgress(file.element, percent));
            },
            upload: function(args) {
                return this.uploader.files.length && (this.uploading = !0, this.uploader.options.data = args || {}, 
                this.uploader.start()), !1;
            },
            refresh: function() {},
            close: function() {
                this.uploader instanceof Uploader && (this.uploading && this.uploader.stop(), 
                this.uploader.destroy()), this.errors = 0, this.uploader = {}, this.uploading = !1;
            },
            getErrorCount: function() {
                return this.errors;
            },
            isUploading: function() {
                return this.uploading;
            },
            stop: function() {
                this.uploader.stop();
            },
            start: function() {
                this.uploader.start();
            },
            setStatus: function(s) {
                var file = this.currentFile;
                file && ($(file.element).removeClass("queue-item-loading queue-item-complete queue-item-error").addClass(s.state || ""), 
                s.state) && "error" === s.state && (this.errors++, s.message) && ($(".uk-progress", file.element).hide(), 
                $('<div class="uk-alert uk-alert-danger uk-width-1-1 uk-text-center"></div>').html(s.message).appendTo(file.element));
            },
            _createDragDrop: function() {
                var self = this, msg = ($("#upload-queue-drag").remove(), $("#upload-queue").empty(), 
                Wf.translate("upload_drop_details", "%filetypes files up to %max_size in size"));
                -1 !== msg.indexOf("%") && (msg = msg.replace(/%([\w]+)/g, function(match, key) {
                    var value = self.options[key] || "";
                    return "filetypes" === key && (value = '<span class="uk-text-truncate uk-display-block">' + value + "</span>"), 
                    value = "max_size" === key ? "<strong>" + Wf.String.formatSize(1024 * value) + "</strong>" : value;
                })), $('<div id="upload-queue-drag" class="uk-flex uk-flex-center uk-flex-column uk-flex-middle uk-text-large uk-height-1-1 uk-text-large uk-comment">   <div class="uk-comment-header uk-flex">       <i class="uk-icon-cloud-upload uk-icon-medium uk-margin-right uk-text-muted uk-comment-avatar"></i><h4 class="uk-comment-title">' + Wf.translate("upload_drop", "Drop files here") + '</h4>   </div>   <p class="uk-margin-small uk-comment-meta uk-width-1-2 uk-text-center">' + msg + "</p></div>").appendTo("#upload-queue-block").show();
            },
            _renameFile: function(file, name) {
                this.uploader.renameFile(file, name), this._trigger("filerename", file);
            },
            _removeFiles: function() {
                this.uploader.splice(), this.errors = 0, $(this.element).empty();
            },
            _fileExists: function(file) {
                return this.uploader.fileExists(file);
            },
            _removeFile: function(file) {
                this._trigger("filedelete", file), $(file.element).hasClass("queue-item-error") && this.errors--, 
                $(file.element).remove(), this.uploader.removeFile(file);
            },
            _createQueue: function(file) {
                var self = this, name = Wf.String.basename(file.filename), title = (name = Wf.String.safe(name, self.options.websafe_mode, self.options.websafe_spaces), 
                file.filename = name, Wf.String.stripExt(name)), remove = (file.element = document.createElement("div"), 
                $('<button class="uk-button uk-button-link"></button>').attr({
                    title: Wf.translate("delete", "Delete")
                }).addClass("queue-item-action").on("click", function(e) {
                    return e.preventDefault(), self.uploading ? self._stop(file) : self._removeFile(file);
                }).append('<i class="uk-icon uk-icon-trash"></i>')), ext = file.extension.toLowerCase(), ext = $('<i class="uk-icon uk-icon-file-' + function(ext) {
                    return /^(flv|mp4|m4v|webm|ogg|ogv|mov|wmv|avi|mvk|webm)$/.test(ext) ? "video" : /^(mp3|ogg|oga)$/.test(ext) ? "audio" : /^(jpg|jpeg|png|gif|png|svg|bmp|tiff|webp)$/.test(ext) ? "image" : /^(txt|htm|html)$/.test(ext) ? "text" : /^(doc|docx|dot|dotx)$/.test(ext) ? "word" : /^(xls|xlsx)$/.test(ext) ? "excel" : /^(ppt|pptx)$/.test(ext) ? "powerpoint" : /^(rar|zip|tar|gz)$/.test(ext) ? "zip" : /^(html|htm)$/.test(ext) ? "code" : /^(txt|rtf|csv)$/.test(ext) ? "text" : ext;
                }(ext) + '"></i><input type="text" value="' + title + '" class="uk-width-1-1" /><span class="queue-item-extension uk-text-muted uk-icon-none">.' + file.extension + "</span>"), name = $('<div class="queue-item-name uk-width-3-4 uk-width-small-4-5 uk-form-icon uk-form-icon-both"></div>').append(ext), buttons = [ remove ], title = ($.each(self.options.buttons, function(name, props) {
                    name = $('<button class="uk-button uk-button-link" title="' + props.title || name + '"></button>').addClass(props.class).on("click", function(e) {
                        $(this).hasClass("disabled") || (props.click || $.noop).call(self, this), 
                        e.preventDefault();
                    });
                    buttons.push(name);
                }), $('<div class="queue-item-size uk-flex-item-auto uk-text-center uk-hidden-mini" title="' + Wf.String.formatSize(file.size) + '" role="presentation"></div>').html(Wf.String.formatSize(file.size))), ext = $('<div class="queue-item-actions uk-flex uk-width-1-4 uk-width-small-1-5 uk-text-right"></div>').appendTo(file.element).append(title).append(buttons), remove = $('<div class="uk-progress uk-width-1-1"><div class="uk-progress-bar"></div></div>');
                $(file.element).addClass("queue-item uk-width-1-1 uk-flex uk-flex-wrap").appendTo($(self.element)).append([ name, ext, remove ]), 
                $('input[type="text"]', file.element).on("change keyup", function(e) {
                    this.value;
                    var v = Wf.String.safe(this.value, self.options.websafe_mode, self.options.websafe_spaces);
                    $(this).toggleClass("uk-form-danger", v !== this.value), "change" === e.type && self._renameFile(file, v + "." + file.extension);
                }).trigger("change"), self._trigger("fileSelect", file);
            },
            _stop: function(file) {
                this.uploader.stop(), $(file.element).removeClass("queue-item-loading");
            }
        }, $.fn.uploader = function(options) {
            var inst = new UploadWidget(this, options);
            return $(this).on("uploadwidget:upload", function(e, data) {
                if (inst.isUploading()) return !1;
                inst.upload(data);
            }), $(this).on("uploadwidget:close", function() {
                inst.close();
            }), this;
        };
    }(jQuery, Wf), ($ = jQuery).fn.listsort = function(options) {
        options = $.extend({
            fields: {}
        }, options);
        var el = this;
        function sortDate(a, b) {
            var a = a.value, b = b.value, r = 0, re = /(\d{2})[\/](\d{2})[\/](\d{4}), (\d{2})[:](\d{2})/g, d1 = a.replace(re, "$3$2$1"), d2 = b.replace(re, "$3$2$1"), a = a.replace(re, "$4$5");
            return d2 < d1 && (r = 1), d1 < d2 && (r = -1), (d1 = b.replace(re, "$4$5")) < a && (r = 1), 
            r = a < d1 ? -1 : r;
        }
        function sortCompare(a, b) {
            return a.value < b.value ? -1 : b.value < a.value ? 1 : 0;
        }
        return $.each(options.fields, function(element, props) {
            $(element).addClass("asc").on("click", function() {
                var direction = "asc", selector = ($(this).toggleClass(function() {
                    return direction = $(this).is(".asc") ? ($(this).removeClass("asc"), 
                    "desc") : ($(this).removeClass("desc"), "asc");
                }), props.selector);
                "string" == $.type(selector) && (selector = [ selector ]), $.each(selector, function(i, s) {
                    !function(selector, type, attribute, direction) {
                        var fn;
                        fn = "date" === type ? sortDate : sortCompare;
                        selector = $(selector, el).map(function() {
                            var v = $(this).attr(attribute) || $(this).text();
                            return "number" == type && (v = parseFloat(v)), "extension" == type && (v = v.substring(v.length, v.lastIndexOf(".") + 1).toLowerCase()), 
                            {
                                value: v = "string" == type ? v.toLowerCase() : v,
                                element: this
                            };
                        }).get();
                        selector.sort(fn), "desc" != direction && "extension" != type || selector.reverse();
                        $.each(selector, function(i, item) {
                            $(el).append(item.element);
                        }), selector = null, $(el).trigger("listsort:sort", {
                            type: type,
                            direction: direction
                        });
                    }(s, $(element).data("sort-type"), props.attribute, direction);
                });
            });
        }), this;
    }, function($) {
        var specialKeyCodeMap = {
            9: "tab",
            17: "ctrl",
            18: "alt",
            27: "esc",
            37: "left",
            39: "right",
            13: "enter",
            38: "up",
            40: "down",
            91: "cmd"
        };
        function escapeRegExChars(str) {
            return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
        }
        $.fn.listfilter = function(options) {
            options = $.extend({
                list: null,
                items: null,
                clear: null,
                sort: null,
                hide: !1,
                filter: null
            }, options);
            function keyup() {
                var context = this, args = arguments, later = function() {
                    timeout = null, immediate || (result = func.apply(context, args));
                }, callNow = immediate && !timeout;
                return clearTimeout(timeout), timeout = setTimeout(later, wait), 
                result = callNow ? func.apply(context, args) : result;
            }
            var func, wait, immediate, timeout, result, el = this;
            $(options.clear).on("click.listfilter", function(e) {
                reset(), $(el).val(""), $(el).trigger("listfilter:clear", [ e ]);
            }), $(el).on("listfilter:filter", function(e, s) {
                !function(s) {
                    var v, x = [];
                    matcher = "." === s.charAt(0) ? (v = s.substr(1), new RegExp(".(" + escapeRegExChars(v) + "[a-z0-9]*)$", "i")) : (s = toUnicode(s), 
                    new RegExp(escapeRegExChars(s), "ui"));
                    /[\u0000-\u1FFF\.\-\s ]/i.test(s) ? $(options.selector, options.list).each(function() {
                        var title = toUnicode($(this).attr("title"));
                        matcher.test(title) ? -1 === $.inArray(this, x) && x.push(this) : -1 !== (title = $.inArray(this, x)) && x.splice(title, 1);
                    }) : x = [];
                    x && x.length ? ($(options.selector, options.list).show().not(x).hide(), 
                    scroll(x[0])) : reset();
                    $(el).trigger("listfilter:found", [ null, x ]);
                }(s);
            }), func = function(e) {
                var v;
                e.keyCode && specialKeyCodeMap[e.keyCode] || (v = $(el).val(), setTimeout(function() {
                    "" === v ? $(options.clear).trigger("click.listfilter") : (e.stopImmediatePropagation(), 
                    v.length < 3 || $(el).trigger("listfilter:find", [ v ]));
                }, 0));
            }, wait = 500;
            function toUnicode(s) {
                for (var str = "", i = 0, ln = s.length; i < ln; i++) {
                    var ch = s[i];
                    str += ch = /[^\w\.\-\s \/]/i.test(ch) ? "\\u" + ch.charCodeAt(0) : ch;
                }
                return str;
            }
            function scroll(el) {
                var el = $(el).position() || {
                    top: 0
                }, top = $(options.list).scrollTop();
                $(options.list).css("overflow", "hidden").animate({
                    scrollTop: el.top + top
                }, 1e3, function() {
                    $(options.list).css("overflow", "auto");
                });
            }
            function reset() {
                $(options.selector, options.list).show(), scroll($(options.selector, options.list).first());
            }
            return $(el).on("keyup.listfilter paste.listfilter cut.listfilter", keyup), 
            this;
        };
    }(jQuery), function($, Wf) {
        for (var y, ext, mimeTypes = {}, items = "video,flv|mp4|m4v|webm|ogg|ogv|mov|wmv|avi,audio,mp3|ogg|oga|webm|m4a,image,jpg|jpeg|apng|png|gif|png|svg|bmp|tiff|webp,text,txt|htm|html,word,doc|docx|dot|dotx,excel,xls|xlsx,powerpoint,ppt|pptx,zip,rar|zip|tar|gz,code,html|htm|xml,text,txt|rtf|csv".split(","), i = 0; i < items.length; i += 2) for (ext = items[i + 1].split("|"), 
        y = 0; y < ext.length; y++) mimeTypes[ext[y]] = items[i];
        function getMimeType(ext) {
            return ext = ext.toLowerCase(), ext = $.trim(ext), mimeTypes[ext] || ext;
        }
        function FileBrowser(element, options) {
            this.element = element, $.extend(this, {
                _actions: {},
                _buttons: {
                    folder: {},
                    file: {}
                },
                _modal: [],
                _returnedItems: [],
                _pasteitems: "",
                _pasteaction: "",
                _limitcount: 0,
                _limitend: 0
            }), this.options = FileBrowser.options, this.setOptions(options), this._init(), 
            this.actionTarget = null;
        }
        var scrollEvents = "click.scroll mousedown.scroll wheel.scroll mousewheel.scroll keyup.scroll touchmove.scroll";
        FileBrowser.options = {
            base: "",
            dir: "images",
            source: "",
            actions: null,
            buttons: null,
            folder_tree: !0,
            details: !0,
            search: !0,
            upload: {
                max_size: 1024,
                filetypes: "*",
                overwrite: !0,
                limit: 0,
                dialog: {},
                elements: null,
                buttons: {}
            },
            folder_new: {
                dialog: null
            },
            rename: {
                dialog: null
            },
            viewable: "jpeg,jpg,gif,png,webp,avi,wmv,wm,asf,asx,wmx,wvx,mov,qt,mpg,mp3,mp4,m4v,mpeg,ogg,ogv,webm,swf,flv,f4v,xml,dcr,rm,ra,ram,divx,html,htm,txt,rtf,pdf,doc,docx,xls,xlsx,ppt,pptx",
            list_limit: 0,
            view_mode: "list",
            expandable: !0,
            websafe_mode: "utf-8",
            websafe_spaces: !1,
            websafe_textcase: "",
            date_format: "%d/%m/%Y, %H:%M",
            allow_download: !1,
            use_state_cookies: !0
        }, FileBrowser.prototype = {
            _trigger: function(ev, args) {
                $(this.element).trigger("filebrowser:" + ev.toLowerCase(), args);
            },
            setOptions: function(options) {
                this.options = $.extend(this.options, options);
            },
            getOptions: function() {
                return this.options;
            },
            _init: function(options) {
                var self = this, options = (this.options = $.extend(this.options, options), 
                $.each(this.options, function(k, v) {
                    "function" == typeof v && ($(self.element).on("filebrowser:" + k.toLowerCase(), v), 
                    delete self.options[k]);
                }), this._addActions(this.options.actions), this._addButtons(this.options.buttons), 
                document.createElement("ul")), options = ($(options).addClass("item-list").attr({
                    id: "item-list",
                    role: "listbox"
                }).on("click.item-list", function(e) {
                    var u, n = e.target, p = n.parentNode;
                    if (!$(n).hasClass("ui-sortable-handle")) return $(n).is(".uk-icon, span, a, img") && (n = $(n).parents("li").get(0)), 
                    "LI" === (self.actionTarget = n).nodeName ? $(n).hasClass("folder") ? (u = $(n).data("url") || self._getPreviousDir(), 
                    e.preventDefault(), self._changeDir(u)) : (e.altKey && $(n).find("a[download]").length || (e.target = n, 
                    self._setSelectedItems(e, !0), self.serializeItemData(n).then(function(data) {
                        self._trigger("onFileClick", [ n, data ]);
                    }), e.preventDefault()), !0) : "INPUT" === n.nodeName ? ($(n).is(":checked") ? (e.target = n, 
                    self._setSelectedItems(e, !0)) : self._removeSelectedItems([ p.parentNode ], !0), 
                    p = $(n).parents("li"), self.serializeItemData(p).then(function(data) {
                        data.state = $(n).is(":checked"), self._trigger("onFileToggle", [ p, data ]);
                    }), !0) : void 0;
                }).on("dblclick.item-list", function(e) {
                    var n = e.target, n = $(n).parents("li").get(0);
                    return $(n).hasClass("folder") ? e.preventDefault() : (self.serializeItemData(n).then(function(data) {
                        self._trigger("onFileInsert", [ n, data ]);
                    }), e.preventDefault()), !1;
                }).on("keydown.item-list", function(e) {
                    switch (e.which) {
                      case 13:
                        var n = $("li.selected:last", "#item-list").get(0);
                        if (!n) return;
                        self.actionTarget = n;
                        var p = $(n).parents("li");
                        if ($(n).hasClass("folder")) return p = $(p).data("url") || self._getPreviousDir(), 
                        self._changeDir(p);
                        self._setSelectedItems(e, !0), self.serializeItemData(n).then(function(data) {
                            self._trigger("onFileClick", [ n, data ]);
                        });
                        break;

                      case 38:
                      case 40:
                        self._setSelectedItems(e);
                    }
                    e.preventDefault();
                }), $(".folder-up", "#browser").on("click", function(e) {
                    e.preventDefault(), self.actionTarget = null;
                    e = self._getPreviousDir();
                    return self._changeDir(e);
                }), $("#browser-list").append(options).on("scroll.browser-list", function(e) {
                    self._updateList();
                }), $(".details-nav-left, .details-nav-right", "#browser-details-nav").on("click", function(e) {
                    var $item = $("li.selected.active", "#item-list").removeClass("active");
                    $(this).hasClass("details-nav-left") && $item.prevAll("li.selected:first").addClass("active"), 
                    $(this).hasClass("details-nav-right") && $item.nextAll("li.selected:first").addClass("active"), 
                    e.preventDefault(), self._showItemDetails();
                }), self._getState("limit", this.options.list_limit, function(val) {
                    return !1 == !/([0125]+)/.test(val);
                })), options = ($("#browser-list-limit-select").val(options), $("#browser-list-limit-select").on("change", function() {
                    self._limitcount = 0, self._setState("limit", $(this).val()), 
                    self.refresh();
                }), $("ul li", "#browser-list-limit").on("click", function(e) {
                    e.preventDefault();
                    var e = 0, count = self._limitcount, limit = parseInt(self._limit, 10);
                    $(this).hasClass("limit-left") && (e = count - limit), $(this).hasClass("limit-right") && (e = count + limit), 
                    $(this).hasClass("limit-right-end") && (e = self._limitend), 
                    self._limitcount = e, self.refresh();
                }), $('input[type="checkbox"]', "#check-all").on("click", function(e) {
                    e = e.target, e = $(e).is(":checked");
                    $('input[type="checkbox"]', "#browser-list").prop("checked", !!e), 
                    e ? self._selectItems($("li", "#browser-list").not(".folder-up"), !0) : self._deselectItems();
                }), this._setupListSort(), $("#block-search-icon").toggle(this.options.search), 
                $("#show-details").toggle(this._treeLoaded()), $("#show-search").on("click", function() {
                    $("#searchbox").toggleClass("uk-hidden").attr("aria-hidden", function() {
                        return $(this).hasClass("uk-hidden");
                    }), $(this).toggleClass("uk-active"), $(this).hasClass("uk-active") && $("#search").trigger("focus");
                }), $("#search + .uk-icon").on("click", function() {
                    $("#search").trigger("focus");
                }), $("body").on("click", function(e) {
                    $("#searchbox").hasClass("uk-hidden") || $(e.target).is("#searchbox, #search, #show-search, #show-search .uk-icon-search, #search + .uk-icon") || ($("#show-search").removeClass("uk-active"), 
                    $("#searchbox").addClass("uk-hidden").attr("aria-hidden", !0));
                }), $("#search").listfilter({
                    list: "#item-list",
                    selector: "li",
                    clear: "#search + .uk-icon"
                }).on("listfilter:find", function(ev, s) {
                    var prefix, el = this;
                    return s ? (prefix = "", "." === s.charAt(0) && (s = s.substr(1), 
                    prefix = "."), self._setLoader(), $("#browser-list").one("load.filter", function() {
                        $(el).trigger("listfilter:found", [ null, $("li.file", "#item-list").get() ]);
                    }), self._reset(), self._searchQuery = prefix + s, self._getList("", self._searchQuery)) : (self._searchQuery = "", 
                    self.refresh()), !0;
                }).on("listfilter:clear", function(ev) {
                    self._searchQuery = "", self.refresh();
                }), $("#refresh").on("click", function(e) {
                    self.refresh(e);
                }).on("button:refresh", function(e, state) {
                    state ? ($(".uk-icon", this).addClass("uk-icon-spinner"), $(this).prop("disabled", !0)) : ($(".uk-icon", this).removeClass("uk-icon-spinner"), 
                    $(this).prop("disabled", !1));
                }), this._getState("details", 0, function(val) {
                    return 0 === (val = parseInt(val, 10)) || 1 === val;
                }));
                parseInt(options, 10) || !this._treeLoaded() ? ($("#show-details").removeClass("uk-active"), 
                $("main").addClass("uk-tree-hidden")) : ($("#show-details").addClass("uk-active"), 
                $("main").removeClass("uk-tree-hidden")), $("#show-details:visible").on("click", function(e) {
                    $(this).toggleClass("uk-active"), $("main").toggleClass("uk-tree-hidden"), 
                    self._setState("details", $("main").hasClass("uk-tree-hidden") ? 1 : 0);
                }), this.options.expandable && ($("#browser").addClass("expandable"), 
                $("#layout-full-toggle").on("click", function() {
                    $("#browser").toggleClass("full-height"), self._trigger($("#browser").hasClass("full-height") ? "onMaximise" : "onMinimise");
                })), $("#browser-list").on(scrollEvents, function() {
                    $(this).stop();
                }), this._setupDir(), this._trigger("onInit", this);
            },
            _updateList: function() {
                var self = this, top = $("#browser-list").scrollTop(), area = $("#browser-list").height() + top;
                $(".file.jpg, .file.jpeg, .file.png, .file.gif, .file.bmp", "#item-list").not("[data-width]").each(function() {
                    $(this).position().top < area && self._getDimensions(this);
                });
            },
            _getInterfaceHeight: function() {
                var ih = Math.max(0, Math.round($("#browser").offset().top) - 5), p = $("#browser").parent("form");
                return ih = $(p).next(":not(div.actionPanel)").length ? Math.round($("div.actionPanel").offset().top) - 10 - $("#browser").innerHeight() : ih;
            },
            resize: function(ih, init) {},
            _translate: function(s, ds) {
                return Wf.translate(s, ds);
            },
            _setupListSort: function() {
                var self = this;
                this._sortValue = this._getState("sort", "", function(val) {
                    return /[a-z-]+/.test(val);
                }), $("#sort-ext, #sort-name, #sort-date, #sort-size").on("click", function() {
                    $(this).siblings(".asc, .desc").removeClass("desc").addClass("asc");
                    var direction = "", direction = $(this).hasClass("asc") ? ($(this).removeClass("asc").addClass("desc"), 
                    "-") : ($(this).removeClass("desc").addClass("asc"), ""), type = $(this).data("sort");
                    self._sortValue = direction + type, self._setState("sort", self._sortValue), 
                    self.refresh();
                }).addClass(function() {
                    return -1 !== this.id.indexOf(self._sortValue) && self._sortValue && "-" === self._sortValue.charAt(0) ? "desc" : "asc";
                });
            },
            _validatePath: function(s) {
                if (/\.{2,}/.test(s) || /:\/\//.test(s) && -1 == s.indexOf(Wf.getURI(!0))) return !1;
                if (/:\/\//.test(s) && (s = Wf.URL.toRelative(s)), /[^\w\.\-\s \/]/i.test(s)) for (var i = 0, ln = s.length; i < ln; i++) {
                    var ch = s[i];
                    if (/[^\w\.\-\s \/]/i.test(ch) && function(c) {
                        for (c = c.toString(16).toUpperCase(); c.length < 4; ) c = "0" + c;
                        return "\\u" + c;
                    }(ch.charCodeAt(0)) < "\\u007F") return !1;
                }
                return !0;
            },
            _trimPath: function(path) {
                return (path = "" + path).replace(/^\//, "").replace(/\/$/, "");
            },
            _cleanPath: function(path) {
                return path = path && (new RegExp("://").test(path) && (path = Wf.URL.toRelative(path)), 
                path = this._trimPath(path), /\.([a-z0-9]{2,}$)/i.test(path)) ? (path = Wf.String.dirname(path)).replace(new RegExp(this.options.dir), "").replace(/^[\/\\]+/, "") : path;
            },
            _setupDir: function() {
                var self = this, dir = "", src = this.options.source || $(this.element).val(), base = this.options.base;
                -1 !== (src = (src = src && base && 0 === src.indexOf(base) ? src.substr(base.length + 1) : src).replace(/(&amp;|\?)/g, "&")).indexOf("&") && (src = src.substr(0, src.indexOf("&"))), 
                src = this._trimPath(src), (src = this._validatePath(src) ? src : "") || (dir = this._getState("dir", "", function(val) {
                    return val && self._validatePath(val);
                })), this._validatePath(dir) || (dir = ""), this._setDir(Wf.String.encodeURI(dir)), 
                src && /:\/\//.test(src) && (src = Wf.URL.toRelative(src)), this.setStatus({
                    message: this._translate("loading", "Loading..."),
                    state: "load"
                }), this._treeLoaded() ? this._createTree(src) : this._getList(src);
            },
            _toggleTree: function(s) {
                $("#browser").toggleClass("full-width", !s), $("div.layout-left", "#browser").attr("aria-hidden", !s), 
                $("#sort-size, #sort-date").attr("aria-hidden", s), $("span.size, span.date", "#item-list").attr("aria-hidden", s);
            },
            _isWebSafe: function(name) {
                var safe = Wf.String.safe(name, this.options.websafe_mode, this.options.websafe_spaces, this.options.websafe_textcase);
                return name.toLowerCase() === safe.toLowerCase();
            },
            _isViewable: function(name) {
                var button = this._getButton("file", "view"), viewable = this.options.viewable;
                return button && button.restrict && (viewable = button.restrict), 
                new RegExp("\\.(" + viewable.replace(/,/g, "|") + ")$", "i").test(name);
            },
            _buildList: function(o) {
                var self = this, h = "";
                $("#item-list").empty(), $("#browser").toggleClass("root", this._isRoot()), 
                this._isRoot(), o.folders.length && $.each(o.folders, function(i, e) {
                    var data = [], classes = [];
                    if (!e.id) return !0;
                    $.each(e.properties, function(k, v) {
                        "" !== v && data.push("data-" + k + '="' + v + '"');
                    }), data.push('data-url="' + (e.url || e.id) + '"'), classes.push(self._isWebSafe(e.name) ? "safe" : "notsafe"), 
                    classes.push(e.writable ? "writable" : "notwritable"), e.classes && classes.push(e.classes), 
                    h = (h = (h = (h += '<li class="uk-grid uk-grid-collapse uk-flex folder ' + classes.join(" ") + '" title="' + e.name + '"' + data.join(" ") + ">") + '  <label class="uk-width-0-10 uk-item-checkbox" aria-label="' + self._translate("select", "Select") + '"><input type="checkbox" /></label>  <i class="uk-width-1-10 uk-icon uk-icon-folder folder"></i>') + '  <a class="uk-width-1-5 uk-padding-remove uk-flex-item-auto uk-text-truncate" href="#">' + e.name + "</a>") + '  <span class="uk-width-6-10 uk-item-date uk-hidden-mini">' + Wf.String.formatDate(e.properties.modified, self.options.date_format) + "</span></li>";
                }), o.files.length && $.each(o.files, function(i, e) {
                    var data = [], classes = [];
                    if (!e.id) return !0;
                    $.each(e.properties, function(k, v) {
                        "" !== v && data.push("data-" + k + '="' + v + '"');
                    }), e.url && data.push('data-url="' + e.url + '"'), data.push('id="' + e.id + '"'), 
                    classes.push(self._isWebSafe(e.name) ? "safe" : "notsafe"), 
                    classes.push(e.writable ? "writable" : "notwritable"), e.selected && self._addReturnedItem({
                        name: e.id
                    }), e.classes && classes.push(e.classes);
                    var ext = Wf.String.getExt(e.name), name = Wf.String.stripExt(e.name), filename = name + "." + ext, icon = ext.toLowerCase(), download = "";
                    self.options.allow_download && e.properties.preview && (download = ' download="' + filename + '"'), 
                    h = (h = (h = (h = (h = (h = (h += '<li class="uk-grid uk-grid-collapse uk-flex file ' + ext.toLowerCase() + " " + classes.join(" ") + '" title="' + e.name + '"' + data.join(" ") + ">") + '  <label class="uk-width-0-10 uk-item-checkbox" aria-label="' + self._translate("select", "Select") + '"><input type="checkbox" /></label>') + '  <i class="uk-width-1-10 uk-icon uk-icon-file uk-icon-file-' + getMimeType(icon) + " file " + icon + '"></i>') + '  <a class="uk-width-1-5 uk-padding-remove uk-flex-item-auto" href="' + (e.properties.preview || "#") + '"' + download + '>      <span class="uk-item-text uk-text-truncate uk-display-inline-block">' + name + "</span>") + '      <span class="uk-item-extension uk-display-inline-block">.' + ext + "</span>  </a>") + '  <span class="uk-width-2-10 uk-item-date uk-hidden-mini">' + Wf.String.formatDate(e.properties.modified, self.options.date_format) + "</span>") + '  <span class="uk-width-4-10 uk-item-size uk-hidden-mini">' + Wf.String.formatSize(e.properties.size) + "</span></li>";
                }), $("#item-list").html(h), this._showListDetails();
            },
            _showListDetails: function() {
                var s = !$(".layout-icon", "#show-details").hasClass("tree") && this._treeLoaded();
                this._toggleTree(s);
            },
            _treeLoaded: function() {
                return this.options.folder_tree && "function" == typeof $.fn.tree;
            },
            _createTree: function(src) {
                var self = this, path = src || this._dir, path = this._cleanPath(path);
                $("#tree-body").on("tree:init", function(e, callback) {
                    Wf.JSON.request("getTree", path, function(o) {
                        $("#tree-body").html(o), "function" == typeof callback && callback(), 
                        path && path !== self._trimPath(self.options.dir) && $("#tree-body").trigger("tree:scroll", path), 
                        self._getList(src);
                    });
                }).on("tree:nodeclick", function(e, evt, node) {
                    self.actionTarget = node, self._changeDir($(node).attr("data-id"));
                }).on("tree:nodeload", function(e, node) {
                    self._refreshTree(node);
                }).tree();
            },
            _refreshTree: function(node) {
                node = node || $(".uk-tree-root", "#tree-body"), $("#tree-body").trigger("tree:toggleloader", node), 
                Wf.JSON.request("getTreeItem", $(node).attr("data-id"), function(o) {
                    o && !o.error && ($("ul:first", node).remove(), $("#tree-body").trigger("tree:createnode", [ o.folders, node ]), 
                    $("#tree-body").trigger("tree:togglenodestate", [ node, !0 ])), 
                    $("#tree-body").trigger("tree:toggleloader", node);
                }, this);
            },
            _reset: function() {
                this._deselectItems(), this._returnedItems = [], $('input[type="checkbox"]', "#check-all").prop("checked", !1), 
                $("li", "#browser-details-nav").addClass("uk-invisible").attr("aria-hidden", !0).filter(".details-nav-text").empty(), 
                this._limit = 0;
            },
            _clearPaste: function() {
                this._pasteaction = "", this._pasteitems = "", this._hideButtons($(".paste", "#buttons"));
            },
            setStatus: function(o) {
                $("#browser-message").removeClass("load error"), $("#browser-message").toggleClass(o.state), 
                $("#refresh").trigger("button:refresh", [ o.state ]), $(".message", "#browser-message").html(o.message);
            },
            _setMessage: function(message, classname) {
                return !0;
            },
            _setLoader: function() {
                this.setStatus({
                    message: this._translate("message_load", "Loading..."),
                    state: "load"
                });
            },
            _resetMessage: function() {
                return !0;
            },
            _resetStatus: function() {
                var x, parts, self = this, dir = decodeURIComponent(this._dir), $status = $("#browser-message"), $pathway = (this.setStatus({
                    message: "",
                    state: ""
                }), $(".uk-breadcrumb.pathway", $status)), sw = ($("li", $pathway).not(":first").remove(), 
                $status.width()), $count = ($("li:first", $pathway).on("click", function() {
                    self._changeDir("/");
                }), dir = $.trim(this._trimPath(dir)), $('<li class="count">( ' + this._foldercount + " " + this._translate("folders", "folders") + ", " + this._filecount + " " + this._translate("files", "files") + ")</li>").appendTo($pathway)), w = $pathway.outerWidth(!0);
                dir && (x = 1, parts = dir.split("/"), $.each(parts, function(i, s) {
                    var path = s, i = (0 < i && (path = parts.slice(0, i + 1).join("/")), 
                    $('<li title="' + s + '"></li>').on("click", function(e) {
                        self._changeDir(path);
                    }).append("<a>" + s + "</a>").insertBefore($count));
                    w += i.outerWidth(!0), sw < w && $("li", $pathway).eq(x++).addClass("uk-breadcrumb-truncate");
                }));
            },
            _getPreviousDir: function() {
                if (this._dir.length < 2) return this._dir;
                for (var dirs = this._dir.split("/"), s = "", i = 0; i < dirs.length - 1; i++) s = Wf.String.path(s, dirs[i]);
                return s;
            },
            _addReturnedItem: function(items) {
                "array" == $.type(items) ? $.merge(this._returnedItems, items) : this._returnedItems.push(items);
            },
            _returnFile: function(file) {
                this._addReturnedItem({
                    name: Wf.String.basename(file)
                }), this._changeDir(Wf.String.dirname(file));
            },
            _setDir: function(dir) {
                this._dir = "" + dir;
            },
            getBaseDir: function() {
                return this.options.dir;
            },
            getCurrentDir: function() {
                return this._dir;
            },
            _isRoot: function() {
                var s = this._dir;
                return "" === this._trimPath(s);
            },
            _changeDir: function(dir) {
                this._reset(), this._limitcount = 0, this._setDir(dir), this._setLoader(), 
                this._getList(dir);
            },
            _setState: function(name, state) {
                this.options.use_state_cookies && Wf.Storage.set("wf_" + Wf.getName() + "_" + name, state);
            },
            _getState: function(name, def, callback) {
                return this.options.use_state_cookies ? (callback = callback || function(val) {
                    return val;
                }, Wf.Storage.get("wf_" + Wf.getName() + "_" + name, def, callback)) : def;
            },
            _getList: function(src, filter) {
                var path = src || this._dir, src = (!src && "" !== this._dir || this._setState("dir", this._cleanPath(path)), 
                this._hideButtons($(".button", "#buttons")), this._limit = parseInt($("#browser-list-limit-select").val(), 10), 
                this._sortValue || ""), method = filter ? "searchItems" : "getItems";
                Wf.JSON.request(method, [ path, this._limit, this._limitcount, filter || "", src ], this._loadList, this);
            },
            refresh: function(e) {
                this._reset(), this.targetElement = null, this._setLoader(), void 0 !== e && ($("#search").val(""), 
                this._searchQuery = "", $("form").append('<input type="hidden" name="refresh" value="1" />'), 
                this._refreshTree()), this._getList("", this._searchQuery);
            },
            load: function(items) {
                var self = this, src = "";
                items && ("string" == $.type(items) && (items = [ items ]), $.each(items, function(i, item) {
                    "string" == $.type(item) && (item = {
                        name: item
                    }), self._addReturnedItem(item), 0 == i && (src = item.name);
                })), this._setLoader(), this._getList(src);
            },
            error: function(error) {
                this._raiseError(error);
            },
            startUpload: function() {
                $("#upload-queue").uploader("start");
            },
            stopUpload: function() {
                $("#upload-queue").uploader("stop");
            },
            setUploadStatus: function(o) {
                $("#upload-queue").uploader("setStatus", o);
            },
            _loadList: function(o) {
                var count, dir = "";
                if ($('input[name="refresh"]', "form").remove(), !o) return this.setStatus({
                    message: "",
                    state: ""
                }), !1;
                this._foldercount = o.total.folders, this._filecount = o.total.files, 
                $(".limit-right li, .limit-left li", "#browser-list-limit").addClass("uk-invisible").attr("aria-hidden", !0), 
                this._limit && (this._limitend = o.total.folders + o.total.files - this._limit, 
                (count = this._limitcount + o.folders.length + o.files.length) < o.total.folders + o.total.files ? $(".limit-right li", "#browser-list-limit").removeClass("uk-invisible").attr("aria-hidden", !1) : $(".limit-right li", "#browser-list-limit").addClass("uk-invisible").attr("aria-hidden", !0), 
                0 < count - this._limit ? $(".limit-left li", "#browser-list-limit").removeClass("uk-invisible").attr("aria-hidden", !1) : $(".limit-left li", "#browser-list-limit").addClass("uk-invisible").attr("aria-hidden", !0)), 
                this._searchQuery || ($.each([].concat(o.folders, o.files), function(i, item) {
                    if (item.id) return dir = Wf.String.encodeURI(Wf.String.dirname(item.id) || "/", !0), 
                    !1;
                }), dir && this._setDir(dir)), this._isRoot() || ($("#folder-list").append('<li class="folder-up" title="Up"><a href="#">...</a></li>'), 
                this._treeLoaded() && ($("#tree-body").trigger("tree:createnode", [ o.folders, this._dir ]), 
                !1 === $(this.actionTarget).is('[role="treeitem"]')) && $("#tree-body").trigger("tree:scroll", this._dir)), 
                this._trigger("onBeforeBuildList", null, o), this._buildList(o), 
                this._resetStatus(), this._resetMessage(), this._trigger("onAfterBuildList", null, o), 
                this._returnedItems.length && (this._findItem(this._returnedItems), 
                this._returnedItems = []), this._pasteitems && this._showPasteButton(), 
                $("#browser-list").trigger("load"), this._trigger("onListComplete");
            },
            _execute: function(name, type, evt, options) {
                var self = this, dir = this._dir, dir = this._trimPath(dir), list = this._serializeSelectedItems(), site = Wf.getURI(!0), elements = "";
                switch (this.options[name] && (elements = this.options[name].elements || ""), 
                name) {
                  case "help":
                    Wf.help();
                    break;

                  case "insert":
                    this._trigger("onFileInsert", null, $("li.selected", "#item-list").get(0));
                    break;

                  case "view":
                    var $item = $("li.selected.active:first", "#item-list"), url = $item.data("url"), url = /http(s)?:\/\//.test(url) ? url : Wf.String.path(site, url), name = ($item.data("preview") && (url = $item.data("preview")), 
                    Wf.String.basename($item.attr("title")));
                    this._isViewable(name) && (/\.(jpeg|jpg|gif|png|webp|svg|apng|avi|wmv|wm|asf|asx|wmx|wvx|mov|qt|mpg|mp3|mp4|m4v|mpeg|ogg|ogv|webm|swf|flv|f4v|xml|dcr|rm|ra|ram|divx|pdf)/i.test(name) ? ($item = {
                        width: $item.data("width") || 0,
                        height: $item.data("height") || 0
                    }, Wf.Modal.media(name, url, $item)) : Wf.Modal.iframe(name, url, {
                        onFrameLoad: function(e) {
                            var iframe = $("div.iframe-preview iframe").get(0), h = iframe.contentWindow.document.body.innerHTML, tmpDiv = document.createElement("div");
                            function toRelative(s) {
                                return (s = Wf.URL.toRelative(s)).replace(/^administrator\//, "");
                            }
                            $(tmpDiv).html(h), $("img, embed", $(tmpDiv)).each(function() {
                                var s = toRelative($(this).attr("src"));
                                /http(s)?:\/\//.test(s) || (s = Wf.String.path(site, s)), 
                                $(this).attr("src", s);
                            }), $("a, area", $(tmpDiv)).each(function() {
                                var s = toRelative($(this).attr("href"));
                                /http(s)?:\/\//.test(s) || (s = Wf.String.path(site, s)), 
                                $(this).attr("href", s);
                            }), $("object", $(tmpDiv)).each(function() {
                                $("param[name=movie], param[name=src]", this).each(function() {
                                    var s = toRelative($(this).attr("value"));
                                    /http(s)?:\/\//.test(s) || (s = Wf.String.path(site, s)), 
                                    $(this).attr("value", s);
                                });
                            }), iframe.contentWindow.document.body.innerHTML = tmpDiv.innerHTML;
                        }
                    }));
                    break;

                  case "upload":
                    var uploadModal = Wf.Modal.upload($.extend({
                        elements: elements,
                        open: function() {
                            $("#upload-queue").uploader($.extend({
                                url: document.location.href,
                                field: $('input[type="file"]:first'),
                                websafe_mode: self.options.websafe_mode,
                                websafe_spaces: self.options.websafe_spaces,
                                websafe_textcase: self.options.websafe_textcase
                            }, self.options.upload)).on("uploadwidget:filerename", function(e, file) {
                                return function(file) {
                                    var found = !1, msg = self._translate("file_exists_alert", "A file with the same name exists in the target folder."), name = Wf.String.safe(file.name, self.options.websafe_mode, self.options.websafe_spaces, self.options.websafe_textcase), file = ($("li", "file-list").each(function() {
                                        name == $(this).attr("title") && (found = !0);
                                    }), file.element), span = $("span.queue-name:first", file);
                                    return found ? $(file).hasClass("exists") || ($(file).addClass("exists"), 
                                    $(span).attr("title", name + "::" + msg), $(span).tips()) : $(file).hasClass("exists") && ($(file).removeClass("exists"), 
                                    $(span).attr("title", name)), !0;
                                }(file);
                            }).on("uploadwidget:filecomplete", function(e, file, item) {
                                self._addReturnedItem(item), self._trigger("onUploadFile", null, file);
                            }).on("uploadwidget:uploadstart", function(e, file) {
                                file.data = $(":input[name]:enabled", file.element).map(function() {
                                    return {
                                        name: this.name,
                                        value: this.value
                                    };
                                }), $(":input[name]:enabled", file.element).prop("disabled", !0);
                            }).on("uploadwidget:uploadcomplete", function(e, errors) {
                                $("#upload-submit").disabled = !1, errors || (self._getList(), 
                                window.setTimeout(function() {
                                    $(uploadModal).trigger("modal.close");
                                }, 1e3), self._trigger("onUploadComplete"));
                            }), self._trigger("onUploadOpen");
                        },
                        upload: function() {
                            var serialized = $(":input[name]:enabled", "#upload-body").map(function() {
                                return {
                                    name: this.name,
                                    value: this.value
                                };
                            }), serialized = $.merge($("form > :input:enabled").serializeArray(), serialized);
                            return serialized.push({
                                name: "upload-dir",
                                value: dir
                            }), self._trigger("onUpload", null, [ serialized ]), 
                            $("#upload-queue").trigger("uploadwidget:upload", [ serialized ]), 
                            !1;
                        },
                        close: function() {
                            $("#upload-queue").trigger("uploadwidget:close");
                        }
                    }, self.options.upload.dialog));
                    break;

                  case "folder_new":
                    Wf.Modal.prompt(self._translate("folder_new", "New Folder"), function(v, args) {
                        v && (self._setLoader(), v = Wf.String.safe(v, self.options.websafe_mode, self.options.websafe_spaces, self.options.websafe_textcase), 
                        args = [ dir, v ].concat(args || []), Wf.JSON.request("folderNew", args, function(o) {
                            o && (self._isRoot() && $("#tree-body").trigger("tree:createnode", [ o.folders, self._dir ]), 
                            self._trigger("onFolderNew")), self.refresh();
                        }));
                    }, {
                        elements: elements,
                        label: {
                            confirm: self._translate("create", "Create")
                        },
                        validate: function(value) {
                            return !!value && Wf.String.safe(value, self.options.websafe_mode, self.options.websafe_spaces, self.options.websafe_textcase);
                        }
                    });
                    break;

                  case "copy":
                  case "cut":
                    if ("copy" === name && (evt.metaKey || evt.ctrlKey)) {
                        var items = this.getSelectedItems(), clip = [];
                        if ($.each(items, function() {
                            if (!$(this).hasClass("file")) return !0;
                            var url = $(this).data("url");
                            -1 === url.indexOf("://") && (url = Wf.String.path(site, url), 
                            url = Wf.URL.toAbsolute(url)), url && clip.push(url);
                        }), clip.length) {
                            $item = document.createElement("input"), url = clip.join(",");
                            if ($($item).css({
                                position: "absolute",
                                left: -9999
                            }).attr("readonly", !0).appendTo("body").val(url).focus(), 
                            $item.select) {
                                $item.select();
                                try {
                                    document.execCommand("copy");
                                } catch (err) {}
                            }
                            $($item).remove();
                        }
                        evt.preventDefault();
                    } else this._pasteaction = name, this._pasteitems = list, this._showPasteButton();
                    break;

                  case "paste":
                    var fn = "copy" == this._pasteaction ? "copyItem" : "moveItem", items = (this._setLoader(), 
                    this._pasteitems.split(","));
                    function callback(o, dir) {
                        o.folders.length && self._treeLoaded() && ($.each(items, function(i, item) {
                            "moveItem" == fn && $("#tree-body").trigger("tree:removenode", [ item ]);
                        }), o = $.map(o.folders, function(item, i) {
                            item = item.name;
                            return {
                                id: item,
                                name: Wf.String.basename(item)
                            };
                        }), $("#tree-body").trigger("tree:createnode", [ o, dir ]));
                    }
                    $.each(items, function(i, item) {
                        var complete = i === items.length - 1;
                        Wf.JSON.request(fn, [ item, dir ], function(o) {
                            var confirmCallback;
                            o ? o.confirm ? (confirmCallback = function(state) {
                                Wf.JSON.request(fn, [ item, dir, state ], function(o) {
                                    o && !o.error && callback(o, dir);
                                });
                            }, Wf.Modal.confirm(self._translate("paste_item_confirm", "An item with the same name already exists in this folder. Do you want to replace it with the one you\u2019re pasting?"), confirmCallback, {
                                header: !1,
                                close: function() {
                                    complete && (self._clearPaste(), self.refresh());
                                },
                                buttons: [ {
                                    text: self._translate("cancel", "Cancel"),
                                    icon: "uk-icon-close",
                                    attributes: {
                                        class: "uk-modal-close"
                                    }
                                }, {
                                    text: self._translate("paste_keep_both", "Keep Both"),
                                    icon: "uk-icon-copy",
                                    click: function(e) {
                                        confirmCallback.call(this, "copy");
                                    },
                                    attributes: {
                                        type: "submit",
                                        class: "uk-button-success uk-modal-close"
                                    }
                                }, {
                                    text: self._translate("paste_replace", "Replace"),
                                    icon: "uk-icon-check",
                                    click: function(e) {
                                        confirmCallback.call(this, "replace");
                                    },
                                    attributes: {
                                        type: "submit",
                                        class: "uk-button-primary uk-modal-close",
                                        autofocus: !0
                                    }
                                } ]
                            })) : (callback(o, dir), complete && (self._clearPaste(), 
                            self.refresh()), o = (o.folders.length ? o.folders : o.files)[0].name, 
                            self._trigger("onPaste", [ fn, item, o ])) : complete && (self._clearPaste(), 
                            self.refresh());
                        }, self, !0);
                    });
                    break;

                  case "delete":
                    url = self._translate("delete_item_alert", "Delete Selected Item(s)");
                    Wf.Modal.confirm(url, function(state) {
                        state && (self._setLoader(), Wf.JSON.request("deleteItem", list, function(o) {
                            o && (o.folders.length && (self._treeLoaded() && $.each(o.folders, function(i, item) {
                                $("#tree-body").trigger("tree:removenode", [ item ]);
                            }), self._trigger("onFolderDelete", null, o.folders)), 
                            o.files.length) && self._trigger("onFileDelete", null, o.files), 
                            self.refresh();
                        }));
                    }, {
                        label: {
                            confirm: self._translate("delete", "Delete"),
                            cancel: self._translate("cancel", "Cancel")
                        },
                        header: !1
                    });
                    break;

                  case "rename":
                    var ext, $item = this.getSelectedItems(0), v = Wf.String.basename(list), renameModal = ($($item).hasClass("file") && (ext = Wf.String.getExt(v), 
                    v = Wf.String.filename(v)), Wf.Modal.prompt("Rename", function(name, args) {
                        if (name = Wf.String.safe(name, self.options.websafe_mode, self.options.websafe_spaces, self.options.websafe_textcase), 
                        v === name) return Wf.Modal.alert(self._translate("rename_item_name_new", "Please specify a new name for the item")), 
                        !1;
                        Wf.Modal.confirm(self._translate("rename_item_alert", "Renaming files/folders will break existing links. Continue?"), function(state) {
                            state && (self._setLoader(), args = [ list, name ].concat(args || []), 
                            Wf.JSON.request("renameItem", args, function(o) {
                                var item;
                                o && (self._reset(), item = Wf.String.path(self._dir, name), 
                                o.folders.length && (self._treeLoaded() && $("#tree-body").trigger("tree:renamenode", [ list, item ]), 
                                self._trigger("onFolderRename", [ list, item ])), 
                                ext && (item = item + "." + ext), o.files.length && self._trigger("onFileRename", [ list, item ]), 
                                item) && self._addReturnedItem({
                                    name: item
                                }), self.refresh();
                            })), $(renameModal).trigger("modal.close");
                        });
                    }, {
                        value: v,
                        header: !1,
                        label: {
                            confirm: self._translate("rename", "Rename")
                        },
                        elements: elements,
                        close_on_submit: !1,
                        validate: function(value) {
                            return !!value && Wf.String.safe(value, self.options.websafe_mode, self.options.websafe_spaces, self.options.websafe_textcase);
                        }
                    }));
                    break;

                  case "custom":
                    var url = options.dialog, action = options.action || null;
                    Wf.Modal.custom(url.title, function(args) {
                        args = [ list ].concat(args || []), Wf.JSON.request(action, args, function(o) {
                            self.refresh();
                        });
                    }, {
                        elements: url.elements
                    });
                }
            },
            _raiseError: function(error) {
                var self = this, err = "";
                "array" === $.type(error) ? (err += '<ul class="error-list">', $.each(error, function(k, v) {
                    err += "<li>" + v + "</li>";
                }), err += "</ul>") : err = error, this._dialog.alert = Wf.Modal.alert(err, {
                    close: function() {
                        self.refresh();
                    }
                });
            },
            _addActions: function(actions) {
                var self = this;
                $.each(actions, function(i, action) {
                    self._addAction(action);
                });
            },
            _addAction: function(o) {
                var icon, self = this, name = o.name || "", fn = this._execute, cls = (o.action && (fn = o.action), 
                name.replace(/_/g, "-")), action = document.createElement("button");
                $(action).addClass("action uk-button"), name && ($(action).attr({
                    id: name,
                    title: o.title,
                    "aria-label": o.title
                }).addClass(cls).append('<label id="' + name + '_label" class="uk-text uk-hidden-mini">&nbsp;' + o.title + "</label>"), 
                $.each((icon = {
                    folder_new: "folder-plus",
                    upload: "cloud-upload",
                    help: "question-circle"
                }[name] || name).split(" "), function(i, k) {
                    $(action).prepend('<i class="uk-icon uk-icon-small uk-icon-' + cls + " uk-icon-" + k + '"></i>');
                }), 0 <= icon.indexOf(" ") && ($(".uk-icon", action).first().addClass("uk-icon-stack uk-text-contrast").removeClass("uk-icon-medium"), 
                $('<span class="uk-stack uk-stack-medium"></span>').prependTo(action).append($(".uk-icon", action))), 
                o.name && $(action).on("mousedown.action", function(e) {
                    return e.preventDefault(), e.stopImmediatePropagation(), "function" == $.type(fn) ? fn.call(self, name) : self._trigger(fn, name);
                }), this._actions[name] = action), $("#browser-actions").append(action);
            },
            _getAction: function(name) {
                return this._actions[name];
            },
            _addButtons: function(buttons) {
                var self = this;
                buttons && (buttons.folder && $.each(buttons.folder, function(i, button) {
                    button && self._addButton(button, "folder");
                }), buttons.file) && $.each(buttons.file, function(i, button) {
                    button && self._addButton(button, "file");
                });
            },
            _addButton: function(o, type) {
                var name, icons, self = this, fn = this._execute, map = (o.action && (fn = o.action), 
                {
                    delete: "trash",
                    cut: "cut",
                    copy: "copy",
                    paste: "paste",
                    rename: "edit",
                    preview: "preview",
                    view: "preview",
                    "image-editor": "crop",
                    "text-editor": "file-xml"
                }), button = $("button." + o.name, $("#browser-buttons"));
                button.length || (button = document.createElement("button"), $(button).attr({
                    title: o.title,
                    "aria-label": o.title
                }), name = o.name.replace(/_/g, "-"), o.icon ? (icons = o.icon.split(" "), 
                $.each(icons, function(i, icon) {
                    $(button).append('<i class="uk-icon uk-icon-' + (map[icon] || icon) + '"></i>');
                }), 1 < icons.length && $('<span class="uk-stack"></span>').append($(".uk-icon", button)).appendTo(button)) : $(button).prepend('<i class="uk-icon uk-icon-' + (map[name] || name) + '"></i>'), 
                name && $(button).on("mousedown.button", function(evt) {
                    if (evt.preventDefault(), evt.stopPropagation(), $("li.selected", "#item-list").length || self._pasteitems) return o.sticky && $(button).toggleClass("uk-active"), 
                    o.dialog ? self._execute("custom", type, evt, o) : "function" == $.type(fn) ? fn.call(self, name, type, evt) : self._trigger(fn, type);
                }), $("#browser-buttons").append(button), $(button).addClass("uk-button uk-button-link button " + o.name + " uk-hidden")), 
                this._buttons[type][o.name] = {
                    name: o.name,
                    element: button,
                    trigger: o.trigger,
                    multiple: o.multiple,
                    single: "undefined" === $.type(o.single) || o.single,
                    restrict: o.restrict || "",
                    sticky: o.sticky
                };
            },
            _hideAllButtons: function() {
                var self = this;
                $(".button", "#browser-buttons").each(function() {
                    self._hideButton(this);
                });
            },
            _hideButtons: function(buttons) {
                var self = this;
                $.each(buttons, function(i, button) {
                    self._hideButton(button);
                });
            },
            _hideButton: function(button) {
                $(button).addClass("uk-hidden").attr("aria-hidden", !0);
            },
            _showButtons: function() {
                var buttons, filebtns, folderbtns, self = this, folder = (this._hideAllButtons(), 
                $("li.folder.selected", "#item-list")), file = $("li.file.selected", "#item-list");
                file.length && folder.length ? (buttons = {}, filebtns = this._buttons.file, 
                folderbtns = this._buttons.folder, $.each(filebtns, function(k, o) {
                    !o.trigger && o.multiple && folderbtns[k] && (buttons[k] = o);
                }), $.each(folderbtns, function(k, o) {
                    !o.trigger && o.multiple && filebtns[k] && (buttons[k] = o);
                }), $.each(buttons, function(k, o) {
                    self._showButton(o.element, o.single, !0);
                })) : (folder = file.length ? "file" : "folder", $.each(this._buttons[folder], function(k, o) {
                    var re, item;
                    o.trigger || o.restrict || self._showButton(o.element, o.single, o.multiple), 
                    o.restrict && (re = o.restrict.split(",").join("|"), item = self.getSelectedItems(0), 
                    new RegExp("\\.(" + re + ")$", "i").test($(item).attr("title"))) && self._showButton(o.element, o.single, o.multiple);
                })), this._pasteitems && this._showPasteButton();
            },
            _showButton: function(button, single, multiple) {
                var show;
                button && (show = !1, 1 < $("li.selected", "#item-list").length ? multiple && (show = !0) : single && (show = !0), 
                show ? $(button).removeClass("uk-hidden").removeAttr("aria-hidden") : $(button).addClass("uk-hidden").attr("aria-hidden", !1));
            },
            _getButton: function(type, name) {
                return this._buttons[type][name] || null;
            },
            _showPasteButton: function() {
                this._showButton($(".button.paste", "#browser-buttons"), !0, !0);
            },
            _isSelectedItem: function(el) {
                return $(el).is("li.selected");
            },
            _deselectItems: function() {
                $("li.selected", "#item-list").removeClass("selected active").find('input[type="checkbox"]').prop("checked", !1), 
                $("#browser-details-text, #browser-details-comment").empty(), $.each([ "#browser-details-nav-left", "#browser-details-nav-right", "#browser-details-nav-text" ], function(i, el) {
                    $(el).addClass("uk-invisible").attr("aria-hidden", !0);
                }), this._hideAllButtons(), $('input[type="checkbox"]', "#check-all").prop("checked", !1);
            },
            _selectItems: function(items, show) {
                $(items).addClass("selected").find('input[type="checkbox"]').prop("checked", !0), 
                show && this._showSelectedItems();
                show = $("#item-list");
                $("input:checked", show).length === $("li", show).length && $('input[type="checkbox"]', "#check-all").prop("checked", !0), 
                this._trigger("onSelectItems", null, items);
            },
            _removeSelectedItems: function(items, show) {
                $(items).removeClass("selected active").find('input[type="checkbox"]').prop("checked", !1), 
                show && this._showSelectedItems(), this._trigger("onRemoveItems", null, items);
            },
            getSelectedItems: function(key) {
                var $items = $("li.selected", "#item-list");
                return "number" == typeof key && $items[key] || $items;
            },
            setSelectedItems: function(items) {
                this._findItem(items);
            },
            _setSelectedItems: function(e, multiple) {
                var checkbox = !1, el = e.target, $list = $("#item-list");
                if ("keydown" === e.type) {
                    if (el = $("li.selected:last", $list).get(0), $list = $("#browser-list"), 
                    38 == e.which && (el = el.previousSibling), !(el = 40 == e.which ? el.nextSibling : el)) return;
                    (el.offsetTop > $list.innerHeight() || el.offsetTop < $list.scrollTop()) && $list.scrollTop(el.offsetTop + $(el).innerHeight() - $list.height());
                }
                $(el).is('input[type="checkbox"]') && (checkbox = multiple = !0, 
                el = $(el).parents("li").get(0)), "LI" != el.nodeName && (el = el.parentNode);
                var selected = $("li.selected", $list);
                if (this._isSelectedItem(el) && 1 === selected.length) return e.preventDefault(), 
                !1;
                var items = $("li.folder, li.file", $list), $list = e.ctrlKey || e.metaKey, e = e.shiftKey;
                if (($list || e || checkbox) && multiple) {
                    if (multiple && ($list || e || checkbox) && (($list || checkbox) && (this._isSelectedItem(el) ? this._removeSelectedItems([ el ], !0) : this._selectItems([ el ], !0)), 
                    e)) if (selected.length) {
                        var si = $(selected).index(), ci = $(el, items).index(), selection = [];
                        if (this._deselectItems(), si < ci) for (var i = ci; si <= i; i--) selection.push(items[i]); else for (i = si; ci <= i; i--) selection.push(items[i]);
                        this._selectItems(selection, !0);
                    } else this._selectItems([ el ], !0);
                } else $(el).find('input[type="checkbox"]').prop("checked", !1), 
                this._deselectItems(), this._selectItems([ el ], !0);
            },
            _showSelectedItems: function() {
                var $items = $("li.selected", "#item-list");
                $items.length ? ($items.first().addClass("active"), this._showItemDetails()) : this._reset();
            },
            _findItem: function(files, type) {
                var self = this, items = [], insert = (type = type || "file", "string" == $.type(files) && (files = [ files ]), 
                !1), $list = $("#item-list"), base = self.getBaseDir();
                $.each(files, function(i, file) {
                    var name, item;
                    file && file.name && (name = decodeURIComponent(file.name), 
                    $list.length) && (item = [], (item = $("li." + type + '[title="' + Wf.String.basename(name) + '"], li.' + type + '[data-url="' + Wf.String.path(base, name) + '"]', $list)).length) && (file.insert && (insert = !0, 
                    items = item, self.serializeItemData(item).then(function(data) {
                        self._trigger("onFileClick", [ item, data ]);
                    })), insert || $.merge(items, item));
                }), items.length && (files = $(items).first().outerHeight() + $(".folder-up").outerHeight(), 
                files = $(items).get(0).offsetTop - files, $("#browser-list").animate({
                    scrollTop: Math.round(files)
                }, 1500, function() {
                    $(this).off(scrollEvents);
                })), this._selectItems(items, !0);
            },
            serializeItemData: function(item) {
                var self = this;
                return new Promise(function(resolve, reject) {
                    var path, props = {};
                    $.each([ "url", "preview", "width", "height", "description", "modified", "size" ], function(i, key) {
                        props[key] = $(item).attr("data-" + key) || "";
                    }), props.title = $(item).attr("title"), props.title = Wf.String.basename(props.title), 
                    props.url ? resolve(props) : (path = Wf.String.path(self._dir, props.title), 
                    Wf.JSON.request("getFileDetails", [ path ], function(o) {
                        o && !o.error && (props = $.extend(props, o)), resolve(props);
                    }));
                });
            },
            _serializeSelectedItems: function() {
                var self = this;
                return $("li.selected", "#item-list").map(function() {
                    return Wf.String.path(self._dir, $(this).attr("title"));
                }).get().join(",");
            },
            _showItemDetails: function() {
                var index, self = this, $items = $("li.selected", "#item-list"), n = $items.length, $nav = $("#browser-details-nav");
                1 < n ? ((index = $items.index($items.filter(".active"))) ? $(".details-nav-left", $nav).removeClass("uk-invisible").attr("aria-hidden", !1) : $(".details-nav-left", $nav).addClass("uk-invisible").attr("aria-hidden", !0), 
                index + 1 < n ? $(".details-nav-right", $nav).removeClass("uk-invisible").attr("aria-hidden", !1) : $(".details-nav-right", $nav).addClass("uk-invisible").attr("aria-hidden", !0), 
                $(".details-nav-text", $nav).removeClass("uk-invisible").html(function() {
                    return self._translate("one_of_many", "%o of %m").replace("%o", index + 1).replace("%m", n);
                })) : $("li", $nav).addClass("uk-invisible").attr("aria-hidden", !0), 
                this._showButtons(), this._getItemDetails();
            },
            _getDimensions: function(file) {
                var src, img = new Image();
                $(file).data("preview") && (src = $(file).data("preview"), $(file).addClass("loading disabled").children("span.checkbox").addClass("disabled"), 
                img.onload = function() {
                    $(file).attr({
                        "data-preview": src,
                        "data-width": img.width,
                        "data-height": img.height
                    }), $(file).removeClass("loading disabled").children("span.checkbox").removeClass("disabled");
                }, img.onerror = function() {
                    $(file).removeClass("loading disabled").children("span.checkbox").removeClass("disabled");
                }, img.src = src);
            },
            _getMediaProps: function(file) {
                return new Promise(function(resolve, reject) {
                    if (!file.type) return reject();
                    var audio, video, timer, props, image, src;
                    "video" === file.type && /\.(mp4|m4v|ogg|ogv|webm)$/i.test(file.preview) && $.support.video ? (props = {}, 
                    (video = document.createElement("video")).onloadedmetadata = function() {
                        props = {
                            duration: parseInt(video.duration / 60, 10) + ":" + parseInt(video.duration % 60, 10),
                            width: video.videoWidth,
                            height: video.videoHeight
                        }, video = null, resolve(props);
                    }, video.src = file.preview) : "audio" === file.type && /\.(mp3|oga|ogg)$/i.test(file.preview) && $.support.audio ? (props = {}, 
                    (audio = document.createElement("audio")).onloadedmetadata = function() {
                        props.duration = parseInt(audio.duration / 60, 10) + ":" + parseInt(audio.duration % 60, 10), 
                        audio = null, resolve(props);
                    }, audio.src = file.preview) : "video" === file.type && /\.(wmv|avi|mov)$/i.test(file.preview) && $.support.video ? (props = {}, 
                    video = document.createElement("video"), document.body.appendChild(video), 
                    video.style.position = "absolute", video.style.left = "-10000px", 
                    timer = setTimeout(function() {
                        video && video.clientWidth && (props.duration = "", props.width = video.clientWidth, 
                        props.height = video.clientHeight, clearTimeout(timer), 
                        document.body.removeChild(video), video = null, resolve(props));
                    }, 100), video.src = file.preview) : "image" === file.type ? (props = {}, 
                    (image = new Image()).onload = function() {
                        props.width = image.width, props.height = image.height, 
                        resolve(props);
                    }, src = Wf.String.encodeURI(file.preview) + "?" + new Date().getTime(), 
                    !/:\/\//.test(file.preview) && -1 === file.preview.indexOf("?") || (src = file.preview), 
                    image.src = src) : reject();
                });
            },
            _getItemDetails: function() {
                var mime, self = this, item = $("li.selected.active", "#item-list"), title = Wf.String.basename($(item).attr("title")), type = $(item).hasClass("folder") ? "folder" : "file", path = ($("#browser-details-text").empty().addClass("loading"), 
                Wf.String.path(this._dir, Wf.String.encodeURI(title))), name = title, ext = "", info = ($(self.element).next("span.loader").remove(), 
                "file" == type && (name = Wf.String.stripExt(title), ext = Wf.String.getExt(title)), 
                document.createElement("div")), title = ($(info).addClass("uk-comment uk-height-1-1").append('<div class="uk-comment-header"><h5 class="uk-width-1-1 uk-margin-remove uk-text-bold uk-text-truncate" title="' + name + '">' + name + '</h5><div class="uk-comment-meta">' + ext + " " + self._translate(type, Wf.String.ucfirst(type)) + '</div><div class="uk-comment-meta" id="info-properties"><div></div>'), 
                $(info).append('<div class="uk-comment-body uk-width-1-1 uk-text-center" id="info-preview"></div>'), 
                $("#browser-details-text").removeClass("loading").empty().append(info), 
                "");
                $(item).hasClass("notwritable") && (title += '<li class="comments ' + type + ' notwritable"><span class="hastip" title="' + self._translate("notwritable_desc", "Unwritable") + '">' + self._translate("notwritable", "Unwritable") + "</span></li>"), 
                $(item).data("trigger") && $.each($(item).data("trigger").split(","), function(i, v) {
                    "" !== v && (v = self._getButton(type, v)) && self._showButton(v.element, v.single, v.multiple);
                }), $(item).data("size") && $(".uk-comment-header", info).append('<div class="uk-comment-meta" id="info-size">' + tinyMCEPopup.getLang("dlg.size", "Size") + ": " + Wf.String.formatSize($(item).data("size")) + "</div>"), 
                $(item).data("modified") && $(".uk-comment-header", info).append('<div class="uk-comment-meta" id="info-modified">' + tinyMCEPopup.getLang("dlg.modified", "Modified") + ": " + Wf.String.formatDate($(item).data("modified"), self.options.date_format) + "</div>"), 
                $(item).data("permissions") && $(".uk-comment-header", info).append('<div class="uk-comment-meta" id="info-permissions">' + tinyMCEPopup.getLang("dlg.permissions", "Permissions") + ": " + $(item).data("permissions") + "</div>"), 
                title && $("#browser-details-comment").empty().append("<ul>" + title + "</ul>"), 
                $("span.hastip", $("#browser-details-comment")).tips(), "folder" == type ? self._trigger("onFolderDetails", null, item) : self.serializeItemData(item).then(function(data) {
                    function callback(data) {
                        data.width && data.height && ($(".uk-comment-header", info).append('<div class="uk-comment-meta" id="info-dimensions">' + self._translate("dimensions", "Dimensions") + ": " + data.width + " x " + data.height + "</div>"), 
                        mime) && "image" === mime && $("#info-preview").empty().append('<img src="' + data.preview + '" alt="" />').removeClass("loading"), 
                        data.duration && $(".uk-comment-header", info).append('<div class="uk-comment-meta" id="info-duration">' + tinyMCEPopup.getLang("dlg.duration", "Duration") + ": " + data.duration + "</div>"), 
                        self._trigger("onFileDetails", [ item, data ]);
                    }
                    if ($.each(data, function(key, value) {
                        $(item).data(key, value);
                    }), (mime = getMimeType(ext)) && /^(image|video|audio)$/.test(mime)) return "image" === mime && data.width && data.height || "video" === mime && data.width && data.height && data.duration || "audio" === mime && data.duration ? callback(data) : void self._getMediaProps({
                        preview: data.preview,
                        type: mime
                    }).then(function(o) {
                        $.each(o, function(key, value) {
                            data[key] = value, $(item).data(data);
                        }), callback(data);
                    }, function() {
                        Wf.JSON.request("getDimensions", [ path ], function(o) {
                            o && !o.error && $.each(o, function(key, value) {
                                data[key] = value, $(item).data(data);
                            }), callback(data);
                        });
                    });
                });
            }
        }, $.fn.filebrowser = function(options) {
            $(this).addClass("filebrowser");
            var instance = new FileBrowser(this, options);
            return $(this).on("filebrowser:insert", function(e, cb) {
                var selected = instance.getSelectedItems(), promises = [];
                $(selected).each(function() {
                    promises.push(instance.serializeItemData(this));
                }), Promise.all(promises).then(function(props) {
                    return "function" == typeof cb ? cb(selected, props) : props;
                });
            }), $(this).on("filebrowser:status", function(e, status) {
                instance.setStatus(status);
            }), $(this).on("filebrowser:load", function(e, url) {
                return instance.load(url);
            }), $(this).on("filebrowser:refresh", function() {
                return instance.refresh();
            }), $(this).on("filebrowser:sort", function() {
                return instance._showItemDetails();
            }), $.fn.filebrowser.getbasedir = function() {
                return instance.getBaseDir();
            }, $.fn.filebrowser.getcurrentdir = function() {
                return instance.getCurrentDir();
            }, $.fn.filebrowser.getselected = function() {
                return instance.getSelectedItems();
            }, $.fn.filebrowser.status = function(status) {
                return instance.setStatus(status);
            }, $.fn.filebrowser.load = function(url) {
                return instance.load(url);
            }, this;
        }, window.FileBrowser = FileBrowser;
    }(jQuery, Wf);
}();