올바른 성장과 따뜻한 나눔이 있는 넥스트리
그리드를 그리다 보면 기존 HTML을 이용해서 <thead>를 colspan, rowspan을 이용해서 컬럼을 그룹핑 해줄수 있었다. 그러나 extjs gridpanel에서 방법을 찾다가 해당 플러그인을 찾았다.
실제작성예
소스다운로드
마크업 <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Example</title> <link rel="stylesheet" type="text/css" href="http://techbug.tistory.com/resources/css/ext-all.css" /> <script type="text/javascript" src="../../adapter/ext/ext-base.js"></script> <script type="text/javascript" src="../../ext-all.js"></script> <script type="text/javascript" src="./GroupHeaderPlugin-HdMenu.j s"></script> <script type="text/javascript" src="./groupingHeader.js"></script> <script type="text/javascript" src="./00_main.js"></script> <style type="text/css"> .ext-ie .x-grid3 table,.ext-safari .x-grid3 table { table-layout:auto; } .ux-grid-hd-group-cell { background: #f9f9f9 url(../../resources/images/default/grid/grid3-hrow.gif) repeat-x 0 bottom; height:24px; border-right: 1px solid rgb(208 208 208) !important; } .ux-grid-hd-group-nocolspan-cell { border-right: 1px solid rgb(208 208 208) !important; } </style> </head> <body></body> </html>
00_main.js
var techbugTestMain = function(){ return { init: function(){ //그리드판넬 그리기 ---------------------------------------- this.gridPanel = new mainGridPanel(); //메인화면 레이아웃 설정----------------------------------- this.mainViewPort = new Ext.Viewport({ layout:'border', border:false, items:[ this.gridPanel ] }); this.mainViewPort.doLayout(); this.mainViewPort.syncSize(); }// End of Init(); }// End of return }(); Ext.EventManager.onDocumentReady(techbugTestMain.init, techbugTestMain, true);
groupingHeader.js mainGridPanel = function(){ //실제 데이타 들어가기 var cmm = new Ext.grid.ColumnModel([ {id:"one", header:'아이디',width:25, sortable:true}, {header:'No',width:25}, {header:'텍스트',width:50}, {header:'Info',width:50}, {header:'Special',width:60}, {header:'No',width:25}, {header:'Text',width:50}, {header:'Info',width:50}, {header:'Special',width:60}, {header:'Special',width:60}, {header:'Changed',width:50} ]); //실제 만드는 부분 cmm.rows = [ [ {header:"", align:"center", rowspan:2}, {header:"연구소", colspan:4, align:"center"}, {header:"데꾸벅", colspan:4, align:"center"}, {header:"넥스트리", colspan:2, align:"center", rowspan:2} ],[ {header:"", align:"center"}, {header:"팀명", colspan:3, align:"center"}, {header:"", align:"center" }, {header:"소속팀", colspan:3, align:"center"} ] ]; //그리드의 초기설정값을 저장한다. mainGridPanel.superclass.constructor.call(this, { region: 'center', border: false, margins:'0 0 0 0', cm: cmm, width: cmm.getTotalWidth(), store: new Ext.data.Store({ reader: new Ext.data.JsonReader({ //데이타 들어가는 부분 fields: [] }), data: [] }), enableColumnMove: false, enableDragDrop: false, enableHdMenu: false, height:100, view: new Ext.grid.GridView({forceFit:true}), title:'Array Grid', plugins: new Ext.ux.plugins.GroupHeaderGrid(), tbar: [ { text:"저장", cls: 'x-btn-icon', scope:this, handler : function(){alert('저장')} } ] }); }; Ext.extend(mainGridPanel,Ext.grid.GridPanel, { });
GroupHeaderPlugin-HdMenu.js /** * Plugin for grouped column headers * @class Ext.ux.plugins.GroupHeaderGrid * @extends Ext.util.Observable * @author ?vind Neshaug * * Based on the code in this thread: http://extjs.com/forum/showthread.php?t=12677 * Thanks to JEBriggs for starting up the code and resizing code from Clayton * Thanks to JorisA for the idea of making this a plugin instead of an extension. * * Supports infinte number of grouped header rows * Supports header group spanning of rows * */ Ext.namespace("Ext.ux.plugins"); Ext.ux.plugins.GroupHeaderGrid = function(config) { Ext.apply(this, config); }; Ext.extend(Ext.ux.plugins.GroupHeaderGrid, Ext.util.Observable, { // PLUGIN INIT init: function(grid){ this.grid = grid; this.view = this.grid.getView(); this.cm = this.grid.getColumnModel(); this.initTemplates(); this.view.renderHeaders.createInterceptor(this.renderHeaders(),this); // testing of linking bands up with headers control structure //this.linkBandsAndHeaders(); }, initTemplates: function(){ this.view.initTemplates.call(this); if(!this.templates.groupedHeader){ this.templates.groupedHeader = new Ext.Template( '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">', '<thead>{groupRows}', '<tr class="x-grid3-hd-row">{cells}</tr></thead>', '</table>' ); } if (!this.templates.groupRow){ this.templates.groupRow = new Ext.Template( '<tr class="x-grid3-hd-row">{groupCells}</tr>' ); } if(!this.templates.groupCell){ this.templates.groupCell = new Ext.Template( '<td id="{grId}" class="{cellClass}" rowspan="{rowspan}" colspan="{colspan}"><div class="x-grid3-hd-inner" unselectable="on" style="text-align:{align}">{header}</div></td>' ); } }, renderHeaders : function(cm){ if (cm){ this.cm = cm; } if(!this.cm.rows) { return true; } else { this.view.renderHeaders = this.renderGroupedHeaders.createDelegate(this); this.view.getHeaderCell = this.getHeaderCell.createDelegate(this); this.view.updateSortIcon = this.updateSortIcon.createDelegate(this); this.view.getColumnWidth = this.getColumnWidth.createDelegate(this); this.view.getColumnStyle = this.getColumnStyle.createDelegate(this); this.view.getTotalWidth = this.getTotalWidth.createDelegate(this); this.view.updateColumnHidden=this.updateColumnHidden.createDelegate(this); this.view.renderHeaders(); this.colModel = this.cm; this.headerBandLinks = this.linkBandsAndHeaders(); return false; } }, renderGroupedHeaders : function() { var cm = this.cm; var rows = this.cm.rows; var groups; var cellTemplate = this.templates.hcell; var cellMarkup = [], sb = [], cellParams = {}; var groupCellMarkup = []; var rowsMarkup = []; for (var i = 0; i < rows.length; i++) {//create markup for rows groups = rows[i]; for (var j = 0; j < groups.length; j++) {//create markup for group cells groups[j].id="ext-ux-gen-"+i+"-"+j; groupCellMarkup[groupCellMarkup.length] = this.renderGroupCell(groups[j]); } rowsMarkup[rowsMarkup.length] = this.renderGroupRows(groupCellMarkup.join("")); var groupCellMarkup = []; } for(var i = 0, len = cm.getColumnCount(); i < len; i++){ // create markup for leaf cells cellMarkup[cellMarkup.length] = this.renderHeaderCell(cm, i); } // use a different template return this.templates.groupedHeader.apply({groupRows: rowsMarkup.join(""), cells: cellMarkup.join(""), tstyle:'width:'+this.view.getTotalWidth()+';'}); }, renderGroupCell : function(group,groupId) { var template = this.templates.groupCell; var cellClass; var rowspan; if (group.colspan < 2 || group.colspan === undefined){ cellClass = "ux-grid-hd-group-nocolspan-cell"; } else { cellClass = "ux-grid-hd-group-cell"; } return template.apply({ header: group.header, colspan: group.colspan, align: group.align, rowspan: group.rowspan, cellClass: cellClass, grId: group.id }); }, renderGroupRows : function(groupCellMarkup) { var template = this.templates.groupRow; return template.apply({groupCells: groupCellMarkup}); }, renderHeaderCell : function(cm,index){ var template = this.templates.hcell; var params = {}; params.id = cm.getColumnId(index); params.value = cm.getColumnHeader(index) || ""; params.style = this.view.getColumnStyle(index, true); if(cm.config[index].align == 'right'){ params.istyle = 'padding-right:16px'; } return template.apply(params); }, // from gridview, with minor fixes getHeaderCell : function(index){ var hds = this.view.mainHd.select('.x-grid3-cell'); return (hds.item(index).dom); }, updateSortIcon : function(col, dir){ var sc = this.view.sortClasses; var hds = this.view.mainHd.select('.x-grid3-cell').removeClass(sc); hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]); }, getColumnWidth : function(col){ var w = this.cm.getColumnWidth(col); if(typeof w == 'number'){ return (Ext.isBorderBox ? w : (w-this.view.borderWidth > 0 ? w-this.view.borderWidth:0)) + 'px'; } return w; }, getColumnStyle : function(col, isHeader){ var style = !isHeader ? (this.cm.config[col].css || '') : ''; style += 'width:'+this.view.getColumnWidth(col)+';'; if(this.cm.isHidden(col)){ style += 'display:none;'; } var align = this.cm.config[col].align; if(align){ style += 'text-align:'+align+';'; } return style; }, getTotalWidth : function(){ return this.cm.getTotalWidth()+'px'; }, updateColumnHidden : function(col, hidden){ var tw = this.getTotalWidth(); var bands = this.headerBandLinks[col]||[]; this.view.innerHd.firstChild.firstChild.style.width = tw; var display = hidden ? 'none' : ''; var hd = this.getHeaderCell(col); hd.style.display = display; var ns = this.view.getRows(); for(var i = 0, len = ns.length; i < len; i++){ ns[i].style.width = tw; ns[i].firstChild.style.width = tw; ns[i].firstChild.rows[0].childNodes[col].style.display = display; } for(var i = 0, len = bands.length; i < len; i++){ var bandId = bands[i]; var band = Ext.getDom(bandId); if (hidden){ if (band.colSpan < 2 || band.colSpan === undefined){ band.style.display = 'none'; } else{ band.colSpan += -1; } } else{ if ((band.colSpan < 2 || band.colSpan === undefined)&&band.style.display === 'none'){ band.style.display = ''; } else{ band.colSpan += 1; } } } this.view.onColumnHiddenUpdated(col, hidden, tw); delete this.view.lastViewWidth; // force recalc this.view.layout(); }, linkBandsAndHeaders : function(){ var bandsWithHeader; var cm = this.grid.getColumnModel(); var columnCount = this.cm.getColumnCount(); var headers = new Array(columnCount); var headerBands = new Array(columnCount); for (var i = 0;i<columnCount;i++){ headers[i] = i; } var nrOfRows = cm.rows.length; for (var i = 0;i<nrOfRows;i++){ var headersInRow = cm.rows[i]; var headersInRowCount = headersInRow.length; var headerCounter = 0; for (var j = 0;j<headersInRowCount;j++){ while(headers[headerCounter] === null){ headerCounter++; } if (headersInRow[j].colspan < 2 || headersInRow[j].colspan === undefined){ headers[j] = null; var bands = headerBands[headerCounter]||[]; bands[bands.length]=headersInRow[j].id; headerBands[headerCounter]=bands; headerCounter++; } else { for (var k = 0;k<headersInRow[j].colspan;k++){ var bands = headerBands[headerCounter]||[]; bands[bands.length]=headersInRow[j].id; headerBands[headerCounter]=bands; headerCounter++; } } } headerCounter = 0; } return headerBands; } });
출처 :
extjs forum 크리에이티브 커먼즈 라이선스