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

JavaScript

开发平台:

JavaScript

  1. /*!  * Ext JS Library 3.1.0  * Copyright(c) 2006-2009 Ext JS, LLC  * licensing@extjs.com  * http://www.extjs.com/license  */ Ext.ns('Ext.ux.grid');
  2. if(Ext.isWebKit){
  3.     Ext.grid.GridView.prototype.borderWidth = 0;
  4. }
  5. Ext.ux.grid.ColumnHeaderGroup = Ext.extend(Ext.util.Observable, {
  6.     constructor: function(config){
  7.         this.config = config;
  8.     },
  9.     init: function(grid){
  10.         Ext.applyIf(grid.colModel, this.config);
  11.         Ext.apply(grid.getView(), this.viewConfig);
  12.     },
  13.     viewConfig: {
  14.         initTemplates: function(){
  15.             this.constructor.prototype.initTemplates.apply(this, arguments);
  16.             var ts = this.templates || {};
  17.             if(!ts.gcell){
  18.                 ts.gcell = new Ext.XTemplate('<td class="x-grid3-hd x-grid3-gcell x-grid3-td-{id} ux-grid-hd-group-row-{row} {cls}" style="{style}">', '<div {tooltip} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">', this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '', '{value}</div></td>');
  19.             }
  20.             this.templates = ts;
  21.             this.hrowRe = new RegExp("ux-grid-hd-group-row-(\d+)", "");
  22.         },
  23.         renderHeaders: function(){
  24.             var ts = this.templates, headers = [], cm = this.cm, rows = cm.rows, tstyle = 'width:' + this.getTotalWidth() + ';';
  25.             for(var row = 0, rlen = rows.length; row < rlen; row++){
  26.                 var r = rows[row], cells = [];
  27.                 for(var i = 0, gcol = 0, len = r.length; i < len; i++){
  28.                     var group = r[i];
  29.                     group.colspan = group.colspan || 1;
  30.                     var id = this.getColumnId(group.dataIndex ? cm.findColumnIndex(group.dataIndex) : gcol), gs = Ext.ux.grid.ColumnHeaderGroup.prototype.getGroupStyle.call(this, group, gcol);
  31.                     cells[i] = ts.gcell.apply({
  32.                         cls: 'ux-grid-hd-group-cell',
  33.                         id: id,
  34.                         row: row,
  35.                         style: 'width:' + gs.width + ';' + (gs.hidden ? 'display:none;' : '') + (group.align ? 'text-align:' + group.align + ';' : ''),
  36.                         tooltip: group.tooltip ? (Ext.QuickTips.isEnabled() ? 'ext:qtip' : 'title') + '="' + group.tooltip + '"' : '',
  37.                         istyle: group.align == 'right' ? 'padding-right:16px' : '',
  38.                         btn: this.grid.enableHdMenu && group.header,
  39.                         value: group.header || '&nbsp;'
  40.                     });
  41.                     gcol += group.colspan;
  42.                 }
  43.                 headers[row] = ts.header.apply({
  44.                     tstyle: tstyle,
  45.                     cells: cells.join('')
  46.                 });
  47.             }
  48.             headers.push(this.constructor.prototype.renderHeaders.apply(this, arguments));
  49.             return headers.join('');
  50.         },
  51.         onColumnWidthUpdated: function(){
  52.             this.constructor.prototype.onColumnWidthUpdated.apply(this, arguments);
  53.             Ext.ux.grid.ColumnHeaderGroup.prototype.updateGroupStyles.call(this);
  54.         },
  55.         onAllColumnWidthsUpdated: function(){
  56.             this.constructor.prototype.onAllColumnWidthsUpdated.apply(this, arguments);
  57.             Ext.ux.grid.ColumnHeaderGroup.prototype.updateGroupStyles.call(this);
  58.         },
  59.         onColumnHiddenUpdated: function(){
  60.             this.constructor.prototype.onColumnHiddenUpdated.apply(this, arguments);
  61.             Ext.ux.grid.ColumnHeaderGroup.prototype.updateGroupStyles.call(this);
  62.         },
  63.         getHeaderCell: function(index){
  64.             return this.mainHd.query(this.cellSelector)[index];
  65.         },
  66.         findHeaderCell: function(el){
  67.             return el ? this.fly(el).findParent('td.x-grid3-hd', this.cellSelectorDepth) : false;
  68.         },
  69.         findHeaderIndex: function(el){
  70.             var cell = this.findHeaderCell(el);
  71.             return cell ? this.getCellIndex(cell) : false;
  72.         },
  73.         updateSortIcon: function(col, dir){
  74.             var sc = this.sortClasses, hds = this.mainHd.select(this.cellSelector).removeClass(sc);
  75.             hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);
  76.         },
  77.         handleHdDown: function(e, t){
  78.             var el = Ext.get(t);
  79.             if(el.hasClass('x-grid3-hd-btn')){
  80.                 e.stopEvent();
  81.                 var hd = this.findHeaderCell(t);
  82.                 Ext.fly(hd).addClass('x-grid3-hd-menu-open');
  83.                 var index = this.getCellIndex(hd);
  84.                 this.hdCtxIndex = index;
  85.                 var ms = this.hmenu.items, cm = this.cm;
  86.                 ms.get('asc').setDisabled(!cm.isSortable(index));
  87.                 ms.get('desc').setDisabled(!cm.isSortable(index));
  88.                 this.hmenu.on('hide', function(){
  89.                     Ext.fly(hd).removeClass('x-grid3-hd-menu-open');
  90.                 }, this, {
  91.                     single: true
  92.                 });
  93.                 this.hmenu.show(t, 'tl-bl?');
  94.             }else if(el.hasClass('ux-grid-hd-group-cell') || Ext.fly(t).up('.ux-grid-hd-group-cell')){
  95.                 e.stopEvent();
  96.             }
  97.         },
  98.         handleHdMove: function(e, t){
  99.             var hd = this.findHeaderCell(this.activeHdRef);
  100.             if(hd && !this.headersDisabled && !Ext.fly(hd).hasClass('ux-grid-hd-group-cell')){
  101.                 var hw = this.splitHandleWidth || 5, r = this.activeHdRegion, x = e.getPageX(), ss = hd.style, cur = '';
  102.                 if(this.grid.enableColumnResize !== false){
  103.                     if(x - r.left <= hw && this.cm.isResizable(this.activeHdIndex - 1)){
  104.                         cur = Ext.isAir ? 'move' : Ext.isWebKit ? 'e-resize' : 'col-resize'; // col-resize
  105.                                                                                                 // not
  106.                                                                                                 // always
  107.                                                                                                 // supported
  108.                     }else if(r.right - x <= (!this.activeHdBtn ? hw : 2) && this.cm.isResizable(this.activeHdIndex)){
  109.                         cur = Ext.isAir ? 'move' : Ext.isWebKit ? 'w-resize' : 'col-resize';
  110.                     }
  111.                 }
  112.                 ss.cursor = cur;
  113.             }
  114.         },
  115.         handleHdOver: function(e, t){
  116.             var hd = this.findHeaderCell(t);
  117.             if(hd && !this.headersDisabled){
  118.                 this.activeHdRef = t;
  119.                 this.activeHdIndex = this.getCellIndex(hd);
  120.                 var fly = this.fly(hd);
  121.                 this.activeHdRegion = fly.getRegion();
  122.                 if(!(this.cm.isMenuDisabled(this.activeHdIndex) || fly.hasClass('ux-grid-hd-group-cell'))){
  123.                     fly.addClass('x-grid3-hd-over');
  124.                     this.activeHdBtn = fly.child('.x-grid3-hd-btn');
  125.                     if(this.activeHdBtn){
  126.                         this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight - 1) + 'px';
  127.                     }
  128.                 }
  129.             }
  130.         },
  131.         handleHdOut: function(e, t){
  132.             var hd = this.findHeaderCell(t);
  133.             if(hd && (!Ext.isIE || !e.within(hd, true))){
  134.                 this.activeHdRef = null;
  135.                 this.fly(hd).removeClass('x-grid3-hd-over');
  136.                 hd.style.cursor = '';
  137.             }
  138.         },
  139.         handleHdMenuClick: function(item){
  140.             var index = this.hdCtxIndex, cm = this.cm, ds = this.ds, id = item.getItemId();
  141.             switch(id){
  142.                 case 'asc':
  143.                     ds.sort(cm.getDataIndex(index), 'ASC');
  144.                     break;
  145.                 case 'desc':
  146.                     ds.sort(cm.getDataIndex(index), 'DESC');
  147.                     break;
  148.                 default:
  149.                     if(id.substr(0, 5) == 'group'){
  150.                         var i = id.split('-'), row = parseInt(i[1], 10), col = parseInt(i[2], 10), r = this.cm.rows[row], group, gcol = 0;
  151.                         for(var i = 0, len = r.length; i < len; i++){
  152.                             group = r[i];
  153.                             if(col >= gcol && col < gcol + group.colspan){
  154.                                 break;
  155.                             }
  156.                             gcol += group.colspan;
  157.                         }
  158.                         if(item.checked){
  159.                             var max = cm.getColumnsBy(this.isHideableColumn, this).length;
  160.                             for(var i = gcol, len = gcol + group.colspan; i < len; i++){
  161.                                 if(!cm.isHidden(i)){
  162.                                     max--;
  163.                                 }
  164.                             }
  165.                             if(max < 1){
  166.                                 this.onDenyColumnHide();
  167.                                 return false;
  168.                             }
  169.                         }
  170.                         for(var i = gcol, len = gcol + group.colspan; i < len; i++){
  171.                             if(cm.config[i].fixed !== true && cm.config[i].hideable !== false){
  172.                                 cm.setHidden(i, item.checked);
  173.                             }
  174.                         }
  175.                     }else{
  176.                         index = cm.getIndexById(id.substr(4));
  177.                         if(index != -1){
  178.                             if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){
  179.                                 this.onDenyColumnHide();
  180.                                 return false;
  181.                             }
  182.                             cm.setHidden(index, item.checked);
  183.                         }
  184.                     }
  185.                     item.checked = !item.checked;
  186.                     if(item.menu){
  187.                         var updateChildren = function(menu){
  188.                             menu.items.each(function(childItem){
  189.                                 if(!childItem.disabled){
  190.                                     childItem.setChecked(item.checked, false);
  191.                                     if(childItem.menu){
  192.                                         updateChildren(childItem.menu);
  193.                                     }
  194.                                 }
  195.                             });
  196.                         }
  197.                         updateChildren(item.menu);
  198.                     }
  199.                     var parentMenu = item, parentItem;
  200.                     while(parentMenu = parentMenu.parentMenu){
  201.                         if(!parentMenu.parentMenu || !(parentItem = parentMenu.parentMenu.items.get(parentMenu.getItemId())) || !parentItem.setChecked){
  202.                             break;
  203.                         }
  204.                         var checked = parentMenu.items.findIndexBy(function(m){
  205.                             return m.checked;
  206.                         }) >= 0;
  207.                         parentItem.setChecked(checked, true);
  208.                     }
  209.                     item.checked = !item.checked;
  210.             }
  211.             return true;
  212.         },
  213.         beforeColMenuShow: function(){
  214.             var cm = this.cm, rows = this.cm.rows;
  215.             this.colMenu.removeAll();
  216.             for(var col = 0, clen = cm.getColumnCount(); col < clen; col++){
  217.                 var menu = this.colMenu, title = cm.getColumnHeader(col), text = [];
  218.                 if(cm.config[col].fixed !== true && cm.config[col].hideable !== false){
  219.                     for(var row = 0, rlen = rows.length; row < rlen; row++){
  220.                         var r = rows[row], group, gcol = 0;
  221.                         for(var i = 0, len = r.length; i < len; i++){
  222.                             group = r[i];
  223.                             if(col >= gcol && col < gcol + group.colspan){
  224.                                 break;
  225.                             }
  226.                             gcol += group.colspan;
  227.                         }
  228.                         if(group && group.header){
  229.                             if(cm.hierarchicalColMenu){
  230.                                 var gid = 'group-' + row + '-' + gcol;
  231.                                 var item = menu.items.item(gid);
  232.                                 var submenu = item ? item.menu : null;
  233.                                 if(!submenu){
  234.                                     submenu = new Ext.menu.Menu({
  235.                                         itemId: gid
  236.                                     });
  237.                                     submenu.on("itemclick", this.handleHdMenuClick, this);
  238.                                     var checked = false, disabled = true;
  239.                                     for(var c = gcol, lc = gcol + group.colspan; c < lc; c++){
  240.                                         if(!cm.isHidden(c)){
  241.                                             checked = true;
  242.                                         }
  243.                                         if(cm.config[c].hideable !== false){
  244.                                             disabled = false;
  245.                                         }
  246.                                     }
  247.                                     menu.add({
  248.                                         itemId: gid,
  249.                                         text: group.header,
  250.                                         menu: submenu,
  251.                                         hideOnClick: false,
  252.                                         checked: checked,
  253.                                         disabled: disabled
  254.                                     });
  255.                                 }
  256.                                 menu = submenu;
  257.                             }else{
  258.                                 text.push(group.header);
  259.                             }
  260.                         }
  261.                     }
  262.                     text.push(title);
  263.                     menu.add(new Ext.menu.CheckItem({
  264.                         itemId: "col-" + cm.getColumnId(col),
  265.                         text: text.join(' '),
  266.                         checked: !cm.isHidden(col),
  267.                         hideOnClick: false,
  268.                         disabled: cm.config[col].hideable === false
  269.                     }));
  270.                 }
  271.             }
  272.         },
  273.         renderUI: function(){
  274.             this.constructor.prototype.renderUI.apply(this, arguments);
  275.             Ext.apply(this.columnDrop, Ext.ux.grid.ColumnHeaderGroup.prototype.columnDropConfig);
  276.             Ext.apply(this.splitZone, Ext.ux.grid.ColumnHeaderGroup.prototype.splitZoneConfig);
  277.         }
  278.     },
  279.     splitZoneConfig: {
  280.         allowHeaderDrag: function(e){
  281.             return !e.getTarget(null, null, true).hasClass('ux-grid-hd-group-cell');
  282.         }
  283.     },
  284.     columnDropConfig: {
  285.         getTargetFromEvent: function(e){
  286.             var t = Ext.lib.Event.getTarget(e);
  287.             return this.view.findHeaderCell(t);
  288.         },
  289.         positionIndicator: function(h, n, e){
  290.             var data = Ext.ux.grid.ColumnHeaderGroup.prototype.getDragDropData.call(this, h, n, e);
  291.             if(data === false){
  292.                 return false;
  293.             }
  294.             var px = data.px + this.proxyOffsets[0];
  295.             this.proxyTop.setLeftTop(px, data.r.top + this.proxyOffsets[1]);
  296.             this.proxyTop.show();
  297.             this.proxyBottom.setLeftTop(px, data.r.bottom);
  298.             this.proxyBottom.show();
  299.             return data.pt;
  300.         },
  301.         onNodeDrop: function(n, dd, e, data){
  302.             var h = data.header;
  303.             if(h != n){
  304.                 var d = Ext.ux.grid.ColumnHeaderGroup.prototype.getDragDropData.call(this, h, n, e);
  305.                 if(d === false){
  306.                     return false;
  307.                 }
  308.                 var cm = this.grid.colModel, right = d.oldIndex < d.newIndex, rows = cm.rows;
  309.                 for(var row = d.row, rlen = rows.length; row < rlen; row++){
  310.                     var r = rows[row], len = r.length, fromIx = 0, span = 1, toIx = len;
  311.                     for(var i = 0, gcol = 0; i < len; i++){
  312.                         var group = r[i];
  313.                         if(d.oldIndex >= gcol && d.oldIndex < gcol + group.colspan){
  314.                             fromIx = i;
  315.                         }
  316.                         if(d.oldIndex + d.colspan - 1 >= gcol && d.oldIndex + d.colspan - 1 < gcol + group.colspan){
  317.                             span = i - fromIx + 1;
  318.                         }
  319.                         if(d.newIndex >= gcol && d.newIndex < gcol + group.colspan){
  320.                             toIx = i;
  321.                         }
  322.                         gcol += group.colspan;
  323.                     }
  324.                     var groups = r.splice(fromIx, span);
  325.                     rows[row] = r.splice(0, toIx - (right ? span : 0)).concat(groups).concat(r);
  326.                 }
  327.                 for(var c = 0; c < d.colspan; c++){
  328.                     var oldIx = d.oldIndex + (right ? 0 : c), newIx = d.newIndex + (right ? -1 : c);
  329.                     cm.moveColumn(oldIx, newIx);
  330.                     this.grid.fireEvent("columnmove", oldIx, newIx);
  331.                 }
  332.                 return true;
  333.             }
  334.             return false;
  335.         }
  336.     },
  337.     getGroupStyle: function(group, gcol){
  338.         var width = 0, hidden = true;
  339.         for(var i = gcol, len = gcol + group.colspan; i < len; i++){
  340.             if(!this.cm.isHidden(i)){
  341.                 var cw = this.cm.getColumnWidth(i);
  342.                 if(typeof cw == 'number'){
  343.                     width += cw;
  344.                 }
  345.                 hidden = false;
  346.             }
  347.         }
  348.         return {
  349.             width: (Ext.isBorderBox ? width : Math.max(width - this.borderWidth, 0)) + 'px',
  350.             hidden: hidden
  351.         };
  352.     },
  353.     updateGroupStyles: function(col){
  354.         var tables = this.mainHd.query('.x-grid3-header-offset > table'), tw = this.getTotalWidth(), rows = this.cm.rows;
  355.         for(var row = 0; row < tables.length; row++){
  356.             tables[row].style.width = tw;
  357.             if(row < rows.length){
  358.                 var cells = tables[row].firstChild.firstChild.childNodes;
  359.                 for(var i = 0, gcol = 0; i < cells.length; i++){
  360.                     var group = rows[row][i];
  361.                     if((typeof col != 'number') || (col >= gcol && col < gcol + group.colspan)){
  362.                         var gs = Ext.ux.grid.ColumnHeaderGroup.prototype.getGroupStyle.call(this, group, gcol);
  363.                         cells[i].style.width = gs.width;
  364.                         cells[i].style.display = gs.hidden ? 'none' : '';
  365.                     }
  366.                     gcol += group.colspan;
  367.                 }
  368.             }
  369.         }
  370.     },
  371.     getGroupRowIndex: function(el){
  372.         if(el){
  373.             var m = el.className.match(this.hrowRe);
  374.             if(m && m[1]){
  375.                 return parseInt(m[1], 10);
  376.             }
  377.         }
  378.         return this.cm.rows.length;
  379.     },
  380.     getGroupSpan: function(row, col){
  381.         if(row < 0){
  382.             return {
  383.                 col: 0,
  384.                 colspan: this.cm.getColumnCount()
  385.             };
  386.         }
  387.         var r = this.cm.rows[row];
  388.         if(r){
  389.             for(var i = 0, gcol = 0, len = r.length; i < len; i++){
  390.                 var group = r[i];
  391.                 if(col >= gcol && col < gcol + group.colspan){
  392.                     return {
  393.                         col: gcol,
  394.                         colspan: group.colspan
  395.                     };
  396.                 }
  397.                 gcol += group.colspan;
  398.             }
  399.             return {
  400.                 col: gcol,
  401.                 colspan: 0
  402.             };
  403.         }
  404.         return {
  405.             col: col,
  406.             colspan: 1
  407.         };
  408.     },
  409.     getDragDropData: function(h, n, e){
  410.         if(h.parentNode != n.parentNode){
  411.             return false;
  412.         }
  413.         var cm = this.grid.colModel, x = Ext.lib.Event.getPageX(e), r = Ext.lib.Dom.getRegion(n.firstChild), px, pt;
  414.         if((r.right - x) <= (r.right - r.left) / 2){
  415.             px = r.right + this.view.borderWidth;
  416.             pt = "after";
  417.         }else{
  418.             px = r.left;
  419.             pt = "before";
  420.         }
  421.         var oldIndex = this.view.getCellIndex(h), newIndex = this.view.getCellIndex(n);
  422.         if(cm.isFixed(newIndex)){
  423.             return false;
  424.         }
  425.         var row = Ext.ux.grid.ColumnHeaderGroup.prototype.getGroupRowIndex.call(this.view, h), 
  426.             oldGroup = Ext.ux.grid.ColumnHeaderGroup.prototype.getGroupSpan.call(this.view, row, oldIndex), 
  427.             newGroup = Ext.ux.grid.ColumnHeaderGroup.prototype.getGroupSpan.call(this.view, row, newIndex),
  428.             oldIndex = oldGroup.col;
  429.             newIndex = newGroup.col + (pt == "after" ? newGroup.colspan : 0);
  430.         if(newIndex >= oldGroup.col && newIndex <= oldGroup.col + oldGroup.colspan){
  431.             return false;
  432.         }
  433.         var parentGroup = Ext.ux.grid.ColumnHeaderGroup.prototype.getGroupSpan.call(this.view, row - 1, oldIndex);
  434.         if(newIndex < parentGroup.col || newIndex > parentGroup.col + parentGroup.colspan){
  435.             return false;
  436.         }
  437.         return {
  438.             r: r,
  439.             px: px,
  440.             pt: pt,
  441.             row: row,
  442.             oldIndex: oldIndex,
  443.             newIndex: newIndex,
  444.             colspan: oldGroup.colspan
  445.         };
  446.     }
  447. });