[ 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-table', function (Y, NAME) { 9 10 /** 11 View class responsible for rendering a `<table>` from provided data. Used as 12 the default `view` for `Y.DataTable.Base` and `Y.DataTable` classes. 13 14 @module datatable 15 @submodule datatable-table 16 @since 3.6.0 17 **/ 18 var toArray = Y.Array, 19 YLang = Y.Lang, 20 fromTemplate = YLang.sub, 21 22 isArray = YLang.isArray, 23 isFunction = YLang.isFunction; 24 25 /** 26 View class responsible for rendering a `<table>` from provided data. Used as 27 the default `view` for `Y.DataTable.Base` and `Y.DataTable` classes. 28 29 30 31 @class TableView 32 @namespace DataTable 33 @extends View 34 @since 3.6.0 35 **/ 36 Y.namespace('DataTable').TableView = Y.Base.create('table', Y.View, [], { 37 38 /** 39 The HTML template used to create the caption Node if the `caption` 40 attribute is set. 41 42 @property CAPTION_TEMPLATE 43 @type {String} 44 @default '<caption class="{className}"></caption>' 45 @since 3.6.0 46 **/ 47 CAPTION_TEMPLATE: '<caption class="{className}"></caption>', 48 49 /** 50 The HTML template used to create the table Node. 51 52 @property TABLE_TEMPLATE 53 @type {String} 54 @default '<table cellspacing="0" class="{className}"></table>' 55 @since 3.6.0 56 **/ 57 TABLE_TEMPLATE : '<table cellspacing="0" class="{className}"></table>', 58 59 /** 60 The object or instance of the class assigned to `bodyView` that is 61 responsible for rendering and managing the table's `<tbody>`(s) and its 62 content. 63 64 @property body 65 @type {Object} 66 @default undefined (initially unset) 67 @since 3.5.0 68 **/ 69 //body: null, 70 71 /** 72 The object or instance of the class assigned to `footerView` that is 73 responsible for rendering and managing the table's `<tfoot>` and its 74 content. 75 76 @property foot 77 @type {Object} 78 @default undefined (initially unset) 79 @since 3.5.0 80 **/ 81 //foot: null, 82 83 /** 84 The object or instance of the class assigned to `headerView` that is 85 responsible for rendering and managing the table's `<thead>` and its 86 content. 87 88 @property head 89 @type {Object} 90 @default undefined (initially unset) 91 @since 3.5.0 92 **/ 93 //head: null, 94 95 //-----------------------------------------------------------------------// 96 // Public methods 97 //-----------------------------------------------------------------------// 98 99 /** 100 Returns the `<td>` Node from the given row and column index. Alternately, 101 the `seed` can be a Node. If so, the nearest ancestor cell is returned. 102 If the `seed` is a cell, it is returned. If there is no cell at the given 103 coordinates, `null` is returned. 104 105 Optionally, include an offset array or string to return a cell near the 106 cell identified by the `seed`. The offset can be an array containing the 107 number of rows to shift followed by the number of columns to shift, or one 108 of "above", "below", "next", or "previous". 109 110 <pre><code>// Previous cell in the previous row 111 var cell = table.getCell(e.target, [-1, -1]); 112 113 // Next cell 114 var cell = table.getCell(e.target, 'next'); 115 var cell = table.getCell(e.taregt, [0, 1];</pre></code> 116 117 This is actually just a pass through to the `bodyView` instance's method 118 by the same name. 119 120 @method getCell 121 @param {Number[]|Node} seed Array of row and column indexes, or a Node that 122 is either the cell itself or a descendant of one. 123 @param {Number[]|String} [shift] Offset by which to identify the returned 124 cell Node 125 @return {Node} 126 @since 3.5.0 127 **/ 128 getCell: function (/* seed, shift */) { 129 return this.body && this.body.getCell && 130 this.body.getCell.apply(this.body, arguments); 131 }, 132 133 /** 134 Returns the generated CSS classname based on the input. If the `host` 135 attribute is configured, it will attempt to relay to its `getClassName` 136 or use its static `NAME` property as a string base. 137 138 If `host` is absent or has neither method nor `NAME`, a CSS classname 139 will be generated using this class's `NAME`. 140 141 @method getClassName 142 @param {String} token* Any number of token strings to assemble the 143 classname from. 144 @return {String} 145 @protected 146 **/ 147 getClassName: function () { 148 // TODO: add attr with setter for host? 149 var host = this.host, 150 NAME = (host && host.constructor.NAME) || 151 this.constructor.NAME; 152 153 if (host && host.getClassName) { 154 return host.getClassName.apply(host, arguments); 155 } else { 156 return Y.ClassNameManager.getClassName 157 .apply(Y.ClassNameManager, 158 [NAME].concat(toArray(arguments, 0, true))); 159 } 160 }, 161 162 /** 163 Relays call to the `bodyView`'s `getRecord` method if it has one. 164 165 @method getRecord 166 @param {String|Node} seed Node or identifier for a row or child element 167 @return {Model} 168 @since 3.6.0 169 **/ 170 getRecord: function () { 171 return this.body && this.body.getRecord && 172 this.body.getRecord.apply(this.body, arguments); 173 }, 174 175 /** 176 Returns the `<tr>` Node from the given row index, Model, or Model's 177 `clientId`. If the rows haven't been rendered yet, or if the row can't be 178 found by the input, `null` is returned. 179 180 This is actually just a pass through to the `bodyView` instance's method 181 by the same name. 182 183 @method getRow 184 @param {Number|String|Model} id Row index, Model instance, or clientId 185 @return {Node} 186 @since 3.5.0 187 **/ 188 getRow: function (/* id */) { 189 return this.body && this.body.getRow && 190 this.body.getRow.apply(this.body, arguments); 191 }, 192 193 194 //-----------------------------------------------------------------------// 195 // Protected and private methods 196 //-----------------------------------------------------------------------// 197 /** 198 Updates the table's `summary` attribute. 199 200 @method _afterSummaryChange 201 @param {EventHandle} e The change event 202 @protected 203 @since 3.6.0 204 **/ 205 _afterSummaryChange: function (e) { 206 this._uiSetSummary(e.newVal); 207 }, 208 209 /** 210 Updates the table's `<caption>`. 211 212 @method _afterCaptionChange 213 @param {EventHandle} e The change event 214 @protected 215 @since 3.6.0 216 **/ 217 _afterCaptionChange: function (e) { 218 this._uiSetCaption(e.newVal); 219 }, 220 221 /** 222 Updates the table's width. 223 224 @method _afterWidthChange 225 @param {EventHandle} e The change event 226 @protected 227 @since 3.6.0 228 **/ 229 _afterWidthChange: function (e) { 230 this._uiSetWidth(e.newVal); 231 }, 232 233 /** 234 Attaches event subscriptions to relay attribute changes to the child Views. 235 236 @method _bindUI 237 @protected 238 @since 3.6.0 239 **/ 240 _bindUI: function () { 241 var relay; 242 243 if (!this._eventHandles) { 244 relay = Y.bind('_relayAttrChange', this); 245 246 this._eventHandles = this.after({ 247 columnsChange : relay, 248 modelListChange: relay, 249 summaryChange : Y.bind('_afterSummaryChange', this), 250 captionChange : Y.bind('_afterCaptionChange', this), 251 widthChange : Y.bind('_afterWidthChange', this) 252 }); 253 } 254 }, 255 256 /** 257 Creates the `<table>`. 258 259 @method _createTable 260 @return {Node} The `<table>` node 261 @protected 262 @since 3.5.0 263 **/ 264 _createTable: function () { 265 return Y.Node.create(fromTemplate(this.TABLE_TEMPLATE, { 266 className: this.getClassName('table') 267 })).empty(); 268 }, 269 270 /** 271 Calls `render()` on the `bodyView` class instance. 272 273 @method _defRenderBodyFn 274 @param {EventFacade} e The renderBody event 275 @protected 276 @since 3.5.0 277 **/ 278 _defRenderBodyFn: function (e) { 279 e.view.render(); 280 }, 281 282 /** 283 Calls `render()` on the `footerView` class instance. 284 285 @method _defRenderFooterFn 286 @param {EventFacade} e The renderFooter event 287 @protected 288 @since 3.5.0 289 **/ 290 _defRenderFooterFn: function (e) { 291 e.view.render(); 292 }, 293 294 /** 295 Calls `render()` on the `headerView` class instance. 296 297 @method _defRenderHeaderFn 298 @param {EventFacade} e The renderHeader event 299 @protected 300 @since 3.5.0 301 **/ 302 _defRenderHeaderFn: function (e) { 303 e.view.render(); 304 }, 305 306 /** 307 Renders the `<table>` and, if there are associated Views, the `<thead>`, 308 `<tfoot>`, and `<tbody>` (empty until `syncUI`). 309 310 Assigns the generated table nodes to the `tableNode`, `_theadNode`, 311 `_tfootNode`, and `_tbodyNode` properties. Assigns the instantiated Views 312 to the `head`, `foot`, and `body` properties. 313 314 315 @method _defRenderTableFn 316 @param {EventFacade} e The renderTable event 317 @protected 318 @since 3.5.0 319 **/ 320 _defRenderTableFn: function (e) { 321 var container = this.get('container'), 322 attrs = this.getAttrs(); 323 324 if (!this.tableNode) { 325 this.tableNode = this._createTable(); 326 } 327 328 attrs.host = this.get('host') || this; 329 attrs.table = this; 330 attrs.container = this.tableNode; 331 332 this._uiSetCaption(this.get('caption')); 333 this._uiSetSummary(this.get('summary')); 334 this._uiSetWidth(this.get('width')); 335 336 if (this.head || e.headerView) { 337 if (!this.head) { 338 this.head = new e.headerView(Y.merge(attrs, e.headerConfig)); 339 } 340 341 this.fire('renderHeader', { view: this.head }); 342 } 343 344 if (this.foot || e.footerView) { 345 if (!this.foot) { 346 this.foot = new e.footerView(Y.merge(attrs, e.footerConfig)); 347 } 348 349 this.fire('renderFooter', { view: this.foot }); 350 } 351 352 attrs.columns = this.displayColumns; 353 354 if (this.body || e.bodyView) { 355 if (!this.body) { 356 this.body = new e.bodyView(Y.merge(attrs, e.bodyConfig)); 357 } 358 359 this.fire('renderBody', { view: this.body }); 360 } 361 362 if (!container.contains(this.tableNode)) { 363 container.append(this.tableNode); 364 } 365 366 this._bindUI(); 367 }, 368 369 /** 370 Cleans up state, destroys child views, etc. 371 372 @method destructor 373 @protected 374 **/ 375 destructor: function () { 376 if (this.head && this.head.destroy) { 377 this.head.destroy(); 378 } 379 delete this.head; 380 381 if (this.foot && this.foot.destroy) { 382 this.foot.destroy(); 383 } 384 delete this.foot; 385 386 if (this.body && this.body.destroy) { 387 this.body.destroy(); 388 } 389 delete this.body; 390 391 if (this._eventHandles) { 392 this._eventHandles.detach(); 393 delete this._eventHandles; 394 } 395 396 if (this.tableNode) { 397 this.tableNode.remove().destroy(true); 398 } 399 }, 400 401 /** 402 Processes the full column array, distilling the columns down to those that 403 correspond to cell data columns. 404 405 @method _extractDisplayColumns 406 @protected 407 **/ 408 _extractDisplayColumns: function () { 409 var columns = this.get('columns'), 410 displayColumns = []; 411 412 function process(cols) { 413 var i, len, col; 414 415 for (i = 0, len = cols.length; i < len; ++i) { 416 col = cols[i]; 417 418 if (isArray(col.children)) { 419 process(col.children); 420 } else { 421 displayColumns.push(col); 422 } 423 } 424 } 425 426 if (columns) { 427 process(columns); 428 } 429 430 /** 431 Array of the columns that correspond to those with value cells in the 432 data rows. Excludes colspan header columns (configured with `children`). 433 434 @property displayColumns 435 @type {Object[]} 436 @since 3.6.0 437 **/ 438 this.displayColumns = displayColumns; 439 }, 440 441 /** 442 Publishes core events. 443 444 @method _initEvents 445 @protected 446 @since 3.5.0 447 **/ 448 _initEvents: function () { 449 this.publish({ 450 // Y.bind used to allow late binding for method override support 451 renderTable : { defaultFn: Y.bind('_defRenderTableFn', this) }, 452 renderHeader: { defaultFn: Y.bind('_defRenderHeaderFn', this) }, 453 renderBody : { defaultFn: Y.bind('_defRenderBodyFn', this) }, 454 renderFooter: { defaultFn: Y.bind('_defRenderFooterFn', this) } 455 }); 456 }, 457 458 /** 459 Constructor logic. 460 461 @method intializer 462 @param {Object} config Configuration object passed to the constructor 463 @protected 464 @since 3.6.0 465 **/ 466 initializer: function (config) { 467 this.host = config.host; 468 469 this._initEvents(); 470 471 this._extractDisplayColumns(); 472 473 this.after('columnsChange', this._extractDisplayColumns, this); 474 }, 475 476 /** 477 Relays attribute changes to the child Views. 478 479 @method _relayAttrChange 480 @param {EventHandle} e The change event 481 @protected 482 @since 3.6.0 483 **/ 484 _relayAttrChange: function (e) { 485 var attr = e.attrName, 486 val = e.newVal; 487 488 if (this.head) { 489 this.head.set(attr, val); 490 } 491 492 if (this.foot) { 493 this.foot.set(attr, val); 494 } 495 496 if (this.body) { 497 if (attr === 'columns') { 498 val = this.displayColumns; 499 } 500 501 this.body.set(attr, val); 502 } 503 }, 504 505 /** 506 Creates the UI in the configured `container`. 507 508 @method render 509 @chainable 510 **/ 511 render: function () { 512 if (this.get('container')) { 513 this.fire('renderTable', { 514 headerView : this.get('headerView'), 515 headerConfig: this.get('headerConfig'), 516 517 bodyView : this.get('bodyView'), 518 bodyConfig : this.get('bodyConfig'), 519 520 footerView : this.get('footerView'), 521 footerConfig: this.get('footerConfig') 522 }); 523 } 524 525 return this; 526 }, 527 528 /** 529 Creates, removes, or updates the table's `<caption>` element per the input 530 value. Empty values result in the caption being removed. 531 532 @method _uiSetCaption 533 @param {String} htmlContent The content to populate the table caption 534 @protected 535 @since 3.5.0 536 **/ 537 _uiSetCaption: function (htmlContent) { 538 var table = this.tableNode, 539 caption = this.captionNode; 540 541 if (htmlContent) { 542 if (!caption) { 543 this.captionNode = caption = Y.Node.create( 544 fromTemplate(this.CAPTION_TEMPLATE, { 545 className: this.getClassName('caption') 546 })); 547 548 table.prepend(this.captionNode); 549 } 550 551 caption.setHTML(htmlContent); 552 553 } else if (caption) { 554 caption.remove(true); 555 556 delete this.captionNode; 557 } 558 }, 559 560 /** 561 Updates the table's `summary` attribute with the input value. 562 563 @method _uiSetSummary 564 @protected 565 @since 3.5.0 566 **/ 567 _uiSetSummary: function (summary) { 568 if (summary) { 569 this.tableNode.setAttribute('summary', summary); 570 } else { 571 this.tableNode.removeAttribute('summary'); 572 } 573 }, 574 575 /** 576 Sets the `boundingBox` and table width per the input value. 577 578 @method _uiSetWidth 579 @param {Number|String} width The width to make the table 580 @protected 581 @since 3.5.0 582 **/ 583 _uiSetWidth: function (width) { 584 var table = this.tableNode; 585 586 // Table width needs to account for borders 587 table.setStyle('width', !width ? '' : 588 (this.get('container').get('offsetWidth') - 589 (parseInt(table.getComputedStyle('borderLeftWidth'), 10)||0) - 590 (parseInt(table.getComputedStyle('borderLeftWidth'), 10)||0)) + 591 'px'); 592 593 table.setStyle('width', width); 594 }, 595 596 /** 597 Ensures that the input is a View class or at least has a `render` method. 598 599 @method _validateView 600 @param {View|Function} val The View class 601 @return {Boolean} 602 @protected 603 **/ 604 _validateView: function (val) { 605 return isFunction(val) && val.prototype.render; 606 } 607 }, { 608 ATTRS: { 609 /** 610 Content for the `<table summary="ATTRIBUTE VALUE HERE">`. Values 611 assigned to this attribute will be HTML escaped for security. 612 613 @attribute summary 614 @type {String} 615 @default '' (empty string) 616 @since 3.5.0 617 **/ 618 //summary: {}, 619 620 /** 621 HTML content of an optional `<caption>` element to appear above the 622 table. Leave this config unset or set to a falsy value to remove the 623 caption. 624 625 @attribute caption 626 @type HTML 627 @default undefined (initially unset) 628 @since 3.6.0 629 **/ 630 //caption: {}, 631 632 /** 633 Columns to include in the rendered table. 634 635 This attribute takes an array of objects. Each object is considered a 636 data column or header cell to be rendered. How the objects are 637 translated into markup is delegated to the `headerView`, `bodyView`, 638 and `footerView`. 639 640 The raw value is passed to the `headerView` and `footerView`. The 641 `bodyView` receives the instance's `displayColumns` array, which is 642 parsed from the columns array. If there are no nested columns (columns 643 configured with a `children` array), the `displayColumns` is the same 644 as the raw value. 645 646 @attribute columns 647 @type {Object[]} 648 @since 3.6.0 649 **/ 650 columns: { 651 validator: isArray 652 }, 653 654 /** 655 Width of the table including borders. This value requires units, so 656 `200` is invalid, but `'200px'` is valid. Setting the empty string 657 (the default) will allow the browser to set the table width. 658 659 @attribute width 660 @type {String} 661 @default '' 662 @since 3.6.0 663 **/ 664 width: { 665 value: '', 666 validator: YLang.isString 667 }, 668 669 /** 670 An instance of this class is used to render the contents of the 671 `<thead>`—the column headers for the table. 672 673 The instance of this View will be assigned to the instance's `head` 674 property. 675 676 It is not strictly necessary that the class function assigned here be 677 a View subclass. It must however have a `render()` method. 678 679 @attribute headerView 680 @type {Function|Object} 681 @default Y.DataTable.HeaderView 682 @since 3.6.0 683 **/ 684 headerView: { 685 value: Y.DataTable.HeaderView, 686 validator: '_validateView' 687 }, 688 689 /** 690 Configuration overrides used when instantiating the `headerView` 691 instance. 692 693 @attribute headerConfig 694 @type {Object} 695 @since 3.6.0 696 **/ 697 //headerConfig: {}, 698 699 /** 700 An instance of this class is used to render the contents of the 701 `<tfoot>` (if appropriate). 702 703 The instance of this View will be assigned to the instance's `foot` 704 property. 705 706 It is not strictly necessary that the class function assigned here be 707 a View subclass. It must however have a `render()` method. 708 709 @attribute footerView 710 @type {Function|Object} 711 @since 3.6.0 712 **/ 713 footerView: { 714 validator: '_validateView' 715 }, 716 717 /** 718 Configuration overrides used when instantiating the `footerView` 719 instance. 720 721 @attribute footerConfig 722 @type {Object} 723 @since 3.6.0 724 **/ 725 //footerConfig: {}, 726 727 /** 728 An instance of this class is used to render the contents of the table's 729 `<tbody>`—the data cells in the table. 730 731 The instance of this View will be assigned to the instance's `body` 732 property. 733 734 It is not strictly necessary that the class function assigned here be 735 a View subclass. It must however have a `render()` method. 736 737 @attribute bodyView 738 @type {Function|Object} 739 @default Y.DataTable.BodyView 740 @since 3.6.0 741 **/ 742 bodyView: { 743 value: Y.DataTable.BodyView, 744 validator: '_validateView' 745 } 746 747 /** 748 Configuration overrides used when instantiating the `bodyView` 749 instance. 750 751 @attribute bodyConfig 752 @type {Object} 753 @since 3.6.0 754 **/ 755 //bodyConfig: {} 756 } 757 }); 758 759 760 761 762 }, '3.17.2', {"requires": ["datatable-core", "datatable-head", "datatable-body", "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 |