API Docs for: 3.8.0
Show:

File: datatable/js/colwidths.js

  1. /**
  2. Adds basic, programmatic column width support to DataTable via column
  3. configuration property `width` and method `table.setColumnWidth(id, width);`.

  4. @module datatable
  5. @submodule datatable-column-widths
  6. @since 3.5.0
  7. **/
  8. var isNumber = Y.Lang.isNumber,
  9.     arrayIndex = Y.Array.indexOf;

  10. Y.Features.add('table', 'badColWidth', {
  11.     test: function () {
  12.         var body = Y.one('body'),
  13.             node, broken;

  14.         if (body) {
  15.             // In modern browsers, <col style="width:X"> will make columns,
  16.             // *including padding and borders* X wide. The cell content width
  17.             // is reduced.  In old browsers and all Opera versions to date, the
  18.             // col's width style is passed to the cells, which causes cell
  19.             // padding/border to bloat the rendered width.
  20.             node = body.insertBefore(
  21.                 '<table style="position:absolute;visibility:hidden;border:0 none">' +
  22.                     '<colgroup><col style="width:9px"></colgroup>' +
  23.                     '<tbody><tr>' +
  24.                         '<td style="' +
  25.                             'padding:0 4px;' +
  26.                             'font:normal 2px/2px arial;' +
  27.                             'border:0 none">' +
  28.                         '.' + // Just something to give the cell dimension
  29.                     '</td></tr></tbody>' +
  30.                 '</table>',
  31.                 body.get('firstChild'));

  32.             broken = node.one('td').getComputedStyle('width') !== '1px';

  33.             node.remove(true);
  34.         }

  35.         return broken;
  36.     }
  37. });

  38. /**
  39. _API docs for this extension are included in the DataTable class._

  40. Adds basic, programmatic column width support to DataTable. Note, this does not
  41. add support for truncated columns.  Due to the way HTML tables render, column
  42. width is more like a "recommended width".  Column content wider than the
  43. assigned width will cause the column to expand, despite the configured width.
  44. Similarly if the table is too narrow to fit the column with the configured
  45. column width, the column width will be reduced.

  46. To set a column width, either add a `width` value to the column configuration
  47. or call the `setColumnWidth(id, width)` method.

  48. Note, assigning column widths is possible without this module, as each cell is
  49. decorated with a class appropriate for that column which you can statically
  50. target in your site's CSS.

  51. To achieve absolute column widths, with content truncation, you can either:

  52. 1. Use this module, configure *all* columns to have `width`s, then add
  53.    `table-layout: fixed;` to your CSS for the appropriate `<table>`, or
  54. 2. Wrap the contents of all cells in the column with a `<div>` (using a
  55.    `cellTemplate` or `formatter`), assign the div's style `width`, then assign
  56.    the column `width` or add a CSS `width` to the column class created by
  57.    DataTable.

  58. <pre><code>.yui3-datatable .yui3-datatable-col-foo {
  59.     padding: 0;
  60.     width: 125px;
  61. }
  62. .yui3-datatable .yui3-datatable-col-foo .yui3-datatable-liner {
  63.     overflow: hidden;
  64.     padding: 4px 10px;
  65.     width: 125px;
  66. }
  67. </pre></code>

  68. <pre><code>var table = new Y.DataTable({
  69.     columns: [
  70.         {
  71.             key: 'foo',
  72.             cellTemplate:
  73.                 '&lt;td class="{className}">' +
  74.                     '&lt;div class="yui3-datatable-liner">{content}&lt;/div>' +
  75.                 '&lt;/td>'
  76.         },
  77.         ...
  78.     ],
  79.     ...
  80. });
  81. </code></pre>

  82. To add a liner to all columns, either provide a custom `bodyView` to the
  83. DataTable constructor or update the default `bodyView`'s `CELL_TEMPLATE` like
  84. so:

  85. <pre><code>table.on('renderBody', function (e) {
  86.     e.view.CELL_TEMPLATE = e.view.CELL_TEMPLATE.replace(/\{content\}/,
  87.             '&lt;div class="yui3-datatable-liner">{content}&lt;/div>');
  88. });
  89. </code></pre>

  90. Keep in mind that DataTable skins apply cell `padding`, so assign your CSS
  91. `width`s accordingly or override the `padding` style for that column's `<td>`s
  92. to 0, and add `padding` to the liner `<div>`'s styles as shown above.

  93. @class DataTable.ColumnWidths
  94. @for DataTable
  95. @since 3.5.0
  96. **/
  97. function ColumnWidths() {}

  98. Y.mix(ColumnWidths.prototype, {
  99.     /**
  100.     The HTML template used to create the table's `<col>`s.

  101.     @property COL_TEMPLATE
  102.     @type {HTML}
  103.     @default '<col/>'
  104.     @since 3.5.0
  105.     **/
  106.     COL_TEMPLATE: '<col/>',

  107.     /**
  108.     The HTML template used to create the table's `<colgroup>`.

  109.     @property COLGROUP_TEMPLATE
  110.     @type {HTML}
  111.     @default '<colgroup/>'
  112.     @since 3.5.0
  113.     **/
  114.     COLGROUP_TEMPLATE: '<colgroup/>',

  115.     /**
  116.     Assigns the style width of the `<col>` representing the column identifed by
  117.     `id` and updates the column configuration.

  118.     Pass the empty string for `width` to return a column to auto sizing.

  119.     This does not trigger a `columnsChange` event today, but I can be convinced
  120.     that it should.

  121.     @method setColumnWidth
  122.     @param {Number|String|Object} id The column config object or key, name, or
  123.             index of a column in the host's `_displayColumns` array.
  124.     @param {Number|String} width CSS width value. Numbers are treated as pixels
  125.     @return {DataTable}
  126.     @chainable
  127.     @since 3.5.0
  128.     **/
  129.     setColumnWidth: function (id, width) {
  130.         var col = this.getColumn(id),
  131.             index = col && arrayIndex(this._displayColumns, col);

  132.         if (index > -1) {
  133.             if (isNumber(width)) {
  134.                 width += 'px';
  135.             }

  136.             col.width = width;

  137.             this._setColumnWidth(index, width);
  138.         }

  139.         return this;
  140.     },

  141.     //--------------------------------------------------------------------------
  142.     // Protected properties and methods
  143.     //--------------------------------------------------------------------------
  144.     /**
  145.     Renders the table's `<colgroup>` and populates the `_colgroupNode` property.

  146.     @method _createColumnGroup
  147.     @protected
  148.     @since 3.5.0
  149.     **/
  150.     _createColumnGroup: function () {
  151.         return Y.Node.create(this.COLGROUP_TEMPLATE);
  152.     },

  153.     /**
  154.     Hooks up to the rendering lifecycle to also render the `<colgroup>` and
  155.     subscribe to `columnChange` events.

  156.     @method initializer
  157.     @protected
  158.     @since 3.5.0
  159.     **/
  160.     initializer: function (config) {
  161.         this.after(['renderView', 'columnsChange'], this._uiSetColumnWidths);
  162.     },

  163.     /**
  164.     Sets a columns's `<col>` element width style. This is needed to get around
  165.     browser rendering differences.

  166.     The colIndex corresponds to the item index of the `<col>` in the table's
  167.     `<colgroup>`.

  168.     To unset the width, pass a falsy value for the `width`.

  169.     @method _setColumnWidth
  170.     @param {Number} colIndex The display column index
  171.     @param {Number|String} width The desired width
  172.     @protected
  173.     @since 3.5.0
  174.     **/
  175.     // TODO: move this to a conditional module
  176.     _setColumnWidth: function (colIndex, width) {
  177.         // Opera (including Opera Next circa 1/13/2012) and IE7- pass on the
  178.         // width style to the cells directly, allowing padding and borders to
  179.         // expand the rendered width.  Chrome 16, Safari 5.1.1, and FF 3.6+ all
  180.         // make the rendered width equal the col's style width, reducing the
  181.         // cells' calculated width.
  182.         var colgroup  = this._colgroupNode,
  183.             col       = colgroup && colgroup.all('col').item(colIndex),
  184.             cell, getCStyle;

  185.         if (col) {
  186.             if (width && isNumber(width)) {
  187.                 width += 'px';
  188.             }

  189.             col.setStyle('width', width);

  190.             // Adjust the width for browsers that make
  191.             // td.style.width === col.style.width
  192.             if  (width && Y.Features.test('table', 'badColWidth')) {
  193.                 cell = this.getCell([0, colIndex]);
  194.                
  195.                 if (cell) {
  196.                     getCStyle = function (prop) {
  197.                         return parseInt(cell.getComputedStyle(prop), 10)|0;
  198.                     };

  199.                     col.setStyle('width',
  200.                         // I hate this
  201.                         parseInt(width, 10) -
  202.                         getCStyle('paddingLeft') -
  203.                         getCStyle('paddingRight') -
  204.                         getCStyle('borderLeftWidth') -
  205.                         getCStyle('borderRightWidth') + 'px');

  206.                 }
  207.             }
  208.         }
  209.     },

  210.     /**
  211.     Populates the table's `<colgroup>` with a `<col>` per item in the `columns`
  212.     attribute without children.  It is assumed that these are the columns that
  213.     have data cells renderered for them.

  214.     @method _uiSetColumnWidths
  215.     @protected
  216.     @since 3.5.0
  217.     **/
  218.     _uiSetColumnWidths: function () {
  219.         if (!this.view) {
  220.             return;
  221.         }

  222.         var template = this.COL_TEMPLATE,
  223.             colgroup = this._colgroupNode,
  224.             columns  = this._displayColumns,
  225.             i, len;

  226.         if (!colgroup) {
  227.             colgroup = this._colgroupNode = this._createColumnGroup();

  228.             this._tableNode.insertBefore(
  229.                 colgroup,
  230.                 this._tableNode.one('> thead, > tfoot, > tbody'));
  231.         } else {
  232.             colgroup.empty();
  233.         }

  234.         for (i = 0, len = columns.length; i < len; ++i) {

  235.             colgroup.append(template);

  236.             this._setColumnWidth(i, columns[i].width);
  237.         }
  238.     }
  239. }, true);

  240. Y.DataTable.ColumnWidths = ColumnWidths;

  241. Y.Base.mix(Y.DataTable, [ColumnWidths]);

  242.