head.js revision 53c97f474022b2633bdeccab063f518c4015f27a
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith/**
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke SmithView class responsible for rendering the `<thead>` section of a table. Used as
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smiththe default `headerView` for `Y.DataTable.Base` and `Y.DataTable` classes.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith@module datatable
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith@submodule datatable-head
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith@since 3.5.0
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith**/
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smithvar Lang = Y.Lang,
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith fromTemplate = Lang.sub,
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith isArray = Lang.isArray,
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith toArray = Y.Array,
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith ClassNameManager = Y.ClassNameManager,
e0a1afd287c016be5722249b10ba81684f33886bLuke Smith _getClassName = ClassNameManager.getClassName;
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith/**
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke SmithView class responsible for rendering the `<thead>` section of a table. Used as
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smiththe default `headerView` for `Y.DataTable.Base` and `Y.DataTable` classes.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke SmithTranslates the provided array of column configuration objects into a rendered
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith`<thead>` based on the data in those objects.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
e0a1afd287c016be5722249b10ba81684f33886bLuke SmithThe structure of the column data is expected to be a single array of objects,
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smithwhere each object corresponds to a `<th>`. Those objects may contain a
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith`children` property containing a similarly structured array to indicate the
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smithnested cells should be grouped under the parent column's colspan in a separate
e0a1afd287c016be5722249b10ba81684f33886bLuke Smithrow of header cells. E.g.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith<pre><code>
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smithnew Y.DataTable.HeaderView({
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith container: tableNode,
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith columns: [
e0a1afd287c016be5722249b10ba81684f33886bLuke Smith { key: 'id' }, // no nesting
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith { key: 'name', children: [
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith { key: 'firstName', label: 'First' },
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith { key: 'lastName', label: 'Last' } ] }
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith ]
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith}).render();
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith</code></pre>
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke SmithThis would translate to the following visualization:
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith<pre>
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith---------------------
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith| | name |
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith| |---------------
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith| id | First | Last |
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith---------------------
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith</pre>
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke SmithSupported properties of the column objects include:
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith * `label` - The HTML content of the header cell.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith * `key` - If `label` is not specified, the `key` is used for content.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith * `children` - Array of columns to appear below this column in the next
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith row.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith * `headerTemplate` - Overrides the instance's `CELL_TEMPLATE` for cells in this
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith column only.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith * `abbr` - The content of the 'abbr' attribute of the `<th>`
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith * `className` - Adds this string of CSS classes to the column header
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
1a40b51b558814291aa784dfd7335004602428ceLuke SmithThrough the life of instantiation and rendering, the column objects will have
1a40b51b558814291aa784dfd7335004602428ceLuke Smiththe following properties added to them:
b30dbdf0ef8772c980fc59f2d2015a295c0b4dc3Luke Smith
b30dbdf0ef8772c980fc59f2d2015a295c0b4dc3Luke Smith * `id` - (Defaulted by DataTable) The id to assign the rendered column
b30dbdf0ef8772c980fc59f2d2015a295c0b4dc3Luke Smith * `_colspan` - To supply the `<th>` attribute
b30dbdf0ef8772c980fc59f2d2015a295c0b4dc3Luke Smith * `_rowspan` - To supply the `<th>` attribute
b30dbdf0ef8772c980fc59f2d2015a295c0b4dc3Luke Smith * `_parent` - (Added by DataTable) If the column is a child of another
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith column, this points to its parent column
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith
0e7d399f99fcb097a927af7e6588f393740585a2Luke SmithThe column object is also used to provide values for {placeholder} tokens in the
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smithinstance's `CELL_TEMPLATE`, so you can modify the template and include other
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smithcolumn object properties to populate them.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith@class HeaderView
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith@namespace DataTable
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith@extends View
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith@since 3.5.0
e0a1afd287c016be5722249b10ba81684f33886bLuke Smith**/
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke SmithY.namespace('DataTable').HeaderView = Y.Base.create('tableHeader', Y.View, [], {
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith // -- Instance properties -------------------------------------------------
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith /**
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith Template used to create the table's header cell markup. Override this to
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith customize how header cell markup is created.
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith @property CELL_TEMPLATE
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith @type {HTML}
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @default '<th id="{id}" colspan="{_colspan}" rowspan="{_rowspan}" class="{className}" scope="col" {_id}{abbr}>{content}</th>'
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @since 3.5.0
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith **/
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith CELL_TEMPLATE:
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith '<th id="{id}" colspan="{_colspan}" rowspan="{_rowspan}" class="{className}" scope="col" {_id}{abbr}>{content}</th>',
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith /**
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith The data representation of the header rows to render. This is assigned by
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith parsing the `columns` configuration array, and is used by the render()
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith method.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @property columns
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @type {Array[]}
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @default (initially unset)
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @since 3.5.0
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith **/
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith //TODO: should this be protected?
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith //columns: null,
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith /**
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith Template used to create the table's header row markup. Override this to
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith customize the row markup.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @property ROW_TEMPLATE
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @type {HTML}
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @default '<tr>{content}</tr>'
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @since 3.5.0
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith **/
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith ROW_TEMPLATE:
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith '<tr>{content}</tr>',
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith /**
0e7d399f99fcb097a927af7e6588f393740585a2Luke Smith The object that serves as the source of truth for column and row data.
0e7d399f99fcb097a927af7e6588f393740585a2Luke Smith This property is assigned at instantiation from the `source` property of
0e7d399f99fcb097a927af7e6588f393740585a2Luke Smith the configuration object passed to the constructor.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
0e7d399f99fcb097a927af7e6588f393740585a2Luke Smith @property source
0e7d399f99fcb097a927af7e6588f393740585a2Luke Smith @type {Object}
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @default (initially unset)
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @since 3.5.0
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith **/
e0a1afd287c016be5722249b10ba81684f33886bLuke Smith //TODO: should this be protected?
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith //source: null,
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith // -- Public methods ------------------------------------------------------
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith /**
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith Builds a CSS class name from the provided tokens. If the instance is
b30dbdf0ef8772c980fc59f2d2015a295c0b4dc3Luke Smith created with `cssPrefix` or `source` in the configuration, it will use this
b30dbdf0ef8772c980fc59f2d2015a295c0b4dc3Luke Smith prefix (the `_cssPrefix` of the `source` object) as the base token. This
b30dbdf0ef8772c980fc59f2d2015a295c0b4dc3Luke Smith allows class instances to generate markup with class names that correspond
b30dbdf0ef8772c980fc59f2d2015a295c0b4dc3Luke Smith to the parent class that is consuming them.
b30dbdf0ef8772c980fc59f2d2015a295c0b4dc3Luke Smith
b30dbdf0ef8772c980fc59f2d2015a295c0b4dc3Luke Smith @method getClassName
b30dbdf0ef8772c980fc59f2d2015a295c0b4dc3Luke Smith @param {String} token* Any number of tokens to include in the class name
b30dbdf0ef8772c980fc59f2d2015a295c0b4dc3Luke Smith @return {String} The generated class name
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @since 3.5.0
1a40b51b558814291aa784dfd7335004602428ceLuke Smith **/
1a40b51b558814291aa784dfd7335004602428ceLuke Smith getClassName: function () {
1a40b51b558814291aa784dfd7335004602428ceLuke Smith var args = toArray(arguments);
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith args.unshift(this._cssPrefix);
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith args.push(true);
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith return _getClassName.apply(ClassNameManager, args);
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith },
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith
1a40b51b558814291aa784dfd7335004602428ceLuke Smith /**
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith Creates the `<thead>` Node content by assembling markup generated by
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith populating the `ROW_TEMPLATE` and `CELL_TEMPLATE` templates with content
1a40b51b558814291aa784dfd7335004602428ceLuke Smith from the `columns` property.
1a40b51b558814291aa784dfd7335004602428ceLuke Smith
1a40b51b558814291aa784dfd7335004602428ceLuke Smith @method render
1a40b51b558814291aa784dfd7335004602428ceLuke Smith @return {HeaderView} The instance
1a40b51b558814291aa784dfd7335004602428ceLuke Smith @chainable
1a40b51b558814291aa784dfd7335004602428ceLuke Smith @since 3.5.0
b30dbdf0ef8772c980fc59f2d2015a295c0b4dc3Luke Smith **/
1a40b51b558814291aa784dfd7335004602428ceLuke Smith render: function () {
1a40b51b558814291aa784dfd7335004602428ceLuke Smith var thead = this.get('container'),
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith columns = this.columns,
79fac3c43e396f54a5fb368ac33ff7c21df23397Luke Smith defaults = {
79fac3c43e396f54a5fb368ac33ff7c21df23397Luke Smith _colspan: 1,
1a40b51b558814291aa784dfd7335004602428ceLuke Smith _rowspan: 1,
79fac3c43e396f54a5fb368ac33ff7c21df23397Luke Smith abbr: ''
79fac3c43e396f54a5fb368ac33ff7c21df23397Luke Smith },
79fac3c43e396f54a5fb368ac33ff7c21df23397Luke Smith i, len, j, jlen, col, html, content, values;
1a40b51b558814291aa784dfd7335004602428ceLuke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith if (thead && columns) {
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith html = '';
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith if (columns.length) {
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith for (i = 0, len = columns.length; i < len; ++i) {
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith content = '';
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith for (j = 0, jlen = columns[i].length; j < jlen; ++j) {
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith col = columns[i][j];
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith values = Y.merge(
1a40b51b558814291aa784dfd7335004602428ceLuke Smith defaults,
1a40b51b558814291aa784dfd7335004602428ceLuke Smith col, {
79fac3c43e396f54a5fb368ac33ff7c21df23397Luke Smith className: this.getClassName('header'),
79fac3c43e396f54a5fb368ac33ff7c21df23397Luke Smith content : col.label || col.key ||
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith ("Column " + (j + 1))
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith }
1a40b51b558814291aa784dfd7335004602428ceLuke Smith );
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith values._id = col._id ?
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith ' data-yui3-col-id="' + col._id + '"' : '';
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith if (col.abbr) {
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith values.abbr = ' abbr="' + col.abbr + '"';
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith }
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith if (col.className) {
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith values.className += ' ' + col.className;
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith }
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith if (col._first) {
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith values.className += ' ' + this.getClassName('first', 'header');
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith }
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith if (col._id) {
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith values.className +=
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith ' ' + this.getClassName('col', col._id);
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith }
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
1080d9c735088a474affe30611ae889315840a17Luke Smith content += fromTemplate(
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith col.headerTemplate || this.CELL_TEMPLATE, values);
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith }
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
1080d9c735088a474affe30611ae889315840a17Luke Smith html += fromTemplate(this.ROW_TEMPLATE, {
1080d9c735088a474affe30611ae889315840a17Luke Smith content: content
1080d9c735088a474affe30611ae889315840a17Luke Smith });
1080d9c735088a474affe30611ae889315840a17Luke Smith }
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith }
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith thead.setContent(html);
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith }
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith this.bindUI();
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith return this;
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith },
1080d9c735088a474affe30611ae889315840a17Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith // -- Protected and private properties and methods ------------------------
1080d9c735088a474affe30611ae889315840a17Luke Smith /**
1080d9c735088a474affe30611ae889315840a17Luke Smith The base token for classes created with the `getClassName` method.
1080d9c735088a474affe30611ae889315840a17Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @property _cssPrefix
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @type {String}
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @default 'yui3-table'
1080d9c735088a474affe30611ae889315840a17Luke Smith @protected
1080d9c735088a474affe30611ae889315840a17Luke Smith @since 3.5.0
1080d9c735088a474affe30611ae889315840a17Luke Smith **/
1080d9c735088a474affe30611ae889315840a17Luke Smith _cssPrefix: ClassNameManager.getClassName('table'),
1080d9c735088a474affe30611ae889315840a17Luke Smith
1080d9c735088a474affe30611ae889315840a17Luke Smith /**
1080d9c735088a474affe30611ae889315840a17Luke Smith Handles changes in the source's columns attribute. Redraws the headers.
1080d9c735088a474affe30611ae889315840a17Luke Smith
1080d9c735088a474affe30611ae889315840a17Luke Smith @method _afterColumnsChange
1080d9c735088a474affe30611ae889315840a17Luke Smith @param {EventFacade} e The `columnsChange` event object
1080d9c735088a474affe30611ae889315840a17Luke Smith @protected
1080d9c735088a474affe30611ae889315840a17Luke Smith @since 3.5.0
1080d9c735088a474affe30611ae889315840a17Luke Smith **/
1080d9c735088a474affe30611ae889315840a17Luke Smith _afterColumnsChange: function (e) {
1080d9c735088a474affe30611ae889315840a17Luke Smith this.columns = this._parseColumns(e.newVal);
1080d9c735088a474affe30611ae889315840a17Luke Smith
1080d9c735088a474affe30611ae889315840a17Luke Smith this.render();
1080d9c735088a474affe30611ae889315840a17Luke Smith },
1080d9c735088a474affe30611ae889315840a17Luke Smith
1080d9c735088a474affe30611ae889315840a17Luke Smith /**
1080d9c735088a474affe30611ae889315840a17Luke Smith Binds event subscriptions from the UI and the source (if assigned).
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @method bindUI
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @protected
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @since 3.5.0
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith **/
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith bindUI: function () {
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith if (this.source && !this._eventHandles.columnsChange) {
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith // TODO: How best to decouple this?
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith this._eventHandles.columnsChange =
e0a1afd287c016be5722249b10ba81684f33886bLuke Smith this.source.after('columnsChange',
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith Y.bind('_afterColumnsChange', this));
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith }
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith },
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith /**
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith Destroys the instance.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @method destructor
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @protected
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @since 3.5.0
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith **/
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith destructor: function () {
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith (new Y.EventHandle(Y.Object.values(this._eventHandles))).detach();
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith },
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith /**
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith Holds the event subscriptions needing to be detached when the instance is
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith `destroy()`ed.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @property _eventHandles
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @type {Object}
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @default undefined (initially unset)
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @protected
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @since 3.5.0
e0a1afd287c016be5722249b10ba81684f33886bLuke Smith **/
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith //_eventHandles: null,
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith /**
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith Initializes the instance. Reads the following configuration properties:
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith * `columns` - (REQUIRED) The initial column information
e0a1afd287c016be5722249b10ba81684f33886bLuke Smith * `cssPrefix` - The base string for classes generated by `getClassName`
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith * `source` - The object to serve as source of truth for column info
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @method initializer
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @param {Object} config Configuration data
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @protected
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith @since 3.5.0
e0a1afd287c016be5722249b10ba81684f33886bLuke Smith **/
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith initializer: function (config) {
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith config || (config = {});
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith var cssPrefix = config.cssPrefix || (config.source || {}).cssPrefix;
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
e0a1afd287c016be5722249b10ba81684f33886bLuke Smith this.source = config.source;
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith this.columns = this._parseColumns(config.columns);
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith this._eventHandles = [];
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith if (cssPrefix) {
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith this._cssPrefix = cssPrefix;
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith }
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith },
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith /**
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith Translate the input column format into a structure useful for rendering a
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith `<thead>`, rows, and cells. The structure of the input is expected to be a
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith single array of objects, where each object corresponds to a `<th>`. Those
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith objects may contain a `children` property containing a similarly structured
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith array to indicate the nested cells should be grouped under the parent
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith column's colspan in a separate row of header cells. E.g.
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith <pre><code>
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith [
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith { key: 'id' }, // no nesting
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith { key: 'name', children: [
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith { key: 'firstName', label: 'First' },
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith { key: 'lastName', label: 'Last' } ] }
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith ]
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith </code></pre>
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith would indicate two header rows with the first column 'id' being assigned a
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith `rowspan` of `2`, the 'name' column appearing in the first row with a
e0a1afd287c016be5722249b10ba81684f33886bLuke Smith `colspan` of `2`, and the 'firstName' and 'lastName' columns appearing in
cfb2dc43f7aba18c4c6b0db07ca060089bd2e670Luke Smith the second row, below the 'name' column.
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith <pre>
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith ---------------------
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith | | name |
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith | |---------------
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith | id | First | Last |
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith ---------------------
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith </pre>
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith Supported properties of the column objects include:
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith * `label` - The HTML content of the header cell.
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith * `key` - If `label` is not specified, the `key` is used for content.
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith * `children` - Array of columns to appear below this column in the next
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith row.
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith * `abbr` - The content of the 'abbr' attribute of the `<th>`
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith * `headerTemplate` - Overrides the instance's `CELL_TEMPLATE` for cells
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith in this column only.
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith The output structure is basically a simulation of the `<thead>` structure
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith with arrays for rows and objects for cells. Column objects have the
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith following properties added to them:
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith * `id` - (Defaulted by DataTable) The id to assign the rendered
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith column
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith * `_colspan` - Per the `<th>` attribute
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith * `_rowspan` - Per the `<th>` attribute
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith * `_parent` - (Added by DataTable) If the column is a child of another
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith column, this points to its parent column
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith The column object is also used to provide values for {placeholder}
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith replacement in the `CELL_TEMPLATE`, so you can modify the template and
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith include other column object properties to populate them.
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith @method _parseColumns
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith @param {Object[]} data Array of column object data
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith @return {Array[]} An array of arrays corresponding to the header row
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith structure to render
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith @protected
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith @since 3.5.0
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith **/
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith _parseColumns: function (data) {
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith var columns = [],
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith stack = [],
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith rowSpan = 1,
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith entry, row, col, children, parent, i, len, j;
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith if (isArray(data) && data.length) {
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith // First pass, assign colspans and calculate row count for
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith // non-nested headers' rowspan
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith stack.push([data, -1]);
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith while (stack.length) {
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith entry = stack[stack.length - 1];
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith row = entry[0];
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith i = entry[1] + 1;
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith for (len = row.length; i < len; ++i) {
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith col = row[i];
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith children = col.children;
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith Y.stamp(col);
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith if (isArray(children) && children.length) {
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith stack.push([children, -1]);
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith entry[1] = i;
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith rowSpan = Math.max(rowSpan, stack.length);
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith // break to let the while loop process the children
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith break;
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith } else {
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith col._colspan = 1;
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith }
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith }
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith if (i >= len) {
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith // All columns in this row are processed
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith if (stack.length > 1) {
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith entry = stack[stack.length - 2];
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith parent = entry[0][entry[1]];
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith parent._colspan = 0;
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith for (i = 0, len = row.length; i < len; ++i) {
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith // Can't use .length because in 3+ rows, colspan
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith // needs to aggregate the colspans of children
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith parent._colspan += row[i]._colspan;
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith }
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith }
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith stack.pop();
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith }
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith }
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith // Second pass, build row arrays and assign rowspan
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith for (i = 0; i < rowSpan; ++i) {
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith columns.push([]);
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith }
deb753fedac28c24a82440a4f7ca53df8a72a124Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith stack.push([data, -1]);
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith while (stack.length) {
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith entry = stack[stack.length - 1];
d15134141197c4fc93eb6094020e03eb72aa8d73Luke Smith row = entry[0];
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith i = entry[1] + 1;
a3e011a6940a2707d43148e12f3d3cd6fd388794Luke Smith
for (len = row.length; i < len; ++i) {
col = row[i];
children = col.children;
columns[stack.length - 1].push(col);
entry[1] = i;
// collect the IDs of parent cols
col._headers = [col.id];
for (j = stack.length - 2; j >= 0; --j) {
parent = stack[j][0][stack[j][1]];
col._headers.unshift(parent.id);
}
if (children && children.length) {
// parent cells must assume rowspan 1 (long story)
// break to let the while loop process the children
stack.push([children, -1]);
break;
} else {
col._rowspan = rowSpan - stack.length + 1;
}
}
if (i >= len) {
// All columns in this row are processed
stack.pop();
}
}
}
for (i = 0, len = columns.length; i < len; i += col._rowspan) {
col = columns[i][0];
col._first = true;
}
return columns;
}
});