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