3
Copyright 2012 Yahoo! Inc. All rights reserved.
4
Licensed under the BSD License.
5
http://yuilibrary.com/license/
7
YUI.add('datatable-column-widths', function(Y) {
10
Adds basic, programmatic column width support to DataTable via column
11
configuration property `width` and method `table.setColumnWidth(id, width);`.
14
@submodule datatable-column-widths
17
var isNumber = Y.Lang.isNumber,
18
arrayIndex = Y.Array.indexOf;
20
Y.Features.add('table', 'badColWidth', {
22
var body = Y.one('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>' +
37
'font:normal 2px/2px arial;' +
39
'.' + // Just something to give the cell dimension
40
'</td></tr></tbody>' +
42
body.get('firstChild'));
44
broken = node.one('td').getComputedStyle('width') !== '1px';
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
79
<pre><code>.yui3-datatable .yui3-datatable-col-foo {
83
.yui3-datatable .yui3-datatable-col-foo .yui3-datatable-liner {
90
<pre><code>var table = new Y.DataTable({
95
'<td class="{className}">' +
96
'<div class="yui3-datatable-liner">{content}</div>' +
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
'<div class="yui3-datatable-liner">{content}</div>');
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
123
function ColumnWidths() {}
125
Y.mix(ColumnWidths.prototype, {
127
The HTML template used to create the table's `<col>`s.
129
@property COL_TEMPLATE
134
COL_TEMPLATE: '<col/>',
137
The HTML template used to create the table's `<colgroup>`.
139
@property COLGROUP_TEMPLATE
141
@default '<colgroup/>'
144
COLGROUP_TEMPLATE: '<colgroup/>',
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
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
163
setColumnWidth: function (id, width) {
164
var col = this.getColumn(id),
165
index = col && arrayIndex(this._displayColumns, col);
168
if (isNumber(width)) {
174
this._setColumnWidth(index, width);
180
//----------------------------------------------------------------------------
181
// Protected properties and methods
182
//----------------------------------------------------------------------------
185
Renders the table's `<colgroup>` and populates the `_colgroupNode` property.
187
@method _createColumnGroup
191
_createColumnGroup: function () {
192
return Y.Node.create(this.COLGROUP_TEMPLATE);
196
Hooks up to the rendering lifecycle to also render the `<colgroup>` and
197
subscribe to `columnChange` events.
203
initializer: function (config) {
204
this.after('renderTable', function (e) {
205
this._uiSetColumns();
207
this.after('columnsChange', this._uiSetColumns);
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
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
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;
238
if (width && isNumber(width)) {
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);
251
getCStyle = function (prop) {
252
return parseInt(cell.getComputedStyle(prop), 10)|0;
255
col.setStyle('width',
257
parseInt(width, 10) -
258
getCStyle('paddingLeft') -
259
getCStyle('paddingRight') -
260
getCStyle('borderLeftWidth') -
261
getCStyle('borderRightWidth') + 'px');
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
277
_uiSetColumns: function () {
278
var template = this.COL_TEMPLATE,
279
colgroup = this._colgroupNode,
280
columns = this._displayColumns,
284
colgroup = this._colgroupNode = this._createColumnGroup();
286
this._tableNode.insertBefore(
288
this._tableNode.one('> thead, > tfoot, > tbody'));
293
for (i = 0, len = columns.length; i < len; ++i) {
295
colgroup.append(template);
297
this._setColumnWidth(i, columns[i].width);
302
Y.DataTable.ColumnWidths = ColumnWidths;
304
Y.Base.mix(Y.DataTable, [ColumnWidths]);
307
}, '3.5.0' ,{requires:['datatable-base']});