modx.tree.checkbox.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /**
  2. * A checkbox-driven tree
  3. *
  4. * @class MODx.tree.CheckboxTree
  5. * @extends Ext.tree.TreePanel
  6. * @param {Object} config An object of config properties
  7. * @xtype tree-checkbox
  8. */
  9. MODx.tree.CheckboxTree = function(config) {
  10. config = config || {};
  11. Ext.applyIf(config,{
  12. rootVisible: false
  13. ,autoScroll: true
  14. ,autoHeight: true
  15. ,cls: 'modx-tree'
  16. });
  17. var tb = this.getToolbar();
  18. if (config.tbar && config.useDefaultToolbar) {
  19. for (var i=0;i<config.tbar.length;i=i+1) {
  20. tb.push(config.tbar[i]);
  21. }
  22. } else if (config.tbar) {
  23. tb = config.tbar;
  24. }
  25. Ext.apply(config,{tbar: tb});
  26. this.config = config;
  27. this.setup();
  28. };
  29. Ext.extend(MODx.tree.CheckboxTree,Ext.tree.TreePanel,{
  30. menu: {}
  31. ,root: null
  32. ,setup: function() {
  33. var root;
  34. if (this.config.url) {
  35. this.config.loader = new Ext.tree.TreeLoader({
  36. preloadChildren: false
  37. ,baseAttrs: {
  38. uiProvider:MODx.tree.CheckboxNodeUI
  39. }
  40. ,dataUrl: this.config.url
  41. });
  42. root = new Ext.tree.AsyncTreeNode({
  43. text: this.config.rootName || ''
  44. ,draggable: false
  45. ,id: this.config.rootId || 'root'
  46. });
  47. } else {
  48. this.config.loader = new Ext.tree.TreeLoader({
  49. preloadChildren: true
  50. ,baseAttrs: {
  51. uiProvider: MODx.tree.CheckboxNodeUI
  52. }
  53. });
  54. root = new Ext.tree.TreeNode({
  55. text: this.config.rootName || ''
  56. ,draggable: false
  57. ,id: this.config.rootId || 'root'
  58. ,children: this.config.data || []
  59. });
  60. }
  61. MODx.tree.CheckboxTree.superclass.constructor.call(this,this.config);
  62. this.addEvents({
  63. refresh: true
  64. });
  65. this.getLoader().doPreload(root);
  66. this.setRootNode(root);
  67. this.cm = new Ext.menu.Menu(Ext.id(),{});
  68. this.on('contextmenu',this._showContextMenu,this);
  69. this.treestateId = Ext.id();
  70. this.on('click',function(x) {
  71. Ext.state.Manager.set(this.treestateId,x.getPath());
  72. },this);
  73. }
  74. ,encode: function(node) {
  75. if (!node) { node = this.getRootNode(); }
  76. var _encode = function(node) {
  77. var resultNode = {};
  78. var kids = node.childNodes;
  79. for (var i = 0;i < kids.length;i=i+1) {
  80. var n = kids[i];
  81. resultNode[n.id] = {
  82. id: n.id
  83. ,checked: n.ui.isChecked()
  84. ,type: n.attributes.type || ''
  85. ,data: n.attributes.data || {}
  86. ,children: _encode(n)
  87. };
  88. }
  89. return resultNode;
  90. };
  91. var nodes = _encode(node);
  92. return Ext.encode(nodes);
  93. }
  94. ,_showContextMenu: function(node,e) {
  95. node.select();
  96. this.cm.activeNode = node;
  97. var nar = node.id.split('_');
  98. this.cm.removeAll();
  99. if (node.attributes.menu && node.attributes.menu.items) {
  100. this.addContextMenuItem(node.attributes.menu.items);
  101. this.cm.show(node.ui.getEl(),'t?');
  102. }
  103. }
  104. ,addContextMenuItem: function(items) {
  105. var a = items, l = a.length;
  106. for(var i = 0; i < l; i++) {
  107. a[i].scope = this;
  108. this.cm.add(a[i]);
  109. }
  110. }
  111. ,removeChildren: function(node) {
  112. while(node.firstChild){
  113. var c = node.firstChild;
  114. node.removeChild(c);
  115. c.destroy();
  116. }
  117. }
  118. ,loadRemoteData: function(data) {
  119. this.removeChildren(this.getRootNode());
  120. for (var c in data) {
  121. if (typeof data[c] === 'object') {
  122. this.getRootNode().appendChild(data[c]);
  123. }
  124. }
  125. }
  126. ,removeNode: function(id) {
  127. var node = this.getNodeById(id);
  128. if (node) {
  129. node.remove();
  130. }
  131. }
  132. ,removeActiveNode: function() {
  133. this.cm.activeNode.remove();
  134. }
  135. ,refresh: function() {
  136. var treeState = Ext.state.Manager.get(this.treestateId);
  137. var root = this.getRootNode();
  138. if (this.config.url) { root.reload(); }
  139. if (treeState === undefined) {
  140. this.root.expand(null,null);
  141. } else {
  142. this.expandPath(treeState,null);
  143. }
  144. this.fireEvent('refresh',{root:this.getRootNode()});
  145. return true;
  146. }
  147. ,expand: function() {
  148. if (this.root) {
  149. this.root.expand();
  150. this.root.expandChildNodes();
  151. }
  152. }
  153. ,collapse: function() {
  154. if (this.root) {
  155. this.root.collapseChildNodes();
  156. this.root.collapse();
  157. }
  158. }
  159. ,getToolbar: function() {
  160. var iu = MODx.config.template_url+'images/restyle/icons/';
  161. return [{
  162. icon: iu+'arrow_down.png'
  163. ,cls: 'x-btn-icon arrow_down'
  164. ,scope: this
  165. ,tooltip: {text: _('tree_expand')}
  166. ,handler: this.expand
  167. },{
  168. icon: iu+'arrow_up.png'
  169. ,cls: 'x-btn-icon arrow_up'
  170. ,scope: this
  171. ,tooltip: {text: _('tree_collapse')}
  172. ,handler: this.collapse
  173. },{
  174. icon: iu+'refresh.png'
  175. ,cls: 'x-btn-icon refresh'
  176. ,scope: this
  177. ,tooltip: {text: _('tree_refresh')}
  178. ,handler: this.refresh
  179. }];
  180. }
  181. });
  182. Ext.reg('tree-checkbox',MODx.tree.CheckboxTree);
  183. /* checkbox node ui */
  184. MODx.tree.CheckboxNodeUI=Ext.extend(Ext.tree.TreeNodeUI,{onCheckChange:function(){MODx.tree.CheckboxNodeUI.superclass.onCheckChange.apply(this,arguments);var p;if((p=this.node.parentNode)&&p.getUI().updateParent){p.getUI().updateParent()}},toggleCheck:function(){var a=MODx.tree.CheckboxNodeUI.superclass.toggleCheck.apply(this,arguments);this.updateChild(a);return a},renderElements:function(n,a,b,c){MODx.tree.CheckboxNodeUI.superclass.renderElements.apply(this,arguments);this.updateChild(this.node.attributes.checked)},updateParent:function(){var a;this.node.eachChild(function(n){if(a===undefined){a=n.attributes.checked}else if(a!==n.attributes.checked){a=this.grayedValue;return false}},this);this.toggleCheck(a)},updateChild:function(a){if(this.checkbox&&false){if(a===true){Ext.fly(this.ctNode).replaceClass('x-tree-branch-unchecked','x-tree-branch-checked')}else if(a===false){Ext.fly(this.ctNode).replaceClass('x-tree-branch-checked','x-tree-branch-unchecked')}else{Ext.fly(this.ctNode).removeClass(['x-tree-branch-checked','x-tree-branch-unchecked'])}}}});Ext.override(Ext.tree.TreeNodeUI,{grayedValue:null,onDisableChange:function(a,b){this.disabled=b;this[b?'addClass':'removeClass']("x-tree-node-disabled")},initEvents:function(){this.node.on("move",this.onMove,this);this.addClass('x-tree-checkboxnode');if(this.node.disabled){this.addClass("x-tree-node-disabled")}if(this.node.hidden){this.hide()}var a=this.node.getOwnerTree();var b=a.enableDD||a.enableDrag||a.enableDrop;if(b&&(!this.node.isRoot||a.rootVisible)){Ext.dd.Registry.register(this.elNode,{node:this.node,handles:this.getDDHandles(),isHandle:false})}},onDblClick:function(e){e.preventDefault();if(this.disabled){return}if(!this.animating&&this.node.isExpandable()){this.node.toggle()}this.fireEvent("dblclick",this.node,e)},onCheckChange:function(){var a=this.isChecked();this.node.attributes.checked=a;this.fireEvent('checkchange',this.node,a)},toggleCheck:function(a){var b=this.checkbox;if(!b){return false}if(a===undefined){a=this.isChecked()===false}if(a===true){Ext.fly(b).replaceClass('x-tree-node-grayed','x-tree-node-checked')}else if(a!==false){Ext.fly(b).replaceClass('x-tree-node-checked','x-tree-node-grayed')}else{Ext.fly(b).removeClass(['x-tree-node-checked','x-tree-node-grayed'])}this.onCheckChange();return a},onCheckboxClick:function(){if(!this.disabled){this.toggleCheck()}},onCheckboxOver:function(){this.addClass('x-tree-checkbox-over')},onCheckboxOut:function(){this.removeClass('x-tree-checkbox-over')},onCheckboxDown:function(){this.addClass('x-tree-checkbox-down')},onCheckboxUp:function(){this.removeClass('x-tree-checkbox-down')},renderElements:function(n,a,b,c){this.indentMarkup=n.parentNode?n.parentNode.ui.getChildIndent():'';var d=a.checked!==undefined;var e=a.href?a.href:Ext.isGecko?"":"#";var f=['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ',a.cls,'" unselectable="on">','<span class="x-tree-node-indent">',this.indentMarkup,"</span>",'<img src="',this.emptyIcon,'" class="x-tree-ec-icon x-tree-elbow" />','<img src="',a.icon||this.emptyIcon,'" class="x-tree-node-icon',(a.icon?" x-tree-node-inline-icon":""),(a.iconCls?" "+a.iconCls:""),'" unselectable="on" />',d?('<img src="'+this.emptyIcon+'" class="x-tree-checkbox'+(a.checked===true?' x-tree-node-checked':(a.checked!==false?' x-tree-node-grayed':''))+'" />'):'','<a hidefocus="on" class="x-tree-node-anchor" href="',e,'" tabIndex="1" ',(a.hrefTarget?' target="'+a.hrefTarget+'"':""),'>','<span unselectable="on">',n.text,'</span>','</a>','</div><ul class="x-tree-node-ct" style="display:none;"></ul>',"</li>"].join('');var g;if(c!==true&&n.nextSibling&&(g=n.nextSibling.ui.getEl())){this.wrap=Ext.DomHelper.insertHtml("beforeBegin",g,f)}else{this.wrap=Ext.DomHelper.insertHtml("beforeEnd",b,f)}this.elNode=this.wrap.childNodes[0];this.ctNode=this.wrap.childNodes[1];var h=this.elNode.childNodes;this.indentNode=h[0];this.ecNode=h[1];this.iconNode=h[2];var i=3;if(d){this.checkbox=h[3];i=i+1}this.anchor=h[i];this.textNode=h[i].firstChild;var z;if(a.description&&this.textNode){z=new Ext.ToolTip({target:this.textNode,html:a.description})}},isChecked:function(){return this.checkbox?(Ext.fly(this.checkbox).hasClass('x-tree-node-checked')?true:Ext.fly(this.checkbox).hasClass('x-tree-node-grayed')?this.grayedValue:false):false}});Ext.override(Ext.tree.TreeEventModel,{initEvents:function(){var a=this.tree.getTreeEl();a.on('click',this.delegateClick,this);if(this.tree.trackMouseOver!==false){a.on('mouseover',this.delegateOver,this);a.on('mouseout',this.delegateOut,this)}a.on('mousedown',this.delegateDown,this);a.on('mouseup',this.delegateUp,this);a.on('dblclick',this.delegateDblClick,this);a.on('contextmenu',this.delegateContextMenu,this)},delegateOver:function(e,t){if(!this.beforeEvent(e)){return}if(this.lastEcOver){this.onIconOut(e,this.lastEcOver);delete this.lastEcOver}if(this.lastCbOver){this.onCheckboxOut(e,this.lastCbOver);delete this.lastCbOver}if(e.getTarget('.x-tree-ec-icon',1)){this.lastEcOver=this.getNode(e);this.onIconOver(e,this.lastEcOver)}else if(e.getTarget('.x-tree-checkbox',1)){this.lastCbOver=this.getNode(e);this.onCheckboxOver(e,this.lastCbOver)}t=this.getNodeTarget(e);if(t){this.onNodeOver(e,this.getNode(e))}},delegateOut:function(e,t){if(!this.beforeEvent(e)){return}var n;if(e.getTarget('.x-tree-ec-icon',1)){n=this.getNode(e);this.onIconOut(e,n);if(n===this.lastEcOver){delete this.lastEcOver}}else if(e.getTarget('.x-tree-checkbox',1)){n=this.getNode(e);this.onCheckboxOut(e,n);if(n===this.lastCbOver){delete this.lastCbOver}}t=this.getNodeTarget(e);if(t&&!e.within(t,true)){this.onNodeOut(e,this.getNode(e))}},delegateDown:function(e,t){if(!this.beforeEvent(e)){return}if(e.getTarget('.x-tree-checkbox',1)){this.onCheckboxDown(e,this.getNode(e))}},delegateUp:function(e,t){if(!this.beforeEvent(e)){return}if(e.getTarget('.x-tree-checkbox',1)){this.onCheckboxUp(e,this.getNode(e))}},delegateOut:function(e,t){if(!this.beforeEvent(e)){return}var n;if(e.getTarget('.x-tree-ec-icon',1)){n=this.getNode(e);this.onIconOut(e,n);if(n===this.lastEcOver){delete this.lastEcOver}}else if(e.getTarget('.x-tree-checkbox',1)){n=this.getNode(e);this.onCheckboxOut(e,n);if(n===this.lastCbOver){delete this.lastCbOver}}if((t=this.getNodeTarget(e))&&!e.within(t,true)){this.onNodeOut(e,this.getNode(e))}},delegateClick:function(e,t){if(!this.beforeEvent(e)){return}if(e.getTarget('.x-tree-checkbox',1)){this.onCheckboxClick(e,this.getNode(e))}else if(e.getTarget('.x-tree-ec-icon',1)){this.onIconClick(e,this.getNode(e))}else if(this.getNodeTarget(e)){this.onNodeClick(e,this.getNode(e))}},onCheckboxClick:function(e,a){a.ui.onCheckboxClick()},onCheckboxOver:function(e,a){a.ui.onCheckboxOver()},onCheckboxOut:function(e,a){a.ui.onCheckboxOut()},onCheckboxDown:function(e,a){a.ui.onCheckboxDown()},onCheckboxUp:function(e,a){a.ui.onCheckboxUp()}});