[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 /* 2 YUI 3.17.2 (build 9c3c78e) 3 Copyright 2014 Yahoo! Inc. All rights reserved. 4 Licensed under the BSD License. 5 http://yuilibrary.com/license/ 6 */ 7 8 YUI.add('datatable-head', function (Y, NAME) { 9 10 /** 11 View class responsible for rendering the `<thead>` section of a table. Used as 12 the default `headerView` for `Y.DataTable.Base` and `Y.DataTable` classes. 13 14 @module datatable 15 @submodule datatable-head 16 @since 3.5.0 17 **/ 18 var Lang = Y.Lang, 19 fromTemplate = Lang.sub, 20 isArray = Lang.isArray, 21 toArray = Y.Array; 22 23 /** 24 View class responsible for rendering the `<thead>` section of a table. Used as 25 the default `headerView` for `Y.DataTable.Base` and `Y.DataTable` classes. 26 27 Translates the provided array of column configuration objects into a rendered 28 `<thead>` based on the data in those objects. 29 30 31 The structure of the column data is expected to be a single array of objects, 32 where each object corresponds to a `<th>`. Those objects may contain a 33 `children` property containing a similarly structured array to indicate the 34 nested cells should be grouped under the parent column's colspan in a separate 35 row of header cells. E.g. 36 37 <pre><code> 38 new Y.DataTable.HeaderView({ 39 container: tableNode, 40 columns: [ 41 { key: 'id' }, // no nesting 42 { key: 'name', children: [ 43 { key: 'firstName', label: 'First' }, 44 { key: 'lastName', label: 'Last' } ] } 45 ] 46 }).render(); 47 </code></pre> 48 49 This would translate to the following visualization: 50 51 <pre> 52 --------------------- 53 | | name | 54 | |--------------- 55 | id | First | Last | 56 --------------------- 57 </pre> 58 59 Supported properties of the column objects include: 60 61 * `label` - The HTML content of the header cell. 62 * `key` - If `label` is not specified, the `key` is used for content. 63 * `children` - Array of columns to appear below this column in the next 64 row. 65 * `headerTemplate` - Overrides the instance's `CELL_TEMPLATE` for cells in this 66 column only. 67 * `abbr` - The content of the 'abbr' attribute of the `<th>` 68 * `title` - The content of the 'title' attribute of the `<th>` 69 * `className` - Adds this string of CSS classes to the column header 70 71 Through the life of instantiation and rendering, the column objects will have 72 the following properties added to them: 73 74 * `id` - (Defaulted by DataTable) The id to assign the rendered column 75 * `_colspan` - To supply the `<th>` attribute 76 * `_rowspan` - To supply the `<th>` attribute 77 * `_parent` - (Added by DataTable) If the column is a child of another 78 column, this points to its parent column 79 80 The column object is also used to provide values for {placeholder} tokens in the 81 instance's `CELL_TEMPLATE`, so you can modify the template and include other 82 column object properties to populate them. 83 84 @class HeaderView 85 @namespace DataTable 86 @extends View 87 @since 3.5.0 88 **/ 89 Y.namespace('DataTable').HeaderView = Y.Base.create('tableHeader', Y.View, [], { 90 // -- Instance properties ------------------------------------------------- 91 92 /** 93 Template used to create the table's header cell markup. Override this to 94 customize how header cell markup is created. 95 96 @property CELL_TEMPLATE 97 @type {String} 98 @default '<th id="{id}" colspan="{_colspan}" rowspan="{_rowspan}" class="{className}" scope="col" {_id}{abbr}{title}>{content}</th>' 99 @since 3.5.0 100 **/ 101 CELL_TEMPLATE: 102 '<th id="{id}" colspan="{_colspan}" rowspan="{_rowspan}" class="{className}" scope="col" {_id}{abbr}{title}>{content}</th>', 103 104 /** 105 The data representation of the header rows to render. This is assigned by 106 parsing the `columns` configuration array, and is used by the render() 107 method. 108 109 @property columns 110 @type {Array[]} 111 @default (initially unset) 112 @since 3.5.0 113 **/ 114 //TODO: should this be protected? 115 //columns: null, 116 117 /** 118 Template used to create the table's header row markup. Override this to 119 customize the row markup. 120 121 @property ROW_TEMPLATE 122 @type {String} 123 @default '<tr>{content}</tr>' 124 @since 3.5.0 125 **/ 126 ROW_TEMPLATE: 127 '<tr>{content}</tr>', 128 129 /** 130 The object that serves as the source of truth for column and row data. 131 This property is assigned at instantiation from the `source` property of 132 the configuration object passed to the constructor. 133 134 @property source 135 @type {Object} 136 @default (initially unset) 137 @since 3.5.0 138 **/ 139 //TODO: should this be protected? 140 //source: null, 141 142 /** 143 HTML templates used to create the `<thead>` containing the table headers. 144 145 @property THEAD_TEMPLATE 146 @type {String} 147 @default '<thead class="{className}">{content}</thead>' 148 @since 3.6.0 149 **/ 150 THEAD_TEMPLATE: '<thead class="{className}"></thead>', 151 152 // -- Public methods ------------------------------------------------------ 153 154 /** 155 Returns the generated CSS classname based on the input. If the `host` 156 attribute is configured, it will attempt to relay to its `getClassName` 157 or use its static `NAME` property as a string base. 158 159 If `host` is absent or has neither method nor `NAME`, a CSS classname 160 will be generated using this class's `NAME`. 161 162 @method getClassName 163 @param {String} token* Any number of token strings to assemble the 164 classname from. 165 @return {String} 166 @protected 167 **/ 168 getClassName: function () { 169 // TODO: add attribute with setter? to host to use property this.host 170 // for performance 171 var host = this.host, 172 NAME = (host && host.constructor.NAME) || 173 this.constructor.NAME; 174 175 if (host && host.getClassName) { 176 return host.getClassName.apply(host, arguments); 177 } else { 178 return Y.ClassNameManager.getClassName 179 .apply(Y.ClassNameManager, 180 [NAME].concat(toArray(arguments, 0, true))); 181 } 182 }, 183 184 /** 185 Creates the `<thead>` Node content by assembling markup generated by 186 populating the `ROW_TEMPLATE` and `CELL_TEMPLATE` templates with content 187 from the `columns` property. 188 189 @method render 190 @chainable 191 @since 3.5.0 192 **/ 193 render: function () { 194 var table = this.get('container'), 195 thead = this.theadNode || 196 (this.theadNode = this._createTHeadNode()), 197 columns = this.columns, 198 defaults = { 199 _colspan: 1, 200 _rowspan: 1, 201 abbr: '', 202 title: '' 203 }, 204 i, len, j, jlen, col, html, content, values; 205 206 if (thead && columns) { 207 html = ''; 208 209 if (columns.length) { 210 for (i = 0, len = columns.length; i < len; ++i) { 211 content = ''; 212 213 for (j = 0, jlen = columns[i].length; j < jlen; ++j) { 214 col = columns[i][j]; 215 values = Y.merge( 216 defaults, 217 col, { 218 className: this.getClassName('header'), 219 content : col.label || col.key || 220 ("Column " + (j + 1)) 221 } 222 ); 223 224 values._id = col._id ? 225 ' data-yui3-col-id="' + col._id + '"' : ''; 226 227 if (col.abbr) { 228 values.abbr = ' abbr="' + col.abbr + '"'; 229 } 230 231 if (col.title) { 232 values.title = ' title="' + col.title + '"'; 233 } 234 235 if (col.className) { 236 values.className += ' ' + col.className; 237 } 238 239 if (col._first) { 240 values.className += ' ' + this.getClassName('first', 'header'); 241 } 242 243 if (col._id) { 244 values.className += 245 ' ' + this.getClassName('col', col._id); 246 } 247 248 content += fromTemplate( 249 col.headerTemplate || this.CELL_TEMPLATE, values); 250 } 251 252 html += fromTemplate(this.ROW_TEMPLATE, { 253 content: content 254 }); 255 } 256 } 257 258 thead.setHTML(html); 259 260 if (thead.get('parentNode') !== table) { 261 table.insertBefore(thead, table.one('tfoot, tbody')); 262 } 263 } 264 265 this.bindUI(); 266 267 return this; 268 }, 269 270 // -- Protected and private properties and methods ------------------------ 271 272 /** 273 Handles changes in the source's columns attribute. Redraws the headers. 274 275 @method _afterColumnsChange 276 @param {EventFacade} e The `columnsChange` event object 277 @protected 278 @since 3.5.0 279 **/ 280 _afterColumnsChange: function (e) { 281 this.columns = this._parseColumns(e.newVal); 282 283 this.render(); 284 }, 285 286 /** 287 Binds event subscriptions from the UI and the source (if assigned). 288 289 @method bindUI 290 @protected 291 @since 3.5.0 292 **/ 293 bindUI: function () { 294 if (!this._eventHandles.columnsChange) { 295 // TODO: How best to decouple this? 296 this._eventHandles.columnsChange = 297 this.after('columnsChange', 298 Y.bind('_afterColumnsChange', this)); 299 } 300 }, 301 302 /** 303 Creates the `<thead>` node that will store the header rows and cells. 304 305 @method _createTHeadNode 306 @return {Node} 307 @protected 308 @since 3.6.0 309 **/ 310 _createTHeadNode: function () { 311 return Y.Node.create(fromTemplate(this.THEAD_TEMPLATE, { 312 className: this.getClassName('columns') 313 })); 314 }, 315 316 /** 317 Destroys the instance. 318 319 @method destructor 320 @protected 321 @since 3.5.0 322 **/ 323 destructor: function () { 324 (new Y.EventHandle(Y.Object.values(this._eventHandles))).detach(); 325 }, 326 327 /** 328 Holds the event subscriptions needing to be detached when the instance is 329 `destroy()`ed. 330 331 @property _eventHandles 332 @type {Object} 333 @default undefined (initially unset) 334 @protected 335 @since 3.5.0 336 **/ 337 //_eventHandles: null, 338 339 /** 340 Initializes the instance. Reads the following configuration properties: 341 342 * `columns` - (REQUIRED) The initial column information 343 * `host` - The object to serve as source of truth for column info 344 345 @method initializer 346 @param {Object} config Configuration data 347 @protected 348 @since 3.5.0 349 **/ 350 initializer: function (config) { 351 this.host = config.host; 352 this.columns = this._parseColumns(config.columns); 353 354 this._eventHandles = []; 355 }, 356 357 /** 358 Translate the input column format into a structure useful for rendering a 359 `<thead>`, rows, and cells. The structure of the input is expected to be a 360 single array of objects, where each object corresponds to a `<th>`. Those 361 objects may contain a `children` property containing a similarly structured 362 array to indicate the nested cells should be grouped under the parent 363 column's colspan in a separate row of header cells. E.g. 364 365 <pre><code> 366 [ 367 { key: 'id' }, // no nesting 368 { key: 'name', children: [ 369 { key: 'firstName', label: 'First' }, 370 { key: 'lastName', label: 'Last' } ] } 371 ] 372 </code></pre> 373 374 would indicate two header rows with the first column 'id' being assigned a 375 `rowspan` of `2`, the 'name' column appearing in the first row with a 376 `colspan` of `2`, and the 'firstName' and 'lastName' columns appearing in 377 the second row, below the 'name' column. 378 379 <pre> 380 --------------------- 381 | | name | 382 | |--------------- 383 | id | First | Last | 384 --------------------- 385 </pre> 386 387 Supported properties of the column objects include: 388 389 * `label` - The HTML content of the header cell. 390 * `key` - If `label` is not specified, the `key` is used for content. 391 * `children` - Array of columns to appear below this column in the next 392 row. 393 * `abbr` - The content of the 'abbr' attribute of the `<th>` 394 * `title` - The content of the 'title' attribute of the `<th>` 395 * `headerTemplate` - Overrides the instance's `CELL_TEMPLATE` for cells 396 in this column only. 397 398 The output structure is basically a simulation of the `<thead>` structure 399 with arrays for rows and objects for cells. Column objects have the 400 following properties added to them: 401 402 * `id` - (Defaulted by DataTable) The id to assign the rendered 403 column 404 * `_colspan` - Per the `<th>` attribute 405 * `_rowspan` - Per the `<th>` attribute 406 * `_parent` - (Added by DataTable) If the column is a child of another 407 column, this points to its parent column 408 409 The column object is also used to provide values for {placeholder} 410 replacement in the `CELL_TEMPLATE`, so you can modify the template and 411 include other column object properties to populate them. 412 413 @method _parseColumns 414 @param {Object[]} data Array of column object data 415 @return {Array[]} An array of arrays corresponding to the header row 416 structure to render 417 @protected 418 @since 3.5.0 419 **/ 420 _parseColumns: function (data) { 421 var columns = [], 422 stack = [], 423 rowSpan = 1, 424 entry, row, col, children, parent, i, len, j; 425 426 if (isArray(data) && data.length) { 427 // don't modify the input array 428 data = data.slice(); 429 430 // First pass, assign colspans and calculate row count for 431 // non-nested headers' rowspan 432 stack.push([data, -1]); 433 434 while (stack.length) { 435 entry = stack[stack.length - 1]; 436 row = entry[0]; 437 i = entry[1] + 1; 438 439 for (len = row.length; i < len; ++i) { 440 row[i] = col = Y.merge(row[i]); 441 children = col.children; 442 443 Y.stamp(col); 444 445 if (!col.id) { 446 col.id = Y.guid(); 447 } 448 449 if (isArray(children) && children.length) { 450 stack.push([children, -1]); 451 entry[1] = i; 452 453 rowSpan = Math.max(rowSpan, stack.length); 454 455 // break to let the while loop process the children 456 break; 457 } else { 458 col._colspan = 1; 459 } 460 } 461 462 if (i >= len) { 463 // All columns in this row are processed 464 if (stack.length > 1) { 465 entry = stack[stack.length - 2]; 466 parent = entry[0][entry[1]]; 467 468 parent._colspan = 0; 469 470 for (i = 0, len = row.length; i < len; ++i) { 471 // Can't use .length because in 3+ rows, colspan 472 // needs to aggregate the colspans of children 473 row[i]._parent = parent; 474 parent._colspan += row[i]._colspan; 475 } 476 } 477 stack.pop(); 478 } 479 } 480 481 // Second pass, build row arrays and assign rowspan 482 for (i = 0; i < rowSpan; ++i) { 483 columns.push([]); 484 } 485 486 stack.push([data, -1]); 487 488 while (stack.length) { 489 entry = stack[stack.length - 1]; 490 row = entry[0]; 491 i = entry[1] + 1; 492 493 for (len = row.length; i < len; ++i) { 494 col = row[i]; 495 children = col.children; 496 497 columns[stack.length - 1].push(col); 498 499 entry[1] = i; 500 501 // collect the IDs of parent cols 502 col._headers = [col.id]; 503 504 for (j = stack.length - 2; j >= 0; --j) { 505 parent = stack[j][0][stack[j][1]]; 506 507 col._headers.unshift(parent.id); 508 } 509 510 if (children && children.length) { 511 // parent cells must assume rowspan 1 (long story) 512 513 // break to let the while loop process the children 514 stack.push([children, -1]); 515 break; 516 } else { 517 col._rowspan = rowSpan - stack.length + 1; 518 } 519 } 520 521 if (i >= len) { 522 // All columns in this row are processed 523 stack.pop(); 524 } 525 } 526 } 527 528 for (i = 0, len = columns.length; i < len; i += col._rowspan) { 529 col = columns[i][0]; 530 531 col._first = true; 532 } 533 534 return columns; 535 } 536 }); 537 538 539 }, '3.17.2', {"requires": ["datatable-core", "view", "classnamemanager"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |