X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/ee06f37b0f6f6d94cd05a6ffae556660f7c4a2bc..c930e9176a5a85509c5b0230e2bff5c22a591432:/docs/source/TreeSelector.html 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 @@ + + + The source code + + + + +
// 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