[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/datatable-head/ -> datatable-head-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('datatable-head', function (Y, NAME) {
   9  
  10  /**
  11  View class responsible for rendering the `<thead>` section of a table. Used as
  12  the default `headerView` for `Y.DataTable.Base` and `Y.DataTable` classes.
  13  
  14  @module datatable
  15  @submodule datatable-head
  16  @since 3.5.0
  17  **/
  18  var Lang = Y.Lang,
  19      fromTemplate = Lang.sub,
  20      isArray = Lang.isArray,
  21      toArray = Y.Array;
  22  
  23  /**
  24  View class responsible for rendering the `<thead>` section of a table. Used as
  25  the default `headerView` for `Y.DataTable.Base` and `Y.DataTable` classes.
  26  
  27  Translates the provided array of column configuration objects into a rendered
  28  `<thead>` based on the data in those objects.
  29  
  30  
  31  The structure of the column data is expected to be a single array of objects,
  32  where each object corresponds to a `<th>`.  Those objects may contain a
  33  `children` property containing a similarly structured array to indicate the
  34  nested cells should be grouped under the parent column's colspan in a separate
  35  row of header cells. E.g.
  36  
  37  <pre><code>
  38  new Y.DataTable.HeaderView({
  39    container: tableNode,
  40    columns: [
  41      { key: 'id' }, // no nesting
  42      { key: 'name', children: [
  43        { key: 'firstName', label: 'First' },
  44        { key: 'lastName',  label: 'Last' } ] }
  45    ]
  46  }).render();
  47  </code></pre>
  48  
  49  This would translate to the following visualization:
  50  
  51  <pre>
  52  ---------------------
  53  |    |     name     |
  54  |    |---------------
  55  | id | First | Last |
  56  ---------------------
  57  </pre>
  58  
  59  Supported properties of the column objects include:
  60  
  61    * `label`     - The HTML content of the header cell.
  62    * `key`       - If `label` is not specified, the `key` is used for content.
  63    * `children`  - Array of columns to appear below this column in the next
  64                    row.
  65    * `headerTemplate` - Overrides the instance's `CELL_TEMPLATE` for cells in this
  66      column only.
  67    * `abbr`      - The content of the 'abbr' attribute of the `<th>`
  68    * `title`     - The content of the 'title' attribute of the `<th>`
  69    * `className` - Adds this string of CSS classes to the column header
  70  
  71  Through the life of instantiation and rendering, the column objects will have
  72  the following properties added to them:
  73  
  74    * `id`       - (Defaulted by DataTable) The id to assign the rendered column
  75    * `_colspan` - To supply the `<th>` attribute
  76    * `_rowspan` - To supply the `<th>` attribute
  77    * `_parent`  - (Added by DataTable) If the column is a child of another
  78      column, this points to its parent column
  79  
  80  The column object is also used to provide values for {placeholder} tokens in the
  81  instance's `CELL_TEMPLATE`, so you can modify the template and include other
  82  column object properties to populate them.
  83  
  84  @class HeaderView
  85  @namespace DataTable
  86  @extends View
  87  @since 3.5.0
  88  **/
  89  Y.namespace('DataTable').HeaderView = Y.Base.create('tableHeader', Y.View, [], {
  90      // -- Instance properties -------------------------------------------------
  91  
  92      /**
  93      Template used to create the table's header cell markup.  Override this to
  94      customize how header cell markup is created.
  95  
  96      @property CELL_TEMPLATE
  97      @type {String}
  98      @default '<th id="{id}" colspan="{_colspan}" rowspan="{_rowspan}" class="{className}" scope="col" {_id}{abbr}{title}>{content}</th>'
  99      @since 3.5.0
 100      **/
 101      CELL_TEMPLATE:
 102          '<th id="{id}" colspan="{_colspan}" rowspan="{_rowspan}" class="{className}" scope="col" {_id}{abbr}{title}>{content}</th>',
 103  
 104      /**
 105      The data representation of the header rows to render.  This is assigned by
 106      parsing the `columns` configuration array, and is used by the render()
 107      method.
 108  
 109      @property columns
 110      @type {Array[]}
 111      @default (initially unset)
 112      @since 3.5.0
 113      **/
 114      //TODO: should this be protected?
 115      //columns: null,
 116  
 117      /**
 118      Template used to create the table's header row markup.  Override this to
 119      customize the row markup.
 120  
 121      @property ROW_TEMPLATE
 122      @type {String}
 123      @default '<tr>{content}</tr>'
 124      @since 3.5.0
 125      **/
 126      ROW_TEMPLATE:
 127          '<tr>{content}</tr>',
 128  
 129      /**
 130      The object that serves as the source of truth for column and row data.
 131      This property is assigned at instantiation from the `source` property of
 132      the configuration object passed to the constructor.
 133  
 134      @property source
 135      @type {Object}
 136      @default (initially unset)
 137      @since 3.5.0
 138      **/
 139      //TODO: should this be protected?
 140      //source: null,
 141  
 142      /**
 143      HTML templates used to create the `<thead>` containing the table headers.
 144  
 145      @property THEAD_TEMPLATE
 146      @type {String}
 147      @default '<thead class="{className}">{content}</thead>'
 148      @since 3.6.0
 149      **/
 150      THEAD_TEMPLATE: '<thead class="{className}"></thead>',
 151  
 152      // -- Public methods ------------------------------------------------------
 153  
 154      /**
 155      Returns the generated CSS classname based on the input.  If the `host`
 156      attribute is configured, it will attempt to relay to its `getClassName`
 157      or use its static `NAME` property as a string base.
 158  
 159      If `host` is absent or has neither method nor `NAME`, a CSS classname
 160      will be generated using this class's `NAME`.
 161  
 162      @method getClassName
 163      @param {String} token* Any number of token strings to assemble the
 164          classname from.
 165      @return {String}
 166      @protected
 167      **/
 168      getClassName: function () {
 169          // TODO: add attribute with setter? to host to use property this.host
 170          // for performance
 171          var host = this.host,
 172              NAME = (host && host.constructor.NAME) ||
 173                      this.constructor.NAME;
 174  
 175          if (host && host.getClassName) {
 176              return host.getClassName.apply(host, arguments);
 177          } else {
 178              return Y.ClassNameManager.getClassName
 179                  .apply(Y.ClassNameManager,
 180                         [NAME].concat(toArray(arguments, 0, true)));
 181          }
 182      },
 183  
 184      /**
 185      Creates the `<thead>` Node content by assembling markup generated by
 186      populating the `ROW_TEMPLATE` and `CELL_TEMPLATE` templates with content
 187      from the `columns` property.
 188  
 189      @method render
 190      @chainable
 191      @since 3.5.0
 192      **/
 193      render: function () {
 194          var table    = this.get('container'),
 195              thead    = this.theadNode ||
 196                          (this.theadNode = this._createTHeadNode()),
 197              columns  = this.columns,
 198              defaults = {
 199                  _colspan: 1,
 200                  _rowspan: 1,
 201                  abbr: '',
 202                  title: ''
 203              },
 204              i, len, j, jlen, col, html, content, values;
 205  
 206          if (thead && columns) {
 207              html = '';
 208  
 209              if (columns.length) {
 210                  for (i = 0, len = columns.length; i < len; ++i) {
 211                      content = '';
 212  
 213                      for (j = 0, jlen = columns[i].length; j < jlen; ++j) {
 214                          col = columns[i][j];
 215                          values = Y.merge(
 216                              defaults,
 217                              col, {
 218                                  className: this.getClassName('header'),
 219                                  content  : col.label || col.key ||
 220                                             ("Column " + (j + 1))
 221                              }
 222                          );
 223  
 224                          values._id = col._id ?
 225                              ' data-yui3-col-id="' + col._id + '"' : '';
 226  
 227                          if (col.abbr) {
 228                              values.abbr = ' abbr="' + col.abbr + '"';
 229                          }
 230  
 231                          if (col.title) {
 232                              values.title = ' title="' + col.title + '"';
 233                          }
 234  
 235                          if (col.className) {
 236                              values.className += ' ' + col.className;
 237                          }
 238  
 239                          if (col._first) {
 240                              values.className += ' ' + this.getClassName('first', 'header');
 241                          }
 242  
 243                          if (col._id) {
 244                              values.className +=
 245                                  ' ' + this.getClassName('col', col._id);
 246                          }
 247  
 248                          content += fromTemplate(
 249                              col.headerTemplate || this.CELL_TEMPLATE, values);
 250                      }
 251  
 252                      html += fromTemplate(this.ROW_TEMPLATE, {
 253                          content: content
 254                      });
 255                  }
 256              }
 257  
 258              thead.setHTML(html);
 259  
 260              if (thead.get('parentNode') !== table) {
 261                  table.insertBefore(thead, table.one('tfoot, tbody'));
 262              }
 263          }
 264  
 265          this.bindUI();
 266  
 267          return this;
 268      },
 269  
 270      // -- Protected and private properties and methods ------------------------
 271  
 272      /**
 273      Handles changes in the source's columns attribute.  Redraws the headers.
 274  
 275      @method _afterColumnsChange
 276      @param {EventFacade} e The `columnsChange` event object
 277      @protected
 278      @since 3.5.0
 279      **/
 280      _afterColumnsChange: function (e) {
 281          this.columns = this._parseColumns(e.newVal);
 282  
 283          this.render();
 284      },
 285  
 286      /**
 287      Binds event subscriptions from the UI and the source (if assigned).
 288  
 289      @method bindUI
 290      @protected
 291      @since 3.5.0
 292      **/
 293      bindUI: function () {
 294          if (!this._eventHandles.columnsChange) {
 295              // TODO: How best to decouple this?
 296              this._eventHandles.columnsChange =
 297                  this.after('columnsChange',
 298                      Y.bind('_afterColumnsChange', this));
 299          }
 300      },
 301  
 302      /**
 303      Creates the `<thead>` node that will store the header rows and cells.
 304  
 305      @method _createTHeadNode
 306      @return {Node}
 307      @protected
 308      @since 3.6.0
 309      **/
 310      _createTHeadNode: function () {
 311          return Y.Node.create(fromTemplate(this.THEAD_TEMPLATE, {
 312              className: this.getClassName('columns')
 313          }));
 314      },
 315  
 316      /**
 317      Destroys the instance.
 318  
 319      @method destructor
 320      @protected
 321      @since 3.5.0
 322      **/
 323      destructor: function () {
 324          (new Y.EventHandle(Y.Object.values(this._eventHandles))).detach();
 325      },
 326  
 327      /**
 328      Holds the event subscriptions needing to be detached when the instance is
 329      `destroy()`ed.
 330  
 331      @property _eventHandles
 332      @type {Object}
 333      @default undefined (initially unset)
 334      @protected
 335      @since 3.5.0
 336      **/
 337      //_eventHandles: null,
 338  
 339      /**
 340      Initializes the instance. Reads the following configuration properties:
 341  
 342        * `columns` - (REQUIRED) The initial column information
 343        * `host`    - The object to serve as source of truth for column info
 344  
 345      @method initializer
 346      @param {Object} config Configuration data
 347      @protected
 348      @since 3.5.0
 349      **/
 350      initializer: function (config) {
 351          this.host  = config.host;
 352          this.columns = this._parseColumns(config.columns);
 353  
 354          this._eventHandles = [];
 355      },
 356  
 357      /**
 358      Translate the input column format into a structure useful for rendering a
 359      `<thead>`, rows, and cells.  The structure of the input is expected to be a
 360      single array of objects, where each object corresponds to a `<th>`.  Those
 361      objects may contain a `children` property containing a similarly structured
 362      array to indicate the nested cells should be grouped under the parent
 363      column's colspan in a separate row of header cells. E.g.
 364  
 365      <pre><code>
 366      [
 367        { key: 'id' }, // no nesting
 368        { key: 'name', children: [
 369          { key: 'firstName', label: 'First' },
 370          { key: 'lastName',  label: 'Last' } ] }
 371      ]
 372      </code></pre>
 373  
 374      would indicate two header rows with the first column 'id' being assigned a
 375      `rowspan` of `2`, the 'name' column appearing in the first row with a
 376      `colspan` of `2`, and the 'firstName' and 'lastName' columns appearing in
 377      the second row, below the 'name' column.
 378  
 379      <pre>
 380      ---------------------
 381      |    |     name     |
 382      |    |---------------
 383      | id | First | Last |
 384      ---------------------
 385      </pre>
 386  
 387      Supported properties of the column objects include:
 388  
 389        * `label`    - The HTML content of the header cell.
 390        * `key`      - If `label` is not specified, the `key` is used for content.
 391        * `children` - Array of columns to appear below this column in the next
 392                       row.
 393        * `abbr`     - The content of the 'abbr' attribute of the `<th>`
 394        * `title`    - The content of the 'title' attribute of the `<th>`
 395        * `headerTemplate` - Overrides the instance's `CELL_TEMPLATE` for cells
 396          in this column only.
 397  
 398      The output structure is basically a simulation of the `<thead>` structure
 399      with arrays for rows and objects for cells.  Column objects have the
 400      following properties added to them:
 401  
 402        * `id`       - (Defaulted by DataTable) The id to assign the rendered
 403                       column
 404        * `_colspan` - Per the `<th>` attribute
 405        * `_rowspan` - Per the `<th>` attribute
 406        * `_parent`  - (Added by DataTable) If the column is a child of another
 407          column, this points to its parent column
 408  
 409      The column object is also used to provide values for {placeholder}
 410      replacement in the `CELL_TEMPLATE`, so you can modify the template and
 411      include other column object properties to populate them.
 412  
 413      @method _parseColumns
 414      @param {Object[]} data Array of column object data
 415      @return {Array[]} An array of arrays corresponding to the header row
 416              structure to render
 417      @protected
 418      @since 3.5.0
 419      **/
 420      _parseColumns: function (data) {
 421          var columns = [],
 422              stack = [],
 423              rowSpan = 1,
 424              entry, row, col, children, parent, i, len, j;
 425  
 426          if (isArray(data) && data.length) {
 427              // don't modify the input array
 428              data = data.slice();
 429  
 430              // First pass, assign colspans and calculate row count for
 431              // non-nested headers' rowspan
 432              stack.push([data, -1]);
 433  
 434              while (stack.length) {
 435                  entry = stack[stack.length - 1];
 436                  row   = entry[0];
 437                  i     = entry[1] + 1;
 438  
 439                  for (len = row.length; i < len; ++i) {
 440                      row[i] = col = Y.merge(row[i]);
 441                      children = col.children;
 442  
 443                      Y.stamp(col);
 444  
 445                      if (!col.id) {
 446                          col.id = Y.guid();
 447                      }
 448  
 449                      if (isArray(children) && children.length) {
 450                          stack.push([children, -1]);
 451                          entry[1] = i;
 452  
 453                          rowSpan = Math.max(rowSpan, stack.length);
 454  
 455                          // break to let the while loop process the children
 456                          break;
 457                      } else {
 458                          col._colspan = 1;
 459                      }
 460                  }
 461  
 462                  if (i >= len) {
 463                      // All columns in this row are processed
 464                      if (stack.length > 1) {
 465                          entry  = stack[stack.length - 2];
 466                          parent = entry[0][entry[1]];
 467  
 468                          parent._colspan = 0;
 469  
 470                          for (i = 0, len = row.length; i < len; ++i) {
 471                              // Can't use .length because in 3+ rows, colspan
 472                              // needs to aggregate the colspans of children
 473                              row[i]._parent   = parent;
 474                              parent._colspan += row[i]._colspan;
 475                          }
 476                      }
 477                      stack.pop();
 478                  }
 479              }
 480  
 481              // Second pass, build row arrays and assign rowspan
 482              for (i = 0; i < rowSpan; ++i) {
 483                  columns.push([]);
 484              }
 485  
 486              stack.push([data, -1]);
 487  
 488              while (stack.length) {
 489                  entry = stack[stack.length - 1];
 490                  row   = entry[0];
 491                  i     = entry[1] + 1;
 492  
 493                  for (len = row.length; i < len; ++i) {
 494                      col = row[i];
 495                      children = col.children;
 496  
 497                      columns[stack.length - 1].push(col);
 498  
 499                      entry[1] = i;
 500  
 501                      // collect the IDs of parent cols
 502                      col._headers = [col.id];
 503  
 504                      for (j = stack.length - 2; j >= 0; --j) {
 505                          parent = stack[j][0][stack[j][1]];
 506  
 507                          col._headers.unshift(parent.id);
 508                      }
 509  
 510                      if (children && children.length) {
 511                          // parent cells must assume rowspan 1 (long story)
 512  
 513                          // break to let the while loop process the children
 514                          stack.push([children, -1]);
 515                          break;
 516                      } else {
 517                          col._rowspan = rowSpan - stack.length + 1;
 518                      }
 519                  }
 520  
 521                  if (i >= len) {
 522                      // All columns in this row are processed
 523                      stack.pop();
 524                  }
 525              }
 526          }
 527  
 528          for (i = 0, len = columns.length; i < len; i += col._rowspan) {
 529              col = columns[i][0];
 530  
 531              col._first = true;
 532          }
 533  
 534          return columns;
 535      }
 536  });
 537  
 538  
 539  }, '3.17.2', {"requires": ["datatable-core", "view", "classnamemanager"]});


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