UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

1,586 lines (1,580 loc) 75.8 kB
//#region ../src/filemanager/commands.js (function($, undefined) { var kendo = window.kendo, extend = $.extend, deferred = $.Deferred, Class = kendo.Class; var Command = Class.extend({ init: function(options) { this.options = options; this.filemanager = options.filemanager; } }); var CreateFolderCommand = Command.extend({ init: function(options) { Command.fn.init.call(this, options); }, _renameNewFolder: function(uid) { let that = this, fileManager = that.filemanager || that, widgetComponent = fileManager.view().widgetComponent, uidAttribute = kendo.attr("uid"), folderElement = widgetComponent.items().filter(function(idx, element) { return $(element).attr(uidAttribute) == uid; }).first(); if (folderElement.length > 0) { widgetComponent.select(folderElement[0]); fileManager.executeCommand({ command: "RenameCommand", options: { target: $(folderElement), item: fileManager.getSelected()[0] } }); } }, exec: function() { var that = this, filemanager = that.filemanager, commandStack = filemanager._commandStack, dataSource = filemanager._viewDataSource || filemanager.dataSource, removeProxy = that._remove.bind(that); that._item = dataSource._createNewModel(); that._item._fromCreateFolderCommand = true; let sanitizedItem = that._item.toJSON(); let command = { item: sanitizedItem, renameFolderProxy: that._renameNewFolder }; commandStack.push(command).fail(removeProxy); dataSource.add(that._item); }, _remove: function() { var that = this, filemanager = that.filemanager, dataSource = filemanager._viewDataSource || filemanager.dataSource; dataSource.pushDestroy(that._item); } }); var RenameCommand = Command.extend({ init: function(options) { Command.fn.init.call(this, options); }, exec: function() { var that = this, target = that.options.target, filemanager = that.filemanager, commandStack = filemanager._commandStack, viewItem = filemanager._view.widgetComponent.dataItem(target); if (target && viewItem) { commandStack.push({ target, item: viewItem }); that.filemanager._view.edit(target); } else { that._renameTreeViewItem(target); } }, _renameTreeViewItem: function(target) { var that = this, filemanager = that.filemanager, commandStack = filemanager._commandStack, uid = target.data("uid"), item = that.filemanager.treeView.widgetComponent.dataSource.getByUid(uid), realItem = that.filemanager.dataSource.get(item.id); that.filemanager._prompt({ type: "rename", defaultInput: realItem.name, target }).done(function(newName) { commandStack.push({ target, item: realItem }); realItem.set("name", newName); }); } }); var DeleteCommand = Command.extend({ init: function(options) { Command.fn.init.call(this, options); }, exec: function() { var that = this, target = that.options.target, filemanager = that.filemanager, items = filemanager.getSelected(), viewItem = that.filemanager._view.widgetComponent.dataItem(target), itemsToRemove; if (target && target.is(".k-selected") && items && items.length) { itemsToRemove = items; } else if (target && viewItem) { itemsToRemove = viewItem; } else if (target) { var uid = target.data("uid"); var item = that.filemanager.treeView.widgetComponent.dataSource.getByUid(uid); var realItem = that.filemanager.dataSource.get(item.id); itemsToRemove = realItem; } filemanager._confirm({ type: "delete", target }).done(function() { that.removeItems(itemsToRemove); }); }, removeItems: function(items) { var that = this; that._itemsToRemove = Array.isArray(items) ? items : [items]; that._removeItem(); }, _removeItem: function() { var that = this, filemanager = that.filemanager, commandStack = filemanager._commandStack, dataSource = filemanager.dataSource, itemToRemove = !!that._itemsToRemove.length && that._itemsToRemove.splice(0, 1)[0]; if (itemToRemove) { commandStack.push({ item: itemToRemove }).then(that._removeItem.bind(that), that._removeItem.bind(that)); dataSource.remove(itemToRemove); } } }); var CopyCommand = Command.extend({ init: function(options) { Command.fn.init.call(this, options); }, exec: function() { var that = this, filemanager = that.filemanager, dataSource = filemanager.dataSource, commandStack = filemanager._commandStack, items = that.options.items, target = dataSource.get(that.options.target), targetDataSource = target.children; for (var i = 0; i < items.length; i++) { var item = dataSource.get(items[i]).toJSON(); item.fileManagerNewItem = true; commandStack.push({ item, target }); targetDataSource.add(item); } } }); var MoveCommand = Command.extend({ init: function(options) { var that = this; Command.fn.init.call(that, options); that._itemsToRemove = []; }, exec: function() { var that = this, filemanager = that.filemanager, commandStack = filemanager._commandStack, dataSource = filemanager.dataSource, items = that.options.items, target = dataSource.get(that.options.target), targetDataSource = target.children, promises = []; for (var i = 0; i < items.length; i++) { var item = dataSource.get(items[i]); var cloning = item.toJSON(); cloning.fileManagerNewItem = true; var promise = commandStack.push({ item, target }).then(that._delete.bind(that)); promises.push(promise); targetDataSource.add(cloning); } kendo.whenAll(promises).always(that._removeItem.bind(that)); }, _delete: function(data) { var that = this; that._itemsToRemove.push(data.item); }, _removeItem: function() { var that = this, filemanager = that.filemanager, commandStack = filemanager._commandStack, dataSource = filemanager.dataSource, itemToRemove = !!that._itemsToRemove.length && that._itemsToRemove.splice(0, 1)[0]; if (itemToRemove) { commandStack.push({ item: itemToRemove }).then(that._removeItem.bind(that), that._removeItem.bind(that)); dataSource.remove(itemToRemove); } } }); var SortCommand = Command.extend({ init: function(options) { Command.fn.init.call(this, options); }, exec: function() { var that = this, options = that.options, filemanager = that.filemanager, sortOptions = filemanager.defaultSortOption; extend(sortOptions, { dir: options.dir, field: options.field }); filemanager._view.widgetComponent.dataSource.sort([filemanager.folderSortOption, sortOptions]); } }); var SearchCommand = Command.extend({ init: function(options) { Command.fn.init.call(this, options); }, exec: function() { var that = this, options = that.options, filemanager = that.filemanager, filter = { field: options.field, operator: options.operator, value: options.value || "" }; filemanager._view.widgetComponent.dataSource.filter(filter); } }); var ChangeViewCommand = Command.extend({ init: function(options) { Command.fn.init.call(this, options); }, exec: function() { var that = this, options = that.options, filemanager = that.filemanager; filemanager.view(options.value); filemanager.resize(true); } }); var OpenDialogCommand = Command.extend({ init: function(options) { Command.fn.init.call(this, options); }, exec: function() { var that = this, filemanager = that.filemanager, dialog = filemanager[that.options.type]; if (dialog) { dialog.open(); } else { window.console.warn(kendo.format("The {0} dialog is not available!", that.options.type)); } } }); var TogglePaneCommand = Command.extend({ init: function(options) { Command.fn.init.call(this, options); }, exec: function() { var that = this, filemanager = that.filemanager, pane = filemanager[that.options.type], resizable = that.getResizable(); if (pane) { pane.toggle(); if (resizable) { filemanager.wrapper.find(resizable.options.handle).toggle(); } } }, getResizable: function() { var that = this, filemanager = that.filemanager, type = that.options.type; if (!filemanager._resizeDraggable) { return; } return filemanager._resizeDraggable[type]; } }); var CommandStack = Class.extend({ init: function() { var that = this; that._stack = {}; that._keys = []; }, push: function(data) { var that = this, guid = kendo.guid(); that._keys.push(guid); that._stack[guid] = { guid, data, deferred: deferred() }; return that._stack[guid].deferred; }, next: function() { var that = this, key = that.keys().splice(0, 1), nextCommand = that._stack[key]; return nextCommand; }, resolve: function(command) { var that = this; delete that._stack[command.guid]; command.deferred.resolve(command.data); }, reject: function(command) { var that = this; delete that._stack[command.guid]; command.deferred.reject(command.data); }, keys: function() { return this._keys; }, empty: function() { return this.keys().length === 0; } }); extend(kendo.ui, { filemanager: { FileManagerCommand: Command, CommandStack, commands: { CreateFolderCommand, RenameCommand, DeleteCommand, MoveCommand, CopyCommand, SortCommand, SearchCommand, ChangeViewCommand, OpenDialogCommand, TogglePaneCommand } } }); })(window.kendo.jQuery); //#endregion //#region ../src/filemanager/view.js (function($, undefined) { var kendo = window.kendo, ui = kendo.ui, Observable = kendo.Observable, extend = $.extend, encode = kendo.htmlEncode, keys = kendo.keys, NAVIGATE = "navigate", SELECT = "select", EXPAND = "expand", CHANGE = "change", OPEN = "open", LOAD = "load", KEYDOWN = "keydown", KEYDOWNACTION = "keydownAction", NS = ".kendoFileManagerViewComponent", fileManagerDraggables = [], fileManagerDragOrigin = null; var registerViewComponent = function(componentName, component) { ui.filemanager.ViewComponents[componentName] = component; }; var getViewComponent = function(componentName) { return ui.filemanager.ViewComponents[componentName] || null; }; var Component = Observable.extend({ init: function(widget, element, options) { var that = this; that.element = element; that.options = options; if (widget) { that.widgetComponent = new widget(element, options); } else { throw new Error("The widget for the ViewComponent is not available! Please add the corresponding scripts!"); } Observable.fn.init.call(that); }, _bindEvents: function() { this.widgetComponent.bind("dataBinding", this._binding.bind(this)); this.widgetComponent.bind("dataBound", this._bound.bind(this)); }, _binding: function(ev) { if (this.trigger("dataBinding", ev)) { ev.preventDefault(); } }, _bound: function() { this.trigger("dataBound"); }, _setDSOptions: function(options, dataSourceOptions) { if (!options.dataSource && dataSourceOptions) { options.dataSource = dataSourceOptions; } }, _initDragAndDrop: function(element, filter) { var that = this; filter = filter || that.options.dropFilter; element = element || that.element; that.draggable = element.kendoDraggable({ filter, hint: that._hint.bind(that), cursorOffset: { top: -10, left: -50 }, holdToDrag: true, ignore: "input, .k-focusable", hold: that._hold.bind(that) }).data("kendoDraggable"); that.draggable.userEvents.minHold = 150; that.droptarget = element.kendoDropTargetArea({ filter, drop: that._onDrop.bind(that), dragenter: function(ev) { ev.dropTarget.addClass("k-filemanager-drop-target"); }, dragleave: function(ev) { ev.dropTarget.removeClass("k-filemanager-drop-target"); } }).data("kendoDraggable"); }, _hold: function(ev) { var that = this, target = ev.currentTarget; if (!target.is(".k-selected")) { if (that.widgetComponent.selectable) { that.widgetComponent.selectable.clear(); } that.widgetComponent.select(target); } if (that.widgetComponent.selectable) { that.widgetComponent.selectable.userEvents.cancel(); } }, _hint: function(target) { var that = this, item = that.widgetComponent.dataItem(target), selectedItems = that.widgetComponent.select(); fileManagerDragOrigin = that.widgetComponent; fileManagerDraggables = selectedItems; if (selectedItems.length > 1) { return `<div class='k-filemanager-drag-hint'>${kendo.ui.icon("file")} <span>${selectedItems.length} ${that.options.messages.items}</span></div>`; } return `<div class='k-filemanager-drag-hint'>${kendo.ui.icon(item.isDirectory ? "folder" : "file")} <span>${item.name}</span></div>`; }, _onDrop: function(ev) { var that = this, target = that.widgetComponent.dataItem(ev.dropTarget), targetId = target.id, itemIds = []; if (!target.isDirectory) { return; } for (var i = 0; i < fileManagerDraggables.length; i++) { var id = fileManagerDragOrigin.dataItem(fileManagerDraggables[i]).id; itemIds.push(id); } this.trigger("drop", { target: targetId, items: itemIds }); }, getSelected: function() { throw new Error("Not Implemented!"); }, refresh: function(dataSource) { this.widgetComponent.setDataSource(dataSource); }, destroy: function() { kendo.destroy(this.element); } }); extend(kendo.ui.filemanager, { ViewComponent: Component, ViewComponents: {}, registerViewComponent, getViewComponent }); var ListView = Component.extend({ init: function(element, options, explicitOptions) { var that = this, dataSourceOptions = explicitOptions.dataSource, messages = explicitOptions.messages; options = extend({}, that.defaultOptions, options, { messages, ariaLabel: explicitOptions.ariaLabel }); that._setDSOptions(options, dataSourceOptions); options.kendoKeydown = options.kendoKeydown || that._kendoKeydown.bind(that); Component.fn.init.call(this, ui.ListView, element, options); that.listView = that.widgetComponent; that._bindEvents(); if (explicitOptions.draggable !== false && !dataSourceOptions.isLocalBinding) { that._initDragAndDrop(); } }, defaultOptions: { layout: "flex", flex: { direction: "row", wrap: "wrap" }, selectable: kendo.support.mobileOS ? "row" : "multiple", template: ({ name, extension, isDirectory }) => `<div class='k-listview-item' title='${encode(name)}${encode(extension ?? "")}'>` + `<div class='k-file-preview'>${kendo.ui.icon({ icon: !isDirectory ? kendo.getFileGroup(extension, true) : "folder", iconClass: "k-file-icon", size: "xxxlarge" })}</div>` + `<div class='k-file-name file-name'>${encode(name)}${encode(extension ?? "")}</div>` + "</div>", editTemplate: ({ extension, isDirectory }) => "<div class='k-listview-item'>" + `<div class='k-file-preview'>${kendo.ui.icon({ icon: !isDirectory ? kendo.getFileGroup(extension, true) : "folder", iconClass: "k-file-icon", size: "xxxlarge" })}</div>` + "<div class='k-file-name'><span class='k-textbox k-input'><input type='text' class='k-input-inner' data-bind='value:name' name='name' required='required' /><span></div>" + "</div>", dropFilter: ".k-listview-item", navigatable: true }, _bindEvents: function() { var that = this, listView = that.listView; listView.bind(CHANGE, that._select.bind(that)); listView.element.on("dblclick" + NS, that._dblClick.bind(that)); listView.element.on("mousedown" + NS, ".k-listview-item:not(.k-edit-item)", that._mousedown.bind(that)); listView.element.on(KEYDOWN + NS, ".k-edit-item", that._keydown.bind(that)); listView.element.on(KEYDOWN + NS, that._keydownAction.bind(that)); listView.bind("edit", function(ev) { var sender = ev.sender; var input = ev.item.find("input"); input.on("blur", function() { var isDirty = sender._modelFromElement(sender.editable.element)?.dirty; sender._closeEditable(); if (!isDirty) { that.trigger("cancel"); } }); }); listView.bind("cancel", function() { that.trigger("cancel"); }); Component.fn._bindEvents.call(this); }, _select: function() { var that = this, dataItems = that.getSelected(); that.trigger(SELECT, { entries: dataItems }); }, _keydown: function(ev) { var that = this; if (ev.keyCode === kendo.keys.ESC) { that.listView._closeEditable(); that.trigger("cancel"); } }, _keydownAction: function(ev) { var that = this, target = $(ev.target).find(".k-focus"); if (target.length && !target.is(".k-edit-item")) { that.trigger(KEYDOWNACTION, { target, keyCode: ev.keyCode }); } }, _mousedown: function(ev) { var that = this, node = $(ev.target).closest(".k-listview-item"); if (ev.which === 3 && !node.is(".k-selected")) { that.listView.selectable.clear(); that.listView.select(node); } }, _kendoKeydown: function(ev) { var that = this; if (ev.keyCode === keys.ENTER && !ev.preventKendoKeydown) { that._handleEnterKey(ev); } }, _handleEnterKey: function(ev) { var that = this, target = $(ev.target), node = that.listView.current(); if (that.widgetComponent.editable && target.is("input")) { target.trigger("blur"); } else if (!that.widgetComponent.editable) { that._triggerOpen(node); } ev.preventKendoKeydown = true; }, _dblClick: function(ev) { var that = this, node = $(ev.target).closest(".k-listview-item"); that._triggerOpen(node); }, _triggerOpen: function(node) { var that = this; if (node.is(".k-edit-item")) { return; } var item = that.listView.dataItem(node); if (item) { that.trigger(OPEN, { entry: item }); } }, addFolder: function() { this.listView.add(); }, edit: function(target) { var that = this, selected = that.listView.select(); that.listView.edit(target || selected); }, getSelected: function() { var that = this, items = that.listView.select(), dataItems = []; for (var i = 0; i < items.length; i++) { var item = that.listView.dataItem(items[i]); if (item) { dataItems.push(item); } } return dataItems; }, destroy: function() { this.listView.element.off(NS); Component.fn.destroy.call(this); } }); ui.filemanager.registerViewComponent("list", ListView); var TreeView = Component.extend({ init: function(element, options, explicitOptions) { var that = this, messages = explicitOptions.messages; options = extend({}, that.defaultOptions, options, { messages }); Component.fn.init.call(this, ui.TreeView, element, options); that.treeView = that.widgetComponent; that._bindEvents(); if (explicitOptions.draggable !== false && !explicitOptions.isLocalBinding) { that._initDragAndDrop(); } }, defaultOptions: { dataTextField: "name", dropFilter: ".k-treeview-item" }, _refreshDataSource: function(ev) { var that = this, treeView = that.treeView, action = ev.action, node = ev.node, parentNode = null, treeEl = treeView.element, activeDescendant = treeEl.attr("aria-activedescendant"), items = ev.items.filter(function(item) { return item.isDirectory; }).map(function(item) { return extend({}, item.toJSON(), { id: item.id || kendo.guid(), hasChildren: item.hasDirectories && item.hasChildren, items: [] }); }); if (node) { const uid = treeView.dataSource.get(node.id)?.uid; parentNode = uid ? treeView.findByUid(uid) : null; if (parentNode && items.length) { treeView._progress(parentNode, false); } } if (!items.length) { return; } if (parentNode && (action == "itemloaded" || action === "sync")) { parentNode.find(".k-treeview-item").each(function(index, item) { treeView.remove(item); }); treeView.append(items, parentNode); if (that._shouldFocus) { treeView.current(parentNode); treeView.focus(); } } else if (action == "remove") { this._remove(items[0].id); } else if (action == "itemchange") { var existingItem = treeView.dataSource.get(items[0].id); if (existingItem) { existingItem.set(ev.field, items[0][ev.field]); } else if (parentNode) { treeView.append(items[0], parentNode); } } else if (!treeView.dataSource.data().length) { treeView.append(items); } else if (action === "sync" || action === undefined && !parentNode) { treeView.items().each(function(index, item) { treeView.remove(item); }); treeView.append(items); if (that._shouldFocus) { treeView.current(treeView._nextVisible($())); treeView.focus(); } } if (!!activeDescendant && treeEl.find("#" + activeDescendant).length === 0) { treeEl.removeAttr("aria-activedescendant"); } }, _remove: function(id) { var that = this, treeView = that.treeView, dataSource = treeView.dataSource, item = dataSource.get(id), node; if (item) { node = treeView.findByUid(item.uid); treeView.remove(node); } }, _bindEvents: function() { var that = this; that.treeView.bind(SELECT, that._navigate.bind(that)); that.treeView.bind(EXPAND, that._expand.bind(that)); that.treeView.element.on(KEYDOWN, that._keydownAction.bind(that)); }, _keydownAction: function(ev) { var that = this, target = $(ev.target).find(".k-focus").closest(".k-treeview-item"); that.trigger(KEYDOWNACTION, { target, keyCode: ev.keyCode }); }, _expand: function(ev) { var that = this, treeView = that.treeView, entry = treeView.dataItem(ev.node); ev.preventDefault(); that.trigger(LOAD, { entryId: entry.id }); }, _navigate: function(ev) { var that = this, node = ev.node, entry = that.treeView.dataItem(node), path = entry.id; ev.preventDefault(); that.trigger(NAVIGATE, { path, entry: entry.toJSON() }); }, _hold: $.noop, getSelected: function() { var that = this, selectedItem = that.treeView.element.find(".k-selected").closest(".k-treeview-item"), item = that.treeView.dataItem(selectedItem); return item; }, refresh: function(id) { var that = this, treeView = that.treeView, entry = treeView.dataSource.get(id), node = entry && treeView.findByUid(entry.uid); if (entry && node) { treeView.element.find(".k-selected").removeClass("k-selected"); node.find("> span.k-treeview-item-content").removeClass("k-hover").addClass("k-selected"); } }, reload: function() { this.treeView.dataSource.read(); } }); ui.filemanager.registerViewComponent("tree", TreeView); if (kendo.ui.Grid) { var Grid = Component.extend({ init: function(element, options, explicitOptions) { var that = this, dataSourceOptions = explicitOptions.dataSource, messages = explicitOptions.messages; options = extend({}, that.defaultOptions, options, { messages }); that._setDSOptions(options, dataSourceOptions); that._setupColumns(options, messages); options.kendoKeydown = options.kendoKeydown || that._kendoKeydown.bind(that); Component.fn.init.call(this, ui.Grid, element, options); that.grid = that.widgetComponent; that._bindEvents(); if (explicitOptions.draggable !== false && !dataSourceOptions.isLocalBinding) { that._initDragAndDrop(); } if (explicitOptions.ariaLabel) { that.element.find("[role=grid]").attr("aria-label", explicitOptions.ariaLabel); } }, defaultOptions: { selectable: kendo.support.mobileOS ? "row" : "multiple", editable: { mode: "inline", confirmation: false }, sortable: true, dropFilter: "tr:not(.k-grid-edit-row)", navigatable: true }, _setupColumns: function(options, messages) { if (!options.columns) { options.columns = [ { field: "name", title: messages.nameField || "Name", template: function(item) { let icon = !item.isDirectory ? kendo.getFileGroup(item.extension, true) : "folder"; let entryName = kendo.htmlEncode(item.name + (item.extension ?? "")); let template = "<div class='file-group-icon'>" + kendo.ui.icon(icon) + "</div>" + "<div class='file-name'>" + entryName + "<div>"; return template; } }, { field: "created", title: messages.dateCreatedField, format: "{0:G}" }, { field: "size", title: messages.sizeField, template: function(item) { if (item.size > 0) { return kendo.getFileSizeMessage(item.size); } else { return ""; } } } ]; } }, _bindEvents: function() { var that = this, grid = that.grid; grid.bind(CHANGE, that._select.bind(that)); grid.table.on("dblclick" + NS, that._dblClick.bind(that)); grid.table.on("mousedown" + NS, "tr:not(.k-grid-edit-row)", that._mousedown.bind(that)); grid.table.on(KEYDOWN + NS, ".k-grid-edit-row", that._keydown.bind(that)); grid.table.on(KEYDOWN + NS, that._keydownAction.bind(that)); grid.bind("edit", function() { that._toggleFocusable(true); }); grid.bind("cancel", function() { that.trigger("cancel"); }); grid.saveRow = $.noop; Component.fn._bindEvents.call(this); }, _kendoKeydown: function(ev) { var that = this, current = that.grid.current(), node = current ? current.closest("tr[data-uid]") : null; if (node && ev.keyCode === keys.ENTER && !ev.preventKendoKeydown) { that._triggerOpen(node); ev.preventKendoKeydown = true; } if (ev.keyCode === keys.F2) { ev.preventKendoKeydown = true; } }, _keydownAction: function(ev) { var that = this, target = $(ev.target).find(".k-focus").closest("tr"); if (target.length && !target.is(".k-grid-edit-row")) { that.trigger(KEYDOWNACTION, { target, keyCode: ev.keyCode }); } }, _keydown: function(ev) { var that = this, grid = that.grid; if (!$(ev.target).closest(".k-grid-edit-row").length) { return; } if (ev.keyCode === kendo.keys.ENTER) { setTimeout(function() { var editorContainer = that.grid._editContainer || $(); editorContainer.find("input").trigger("blur"); that._closeEditable(); }); that._tryCancel(); } if (ev.keyCode === kendo.keys.ESC) { grid.cancelChanges(); that.trigger("cancel"); } }, _mousedown: function(ev) { var that = this, node = $(ev.target).closest("tr[data-uid]"); if (ev.which === 1 && that.grid.editable) { setTimeout(function() { that._closeEditable(); }); that._tryCancel(); } if (ev.which === 3 && !node.is(".k-selected")) { that.grid.selectable.clear(); that.grid.select(node); } }, _tryCancel: function() { var that = this, grid = that.grid, container; if (grid.editable) { container = grid._editContainer; if (!container.find("input").val()) { grid.cancelChanges(); } } setTimeout(function() { that._toggleFocusable(false); }); }, _toggleFocusable: function(state) { var that = this, grid = that.grid; grid.table.find("tr,td").children().addBack().toggleClass("k-focusable", state); }, _closeEditable: function() { var that = this, container; if (that.grid.editable && !that.grid.editable.options.model.dirty) { container = that.grid._editContainer; that.grid._destroyEditable(); that.grid._displayRow(container); that.trigger("cancel"); } }, _select: function() { var that = this, dataItems = that.getSelected(); that.trigger(SELECT, { entries: dataItems }); }, _dblClick: function(ev) { var that = this, node = $(ev.target).closest("tr[data-uid]"); that._triggerOpen(node); }, _triggerOpen: function(node) { var that = this; if (node.is(".k-grid-edit-row")) { return; } var item = that.grid.dataItem(node); if (item) { that.trigger(OPEN, { entry: item }); } }, items: function() { let that = this, rows = that.grid.tbody.find("tr"); return rows; }, getSelected: function() { var that = this, items = that.grid.select(), dataItems = []; for (var i = 0; i < items.length; i++) { dataItems.push(that.grid.dataItem(items[i])); } return dataItems; }, addFolder: function() { this.grid.addRow(); }, edit: function(target) { var that = this, selected = that.grid.select(); that.grid.editRow(target || selected); }, destroy: function() { this.grid.table.off(NS); this.grid.element.off(NS); Component.fn.destroy.call(this); } }); ui.filemanager.registerViewComponent("grid", Grid); } })(window.kendo.jQuery); //#endregion //#region ../src/filemanager/data.js (function($, undefined) { var kendo = window.kendo, extend = $.extend, data = kendo.data, Node = data.Node, HierarchicalDataSource = data.HierarchicalDataSource, DataSource = data.DataSource; extend(true, kendo.data, { schemas: { "filemanager": { data: function(data) { return data.items || data || []; }, model: { id: "path", hasChildren: "hasDirectories", fields: { name: { editable: true, type: "string", defaultValue: "New Folder" }, size: { editable: false, type: "number" }, path: { editable: false, type: "string" }, extension: { editable: false, type: "string" }, isDirectory: { editable: false, defaultValue: true, type: "boolean" }, hasDirectories: { editable: false, defaultValue: false, type: "boolean" }, created: { type: "date", editable: false }, createdUtc: { type: "date", editable: false }, modified: { type: "date", editable: false }, modifiedUtc: { type: "date", editable: false } } } } } }); var FileEntry = Node.define({ init: function(value) { var that = this, isDirectory = this.isDirectory; Node.fn.init.call(this, value); if (typeof isDirectory === "string") { isDirectory = kendo.getter(isDirectory); } if (kendo.isFunction(isDirectory)) { var isDirectoryObject = isDirectory.call(that, that); if (isDirectoryObject && isDirectoryObject.length === 0) { that.isDirectory = false; } else { that.isDirectory = !!isDirectoryObject; } } if (that.isDirectory) { that._initChildren(); } }, _initChildren: function() { var that = this; var children, transport, parameterMap; if (!(that.children instanceof kendo.data.FileManagerDataSource)) { children = that.children = new kendo.data.FileManagerDataSource(that._childrenOptions); transport = children.transport; parameterMap = transport.parameterMap; transport.parameterMap = function(data, type) { if (type === "read" || type === "create") { data.target = that.id; } if (parameterMap) { data = parameterMap.call(that, data, type); } return data; }; children.parent = function() { return that; }; children.bind("change", function(e) { e.node = e.node || that; that.trigger("change", e); }); children.bind("error", function(e) { var collection = that.parent(); if (collection) { e.node = e.node || that; collection.trigger("error", e); } }); that._updateChildrenField(); } }, isNew: function() { if (this.fileManagerNewItem) { delete this.fileManagerNewItem; return true; } return this.id === this._defaultId; } }); var FileManagerDataSource = HierarchicalDataSource.extend({ init: function(options) { var fileEntry = FileEntry.define({ children: options }); if (options.filter && !options.serverFiltering) { this._hierarchicalFilter = options.filter; options.filter = null; } DataSource.fn.init.call(this, $.extend(true, {}, { schema: { modelBase: fileEntry, model: fileEntry } }, options)); this.isLocalBinding = this.transport instanceof kendo.data.LocalTransport; this._attachBubbleHandlers(); }, insert: function(index, model) { var parentNode = this.parent(); if (parentNode && parentNode._initChildren) { if (model && model.isDirectory) { parentNode.hasDirectories = true; } parentNode.hasChildren = true; parentNode._initChildren(); } return DataSource.fn.insert.call(this, index, model); }, remove: function(node) { var that = this, parentNode = node.parentNode(), dataSource = that, result; if (parentNode && parentNode._initChildren) { dataSource = parentNode.children; } that._cleanDestroyed(node); result = DataSource.fn.remove.call(dataSource, node); if (parentNode && dataSource.data() && !dataSource.data().length) { parentNode.hasChildren = false; } else if (parentNode && !this._hasDirectories(parentNode)) { parentNode.hasDirectories = false; } return result; }, _cleanDestroyed: function(node) { var that = this, dataSource = that; if (node.parentNode && node.parentNode()) { node = node.parentNode(); dataSource = node.children; dataSource._destroyed = []; that._cleanDestroyed(node); } else { dataSource._destroyed = []; } }, _hasDirectories: function(node) { var result; if (!node.children.data()) { return false; } result = node.children.data().filter(function(item) { return item.isDirectory; }); return !!result.length; } }); FileManagerDataSource.create = function(options) { options = options && options.push ? { data: options } : options; var dataSource = options || {}, data = dataSource.data; if (data && data._dataSource) { return data._dataSource; } dataSource.data = data; return dataSource instanceof FileManagerDataSource ? dataSource : new FileManagerDataSource(dataSource); }; kendo.observableFileManagerData = function(array) { var dataSource = FileManagerDataSource.create({ data: array, schema: kendo.data.schemas.filemanager }); dataSource.fetch(); dataSource._data._dataSource = dataSource; return dataSource._data; }; extend(kendo.data, { FileManagerDataSource, FileEntry }); })(window.kendo.jQuery); //#endregion //#region ../src/filemanager/contextmenu.js (function($, undefined) { var kendo = window.kendo, extend = $.extend, template = kendo.template, ContextMenu = kendo.ui.ContextMenu, ACTION = "action"; var FileManagerContextMenu = ContextMenu.extend({ init: function(element, options) { var that = this; ContextMenu.fn.init.call(that, element, options); that._overrideTemplates(); that._initDefaultItems(); that._extendItems(); that.bind("select", that._onSelect.bind(that)); that.bind("open", that._onOpen.bind(that)); }, _overrideTemplates: function() { this.templates.sprite = template(({ spriteCssClass, icon }) => { if (spriteCssClass) { return `<span class="${spriteCssClass}"></span>`; } return ""; }); }, _initDefaultItems: function() { var that = this, messages = that.options.messages; if (that.options.isLocalBinding) { that.defaultItems = {}; } else { that.defaultItems = { "rename": { text: messages.rename, icon: "pencil", command: "RenameCommand" }, "delete": { text: messages.delete, icon: "trash", command: "DeleteCommand" } }; } }, events: ContextMenu.fn.events.concat([ACTION]), _extendItems: function() { var that = this, items = that.options.items, item, isBuiltInTool; if (items && items.length) { for (var i = 0; i < items.length; i++) { item = items[i]; isBuiltInTool = $.isPlainObject(item) && Object.keys(item).length === 1 && item.name; if (isBuiltInTool) { item = item.name; } if ($.isPlainObject(item)) { that._extendItem(item); that.append(item); } else if (that.defaultItems[item]) { item = that.defaultItems[item]; that._extendItem(item); that.append(item); } } } else { for (var key in that.defaultItems) { item = that.defaultItems[key]; that._extendItem(item); that.append(item); } } }, _extendItem: function(item) { var that = this, messages = that.options.messages; extend(item, { text: messages[item.text], spriteCssClass: item.spriteCssClass || "", attr: { "data-command": item.command } }); }, _onSelect: function(ev) { var command = $(ev.item).data("command"); var target = $(ev.target); if (!command) { return; } this.action({ command, options: { target } }); }, _onOpen: function(ev) { var menu = ev.sender, items = menu.options.items; if (!items && $.isEmptyObject(this.defaultItems)) { ev.preventDefault(); } }, action: function(args) { this.trigger(ACTION, args); } }); extend(kendo.ui.filemanager, { ContextMenu: FileManagerContextMenu }); })(window.kendo.jQuery); //#endregion //#region ../src/kendo.filemanager.js const __meta__ = { id: "filemanager", name: "FileManager", category: "web", description: "The FileManager widget displays offers file management functionality.", depends: [ "core", "data", "listview", "toolbar", "breadcrumb", "menu", "treeview", "upload", "dialog", "switch", "resizable", "selectable", "editable", "textbox", "icons" ], features: [{ id: "filemanager-grid-view", name: "GridView", description: "Support for GridView", depends: ["grid"] }] }; (function($, undefined) { var ui = kendo.ui, extend = $.extend, encode = kendo.htmlEncode, isPlainObject = $.isPlainObject, isArray = Array.isArray, DataBoundWidget = ui.DataBoundWidget, template = kendo.template, outerHeight = kendo._outerHeight, ns = ".kendoFileManager", NAVIGATE = "navigate", SELECT = "select", OPEN = "open", ERROR = "error", CHANGE = "change", UPLOAD = "upload", SUCCESS = "success", CLICK = "click", TOGGLE = "toggle", CLOSE = "close", HIDE = "hide", LOAD = "load", DATABINDING = "dataBinding", DATABOUND = "dataBound", DROP = "drop", EXECUTE = "execute", COMMAND = "command", KEYDOWNACTION = "keydownAction", CANCEL = "cancel", TREE_TYPE = "tree", DOT = "."; var fileManagerStyles = { wrapper: "k-widget k-filemanager", header: "k-filemanager-header", navigation: "k-filemanager-navigation", contentContainer: "k-filemanager-content-container", content: "k-filemanager-content", preview: "k-filemanager-preview", toolbar: "k-filemanager-toolbar", treeview: "k-filemanager-treeview", breadcrumb: "k-filemanager-breadcrumb", view: "k-filemanager-view", grid: "k-filemanager-grid", list: "k-filemanager-listview", upload: "k-filemanager-upload", uploadDialog: "k-filemanager-upload-dialog", splitBar: "k-splitbar", splitBarHorizontal: "k-splitbar-horizontal k-splitbar-draggable-horizontal", splitBarHover: "k-splitbar-horizontal-hover", splitBarIcon: "k-icon k-resize-handle", splitBarNavigation: "k-filemanager-splitbar-navigation", splitBarPreview: "k-filemanager-splitbar-preview", resizable: "k-filemanager-resizable" }; var fileManagerTemplateStyles = { filePreview: "k-file-preview", fileInfo: "k-file-info", fileName: "k-file-name", fileMeta: "k-file-meta", metaLabel: "k-file-meta-label", metaValue: "k-file-meta-value", extension: "k-file-type", size: "k-file-size", created: "k-file-created", modified: "k-file-modified" }; var viewTypes = { grid: "grid", list: "list" }; var NO_FILE_PREVIEW_TEMPLATE = ({ styles, messages }) => `<div class="${encode(styles.fileInfo)}">` + `<div class="${encode(styles.filePreview)}">` + "<span class=\"k-file-icon k-icon k-svg-icon k-i-none\" aria-hidden=\"true\"></span>" + "</div>" + `<span class="${encode(styles.fileName)}" k-no-file-selected>${encode(messages.noFileSelected)}</span>` + "</div>"; var SINGLE_FILES_PREVIEW_TEMPLATE = ({ styles, selection, metaFields, messages }) => { let result = ""; result += `<div class="${encode(styles.fileInfo)}">` + `<div class="${encode(styles.filePreview)}">` + kendo.ui.icon({ icon: !selection[0].isDirectory ? encode(kendo.getFileGroup(selection[0].extension, true)) : "folder", iconClass: "k-file-icon", size: "xxxlarge" }) + "</div>" + `<span class="${encode(styles.fileName)}">${encode(selection[0].name)}</span>`; if (metaFields) { result += `<dl class="${encode(styles.fileMeta)}">`; for (var i = 0; i < metaFields.length; i += 1) { var field = metaFields[i]; result += `<dt class="${encode(styles.metaLabel)}">${encode(messages[field])}: </dt>` + `<dd class="${encode(styles.metaValue)} ${encode(styles[field])}">`; if (field == "size") { result += ` ${encode(kendo.getFileSizeMessage(selection[0][field]))}`; } else if (selection[0][field] instanceof Date) { result += ` ${encode(kendo.toString(selection[0][field], "G"))}`; } else if (field == "extension") { result += ` ${encode(!selection[0].isDirectory ? kendo.getFileGroup(selection[0].extension) : "folder")}`; } else { result += ` ${encode(selection[0][field])}`; } result += "</dd>" + "<dd class=\"k-line-break\"></dd>"; } result += "</dl>"; } result += "</div>"; return result; }; var MULTIPLE_FILES_PREVIEW_TEMPLATE = ({ styles, selection, messages }) => `<div class="${encode(styles.fileInfo)}">` + `<div class="${encode(styles.filePreview)}">` + kendo.ui.icon({ icon: "file", iconClass: "k-file-icon", size: "xxxlarge" }) + "</div>" + `<span class="${encode(styles.fileName)}">` + `${encode(selection.length)} ` + `${encode(messages.items)}` + "</span>" + "</div>"; var FileManager = DataBoundWidget.extend({ init: function(element, options) { var that = this; DataBoundWidget.fn.init.call(that, element, options); that.options = kendo.deepExtend({}, that.options, options); that.defaultSortOption = { field: "name", dir: "asc" }; that.folderSortOption = { field: "isDirectory", dir: "desc" }; that._commandStack = new ui.filemanager.CommandStack(); that._dataSource(); that._wrapper(); that._renderHeader(); that._renderContentContainer(); that._initContextMenu(); that._renderNavigation(); that._renderContent(); that._renderPreview(); that._initUploadDialog(); that._resizable(); that._attachKeyDown(); that.resize(); kendo.notify(that, kendo.ui); }, options: { name: "FileManager", height: 500, resizable: true, initialView: viewTypes.list, toolbar: { resizable: true }, contextMenu: {}, upload: {}, uploadUrl: "", views: {}, breadcrumb: {}, draggable: true, dialogs: { upload: { width: 530 }, moveConfirm: { width: 350, closable: true }, deleteConfirm: { width: 360, closable: true }, renamePrompt: { width: 350, closable: true } }, previewPane: { metaFields: [ "extension", "size", "created", "modified" ], noFileTemplate: NO_FILE_PREVIEW_TEMPLATE, singleFileTemplate: SINGLE_FILES_PREVIEW_TEMPLATE, multipleFilesTemplate: MULTIPLE_FILES_PREVIEW_TEMPLATE }, messages: { toolbar: { createFolder: "New Folder", upload: "Upload", sortDirection: "Sort Direction", sortDirectionAsc: "Sort Direction Ascending", sortDirectionDesc: "Sort Direction Descending", sortField: "Sort By", nameField: "Name", sizeField: "File Size", typeField: "Type", dateModifiedField: "Date Modified", dateCreatedField: "Date Created", listView: "List View", gridView: "Grid View", search: "Search", details: "View Details", detailsChecked: "On", detailsUnchecked: "Off", "delete": "Delete", rename: "Rename" }, views: { nameField: "Name", sizeField: "File Size", typeField: "Type", dateModifiedField: "Date Modified", dateCreatedField: "Date Created", items: "items", listLabel: "FileManager ListView", gridLabel: "FileManager Grid", treeLabel: "FileManager TreeView" }, dialogs: { upload: { title: "Upload Files", clear: "Clear List", done: "Done" }, moveConfirm: { title: "Confirm", content: "<p class='k-text-center'>Do you want to move or copy?</p>", okText: "Copy", cancel: "Move", close: "close" }, deleteConfirm: { title: "Confirm", content: "<p class='k-text-center'>Are you sure you want to delete the selected file(s)?</br>You cannot undo this action.</p>", okText: "Delete", cancel: "Cancel", close: "close" }, renamePrompt: { title: "Prompt", content: "<p class='k-text-center'>Enter new name for the file.</p>", okText: "Rename", cancel: "Cancel", close: "close" } }, previewPane: { noFileSelected: "No File Selected", extension: "Type", size: "Size", created: "Date Created", createdUtc: "Date Created UTC", modified: "Date Modified", modifiedUtc: "Date Modified UTC", items: "items" } } }, events: [ NAVIGATE, SELECT, OPEN, DATABINDING, DATABOUND, ERROR, DROP, EXECUTE, COMMAND ], defaultTools: { createFolder: { type: "button", name: "createFolder", command: "CreateFolderCommand", rules: { remote: true } }, upload: { type: "button", name: "upload", command: "OpenDialogCommand", options: "{ \"type\": \"uploadDialog\" }", rules: { remote: true } }, sortDirection: { type: "buttonGroup", buttons: [{ name: "sortDirectionAsc", showText: "overflow", icon: "sort-asc-small", togglable: true, group: "sortDirection", command: "SortCommand", options: "{ \"dir\": \"asc\" }", selected: true }, { name: "sortDirectionDesc", showText: "overflow", icon: "sort-desc-small", togglable: true, group: "sortDirection", command: "SortCommand", options: "{ \"dir\": \"desc\" }" }] }, sortField: { type: "splitButton", name: "sortField", command: "SortCommand", menuButtons: [ { name: "nameField", options: "{\"field\": \"name\"}", command: "SortCommand" }, { name: "typeField", options: "{\"field\": \"extension\"}", command: "SortCommand" }, { name: "sizeField", options: "{\"field\": \"size\"}", command: "SortCommand" }, { name: "dateCreatedField", options: "{\"field\": \"created\"}", command: "SortCommand" }, { name: "dateModifiedField", options: "{\"field\": \"modified\"}", command: "SortCommand" } ] }, changeView: { type: "buttonGroup", buttons: [{ name: "gridView", showText: "overflow", icon: "grid", togglable: true, group: "changeView", command: "ChangeViewCommand", options: "grid" }, { name: "listView", showText: "overflow", icon: "grid-layout", togglable: true, group: "changeView", command: "ChangeViewCommand", options: "list" }] }, spacer: { type: "spacer" }, details: { type: "component", name: "details", items: [{ template: function(data) { return "<label for='details-toggle'>" + encode(data.componentOptions.messages.text) + "</label>"; }, overflow: "never", componentOptions: { messages: { text: "details" } } }, { name: "details", command: "TogglePaneCommand", options: "{ \"type\": \"preview\" }", overflow: "never", element: "<input id='details-toggle' class='k-filemanager-details-toggle' />", component: "Switch", componentOptions: { messages: { checked: "detailsChecked", unchecked: "detailsUnchecked" }, commandOn: "change" } }] }, search: { type: "component", name: "search", command: "SearchCommand", options: "{ \"field\": \"name\", \"operator\": \"startswith\" }", overflow: "never", component: "TextBox", componentOptions: { placeholder: "search", icon: "search", commandOn: "input" } } }, _attachKeyDown: function() { var that = this; that.wrapper.on("keydown" + ns, (e) => { if (e.keyCode === kendo.keys.F10) { e.preventDefault(); that.toolbar.element.find("[tabindex=0]").first().trigger("focus"); } }); }, _dataSource: function() { var that = this, options = that.options, dataSourceOptions = options.dataSource || {}, typeSortOrder = that.folderSortOption, nameSortOrder = that.defaultSortOption, dataSource; if (!(dataSourceOptions instanceof kendo.data.FileManagerDataSource)) { if (isArray(dataSourceOptions)) { dataSource = { data: dataSourceOptions, autoSync: false, sort: [typeSortOrder, nameSortOrder] }; } else { dataSource = extend(true, dataSourceOptions, { autoSync: false, sort: [typeSortOrder, nameSortOrder] }); } if (dataSourceOptions && isPlainObject(dataSourceOptions.schema)) { dataSource.schema = dataSourceOptions.schema; } else if (isPlainObject(kendo.data.schemas.filemanager)) { dataSource.schema = kendo.data.schemas.filemanager; } } else { dataSource = dataSourceOptions; } if (that.dataSource && that._errorHandler) { that.dataSource.unbind(ERROR, that._errorHandler); that.dataSource.unbind(CHANGE, that._changeHandler); } else { that._errorHandler = that._error.bind(that); that._changeHandler = that._change.bind(that); } that.dataSource = kendo.data.FileManagerDataSource.create(dataSource).bind(ERROR, that._errorHandler).bind(CHANGE, that._changeHandler); }, _error: function(ev) {