NOBUG: Fixed file access permissions
[moodle.git] / lib / yuilib / 3.13.0 / datatable-column-widths / datatable-column-widths.js
blob96e7985d1e2c463c5c1d5d3d4fba0e7233780cd3
1 /*
2 YUI 3.13.0 (build 508226d)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
6 */
8 YUI.add('datatable-column-widths', function (Y, NAME) {
10 /**
11 Adds basic, programmatic column width support to DataTable via column
12 configuration property `width` and method `table.setColumnWidth(id, width);`.
14 @module datatable
15 @submodule datatable-column-widths
16 @since 3.5.0
17 **/
18 var isNumber = Y.Lang.isNumber,
19     arrayIndex = Y.Array.indexOf;
21 Y.Features.add('table', 'badColWidth', {
22     test: function () {
23         var body = Y.one('body'),
24             node, broken;
26         if (body) {
27             // In modern browsers, <col style="width:X"> will make columns,
28             // *including padding and borders* X wide. The cell content width
29             // is reduced.  In old browsers and all Opera versions to date, the
30             // col's width style is passed to the cells, which causes cell
31             // padding/border to bloat the rendered width.
32             node = body.insertBefore(
33                 '<table style="position:absolute;visibility:hidden;border:0 none">' +
34                     '<colgroup><col style="width:9px"></colgroup>' +
35                     '<tbody><tr>' +
36                         '<td style="' +
37                             'padding:0 4px;' +
38                             'font:normal 2px/2px arial;' +
39                             'border:0 none">' +
40                         '.' + // Just something to give the cell dimension
41                     '</td></tr></tbody>' +
42                 '</table>',
43                 body.get('firstChild'));
45             broken = node.one('td').getComputedStyle('width') !== '1px';
47             node.remove(true);
48         }
50         return broken;
51     }
52 });
54 /**
55 _API docs for this extension are included in the DataTable class._
57 Adds basic, programmatic column width support to DataTable. Note, this does not
58 add support for truncated columns.  Due to the way HTML tables render, column
59 width is more like a "recommended width".  Column content wider than the
60 assigned width will cause the column to expand, despite the configured width.
61 Similarly if the table is too narrow to fit the column with the configured
62 column width, the column width will be reduced.
64 To set a column width, either add a `width` value to the column configuration
65 or call the `setColumnWidth(id, width)` method.
67 Note, assigning column widths is possible without this module, as each cell is
68 decorated with a class appropriate for that column which you can statically
69 target in your site's CSS.
71 To achieve absolute column widths, with content truncation, you can either:
73 1. Use this module, configure *all* columns to have `width`s, then add
74    `table-layout: fixed;` to your CSS for the appropriate `<table>`, or
75 2. Wrap the contents of all cells in the column with a `<div>` (using a
76    `cellTemplate` or `formatter`), assign the div's style `width`, then assign
77    the column `width` or add a CSS `width` to the column class created by
78    DataTable.
80 <pre><code>.yui3-datatable .yui3-datatable-col-foo {
81     padding: 0;
82     width: 125px;
84 .yui3-datatable .yui3-datatable-col-foo .yui3-datatable-liner {
85     overflow: hidden;
86     padding: 4px 10px;
87     width: 125px;
89 </pre></code>
91 <pre><code>var table = new Y.DataTable({
92     columns: [
93         {
94             key: 'foo',
95             cellTemplate:
96                 '&lt;td class="{className}">' +
97                     '&lt;div class="yui3-datatable-liner">{content}&lt;/div>' +
98                 '&lt;/td>'
99         },
100         ...
101     ],
102     ...
104 </code></pre>
106 To add a liner to all columns, either provide a custom `bodyView` to the
107 DataTable constructor or update the default `bodyView`'s `CELL_TEMPLATE` like
110 <pre><code>table.on('table:renderBody', function (e) {
111     e.view.CELL_TEMPLATE = e.view.CELL_TEMPLATE.replace(/\{content\}/,
112             '&lt;div class="yui3-datatable-liner">{content}&lt;/div>');
114 </code></pre>
116 Keep in mind that DataTable skins apply cell `padding`, so assign your CSS
117 `width`s accordingly or override the `padding` style for that column's `<td>`s
118 to 0, and add `padding` to the liner `<div>`'s styles as shown above.
120 @class DataTable.ColumnWidths
121 @for DataTable
122 @since 3.5.0
124 function ColumnWidths() {}
126 Y.mix(ColumnWidths.prototype, {
127     /**
128     The HTML template used to create the table's `<col>`s.
130     @property COL_TEMPLATE
131     @type {HTML}
132     @default '<col/>'
133     @since 3.5.0
134     **/
135     COL_TEMPLATE: '<col/>',
137     /**
138     The HTML template used to create the table's `<colgroup>`.
140     @property COLGROUP_TEMPLATE
141     @type {HTML}
142     @default '<colgroup/>'
143     @since 3.5.0
144     **/
145     COLGROUP_TEMPLATE: '<colgroup/>',
147     /**
148     Assigns the style width of the `<col>` representing the column identifed by
149     `id` and updates the column configuration.
151     Pass the empty string for `width` to return a column to auto sizing.
153     This does not trigger a `columnsChange` event today, but I can be convinced
154     that it should.
156     @method setColumnWidth
157     @param {Number|String|Object} id The column config object or key, name, or
158             index of a column in the host's `_displayColumns` array.
159     @param {Number|String} width CSS width value. Numbers are treated as pixels
160     @return {DataTable}
161     @chainable
162     @since 3.5.0
163     **/
164     setColumnWidth: function (id, width) {
165         var col = this.getColumn(id),
166             index = col && arrayIndex(this._displayColumns, col);
168         if (index > -1) {
169             if (isNumber(width)) {
170                 width += 'px';
171             }
173             col.width = width;
175             this._setColumnWidth(index, width);
176         }
178         return this;
179     },
181     //--------------------------------------------------------------------------
182     // Protected properties and methods
183     //--------------------------------------------------------------------------
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 () {
204         this.after(['renderView', 'columnsChange'], this._uiSetColumnWidths);
205     },
207     /**
208     Sets a columns's `<col>` element width style. This is needed to get around
209     browser rendering differences.
211     The colIndex corresponds to the item index of the `<col>` in the table's
212     `<colgroup>`.
214     To unset the width, pass a falsy value for the `width`.
216     @method _setColumnWidth
217     @param {Number} colIndex The display column index
218     @param {Number|String} width The desired width
219     @protected
220     @since 3.5.0
221     **/
222     // TODO: move this to a conditional module
223     _setColumnWidth: function (colIndex, width) {
224         // Opera (including Opera Next circa 1/13/2012) and IE7- pass on the
225         // width style to the cells directly, allowing padding and borders to
226         // expand the rendered width.  Chrome 16, Safari 5.1.1, and FF 3.6+ all
227         // make the rendered width equal the col's style width, reducing the
228         // cells' calculated width.
229         var colgroup  = this._colgroupNode,
230             col       = colgroup && colgroup.all('col').item(colIndex),
231             cell, getCStyle;
233         if (col) {
234             if (width && isNumber(width)) {
235                 width += 'px';
236             }
238             col.setStyle('width', width);
240             // Adjust the width for browsers that make
241             // td.style.width === col.style.width
242             if  (width && Y.Features.test('table', 'badColWidth')) {
243                 cell = this.getCell([0, colIndex]);
245                 if (cell) {
246                     getCStyle = function (prop) {
247                         return parseInt(cell.getComputedStyle(prop), 10)||0;
248                     };
250                     col.setStyle('width',
251                         // I hate this
252                         parseInt(width, 10) -
253                         getCStyle('paddingLeft') -
254                         getCStyle('paddingRight') -
255                         getCStyle('borderLeftWidth') -
256                         getCStyle('borderRightWidth') + 'px');
258                 }
259             }
260         }
261     },
263     /**
264     Populates the table's `<colgroup>` with a `<col>` per item in the `columns`
265     attribute without children.  It is assumed that these are the columns that
266     have data cells renderered for them.
268     @method _uiSetColumnWidths
269     @protected
270     @since 3.5.0
271     **/
272     _uiSetColumnWidths: function () {
273         if (!this.view) {
274             return;
275         }
277         var template = this.COL_TEMPLATE,
278             colgroup = this._colgroupNode,
279             columns  = this._displayColumns,
280             i, len;
282         if (!colgroup) {
283             colgroup = this._colgroupNode = this._createColumnGroup();
285             this._tableNode.insertBefore(
286                 colgroup,
287                 this._tableNode.one('> thead, > tfoot, > tbody'));
288         } else {
289             colgroup.empty();
290         }
292         for (i = 0, len = columns.length; i < len; ++i) {
294             colgroup.append(template);
296             this._setColumnWidth(i, columns[i].width);
297         }
298     }
299 }, true);
301 Y.DataTable.ColumnWidths = ColumnWidths;
303 Y.Base.mix(Y.DataTable, [ColumnWidths]);
305 Adds a style `width` setting to an associated `<col>`
306 element for the column.
308 Note, the assigned width will not truncate cell content, and
309 it will not preserve the configured width if doing so would
310 compromise either the instance's `width` configuration or
311 the natural width of the table's containing DOM elements.
313 If absolute widths are required, it can be accomplished with
314 some custom CSS and the use of a `cellTemplate`, or
315 `formatter`.  
317 See the description of 
318 [datatable-column-widths](DataTable.ColumnWidths.html) 
319 for an example of how to do this.
321     { key: 'a', width: '400px' },
322     { key: 'b', width: '10em' }
324 @property width
325 @type String
326 @for DataTable.Column
327  */
330 }, '3.13.0', {"requires": ["datatable-base"]});