Merge branch 'MDL-32509' of git://github.com/danpoltawski/moodle
[moodle.git] / lib / yui / 3.5.0 / build / datatable-column-widths / datatable-column-widths.js
blobdf858d46a629282fd6f9a330b0ce09f8ff56e7e6
1 /*
2 YUI 3.5.0 (build 5089)
3 Copyright 2012 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
6 */
7 YUI.add('datatable-column-widths', function(Y) {
9 /**
10 Adds basic, programmatic column width support to DataTable via column
11 configuration property `width` and method `table.setColumnWidth(id, width);`.
13 @module datatable
14 @submodule datatable-column-widths
15 @since 3.5.0
16 **/
17 var isNumber = Y.Lang.isNumber,
18     arrayIndex = Y.Array.indexOf;
20 Y.Features.add('table', 'badColWidth', {
21     test: function () {
22         var body = Y.one('body'),
23             node, broken;
25         if (body) {
26             // In modern browsers, <col style="width:X"> will make columns,
27             // *including padding and borders* X wide. The cell content width
28             // is reduced.  In old browsers and all Opera versions to date, the
29             // col's width style is passed to the cells, which causes cell
30             // padding/border to bloat the rendered width.
31             node = body.insertBefore(
32                 '<table style="position:absolute;visibility:hidden;border:0 none">' +
33                     '<colgroup><col style="width:9px"></colgroup>' +
34                     '<tbody><tr>' +
35                         '<td style="' +
36                             'padding:0 4px;' +
37                             'font:normal 2px/2px arial;' +
38                             'border:0 none">' +
39                         '.' + // Just something to give the cell dimension
40                     '</td></tr></tbody>' +
41                 '</table>',
42                 body.get('firstChild'));
44             broken = node.one('td').getComputedStyle('width') !== '1px';
46             node.remove(true);
47         }
49         return broken;
50     }
51 });
53 /**
54 _API docs for this extension are included in the DataTable class._
56 Adds basic, programmatic column width support to DataTable. Note, this does not
57 add support for truncated columns.  Due to the way HTML tables render, column
58 width is more like a "recommended width".  Column content wider than the
59 assigned width will cause the column to expand, despite the configured width.
60 Similarly if the table is too narrow to fit the column with the configured
61 column width, the column width will be reduced.
63 To set a column width, either add a `width` value to the column configuration
64 or call the `setColumnWidth(id, width)` method.
66 Note, assigning column widths is possible without this module, as each cell is
67 decorated with a class appropriate for that column which you can statically
68 target in your site's CSS.
70 To achieve absolute column widths, with content truncation, you can either:
72 1. Use this module, configure *all* columns to have `width`s, then add
73    `table-layout: fixed;` to your CSS for the appropriate `<table>`, or
74 2. Wrap the contents of all cells in the column with a `<div>` (using a
75    `cellTemplate` or `formatter`), assign the div's style `width`, then assign
76    the column `width` or add a CSS `width` to the column class created by
77    DataTable.
79 <pre><code>.yui3-datatable .yui3-datatable-col-foo {
80     padding: 0;
81     width: 125px;
83 .yui3-datatable .yui3-datatable-col-foo .yui3-datatable-liner {
84     overflow: hidden;
85     padding: 4px 10px;
86     width: 125px;
88 </pre></code>
90 <pre><code>var table = new Y.DataTable({
91     columns: [
92         {
93             key: 'foo',
94             cellTemplate:
95                 '&lt;td class="{className}">' +
96                     '&lt;div class="yui3-datatable-liner">{content}&lt;/div>' +
97                 '&lt;/td>'
98         },
99         ...
100     ],
101     ...
103 </code></pre>
105 To add a liner to all columns, either provide a custom `bodyView` to the
106 DataTable constructor or update the default `bodyView`'s `CELL_TEMPLATE` like
109 <pre><code>table.on('renderBody', function (e) {
110     e.view.CELL_TEMPLATE = e.view.CELL_TEMPLATE.replace(/\{content\}/,
111             '&lt;div class="yui3-datatable-liner">{content}&lt;/div>');
113 </code></pre>
115 Keep in mind that DataTable skins apply cell `padding`, so assign your CSS
116 `width`s accordingly or override the `padding` style for that column's `<td>`s
117 to 0, and add `padding` to the liner `<div>`'s styles as shown above.
119 @class DataTable.ColumnWidths
120 @for DataTable
121 @since 3.5.0
123 function ColumnWidths() {}
125 Y.mix(ColumnWidths.prototype, {
126     /**
127     The HTML template used to create the table's `<col>`s.
129     @property COL_TEMPLATE
130     @type {HTML}
131     @default '<col/>'
132     @since 3.5.0
133     **/
134     COL_TEMPLATE: '<col/>',
136     /**
137     The HTML template used to create the table's `<colgroup>`.
139     @property COLGROUP_TEMPLATE
140     @type {HTML}
141     @default '<colgroup/>'
142     @since 3.5.0
143     **/
144     COLGROUP_TEMPLATE: '<colgroup/>',
146     /**
147     Assigns the style width of the `<col>` representing the column identifed by
148     `id` and updates the column configuration.
150     Pass the empty string for `width` to return a column to auto sizing.
152     This does not trigger a `columnsChange` event today, but I can be convinced
153     that it should.
155     @method setColumnWidth
156     @param {Number|String|Object} id The column config object or key, name, or
157             index of a column in the host's `_displayColumns` array.
158     @param {Number|String} width CSS width value. Numbers are treated as pixels
159     @return {DataTable}
160     @chainable
161     @since 3.5.0
162     **/
163     setColumnWidth: function (id, width) {
164         var col = this.getColumn(id),
165             index = col && arrayIndex(this._displayColumns, col);
167         if (index > -1) {
168             if (isNumber(width)) {
169                 width += 'px';
170             }
172             col.width = width;
174             this._setColumnWidth(index, width);
175         }
177         return this;
178     },
180     //----------------------------------------------------------------------------
181     // Protected properties and methods
182     //----------------------------------------------------------------------------
184     /**
185     Renders the table's `<colgroup>` and populates the `_colgroupNode` property.
187     @method _createColumnGroup
188     @protected
189     @since 3.5.0
190     **/
191     _createColumnGroup: function () {
192         return Y.Node.create(this.COLGROUP_TEMPLATE);
193     },
195     /**
196     Hooks up to the rendering lifecycle to also render the `<colgroup>` and
197     subscribe to `columnChange` events.
199     @method initializer
200     @protected
201     @since 3.5.0
202     **/
203     initializer: function (config) {
204         this.after('renderTable', function (e) {
205             this._uiSetColumns();
207             this.after('columnsChange', this._uiSetColumns);
208         });
209     },
211     /**
212     Sets a columns's `<col>` element width style. This is needed to get around
213     browser rendering differences.
215     The colIndex corresponds to the item index of the `<col>` in the table's
216     `<colgroup>`.
218     To unset the width, pass a falsy value for the `width`.
220     @method _setColumnWidth
221     @param {Number} colIndex The display column index
222     @param {Number|String} width The desired width
223     @protected
224     @since 3.5.0
225     **/
226     // TODO: move this to a conditional module
227     _setColumnWidth: function (colIndex, width) {
228         // Opera (including Opera Next circa 1/13/2012) and IE7- pass on the
229         // width style to the cells directly, allowing padding and borders to
230         // expand the rendered width.  Chrome 16, Safari 5.1.1, and FF 3.6+ all
231         // make the rendered width equal the col's style width, reducing the
232         // cells' calculated width.
233         var colgroup  = this._colgroupNode,
234             col       = colgroup && colgroup.all('col').item(colIndex),
235             firstRow, cell, getCStyle;
237         if (col) {
238             if (width && isNumber(width)) {
239                 width += 'px';
240             }
242             col.setStyle('width', width);
244             // Adjust the width for browsers that make
245             // td.style.width === col.style.width
246             if  (width && Y.Features.test('table', 'badColWidth')) {
247                 firstRow = this._tbodyNode && this._tbodyNode.one('tr');
248                 cell     = firstRow && firstRow.all('td').item(colIndex);
249                 
250                 if (cell) {
251                     getCStyle = function (prop) {
252                         return parseInt(cell.getComputedStyle(prop), 10)|0;
253                     };
255                     col.setStyle('width',
256                         // I hate this
257                         parseInt(width, 10) -
258                         getCStyle('paddingLeft') -
259                         getCStyle('paddingRight') -
260                         getCStyle('borderLeftWidth') -
261                         getCStyle('borderRightWidth') + 'px');
263                 }
264             }
265         }
266     },
268     /**
269     Populates the table's `<colgroup>` with a `<col>` per item in the `columns`
270     attribute without children.  It is assumed that these are the columns that
271     have data cells renderered for them.
273     @method _uiSetColumns
274     @protected
275     @since 3.5.0
276     **/
277     _uiSetColumns: function () {
278         var template = this.COL_TEMPLATE,
279             colgroup = this._colgroupNode,
280             columns  = this._displayColumns,
281             i, len;
283         if (!colgroup) {
284             colgroup = this._colgroupNode = this._createColumnGroup();
286             this._tableNode.insertBefore(
287                 colgroup,
288                 this._tableNode.one('> thead, > tfoot, > tbody'));
289         } else {
290             colgroup.empty();
291         }
293         for (i = 0, len = columns.length; i < len; ++i) {
295             colgroup.append(template);
297             this._setColumnWidth(i, columns[i].width);
298         }
299     }
300 }, true);
302 Y.DataTable.ColumnWidths = ColumnWidths;
304 Y.Base.mix(Y.DataTable, [ColumnWidths]);
307 }, '3.5.0' ,{requires:['datatable-base']});