[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/recordset-base/ -> recordset-base-debug.js (source)

   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"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1