[ 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 Y.log('empty fired'); 426 }, 427 428 /** 429 Updates the internal hash table. 430 431 @method _defUpdateHash 432 @param {EventFacade} e Event triggering the hash table update 433 @private 434 **/ 435 _updateHash: function (e) { 436 var handler = "_hash", 437 type = e.type.replace(/.*:/,''), 438 newHash; 439 440 // _hashAdd, _hashRemove, _hashEmpty, etc 441 // Not a switch or else if setup to allow for external expansion. 442 handler += type.charAt(0).toUpperCase() + type.slice(1); 443 444 newHash = this[handler] && 445 this[handler](this.get('table'), this.get('key'), e); 446 447 if (newHash) { 448 this.set('table', newHash); 449 } 450 }, 451 452 /** 453 Regenerates the hash table from the current internal array of Records. 454 455 @method _hashRecordsChange 456 @param {Object} hash The hash map before replacement 457 @param {String} key The key by which to add items to the hash 458 @param {Object} e The event or object containing the items to be added. 459 Items are expected to be stored in an array assigned to 460 the `added` property. 461 @return {Object} The updated hash map 462 @private 463 **/ 464 _hashRecordsChange: function (hash, key, e) { 465 return this._buildHashTable(key); 466 }, 467 468 /** 469 Builds a hash table from the current internal array of Records. 470 471 @method _buildHashTable 472 @param {String} key The Record key to hash the items by 473 @return {Object} A new hash map of Records keyed by each Records' key 474 @private 475 **/ 476 _buildHashTable: function (key) { 477 return this._hashAdd({}, key, { added: this._items }); 478 }, 479 480 /** 481 Adds items to the hash table. Items are the values, and the keys are the 482 values of the item's attribute named in the `key` parameter. 483 484 @method _hashAdd 485 @param {Object} hash The hash map before adding items 486 @param {String} key The key by which to add the items to the hash 487 @param {Object} e The event or object containing the items to be added. 488 Items are expected to be stored in an array assigned to 489 the `added` property. 490 @return {Object} The updated hash map 491 @private 492 **/ 493 _hashAdd: function(hash, key, e) { 494 var items = e.added, 495 i, len; 496 497 for (i = 0, len = e.added.length; i < len; ++i) { 498 hash[items[i].get(key)] = items[i]; 499 } 500 501 return hash; 502 }, 503 504 /** 505 Removes items from the hash table. 506 507 @method _hashRemove 508 @param {Object} hash The hash map before removing items 509 @param {String} key The key by which to remove the items from the hash 510 @param {Object} e The event or object containing the items to be removed. 511 Items are expected to be stored in an array assigned to 512 the `removed` property. 513 @return {Object} The updated hash map 514 @private 515 **/ 516 _hashRemove: function(hash, key, e) { 517 for (var i = e.removed.length - 1; i >= 0; --i) { 518 delete hash[e.removed[i].get(key)]; 519 } 520 521 return hash; 522 }, 523 524 /** 525 Updates items in the hash table. 526 527 @method _hashUpdate 528 @param {Object} hash The hash map before updating items 529 @param {String} key The key by which to update the items to the hash 530 @param {Object} e The event or object containing the items to be updated. 531 Items are expected to be stored in an array assigned to 532 the `updated` property. Optionally, items can be 533 identified for being overwritten by including them in an 534 array assigned to the `overwritten` property. 535 @return {Object} The updated hash map 536 @private 537 **/ 538 _hashUpdate: function (hash, key, e) { 539 if (e.overwritten && e.overwritten.length) { 540 hash = this._hashRemove(hash, key, { removed: e.overwritten }); 541 } 542 543 return this._hashAdd(hash, key, { added: e.updated }); 544 }, 545 546 /** 547 Clears the hash table. 548 549 @method _hashEmpty 550 @param {Object} hash The hash map before adding items 551 @param {String} key The key by which to remove the items from the hash 552 @param {Object} e The event or object containing the items to be removed. 553 Items are expected to be stored in an array assigned to 554 the `removed` property. 555 @return {Object} An empty hash 556 @private 557 **/ 558 _hashEmpty: function() { 559 return {}; 560 }, 561 562 /** 563 * Sets up the hashtable with all the records currently in the recordset 564 * 565 * @method _initHashTable 566 * @private 567 */ 568 _initHashTable: function() { 569 return this._hashAdd({}, this.get('key'), { added: this._items || [] }); 570 }, 571 572 /** 573 * Helper method - it takes an object bag and converts it to a Y.Record 574 * 575 * @method _changeToRecord 576 * @param obj {Object|Record} Any objet literal or Y.Record instance 577 * @return {Record} A Record instance. 578 * @private 579 */ 580 _changeToRecord: function(obj) { 581 return (obj instanceof Y.Record) ? obj : new Y.Record({ data: obj }); 582 }, 583 584 /** 585 Ensures the value being set is an array of Record instances. If array items 586 are raw object data, they are turned into Records. 587 588 @method _setRecords 589 @param {Record[]|Object[]} items The Records or data Objects to store as 590 Records. 591 @return {Record[]} 592 **/ 593 _setRecords: function (items) { 594 if (!Y.Lang.isArray(items)) { 595 return Y.Attribute.INVALID_VALUE; 596 } 597 598 var records = [], 599 i, len; 600 601 // FIXME: This should use the flyweight pattern if possible 602 for (i = 0, len = items.length; i < len; ++i) { 603 records[i] = this._changeToRecord(items[i]); 604 } 605 606 return (this._items = records); 607 } 608 }, { 609 ATTRS: { 610 611 /** 612 * An array of Records that the Recordset is storing. Passing an array 613 * of raw record data is also accepted. The data for each item will be 614 * wrapped in a Record instance. 615 * 616 * @attribute records 617 * @type {Record[]} 618 */ 619 records: { 620 // TODO: necessary? valueFn? 621 lazyAdd: false, 622 getter: function() { 623 // give them a copy, not the internal object 624 return Y.Array(this._items); 625 }, 626 setter: "_setRecords" 627 }, 628 629 /** 630 A hash table where the ID of the record is the key, and the record 631 instance is the value. 632 633 @attribute table 634 @type object 635 **/ 636 table: { 637 valueFn: '_initHashTable' 638 }, 639 640 /** 641 The ID to use as the key in the hash table. 642 643 @attribute key 644 @type string 645 **/ 646 key: { 647 value: 'id', 648 readOnly: true 649 } 650 651 } 652 }); 653 Y.augment(Recordset, ArrayList); 654 Y.Recordset = Recordset; 655 656 657 658 }, '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 |