[ 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('recordset-base', function (Y, NAME) { 9 10 /** 11 * Provides a wrapper around a standard javascript object. Can be inserted into a Recordset instance. 12 * 13 * @class Record 14 */ 15 var Record = Y.Base.create('record', Y.Base, [], { 16 _setId: function() { 17 return Y.guid(); 18 }, 19 20 initializer: function() { 21 }, 22 23 destructor: function() { 24 }, 25 26 /** 27 * Retrieve a particular (or all) values from the object 28 * 29 * @param field {string} (optional) The key to retrieve the value from. If not supplied, the entire object is returned. 30 * @method getValue 31 * @public 32 */ 33 getValue: function(field) { 34 if (field === undefined) { 35 return this.get("data"); 36 } 37 else { 38 return this.get("data")[field]; 39 } 40 return null; 41 } 42 }, 43 { 44 ATTRS: { 45 46 /** 47 * @description Unique ID of the record instance 48 * @attribute id 49 * @type string 50 */ 51 id: { 52 valueFn: "_setId" 53 }, 54 55 /** 56 * @description The object stored within the record instance 57 * @attribute data 58 * @type object 59 */ 60 data: { 61 value: null 62 } 63 } 64 }); 65 66 Y.Record = Record; 67 /** 68 The Recordset utility provides a standard way for dealing with 69 a collection of similar objects. 70 @module recordset 71 @main recordset 72 @submodule recordset-base 73 **/ 74 75 76 var ArrayList = Y.ArrayList, 77 Lang = Y.Lang, 78 79 /** 80 The Recordset utility provides a standard way for dealing with 81 a collection of similar objects. 82 83 Provides the base Recordset implementation, which can be extended to add 84 additional functionality, such as custom indexing. sorting, and filtering. 85 86 @class Recordset 87 @extends Base 88 @uses ArrayList 89 @param config {Object} Configuration object with initial attribute values 90 @constructor 91 **/ 92 Recordset = Y.Base.create('recordset', Y.Base, [], { 93 94 95 /** 96 * Publish default functions for events. Create the initial hash table. 97 * 98 * @method initializer 99 * @protected 100 */ 101 initializer: function() { 102 // The reason the conditional is needed is because of two scenarios: 103 // 1. Instantiating new Y.Recordset() will not go into the setter of "records", and so it is necessary to create this._items in the initializer. 104 // 2. Instantiating new Y.Recordset({records: [{...}]}) will call the setter of "records" and create this._items. In this case, we don't want that to be overwritten by []. 105 if (!this._items) { 106 this._items = []; 107 } 108 109 //set up event listener to fire events when recordset is modified in anyway 110 this.publish({ 111 /** 112 * <p>At least one record is being added. Additional properties of 113 * the event are:</p> 114 * <dl> 115 * <dt>added</dt> 116 * <dd>Array of new records to be added</dd> 117 * <dt>index</dt> 118 * <dd>The insertion index in the Recordset's internal 119 * array</dd> 120 * </dl> 121 * 122 * <p>Preventing this event will cause the new records NOT to be 123 * added to the Recordset's internal collection.</p> 124 * 125 * @event add 126 * @preventable _defAddFn 127 */ 128 add: { defaultFn: this._defAddFn }, 129 130 /** 131 * <p>At least one record is being removed. Additional properties of 132 * the event are:</p> 133 * <dl> 134 * <dt>removed</dt> 135 * <dd>Array of records to be removed</dd> 136 * <dt>range</dt> 137 * <dd>Number of records to be removed</dd> 138 * <dt>index</dt> 139 * <dd>The starting index in the Recordset's internal 140 * array from which to remove records</dd> 141 * </dl> 142 * 143 * <p>Preventing this event will cause the records NOT to be 144 * removed from the Recordset's internal collection.</p> 145 * 146 * @event remove 147 * @preventable _defRemoveFn 148 */ 149 remove: { defaultFn: this._defRemoveFn }, 150 151 /** 152 * The Recordset is being flushed of all records. 153 * 154 * @event empty 155 * @preventable _defEmptyFn 156 */ 157 empty: { defaultFn: this._defEmptyFn }, 158 159 /** 160 * <p>At least one record is being updated. Additional properties of 161 * the event are:</p> 162 * <dl> 163 * <dt>updated</dt> 164 * <dd>Array of records with updated values</dd> 165 * <dt>overwritten</dt> 166 * <dd>Array of current records that will be replaced</dd> 167 * <dt>index</dt> 168 * <dd>The starting index in the Recordset's internal 169 * array from which to update will apply</dd> 170 * </dl> 171 * 172 * <p>Preventing this event will cause the records NOT to be 173 * updated in the Recordset's internal collection.</p> 174 * 175 * @event update 176 * @preventable _defUpdateFn 177 */ 178 update: { defaultFn: this._defUpdateFn } 179 }); 180 181 this._buildHashTable(this.get('key')); 182 183 this.after([ 184 'recordsChange', 185 'add', 186 'remove', 187 'update', 188 'empty'], this._updateHash); 189 }, 190 191 /** 192 * Returns the record with particular ID or index 193 * 194 * @method getRecord 195 * @param i {String, Number} The ID of the record if a string, or the index if a number. 196 * @return {Record} A Y.Record instance 197 */ 198 getRecord: function(i) { 199 200 if (Lang.isString(i)) { 201 return this.get('table')[i]; 202 } 203 else if (Lang.isNumber(i)) { 204 return this._items[i]; 205 } 206 return null; 207 }, 208 209 210 /** 211 * Returns the record at a particular index 212 * 213 * @method getRecordByIndex 214 * @param i {Number} Index at which the required record resides 215 * @return {Record} A Y.Record instance 216 */ 217 getRecordByIndex: function(i) { 218 return this._items[i]; 219 }, 220 221 /** 222 * Returns a range of records beginning at particular index 223 * 224 * @method getRecordsByIndex 225 * @param index {Number} Index at which the required record resides 226 * @param range {Number} (Optional) Number of records to retrieve. The default is 1 227 * @return {Array} An array of Y.Record instances 228 */ 229 getRecordsByIndex: function(index, range) { 230 var i = 0, 231 returnedRecords = []; 232 //Range cannot take on negative values 233 range = (Lang.isNumber(range) && (range > 0)) ? range: 1; 234 235 for (; i < range; i++) { 236 returnedRecords.push(this._items[index + i]); 237 } 238 return returnedRecords; 239 }, 240 241 /** 242 * Returns the length of the recordset 243 * 244 * @method getLength 245 * @return {Number} Number of records in the recordset 246 */ 247 getLength: function() { 248 return this.size(); 249 }, 250 251 /** 252 Gets an array of values for a data _key_ in the set's records. If no _key_ 253 is supplied, the returned array will contain the full data object for each 254 record. 255 256 @method getValuesByKey 257 @param {String} [key] Data property to get from all records 258 @return {Array} An array of values for the given _key_ if supplied. 259 Otherwise, an array of each record's data hash. 260 **/ 261 getValuesByKey: function(key) { 262 var i = 0, 263 len = this._items.length, 264 retVals = []; 265 for (; i < len; i++) { 266 retVals.push(this._items[i].getValue(key)); 267 } 268 return retVals; 269 }, 270 271 272 /** 273 * Adds one or more Records to the RecordSet at the given index. If index is null, then adds the Records to the end of the RecordSet. 274 * 275 * @method add 276 * @param {Record|Object|Array} oData A Y.Record instance, An object literal of data or an array of object literals 277 * @param [index] {Number} [index] Index at which to add the record(s) 278 * @return {Recordset} The updated recordset instance 279 */ 280 add: function(oData, index) { 281 282 var newRecords = [], 283 idx, 284 i = 0; 285 286 idx = (Lang.isNumber(index) && (index > -1)) ? index: this._items.length; 287 288 //Passing in array of object literals for oData 289 if (Lang.isArray(oData)) { 290 for (; i < oData.length; i++) { 291 newRecords[i] = this._changeToRecord(oData[i]); 292 } 293 } else if (Lang.isObject(oData)) { 294 newRecords[0] = this._changeToRecord(oData); 295 } 296 297 this.fire('add', { 298 added: newRecords, 299 index: idx 300 }); 301 return this; 302 }, 303 304 /** 305 Removes one or more Records to the RecordSet at the given index. If index 306 is null, then removes a single Record from the end of the RecordSet. 307 308 @method remove 309 @param {Number} [index] Index at which to remove the record(s) from 310 @param {Number} [range] Number of records to remove (including the one 311 at the index) 312 @return {Recordset} The updated recordset instance 313 **/ 314 remove: function(index, range) { 315 var remRecords = []; 316 317 //Default is to only remove the last record - the length is always 1 greater than the last index 318 index = (index > -1) ? index: (this._items.length - 1); 319 range = (range > 0) ? range: 1; 320 321 remRecords = this._items.slice(index, (index + range)); 322 this.fire('remove', { 323 removed: remRecords, 324 range: range, 325 index: index 326 }); 327 //this._recordRemoved(remRecords, index); 328 //return ({data: remRecords, index:index}); 329 return this; 330 }, 331 332 /** 333 * Empties the recordset 334 * 335 * @method empty 336 * @return {Recordset} The updated recordset instance 337 */ 338 empty: function() { 339 this.fire('empty', {}); 340 return this; 341 }, 342 343 /** 344 Updates the recordset with the new records passed in. Overwrites existing 345 records when updating the index with the new records. 346 347 @method update 348 @param {Record|Object|Array} data A Y.Record instance, An object literal of 349 data or an array of object literals 350 @param {Number} [index] The index to start updating from. 351 @return {Recordset} The updated recordset instance 352 **/ 353 update: function(data, index) { 354 var rec, 355 arr, 356 i = 0; 357 358 // Whatever is passed in, we are changing it to an array so that it can 359 // be easily iterated in the _defUpdateFn method 360 arr = (!(Lang.isArray(data))) ? [data] : data; 361 rec = this._items.slice(index, index + arr.length); 362 363 for (; i < arr.length; i++) { 364 arr[i] = this._changeToRecord(arr[i]); 365 } 366 367 this.fire('update', { 368 updated: arr, 369 overwritten: rec, 370 index: index 371 }); 372 373 return this; 374 }, 375 376 /** 377 * Default behavior for the "add" event. Adds Record instances starting from 378 * the index specified in `e.index`. 379 * 380 * @method _defAddFn 381 * @param {EventFacade} e The add event 382 * @private 383 */ 384 _defAddFn: function(e) { 385 this._items.splice.apply(this._items, [e.index, 0].concat(e.added)); 386 }, 387 388 /** 389 * Default behavior for the "remove" event. Removes Records from the 390 * internal array starting from `e.index`. By default, it will remove one 391 * Record. But if `e.range` is set, it will remove that many Records. 392 * 393 * @method _defRemoveFn 394 * @param {EventFacade} e The remove event 395 * @private 396 */ 397 _defRemoveFn: function(e) { 398 this._items.splice(e.index, e.range || 1); 399 }, 400 401 /** 402 * Default behavior for the "update" event. Sets Record instances for each 403 * item in `e.updated` at indexes starting from `e.index`. 404 * 405 * @method _defUpdateFn 406 * @param {EventFacade} e The update event 407 * @private 408 */ 409 _defUpdateFn: function(e) { 410 for (var i = 0; i < e.updated.length; i++) { 411 this._items[e.index + i] = this._changeToRecord(e.updated[i]); 412 } 413 }, 414 415 /** 416 * Default behavior for the "empty" event. Clears the internal array of 417 * Records. 418 * 419 * @method _defEmptyFn 420 * @param {EventFacade} e The empty event 421 * @private 422 */ 423 _defEmptyFn: function(e) { 424 this._items = []; 425 }, 426 427 /** 428 Updates the internal hash table. 429 430 @method _defUpdateHash 431 @param {EventFacade} e Event triggering the hash table update 432 @private 433 **/ 434 _updateHash: function (e) { 435 var handler = "_hash", 436 type = e.type.replace(/.*:/,''), 437 newHash; 438 439 // _hashAdd, _hashRemove, _hashEmpty, etc 440 // Not a switch or else if setup to allow for external expansion. 441 handler += type.charAt(0).toUpperCase() + type.slice(1); 442 443 newHash = this[handler] && 444 this[handler](this.get('table'), this.get('key'), e); 445 446 if (newHash) { 447 this.set('table', newHash); 448 } 449 }, 450 451 /** 452 Regenerates the hash table from the current internal array of Records. 453 454 @method _hashRecordsChange 455 @param {Object} hash The hash map before replacement 456 @param {String} key The key by which to add items to the hash 457 @param {Object} e The event or object containing the items to be added. 458 Items are expected to be stored in an array assigned to 459 the `added` property. 460 @return {Object} The updated hash map 461 @private 462 **/ 463 _hashRecordsChange: function (hash, key, e) { 464 return this._buildHashTable(key); 465 }, 466 467 /** 468 Builds a hash table from the current internal array of Records. 469 470 @method _buildHashTable 471 @param {String} key The Record key to hash the items by 472 @return {Object} A new hash map of Records keyed by each Records' key 473 @private 474 **/ 475 _buildHashTable: function (key) { 476 return this._hashAdd({}, key, { added: this._items }); 477 }, 478 479 /** 480 Adds items to the hash table. Items are the values, and the keys are the 481 values of the item's attribute named in the `key` parameter. 482 483 @method _hashAdd 484 @param {Object} hash The hash map before adding items 485 @param {String} key The key by which to add the items to the hash 486 @param {Object} e The event or object containing the items to be added. 487 Items are expected to be stored in an array assigned to 488 the `added` property. 489 @return {Object} The updated hash map 490 @private 491 **/ 492 _hashAdd: function(hash, key, e) { 493 var items = e.added, 494 i, len; 495 496 for (i = 0, len = e.added.length; i < len; ++i) { 497 hash[items[i].get(key)] = items[i]; 498 } 499 500 return hash; 501 }, 502 503 /** 504 Removes items from the hash table. 505 506 @method _hashRemove 507 @param {Object} hash The hash map before removing items 508 @param {String} key The key by which to remove the items from the hash 509 @param {Object} e The event or object containing the items to be removed. 510 Items are expected to be stored in an array assigned to 511 the `removed` property. 512 @return {Object} The updated hash map 513 @private 514 **/ 515 _hashRemove: function(hash, key, e) { 516 for (var i = e.removed.length - 1; i >= 0; --i) { 517 delete hash[e.removed[i].get(key)]; 518 } 519 520 return hash; 521 }, 522 523 /** 524 Updates items in the hash table. 525 526 @method _hashUpdate 527 @param {Object} hash The hash map before updating items 528 @param {String} key The key by which to update the items to the hash 529 @param {Object} e The event or object containing the items to be updated. 530 Items are expected to be stored in an array assigned to 531 the `updated` property. Optionally, items can be 532 identified for being overwritten by including them in an 533 array assigned to the `overwritten` property. 534 @return {Object} The updated hash map 535 @private 536 **/ 537 _hashUpdate: function (hash, key, e) { 538 if (e.overwritten && e.overwritten.length) { 539 hash = this._hashRemove(hash, key, { removed: e.overwritten }); 540 } 541 542 return this._hashAdd(hash, key, { added: e.updated }); 543 }, 544 545 /** 546 Clears the hash table. 547 548 @method _hashEmpty 549 @param {Object} hash The hash map before adding items 550 @param {String} key The key by which to remove the items from the hash 551 @param {Object} e The event or object containing the items to be removed. 552 Items are expected to be stored in an array assigned to 553 the `removed` property. 554 @return {Object} An empty hash 555 @private 556 **/ 557 _hashEmpty: function() { 558 return {}; 559 }, 560 561 /** 562 * Sets up the hashtable with all the records currently in the recordset 563 * 564 * @method _initHashTable 565 * @private 566 */ 567 _initHashTable: function() { 568 return this._hashAdd({}, this.get('key'), { added: this._items || [] }); 569 }, 570 571 /** 572 * Helper method - it takes an object bag and converts it to a Y.Record 573 * 574 * @method _changeToRecord 575 * @param obj {Object|Record} Any objet literal or Y.Record instance 576 * @return {Record} A Record instance. 577 * @private 578 */ 579 _changeToRecord: function(obj) { 580 return (obj instanceof Y.Record) ? obj : new Y.Record({ data: obj }); 581 }, 582 583 /** 584 Ensures the value being set is an array of Record instances. If array items 585 are raw object data, they are turned into Records. 586 587 @method _setRecords 588 @param {Record[]|Object[]} items The Records or data Objects to store as 589 Records. 590 @return {Record[]} 591 **/ 592 _setRecords: function (items) { 593 if (!Y.Lang.isArray(items)) { 594 return Y.Attribute.INVALID_VALUE; 595 } 596 597 var records = [], 598 i, len; 599 600 // FIXME: This should use the flyweight pattern if possible 601 for (i = 0, len = items.length; i < len; ++i) { 602 records[i] = this._changeToRecord(items[i]); 603 } 604 605 return (this._items = records); 606 } 607 }, { 608 ATTRS: { 609 610 /** 611 * An array of Records that the Recordset is storing. Passing an array 612 * of raw record data is also accepted. The data for each item will be 613 * wrapped in a Record instance. 614 * 615 * @attribute records 616 * @type {Record[]} 617 */ 618 records: { 619 // TODO: necessary? valueFn? 620 lazyAdd: false, 621 getter: function() { 622 // give them a copy, not the internal object 623 return Y.Array(this._items); 624 }, 625 setter: "_setRecords" 626 }, 627 628 /** 629 A hash table where the ID of the record is the key, and the record 630 instance is the value. 631 632 @attribute table 633 @type object 634 **/ 635 table: { 636 valueFn: '_initHashTable' 637 }, 638 639 /** 640 The ID to use as the key in the hash table. 641 642 @attribute key 643 @type string 644 **/ 645 key: { 646 value: 'id', 647 readOnly: true 648 } 649 650 } 651 }); 652 Y.augment(Recordset, ArrayList); 653 Y.Recordset = Recordset; 654 655 656 657 }, '3.17.2', {"requires": ["base", "arraylist"]});
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 |