TreeGrid.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:13k
源码类别:

JavaScript

开发平台:

JavaScript

  1. /*!
  2.  * Ext JS Library 3.1.0
  3.  * Copyright(c) 2006-2009 Ext JS, LLC
  4.  * licensing@extjs.com
  5.  * http://www.extjs.com/license
  6.  */
  7. /**
  8.  * @class Ext.ux.tree.TreeGrid
  9.  * @extends Ext.tree.TreePanel
  10.  * 
  11.  * @xtype treegrid
  12.  */
  13. Ext.ux.tree.TreeGrid = Ext.extend(Ext.tree.TreePanel, {
  14.     rootVisible : false,
  15.     useArrows : true,
  16.     lines : false,
  17.     borderWidth : Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell
  18.     cls : 'x-treegrid',
  19.     columnResize : true,
  20.     enableSort : true,
  21.     reserveScrollOffset : true,
  22.     enableHdMenu : true,
  23.     
  24.     columnsText : 'Columns',
  25.     initComponent : function() {
  26.         if(!this.root) {
  27.             this.root = new Ext.tree.AsyncTreeNode({text: 'Root'});
  28.         }
  29.         
  30.         // initialize the loader
  31.         var l = this.loader;
  32.         if(!l){
  33.             l = new Ext.ux.tree.TreeGridLoader({
  34.                 dataUrl: this.dataUrl,
  35.                 requestMethod: this.requestMethod,
  36.                 store: this.store
  37.             });
  38.         }else if(Ext.isObject(l) && !l.load){
  39.             l = new Ext.ux.tree.TreeGridLoader(l);
  40.         }
  41.         else if(l) {
  42.             l.createNode = function(attr) {
  43.                 if (!attr.uiProvider) {
  44.                     attr.uiProvider = Ext.ux.tree.TreeGridNodeUI;
  45.                 }
  46.                 return Ext.tree.TreeLoader.prototype.createNode.call(this, attr);
  47.             }
  48.         }
  49.         this.loader = l;
  50.                             
  51.         Ext.ux.tree.TreeGrid.superclass.initComponent.call(this);                    
  52.         
  53.         this.initColumns();
  54.         
  55.         if(this.enableSort) {
  56.             this.treeGridSorter = new Ext.ux.tree.TreeGridSorter(this, this.enableSort);
  57.         }
  58.         
  59.         if(this.columnResize){
  60.             this.colResizer = new Ext.tree.ColumnResizer(this.columnResize);
  61.             this.colResizer.init(this);
  62.         }
  63.         
  64.         var c = this.columns;
  65.         if(!this.internalTpl){                                
  66.             this.internalTpl = new Ext.XTemplate(
  67.                 '<div class="x-grid3-header">',
  68.                     '<div class="x-treegrid-header-inner">',
  69.                         '<div class="x-grid3-header-offset">',
  70.                             '<table cellspacing="0" cellpadding="0" border="0"><colgroup><tpl for="columns"><col /></tpl></colgroup>',
  71.                             '<thead><tr class="x-grid3-hd-row">',
  72.                             '<tpl for="columns">',
  73.                             '<td class="x-grid3-hd x-grid3-cell x-treegrid-hd" style="text-align: {align};" id="', this.id, '-xlhd-{#}">',
  74.                                 '<div class="x-grid3-hd-inner x-treegrid-hd-inner" unselectable="on">',
  75.                                      this.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '',
  76.                                      '{header}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',
  77.                                  '</div>',
  78.                             '</td></tpl>',
  79.                             '</tr></thead>',
  80.                         '</div></table>',
  81.                     '</div></div>',
  82.                 '</div>',
  83.                 '<div class="x-treegrid-root-node">',
  84.                     '<table class="x-treegrid-root-table" cellpadding="0" cellspacing="0" style="table-layout: fixed;"></table>',
  85.                 '</div>'
  86.             );
  87.         }
  88.         
  89.         if(!this.colgroupTpl) {
  90.             this.colgroupTpl = new Ext.XTemplate(
  91.                 '<colgroup><tpl for="columns"><col style="width: {width}px"/></tpl></colgroup>'
  92.             );
  93.         }
  94.     },
  95.     initColumns : function() {
  96.         var cs = this.columns,
  97.             len = cs.length, 
  98.             columns = [],
  99.             i, c;
  100.         for(i = 0; i < len; i++){
  101.             c = cs[i];
  102.             if(!c.isColumn) {
  103.                 c.xtype = c.xtype ? (/^tg/.test(c.xtype) ? c.xtype : 'tg' + c.xtype) : 'tgcolumn';
  104.                 c = Ext.create(c);
  105.             }
  106.             c.init(this);
  107.             columns.push(c);
  108.             
  109.             if(this.enableSort !== false && c.sortable !== false) {
  110.                 c.sortable = true;
  111.                 this.enableSort = true;
  112.             }
  113.         }
  114.         this.columns = columns;
  115.     },
  116.     onRender : function(){
  117.         Ext.tree.TreePanel.superclass.onRender.apply(this, arguments);
  118.         this.el.addClass('x-treegrid');
  119.         
  120.         this.outerCt = this.body.createChild({
  121.             cls:'x-tree-root-ct x-treegrid-ct ' + (this.useArrows ? 'x-tree-arrows' : this.lines ? 'x-tree-lines' : 'x-tree-no-lines')
  122.         });
  123.         
  124.         this.internalTpl.overwrite(this.outerCt, {columns: this.columns});
  125.         
  126.         this.mainHd = Ext.get(this.outerCt.dom.firstChild);
  127.         this.innerHd = Ext.get(this.mainHd.dom.firstChild);
  128.         this.innerBody = Ext.get(this.outerCt.dom.lastChild);
  129.         this.innerCt = Ext.get(this.innerBody.dom.firstChild);
  130.         
  131.         this.colgroupTpl.insertFirst(this.innerCt, {columns: this.columns});
  132.         
  133.         if(this.hideHeaders){
  134.             this.header.dom.style.display = 'none';
  135.         }
  136.         else if(this.enableHdMenu !== false){
  137.             this.hmenu = new Ext.menu.Menu({id: this.id + '-hctx'});
  138.             if(this.enableColumnHide !== false){
  139.                 this.colMenu = new Ext.menu.Menu({id: this.id + '-hcols-menu'});
  140.                 this.colMenu.on({
  141.                     scope: this,
  142.                     beforeshow: this.beforeColMenuShow,
  143.                     itemclick: this.handleHdMenuClick
  144.                 });
  145.                 this.hmenu.add({
  146.                     itemId:'columns',
  147.                     hideOnClick: false,
  148.                     text: this.columnsText,
  149.                     menu: this.colMenu,
  150.                     iconCls: 'x-cols-icon'
  151.                 });
  152.             }
  153.             this.hmenu.on('itemclick', this.handleHdMenuClick, this);
  154.         }
  155.     },
  156.     setRootNode : function(node){
  157.         node.attributes.uiProvider = Ext.ux.tree.TreeGridRootNodeUI;        
  158.         node = Ext.ux.tree.TreeGrid.superclass.setRootNode.call(this, node);
  159.         if(this.innerCt) {
  160.             this.colgroupTpl.insertFirst(this.innerCt, {columns: this.columns});
  161.         }
  162.         return node;
  163.     },
  164.     
  165.     initEvents : function() {
  166.         Ext.ux.tree.TreeGrid.superclass.initEvents.apply(this, arguments);
  167.         this.mon(this.innerBody, 'scroll', this.syncScroll, this);
  168.         this.mon(this.innerHd, 'click', this.handleHdDown, this);
  169.         this.mon(this.mainHd, {
  170.             scope: this,
  171.             mouseover: this.handleHdOver,
  172.             mouseout: this.handleHdOut
  173.         });
  174.     },
  175.     
  176.     onResize : function(w, h) {
  177.         Ext.ux.tree.TreeGrid.superclass.onResize.apply(this, arguments);
  178.         
  179.         var bd = this.innerBody.dom;
  180.         var hd = this.innerHd.dom;
  181.         if(!bd){
  182.             return;
  183.         }
  184.         if(Ext.isNumber(h)){
  185.             bd.style.height = this.body.getHeight(true) - hd.offsetHeight + 'px';
  186.         }
  187.         if(Ext.isNumber(w)){                        
  188.             var sw = Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
  189.             if(this.reserveScrollOffset || ((bd.offsetWidth - bd.clientWidth) > 10)){
  190.                 this.setScrollOffset(sw);
  191.             }else{
  192.                 var me = this;
  193.                 setTimeout(function(){
  194.                     me.setScrollOffset(bd.offsetWidth - bd.clientWidth > 10 ? sw : 0);
  195.                 }, 10);
  196.             }
  197.         }
  198.     },
  199.     updateColumnWidths : function() {
  200.         var cols = this.columns,
  201.             colCount = cols.length,
  202.             groups = this.outerCt.query('colgroup'),
  203.             groupCount = groups.length,
  204.             c, g, i, j;
  205.         for(i = 0; i<colCount; i++) {
  206.             c = cols[i];
  207.             for(j = 0; j<groupCount; j++) {
  208.                 g = groups[j];
  209.                 g.childNodes[i].style.width = (c.hidden ? 0 : c.width) + 'px';
  210.             }
  211.         }
  212.         
  213.         for(i = 0, groups = this.innerHd.query('td'), len = groups.length; i<len; i++) {
  214.             c = Ext.fly(groups[i]);
  215.             if(cols[i] && cols[i].hidden) {
  216.                 c.addClass('x-treegrid-hd-hidden');
  217.             }
  218.             else {
  219.                 c.removeClass('x-treegrid-hd-hidden');
  220.             }
  221.         }
  222.         var tcw = this.getTotalColumnWidth();                        
  223.         Ext.fly(this.innerHd.dom.firstChild).setWidth(tcw + (this.scrollOffset || 0));
  224.         this.outerCt.select('table').setWidth(tcw);
  225.         this.syncHeaderScroll();    
  226.     },
  227.                     
  228.     getVisibleColumns : function() {
  229.         var columns = [],
  230.             cs = this.columns,
  231.             len = cs.length,
  232.             i;
  233.             
  234.         for(i = 0; i<len; i++) {
  235.             if(!cs[i].hidden) {
  236.                 columns.push(cs[i]);
  237.             }
  238.         }        
  239.         return columns;
  240.     },
  241.     getTotalColumnWidth : function() {
  242.         var total = 0;
  243.         for(var i = 0, cs = this.getVisibleColumns(), len = cs.length; i<len; i++) {
  244.             total += cs[i].width;
  245.         }
  246.         return total;
  247.     },
  248.     setScrollOffset : function(scrollOffset) {
  249.         this.scrollOffset = scrollOffset;                        
  250.         this.updateColumnWidths();
  251.     },
  252.     // private
  253.     handleHdDown : function(e, t){
  254.         var hd = e.getTarget('.x-treegrid-hd');
  255.         if(hd && Ext.fly(t).hasClass('x-grid3-hd-btn')){
  256.             var ms = this.hmenu.items,
  257.                 cs = this.columns,
  258.                 index = this.findHeaderIndex(hd),
  259.                 c = cs[index],
  260.                 sort = c.sortable;
  261.                 
  262.             e.stopEvent();
  263.             Ext.fly(hd).addClass('x-grid3-hd-menu-open');
  264.             this.hdCtxIndex = index;
  265.             
  266.             this.fireEvent('headerbuttonclick', ms, c, hd, index);
  267.             
  268.             this.hmenu.on('hide', function(){
  269.                 Ext.fly(hd).removeClass('x-grid3-hd-menu-open');
  270.             }, this, {single:true});
  271.             
  272.             this.hmenu.show(t, 'tl-bl?');
  273.         }
  274.         else if(hd) {
  275.             var index = this.findHeaderIndex(hd);
  276.             this.fireEvent('headerclick', this.columns[index], hd, index);
  277.         }
  278.     },
  279.     // private
  280.     handleHdOver : function(e, t){                    
  281.         var hd = e.getTarget('.x-treegrid-hd');                        
  282.         if(hd && !this.headersDisabled){
  283.             index = this.findHeaderIndex(hd);
  284.             this.activeHdRef = t;
  285.             this.activeHdIndex = index;
  286.             var el = Ext.get(hd);
  287.             this.activeHdRegion = el.getRegion();
  288.             el.addClass('x-grid3-hd-over');
  289.             this.activeHdBtn = el.child('.x-grid3-hd-btn');
  290.             if(this.activeHdBtn){
  291.                 this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight-1)+'px';
  292.             }
  293.         }
  294.     },
  295.     
  296.     // private
  297.     handleHdOut : function(e, t){
  298.         var hd = e.getTarget('.x-treegrid-hd');
  299.         if(hd && (!Ext.isIE || !e.within(hd, true))){
  300.             this.activeHdRef = null;
  301.             Ext.fly(hd).removeClass('x-grid3-hd-over');
  302.             hd.style.cursor = '';
  303.         }
  304.     },
  305.                     
  306.     findHeaderIndex : function(hd){
  307.         hd = hd.dom || hd;
  308.         var cs = hd.parentNode.childNodes;
  309.         for(var i = 0, c; c = cs[i]; i++){
  310.             if(c == hd){
  311.                 return i;
  312.             }
  313.         }
  314.         return -1;
  315.     },
  316.     
  317.     // private
  318.     beforeColMenuShow : function(){
  319.         var cols = this.columns,  
  320.             colCount = cols.length,
  321.             i, c;                        
  322.         this.colMenu.removeAll();                    
  323.         for(i = 1; i < colCount; i++){
  324.             c = cols[i];
  325.             if(c.hideable !== false){
  326.                 this.colMenu.add(new Ext.menu.CheckItem({
  327.                     itemId: 'col-' + i,
  328.                     text: c.header,
  329.                     checked: !c.hidden,
  330.                     hideOnClick:false,
  331.                     disabled: c.hideable === false
  332.                 }));
  333.             }
  334.         }
  335.     },
  336.                     
  337.     // private
  338.     handleHdMenuClick : function(item){
  339.         var index = this.hdCtxIndex,
  340.             id = item.getItemId();
  341.         
  342.         if(this.fireEvent('headermenuclick', this.columns[index], id, index) !== false) {
  343.             index = id.substr(4);
  344.             if(index > 0 && this.columns[index]) {
  345.                 this.setColumnVisible(index, !item.checked);
  346.             }     
  347.         }
  348.         
  349.         return true;
  350.     },
  351.     
  352.     setColumnVisible : function(index, visible) {
  353.         this.columns[index].hidden = !visible;        
  354.         this.updateColumnWidths();
  355.     },
  356.     /**
  357.      * Scrolls the grid to the top
  358.      */
  359.     scrollToTop : function(){
  360.         this.innerBody.dom.scrollTop = 0;
  361.         this.innerBody.dom.scrollLeft = 0;
  362.     },
  363.     // private
  364.     syncScroll : function(){
  365.         this.syncHeaderScroll();
  366.         var mb = this.innerBody.dom;
  367.         this.fireEvent('bodyscroll', mb.scrollLeft, mb.scrollTop);
  368.     },
  369.     // private
  370.     syncHeaderScroll : function(){
  371.         var mb = this.innerBody.dom;
  372.         this.innerHd.dom.scrollLeft = mb.scrollLeft;
  373.         this.innerHd.dom.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore)
  374.     },
  375.     
  376.     registerNode : function(n) {
  377.         Ext.ux.tree.TreeGrid.superclass.registerNode.call(this, n);
  378.         if(!n.uiProvider && !n.isRoot && !n.ui.isTreeGridNodeUI) {
  379.             n.ui = new Ext.ux.tree.TreeGridNodeUI(n);
  380.         }
  381.     }
  382. });
  383. Ext.reg('treegrid', Ext.ux.tree.TreeGrid);