2 * Ext JS Library 0.30
\r
3 * Copyright(c) 2006-2009, Ext JS, LLC.
\r
4 * licensing@extjs.com
\r
6 * http://extjs.com/license
\r
9 // custom menu item to contain Ext trees
\r
10 Ext.menu.TreeItem = Ext.extend(Ext.menu.Adapter, {
\r
11 constructor : function(config){
\r
12 Ext.menu.TreeItem.superclass.constructor.call(this, config.tree, config);
\r
13 this.tree = this.component;
\r
14 this.addEvents('selectionchange');
\r
16 this.tree.on("render", function(tree){
\r
17 tree.body.swallowEvent(['click','keydown', 'keypress', 'keyup']);
\r
20 this.tree.getSelectionModel().on("selectionchange", this.onSelect, this);
\r
23 onSelect : function(tree, sel){
\r
24 this.fireEvent("select", this, sel, tree);
\r
29 // custom menu containing a single tree
\r
30 Ext.menu.TreeMenu = Ext.extend(Ext.menu.Menu, {
\r
36 constructor : function(config){
\r
37 Ext.menu.TreeMenu.superclass.constructor.call(this, config);
\r
38 this.treeItem = new Ext.menu.TreeItem(config);
\r
39 this.add(this.treeItem);
\r
41 this.tree = this.treeItem.tree;
\r
42 this.tree.on('click', this.onNodeClick, this);
\r
43 this.relayEvents(this.treeItem, ["selectionchange"]);
\r
47 beforeDestroy : function() {
\r
48 this.tree.destroy();
\r
51 onNodeClick : function(node, e){
\r
52 if(!node.attributes.isFolder){
\r
53 this.treeItem.handleClick(e);
\r
59 // custom form field for displaying a tree, similar to select or combo
\r
60 Ext.ux.TreeSelector = Ext.extend(Ext.form.TriggerField, {
\r
61 initComponent : function(){
\r
62 Ext.ux.TreeSelector.superclass.initComponent.call(this);
\r
63 this.addEvents('selectionchange');
\r
65 this.tree.getSelectionModel().on('selectionchange', this.onSelection, this);
\r
67 'expandnode': this.sync,
\r
68 'collapsenode' : this.sync,
\r
69 'append' : this.sync,
\r
70 'remove' : this.sync,
\r
71 'insert' : this.sync,
\r
74 this.on('focus', this.onTriggerClick, this);
\r
78 if(this.menu && this.menu.isVisible()){
\r
79 if(this.tree.body.getHeight() > this.maxHeight){
\r
80 this.tree.body.setHeight(this.maxHeight);
\r
81 this.restricted = true;
\r
82 }else if(this.restricted && this.tree.body.dom.firstChild.offsetHeight < this.maxHeight){
\r
83 this.tree.body.setHeight('');
\r
84 this.restricted = false;
\r
86 this.menu.el.sync();
\r
90 onSelection : function(tree, node){
\r
92 this.setRawValue('');
\r
94 this.setRawValue(node.text);
\r
98 initEvents : function(){
\r
99 Ext.ux.TreeSelector.superclass.initEvents.call(this);
\r
100 this.el.on('mousedown', this.onTriggerClick, this);
\r
101 this.el.on("keydown", this.onKeyDown, this);
\r
104 onKeyDown : function(e){
\r
105 if(e.getKey() == e.DOWN){
\r
106 this.onTriggerClick();
\r
110 validateBlur : function(){
\r
111 return !this.menu || !this.menu.isVisible();
\r
114 getValue : function(){
\r
115 var sm = this.tree.getSelectionModel();
\r
116 var s = sm.getSelectedNode();
\r
117 return s ? s.id : '';
\r
120 setValue : function(id){
\r
121 var n = this.tree.getNodeById(id);
\r
125 this.tree.getSelectionModel().clearSelections();
\r
130 onDestroy : function(){
\r
132 this.menu.destroy();
\r
135 this.wrap.remove();
\r
137 Ext.ux.TreeSelector.superclass.onDestroy.call(this);
\r
142 show : function(){ // retain focus styling
\r
146 this.focus.defer(10, this);
\r
147 var ml = this.menuListeners;
\r
148 this.menu.un("show", ml.show, this);
\r
149 this.menu.un("hide", ml.hide, this);
\r
153 onTriggerClick : function(){
\r
157 this.menu.on(Ext.apply({}, this.menuListeners, {
\r
161 this.menu.show(this.el, "tl-bl?");
\r
163 var sm = this.tree.getSelectionModel();
\r
164 var selected = sm.getSelectedNode();
\r
166 selected.ensureVisible();
\r
167 sm.activate.defer(250, sm, [selected]);
\r
171 beforeBlur : function(){
\r
175 onRender : function(){
\r
176 Ext.ux.TreeSelector.superclass.onRender.apply(this, arguments);
\r
177 this.menu = new Ext.menu.TreeMenu(Ext.apply(this.menuConfig || {}, {tree: this.tree}));
\r
178 this.menu.render();
\r
180 this.tree.body.addClass('x-tree-selector');
\r
187 * Custom tree keyboard navigation that supports node navigation without selection
\r
189 Ext.tree.ActivationModel = Ext.extend(Ext.tree.DefaultSelectionModel, {
\r
190 select : function(node){
\r
191 return this.activate(Ext.tree.ActivationModel.superclass.select.call(this, node));
\r
194 activate : function(node){
\r
198 if(this.activated != node) {
\r
199 if(this.activated){
\r
200 this.activated.ui.removeClass('x-tree-activated');
\r
202 this.activated = node;
\r
203 node.ui.addClass('x-tree-activated');
\r
209 activatePrevious : function(){
\r
210 var s = this.activated;
\r
214 var ps = s.previousSibling;
\r
216 if(!ps.isExpanded() || ps.childNodes.length < 1){
\r
217 return this.activate(ps);
\r
219 var lc = ps.lastChild;
\r
220 while(lc && lc.isExpanded() && lc.childNodes.length > 0){
\r
223 return this.activate(lc);
\r
225 } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
\r
226 return this.activate(s.parentNode);
\r
231 activateNext : function(){
\r
232 var s = this.activated;
\r
236 if(s.firstChild && s.isExpanded()){
\r
237 return this.activate(s.firstChild);
\r
238 }else if(s.nextSibling){
\r
239 return this.activate(s.nextSibling);
\r
240 }else if(s.parentNode){
\r
242 s.parentNode.bubble(function(){
\r
243 if(this.nextSibling){
\r
244 newS = this.getOwnerTree().selModel.activate(this.nextSibling);
\r
253 onKeyDown : function(e){
\r
254 var s = this.activated;
\r
255 // undesirable, but required
\r
260 var k = e.getKey();
\r
264 this.activateNext();
\r
268 this.activatePrevious();
\r
271 e.preventDefault();
\r
272 if(s.hasChildNodes()){
\r
273 if(!s.isExpanded()){
\r
275 }else if(s.firstChild){
\r
276 this.activate(s.firstChild, e);
\r
281 e.preventDefault();
\r
282 if(s.hasChildNodes() && s.isExpanded()){
\r
284 }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
\r
285 this.activate(s.parentNode, e);
\r