|
1 /* |
|
2 YUI 3.10.3 (build 2fb5187) |
|
3 Copyright 2013 Yahoo! Inc. All rights reserved. |
|
4 Licensed under the BSD License. |
|
5 http://yuilibrary.com/license/ |
|
6 */ |
|
7 |
|
8 YUI.add('datatable-column-widths', function (Y, NAME) { |
|
9 |
|
10 /** |
|
11 Adds basic, programmatic column width support to DataTable via column |
|
12 configuration property `width` and method `table.setColumnWidth(id, width);`. |
|
13 |
|
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; |
|
20 |
|
21 Y.Features.add('table', 'badColWidth', { |
|
22 test: function () { |
|
23 var body = Y.one('body'), |
|
24 node, broken; |
|
25 |
|
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')); |
|
44 |
|
45 broken = node.one('td').getComputedStyle('width') !== '1px'; |
|
46 |
|
47 node.remove(true); |
|
48 } |
|
49 |
|
50 return broken; |
|
51 } |
|
52 }); |
|
53 |
|
54 /** |
|
55 _API docs for this extension are included in the DataTable class._ |
|
56 |
|
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. |
|
63 |
|
64 To set a column width, either add a `width` value to the column configuration |
|
65 or call the `setColumnWidth(id, width)` method. |
|
66 |
|
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. |
|
70 |
|
71 To achieve absolute column widths, with content truncation, you can either: |
|
72 |
|
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. |
|
79 |
|
80 <pre><code>.yui3-datatable .yui3-datatable-col-foo { |
|
81 padding: 0; |
|
82 width: 125px; |
|
83 } |
|
84 .yui3-datatable .yui3-datatable-col-foo .yui3-datatable-liner { |
|
85 overflow: hidden; |
|
86 padding: 4px 10px; |
|
87 width: 125px; |
|
88 } |
|
89 </pre></code> |
|
90 |
|
91 <pre><code>var table = new Y.DataTable({ |
|
92 columns: [ |
|
93 { |
|
94 key: 'foo', |
|
95 cellTemplate: |
|
96 '<td class="{className}">' + |
|
97 '<div class="yui3-datatable-liner">{content}</div>' + |
|
98 '</td>' |
|
99 }, |
|
100 ... |
|
101 ], |
|
102 ... |
|
103 }); |
|
104 </code></pre> |
|
105 |
|
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 |
|
108 so: |
|
109 |
|
110 <pre><code>table.on('table:renderBody', function (e) { |
|
111 e.view.CELL_TEMPLATE = e.view.CELL_TEMPLATE.replace(/\{content\}/, |
|
112 '<div class="yui3-datatable-liner">{content}</div>'); |
|
113 }); |
|
114 </code></pre> |
|
115 |
|
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. |
|
119 |
|
120 @class DataTable.ColumnWidths |
|
121 @for DataTable |
|
122 @since 3.5.0 |
|
123 **/ |
|
124 function ColumnWidths() {} |
|
125 |
|
126 Y.mix(ColumnWidths.prototype, { |
|
127 /** |
|
128 The HTML template used to create the table's `<col>`s. |
|
129 |
|
130 @property COL_TEMPLATE |
|
131 @type {HTML} |
|
132 @default '<col/>' |
|
133 @since 3.5.0 |
|
134 **/ |
|
135 COL_TEMPLATE: '<col/>', |
|
136 |
|
137 /** |
|
138 The HTML template used to create the table's `<colgroup>`. |
|
139 |
|
140 @property COLGROUP_TEMPLATE |
|
141 @type {HTML} |
|
142 @default '<colgroup/>' |
|
143 @since 3.5.0 |
|
144 **/ |
|
145 COLGROUP_TEMPLATE: '<colgroup/>', |
|
146 |
|
147 /** |
|
148 Assigns the style width of the `<col>` representing the column identifed by |
|
149 `id` and updates the column configuration. |
|
150 |
|
151 Pass the empty string for `width` to return a column to auto sizing. |
|
152 |
|
153 This does not trigger a `columnsChange` event today, but I can be convinced |
|
154 that it should. |
|
155 |
|
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); |
|
167 |
|
168 if (index > -1) { |
|
169 if (isNumber(width)) { |
|
170 width += 'px'; |
|
171 } |
|
172 |
|
173 col.width = width; |
|
174 |
|
175 this._setColumnWidth(index, width); |
|
176 } |
|
177 |
|
178 return this; |
|
179 }, |
|
180 |
|
181 //-------------------------------------------------------------------------- |
|
182 // Protected properties and methods |
|
183 //-------------------------------------------------------------------------- |
|
184 /** |
|
185 Renders the table's `<colgroup>` and populates the `_colgroupNode` property. |
|
186 |
|
187 @method _createColumnGroup |
|
188 @protected |
|
189 @since 3.5.0 |
|
190 **/ |
|
191 _createColumnGroup: function () { |
|
192 return Y.Node.create(this.COLGROUP_TEMPLATE); |
|
193 }, |
|
194 |
|
195 /** |
|
196 Hooks up to the rendering lifecycle to also render the `<colgroup>` and |
|
197 subscribe to `columnChange` events. |
|
198 |
|
199 @method initializer |
|
200 @protected |
|
201 @since 3.5.0 |
|
202 **/ |
|
203 initializer: function () { |
|
204 this.after(['renderView', 'columnsChange'], this._uiSetColumnWidths); |
|
205 }, |
|
206 |
|
207 /** |
|
208 Sets a columns's `<col>` element width style. This is needed to get around |
|
209 browser rendering differences. |
|
210 |
|
211 The colIndex corresponds to the item index of the `<col>` in the table's |
|
212 `<colgroup>`. |
|
213 |
|
214 To unset the width, pass a falsy value for the `width`. |
|
215 |
|
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; |
|
232 |
|
233 if (col) { |
|
234 if (width && isNumber(width)) { |
|
235 width += 'px'; |
|
236 } |
|
237 |
|
238 col.setStyle('width', width); |
|
239 |
|
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]); |
|
244 |
|
245 if (cell) { |
|
246 getCStyle = function (prop) { |
|
247 return parseInt(cell.getComputedStyle(prop), 10)||0; |
|
248 }; |
|
249 |
|
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'); |
|
257 |
|
258 } |
|
259 } |
|
260 } |
|
261 }, |
|
262 |
|
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. |
|
267 |
|
268 @method _uiSetColumnWidths |
|
269 @protected |
|
270 @since 3.5.0 |
|
271 **/ |
|
272 _uiSetColumnWidths: function () { |
|
273 if (!this.view) { |
|
274 return; |
|
275 } |
|
276 |
|
277 var template = this.COL_TEMPLATE, |
|
278 colgroup = this._colgroupNode, |
|
279 columns = this._displayColumns, |
|
280 i, len; |
|
281 |
|
282 if (!colgroup) { |
|
283 colgroup = this._colgroupNode = this._createColumnGroup(); |
|
284 |
|
285 this._tableNode.insertBefore( |
|
286 colgroup, |
|
287 this._tableNode.one('> thead, > tfoot, > tbody')); |
|
288 } else { |
|
289 colgroup.empty(); |
|
290 } |
|
291 |
|
292 for (i = 0, len = columns.length; i < len; ++i) { |
|
293 |
|
294 colgroup.append(template); |
|
295 |
|
296 this._setColumnWidth(i, columns[i].width); |
|
297 } |
|
298 } |
|
299 }, true); |
|
300 |
|
301 Y.DataTable.ColumnWidths = ColumnWidths; |
|
302 |
|
303 Y.Base.mix(Y.DataTable, [ColumnWidths]); |
|
304 |
|
305 |
|
306 }, '3.10.3', {"requires": ["datatable-base"]}); |