2
YUI 3.10.3 (build 2fb5187)
3
Copyright 2013 Yahoo! Inc. All rights reserved.
4
Licensed under the BSD License.
5
http://yuilibrary.com/license/
8
YUI.add('recordset-base', function (Y, NAME) {
11
* Provides a wrapper around a standard javascript object. Can be inserted into a Recordset instance.
15
var Record = Y.Base.create('record', Y.Base, [], {
20
initializer: function() {
23
destructor: function() {
27
* Retrieve a particular (or all) values from the object
29
* @param field {string} (optional) The key to retrieve the value from. If not supplied, the entire object is returned.
33
getValue: function(field) {
34
if (field === undefined) {
35
return this.get("data");
38
return this.get("data")[field];
47
* @description Unique ID of the record instance
56
* @description The object stored within the record instance
68
The Recordset utility provides a standard way for dealing with
69
a collection of similar objects.
72
@submodule recordset-base
76
var ArrayList = Y.ArrayList,
80
The Recordset utility provides a standard way for dealing with
81
a collection of similar objects.
83
Provides the base Recordset implementation, which can be extended to add
84
additional functionality, such as custom indexing. sorting, and filtering.
89
@param config {Object} Configuration object with initial attribute values
92
Recordset = Y.Base.create('recordset', Y.Base, [], {
96
* Publish default functions for events. Create the initial hash table.
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 [].
109
//set up event listener to fire events when recordset is modified in anyway
112
* <p>At least one record is being added. Additional properties of
116
* <dd>Array of new records to be added</dd>
118
* <dd>The insertion index in the Recordset's internal
122
* <p>Preventing this event will cause the new records NOT to be
123
* added to the Recordset's internal collection.</p>
126
* @preventable _defAddFn
128
add: { defaultFn: this._defAddFn },
131
* <p>At least one record is being removed. Additional properties of
135
* <dd>Array of records to be removed</dd>
137
* <dd>Number of records to be removed</dd>
139
* <dd>The starting index in the Recordset's internal
140
* array from which to remove records</dd>
143
* <p>Preventing this event will cause the records NOT to be
144
* removed from the Recordset's internal collection.</p>
147
* @preventable _defRemoveFn
149
remove: { defaultFn: this._defRemoveFn },
152
* The Recordset is being flushed of all records.
155
* @preventable _defEmptyFn
157
empty: { defaultFn: this._defEmptyFn },
160
* <p>At least one record is being updated. Additional properties of
164
* <dd>Array of records with updated values</dd>
165
* <dt>overwritten</dt>
166
* <dd>Array of current records that will be replaced</dd>
168
* <dd>The starting index in the Recordset's internal
169
* array from which to update will apply</dd>
172
* <p>Preventing this event will cause the records NOT to be
173
* updated in the Recordset's internal collection.</p>
176
* @preventable _defUpdateFn
178
update: { defaultFn: this._defUpdateFn }
181
this._buildHashTable(this.get('key'));
188
'empty'], this._updateHash);
192
* Returns the record with particular ID or index
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
198
getRecord: function(i) {
200
if (Lang.isString(i)) {
201
return this.get('table')[i];
203
else if (Lang.isNumber(i)) {
204
return this._items[i];
211
* Returns the record at a particular index
213
* @method getRecordByIndex
214
* @param i {Number} Index at which the required record resides
215
* @return {Record} A Y.Record instance
217
getRecordByIndex: function(i) {
218
return this._items[i];
222
* Returns a range of records beginning at particular index
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
229
getRecordsByIndex: function(index, range) {
231
returnedRecords = [];
232
//Range cannot take on negative values
233
range = (Lang.isNumber(range) && (range > 0)) ? range: 1;
235
for (; i < range; i++) {
236
returnedRecords.push(this._items[index + i]);
238
return returnedRecords;
242
* Returns the length of the recordset
245
* @return {Number} Number of records in the recordset
247
getLength: function() {
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
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.
261
getValuesByKey: function(key) {
263
len = this._items.length,
265
for (; i < len; i++) {
266
retVals.push(this._items[i].getValue(key));
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.
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
280
add: function(oData, index) {
286
idx = (Lang.isNumber(index) && (index > -1)) ? index: this._items.length;
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]);
293
} else if (Lang.isObject(oData)) {
294
newRecords[0] = this._changeToRecord(oData);
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.
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
312
@return {Recordset} The updated recordset instance
314
remove: function(index, range) {
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;
321
remRecords = this._items.slice(index, (index + range));
322
this.fire('remove', {
327
//this._recordRemoved(remRecords, index);
328
//return ({data: remRecords, index:index});
333
* Empties the recordset
336
* @return {Recordset} The updated recordset instance
339
this.fire('empty', {});
344
Updates the recordset with the new records passed in. Overwrites existing
345
records when updating the index with the new records.
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
353
update: function(data, index) {
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);
363
for (; i < arr.length; i++) {
364
arr[i] = this._changeToRecord(arr[i]);
367
this.fire('update', {
377
* Default behavior for the "add" event. Adds Record instances starting from
378
* the index specified in `e.index`.
381
* @param {EventFacade} e The add event
384
_defAddFn: function(e) {
385
this._items.splice.apply(this._items, [e.index, 0].concat(e.added));
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.
393
* @method _defRemoveFn
394
* @param {EventFacade} e The remove event
397
_defRemoveFn: function(e) {
398
this._items.splice(e.index, e.range || 1);
402
* Default behavior for the "update" event. Sets Record instances for each
403
* item in `e.updated` at indexes starting from `e.index`.
405
* @method _defUpdateFn
406
* @param {EventFacade} e The update event
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]);
416
* Default behavior for the "empty" event. Clears the internal array of
419
* @method _defEmptyFn
420
* @param {EventFacade} e The empty event
423
_defEmptyFn: function(e) {
425
Y.log('empty fired');
429
Updates the internal hash table.
431
@method _defUpdateHash
432
@param {EventFacade} e Event triggering the hash table update
435
_updateHash: function (e) {
436
var handler = "_hash",
437
type = e.type.replace(/.*:/,''),
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);
444
newHash = this[handler] &&
445
this[handler](this.get('table'), this.get('key'), e);
448
this.set('table', newHash);
453
Regenerates the hash table from the current internal array of Records.
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
464
_hashRecordsChange: function (hash, key, e) {
465
return this._buildHashTable(key);
469
Builds a hash table from the current internal array of Records.
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
476
_buildHashTable: function (key) {
477
return this._hashAdd({}, key, { added: this._items });
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.
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
493
_hashAdd: function(hash, key, e) {
497
for (i = 0, len = e.added.length; i < len; ++i) {
498
hash[items[i].get(key)] = items[i];
505
Removes items from the hash table.
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
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)];
525
Updates items in the hash table.
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
538
_hashUpdate: function (hash, key, e) {
539
if (e.overwritten && e.overwritten.length) {
540
hash = this._hashRemove(hash, key, { removed: e.overwritten });
543
return this._hashAdd(hash, key, { added: e.updated });
547
Clears the hash table.
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
558
_hashEmpty: function() {
563
* Sets up the hashtable with all the records currently in the recordset
565
* @method _initHashTable
568
_initHashTable: function() {
569
return this._hashAdd({}, this.get('key'), { added: this._items || [] });
573
* Helper method - it takes an object bag and converts it to a Y.Record
575
* @method _changeToRecord
576
* @param obj {Object|Record} Any objet literal or Y.Record instance
577
* @return {Record} A Record instance.
580
_changeToRecord: function(obj) {
581
return (obj instanceof Y.Record) ? obj : new Y.Record({ data: obj });
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.
589
@param {Record[]|Object[]} items The Records or data Objects to store as
593
_setRecords: function (items) {
594
if (!Y.Lang.isArray(items)) {
595
return Y.Attribute.INVALID_VALUE;
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]);
606
return (this._items = records);
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.
620
// TODO: necessary? valueFn?
623
// give them a copy, not the internal object
624
return Y.Array(this._items);
626
setter: "_setRecords"
630
A hash table where the ID of the record is the key, and the record
631
instance is the value.
637
valueFn: '_initHashTable'
641
The ID to use as the key in the hash table.
653
Y.augment(Recordset, ArrayList);
654
Y.Recordset = Recordset;
658
}, '3.10.3', {"requires": ["base", "arraylist"]});