modx.tree.column.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /* column tree extension */
  2. Ext.ns('Ext.ux.tree');Ext.ux.tree.ColumnTree=Ext.extend(Ext.tree.TreePanel,{lines:false,borderWidth:Ext.isBorderBox?0:2,cls:'x-column-tree',onRender:function(){Ext.tree.ColumnTree.superclass.onRender.apply(this,arguments);this.headers=this.header.createChild({cls:'x-tree-headers'});var a=this.columns,c;var b=0;var d=19;for(var i=0,len=a.length;i<len;i++){c=a[i];b+=c.width;this.headers.createChild({cls:'x-tree-hd '+(c.cls?c.cls+'-hd':''),cn:{cls:'x-tree-hd-text',html:c.header},style:'width:'+(c.width-this.borderWidth)+'px;'})}this.headers.createChild({cls:'x-clear'});this.headers.setWidth(b+d);this.innerCt.setWidth(b)}});Ext.reg('columntree',Ext.ux.tree.ColumnTree);Ext.tree.ColumnTree=Ext.ux.tree.ColumnTree;Ext.ux.tree.ColumnNodeUI=Ext.extend(Ext.tree.TreeNodeUI,{focus:Ext.emptyFn,renderElements:function(n,a,b,d){this.indentMarkup=n.parentNode?n.parentNode.ui.getChildIndent():'';var t=n.getOwnerTree();var e=t.columns;var f=t.borderWidth;var c=e[0];var g=['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf ',a.cls,'">','<div class="x-tree-col" style="width:',c.width-f,'px;">','<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">','<a hidefocus="on" class="x-tree-node-anchor" href="',a.href?a.href:"#",'" tabIndex="1" ',a.hrefTarget?' target="'+a.hrefTarget+'"':"",'>','<span unselectable="on">',n.text||(c.renderer?c.renderer(a[c.dataIndex],n,a):a[c.dataIndex]),"</span></a>","</div>"];for(var i=1,len=e.length;i<len;i++){c=e[i];g.push('<div class="x-tree-col ',(c.cls?c.cls:''),'" style="width:',c.width-f,'px;">','<div class="x-tree-col-text">',(c.renderer?c.renderer(a[c.dataIndex],n,a):a[c.dataIndex]),"</div>","</div>")}g.push('<div class="x-clear"></div></div>','<ul class="x-tree-node-ct" style="display:none;"></ul>',"</li>");if(d!==true&&n.nextSibling&&n.nextSibling.ui.getEl()){this.wrap=Ext.DomHelper.insertHtml("beforeBegin",n.nextSibling.ui.getEl(),g.join(""))}else{this.wrap=Ext.DomHelper.insertHtml("beforeEnd",b,g.join(""))}this.elNode=this.wrap.childNodes[0];this.ctNode=this.wrap.childNodes[1];var h=this.elNode.firstChild.childNodes;this.indentNode=h[0];this.ecNode=h[1];this.iconNode=h[2];this.anchor=h[3];this.textNode=h[3].firstChild}});Ext.tree.ColumnNodeUI=Ext.ux.tree.ColumnNodeUI;
  3. /**
  4. * @class MODx.tree.ColumnTree
  5. * @extends Ext.tree.ColumnTree
  6. * @param {Object} config An object of configuration properties
  7. * @xtype tree-column
  8. */
  9. MODx.tree.ColumnTree = function(config) {
  10. config = config || {};
  11. Ext.applyIf(config,{
  12. rootVisible: false
  13. ,autoScroll: true
  14. ,autoHeight: true
  15. ,root: {
  16. nodeType: 'async'
  17. ,text: config.rootText || ''
  18. }
  19. ,loader: new Ext.tree.TreeLoader({
  20. dataUrl: config.url
  21. ,baseParams: config.baseParams || {}
  22. ,uiProviders: {
  23. 'col': Ext.tree.ColumnNodeUI
  24. }
  25. ,listeners: config.loaderListeners || {
  26. 'beforeload': {fn:function(treeLoader, node) {
  27. if (node.attributes.class_key) {
  28. var bp = {};
  29. Ext.apply(bp,this.config.baseParams);
  30. Ext.apply(bp,node.attributes);
  31. bp.loader = null; bp.uiProvider = null;
  32. this.getLoader().baseParams = bp;
  33. }
  34. },scope:this}
  35. }
  36. })
  37. ,tbar: this._getToolbar()
  38. ,menuConfig: { defaultAlign: 'tl-b?' ,enableScrolling: false }
  39. });
  40. MODx.tree.ColumnTree.superclass.constructor.call(this,config);
  41. this.on('contextmenu',this._showContextMenu,this);
  42. this.on('nodedragover',this._handleDrop,this);
  43. this.on('nodedrop',this._handleDrag,this);
  44. this.cm = new Ext.menu.Menu(config.menuConfig);
  45. this.config = config;
  46. };
  47. Ext.extend(MODx.tree.ColumnTree,Ext.tree.ColumnTree,{
  48. windows: {}
  49. /**
  50. * Shows the current context menu.
  51. * @param {Ext.tree.TreeNode} node The
  52. * @param {Ext.EventObject} e The event object run.
  53. */
  54. ,_showContextMenu: function(node,e) {
  55. node.select();
  56. this.cm.activeNode = node;
  57. this.cm.record = node.attributes;
  58. /*this.cm.record.id = node.attributes.pk;*/
  59. this.cm.removeAll();
  60. if (node.attributes.menu && node.attributes.menu.items) {
  61. this._addContextMenuItem(node.attributes.menu.items);
  62. this.cm.show(node.ui.getEl(),'t?');
  63. }
  64. }
  65. /**
  66. * Add context menu items to the tree.
  67. * @param {Object, Array} items Either an Object config or array of Object configs.
  68. */
  69. ,_addContextMenuItem: function(items) {
  70. var a = items, l = a.length;
  71. for(var i = 0; i < l; i++) {
  72. a[i].scope = this;
  73. this.cm.add(a[i]);
  74. }
  75. }
  76. /**
  77. * Handles all drag events into the tree.
  78. * @param {Object} dropEvent The node dropped on the parent node.
  79. */
  80. ,_handleDrag: function(dropEvent) {
  81. Ext.Msg.show({
  82. title: _('please_wait')
  83. ,msg: _('saving')
  84. ,width: 240
  85. ,progress:true
  86. ,closable:false
  87. });
  88. MODx.util.Progress.reset();
  89. for(var i = 1; i < 20; i++) {
  90. setTimeout('MODx.util.Progress.time('+i+','+MODx.util.Progress.id+')',i*1000);
  91. }
  92. /**
  93. * Simplify nodes into JSON format.
  94. * @param {Object} node
  95. */
  96. function simplifyNodes(node) {
  97. var resultNode = {};
  98. var kids = node.childNodes;
  99. var len = kids.length;
  100. for (var i = 0; i < len; i++) {
  101. resultNode[kids[i].id] = simplifyNodes(kids[i]);
  102. }
  103. return resultNode;
  104. }
  105. var encNodes = Ext.encode(simplifyNodes(dropEvent.tree.root));
  106. MODx.Ajax.request({
  107. url: this.config.url
  108. ,params: {
  109. data: encodeURIComponent(encNodes)
  110. ,action: this.config.sortAction || 'sort'
  111. }
  112. ,listeners: {
  113. 'success': {fn:function(r) {
  114. MODx.util.Progress.reset();
  115. Ext.Msg.hide();
  116. this.reloadNode(dropEvent.target);
  117. },scope:this}
  118. ,'failure': {fn:function(r) {
  119. MODx.util.Progress.reset();
  120. Ext.Msg.hide();
  121. MODx.form.Handler.errorJSON(r);
  122. return false;
  123. },scope:this}
  124. }
  125. });
  126. }
  127. ,reloadNode: function(n) {
  128. this.getLoader().load(n);
  129. n.expand();
  130. }
  131. /**
  132. * Abstract definition to handle drop events.
  133. */
  134. ,_handleDrop: function() { }
  135. ,loadWindow: function(btn,e,win) {
  136. var r = win.record || this.cm.record;
  137. if (!this.windows[win.xtype]) {
  138. Ext.applyIf(win,{
  139. record: win.blankValues ? {} : r
  140. ,grid: this
  141. ,listeners: {
  142. 'success': {fn:win.success || this.refresh,scope:win.scope || this}
  143. }
  144. });
  145. this.windows[win.xtype] = Ext.ComponentMgr.create(win);
  146. }
  147. if (this.windows[win.xtype].setValues && win.blankValues !== true) {
  148. this.windows[win.xtype].setValues(r);
  149. }
  150. this.windows[win.xtype].show(e.target);
  151. }
  152. ,refresh: function(func,scope,args) {
  153. this.getLoader().baseParams = this.config.baseParams;
  154. this.getRootNode().reload();
  155. this.getRootNode().expand(null,null);
  156. if (func) {
  157. scope = scope || this;
  158. args = args || [];
  159. this.getRootNode().on('load',function() { Ext.callback(func,scope,args); },scope);
  160. }
  161. return true;
  162. }
  163. ,refreshActiveNode: function() {
  164. if (this.cm.activeNode) {
  165. this.getLoader().load(this.cm.activeNode);
  166. this.cm.activeNode.expand();
  167. } else { this.refresh(); }
  168. }
  169. ,refreshParentNode: function() { this.refreshNode(this.cm.activeNode.id); }
  170. ,refreshNode: function(id,self) {
  171. var node = this.getNodeById(id);
  172. if (node) {
  173. var n = self ? node : node.parentNode;
  174. var l = this.getLoader().load(n);
  175. n.expand();
  176. }
  177. }
  178. ,_getToolbar: function() {
  179. var iu = MODx.config.template_url+'images/restyle/icons/';
  180. return [{
  181. icon: iu+'refresh.png'
  182. ,cls: 'x-btn-icon'
  183. ,tooltip: {text: _('tree_refresh')}
  184. ,handler: this.refresh
  185. ,scope: this
  186. }];
  187. }
  188. /**
  189. * Render the row to a colored Yes/No value.
  190. *
  191. * @access public
  192. * @param {Object} d The data record
  193. * @param {Object} c The dom properties
  194. * @return {String} The value to return
  195. */
  196. ,rendYesNo: function(d,c,a) {
  197. switch(d) {
  198. case '':
  199. return '-';
  200. case 0:
  201. c.css = 'red';
  202. return _('no');
  203. case 1:
  204. c.css = 'green';
  205. return _('yes');
  206. }
  207. }
  208. });
  209. Ext.reg('tree-column',MODx.tree.ColumnTree);