X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/ee06f37b0f6f6d94cd05a6ffae556660f7c4a2bc..c930e9176a5a85509c5b0230e2bff5c22a591432:/docs/source/TreeSelector.html?ds=sidebyside diff --git a/docs/source/TreeSelector.html b/docs/source/TreeSelector.html new file mode 100644 index 00000000..225dc43f --- /dev/null +++ b/docs/source/TreeSelector.html @@ -0,0 +1,291 @@ + +
+// custom menu item to contain Ext trees +Ext.menu.TreeItem = Ext.extend(Ext.menu.Adapter, { + constructor : function(config){ + Ext.menu.TreeItem.superclass.constructor.call(this, config.tree, config); + this.tree = this.component; + this.addEvents('selectionchange'); + + this.tree.on("render", function(tree){ + tree.body.swallowEvent(['click','keydown', 'keypress', 'keyup']); + }); + + this.tree.getSelectionModel().on("selectionchange", this.onSelect, this); + }, + + onSelect : function(tree, sel){ + this.fireEvent("select", this, sel, tree); + } +}); + + +// custom menu containing a single tree +Ext.menu.TreeMenu = Ext.extend(Ext.menu.Menu, { + cls:'x-tree-menu', + keyNav: true, + hideOnClick:false, + plain: true, + + constructor : function(config){ + Ext.menu.TreeMenu.superclass.constructor.call(this, config); + this.treeItem = new Ext.menu.TreeItem(config); + this.add(this.treeItem); + + this.tree = this.treeItem.tree; + this.tree.on('click', this.onNodeClick, this); + this.relayEvents(this.treeItem, ["selectionchange"]); + }, + + // private + beforeDestroy : function() { + this.tree.destroy(); + }, + + onNodeClick : function(node, e){ + if(!node.attributes.isFolder){ + this.treeItem.handleClick(e); + } + } +}); + + +// custom form field for displaying a tree, similar to select or combo +Ext.ux.TreeSelector = Ext.extend(Ext.form.TriggerField, { + initComponent : function(){ + Ext.ux.TreeSelector.superclass.initComponent.call(this); + this.addEvents('selectionchange'); + + this.tree.getSelectionModel().on('selectionchange', this.onSelection, this); + this.tree.on({ + 'expandnode': this.sync, + 'collapsenode' : this.sync, + 'append' : this.sync, + 'remove' : this.sync, + 'insert' : this.sync, + scope: this + }); + this.on('focus', this.onTriggerClick, this); + }, + + sync : function(){ + if(this.menu && this.menu.isVisible()){ + if(this.tree.body.getHeight() > this.maxHeight){ + this.tree.body.setHeight(this.maxHeight); + this.restricted = true; + }else if(this.restricted && this.tree.body.dom.firstChild.offsetHeight < this.maxHeight){ + this.tree.body.setHeight(''); + this.restricted = false; + } + this.menu.el.sync(); + } + }, + + onSelection : function(tree, node){ + if(!node){ + this.setRawValue(''); + }else{ + this.setRawValue(node.text); + } + }, + + initEvents : function(){ + Ext.ux.TreeSelector.superclass.initEvents.call(this); + this.el.on('mousedown', this.onTriggerClick, this); + this.el.on("keydown", this.onKeyDown, this); + }, + + onKeyDown : function(e){ + if(e.getKey() == e.DOWN){ + this.onTriggerClick(); + } + }, + + validateBlur : function(){ + return !this.menu || !this.menu.isVisible(); + }, + + getValue : function(){ + var sm = this.tree.getSelectionModel(); + var s = sm.getSelectedNode(); + return s ? s.id : ''; + }, + + setValue : function(id){ + var n = this.tree.getNodeById(id); + if(n){ + n.select(); + }else{ + this.tree.getSelectionModel().clearSelections(); + } + }, + + // private + onDestroy : function(){ + if(this.menu) { + this.menu.destroy(); + } + if(this.wrap){ + this.wrap.remove(); + } + Ext.ux.TreeSelector.superclass.onDestroy.call(this); + }, + + // private + menuListeners : { + show : function(){ // retain focus styling + this.onFocus(); + }, + hide : function(){ + this.focus.defer(10, this); + var ml = this.menuListeners; + this.menu.un("show", ml.show, this); + this.menu.un("hide", ml.hide, this); + } + }, + + onTriggerClick : function(){ + if(this.disabled){ + return; + } + this.menu.on(Ext.apply({}, this.menuListeners, { + scope:this + })); + + this.menu.show(this.el, "tl-bl?"); + this.sync(); + var sm = this.tree.getSelectionModel(); + var selected = sm.getSelectedNode(); + if(selected){ + selected.ensureVisible(); + sm.activate.defer(250, sm, [selected]); + } + }, + + beforeBlur : function(){ + // + }, + + onRender : function(){ + Ext.ux.TreeSelector.superclass.onRender.apply(this, arguments); + this.menu = new Ext.menu.TreeMenu(Ext.apply(this.menuConfig || {}, {tree: this.tree})); + this.menu.render(); + + this.tree.body.addClass('x-tree-selector'); + }, + + readOnly: true +}); + +/* + * Custom tree keyboard navigation that supports node navigation without selection + */ +Ext.tree.ActivationModel = Ext.extend(Ext.tree.DefaultSelectionModel, { + select : function(node){ + return this.activate(Ext.tree.ActivationModel.superclass.select.call(this, node)); + }, + + activate : function(node){ + if(!node){ + return; + } + if(this.activated != node) { + if(this.activated){ + this.activated.ui.removeClass('x-tree-activated'); + } + this.activated = node; + node.ui.addClass('x-tree-activated'); + } + node.ui.focus(); + return node; + }, + + activatePrevious : function(){ + var s = this.activated; + if(!s){ + return null; + } + var ps = s.previousSibling; + if(ps){ + if(!ps.isExpanded() || ps.childNodes.length < 1){ + return this.activate(ps); + } else{ + var lc = ps.lastChild; + while(lc && lc.isExpanded() && lc.childNodes.length > 0){ + lc = lc.lastChild; + } + return this.activate(lc); + } + } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){ + return this.activate(s.parentNode); + } + return null; + }, + + activateNext : function(){ + var s = this.activated; + if(!s){ + return null; + } + if(s.firstChild && s.isExpanded()){ + return this.activate(s.firstChild); + }else if(s.nextSibling){ + return this.activate(s.nextSibling); + }else if(s.parentNode){ + var newS = null; + s.parentNode.bubble(function(){ + if(this.nextSibling){ + newS = this.getOwnerTree().selModel.activate(this.nextSibling); + return false; + } + }); + return newS; + } + return null; + }, + + onKeyDown : function(e){ + var s = this.activated; + // undesirable, but required + var sm = this; + if(!s){ + return; + } + var k = e.getKey(); + switch(k){ + case e.DOWN: + e.stopEvent(); + this.activateNext(); + break; + case e.UP: + e.stopEvent(); + this.activatePrevious(); + break; + case e.RIGHT: + e.preventDefault(); + if(s.hasChildNodes()){ + if(!s.isExpanded()){ + s.expand(); + }else if(s.firstChild){ + this.activate(s.firstChild, e); + } + } + break; + case e.LEFT: + e.preventDefault(); + if(s.hasChildNodes() && s.isExpanded()){ + s.collapse(); + }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){ + this.activate(s.parentNode, e); + } + break; + }; + } +});+ + \ No newline at end of file