X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/6e39d509471fe9b4e2660e0d1631b350d0c66f40..refs/heads/old:/src/widgets/tree/TreeNodeUI.js?ds=inline
diff --git a/src/widgets/tree/TreeNodeUI.js b/src/widgets/tree/TreeNodeUI.js
index 46ba4ef0..6c1aa086 100644
--- a/src/widgets/tree/TreeNodeUI.js
+++ b/src/widgets/tree/TreeNodeUI.js
@@ -1,627 +1,676 @@
/*!
- * Ext JS Library 3.1.0
- * Copyright(c) 2006-2009 Ext JS, LLC
- * licensing@extjs.com
- * http://www.extjs.com/license
+ * Ext JS Library 3.3.1
+ * Copyright(c) 2006-2010 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
*/
-/**
- * @class Ext.tree.TreeNodeUI
- * This class provides the default UI implementation for Ext TreeNodes.
- * The TreeNode UI implementation is separate from the
- * tree implementation, and allows customizing of the appearance of
- * tree nodes.
- *
- * If you are customizing the Tree's user interface, you
- * may need to extend this class, but you should never need to instantiate this class.
- *
- * This class provides access to the user interface components of an Ext TreeNode, through
- * {@link Ext.tree.TreeNode#getUI}
- */
-Ext.tree.TreeNodeUI = function(node){
- this.node = node;
- this.rendered = false;
- this.animating = false;
- this.wasLeaf = true;
- this.ecc = 'x-tree-ec-icon x-tree-elbow';
- this.emptyIcon = Ext.BLANK_IMAGE_URL;
-};
-
-Ext.tree.TreeNodeUI.prototype = {
- // private
- removeChild : function(node){
- if(this.rendered){
- this.ctNode.removeChild(node.ui.getEl());
- }
- },
-
- // private
- beforeLoad : function(){
- this.addClass("x-tree-node-loading");
- },
-
- // private
- afterLoad : function(){
- this.removeClass("x-tree-node-loading");
- },
-
- // private
- onTextChange : function(node, text, oldText){
- if(this.rendered){
- this.textNode.innerHTML = text;
- }
- },
-
- // private
- onDisableChange : function(node, state){
- this.disabled = state;
- if (this.checkbox) {
- this.checkbox.disabled = state;
- }
- if(state){
- this.addClass("x-tree-node-disabled");
- }else{
- this.removeClass("x-tree-node-disabled");
- }
- },
-
- // private
- onSelectedChange : function(state){
- if(state){
- this.focus();
- this.addClass("x-tree-selected");
- }else{
- //this.blur();
- this.removeClass("x-tree-selected");
- }
- },
-
- // private
- onMove : function(tree, node, oldParent, newParent, index, refNode){
- this.childIndent = null;
- if(this.rendered){
- var targetNode = newParent.ui.getContainer();
- if(!targetNode){//target not rendered
- this.holder = document.createElement("div");
- this.holder.appendChild(this.wrap);
- return;
- }
- var insertBefore = refNode ? refNode.ui.getEl() : null;
- if(insertBefore){
- targetNode.insertBefore(this.wrap, insertBefore);
- }else{
- targetNode.appendChild(this.wrap);
- }
- this.node.renderIndent(true, oldParent != newParent);
- }
- },
-
-/**
- * Adds one or more CSS classes to the node's UI element.
- * Duplicate classes are automatically filtered out.
- * @param {String/Array} className The CSS class to add, or an array of classes
- */
- addClass : function(cls){
- if(this.elNode){
- Ext.fly(this.elNode).addClass(cls);
- }
- },
-
-/**
- * Removes one or more CSS classes from the node's UI element.
- * @param {String/Array} className The CSS class to remove, or an array of classes
- */
- removeClass : function(cls){
- if(this.elNode){
- Ext.fly(this.elNode).removeClass(cls);
- }
- },
-
- // private
- remove : function(){
- if(this.rendered){
- this.holder = document.createElement("div");
- this.holder.appendChild(this.wrap);
- }
- },
-
- // private
- fireEvent : function(){
- return this.node.fireEvent.apply(this.node, arguments);
- },
-
- // private
- initEvents : function(){
- this.node.on("move", this.onMove, this);
-
- if(this.node.disabled){
- this.onDisableChange(this.node, true);
- }
- if(this.node.hidden){
- this.hide();
- }
- var ot = this.node.getOwnerTree();
- var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
- if(dd && (!this.node.isRoot || ot.rootVisible)){
- Ext.dd.Registry.register(this.elNode, {
- node: this.node,
- handles: this.getDDHandles(),
- isHandle: false
- });
- }
- },
-
- // private
- getDDHandles : function(){
- return [this.iconNode, this.textNode, this.elNode];
- },
-
-/**
- * Hides this node.
- */
- hide : function(){
- this.node.hidden = true;
- if(this.wrap){
- this.wrap.style.display = "none";
- }
- },
-
-/**
- * Shows this node.
- */
- show : function(){
- this.node.hidden = false;
- if(this.wrap){
- this.wrap.style.display = "";
- }
- },
-
- // private
- onContextMenu : function(e){
- if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
- e.preventDefault();
- this.focus();
- this.fireEvent("contextmenu", this.node, e);
- }
- },
-
- // private
- onClick : function(e){
- if(this.dropping){
- e.stopEvent();
- return;
- }
- if(this.fireEvent("beforeclick", this.node, e) !== false){
- var a = e.getTarget('a');
- if(!this.disabled && this.node.attributes.href && a){
- this.fireEvent("click", this.node, e);
- return;
- }else if(a && e.ctrlKey){
- e.stopEvent();
- }
- e.preventDefault();
- if(this.disabled){
- return;
- }
-
- if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
- this.node.toggle();
- }
-
- this.fireEvent("click", this.node, e);
- }else{
- e.stopEvent();
- }
- },
-
- // private
- onDblClick : function(e){
- e.preventDefault();
- if(this.disabled){
- return;
- }
- if(this.fireEvent("beforedblclick", this.node, e) !== false){
- if(this.checkbox){
- this.toggleCheck();
- }
- if(!this.animating && this.node.isExpandable()){
- this.node.toggle();
- }
- this.fireEvent("dblclick", this.node, e);
- }
- },
-
- onOver : function(e){
- this.addClass('x-tree-node-over');
- },
-
- onOut : function(e){
- this.removeClass('x-tree-node-over');
- },
-
- // private
- onCheckChange : function(){
- var checked = this.checkbox.checked;
- // fix for IE6
- this.checkbox.defaultChecked = checked;
- this.node.attributes.checked = checked;
- this.fireEvent('checkchange', this.node, checked);
- },
-
- // private
- ecClick : function(e){
- if(!this.animating && this.node.isExpandable()){
- this.node.toggle();
- }
- },
-
- // private
- startDrop : function(){
- this.dropping = true;
- },
-
- // delayed drop so the click event doesn't get fired on a drop
- endDrop : function(){
- setTimeout(function(){
- this.dropping = false;
- }.createDelegate(this), 50);
- },
-
- // private
- expand : function(){
- this.updateExpandIcon();
- this.ctNode.style.display = "";
- },
-
- // private
- focus : function(){
- if(!this.node.preventHScroll){
- try{this.anchor.focus();
- }catch(e){}
- }else{
- try{
- var noscroll = this.node.getOwnerTree().getTreeEl().dom;
- var l = noscroll.scrollLeft;
- this.anchor.focus();
- noscroll.scrollLeft = l;
- }catch(e){}
- }
- },
-
-/**
- * Sets the checked status of the tree node to the passed value, or, if no value was passed,
- * toggles the checked status. If the node was rendered with no checkbox, this has no effect.
- * @param {Boolean} (optional) The new checked status.
- */
- toggleCheck : function(value){
- var cb = this.checkbox;
- if(cb){
- cb.checked = (value === undefined ? !cb.checked : value);
- this.onCheckChange();
- }
- },
-
- // private
- blur : function(){
- try{
- this.anchor.blur();
- }catch(e){}
- },
-
- // private
- animExpand : function(callback){
- var ct = Ext.get(this.ctNode);
- ct.stopFx();
- if(!this.node.isExpandable()){
- this.updateExpandIcon();
- this.ctNode.style.display = "";
- Ext.callback(callback);
- return;
- }
- this.animating = true;
- this.updateExpandIcon();
-
- ct.slideIn('t', {
- callback : function(){
- this.animating = false;
- Ext.callback(callback);
- },
- scope: this,
- duration: this.node.ownerTree.duration || .25
- });
- },
-
- // private
- highlight : function(){
- var tree = this.node.getOwnerTree();
- Ext.fly(this.wrap).highlight(
- tree.hlColor || "C3DAF9",
- {endColor: tree.hlBaseColor}
- );
- },
-
- // private
- collapse : function(){
- this.updateExpandIcon();
- this.ctNode.style.display = "none";
- },
-
- // private
- animCollapse : function(callback){
- var ct = Ext.get(this.ctNode);
- ct.enableDisplayMode('block');
- ct.stopFx();
-
- this.animating = true;
- this.updateExpandIcon();
-
- ct.slideOut('t', {
- callback : function(){
- this.animating = false;
- Ext.callback(callback);
- },
- scope: this,
- duration: this.node.ownerTree.duration || .25
- });
- },
-
- // private
- getContainer : function(){
- return this.ctNode;
- },
-
-/**
- * Returns the element which encapsulates this node.
- * @return {HtmlElement} The DOM element. The default implementation uses a <li>
.
- */
- getEl : function(){
- return this.wrap;
- },
-
- // private
- appendDDGhost : function(ghostNode){
- ghostNode.appendChild(this.elNode.cloneNode(true));
- },
-
- // private
- getDDRepairXY : function(){
- return Ext.lib.Dom.getXY(this.iconNode);
- },
-
- // private
- onRender : function(){
- this.render();
- },
-
- // private
- render : function(bulkRender){
- var n = this.node, a = n.attributes;
- var targetNode = n.parentNode ?
- n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
-
- if(!this.rendered){
- this.rendered = true;
-
- this.renderElements(n, a, targetNode, bulkRender);
-
- if(a.qtip){
- if(this.textNode.setAttributeNS){
- this.textNode.setAttributeNS("ext", "qtip", a.qtip);
- if(a.qtipTitle){
- this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
- }
- }else{
- this.textNode.setAttribute("ext:qtip", a.qtip);
- if(a.qtipTitle){
- this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
- }
- }
- }else if(a.qtipCfg){
- a.qtipCfg.target = Ext.id(this.textNode);
- Ext.QuickTips.register(a.qtipCfg);
- }
- this.initEvents();
- if(!this.node.expanded){
- this.updateExpandIcon(true);
- }
- }else{
- if(bulkRender === true) {
- targetNode.appendChild(this.wrap);
- }
- }
- },
-
- // private
- renderElements : function(n, a, targetNode, bulkRender){
- // add some indent caching, this helps performance when rendering a large tree
- this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
-
- var cb = Ext.isBoolean(a.checked),
- nel,
- href = a.href ? a.href : Ext.isGecko ? "" : "#",
- buf = ['
- * If you are customizing the Tree's user interface, you
- * may need to extend this class, but you should never need to instantiate this class.
- */
-Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
- // private
- render : function(){
- if(!this.rendered){
- var targetNode = this.node.ownerTree.innerCt.dom;
- this.node.expanded = true;
- targetNode.innerHTML = '
+ * If you are customizing the Tree's user interface, you
+ * may need to extend this class, but you should never need to instantiate this class.
+ *
+ * This class provides access to the user interface components of an Ext TreeNode, through
+ * {@link Ext.tree.TreeNode#getUI}
+ */
+Ext.tree.TreeNodeUI = Ext.extend(Object, {
+
+ constructor : function(node){
+ Ext.apply(this, {
+ node: node,
+ rendered: false,
+ animating: false,
+ wasLeaf: true,
+ ecc: 'x-tree-ec-icon x-tree-elbow',
+ emptyIcon: Ext.BLANK_IMAGE_URL
+ });
+ },
+
+ // private
+ removeChild : function(node){
+ if(this.rendered){
+ this.ctNode.removeChild(node.ui.getEl());
+ }
+ },
+
+ // private
+ beforeLoad : function(){
+ this.addClass("x-tree-node-loading");
+ },
+
+ // private
+ afterLoad : function(){
+ this.removeClass("x-tree-node-loading");
+ },
+
+ // private
+ onTextChange : function(node, text, oldText){
+ if(this.rendered){
+ this.textNode.innerHTML = text;
+ }
+ },
+
+ // private
+ onIconClsChange : function(node, cls, oldCls){
+ if(this.rendered){
+ Ext.fly(this.iconNode).replaceClass(oldCls, cls);
+ }
+ },
+
+ // private
+ onIconChange : function(node, icon){
+ if(this.rendered){
+ //'',
+ var empty = Ext.isEmpty(icon);
+ this.iconNode.src = empty ? this.emptyIcon : icon;
+ Ext.fly(this.iconNode)[empty ? 'removeClass' : 'addClass']('x-tree-node-inline-icon');
+ }
+ },
+
+ // private
+ onTipChange : function(node, tip, title){
+ if(this.rendered){
+ var hasTitle = Ext.isDefined(title);
+ if(this.textNode.setAttributeNS){
+ this.textNode.setAttributeNS("ext", "qtip", tip);
+ if(hasTitle){
+ this.textNode.setAttributeNS("ext", "qtitle", title);
+ }
+ }else{
+ this.textNode.setAttribute("ext:qtip", tip);
+ if(hasTitle){
+ this.textNode.setAttribute("ext:qtitle", title);
+ }
+ }
+ }
+ },
+
+ // private
+ onHrefChange : function(node, href, target){
+ if(this.rendered){
+ this.anchor.href = this.getHref(href);
+ if(Ext.isDefined(target)){
+ this.anchor.target = target;
+ }
+ }
+ },
+
+ // private
+ onClsChange : function(node, cls, oldCls){
+ if(this.rendered){
+ Ext.fly(this.elNode).replaceClass(oldCls, cls);
+ }
+ },
+
+ // private
+ onDisableChange : function(node, state){
+ this.disabled = state;
+ if (this.checkbox) {
+ this.checkbox.disabled = state;
+ }
+ this[state ? 'addClass' : 'removeClass']('x-tree-node-disabled');
+ },
+
+ // private
+ onSelectedChange : function(state){
+ if(state){
+ this.focus();
+ this.addClass("x-tree-selected");
+ }else{
+ //this.blur();
+ this.removeClass("x-tree-selected");
+ }
+ },
+
+ // private
+ onMove : function(tree, node, oldParent, newParent, index, refNode){
+ this.childIndent = null;
+ if(this.rendered){
+ var targetNode = newParent.ui.getContainer();
+ if(!targetNode){//target not rendered
+ this.holder = document.createElement("div");
+ this.holder.appendChild(this.wrap);
+ return;
+ }
+ var insertBefore = refNode ? refNode.ui.getEl() : null;
+ if(insertBefore){
+ targetNode.insertBefore(this.wrap, insertBefore);
+ }else{
+ targetNode.appendChild(this.wrap);
+ }
+ this.node.renderIndent(true, oldParent != newParent);
+ }
+ },
+
+/**
+ * Adds one or more CSS classes to the node's UI element.
+ * Duplicate classes are automatically filtered out.
+ * @param {String/Array} className The CSS class to add, or an array of classes
+ */
+ addClass : function(cls){
+ if(this.elNode){
+ Ext.fly(this.elNode).addClass(cls);
+ }
+ },
+
+/**
+ * Removes one or more CSS classes from the node's UI element.
+ * @param {String/Array} className The CSS class to remove, or an array of classes
+ */
+ removeClass : function(cls){
+ if(this.elNode){
+ Ext.fly(this.elNode).removeClass(cls);
+ }
+ },
+
+ // private
+ remove : function(){
+ if(this.rendered){
+ this.holder = document.createElement("div");
+ this.holder.appendChild(this.wrap);
+ }
+ },
+
+ // private
+ fireEvent : function(){
+ return this.node.fireEvent.apply(this.node, arguments);
+ },
+
+ // private
+ initEvents : function(){
+ this.node.on("move", this.onMove, this);
+
+ if(this.node.disabled){
+ this.onDisableChange(this.node, true);
+ }
+ if(this.node.hidden){
+ this.hide();
+ }
+ var ot = this.node.getOwnerTree();
+ var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
+ if(dd && (!this.node.isRoot || ot.rootVisible)){
+ Ext.dd.Registry.register(this.elNode, {
+ node: this.node,
+ handles: this.getDDHandles(),
+ isHandle: false
+ });
+ }
+ },
+
+ // private
+ getDDHandles : function(){
+ return [this.iconNode, this.textNode, this.elNode];
+ },
+
+/**
+ * Hides this node.
+ */
+ hide : function(){
+ this.node.hidden = true;
+ if(this.wrap){
+ this.wrap.style.display = "none";
+ }
+ },
+
+/**
+ * Shows this node.
+ */
+ show : function(){
+ this.node.hidden = false;
+ if(this.wrap){
+ this.wrap.style.display = "";
+ }
+ },
+
+ // private
+ onContextMenu : function(e){
+ if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
+ e.preventDefault();
+ this.focus();
+ this.fireEvent("contextmenu", this.node, e);
+ }
+ },
+
+ // private
+ onClick : function(e){
+ if(this.dropping){
+ e.stopEvent();
+ return;
+ }
+ if(this.fireEvent("beforeclick", this.node, e) !== false){
+ var a = e.getTarget('a');
+ if(!this.disabled && this.node.attributes.href && a){
+ this.fireEvent("click", this.node, e);
+ return;
+ }else if(a && e.ctrlKey){
+ e.stopEvent();
+ }
+ e.preventDefault();
+ if(this.disabled){
+ return;
+ }
+
+ if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
+ this.node.toggle();
+ }
+
+ this.fireEvent("click", this.node, e);
+ }else{
+ e.stopEvent();
+ }
+ },
+
+ // private
+ onDblClick : function(e){
+ e.preventDefault();
+ if(this.disabled){
+ return;
+ }
+ if(this.fireEvent("beforedblclick", this.node, e) !== false){
+ if(this.checkbox){
+ this.toggleCheck();
+ }
+ if(!this.animating && this.node.isExpandable()){
+ this.node.toggle();
+ }
+ this.fireEvent("dblclick", this.node, e);
+ }
+ },
+
+ onOver : function(e){
+ this.addClass('x-tree-node-over');
+ },
+
+ onOut : function(e){
+ this.removeClass('x-tree-node-over');
+ },
+
+ // private
+ onCheckChange : function(){
+ var checked = this.checkbox.checked;
+ // fix for IE6
+ this.checkbox.defaultChecked = checked;
+ this.node.attributes.checked = checked;
+ this.fireEvent('checkchange', this.node, checked);
+ },
+
+ // private
+ ecClick : function(e){
+ if(!this.animating && this.node.isExpandable()){
+ this.node.toggle();
+ }
+ },
+
+ // private
+ startDrop : function(){
+ this.dropping = true;
+ },
+
+ // delayed drop so the click event doesn't get fired on a drop
+ endDrop : function(){
+ setTimeout(function(){
+ this.dropping = false;
+ }.createDelegate(this), 50);
+ },
+
+ // private
+ expand : function(){
+ this.updateExpandIcon();
+ this.ctNode.style.display = "";
+ },
+
+ // private
+ focus : function(){
+ if(!this.node.preventHScroll){
+ try{this.anchor.focus();
+ }catch(e){}
+ }else{
+ try{
+ var noscroll = this.node.getOwnerTree().getTreeEl().dom;
+ var l = noscroll.scrollLeft;
+ this.anchor.focus();
+ noscroll.scrollLeft = l;
+ }catch(e){}
+ }
+ },
+
+/**
+ * Sets the checked status of the tree node to the passed value, or, if no value was passed,
+ * toggles the checked status. If the node was rendered with no checkbox, this has no effect.
+ * @param {Boolean} value (optional) The new checked status.
+ */
+ toggleCheck : function(value){
+ var cb = this.checkbox;
+ if(cb){
+ cb.checked = (value === undefined ? !cb.checked : value);
+ this.onCheckChange();
+ }
+ },
+
+ // private
+ blur : function(){
+ try{
+ this.anchor.blur();
+ }catch(e){}
+ },
+
+ // private
+ animExpand : function(callback){
+ var ct = Ext.get(this.ctNode);
+ ct.stopFx();
+ if(!this.node.isExpandable()){
+ this.updateExpandIcon();
+ this.ctNode.style.display = "";
+ Ext.callback(callback);
+ return;
+ }
+ this.animating = true;
+ this.updateExpandIcon();
+
+ ct.slideIn('t', {
+ callback : function(){
+ this.animating = false;
+ Ext.callback(callback);
+ },
+ scope: this,
+ duration: this.node.ownerTree.duration || .25
+ });
+ },
+
+ // private
+ highlight : function(){
+ var tree = this.node.getOwnerTree();
+ Ext.fly(this.wrap).highlight(
+ tree.hlColor || "C3DAF9",
+ {endColor: tree.hlBaseColor}
+ );
+ },
+
+ // private
+ collapse : function(){
+ this.updateExpandIcon();
+ this.ctNode.style.display = "none";
+ },
+
+ // private
+ animCollapse : function(callback){
+ var ct = Ext.get(this.ctNode);
+ ct.enableDisplayMode('block');
+ ct.stopFx();
+
+ this.animating = true;
+ this.updateExpandIcon();
+
+ ct.slideOut('t', {
+ callback : function(){
+ this.animating = false;
+ Ext.callback(callback);
+ },
+ scope: this,
+ duration: this.node.ownerTree.duration || .25
+ });
+ },
+
+ // private
+ getContainer : function(){
+ return this.ctNode;
+ },
+
+/**
+ * Returns the element which encapsulates this node.
+ * @return {HtmlElement} The DOM element. The default implementation uses a <li>
.
+ */
+ getEl : function(){
+ return this.wrap;
+ },
+
+ // private
+ appendDDGhost : function(ghostNode){
+ ghostNode.appendChild(this.elNode.cloneNode(true));
+ },
+
+ // private
+ getDDRepairXY : function(){
+ return Ext.lib.Dom.getXY(this.iconNode);
+ },
+
+ // private
+ onRender : function(){
+ this.render();
+ },
+
+ // private
+ render : function(bulkRender){
+ var n = this.node, a = n.attributes;
+ var targetNode = n.parentNode ?
+ n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
+
+ if(!this.rendered){
+ this.rendered = true;
+
+ this.renderElements(n, a, targetNode, bulkRender);
+
+ if(a.qtip){
+ this.onTipChange(n, a.qtip, a.qtipTitle);
+ }else if(a.qtipCfg){
+ a.qtipCfg.target = Ext.id(this.textNode);
+ Ext.QuickTips.register(a.qtipCfg);
+ }
+ this.initEvents();
+ if(!this.node.expanded){
+ this.updateExpandIcon(true);
+ }
+ }else{
+ if(bulkRender === true) {
+ targetNode.appendChild(this.wrap);
+ }
+ }
+ },
+
+ // private
+ renderElements : function(n, a, targetNode, bulkRender){
+ // add some indent caching, this helps performance when rendering a large tree
+ this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
+
+ var cb = Ext.isBoolean(a.checked),
+ nel,
+ href = this.getHref(a.href),
+ buf = ['
+ * If you are customizing the Tree's user interface, you
+ * may need to extend this class, but you should never need to instantiate this class.
+ */
+Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
+ // private
+ render : function(){
+ if(!this.rendered){
+ var targetNode = this.node.ownerTree.innerCt.dom;
+ this.node.expanded = true;
+ targetNode.innerHTML = '