Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | define([ 'dojo/_base/lang', 'dojo/_base/declare', 'dojo/sniff', 'dojo/query', '../util/misc' ], function (lang, declare, has, query, miscUtil) { return declare(null, { // summary: // Extension allowing for specification of columns with additional // header rows spanning multiple columns for strictly display purposes. // Only works on `columns` arrays, not `columns` objects or `subRows` // (nor ColumnSets). // description: // CompoundColumns allows nested header cell configurations, wherein the // higher-level headers may span multiple columns and are for // display purposes only. // These nested header cells are configured using a special recursive // `children` property in the column definition, where only the deepest // children are ultimately rendered in the grid as actual columns. // In addition, the deepest child columns may be rendered without // individual headers by specifying `showChildHeaders: false` on the parent. configStructure: function () { // create a set of sub rows for the header row so we can do compound columns // the first row is a special spacer row var columns = (this.subRows && this.subRows[0]) || this.columns, headerRows = [[]], topHeaderRow = headerRows[0], contentColumns = []; // This first row is spacer row that will be made invisible (zero height) // with CSS, but it must be rendered as the first row since that is what // the table layout is driven by. headerRows[0].className = 'dgrid-spacer-row'; function processColumns(columns, level, hasLabel, parent) { var numColumns = 0, noop = function () {}, children, hasChildLabels; function processColumn(column, i) { // Handle the column config when it is an object rather // than an array. if (typeof column === 'string') { column = {label: column}; } if (!(columns instanceof Array) && !column.field) { column.field = i; } children = column.children; hasChildLabels = children && (column.showChildHeaders !== false); // Set a reference to the parent column so later the children's ids can // be updated to indicate the parent-child relationship. column.parentColumn = parent; if (children) { // it has children // make sure the column has an id if (column.id == null) { column.id = ((parent && parent.id) || level - 1) + '-' + topHeaderRow.length; } else if (parent && parent.id) { // Make sure nested compound columns have ids that are prefixed with // their parent's ids. column.id = parent.id + '-' + column.id; } } else { // it has no children, it is a normal header, add it to the content columns contentColumns.push(column); // add each one to the first spacer header row for proper layout of the header cells topHeaderRow.push(lang.delegate(column, {renderHeaderCell: noop})); numColumns++; } if (!hasChildLabels) { // create a header version of the column where we can define a specific rowSpan // we define the rowSpan as a negative, the number of levels less than the // total number of rows, which we don't know yet column = lang.delegate(column, {rowSpan: -level}); } if (children) { // Recursively process the children; this is specifically // performed *after* any potential lang.delegate calls // so the parent reference will receive additional info numColumns += (column.colSpan = processColumns(children, level + 1, hasChildLabels, column)); } // add the column to the header rows at the appropriate level if (hasLabel) { (headerRows[level] || (headerRows[level] = [])).push(column); } } miscUtil.each(columns, processColumn, this); return numColumns; } processColumns(columns, 1, true); var numHeaderRows = headerRows.length, i, j, headerRow, headerColumn; // Now go back through and increase the rowSpans of the headers to be // total rows minus the number of levels they are at. for (i = 0; i < numHeaderRows; i++) { headerRow = headerRows[i]; for (j = 0; j < headerRow.length; j++) { headerColumn = headerRow[j]; if (headerColumn.rowSpan < 1) { headerColumn.rowSpan += numHeaderRows; } } } // we need to set this to be used for subRows, so we make it a single row contentColumns = [contentColumns]; // set our header rows so that the grid will use the alternate header row // configuration for rendering the headers contentColumns.headerRows = headerRows; this.subRows = contentColumns; this.inherited(arguments); }, renderHeader: function () { var i, columns = this.subRows[0], headerColumns = this.subRows.headerRows[0]; this.inherited(arguments); // The object delegation performed in configStructure unfortunately // "protects" the original column definition objects (referenced by // columns and subRows) from obtaining headerNode information, so // copy them back in. for (i = columns.length; i--;) { columns[i].headerNode = headerColumns[i].headerNode; } }, _findSortArrowParent: function () { var parent = this.inherited(arguments), spacerRow = query('.dgrid-spacer-row', this.headerNode)[0], columnId, nodes; if (parent && spacerRow.contains(parent)) { columnId = parent.columnId; nodes = query('.dgrid-column-' + columnId, this.headerNode); return nodes[nodes.length - 1]; } }, _configColumn: function (column, rowColumns, prefix) { // Updates the id on a column definition that is a child to include // the parent's id. var parent = column.parentColumn; var columnId = column.id; if (parent) { // Adjust the id to incorporate the parent's id. // Remove the prefix if it was used to create the id var id = columnId.indexOf(prefix) === 0 ? columnId.substring(prefix.length) : columnId; prefix = parent.id + '-'; columnId = column.id = prefix + id; } this.inherited(arguments, [column, rowColumns, prefix]); }, cell: function (target, columnId) { // summary: // Get the cell object by node, event, or id, plus a columnId. // This extension prefixes children's column ids with the parents' column ids, // so cell takes that into account when looking for a column id. if (typeof columnId !== 'object') { // Find the columnId that corresponds with the provided id. // The provided id may be a suffix of the actual id. var column = this.column(columnId); if (column) { columnId = column.id; } } return this.inherited(arguments, [target, columnId]); }, column: function (target) { // summary: // Get the column object by node, event, or column id. Take into account parent column id // prefixes that may be added by this extension. var results = this.inherited(arguments); if (results == null && typeof target !== 'object') { // Find a column id that ends with the provided column id. This will locate a child column // by an id that was provided in the original column configuration. For example, if a compound column // was given the id "compound" and a child column was given the id "child", this will find the column // using only "child". If "compound-child" was being searched for, the inherited call // above would have found the cell. var suffix = '-' + target, suffixLength = suffix.length; for (var completeId in this.columns) { if (completeId.indexOf(suffix, completeId.length - suffixLength) !== -1) { return this.columns[completeId]; } } } return results; }, _updateCompoundHiddenStates: function (id, hidden) { // summary: // Called from _hideColumn and _showColumn (for ColumnHider) // to adjust parent header cells var column = this.columns[id], colSpan; if (column && column.hidden === hidden) { // Avoid redundant processing (since it would cause colSpan skew) return; } // column will be undefined when this is called for parents while (column && column.parentColumn) { // Update colSpans / hidden state of parents column = column.parentColumn; colSpan = column.colSpan = column.colSpan + (hidden ? -1 : 1); if (colSpan) { column.headerNode.colSpan = colSpan; } if (colSpan === 1 && !hidden) { this._showColumn(column.id); } else if (!colSpan && hidden) { this._hideColumn(column.id); } } }, _hideColumn: function (id) { var self = this; this._updateCompoundHiddenStates(id, true); this.inherited(arguments); if (has('ff')) { // Firefox causes display quirks in certain situations; // avoid them by forcing reflow of the header this.headerNode.style.display = 'none'; setTimeout(function () { self.headerNode.style.display = ''; self.resize(); }, 0); } }, _showColumn: function (id) { this._updateCompoundHiddenStates(id, false); this.inherited(arguments); }, _getResizedColumnWidths: function () { // Overrides ColumnResizer method to report the total width and // last column correctly for CompoundColumns structures var total = 0, columns = this.columns, id; for (id in columns) { total += columns[id].headerNode.offsetWidth; } return { totalWidth: total, lastColId: this.subRows[0][this.subRows[0].length - 1].id }; } }); }); |