[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/datatable-mutable/ -> datatable-mutable.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('datatable-mutable', function (Y, NAME) {
   9  
  10  /**
  11  Adds mutation convenience methods such as `table.addRow(data)` to `Y.DataTable`. (or other built class).
  12  
  13  @module datatable
  14  @submodule datatable-mutable
  15  @since 3.5.0
  16  **/
  17  var toArray = Y.Array,
  18      YLang   = Y.Lang,
  19      isString = YLang.isString,
  20      isArray  = YLang.isArray,
  21      isObject = YLang.isObject,
  22      isNumber = YLang.isNumber,
  23      arrayIndex = Y.Array.indexOf,
  24      Mutable;
  25  
  26  /**
  27  _API docs for this extension are included in the DataTable class._
  28  
  29  Class extension to add mutation convenience methods to `Y.DataTable` (or other
  30  built class).
  31  
  32  Column mutation methods are paired with new custom events:
  33  
  34   * addColumn
  35   * removeColumn
  36   * modifyColumn
  37   * moveColumn
  38  
  39  Row mutation events are bubbled from the DataTable's `data` ModelList through
  40  the DataTable instance.
  41  
  42  @class DataTable.Mutable
  43  @for DataTable
  44  @since 3.5.0
  45  **/
  46  Y.namespace('DataTable').Mutable = Mutable = function () {};
  47  
  48  Mutable.ATTRS = {
  49      /**
  50      Controls whether `addRow`, `removeRow`, and `modifyRow` should trigger the
  51      underlying Model's sync layer by default.
  52  
  53      When `true`, it is unnecessary to pass the "sync" configuration property to
  54      those methods to trigger per-operation sync.
  55  
  56  
  57      @attribute autoSync
  58      @type {Boolean}
  59      @default `false`
  60      @since 3.5.0
  61      **/
  62      autoSync: {
  63          value: false,
  64          validator: YLang.isBoolean
  65      }
  66  };
  67  
  68  Y.mix(Mutable.prototype, {
  69      /**
  70      Adds the column configuration to the DataTable's `columns` configuration.
  71      If the `index` parameter is supplied, it is injected at that index.  If the
  72      table has nested headers, inject a subcolumn by passing an array of indexes
  73      to identify the new column's final location.
  74  
  75      The `index` parameter is required if adding a nested column.
  76  
  77      This method is a convienience method for fetching the DataTable's `columns`
  78      attribute, updating it, and calling
  79      `table.set('columns', _updatedColumnsDefs_)`
  80  
  81      For example:
  82  
  83      <pre><code>// Becomes last column
  84      table.addColumn('name');
  85  
  86      // Inserted after the current second column, moving the current third column
  87      // to index 4
  88      table.addColumn({ key: 'price', formatter: currencyFormatter }, 2 );
  89  
  90      // Insert a new column in a set of headers three rows deep.  The index array
  91      // translates to
  92      // [ 2, --  in the third column's children
  93      //   1, --  in the second child's children
  94      //   3 ] -- as the fourth child column
  95      table.addColumn({ key: 'age', sortable: true }, [ 2, 1, 3 ]);
  96      </code></pre>
  97  
  98      @method addColumn
  99      @param {Object|String} config The new column configuration object
 100      @param {Number|Number[]} [index] the insertion index
 101      @return {DataTable}
 102      @chainable
 103      @since 3.5.0
 104      **/
 105      addColumn: function (config, index) {
 106          if (isString(config)) {
 107              config = { key: config };
 108          }
 109  
 110          if (config) {
 111              if (arguments.length < 2 || (!isNumber(index) && !isArray(index))) {
 112                  index = this.get('columns').length;
 113              }
 114  
 115              this.fire('addColumn', {
 116                  column: config,
 117                  index: index
 118              });
 119          }
 120          return this;
 121      },
 122  
 123      /**
 124      Updates an existing column definition. Fires the `modifyColumn` event.
 125  
 126      For example:
 127  
 128      <pre><code>// Add a formatter to the existing 'price' column definition
 129      table.modifyColumn('price', { formatter: currencyFormatter });
 130  
 131      // Change the label on a header cell in a set of nested headers three rows
 132      // deep.  The index array translates to
 133      // [ 2,  -- in the third column's children
 134      //   1,  -- the second child
 135      //   3 ] -- the fourth child column
 136      table.modifyColumn([2, 1, 3], { label: 'Experience' });
 137      </code></pre>
 138  
 139      @method modifyColumn
 140      @param {String|Number|Number[]|Object} name The column key, name, index, or
 141                  current configuration object
 142      @param {Object} config The new column configuration properties
 143      @return {DataTable}
 144      @chainable
 145      @since 3.5.0
 146      **/
 147      modifyColumn: function (name, config) {
 148          if (isString(config)) {
 149              config = { key: config };
 150          }
 151  
 152          if (isObject(config)) {
 153              this.fire('modifyColumn', {
 154                  column: name,
 155                  newColumnDef: config
 156              });
 157          }
 158  
 159          return this;
 160      },
 161  
 162      /**
 163      Moves an existing column to a new location. Fires the `moveColumn` event.
 164  
 165      The destination index can be a number or array of numbers to place a column
 166      header in a nested header row.
 167  
 168      @method moveColumn
 169      @param {String|Number|Number[]|Object} name The column key, name, index, or
 170                  current configuration object
 171      @param {Number|Number[]} index The destination index of the column
 172      @return {DataTable}
 173      @chainable
 174      @since 3.5.0
 175      **/
 176      moveColumn: function (name, index) {
 177          if (name !== undefined && (isNumber(index) || isArray(index))) {
 178              this.fire('moveColumn', {
 179                  column: name,
 180                  index: index
 181              });
 182          }
 183  
 184          return this;
 185      },
 186  
 187      /**
 188      Removes an existing column. Fires the `removeColumn` event.
 189  
 190      @method removeColumn
 191      @param {String|Number|Number[]|Object} name The column key, name, index, or
 192                  current configuration object
 193      @return {DataTable}
 194      @chainable
 195      @since 3.5.0
 196      **/
 197      removeColumn: function (name) {
 198          if (name !== undefined) {
 199              this.fire('removeColumn', {
 200                  column: name
 201              });
 202          }
 203  
 204          return this;
 205      },
 206  
 207      /**
 208      Adds a new record to the DataTable's `data` ModelList.  Record data can be
 209      an object of field values or an instance of the DataTable's configured
 210      `recordType` class.
 211  
 212      This relays all parameters to the `data` ModelList's `add` method.
 213  
 214      If a configuration object is passed as a second argument, and that object
 215      has `sync: true` set, the underlying Model will be `save()`d.
 216  
 217      If the DataTable's `autoSync` attribute is set to `true`, the additional
 218      argument is not needed.
 219  
 220      If syncing and the last argument is a function, that function will be used
 221      as a callback to the Model's `save()` method.
 222  
 223      @method addRow
 224      @param {Object} data The data or Model instance for the new record
 225      @param {Object} [config] Configuration to pass along
 226      @param {Function} [callback] Callback function for Model's `save()`
 227        @param {Error|null} callback.err If an error occurred or validation
 228          failed, this parameter will contain the error. If the sync operation
 229          succeeded, _err_ will be `null`.
 230        @param {Any} callback.response The server's response. This value will
 231          be passed to the `parse()` method, which is expected to parse it and
 232          return an attribute hash.
 233      @return {DataTable}
 234      @chainable
 235      @since 3.5.0
 236      **/
 237      addRow: function (data, config) {
 238          // Allow autoSync: true + addRow({ data }, { sync: false })
 239          var sync = (config && ('sync' in config)) ?
 240                  config.sync :
 241                  this.get('autoSync'),
 242              models, model, i, len, args;
 243  
 244          if (data && this.data) {
 245              models = this.data.add.apply(this.data, arguments);
 246  
 247              if (sync) {
 248                  models = toArray(models);
 249                  args   = toArray(arguments, 1, true);
 250  
 251                  for (i = 0, len = models.length; i < len; ++i) {
 252                      model = models[i];
 253  
 254                      if (model.isNew()) {
 255                          models[i].save.apply(models[i], args);
 256                      }
 257                  }
 258              }
 259          }
 260  
 261          return this;
 262      },
 263  
 264      /**
 265      Removes a record from the DataTable's `data` ModelList.  The record can be
 266      provided explicitly or targeted by it's `id` (see ModelList's `getById`
 267      method), `clientId`, or index in the ModelList.
 268  
 269      After locating the target Model, this relays the Model and all other passed
 270      arguments to the `data` ModelList's `remove` method.
 271  
 272      If a configuration object is passed as a second argument, and that object
 273      has `sync: true` set, the underlying Model will be destroyed, passing
 274      `{ delete: true }` to trigger calling the Model's sync layer.
 275  
 276      If the DataTable's `autoSync` attribute is set to `true`, the additional
 277      argument is not needed.
 278  
 279      If syncing and the last argument is a function, that function will be used
 280      as a callback to the Model's `destroy()` method.
 281  
 282      @method removeRow
 283      @param {Object|String|Number} id The Model instance or identifier
 284      @param {Object} [config] Configuration to pass along
 285      @param {Function} [callback] Callback function for Model's `save()`
 286        @param {Error|null} callback.err If an error occurred or validation
 287          failed, this parameter will contain the error. If the sync operation
 288          succeeded, _err_ will be `null`.
 289        @param {Any} callback.response The server's response. This value will
 290          be passed to the `parse()` method, which is expected to parse it and
 291          return an attribute hash.
 292      @return {DataTable}
 293      @chainable
 294      @since 3.5.0
 295      **/
 296      removeRow: function (id, config) {
 297          var modelList = this.data,
 298              // Allow autoSync: true + addRow({ data }, { sync: false })
 299              sync      = (config && ('sync' in config)) ?
 300                              config.sync :
 301                              this.get('autoSync'),
 302              models, model, i, len, args;
 303  
 304          // TODO: support removing via DOM element. This should be relayed to View
 305          if (isObject(id) && id instanceof this.get('recordType')) {
 306              model = id;
 307          } else if (modelList && id !== undefined) {
 308              model = modelList.getById(id) ||
 309                      modelList.getByClientId(id) ||
 310                      modelList.item(id);
 311          }
 312  
 313          if (model) {
 314              args = toArray(arguments, 1, true);
 315  
 316              models = modelList.remove.apply(modelList,
 317                  [model].concat(args));
 318  
 319              if (sync) {
 320                  if (!isObject(args[0])) {
 321                      args.unshift({});
 322                  }
 323  
 324                  args[0]['delete'] = true;
 325  
 326                  models = toArray(models);
 327  
 328                  for (i = 0, len = models.length; i < len; ++i) {
 329                      model = models[i];
 330                      model.destroy.apply(model, args);
 331                  }
 332              }
 333          }
 334  
 335          return this;
 336      },
 337  
 338      /**
 339      Updates an existing record in the DataTable's `data` ModelList.  The record
 340      can be provided explicitly or targeted by it's `id` (see ModelList's
 341      `getById` method), `clientId`, or index in the ModelList.
 342  
 343      After locating the target Model, this relays the all other passed
 344      arguments to the Model's `setAttrs` method.
 345  
 346      If a configuration object is passed as a second argument, and that object
 347      has `sync: true` set, the underlying Model will be `save()`d.
 348  
 349      If the DataTable's `autoSync` attribute is set to `true`, the additional
 350      argument is not needed.
 351  
 352      If syncing and the last argument is a function, that function will be used
 353      as a callback to the Model's `save()` method.
 354  
 355      @method modifyRow
 356      @param {Object|String|Number} id The Model instance or identifier
 357      @param {Object} data New data values for the Model
 358      @param {Object} [config] Configuration to pass along to `setAttrs()`
 359      @param {Function} [callback] Callback function for Model's `save()`
 360        @param {Error|null} callback.err If an error occurred or validation
 361          failed, this parameter will contain the error. If the sync operation
 362          succeeded, _err_ will be `null`.
 363        @param {Any} callback.response The server's response. This value will
 364          be passed to the `parse()` method, which is expected to parse it and
 365          return an attribute hash.
 366      @return {DataTable}
 367      @chainable
 368      @since 3.5.0
 369      **/
 370      modifyRow: function (id, data, config) {
 371          var modelList = this.data,
 372              // Allow autoSync: true + addRow({ data }, { sync: false })
 373              sync      = (config && ('sync' in config)) ?
 374                              config.sync :
 375                              this.get('autoSync'),
 376              model, args;
 377  
 378          if (isObject(id) && id instanceof this.get('recordType')) {
 379              model = id;
 380          } else if (modelList && id !== undefined) {
 381              model = modelList.getById(id) ||
 382                      modelList.getByClientId(id) ||
 383                      modelList.item(id);
 384          }
 385  
 386          if (model && isObject(data)) {
 387              args = toArray(arguments, 1, true);
 388  
 389              model.setAttrs.apply(model, args);
 390  
 391              if (sync && !model.isNew()) {
 392                  model.save.apply(model, args);
 393              }
 394          }
 395  
 396          return this;
 397      },
 398  
 399      // --------------------------------------------------------------------------
 400      // Protected properties and methods
 401      // --------------------------------------------------------------------------
 402  
 403      /**
 404      Default function for the `addColumn` event.
 405  
 406      Inserts the specified column at the provided index.
 407  
 408      @method _defAddColumnFn
 409      @param {EventFacade} e The `addColumn` event
 410          @param {Object} e.column The new column definition object
 411          @param {Number|Number[]} e.index The array index to insert the new column
 412      @protected
 413      @since 3.5.0
 414      **/
 415      _defAddColumnFn: function (e) {
 416          var index   = toArray(e.index),
 417              columns = this.get('columns'),
 418              cols    = columns,
 419              i, len;
 420  
 421          for (i = 0, len = index.length - 1; cols && i < len; ++i) {
 422              cols = cols[index[i]] && cols[index[i]].children;
 423          }
 424  
 425          if (cols) {
 426              cols.splice(index[i], 0, e.column);
 427  
 428              this.set('columns', columns, { originEvent: e });
 429          }
 430      },
 431  
 432      /**
 433      Default function for the `modifyColumn` event.
 434  
 435      Mixes the new column properties into the specified column definition.
 436  
 437      @method _defModifyColumnFn
 438      @param {EventFacade} e The `modifyColumn` event
 439          @param {Object|String|Number|Number[]} e.column The column definition object or identifier
 440          @param {Object} e.newColumnDef The properties to assign to the column
 441      @protected
 442      @since 3.5.0
 443      **/
 444      _defModifyColumnFn: function (e) {
 445          var columns = this.get('columns'),
 446              column  = this.getColumn(e.column);
 447  
 448          if (column) {
 449              Y.mix(column, e.newColumnDef, true);
 450  
 451              this.set('columns', columns, { originEvent: e });
 452          }
 453      },
 454  
 455      /**
 456      Default function for the `moveColumn` event.
 457  
 458      Removes the specified column from its current location and inserts it at the
 459      specified array index (may be an array of indexes for nested headers).
 460  
 461      @method _defMoveColumnFn
 462      @param {EventFacade} e The `moveColumn` event
 463          @param {Object|String|Number|Number[]} e.column The column definition object or identifier
 464          @param {Object} e.index The destination index to move to
 465      @protected
 466      @since 3.5.0
 467      **/
 468      _defMoveColumnFn: function (e) {
 469          var columns = this.get('columns'),
 470              column  = this.getColumn(e.column),
 471              toIndex = toArray(e.index),
 472              fromCols, fromIndex, toCols, i, len;
 473  
 474          if (column) {
 475              fromCols  = column._parent ? column._parent.children : columns;
 476              fromIndex = arrayIndex(fromCols, column);
 477  
 478              if (fromIndex > -1) {
 479                  toCols = columns;
 480  
 481                  for (i = 0, len = toIndex.length - 1; toCols && i < len; ++i) {
 482                      toCols = toCols[toIndex[i]] && toCols[toIndex[i]].children;
 483                  }
 484  
 485                  if (toCols) {
 486                      len = toCols.length;
 487                      fromCols.splice(fromIndex, 1);
 488                      toIndex = toIndex[i];
 489  
 490                      if (len > toCols.lenth) {
 491                          // spliced off the same array, so adjust destination
 492                          // index if necessary
 493                          if (fromIndex < toIndex) {
 494                              toIndex--;
 495                          }
 496                      }
 497  
 498                      toCols.splice(toIndex, 0, column);
 499  
 500                      this.set('columns', columns, { originEvent: e });
 501                  }
 502              }
 503          }
 504      },
 505  
 506      /**
 507      Default function for the `removeColumn` event.
 508  
 509      Splices the specified column from its containing columns array.
 510  
 511      @method _defRemoveColumnFn
 512      @param {EventFacade} e The `removeColumn` event
 513          @param {Object|String|Number|Number[]} e.column The column definition object or identifier
 514      @protected
 515      @since 3.5.0
 516      **/
 517      _defRemoveColumnFn: function (e) {
 518          var columns = this.get('columns'),
 519              column  = this.getColumn(e.column),
 520              cols, index;
 521  
 522          if (column) {
 523              cols = column._parent ? column._parent.children : columns;
 524              index = Y.Array.indexOf(cols, column);
 525  
 526              if (index > -1) {
 527                  cols.splice(index, 1);
 528  
 529                  this.set('columns', columns, { originEvent: e });
 530              }
 531          }
 532      },
 533  
 534      /**
 535      Publishes the events used by the mutation methods:
 536  
 537       * addColumn
 538       * removeColumn
 539       * modifyColumn
 540       * moveColumn
 541  
 542      @method initializer
 543      @protected
 544      @since 3.5.0
 545      **/
 546      initializer: function () {
 547          this.publish({
 548              addColumn:    { defaultFn: Y.bind('_defAddColumnFn', this) },
 549              removeColumn: { defaultFn: Y.bind('_defRemoveColumnFn', this) },
 550              moveColumn:   { defaultFn: Y.bind('_defMoveColumnFn', this) },
 551              modifyColumn: { defaultFn: Y.bind('_defModifyColumnFn', this) }
 552          });
 553      }
 554  });
 555  
 556  /**
 557  Adds an array of new records to the DataTable's `data` ModelList.  Record data
 558  can be an array of objects containing field values or an array of instance of
 559  the DataTable's configured `recordType` class.
 560  
 561  This relays all parameters to the `data` ModelList's `add` method.
 562  
 563  Technically, this is an alias to `addRow`, but please use the appropriately
 564  named method for readability.
 565  
 566  If a configuration object is passed as a second argument, and that object
 567  has `sync: true` set, the underlying Models will be `save()`d.
 568  
 569  If the DataTable's `autoSync` attribute is set to `true`, the additional
 570  argument is not needed.
 571  
 572  If syncing and the last argument is a function, that function will be used
 573  as a callback to each Model's `save()` method.
 574  
 575  @method addRows
 576  @param {Object[]} data The data or Model instances to add
 577  @param {Object} [config] Configuration to pass along
 578  @param {Function} [callback] Callback function for each Model's `save()`
 579    @param {Error|null} callback.err If an error occurred or validation
 580      failed, this parameter will contain the error. If the sync operation
 581      succeeded, _err_ will be `null`.
 582    @param {Any} callback.response The server's response. This value will
 583      be passed to the `parse()` method, which is expected to parse it and
 584      return an attribute hash.
 585  @return {DataTable}
 586  @chainable
 587  @since 3.5.0
 588  **/
 589  Mutable.prototype.addRows = Mutable.prototype.addRow;
 590  
 591  // Add feature APIs to public Y.DataTable class
 592  if (YLang.isFunction(Y.DataTable)) {
 593      Y.Base.mix(Y.DataTable, [Mutable]);
 594  }
 595  
 596  /**
 597  Fired by the `addColumn` method.
 598  
 599  @event addColumn
 600  @preventable _defAddColumnFn
 601  @param {Object} column The new column definition object
 602  @param {Number|Number[]} index The array index to insert the new column
 603  @since 3.5.0
 604  **/
 605  
 606  /**
 607  Fired by the `removeColumn` method.
 608  
 609  @event removeColumn
 610  @preventable _defRemoveColumnFn
 611  @param {Object|String|Number|Number[]} column The column definition object or identifier
 612  @since 3.5.0
 613  **/
 614  
 615  /**
 616  Fired by the `modifyColumn` method.
 617  
 618  @event modifyColumn
 619  @preventable _defModifyColumnFn
 620  @param {Object|String|Number|Number[]} column The column definition object or identifier
 621  @param {Object} newColumnDef The properties to assign to the column
 622  @since 3.5.0
 623  **/
 624  
 625  /**
 626  Fired by the `moveColumn` method.
 627  
 628  @event moveColumn
 629  @preventable _defMoveColumnFn
 630  @param {Object|String|Number|Number[]} column The column definition object or identifier
 631  @param {Object} index The destination index to move to
 632  @since 3.5.0
 633  **/
 634  
 635  
 636  
 637  }, '3.17.2', {"requires": ["datatable-base"]});


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