[ 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-core', function (Y, NAME) { 9 10 /** 11 The core implementation of the `DataTable` and `DataTable.Base` Widgets. 12 13 @module datatable 14 @submodule datatable-core 15 @since 3.5.0 16 **/ 17 18 var INVALID = Y.Attribute.INVALID_VALUE, 19 20 Lang = Y.Lang, 21 isFunction = Lang.isFunction, 22 isObject = Lang.isObject, 23 isArray = Lang.isArray, 24 isString = Lang.isString, 25 isNumber = Lang.isNumber, 26 27 toArray = Y.Array, 28 29 keys = Y.Object.keys, 30 31 Table; 32 33 /** 34 _API docs for this extension are included in the DataTable class._ 35 36 Class extension providing the core API and structure for the DataTable Widget. 37 38 Use this class extension with Widget or another Base-based superclass to create 39 the basic DataTable model API and composing class structure. 40 41 @class DataTable.Core 42 @for DataTable 43 @since 3.5.0 44 **/ 45 Table = Y.namespace('DataTable').Core = function () {}; 46 47 Table.ATTRS = { 48 /** 49 Columns to include in the rendered table. 50 51 If omitted, the attributes on the configured `recordType` or the first item 52 in the `data` collection will be used as a source. 53 54 This attribute takes an array of strings or objects (mixing the two is 55 fine). Each string or object is considered a column to be rendered. 56 Strings are converted to objects, so `columns: ['first', 'last']` becomes 57 `columns: [{ key: 'first' }, { key: 'last' }]`. 58 59 DataTable.Core only concerns itself with a few properties of columns. 60 These properties are: 61 62 * `key` - Used to identify the record field/attribute containing content for 63 this column. Also used to create a default Model if no `recordType` or 64 `data` are provided during construction. If `name` is not specified, this 65 is assigned to the `_id` property (with added incrementer if the key is 66 used by multiple columns). 67 * `children` - Traversed to initialize nested column objects 68 * `name` - Used in place of, or in addition to, the `key`. Useful for 69 columns that aren't bound to a field/attribute in the record data. This 70 is assigned to the `_id` property. 71 * `id` - For backward compatibility. Implementers can specify the id of 72 the header cell. This should be avoided, if possible, to avoid the 73 potential for creating DOM elements with duplicate IDs. 74 * `field` - For backward compatibility. Implementers should use `name`. 75 * `_id` - Assigned unique-within-this-instance id for a column. By order 76 of preference, assumes the value of `name`, `key`, `id`, or `_yuid`. 77 This is used by the rendering views as well as feature module 78 as a means to identify a specific column without ambiguity (such as 79 multiple columns using the same `key`. 80 * `_yuid` - Guid stamp assigned to the column object. 81 * `_parent` - Assigned to all child columns, referencing their parent 82 column. 83 84 @attribute columns 85 @type {Object[]|String[]} 86 @default (from `recordType` ATTRS or first item in the `data`) 87 @since 3.5.0 88 **/ 89 columns: { 90 // TODO: change to setter to clone input array/objects 91 validator: isArray, 92 setter: '_setColumns', 93 getter: '_getColumns' 94 }, 95 96 /** 97 Model subclass to use as the `model` for the ModelList stored in the `data` 98 attribute. 99 100 If not provided, it will try really hard to figure out what to use. The 101 following attempts will be made to set a default value: 102 103 1. If the `data` attribute is set with a ModelList instance and its `model` 104 property is set, that will be used. 105 2. If the `data` attribute is set with a ModelList instance, and its 106 `model` property is unset, but it is populated, the `ATTRS` of the 107 `constructor of the first item will be used. 108 3. If the `data` attribute is set with a non-empty array, a Model subclass 109 will be generated using the keys of the first item as its `ATTRS` (see 110 the `_createRecordClass` method). 111 4. If the `columns` attribute is set, a Model subclass will be generated 112 using the columns defined with a `key`. This is least desirable because 113 columns can be duplicated or nested in a way that's not parsable. 114 5. If neither `data` nor `columns` is set or populated, a change event 115 subscriber will listen for the first to be changed and try all over 116 again. 117 118 @attribute recordType 119 @type {Function} 120 @default (see description) 121 @since 3.5.0 122 **/ 123 recordType: { 124 getter: '_getRecordType', 125 setter: '_setRecordType' 126 }, 127 128 /** 129 The collection of data records to display. This attribute is a pass 130 through to a `data` property, which is a ModelList instance. 131 132 If this attribute is passed a ModelList or subclass, it will be assigned to 133 the property directly. If an array of objects is passed, a new ModelList 134 will be created using the configured `recordType` as its `model` property 135 and seeded with the array. 136 137 Retrieving this attribute will return the ModelList stored in the `data` 138 property. 139 140 @attribute data 141 @type {ModelList|Object[]} 142 @default `new ModelList()` 143 @since 3.5.0 144 **/ 145 data: { 146 valueFn: '_initData', 147 setter : '_setData', 148 lazyAdd: false 149 }, 150 151 /** 152 Content for the `<table summary="ATTRIBUTE VALUE HERE">`. Values assigned 153 to this attribute will be HTML escaped for security. 154 155 @attribute summary 156 @type {String} 157 @default '' (empty string) 158 @since 3.5.0 159 **/ 160 //summary: {}, 161 162 /** 163 HTML content of an optional `<caption>` element to appear above the table. 164 Leave this config unset or set to a falsy value to remove the caption. 165 166 @attribute caption 167 @type HTML 168 @default '' (empty string) 169 @since 3.5.0 170 **/ 171 //caption: {}, 172 173 /** 174 Deprecated as of 3.5.0. Passes through to the `data` attribute. 175 176 WARNING: `get('recordset')` will NOT return a Recordset instance as of 177 3.5.0. This is a break in backward compatibility. 178 179 @attribute recordset 180 @type {Object[]|Recordset} 181 @deprecated Use the `data` attribute 182 @since 3.5.0 183 **/ 184 recordset: { 185 setter: '_setRecordset', 186 getter: '_getRecordset', 187 lazyAdd: false 188 }, 189 190 /** 191 Deprecated as of 3.5.0. Passes through to the `columns` attribute. 192 193 WARNING: `get('columnset')` will NOT return a Columnset instance as of 194 3.5.0. This is a break in backward compatibility. 195 196 @attribute columnset 197 @type {Object[]} 198 @deprecated Use the `columns` attribute 199 @since 3.5.0 200 **/ 201 columnset: { 202 setter: '_setColumnset', 203 getter: '_getColumnset', 204 lazyAdd: false 205 } 206 }; 207 208 Y.mix(Table.prototype, { 209 // -- Instance properties ------------------------------------------------- 210 /** 211 The ModelList that manages the table's data. 212 213 @property data 214 @type {ModelList} 215 @default undefined (initially unset) 216 @since 3.5.0 217 **/ 218 //data: null, 219 220 // -- Public methods ------------------------------------------------------ 221 222 /** 223 Gets the column configuration object for the given key, name, or index. For 224 nested columns, `name` can be an array of indexes, each identifying the index 225 of that column in the respective parent's "children" array. 226 227 If you pass a column object, it will be returned. 228 229 For columns with keys, you can also fetch the column with 230 `instance.get('columns.foo')`. 231 232 @method getColumn 233 @param {String|Number|Number[]} name Key, "name", index, or index array to 234 identify the column 235 @return {Object} the column configuration object 236 @since 3.5.0 237 **/ 238 getColumn: function (name) { 239 var col, columns, i, len, cols; 240 241 if (isObject(name) && !isArray(name)) { 242 if (name && name._node) { 243 col = this.body.getColumn(name); 244 } else { 245 col = name; 246 } 247 } else { 248 col = this.get('columns.' + name); 249 } 250 251 if (col) { 252 return col; 253 } 254 255 columns = this.get('columns'); 256 257 if (isNumber(name) || isArray(name)) { 258 name = toArray(name); 259 cols = columns; 260 261 for (i = 0, len = name.length - 1; cols && i < len; ++i) { 262 cols = cols[name[i]] && cols[name[i]].children; 263 } 264 265 return (cols && cols[name[i]]) || null; 266 } 267 268 return null; 269 }, 270 271 /** 272 Returns the Model associated to the record `id`, `clientId`, or index (not 273 row index). If none of those yield a Model from the `data` ModelList, the 274 arguments will be passed to the `view` instance's `getRecord` method 275 if it has one. 276 277 If no Model can be found, `null` is returned. 278 279 @method getRecord 280 @param {Number|String|Node} seed Record `id`, `clientId`, index, Node, or 281 identifier for a row or child element 282 @return {Model} 283 @since 3.5.0 284 **/ 285 getRecord: function (seed) { 286 var record = this.data.getById(seed) || this.data.getByClientId(seed); 287 288 if (!record) { 289 if (isNumber(seed)) { 290 record = this.data.item(seed); 291 } 292 293 // TODO: this should be split out to base somehow 294 if (!record && this.view && this.view.getRecord) { 295 record = this.view.getRecord.apply(this.view, arguments); 296 } 297 } 298 299 return record || null; 300 }, 301 302 // -- Protected and private properties and methods ------------------------ 303 304 /** 305 This tells `Y.Base` that it should create ad-hoc attributes for config 306 properties passed to DataTable's constructor. This is useful for setting 307 configurations on the DataTable that are intended for the rendering View(s). 308 309 @property _allowAdHocAttrs 310 @type Boolean 311 @default true 312 @protected 313 @since 3.6.0 314 **/ 315 _allowAdHocAttrs: true, 316 317 /** 318 A map of column key to column configuration objects parsed from the 319 `columns` attribute. 320 321 @property _columnMap 322 @type {Object} 323 @default undefined (initially unset) 324 @protected 325 @since 3.5.0 326 **/ 327 //_columnMap: null, 328 329 /** 330 The Node instance of the table containing the data rows. This is set when 331 the table is rendered. It may also be set by progressive enhancement, 332 though this extension does not provide the logic to parse from source. 333 334 @property _tableNode 335 @type {Node} 336 @default undefined (initially unset) 337 @protected 338 @since 3.5.0 339 **/ 340 //_tableNode: null, 341 342 /** 343 Updates the `_columnMap` property in response to changes in the `columns` 344 attribute. 345 346 @method _afterColumnsChange 347 @param {EventFacade} e The `columnsChange` event object 348 @protected 349 @since 3.5.0 350 **/ 351 _afterColumnsChange: function (e) { 352 this._setColumnMap(e.newVal); 353 }, 354 355 /** 356 Updates the `modelList` attributes of the rendered views in response to the 357 `data` attribute being assigned a new ModelList. 358 359 @method _afterDataChange 360 @param {EventFacade} e the `dataChange` event 361 @protected 362 @since 3.5.0 363 **/ 364 _afterDataChange: function (e) { 365 var modelList = e.newVal; 366 367 this.data = e.newVal; 368 369 if (!this.get('columns') && modelList.size()) { 370 // TODO: this will cause a re-render twice because the Views are 371 // subscribed to columnsChange 372 this._initColumns(); 373 } 374 }, 375 376 /** 377 Assigns to the new recordType as the model for the data ModelList 378 379 @method _afterRecordTypeChange 380 @param {EventFacade} e recordTypeChange event 381 @protected 382 @since 3.6.0 383 **/ 384 _afterRecordTypeChange: function (e) { 385 var data = this.data.toJSON(); 386 387 this.data.model = e.newVal; 388 389 this.data.reset(data); 390 391 if (!this.get('columns') && data) { 392 if (data.length) { 393 this._initColumns(); 394 } else { 395 this.set('columns', keys(e.newVal.ATTRS)); 396 } 397 } 398 }, 399 400 /** 401 Creates a Model subclass from an array of attribute names or an object of 402 attribute definitions. This is used to generate a class suitable to 403 represent the data passed to the `data` attribute if no `recordType` is 404 set. 405 406 @method _createRecordClass 407 @param {String[]|Object} attrs Names assigned to the Model subclass's 408 `ATTRS` or its entire `ATTRS` definition object 409 @return {Model} 410 @protected 411 @since 3.5.0 412 **/ 413 _createRecordClass: function (attrs) { 414 var ATTRS, i, len; 415 416 if (isArray(attrs)) { 417 ATTRS = {}; 418 419 for (i = 0, len = attrs.length; i < len; ++i) { 420 ATTRS[attrs[i]] = {}; 421 } 422 } else if (isObject(attrs)) { 423 ATTRS = attrs; 424 } 425 426 return Y.Base.create('record', Y.Model, [], null, { ATTRS: ATTRS }); 427 }, 428 429 /** 430 Tears down the instance. 431 432 @method destructor 433 @protected 434 @since 3.6.0 435 **/ 436 destructor: function () { 437 new Y.EventHandle(Y.Object.values(this._eventHandles)).detach(); 438 }, 439 440 /** 441 The getter for the `columns` attribute. Returns the array of column 442 configuration objects if `instance.get('columns')` is called, or the 443 specific column object if `instance.get('columns.columnKey')` is called. 444 445 @method _getColumns 446 @param {Object[]} columns The full array of column objects 447 @param {String} name The attribute name requested 448 (e.g. 'columns' or 'columns.foo'); 449 @protected 450 @since 3.5.0 451 **/ 452 _getColumns: function (columns, name) { 453 // Workaround for an attribute oddity (ticket #2529254) 454 // getter is expected to return an object if get('columns.foo') is called. 455 // Note 'columns.' is 8 characters 456 return name.length > 8 ? this._columnMap : columns; 457 }, 458 459 /** 460 Relays the `get()` request for the deprecated `columnset` attribute to the 461 `columns` attribute. 462 463 THIS BREAKS BACKWARD COMPATIBILITY. 3.4.1 and prior implementations will 464 expect a Columnset instance returned from `get('columnset')`. 465 466 @method _getColumnset 467 @param {Object} ignored The current value stored in the `columnset` state 468 @param {String} name The attribute name requested 469 (e.g. 'columnset' or 'columnset.foo'); 470 @deprecated This will be removed with the `columnset` attribute in a future 471 version. 472 @protected 473 @since 3.5.0 474 **/ 475 _getColumnset: function (_, name) { 476 return this.get(name.replace(/^columnset/, 'columns')); 477 }, 478 479 /** 480 Returns the Model class of the instance's `data` attribute ModelList. If 481 not set, returns the explicitly configured value. 482 483 @method _getRecordType 484 @param {Model} val The currently configured value 485 @return {Model} 486 **/ 487 _getRecordType: function (val) { 488 // Prefer the value stored in the attribute because the attribute 489 // change event defaultFn sets e.newVal = this.get('recordType') 490 // before notifying the after() subs. But if this getter returns 491 // this.data.model, then after() subs would get e.newVal === previous 492 // model before _afterRecordTypeChange can set 493 // this.data.model = e.newVal 494 return val || (this.data && this.data.model); 495 }, 496 497 /** 498 Initializes the `_columnMap` property from the configured `columns` 499 attribute. If `columns` is not set, but there are records in the `data` 500 ModelList, use 501 `ATTRS` of that class. 502 503 @method _initColumns 504 @protected 505 @since 3.5.0 506 **/ 507 _initColumns: function () { 508 var columns = this.get('columns') || [], 509 item; 510 511 // Default column definition from the configured recordType 512 if (!columns.length && this.data.size()) { 513 // TODO: merge superclass attributes up to Model? 514 item = this.data.item(0); 515 516 if (item.toJSON) { 517 item = item.toJSON(); 518 } 519 520 this.set('columns', keys(item)); 521 } 522 523 this._setColumnMap(columns); 524 }, 525 526 /** 527 Sets up the change event subscriptions to maintain internal state. 528 529 @method _initCoreEvents 530 @protected 531 @since 3.6.0 532 **/ 533 _initCoreEvents: function () { 534 this._eventHandles.coreAttrChanges = this.after({ 535 columnsChange : Y.bind('_afterColumnsChange', this), 536 recordTypeChange: Y.bind('_afterRecordTypeChange', this), 537 dataChange : Y.bind('_afterDataChange', this) 538 }); 539 }, 540 541 /** 542 Defaults the `data` attribute to an empty ModelList if not set during 543 construction. Uses the configured `recordType` for the ModelList's `model` 544 proeprty if set. 545 546 @method _initData 547 @protected 548 @return {ModelList} 549 @since 3.6.0 550 **/ 551 _initData: function () { 552 var recordType = this.get('recordType'), 553 // TODO: LazyModelList if recordType doesn't have complex ATTRS 554 modelList = new Y.ModelList(); 555 556 if (recordType) { 557 modelList.model = recordType; 558 } 559 560 return modelList; 561 }, 562 563 /** 564 Initializes the instance's `data` property from the value of the `data` 565 attribute. If the attribute value is a ModelList, it is assigned directly 566 to `this.data`. If it is an array, a ModelList is created, its `model` 567 property is set to the configured `recordType` class, and it is seeded with 568 the array data. This ModelList is then assigned to `this.data`. 569 570 @method _initDataProperty 571 @param {Array|ModelList|ArrayList} data Collection of data to populate the 572 DataTable 573 @protected 574 @since 3.6.0 575 **/ 576 _initDataProperty: function (data) { 577 var recordType; 578 579 if (!this.data) { 580 recordType = this.get('recordType'); 581 582 if (data && data.each && data.toJSON) { 583 this.data = data; 584 585 if (recordType) { 586 this.data.model = recordType; 587 } 588 } else { 589 // TODO: customize the ModelList or read the ModelList class 590 // from a configuration option? 591 this.data = new Y.ModelList(); 592 593 if (recordType) { 594 this.data.model = recordType; 595 } 596 } 597 598 // TODO: Replace this with an event relay for specific events. 599 // Using bubbling causes subscription conflicts with the models' 600 // aggregated change event and 'change' events from DOM elements 601 // inside the table (via Widget UI event). 602 this.data.addTarget(this); 603 } 604 }, 605 606 /** 607 Initializes the columns, `recordType` and data ModelList. 608 609 @method initializer 610 @param {Object} config Configuration object passed to constructor 611 @protected 612 @since 3.5.0 613 **/ 614 initializer: function (config) { 615 var data = config.data, 616 columns = config.columns, 617 recordType; 618 619 // Referencing config.data to allow _setData to be more stringent 620 // about its behavior 621 this._initDataProperty(data); 622 623 // Default columns from recordType ATTRS if recordType is supplied at 624 // construction. If no recordType is supplied, but the data is 625 // supplied as a non-empty array, use the keys of the first item 626 // as the columns. 627 if (!columns) { 628 recordType = (config.recordType || config.data === this.data) && 629 this.get('recordType'); 630 631 if (recordType) { 632 columns = keys(recordType.ATTRS); 633 } else if (isArray(data) && data.length) { 634 columns = keys(data[0]); 635 } 636 637 if (columns) { 638 this.set('columns', columns); 639 } 640 } 641 642 this._initColumns(); 643 644 this._eventHandles = {}; 645 646 this._initCoreEvents(); 647 }, 648 649 /** 650 Iterates the array of column configurations to capture all columns with a 651 `key` property. An map is built with column keys as the property name and 652 the corresponding column object as the associated value. This map is then 653 assigned to the instance's `_columnMap` property. 654 655 @method _setColumnMap 656 @param {Object[]|String[]} columns The array of column config objects 657 @protected 658 @since 3.6.0 659 **/ 660 _setColumnMap: function (columns) { 661 var map = {}; 662 663 function process(cols) { 664 var i, len, col, key; 665 666 for (i = 0, len = cols.length; i < len; ++i) { 667 col = cols[i]; 668 key = col.key; 669 670 // First in wins for multiple columns with the same key 671 // because the first call to genId (in _setColumns) will 672 // return the same key, which will then be overwritten by the 673 // subsequent same-keyed column. So table.getColumn(key) would 674 // return the last same-keyed column. 675 if (key && !map[key]) { 676 map[key] = col; 677 } 678 //TODO: named columns can conflict with keyed columns 679 map[col._id] = col; 680 681 if (col.children) { 682 process(col.children); 683 } 684 } 685 } 686 687 process(columns); 688 689 this._columnMap = map; 690 }, 691 692 /** 693 Translates string columns into objects with that string as the value of its 694 `key` property. 695 696 All columns are assigned a `_yuid` stamp and `_id` property corresponding 697 to the column's configured `name` or `key` property with any spaces 698 replaced with dashes. If the same `name` or `key` appears in multiple 699 columns, subsequent appearances will have their `_id` appended with an 700 incrementing number (e.g. if column "foo" is included in the `columns` 701 attribute twice, the first will get `_id` of "foo", and the second an `_id` 702 of "foo1"). Columns that are children of other columns will have the 703 `_parent` property added, assigned the column object to which they belong. 704 705 @method _setColumns 706 @param {null|Object[]|String[]} val Array of config objects or strings 707 @return {null|Object[]} 708 @protected 709 **/ 710 _setColumns: function (val) { 711 var keys = {}, 712 known = [], 713 knownCopies = [], 714 arrayIndex = Y.Array.indexOf; 715 716 function copyObj(o) { 717 var copy = {}, 718 key, val, i; 719 720 known.push(o); 721 knownCopies.push(copy); 722 723 for (key in o) { 724 if (o.hasOwnProperty(key)) { 725 val = o[key]; 726 727 if (isArray(val)) { 728 copy[key] = val.slice(); 729 } else if (isObject(val, true)) { 730 i = arrayIndex(known, val); 731 732 copy[key] = i === -1 ? copyObj(val) : knownCopies[i]; 733 } else { 734 copy[key] = o[key]; 735 } 736 } 737 } 738 739 return copy; 740 } 741 742 function genId(name) { 743 // Sanitize the name for use in generated CSS classes. 744 // TODO: is there more to do for other uses of _id? 745 name = name.replace(/\s+/, '-'); 746 747 if (keys[name]) { 748 name += (keys[name]++); 749 } else { 750 keys[name] = 1; 751 } 752 753 return name; 754 } 755 756 function process(cols, parent) { 757 var columns = [], 758 i, len, col, yuid; 759 760 for (i = 0, len = cols.length; i < len; ++i) { 761 columns[i] = // chained assignment 762 col = isString(cols[i]) ? { key: cols[i] } : copyObj(cols[i]); 763 764 yuid = Y.stamp(col); 765 766 // For backward compatibility 767 if (!col.id) { 768 // Implementers can shoot themselves in the foot by setting 769 // this config property to a non-unique value 770 col.id = yuid; 771 } 772 if (col.field) { 773 // Field is now known as "name" to avoid confusion with data 774 // fields or schema.resultFields 775 col.name = col.field; 776 } 777 778 if (parent) { 779 col._parent = parent; 780 } else { 781 delete col._parent; 782 } 783 784 // Unique id based on the column's configured name or key, 785 // falling back to the yuid. Duplicates will have a counter 786 // added to the end. 787 col._id = genId(col.name || col.key || col.id); 788 789 if (isArray(col.children)) { 790 col.children = process(col.children, col); 791 } 792 } 793 794 return columns; 795 } 796 797 return val && process(val); 798 }, 799 800 /** 801 Relays attribute assignments of the deprecated `columnset` attribute to the 802 `columns` attribute. If a Columnset is object is passed, its basic object 803 structure is mined. 804 805 @method _setColumnset 806 @param {Array|Columnset} val The columnset value to relay 807 @deprecated This will be removed with the deprecated `columnset` attribute 808 in a later version. 809 @protected 810 @since 3.5.0 811 **/ 812 _setColumnset: function (val) { 813 this.set('columns', val); 814 815 return isArray(val) ? val : INVALID; 816 }, 817 818 /** 819 Accepts an object with `each` and `getAttrs` (preferably a ModelList or 820 subclass) or an array of data objects. If an array is passes, it will 821 create a ModelList to wrap the data. In doing so, it will set the created 822 ModelList's `model` property to the class in the `recordType` attribute, 823 which will be defaulted if not yet set. 824 825 If the `data` property is already set with a ModelList, passing an array as 826 the value will call the ModelList's `reset()` method with that array rather 827 than replacing the stored ModelList wholesale. 828 829 Any non-ModelList-ish and non-array value is invalid. 830 831 @method _setData 832 @protected 833 @since 3.5.0 834 **/ 835 _setData: function (val) { 836 if (val === null) { 837 val = []; 838 } 839 840 if (isArray(val)) { 841 this._initDataProperty(); 842 843 // silent to prevent subscribers to both reset and dataChange 844 // from reacting to the change twice. 845 // TODO: would it be better to return INVALID to silence the 846 // dataChange event, or even allow both events? 847 this.data.reset(val, { silent: true }); 848 849 // Return the instance ModelList to avoid storing unprocessed 850 // data in the state and their vivified Model representations in 851 // the instance's data property. Decreases memory consumption. 852 val = this.data; 853 } else if (!val || !val.each || !val.toJSON) { 854 // ModelList/ArrayList duck typing 855 val = INVALID; 856 } 857 858 return val; 859 }, 860 861 /** 862 Relays the value assigned to the deprecated `recordset` attribute to the 863 `data` attribute. If a Recordset instance is passed, the raw object data 864 will be culled from it. 865 866 @method _setRecordset 867 @param {Object[]|Recordset} val The recordset value to relay 868 @deprecated This will be removed with the deprecated `recordset` attribute 869 in a later version. 870 @protected 871 @since 3.5.0 872 **/ 873 _setRecordset: function (val) { 874 var data; 875 876 if (val && Y.Recordset && val instanceof Y.Recordset) { 877 data = []; 878 val.each(function (record) { 879 data.push(record.get('data')); 880 }); 881 val = data; 882 } 883 884 this.set('data', val); 885 886 return val; 887 }, 888 889 /** 890 Accepts a Base subclass (preferably a Model subclass). Alternately, it will 891 generate a custom Model subclass from an array of attribute names or an 892 object defining attributes and their respective configurations (it is 893 assigned as the `ATTRS` of the new class). 894 895 Any other value is invalid. 896 897 @method _setRecordType 898 @param {Function|String[]|Object} val The Model subclass, array of 899 attribute names, or the `ATTRS` definition for a custom model 900 subclass 901 @return {Function} A Base/Model subclass 902 @protected 903 @since 3.5.0 904 **/ 905 _setRecordType: function (val) { 906 var modelClass; 907 908 // Duck type based on known/likely consumed APIs 909 if (isFunction(val) && val.prototype.toJSON && val.prototype.setAttrs) { 910 modelClass = val; 911 } else if (isObject(val)) { 912 modelClass = this._createRecordClass(val); 913 } 914 915 return modelClass || INVALID; 916 } 917 918 }); 919 920 921 922 /** 923 _This is a documentation entry only_ 924 925 Columns are described by object literals with a set of properties. 926 There is not an actual `DataTable.Column` class. 927 However, for the purpose of documenting it, this pseudo-class is declared here. 928 929 DataTables accept an array of column definitions in their [columns](DataTable.html#attr_columns) 930 attribute. Each entry in this array is a column definition which may contain 931 any combination of the properties listed below. 932 933 There are no mandatory properties though a column will usually have a 934 [key](#property_key) property to reference the data it is supposed to show. 935 The [columns](DataTable.html#attr_columns) attribute can accept a plain string 936 in lieu of an object literal, which is the equivalent of an object with the 937 [key](#property_key) property set to that string. 938 939 @class DataTable.Column 940 */ 941 942 /** 943 Binds the column values to the named property in the [data](DataTable.html#attr_data). 944 945 Optional if [formatter](#property_formatter), [nodeFormatter](#property_nodeFormatter), 946 or [cellTemplate](#property_cellTemplate) is used to populate the content. 947 948 It should not be set if [children](#property_children) is set. 949 950 The value is used for the [\_id](#property__id) property unless the [name](#property_name) 951 property is also set. 952 953 { key: 'username' } 954 955 The above column definition can be reduced to this: 956 957 'username' 958 959 @property key 960 @type String 961 */ 962 /** 963 An identifier that can be used to locate a column via 964 [getColumn](DataTable.html#method_getColumn) 965 or style columns with class `yui3-datatable-col-NAME` after dropping characters 966 that are not valid for CSS class names. 967 968 It defaults to the [key](#property_key). 969 970 The value is used for the [\_id](#property__id) property. 971 972 { name: 'fullname', formatter: ... } 973 974 @property name 975 @type String 976 */ 977 /** 978 An alias for [name](#property_name) for backward compatibility. 979 980 { field: 'fullname', formatter: ... } 981 982 @property field 983 @type String 984 */ 985 /** 986 Overrides the default unique id assigned `<th id="HERE">`. 987 988 __Use this with caution__, since it can result in 989 duplicate ids in the DOM. 990 991 { 992 name: 'checkAll', 993 id: 'check-all', 994 label: ... 995 formatter: ... 996 } 997 998 @property id 999 @type String 1000 */ 1001 /** 1002 HTML to populate the header `<th>` for the column. 1003 It defaults to the value of the [key](#property_key) property or the text 1004 `Column n` where _n_ is an ordinal number. 1005 1006 { key: 'MfgvaPrtNum', label: 'Part Number' } 1007 1008 @property label 1009 @type {String} 1010 */ 1011 /** 1012 Used to create stacked headers. 1013 1014 Child columns may also contain `children`. There is no limit 1015 to the depth of nesting. 1016 1017 Columns configured with `children` are for display only and 1018 <strong>should not</strong> be configured with a [key](#property_key). 1019 Configurations relating to the display of data, such as 1020 [formatter](#property_formatter), [nodeFormatter](#property_nodeFormatter), 1021 [emptyCellValue](#property_emptyCellValue), etc. are ignored. 1022 1023 { label: 'Name', children: [ 1024 { key: 'firstName', label: 'First`}, 1025 { key: 'lastName', label: 'Last`} 1026 ]} 1027 1028 @property children 1029 @type Array 1030 */ 1031 /** 1032 Assigns the value `<th abbr="HERE">`. 1033 1034 { 1035 key : 'forecast', 1036 label: '1yr Target Forecast', 1037 abbr : 'Forecast' 1038 } 1039 1040 @property abbr 1041 @type String 1042 */ 1043 /** 1044 Assigns the value `<th title="HERE">`. 1045 1046 { 1047 key : 'forecast', 1048 label: '1yr Target Forecast', 1049 title: 'Target Forecast for the Next 12 Months' 1050 } 1051 1052 @property title 1053 @type String 1054 */ 1055 /** 1056 Overrides the default [CELL_TEMPLATE](DataTable.HeaderView.html#property_CELL_TEMPLATE) 1057 used by `Y.DataTable.HeaderView` to render the header cell 1058 for this column. This is necessary when more control is 1059 needed over the markup for the header itself, rather than 1060 its content. 1061 1062 Use the [label](#property_label) configuration if you don't need to 1063 customize the `<th>` iteself. 1064 1065 Implementers are strongly encouraged to preserve at least 1066 the `{id}` and `{_id}` placeholders in the custom value. 1067 1068 { 1069 headerTemplate: 1070 '<th id="{id}" ' + 1071 'title="Unread" ' + 1072 'class="{className}" ' + 1073 '{_id}>●</th>' 1074 } 1075 1076 @property headerTemplate 1077 @type HTML 1078 */ 1079 /** 1080 Overrides the default [CELL_TEMPLATE](DataTable.BodyView.html#property_CELL_TEMPLATE) 1081 used by `Y.DataTable.BodyView` to render the data cells 1082 for this column. This is necessary when more control is 1083 needed over the markup for the `<td>` itself, rather than 1084 its content. 1085 1086 { 1087 key: 'id', 1088 cellTemplate: 1089 '<td class="{className}">' + 1090 '<input type="checkbox" ' + 1091 'id="{content}">' + 1092 '</td>' 1093 } 1094 1095 1096 @property cellTemplate 1097 @type String 1098 */ 1099 /** 1100 String or function used to translate the raw record data for each cell in a 1101 given column into a format better suited to display. 1102 1103 If it is a string, it will initially be assumed to be the name of one of the 1104 formatting functions in 1105 [Y.DataTable.BodyView.Formatters](DataTable.BodyView.Formatters.html). 1106 If one such formatting function exists, it will be used. 1107 1108 If no such named formatter is found, it will be assumed to be a template 1109 string and will be expanded. The placeholders can contain the key to any 1110 field in the record or the placeholder `{value}` which represents the value 1111 of the current field. 1112 1113 If the value is a function, it will be assumed to be a formatting function. 1114 A formatting function receives a single argument, an object with the following properties: 1115 1116 * __value__ The raw value from the record Model to populate this cell. 1117 Equivalent to `o.record.get(o.column.key)` or `o.data[o.column.key]`. 1118 * __data__ The Model data for this row in simple object format. 1119 * __record__ The Model for this row. 1120 * __column__ The column configuration object. 1121 * __className__ A string of class names to add `<td class="HERE">` in addition to 1122 the column class and any classes in the column's className configuration. 1123 * __rowIndex__ The index of the current Model in the ModelList. 1124 Typically correlates to the row index as well. 1125 * __rowClass__ A string of css classes to add `<tr class="HERE"><td....` 1126 This is useful to avoid the need for nodeFormatters to add classes to the containing row. 1127 1128 The formatter function may return a string value that will be used for the cell 1129 contents or it may change the value of the `value`, `className` or `rowClass` 1130 properties which well then be used to format the cell. If the value for the cell 1131 is returned in the `value` property of the input argument, no value should be returned. 1132 1133 { 1134 key: 'name', 1135 formatter: 'link', // named formatter 1136 linkFrom: 'website' // extra column property for link formatter 1137 }, 1138 { 1139 key: 'cost', 1140 formatter: '${value}' // formatter template string 1141 //formatter: '${cost}' // same result but less portable 1142 }, 1143 { 1144 name: 'Name', // column does not have associated field value 1145 // thus, it uses name instead of key 1146 formatter: '{firstName} {lastName}' // template references other fields 1147 }, 1148 { 1149 key: 'price', 1150 formatter: function (o) { // function both returns a string to show 1151 if (o.value > 3) { // and a className to apply to the cell 1152 o.className += 'expensive'; 1153 } 1154 1155 return '$' + o.value.toFixed(2); 1156 } 1157 }, 1158 @property formatter 1159 @type String || Function 1160 1161 */ 1162 /** 1163 Used to customize the content of the data cells for this column. 1164 1165 `nodeFormatter` is significantly slower than [formatter](#property_formatter) 1166 and should be avoided if possible. Unlike [formatter](#property_formatter), 1167 `nodeFormatter` has access to the `<td>` element and its ancestors. 1168 1169 The function provided is expected to fill in the `<td>` element itself. 1170 __Node formatters should return `false`__ except in certain conditions as described 1171 in the users guide. 1172 1173 The function receives a single object 1174 argument with the following properties: 1175 1176 * __td__ The `<td>` Node for this cell. 1177 * __cell__ If the cell `<td> contains an element with class `yui3-datatable-liner, 1178 this will refer to that Node. Otherwise, it is equivalent to `td` (default behavior). 1179 * __value__ The raw value from the record Model to populate this cell. 1180 Equivalent to `o.record.get(o.column.key)` or `o.data[o.column.key]`. 1181 * __data__ The Model data for this row in simple object format. 1182 * __record__ The Model for this row. 1183 * __column__ The column configuration object. 1184 * __rowIndex__ The index of the current Model in the ModelList. 1185 _Typically_ correlates to the row index as well. 1186 1187 @example 1188 nodeFormatter: function (o) { 1189 if (o.value < o.data.quota) { 1190 o.td.setAttribute('rowspan', 2); 1191 o.td.setAttribute('data-term-id', this.record.get('id')); 1192 1193 o.td.ancestor().insert( 1194 '<tr><td colspan"3">' + 1195 '<button class="term">terminate</button>' + 1196 '</td></tr>', 1197 'after'); 1198 } 1199 1200 o.cell.setHTML(o.value); 1201 return false; 1202 } 1203 1204 @property nodeFormatter 1205 @type Function 1206 */ 1207 /** 1208 Provides the default value to populate the cell if the data 1209 for that cell is `undefined`, `null`, or an empty string. 1210 1211 { 1212 key: 'price', 1213 emptyCellValue: '???' 1214 } 1215 1216 @property emptyCellValue 1217 @type {String} depending on the setting of allowHTML 1218 */ 1219 /** 1220 Skips the security step of HTML escaping the value for cells 1221 in this column. 1222 1223 This is also necessary if [emptyCellValue](#property_emptyCellValue) 1224 is set with an HTML string. 1225 `nodeFormatter`s ignore this configuration. If using a 1226 `nodeFormatter`, it is recommended to use 1227 [Y.Escape.html()](Escape.html#method_html) 1228 on any user supplied content that is to be displayed. 1229 1230 { 1231 key: 'preview', 1232 allowHTML: true 1233 } 1234 1235 @property allowHTML 1236 @type Boolean 1237 */ 1238 /** 1239 A string of CSS classes that will be added to the `<td>`'s 1240 `class` attribute. 1241 1242 Note, all cells will automatically have a class in the 1243 form of "yui3-datatable-col-XXX" added to the `<td>`, where 1244 XXX is the column's configured `name`, `key`, or `id` (in 1245 that order of preference) sanitized from invalid characters. 1246 1247 { 1248 key: 'symbol', 1249 className: 'no-hide' 1250 } 1251 1252 @property className 1253 @type String 1254 */ 1255 /** 1256 (__read-only__) The unique identifier assigned 1257 to each column. This is used for the `id` if not set, and 1258 the `_id` if none of [name](#property_name), 1259 [field](#property_field), [key](#property_key), or [id](#property_id) are 1260 set. 1261 1262 @property _yuid 1263 @type String 1264 @protected 1265 */ 1266 /** 1267 (__read-only__) A unique-to-this-instance name 1268 used extensively in the rendering process. It is also used 1269 to create the column's classname, as the input name 1270 `table.getColumn(HERE)`, and in the column header's 1271 `<th data-yui3-col-id="HERE">`. 1272 1273 The value is populated by the first of [name](#property_name), 1274 [field](#property_field), [key](#property_key), [id](#property_id), 1275 or [_yuid](#property__yuid) to have a value. If that value 1276 has already been used (such as when multiple columns have 1277 the same `key`), an incrementer is added to the end. For 1278 example, two columns with `key: "id"` will have `_id`s of 1279 "id" and "id2". `table.getColumn("id")` will return the 1280 first column, and `table.getColumn("id2")` will return the 1281 second. 1282 1283 @property _id 1284 @type String 1285 @protected 1286 */ 1287 /** 1288 (__read-only__) Used by 1289 `Y.DataTable.HeaderView` when building stacked column 1290 headers. 1291 1292 @property _colspan 1293 @type Integer 1294 @protected 1295 */ 1296 /** 1297 (__read-only__) Used by 1298 `Y.DataTable.HeaderView` when building stacked column 1299 headers. 1300 1301 @property _rowspan 1302 @type Integer 1303 @protected 1304 */ 1305 /** 1306 (__read-only__) Assigned to all columns in a 1307 column's `children` collection. References the parent 1308 column object. 1309 1310 @property _parent 1311 @type DataTable.Column 1312 @protected 1313 */ 1314 /** 1315 (__read-only__) Array of the `id`s of the 1316 column and all parent columns. Used by 1317 `Y.DataTable.BodyView` to populate `<td headers="THIS">` 1318 when a cell references more than one header. 1319 1320 @property _headers 1321 @type Array 1322 @protected 1323 */ 1324 1325 1326 }, '3.17.2', {"requires": ["escape", "model-list", "node-event-delegate"]});
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 |