📄 ext.ux.filetreepanel.js
字号:
/** * @event newdir * Fires after the new directory has been successfully created * @param {Ext.ux.FileTreePanel} this * @param {Ext.tree.AsyncTreeNode} new node/directory that has been created */ ,'newdir' /** * @event newdirfailure * Fires if creation of new directory failed * @param {Ext.ux.FileTreePanel} this * @param {String} path creation of which failed */ ,'newdirfailure' ); // eo addEvents // }}} } // eo function initComponent // }}} // {{{ /** * onRender override - just expands root node if configured * @private */ ,onRender:function() { // call parent Ext.ux.FileTreePanel.superclass.onRender.apply(this, arguments); if(true === this.topMenu) { this.topMenu = Ext.getCmp(this.getTopToolbar().items.itemAt(0).id); this.getSelectionModel().on({ scope:this ,selectionchange:function(sm, node) { var disable = node ? false : true; disable = disable || this.readOnly; this.topMenu.setDisabled(disable); } }); Ext.apply(this.topMenu, { showMenu:function() { this.showContextMenu(false); }.createDelegate(this)// ,menu:this.getContextMenu() }); } // expand root node if so configured if(this.expandOnRender) { this.root.expand(); } // prevent default browser context menu to appear this.el.on({ contextmenu:{fn:function(){return false;},stopEvent:true} }); // setup loading mask if configured if(true === this.loadMask) { this.loader.on({ scope:this.el ,beforeload:this.el.mask.createDelegate(this.el, [this.loadingText + '...']) ,load:this.el.unmask ,loadexception:this.el.unmask }); } } // eo function onRender // }}} // new methods // {{{ /** * runs after an Ajax requested command has completed/failed * @private * @param {Object} options Options used for the request * @param {Boolean} success true if ajax call was successful (cmd may have failed) * @param {Object} response ajax call response object */ ,cmdCallback:function(options, success, response) { var i, o, node; var showMsg = true; // process Ajax success if(true === success) { // try to decode JSON response try { o = Ext.decode(response.responseText); } catch(ex) { this.showError(response.responseText); } // process command success if(true === o.success) { switch(options.params.cmd) { case 'delete': if(true !== this.eventsSuspended) { this.fireEvent('delete', this, this.getPath(options.node)); } options.node.parentNode.removeChild(options.node); break; case 'newdir': if(true !== this.eventsSuspended) { this.fireEvent('newdir', this, options.node); } break; case 'rename': this.updateCls(options.node, options.params.oldname); if(true !== this.eventsSuspended) { this.fireEvent('rename', this, options.node, options.params.newname, options.params.oldname); } break; } } // eo process command success // process command failure else { switch(options.params.cmd) { case 'rename': // handle drag & drop rename error if(options.oldParent) { options.oldParent.appendChild(options.node); } // handle simple rename error else { options.node.setText(options.oldName); } // signal failure to onNodeDrop if(options.e) { options.e.failure = true; } if(true !== this.eventsSuspended) { this.fireEvent('renamefailure', this, options.node, options.params.newname, options.params.oldname); } break; case 'newdir': if(false !== this.eventsSuspended) { this.fireEvent('newdirfailure', this, options.params.dir); } options.node.parentNode.removeChild(options.node); break; case 'delete': if(true !== this.eventsSuspended) { this.fireEvent('deletefailure', this, options.node); } options.node.parentNode.reload.defer(1, options.node.parentNode); break; default: this.root.reload(); break; } // show default message box with server error this.showError(o.error || response.responseText); } // eo process command failure } // eo process Ajax success // process Ajax failure else { this.showError(response.responseText); } } // eo function cmdCallback // }}} // {{{ /** * displays overwrite confirm msg box and runs passed callback if response is yes * @private * @param {String} filename File to overwrite * @param {Function} callback Function to call on yes response * @param {Object} scope Scope for callback (defaults to this) */ ,confirmOverwrite:function(filename, callback, scope) { Ext.Msg.show({ title:this.confirmText ,msg:String.format(this.existsText, filename) + '. ' + this.overwriteText ,icon:Ext.Msg.QUESTION ,buttons:Ext.Msg.YESNO ,fn:callback.createDelegate(scope || this) }); } // }}} // {{{ /** * creates new directory (node) * @private * @param {Ext.tree.AsyncTreeNode} node */ ,createNewDir:function(node) { // fire beforenewdir event if(true !== this.eventsSuspended && false === this.fireEvent('beforenewdir', this, node)) { return; } var treeEditor = this.treeEditor; var newNode; // get node to append the new directory to var appendNode = node.isLeaf() ? node.parentNode : node; // create new folder after the appendNode is expanded appendNode.expand(false, false, function(n) { // create new node newNode = n.appendChild(new Ext.tree.AsyncTreeNode({text:this.newdirText, iconCls:'folder'})); // setup one-shot event handler for editing completed treeEditor.on({ complete:{ scope:this ,single:true ,fn:this.onNewDir }} ); // creating new directory flag treeEditor.creatingNewDir = true; // start editing after short delay (function(){treeEditor.triggerEdit(newNode);}.defer(10)); // expand callback needs to run in this context }.createDelegate(this)); } // eo function creatingNewDir // }}} // {{{ /** * deletes the passed node * @private * @param {Ext.tree.AsyncTreeNode} node */ ,deleteNode:function(node) { // fire beforedelete event if(true !== this.eventsSuspended && false === this.fireEvent('beforedelete', this, node)) { return; } Ext.Msg.show({ title:this.deleteText ,msg:this.reallyWantText + ' ' + this.deleteText.toLowerCase() + ' <b>' + node.text + '</b>?' ,icon:Ext.Msg.WARNING ,buttons:Ext.Msg.YESNO ,scope:this ,fn:function(response) { // do nothing if answer is not yes if('yes' !== response) { this.getEl().dom.focus(); return; } // setup request options var options = { url:this.deleteUrl || this.url ,method:this.method ,scope:this ,callback:this.cmdCallback ,node:node ,params:{ cmd:'delete' ,file:this.getPath(node) } }; Ext.Ajax.request(options); } }); } // eo function deleteNode // }}} // {{{ /** * requests file download from server * @private * @param {String} path Full path including file name but relative to server root path */ ,downloadFile:function(path) { // create hidden target iframe var id = Ext.id(); var frame = document.createElement('iframe'); frame.id = id; frame.name = id; frame.className = 'x-hidden'; if(Ext.isIE) { frame.src = Ext.SSL_SECURE_URL; } document.body.appendChild(frame); if(Ext.isIE) { document.frames[id].name = id; } var form = Ext.DomHelper.append(document.body, { tag:'form' ,method:'post' ,action:this.downloadUrl || this.url ,target:id }); document.body.appendChild(form); var hidden; // append cmd to form hidden = document.createElement('input'); hidden.type = 'hidden'; hidden.name = 'cmd'; hidden.value = 'download'; form.appendChild(hidden); // append path to form hidden = document.createElement('input'); hidden.type = 'hidden'; hidden.name = 'path'; hidden.value = path; form.appendChild(hidden); var callback = function() { Ext.EventManager.removeListener(frame, 'load', callback, this); setTimeout(function() {document.body.removeChild(form);}, 100); setTimeout(function() {document.body.removeChild(frame);}, 110); }; Ext.EventManager.on(frame, 'load', callback, this); form.submit(); } // }}} // {{{ /** * returns (and lazy create) the context menu * @private */ ,getContextMenu:function() { // lazy create context menu if(!this.contextmenu) { var config = { singleUpload:this.singleUpload ,maxFileSize:this.maxFileSize ,enableProgress:this.enableProgress }; if(this.baseParams) { config.baseParams = this.baseParams; } this.contextmenu = new Ext.ux.FileTreeMenu(config); this.contextmenu.on({click:{scope:this, fn:this.onContextClick}}); this.uploadPanel = this.contextmenu.getItemByCmd('upload-panel').component; this.uploadPanel.on({ beforeupload:{scope:this, fn:this.onBeforeUpload} ,allfinished:{scope:this, fn:this.onAllFinished} }); this.uploadPanel.setUrl(this.uploadUrl || this.url); } return this.contextmenu; } // eo function getContextMenu // }}} // {{{ /** * returns file class based on name extension * @private * @param {String} name File name to get class of */ ,getFileCls:function(name) { var atmp = name.split('.'); if(1 === atmp.length) { return this.fileCls; } else { return this.fileCls + '-' + atmp.pop().toLowerCase(); } } // }}} // {{{ /** * returns path of node (file/directory) * @private */ ,getPath:function(node) { var path, p, a; // get path for non-root node if(node !== this.root) { p = node.parentNode; a = [node.text]; while(p && p !== this.root) { a.unshift(p.text); p = p.parentNode; } a.unshift(this.root.attributes.path || ''); path = a.join(this.pathSeparator); } // path for root node is it's path attribute else { path = node.attributes.path || ''; } // a little bit of security: strip leading / or . // full path security checking has to be implemented on server path = path.replace(/^[\/\.]*/, ''); return path; } // eo function getPath // }}} // {{{ /** * returns true if node has child with the specified name (text) * @private * @param {Ext.data.Node} node * @param {String} childName */ ,hasChild:function(node, childName) { return (node.isLeaf() ? node.parentNode : node).findChild('text', childName) !== null; } // }}} // {{{ /** * Hides context menu * @return {Ext.ux.FileTreeMenu} this */ ,hideContextMenu:function() { if(this.contextmenu && this.contextmenu.isVisible()) { this.contextmenu.hide(); } return this; } // eo function hideContextMenu // }}} // {{{ /** * called before editing is completed - allows edit cancellation * @private * @param {TreeEditor} editor * @param {String} newName * @param {String} oldName */ ,onBeforeEditComplete:function(editor, newName, oldName) { if(editor.cancellingEdit) { editor.cancellingEdit = false; return; } var oldPath = this.getPath(editor.editNode); var newPath = oldPath.replace(/\/[^\\]+$/, '/' + newName); if(false === this.fireEvent('beforerename', this, editor.editNode, newPath, oldPath)) { editor.cancellingEdit = true; editor.cancelEdit(); return false; } } // }}} // {{{ /** * runs before node is dropped * @private * @param {Object} e dropEvent object */ ,onBeforeNodeDrop:function(e) { // source node, node being dragged var s = e.dropNode; // destination node (dropping on this node) var d = e.target.leaf ? e.target.parentNode : e.target; // node has been dropped within the same parent if(s.parentNode === d) { return false; } // check if same name exists in the destination // this works only if destination node is loaded if(this.hasChild(d, s.text) && undefined === e.confirmed) { this.confirmOverwrite(s.text, function(response) { e.confirmed = 'yes' === response; this.onBeforeNodeDrop(e); }); return false; } if(false === e.confirmed) { return false; } e.confirmed = undefined; e.oldParent = s.parentNode; var oldName = this.getPath(s); var newName = this.getPath(d) + '/' + s.text; // fire beforerename event if(true !== this.eventsSuspended && false === this.fireEvent('beforerename', this, s, newName, oldName)) { return false; } var options = { url:this.renameUrl || this.url ,method:this.method ,scope:this ,callback:this.cmdCallback ,node:s ,oldParent:s.parentNode ,e:e ,params:{ cmd:'rename' ,oldname:oldName
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -