/*!
- * Ext JS Library 3.0.0
+ * Ext JS Library 3.0.3
* Copyright(c) 2006-2009 Ext JS, LLC
* licensing@extjs.com
* http://www.extjs.com/license
enableDD : false,\r
hlDrop : Ext.enableFx,\r
pathSeparator: "/",\r
+ \r
+ /**\r
+ * @cfg {Array} bubbleEvents\r
+ * <p>An array of events that, when fired, should be bubbled to any parent container.\r
+ * Defaults to <tt>['add', 'remove']</tt>.\r
+ */\r
+ bubbleEvents: [],\r
\r
initComponent : function(){\r
Ext.tree.TreePanel.superclass.initComponent.call(this);\r
*/\r
"checkchange",\r
/**\r
+ * @event beforedblclick\r
+ * Fires before double click processing on a node. Return false to cancel the default action.\r
+ * @param {Node} node The node\r
+ * @param {Ext.EventObject} e The event object\r
+ */\r
+ "beforedblclick",\r
+ /**\r
* @event dblclick\r
* Fires when a node is double clicked\r
* @param {Node} node The node\r
*/\r
selectPath : function(path, attr, callback){\r
attr = attr || "id";\r
- var keys = path.split(this.pathSeparator);\r
- var v = keys.pop();\r
- if(keys.length > 0){\r
+ var keys = path.split(this.pathSeparator),\r
+ v = keys.pop();\r
+ if(keys.length > 1){\r
var f = function(success, node){\r
if(success && node){\r
var n = node.findChild(attr, v);\r
\r
Ext.tree.TreeEventModel.prototype = {\r
initEvents : function(){\r
- var el = this.tree.getTreeEl();\r
- el.on('click', this.delegateClick, this);\r
- if(this.tree.trackMouseOver !== false){\r
- this.tree.innerCt.on('mouseover', this.delegateOver, this);\r
- this.tree.innerCt.on('mouseout', this.delegateOut, this);\r
+ var t = this.tree;\r
+ \r
+ if(t.trackMouseOver !== false){\r
+ t.mon(t.innerCt, {\r
+ scope: this,\r
+ mouseover: this.delegateOver,\r
+ mouseout: this.delegateOut\r
+ });\r
}\r
- el.on('dblclick', this.delegateDblClick, this);\r
- el.on('contextmenu', this.delegateContextMenu, this);\r
+ t.mon(t.getTreeEl(), {\r
+ scope: this,\r
+ click: this.delegateClick,\r
+ dblclick: this.delegateDblClick,\r
+ contextmenu: this.delegateContextMenu\r
+ });\r
},\r
\r
getNode : function(e){\r
Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {\r
init : function(tree){\r
this.tree = tree;\r
- tree.getTreeEl().on("keydown", this.onKeyDown, this);\r
+ tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);\r
tree.on("click", this.onNodeClick, this);\r
},\r
\r
* @param {TreeNode} node The node to select\r
* @return {TreeNode} The selected node\r
*/\r
- select : function(node){\r
+ select : function(node, /* private*/ selectNextNode){\r
+ // If node is hidden, select the next node in whatever direction was being moved in.\r
+ if (!Ext.fly(node.ui.wrap).isVisible() && selectNextNode) {\r
+ return selectNextNode.call(this, node);\r
+ }\r
var last = this.selNode;\r
if(node == last){\r
node.ui.onSelectedChange(true);\r
* Selects the node above the selected node in the tree, intelligently walking the nodes\r
* @return TreeNode The new selection\r
*/\r
- selectPrevious : function(){\r
- var s = this.selNode || this.lastSelNode;\r
- if(!s){\r
+ selectPrevious : function(/* private */ s){\r
+ if(!(s = s || this.selNode || this.lastSelNode)){\r
return null;\r
}\r
+ // Here we pass in the current function to select to indicate the direction we're moving\r
var ps = s.previousSibling;\r
if(ps){\r
if(!ps.isExpanded() || ps.childNodes.length < 1){\r
- return this.select(ps);\r
+ return this.select(ps, this.selectPrevious);\r
} else{\r
var lc = ps.lastChild;\r
- while(lc && lc.isExpanded() && lc.childNodes.length > 0){\r
+ while(lc && lc.isExpanded() && Ext.fly(lc.ui.wrap).isVisible() && lc.childNodes.length > 0){\r
lc = lc.lastChild;\r
}\r
- return this.select(lc);\r
+ return this.select(lc, this.selectPrevious);\r
}\r
} else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){\r
- return this.select(s.parentNode);\r
+ return this.select(s.parentNode, this.selectPrevious);\r
}\r
return null;\r
},\r
* Selects the node above the selected node in the tree, intelligently walking the nodes\r
* @return TreeNode The new selection\r
*/\r
- selectNext : function(){\r
- var s = this.selNode || this.lastSelNode;\r
- if(!s){\r
+ selectNext : function(/* private */ s){\r
+ if(!(s = s || this.selNode || this.lastSelNode)){\r
return null;\r
}\r
- if(s.firstChild && s.isExpanded()){\r
- return this.select(s.firstChild);\r
+ // Here we pass in the current function to select to indicate the direction we're moving\r
+ if(s.firstChild && s.isExpanded() && Ext.fly(s.ui.wrap).isVisible()){\r
+ return this.select(s.firstChild, this.selectNext);\r
}else if(s.nextSibling){\r
- return this.select(s.nextSibling);\r
+ return this.select(s.nextSibling, this.selectNext);\r
}else if(s.parentNode){\r
var newS = null;\r
s.parentNode.bubble(function(){\r
if(this.nextSibling){\r
- newS = this.getOwnerTree().selModel.select(this.nextSibling);\r
+ newS = this.getOwnerTree().selModel.select(this.nextSibling, this.selectNext);\r
return false;\r
}\r
});\r
Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {\r
init : function(tree){\r
this.tree = tree;\r
- tree.getTreeEl().on("keydown", this.onKeyDown, this);\r
+ tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);\r
tree.on("click", this.onNodeClick, this);\r
},\r
\r
if(t){\r
t.unregisterNode(this);\r
}\r
- this.id = id;\r
+ this.id = this.attributes.id = id;\r
if(t){\r
t.registerNode(this);\r
}\r
*/\r
Ext.tree.TreeNode = function(attributes){\r
attributes = attributes || {};\r
- if(typeof attributes == "string"){\r
+ if(typeof attributes == 'string'){\r
attributes = {text: attributes};\r
}\r
this.childrenRendered = false;\r
this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;\r
\r
/**\r
- * Read-only. The text for this node. To change it use setText().\r
+ * Read-only. The text for this node. To change it use <code>{@link #setText}</code>.\r
* @type String\r
*/\r
this.text = attributes.text;\r
* @param {String} text The new text\r
* @param {String} oldText The old text\r
*/\r
- "textchange",\r
+ 'textchange',\r
/**\r
* @event beforeexpand\r
* Fires before this node is expanded, return false to cancel.\r
* @param {Boolean} deep\r
* @param {Boolean} anim\r
*/\r
- "beforeexpand",\r
+ 'beforeexpand',\r
/**\r
* @event beforecollapse\r
* Fires before this node is collapsed, return false to cancel.\r
* @param {Boolean} deep\r
* @param {Boolean} anim\r
*/\r
- "beforecollapse",\r
+ 'beforecollapse',\r
/**\r
* @event expand\r
* Fires when this node is expanded\r
* @param {Node} this This node\r
*/\r
- "expand",\r
+ 'expand',\r
/**\r
* @event disabledchange\r
* Fires when the disabled status of this node changes\r
* @param {Node} this This node\r
* @param {Boolean} disabled\r
*/\r
- "disabledchange",\r
+ 'disabledchange',\r
/**\r
* @event collapse\r
* Fires when this node is collapsed\r
* @param {Node} this This node\r
*/\r
- "collapse",\r
+ 'collapse',\r
/**\r
* @event beforeclick\r
* Fires before click processing. Return false to cancel the default action.\r
* @param {Node} this This node\r
* @param {Ext.EventObject} e The event object\r
*/\r
- "beforeclick",\r
+ 'beforeclick',\r
/**\r
* @event click\r
* Fires when this node is clicked\r
* @param {Node} this This node\r
* @param {Ext.EventObject} e The event object\r
*/\r
- "click",\r
+ 'click',\r
/**\r
* @event checkchange\r
* Fires when a node with a checkbox's checked property changes\r
* @param {Node} this This node\r
* @param {Boolean} checked\r
*/\r
- "checkchange",\r
+ 'checkchange',\r
+ /**\r
+ * @event beforedblclick\r
+ * Fires before double click processing. Return false to cancel the default action.\r
+ * @param {Node} this This node\r
+ * @param {Ext.EventObject} e The event object\r
+ */\r
+ 'beforedblclick',\r
/**\r
* @event dblclick\r
* Fires when this node is double clicked\r
* @param {Node} this This node\r
* @param {Ext.EventObject} e The event object\r
*/\r
- "dblclick",\r
+ 'dblclick',\r
/**\r
* @event contextmenu\r
* Fires when this node is right clicked\r
* @param {Node} this This node\r
* @param {Ext.EventObject} e The event object\r
*/\r
- "contextmenu",\r
+ 'contextmenu',\r
/**\r
* @event beforechildrenrendered\r
* Fires right before the child nodes for this node are rendered\r
* @param {Node} this This node\r
*/\r
- "beforechildrenrendered"\r
+ 'beforechildrenrendered'\r
);\r
\r
var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;\r
this.ui = new uiClass(this);\r
};\r
Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {\r
- preventHScroll: true,\r
+ preventHScroll : true,\r
/**\r
* Returns true if this node is expanded\r
* @return {Boolean}\r
\r
// private override\r
insertBefore : function(node, refNode){\r
- if(!node.render){ \r
+ if(!node.render){\r
node = this.getLoader().createNode(node);\r
}\r
var newNode = Ext.tree.TreeNode.superclass.insertBefore.call(this, node, refNode);\r
if(this.rendered){ // event without subscribing\r
this.ui.onTextChange(this, text, oldText);\r
}\r
- this.fireEvent("textchange", this, text, oldText);\r
+ this.fireEvent('textchange', this, text, oldText);\r
},\r
\r
/**\r
*/\r
expand : function(deep, anim, callback, scope){\r
if(!this.expanded){\r
- if(this.fireEvent("beforeexpand", this, deep, anim) === false){\r
+ if(this.fireEvent('beforeexpand', this, deep, anim) === false){\r
return;\r
}\r
if(!this.childrenRendered){\r
this.expanded = true;\r
if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){\r
this.ui.animExpand(function(){\r
- this.fireEvent("expand", this);\r
+ this.fireEvent('expand', this);\r
this.runCallback(callback, scope || this, [this]);\r
if(deep === true){\r
this.expandChildNodes(true);\r
return;\r
}else{\r
this.ui.expand();\r
- this.fireEvent("expand", this);\r
+ this.fireEvent('expand', this);\r
this.runCallback(callback, scope || this, [this]);\r
}\r
}else{\r
this.expandChildNodes(true);\r
}\r
},\r
- \r
- runCallback: function(cb, scope, args){\r
+\r
+ runCallback : function(cb, scope, args){\r
if(Ext.isFunction(cb)){\r
cb.apply(scope, args);\r
}\r
*/\r
collapse : function(deep, anim, callback, scope){\r
if(this.expanded && !this.isHiddenRoot()){\r
- if(this.fireEvent("beforecollapse", this, deep, anim) === false){\r
+ if(this.fireEvent('beforecollapse', this, deep, anim) === false){\r
return;\r
}\r
this.expanded = false;\r
if((this.getOwnerTree().animate && anim !== false) || anim){\r
this.ui.animCollapse(function(){\r
- this.fireEvent("collapse", this);\r
+ this.fireEvent('collapse', this);\r
this.runCallback(callback, scope || this, [this]);\r
if(deep === true){\r
this.collapseChildNodes(true);\r
return;\r
}else{\r
this.ui.collapse();\r
- this.fireEvent("collapse", this);\r
+ this.fireEvent('collapse', this);\r
this.runCallback(callback, scope || this, [this]);\r
}\r
}else if(!this.expanded){\r
if(this.rendered && this.ui.onDisableChange){ // event without subscribing\r
this.ui.onDisableChange(this, true);\r
}\r
- this.fireEvent("disabledchange", this, true);\r
+ this.fireEvent('disabledchange', this, true);\r
},\r
\r
/**\r
if(this.rendered && this.ui.onDisableChange){ // event without subscribing\r
this.ui.onDisableChange(this, false);\r
}\r
- this.fireEvent("disabledchange", this, false);\r
+ this.fireEvent('disabledchange', this, false);\r
},\r
\r
// private\r
renderChildren : function(suppressEvent){\r
if(suppressEvent !== false){\r
- this.fireEvent("beforechildrenrendered", this);\r
+ this.fireEvent('beforechildrenrendered', this);\r
}\r
var cs = this.childNodes;\r
for(var i = 0, len = cs.length; i < len; i++){\r
this.ui.destroy();\r
}\r
},\r
- \r
+\r
// private\r
- onIdChange: function(id){\r
+ onIdChange : function(id){\r
this.ui.onIdChange(id);\r
}\r
});\r
this.node.on("move", this.onMove, this);\r
\r
if(this.node.disabled){\r
- this.addClass("x-tree-node-disabled");\r
- if (this.checkbox) {\r
- this.checkbox.disabled = true;\r
- } \r
+ this.onDisableChange(this.node, true); \r
}\r
if(this.node.hidden){\r
this.hide();\r
if(this.disabled){\r
return;\r
}\r
- if(this.checkbox){\r
- this.toggleCheck();\r
- }\r
- if(!this.animating && this.node.isExpandable()){\r
- this.node.toggle();\r
+ if(this.fireEvent("beforedblclick", this.node, e) !== false){\r
+ if(this.checkbox){\r
+ this.toggleCheck();\r
+ }\r
+ if(!this.animating && this.node.isExpandable()){\r
+ this.node.toggle();\r
+ }\r
+ this.fireEvent("dblclick", this.node, e);\r
}\r
- this.fireEvent("dblclick", this.node, e);\r
},\r
\r
onOver : function(e){\r
}\r
}\r
if(this.doPreload(node)){ // preloaded json children\r
- this.runCallback(callback, scope || node, []);\r
+ this.runCallback(callback, scope || node, [node]);\r
}else if(this.directFn || this.dataUrl || this.url){\r
this.requestData(node, callback, scope || node);\r
}\r
* Example:<pre><code>\r
new Ext.tree.TreePanel({\r
...\r
- new Ext.tree.TreeLoader({\r
+ loader: new Ext.tree.TreeLoader({\r
url: 'dataUrl',\r
createNode: function(attr) {\r
// Allow consolidation consignments to have\r
attr.iconCls = 'x-consol',\r
attr.allowDrop = true;\r
}\r
- return Ext.tree.TreeLoader.prototype.call(this, attr);\r
+ return Ext.tree.TreeLoader.prototype.createNode.call(this, attr);\r
}\r
}),\r
...\r
if(this.baseAttrs){\r
Ext.applyIf(attr, this.baseAttrs);\r
}\r
- if(this.applyLoader !== false){\r
+ if(this.applyLoader !== false && !attr.loader){\r
attr.loader = this;\r
}\r
if(typeof attr.uiProvider == 'string'){\r