define(["./GridFromHtml", "./ColumnSet", "dojo/_base/declare"], function(GridFromHtml, ColumnSet, declare){ // summary: // This module augments GridFromHtml with additional support for interpreting // ColumnSets from colgroups in table markup. function getColumnSetsFromDom(domNode){ // summary: // Generates ColumnSets from DOM. var columnsets = [], // to be pushed upon / returned cgspans = [], // stores info on columnset sizes (colgroup span) rowspans = [], // will store info on any "unexhausted" rowspans colgroups = domNode.getElementsByTagName("colgroup"), cglen = colgroups.length, trs = domNode.getElementsByTagName("tr"), trslen = trs.length, getNum = GridFromHtml.utils.getNumFromAttr, getCol = GridFromHtml.utils.getColumnFromCell, // used in loops: currcol, // keeps track of what column we're at currcg, // and which colgroup groupColumns, tr, ths, i, j, tmp; function incCurrcol(amount){ // Check whether we've passed into the next colgroup within current row. // (Used within th loop) currcol += amount; tmp = cgspans[currcg]; if(currcol >= tmp){ // First, push info for the set we just finished: // (i is still the active row index from the for loop) columnsets[currcg][i] = groupColumns; // Now, time to move on to the next columnset for this row. currcol -= tmp; currcg++; groupColumns = []; } } // no need for ColumnSet unless there's >1 colgroup if(cglen < 2){ return false; } // read span from each colgroup (defaults to 1) for(i = 0; i < cglen; i++){ // store number of cells this column spans tmp = getNum(colgroups[i], "span") || 1; cgspans[i] = tmp; // add nested array to return value to be populated for this set columnsets[i] = []; // initialize inner rowspan-tracking array for each rowspans[i] = []; for(j = 0; j < tmp; j++){ rowspans[i][j] = 0; } } for(i = 0; i < trslen; i++){ currcol = currcg = 0; groupColumns = []; tr = trs[i]; ths = tr.getElementsByTagName("th"), thslen = ths.length; for(j = 0; j < thslen; j++){ // account for space occupied by previous rowSpans while(rowspans[currcg][currcol]){ // decrement rowspan "leftover" for next iteration rowspans[currcg][currcol]--; // skip past this cell for now, and try again w/ updated currcg/col incCurrcol(1); } // store cell info tmp = getCol(ths[j]); groupColumns.push(tmp); // if this cell has rowspan, keep that in mind for future iterations rowspans[currcg][currcol] = tmp.rowSpan ? tmp.rowSpan - 1 : 0; // increment currcol/currcg appropriately, accounting for cell colSpan incCurrcol(tmp.colSpan || 1); } // At the end of processing each row, there is a chance that the last // column set didn't get pushed yet (specifically if there are trailing // rowspans - since rowspan "debt" gets iterated at the beginning of each // iteration, not the end). In that case, push the last one now. if(groupColumns.length){ columnsets[currcg][i] = groupColumns; } } if(tr){ domNode.removeChild(tr.parentNode); } return columnsets; } return declare([GridFromHtml, ColumnSet], { configStructure: function(){ // summary: // Configure subRows based on HTML originally in srcNodeRef var tmp; if(!this._checkedTrs){ tmp = getColumnSetsFromDom(this.srcNodeRef); if(tmp){ this.columnSets = tmp; this._checkedTrs = true; }else{ // no reason to worry about ColumnSets, let GridFromHtml do the job return this.inherited(arguments); } } return this.inherited(arguments); } }); });