--- /dev/null
+/*!
+ * 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');\r
+\r
+if(Ext.isWebKit){\r
+ Ext.grid.GridView.prototype.borderWidth = 0;\r
+}\r
+\r
+Ext.ux.grid.ColumnHeaderGroup = Ext.extend(Ext.util.Observable, {\r
+\r
+ constructor: function(config){\r
+ this.config = config;\r
+ },\r
+\r
+ init: function(grid){\r
+ Ext.applyIf(grid.colModel, this.config);\r
+ Ext.apply(grid.getView(), this.viewConfig);\r
+ },\r
+\r
+ viewConfig: {\r
+ initTemplates: function(){\r
+ this.constructor.prototype.initTemplates.apply(this, arguments);\r
+ var ts = this.templates || {};\r
+ if(!ts.gcell){\r
+ 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>');\r
+ }\r
+ this.templates = ts;\r
+ this.hrowRe = new RegExp("ux-grid-hd-group-row-(\\d+)", "");\r
+ },\r
+\r
+ renderHeaders: function(){\r
+ var ts = this.templates, headers = [], cm = this.cm, rows = cm.rows, tstyle = 'width:' + this.getTotalWidth() + ';';\r
+\r
+ for(var row = 0, rlen = rows.length; row < rlen; row++){\r
+ var r = rows[row], cells = [];\r
+ for(var i = 0, gcol = 0, len = r.length; i < len; i++){\r
+ var group = r[i];\r
+ group.colspan = group.colspan || 1;\r
+ var id = this.getColumnId(group.dataIndex ? cm.findColumnIndex(group.dataIndex) : gcol), gs = Ext.ux.grid.ColumnHeaderGroup.prototype.getGroupStyle.call(this, group, gcol);\r
+ cells[i] = ts.gcell.apply({\r
+ cls: 'ux-grid-hd-group-cell',\r
+ id: id,\r
+ row: row,\r
+ style: 'width:' + gs.width + ';' + (gs.hidden ? 'display:none;' : '') + (group.align ? 'text-align:' + group.align + ';' : ''),\r
+ tooltip: group.tooltip ? (Ext.QuickTips.isEnabled() ? 'ext:qtip' : 'title') + '="' + group.tooltip + '"' : '',\r
+ istyle: group.align == 'right' ? 'padding-right:16px' : '',\r
+ btn: this.grid.enableHdMenu && group.header,\r
+ value: group.header || ' '\r
+ });\r
+ gcol += group.colspan;\r
+ }\r
+ headers[row] = ts.header.apply({\r
+ tstyle: tstyle,\r
+ cells: cells.join('')\r
+ });\r
+ }\r
+ headers.push(this.constructor.prototype.renderHeaders.apply(this, arguments));\r
+ return headers.join('');\r
+ },\r
+\r
+ onColumnWidthUpdated: function(){\r
+ this.constructor.prototype.onColumnWidthUpdated.apply(this, arguments);\r
+ Ext.ux.grid.ColumnHeaderGroup.prototype.updateGroupStyles.call(this);\r
+ },\r
+\r
+ onAllColumnWidthsUpdated: function(){\r
+ this.constructor.prototype.onAllColumnWidthsUpdated.apply(this, arguments);\r
+ Ext.ux.grid.ColumnHeaderGroup.prototype.updateGroupStyles.call(this);\r
+ },\r
+\r
+ onColumnHiddenUpdated: function(){\r
+ this.constructor.prototype.onColumnHiddenUpdated.apply(this, arguments);\r
+ Ext.ux.grid.ColumnHeaderGroup.prototype.updateGroupStyles.call(this);\r
+ },\r
+\r
+ getHeaderCell: function(index){\r
+ return this.mainHd.query(this.cellSelector)[index];\r
+ },\r
+\r
+ findHeaderCell: function(el){\r
+ return el ? this.fly(el).findParent('td.x-grid3-hd', this.cellSelectorDepth) : false;\r
+ },\r
+\r
+ findHeaderIndex: function(el){\r
+ var cell = this.findHeaderCell(el);\r
+ return cell ? this.getCellIndex(cell) : false;\r
+ },\r
+\r
+ updateSortIcon: function(col, dir){\r
+ var sc = this.sortClasses, hds = this.mainHd.select(this.cellSelector).removeClass(sc);\r
+ hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);\r
+ },\r
+\r
+ handleHdDown: function(e, t){\r
+ var el = Ext.get(t);\r
+ if(el.hasClass('x-grid3-hd-btn')){\r
+ e.stopEvent();\r
+ var hd = this.findHeaderCell(t);\r
+ Ext.fly(hd).addClass('x-grid3-hd-menu-open');\r
+ var index = this.getCellIndex(hd);\r
+ this.hdCtxIndex = index;\r
+ var ms = this.hmenu.items, cm = this.cm;\r
+ ms.get('asc').setDisabled(!cm.isSortable(index));\r
+ ms.get('desc').setDisabled(!cm.isSortable(index));\r
+ this.hmenu.on('hide', function(){\r
+ Ext.fly(hd).removeClass('x-grid3-hd-menu-open');\r
+ }, this, {\r
+ single: true\r
+ });\r
+ this.hmenu.show(t, 'tl-bl?');\r
+ }else if(el.hasClass('ux-grid-hd-group-cell') || Ext.fly(t).up('.ux-grid-hd-group-cell')){\r
+ e.stopEvent();\r
+ }\r
+ },\r
+\r
+ handleHdMove: function(e, t){\r
+ var hd = this.findHeaderCell(this.activeHdRef);\r
+ if(hd && !this.headersDisabled && !Ext.fly(hd).hasClass('ux-grid-hd-group-cell')){\r
+ var hw = this.splitHandleWidth || 5, r = this.activeHdRegion, x = e.getPageX(), ss = hd.style, cur = '';\r
+ if(this.grid.enableColumnResize !== false){\r
+ if(x - r.left <= hw && this.cm.isResizable(this.activeHdIndex - 1)){\r
+ cur = Ext.isAir ? 'move' : Ext.isWebKit ? 'e-resize' : 'col-resize'; // col-resize\r
+ // not\r
+ // always\r
+ // supported\r
+ }else if(r.right - x <= (!this.activeHdBtn ? hw : 2) && this.cm.isResizable(this.activeHdIndex)){\r
+ cur = Ext.isAir ? 'move' : Ext.isWebKit ? 'w-resize' : 'col-resize';\r
+ }\r
+ }\r
+ ss.cursor = cur;\r
+ }\r
+ },\r
+\r
+ handleHdOver: function(e, t){\r
+ var hd = this.findHeaderCell(t);\r
+ if(hd && !this.headersDisabled){\r
+ this.activeHdRef = t;\r
+ this.activeHdIndex = this.getCellIndex(hd);\r
+ var fly = this.fly(hd);\r
+ this.activeHdRegion = fly.getRegion();\r
+ if(!(this.cm.isMenuDisabled(this.activeHdIndex) || fly.hasClass('ux-grid-hd-group-cell'))){\r
+ fly.addClass('x-grid3-hd-over');\r
+ this.activeHdBtn = fly.child('.x-grid3-hd-btn');\r
+ if(this.activeHdBtn){\r
+ this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight - 1) + 'px';\r
+ }\r
+ }\r
+ }\r
+ },\r
+\r
+ handleHdOut: function(e, t){\r
+ var hd = this.findHeaderCell(t);\r
+ if(hd && (!Ext.isIE || !e.within(hd, true))){\r
+ this.activeHdRef = null;\r
+ this.fly(hd).removeClass('x-grid3-hd-over');\r
+ hd.style.cursor = '';\r
+ }\r
+ },\r
+\r
+ handleHdMenuClick: function(item){\r
+ var index = this.hdCtxIndex, cm = this.cm, ds = this.ds, id = item.getItemId();\r
+ switch(id){\r
+ case 'asc':\r
+ ds.sort(cm.getDataIndex(index), 'ASC');\r
+ break;\r
+ case 'desc':\r
+ ds.sort(cm.getDataIndex(index), 'DESC');\r
+ break;\r
+ default:\r
+ if(id.substr(0, 5) == 'group'){\r
+ var i = id.split('-'), row = parseInt(i[1], 10), col = parseInt(i[2], 10), r = this.cm.rows[row], group, gcol = 0;\r
+ for(var i = 0, len = r.length; i < len; i++){\r
+ group = r[i];\r
+ if(col >= gcol && col < gcol + group.colspan){\r
+ break;\r
+ }\r
+ gcol += group.colspan;\r
+ }\r
+ if(item.checked){\r
+ var max = cm.getColumnsBy(this.isHideableColumn, this).length;\r
+ for(var i = gcol, len = gcol + group.colspan; i < len; i++){\r
+ if(!cm.isHidden(i)){\r
+ max--;\r
+ }\r
+ }\r
+ if(max < 1){\r
+ this.onDenyColumnHide();\r
+ return false;\r
+ }\r
+ }\r
+ for(var i = gcol, len = gcol + group.colspan; i < len; i++){\r
+ if(cm.config[i].fixed !== true && cm.config[i].hideable !== false){\r
+ cm.setHidden(i, item.checked);\r
+ }\r
+ }\r
+ }else{\r
+ index = cm.getIndexById(id.substr(4));\r
+ if(index != -1){\r
+ if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){\r
+ this.onDenyColumnHide();\r
+ return false;\r
+ }\r
+ cm.setHidden(index, item.checked);\r
+ }\r
+ }\r
+ item.checked = !item.checked;\r
+ if(item.menu){\r
+ var updateChildren = function(menu){\r
+ menu.items.each(function(childItem){\r
+ if(!childItem.disabled){\r
+ childItem.setChecked(item.checked, false);\r
+ if(childItem.menu){\r
+ updateChildren(childItem.menu);\r
+ }\r
+ }\r
+ });\r
+ }\r
+ updateChildren(item.menu);\r
+ }\r
+ var parentMenu = item, parentItem;\r
+ while(parentMenu = parentMenu.parentMenu){\r
+ if(!parentMenu.parentMenu || !(parentItem = parentMenu.parentMenu.items.get(parentMenu.getItemId())) || !parentItem.setChecked){\r
+ break;\r
+ }\r
+ var checked = parentMenu.items.findIndexBy(function(m){\r
+ return m.checked;\r
+ }) >= 0;\r
+ parentItem.setChecked(checked, true);\r
+ }\r
+ item.checked = !item.checked;\r
+ }\r
+ return true;\r
+ },\r
+\r
+ beforeColMenuShow: function(){\r
+ var cm = this.cm, rows = this.cm.rows;\r
+ this.colMenu.removeAll();\r
+ for(var col = 0, clen = cm.getColumnCount(); col < clen; col++){\r
+ var menu = this.colMenu, title = cm.getColumnHeader(col), text = [];\r
+ if(cm.config[col].fixed !== true && cm.config[col].hideable !== false){\r
+ for(var row = 0, rlen = rows.length; row < rlen; row++){\r
+ var r = rows[row], group, gcol = 0;\r
+ for(var i = 0, len = r.length; i < len; i++){\r
+ group = r[i];\r
+ if(col >= gcol && col < gcol + group.colspan){\r
+ break;\r
+ }\r
+ gcol += group.colspan;\r
+ }\r
+ if(group && group.header){\r
+ if(cm.hierarchicalColMenu){\r
+ var gid = 'group-' + row + '-' + gcol;\r
+ var item = menu.items.item(gid);\r
+ var submenu = item ? item.menu : null;\r
+ if(!submenu){\r
+ submenu = new Ext.menu.Menu({\r
+ itemId: gid\r
+ });\r
+ submenu.on("itemclick", this.handleHdMenuClick, this);\r
+ var checked = false, disabled = true;\r
+ for(var c = gcol, lc = gcol + group.colspan; c < lc; c++){\r
+ if(!cm.isHidden(c)){\r
+ checked = true;\r
+ }\r
+ if(cm.config[c].hideable !== false){\r
+ disabled = false;\r
+ }\r
+ }\r
+ menu.add({\r
+ itemId: gid,\r
+ text: group.header,\r
+ menu: submenu,\r
+ hideOnClick: false,\r
+ checked: checked,\r
+ disabled: disabled\r
+ });\r
+ }\r
+ menu = submenu;\r
+ }else{\r
+ text.push(group.header);\r
+ }\r
+ }\r
+ }\r
+ text.push(title);\r
+ menu.add(new Ext.menu.CheckItem({\r
+ itemId: "col-" + cm.getColumnId(col),\r
+ text: text.join(' '),\r
+ checked: !cm.isHidden(col),\r
+ hideOnClick: false,\r
+ disabled: cm.config[col].hideable === false\r
+ }));\r
+ }\r
+ }\r
+ },\r
+\r
+ renderUI: function(){\r
+ this.constructor.prototype.renderUI.apply(this, arguments);\r
+ Ext.apply(this.columnDrop, Ext.ux.grid.ColumnHeaderGroup.prototype.columnDropConfig);\r
+ Ext.apply(this.splitZone, Ext.ux.grid.ColumnHeaderGroup.prototype.splitZoneConfig);\r
+ }\r
+ },\r
+\r
+ splitZoneConfig: {\r
+ allowHeaderDrag: function(e){\r
+ return !e.getTarget(null, null, true).hasClass('ux-grid-hd-group-cell');\r
+ }\r
+ },\r
+\r
+ columnDropConfig: {\r
+ getTargetFromEvent: function(e){\r
+ var t = Ext.lib.Event.getTarget(e);\r
+ return this.view.findHeaderCell(t);\r
+ },\r
+\r
+ positionIndicator: function(h, n, e){\r
+ var data = Ext.ux.grid.ColumnHeaderGroup.prototype.getDragDropData.call(this, h, n, e);\r
+ if(data === false){\r
+ return false;\r
+ }\r
+ var px = data.px + this.proxyOffsets[0];\r
+ this.proxyTop.setLeftTop(px, data.r.top + this.proxyOffsets[1]);\r
+ this.proxyTop.show();\r
+ this.proxyBottom.setLeftTop(px, data.r.bottom);\r
+ this.proxyBottom.show();\r
+ return data.pt;\r
+ },\r
+\r
+ onNodeDrop: function(n, dd, e, data){\r
+ var h = data.header;\r
+ if(h != n){\r
+ var d = Ext.ux.grid.ColumnHeaderGroup.prototype.getDragDropData.call(this, h, n, e);\r
+ if(d === false){\r
+ return false;\r
+ }\r
+ var cm = this.grid.colModel, right = d.oldIndex < d.newIndex, rows = cm.rows;\r
+ for(var row = d.row, rlen = rows.length; row < rlen; row++){\r
+ var r = rows[row], len = r.length, fromIx = 0, span = 1, toIx = len;\r
+ for(var i = 0, gcol = 0; i < len; i++){\r
+ var group = r[i];\r
+ if(d.oldIndex >= gcol && d.oldIndex < gcol + group.colspan){\r
+ fromIx = i;\r
+ }\r
+ if(d.oldIndex + d.colspan - 1 >= gcol && d.oldIndex + d.colspan - 1 < gcol + group.colspan){\r
+ span = i - fromIx + 1;\r
+ }\r
+ if(d.newIndex >= gcol && d.newIndex < gcol + group.colspan){\r
+ toIx = i;\r
+ }\r
+ gcol += group.colspan;\r
+ }\r
+ var groups = r.splice(fromIx, span);\r
+ rows[row] = r.splice(0, toIx - (right ? span : 0)).concat(groups).concat(r);\r
+ }\r
+ for(var c = 0; c < d.colspan; c++){\r
+ var oldIx = d.oldIndex + (right ? 0 : c), newIx = d.newIndex + (right ? -1 : c);\r
+ cm.moveColumn(oldIx, newIx);\r
+ this.grid.fireEvent("columnmove", oldIx, newIx);\r
+ }\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+ },\r
+\r
+ getGroupStyle: function(group, gcol){\r
+ var width = 0, hidden = true;\r
+ for(var i = gcol, len = gcol + group.colspan; i < len; i++){\r
+ if(!this.cm.isHidden(i)){\r
+ var cw = this.cm.getColumnWidth(i);\r
+ if(typeof cw == 'number'){\r
+ width += cw;\r
+ }\r
+ hidden = false;\r
+ }\r
+ }\r
+ return {\r
+ width: (Ext.isBorderBox ? width : Math.max(width - this.borderWidth, 0)) + 'px',\r
+ hidden: hidden\r
+ };\r
+ },\r
+\r
+ updateGroupStyles: function(col){\r
+ var tables = this.mainHd.query('.x-grid3-header-offset > table'), tw = this.getTotalWidth(), rows = this.cm.rows;\r
+ for(var row = 0; row < tables.length; row++){\r
+ tables[row].style.width = tw;\r
+ if(row < rows.length){\r
+ var cells = tables[row].firstChild.firstChild.childNodes;\r
+ for(var i = 0, gcol = 0; i < cells.length; i++){\r
+ var group = rows[row][i];\r
+ if((typeof col != 'number') || (col >= gcol && col < gcol + group.colspan)){\r
+ var gs = Ext.ux.grid.ColumnHeaderGroup.prototype.getGroupStyle.call(this, group, gcol);\r
+ cells[i].style.width = gs.width;\r
+ cells[i].style.display = gs.hidden ? 'none' : '';\r
+ }\r
+ gcol += group.colspan;\r
+ }\r
+ }\r
+ }\r
+ },\r
+\r
+ getGroupRowIndex: function(el){\r
+ if(el){\r
+ var m = el.className.match(this.hrowRe);\r
+ if(m && m[1]){\r
+ return parseInt(m[1], 10);\r
+ }\r
+ }\r
+ return this.cm.rows.length;\r
+ },\r
+\r
+ getGroupSpan: function(row, col){\r
+ if(row < 0){\r
+ return {\r
+ col: 0,\r
+ colspan: this.cm.getColumnCount()\r
+ };\r
+ }\r
+ var r = this.cm.rows[row];\r
+ if(r){\r
+ for(var i = 0, gcol = 0, len = r.length; i < len; i++){\r
+ var group = r[i];\r
+ if(col >= gcol && col < gcol + group.colspan){\r
+ return {\r
+ col: gcol,\r
+ colspan: group.colspan\r
+ };\r
+ }\r
+ gcol += group.colspan;\r
+ }\r
+ return {\r
+ col: gcol,\r
+ colspan: 0\r
+ };\r
+ }\r
+ return {\r
+ col: col,\r
+ colspan: 1\r
+ };\r
+ },\r
+\r
+ getDragDropData: function(h, n, e){\r
+ if(h.parentNode != n.parentNode){\r
+ return false;\r
+ }\r
+ var cm = this.grid.colModel, x = Ext.lib.Event.getPageX(e), r = Ext.lib.Dom.getRegion(n.firstChild), px, pt;\r
+ if((r.right - x) <= (r.right - r.left) / 2){\r
+ px = r.right + this.view.borderWidth;\r
+ pt = "after";\r
+ }else{\r
+ px = r.left;\r
+ pt = "before";\r
+ }\r
+ var oldIndex = this.view.getCellIndex(h), newIndex = this.view.getCellIndex(n);\r
+ if(cm.isFixed(newIndex)){\r
+ return false;\r
+ }\r
+ var row = Ext.ux.grid.ColumnHeaderGroup.prototype.getGroupRowIndex.call(this.view, h), \r
+ oldGroup = Ext.ux.grid.ColumnHeaderGroup.prototype.getGroupSpan.call(this.view, row, oldIndex), \r
+ newGroup = Ext.ux.grid.ColumnHeaderGroup.prototype.getGroupSpan.call(this.view, row, newIndex),\r
+ oldIndex = oldGroup.col;\r
+ newIndex = newGroup.col + (pt == "after" ? newGroup.colspan : 0);\r
+ if(newIndex >= oldGroup.col && newIndex <= oldGroup.col + oldGroup.colspan){\r
+ return false;\r
+ }\r
+ var parentGroup = Ext.ux.grid.ColumnHeaderGroup.prototype.getGroupSpan.call(this.view, row - 1, oldIndex);\r
+ if(newIndex < parentGroup.col || newIndex > parentGroup.col + parentGroup.colspan){\r
+ return false;\r
+ }\r
+ return {\r
+ r: r,\r
+ px: px,\r
+ pt: pt,\r
+ row: row,\r
+ oldIndex: oldIndex,\r
+ newIndex: newIndex,\r
+ colspan: oldGroup.colspan\r
+ };\r
+ }\r
+});
\ No newline at end of file