datatable-scroll-debug.js revision 9f61355243edf6ed98ab0e2994fb132ffd47dd66
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav GlassYUI.add('datatable-scroll', function(Y) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith// TODO: split this into a plugin and a class extension to add the ATTRS (ala
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith// Plugin.addHostAttr()
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass/**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke SmithAdds the ability to make the table rows scrollable while preserving the header
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smithplacement.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke SmithThere are two types of scrolling, horizontal (x) and vertical (y). Horizontal
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smithscrolling is achieved by wrapping the entire table in a scrollable container.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke SmithVertical scrolling is achieved by splitting the table headers and data into two
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smithseparate tables, the latter of which is wrapped in a vertically scrolling
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smithcontainer. In this case, column widths of header cells and data cells are kept
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smithin sync programmatically.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke SmithSince the split table synchronization can be costly at runtime, the split is only done if the data in the table stretches beyond the configured `height` value.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke SmithTo activate or deactivate scrolling, set the `scrollable` attribute to one of
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smiththe following values:
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith * `false` - (default) Scrolling is disabled.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith * `true` or 'xy' - If `height` is set, vertical scrolling will be activated, if
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith `width` is set, horizontal scrolling will be activated.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith * 'x' - Activate horizontal scrolling only. Requires the `width` attribute is
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith also set.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith * 'y' - Activate vertical scrolling only. Requires the `height` attribute is
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith also set.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @module @datatable-scroll
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @class DataTable.Scrollable
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @for DataTable
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith**/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smithvar YLang = Y.Lang,
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith isString = YLang.isString,
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith isNumber = YLang.isNumber,
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith isArray = YLang.isArray,
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Scrollable;
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke SmithY.DataTable.Scrollable = Scrollable = function () {};
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke SmithScrollable.ATTRS = {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Activates or deactivates scrolling in the table. Acceptable values are:
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith * `false` - (default) Scrolling is disabled.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith * `true` or 'xy' - If `height` is set, vertical scrolling will be activated, if
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith `width` is set, horizontal scrolling will be activated.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith * 'x' - Activate horizontal scrolling only. Requires the `width` attribute is
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith also set.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith * 'y' - Activate vertical scrolling only. Requires the `height` attribute is
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith also set.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @attribute scrollable
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @type {String|Boolean}
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @value false
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrollable: {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith value: false,
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith setter: '_setScrollable'
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith }
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith};
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke SmithY.mix(Scrollable.prototype, {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith /**
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith Template for the `<table>` that is used to fix the caption in place when
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith the table is horizontally scrolling.
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith @property X_SCROLL_CAPTION_TABLE_TEMPLATE
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith @type {HTML}
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith @value '<table class="{className}"></table>'
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith **/
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith X_SCROLL_CAPTION_TABLE_TEMPLATE: '<table class="{className}"></table>',
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith /**
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith Template for the `<div>` that is used to contain the table when the table is
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith horizontally scrolling.
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith @property X_SCROLLER_TEMPLATE
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith @type {HTML}
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith @value '<div class="{className}"></div>'
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith **/
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith X_SCROLLER_TEMPLATE: '<div class="{className}"></div>',
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Template for the `<div>` that is used to contain the rows when the table is
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith vertically scrolling.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith @property Y_SCROLLER_TEMPLATE
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @type {HTML}
d56b1611c63d6a01384b52aac3d617c681679173Luke Smith @value '<div class="{className}"><table class="{tableClassName}"></table></div>'
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith Y_SCROLLER_TEMPLATE: '<div class="{className}"><table class="{tableClassName}"></table></div>',
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Scrolls a given row or cell into view if the table is scrolling. Pass the
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith `clientId` of a Model from the DataTable's `data` ModelList or its row
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith index to scroll to a row or a [row index, column index] array to scroll to
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith a cell. Alternately, to scroll to any element contained within the table's
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrolling areas, pass its ID, or the Node itself (though you could just as
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith well call `node.scrollIntoView()` yourself, but hey, whatever).
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method scrollTo
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @param {String|Number|Number[]|Node} id A row clientId, row index, cell
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith coordinate array, id string, or Node
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrollTo: function (id) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith var target;
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith if (id && this._tbodyNode && (this._yScrollNode || this._xScrollNode)) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith if (isArray(id)) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith target = this.getCell(id);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith } else if (isNumber(id)) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith target = this.getRow(id);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith } else if (isString(id)) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith target = this._tbodyNode.one('#' + id);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith } else if (id instanceof Y.Node &&
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // TODO: ancestor(yScrollNode, xScrollNode)
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith id.ancestor('.yui3-datatable') === this.get('boundingBox')) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith target = id;
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith }
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith target && target.scrollIntoView();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith //----------------------------------------------------------------------------
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // Protected properties and methods
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith //----------------------------------------------------------------------------
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Relays changes in the table structure or content to trigger a reflow of the
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrolling setup.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _afterContentChange
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @param {EventFacade} e The relevant change event (ignored)
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _afterContentChange: function (e) {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this._mergeXScrollContent();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._mergeYScrollContent();
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this._uiSetWidth(this.get('width'));
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._syncScrollUI();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Reacts to changes in the `scrollable` attribute by updating the `_xScroll`
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith and `_yScroll` properties and syncing the scrolling structure accordingly.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _afterScrollableChange
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @param {EventFacade} e The relevant change event (ignored)
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _afterScrollableChange: function (e) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._uiSetScrollable();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._syncScrollUI();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Syncs the scrolling structure if the table is configured to scroll vertically.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _afterScrollHeightChange
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @param {EventFacade} e The relevant change event (ignored)
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _afterScrollHeightChange: function (e) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._yScroll && this._syncScrollUI();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Attaches internal subscriptions to keep the scrolling structure up to date
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith with changes in the table's `data`, `columns`, `caption`, or `height`. The
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith `width` is taken care of already.
488020361dcc98fbcf160519fd817ec79a954673Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith This executes after the table's native `bindUI` method.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _bindScrollUI
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
488020361dcc98fbcf160519fd817ec79a954673Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _bindScrollUI: function () {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this.after([
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith 'dataChange',
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith 'columnsChange',
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith 'captionChange',
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith 'heightChange'],
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Y.bind('_afterContentChange', this));
488020361dcc98fbcf160519fd817ec79a954673Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this.data.after([
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith 'add', 'remove', 'reset', '*:change'],
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Y.bind('_afterContentChange', this));
488020361dcc98fbcf160519fd817ec79a954673Luke Smith },
488020361dcc98fbcf160519fd817ec79a954673Luke Smith
488020361dcc98fbcf160519fd817ec79a954673Luke Smith /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Calculates the height of the div containing the vertically scrolling rows.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith The height is produced by subtracting the `offsetHeight` of the scrolling
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith `<div>` from the `clientHeight` of the `contentBox`.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _calcScrollHeight
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _calcScrollHeight: function () {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith var scrollNode = this._yScrollNode;
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith return this.get('contentBox').get('clientHeight') -
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrollNode.get('offsetTop') -
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // To account for padding and borders of the scroll div
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrollNode.get('offsetHeight') +
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrollNode.get('clientHeight');
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith /**
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith Populates the `_xScrollNode` property by creating the `<div>` Node described
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith by the `X_SCROLLER_TEMPLATE`.
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith @method _createXScrollNode
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith @protected
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith **/
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith _createXScrollNode: function () {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith if (!this._xScrollNode) {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this._xScrollNode = Y.Node.create(
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith Y.Lang.sub(this.X_SCROLLER_TEMPLATE, {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith className: this.getClassName('x','scroller')
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith }));
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith }
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith },
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Populates the `_yScrollNode` property by creating the `<div>` Node described
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith by the `Y_SCROLLER_TEMPLATE`.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _createYScrollNode
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _createYScrollNode: function () {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith if (!this._yScrollNode) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._yScrollNode = Y.Node.create(
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith Y.Lang.sub(this.Y_SCROLLER_TEMPLATE, {
d56b1611c63d6a01384b52aac3d617c681679173Luke Smith className: this.getClassName('y','scroller'),
d56b1611c63d6a01384b52aac3d617c681679173Luke Smith tableClassName: this.getClassName('y', 'scroll', 'table')
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith }));
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Assigns style widths to all columns based on their current `offsetWidth`s.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith This faciliates creating a clone of the `<colgroup>` so column widths are
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith the same after the table is split in to header and data tables.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _fixColumnWidths
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _fixColumnWidths: function () {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith var tbody = this._tbodyNode,
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith table = tbody.get('parentNode'),
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith firstRow = tbody.one('tr'),
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith cells = firstRow && firstRow.all('td'),
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrollbar = Y.DOM.getScrollbarWidth(),
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith widths = [], i, len, cell;
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith if (cells) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // The thead and tbody need to be in the same table to accurately
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // calculate column widths.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._tableNode.appendChild(this._tbodyNode);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith i = cells.size() - 1;
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith cell = cells.item(i);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // FIXME? This may be fragile if the table has a fixed width and
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // increasing the size of the last column would push the overall
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // width beyond the configured width.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // bump up the width of the last column to account for the scrollbar.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._setColumnWidth(i,
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith (cell.get('offsetWidth') + scrollbar) + 'px');
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // Avoid assignment without scrollbar adjustment
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith cells.pop();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // Two passes so assigned widths don't cause subsequent width changes
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // which would cost reflows.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith widths = cells.get('offsetWidth');
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith for (i = 0, len = widths.length; i < len; ++i) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._setColumnWidth(i, widths[i] + 'px');
488020361dcc98fbcf160519fd817ec79a954673Luke Smith }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith table.appendChild(this._tbodyNode);
488020361dcc98fbcf160519fd817ec79a954673Luke Smith }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Sets up event handlers and AOP advice methods to bind the DataTable's natural
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith behaviors with the scrolling APIs and state.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method initializer
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @param {Object} config The config object passed to the constructor (ignored)
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith initializer: function () {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._setScrollProperties();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this.after(['scrollableChange', 'heightChange', 'widthChange'],
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._setScrollProperties);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Y.Do.after(this._bindScrollUI, this, 'bindUI');
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Y.Do.after(this._syncScrollUI, this, 'syncUI');
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith /**
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith Merges the caption and content tables back into one table if they are split.
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith @method _mergeXScrollContent
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith @protected
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith **/
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith _mergeXScrollContent: function () {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith var scrollNode = this._xScrollNode,
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith captionTable;
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this.get('boundingBox').removeClass(this.getClassName('scrollable', 'x'));
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith if (scrollNode) {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith if (this._captionNode) {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith captionTable = this._captionNode && this._captionNode.ancestor(
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith '.' + this.getClassName('caption', 'table'));
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this._tableNode.insertBefore(this._captionNode,
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this._tableNode.get('firstChild'));
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith if (captionTable) {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith captionTable.remove().destroy(true);
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith }
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith }
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith scrollNode.replace(scrollNode.get('childNodes').toFrag());
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this._xScrollNode = null;
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith }
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith },
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Merges the header and data tables back into one table if they are split.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _mergeYScrollContent
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _mergeYScrollContent: function () {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this.get('boundingBox').removeClass(this.getClassName('scrollable', 'y'));
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith if (this._yScrollNode) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._tableNode.append(this._tbodyNode);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._yScrollNode.remove().destroy(true);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._yScrollNode = null;
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._removeHeaderScrollPadding();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._setARIARoles();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._uiSetColumns();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Removes the additional padding added to the last cells in each header row to
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith allow the scrollbar to fit below.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _removeHeaderScrollPadding
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _removeHeaderScrollPadding: function () {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith var rows = this._theadNode.all('> tr').getDOMNodes(),
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith cell, i, len;
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // The last cell in all rows of the table headers
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith for (i = 0, len = rows.length; i < len; i += (cell.rowSpan || 1)) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith cell = Y.one(rows[i].cells[rows[i].cells.length - 1])
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith .setStyle('paddingRight', '');
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Moves the ARIA "grid" role from the table to the `contentBox` and adds the
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith "presentation" role to both header and data tables to support the two
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith tables reporting as one table for screen readers.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _setARIARoles
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _setARIARoles: function () {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith var contentBox = this.get('contentBox');
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith if (this._yScrollNode) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._tableNode.setAttribute('role', 'presentation');
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._yScrollNode.one('> table').setAttribute('role', 'presentation');
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith contentBox.setAttribute('role', 'grid');
488020361dcc98fbcf160519fd817ec79a954673Luke Smith } else {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._tableNode.setAttribute('role', 'grid');
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith contentBox.removeAttribute('role');
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Adds additional padding to the current amount of right padding on each row's
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith last cell to account for the width of the scrollbar below.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _setHeaderScrollPadding
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _setHeaderScrollPadding: function () {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith var rows = this._theadNode.all('> tr').getDOMNodes(),
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith padding, cell, i, len;
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith cell = Y.one(rows[0].cells[rows[0].cells.length - 1]);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith padding = (Y.DOM.getScrollbarWidth() +
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith parseInt(cell.getComputedStyle('paddingRight'), 10)) + 'px';
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // The last cell in all rows of the table headers
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith for (i = 0, len = rows.length; i < len; i += (cell.rowSpan || 1)) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith cell = Y.one(rows[i].cells[rows[i].cells.length - 1])
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith .setStyle('paddingRight', padding);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Accepts (case insensitive) values "x", "y", "xy", `true`, and `false`.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith `true` is translated to "xy" and upper case values are converted to lower
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith case. All other values are invalid.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _setScrollable
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @param {String|Boolea} val Incoming value for the `scrollable` attribute
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @return {String}
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _setScrollable: function (val) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith if (val === true) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith val = 'xy';
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith }
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith if (isString(val)) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith val = val.toLowerCase();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith return (val === false || val === 'y' || val === 'x' || val === 'xy') ?
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith val :
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Y.Attribute.INVALID_VALUE;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Assigns the `_xScroll` and `_yScroll` properties to true if an
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith appropriate value is set in the `scrollable` attribute and the `height`
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith and/or `width` is set.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _setScrollProperties
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _setScrollProperties: function () {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith var scrollable = this.get('scrollable') || '',
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith width = this.get('width'),
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith height = this.get('height');
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._xScroll = width && scrollable.indexOf('x') > -1;
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._yScroll = height && scrollable.indexOf('y') > -1;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Clones the fixed (see `_fixColumnWidths` method) `<colgroup>` for use by the
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith table in the vertical scrolling container. The last column's width is reduced
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith by the width of the scrollbar (which is offset by additional padding on the
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith last header cell(s) in the header table - see `_setHeaderScrollPadding`).
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _setYScrollColWidths
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _setYScrollColWidths: function () {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith var scrollNode = this._yScrollNode,
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith table = scrollNode && scrollNode.one('> table'),
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // hack to account for right border
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith colgroup, lastCol;
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith if (table) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrollNode.all('colgroup,col').remove();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith colgroup = this._colgroupNode.cloneNode(true);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith colgroup.set('id', Y.stamp(colgroup));
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // Browsers with proper support for column widths need the
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // scrollbar width subtracted from the last column.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith if (!Y.Features.test('table', 'badColWidth')) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith lastCol = colgroup.all('col').pop();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // Subtract the scrollbar width added to the last col
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith lastCol.setStyle('width',
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith (parseInt(lastCol.getStyle('width'), 10) - 1 -
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Y.DOM.getScrollbarWidth()) + 'px');
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith table.insertBefore(colgroup, table.one('> thead, > tfoot, > tbody'));
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith /**
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith Splits the data table from its caption if it has one and wraps the table in
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith a horizontally scrollable container `<div>`.
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith @method _splitXScrollContent
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith @protected
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith **/
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith _splitXScrollContent: function () {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith var captionTable;
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this._createXScrollNode();
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this._tableNode.wrap(this._xScrollNode);
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith if (this._yScrollNode) {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this._xScrollNode.append(this._yScrollNode);
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith }
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith if (this._captionNode) {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith captionTable = Y.Node.create(
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith // TODO: Please someone give this a shorter name!
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith Y.Lang.sub(this.X_SCROLL_CAPTION_TABLE_TEMPLATE, {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith className: this.getClassName('caption', 'table')
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith }));
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith captionTable.setStyle('width', this.get('width'));
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith captionTable.insertBefore(this._captionNode,
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith captionTable.get('firstChild'));
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this.get('contentBox').insertBefore(captionTable, this._xScrollNode);
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith }
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith },
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Splits the unified table with headers and data into two tables, the latter
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith contained within a vertically scrollable container `<div>`.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _splitYScrollContent
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _splitYScrollContent: function () {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith var table = this._tableNode,
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrollNode = this._yScrollTable,
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrollbar = Y.DOM.getScrollbarWidth(),
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrollTable, width;
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this.get('boundingBox').addClass(this.getClassName('scrollable','y'));
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith if (!scrollNode) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // I don't want to take into account the added paddingRight done in
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // _setHeaderScrollPadding for the data cells that will be
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // scrolling below
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._fixColumnWidths();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._setHeaderScrollPadding();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // lock the header table width in case the removal of the tbody would
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // allow the table to shrink (such as when the tbody data causes a
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // browser horizontal scrollbar).
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith width = parseInt(table.getComputedStyle('width'), 10);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith table.setStyle('width', width + 'px');
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._createYScrollNode();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrollNode = this._yScrollNode;
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrollTable = scrollNode.one('table');
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrollTable.append(this._tbodyNode);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith table.insert(scrollNode, 'after');
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith scrollNode.setStyles({
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith height: this._calcScrollHeight() + 'px',
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // FIXME: Lazy hack to account for scroll node borders
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith width : (width - 2) + 'px'
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith });
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
d56b1611c63d6a01384b52aac3d617c681679173Luke Smith scrollTable.setStyle('width', scrollNode.get('clientWidth') + 'px');
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._setARIARoles();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._setYScrollColWidths();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith Splits or merges the table for X and Y scrolling depending on the current
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith widget state. If the table needs to be split, but is already, does nothing.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _syncScrollUI
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _syncScrollUI: function () {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith var cBox = this.get('contentBox'),
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith node = this._yScrollNode || cBox,
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith table = node.one('table');
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._uiSetScrollable();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith if (this._yScroll) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // Only split the table if the content is longer than the height
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith if (table.get('scrollHeight') > node.get('clientHeight')) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._splitYScrollContent();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith } else {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._mergeYScrollContent();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith }
488020361dcc98fbcf160519fd817ec79a954673Luke Smith } else {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._mergeYScrollContent();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith if (this._xScroll) {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith // Only split the table if the content is longer than the height
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith if (table.get('scrollWidth') > node.get('clientWidth')) {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this._splitXScrollContent();
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith } else {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this._mergeXScrollContent();
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith }
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith } else {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this._mergeXScrollContent();
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith }
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // TODO: fix X scroll. I'll need to split tables here as well for the
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // caption if there is one present, so the horizontal scroll happens
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // under the stationary caption.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // Also, similarly, only activate the x scrolling if the table is wider
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // than the configured width.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Overrides the default Widget `_uiSetWidth` to assign the width to either
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith the table or the `contentBox` (for horizontal scrolling) in addition to the
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith native behavior of setting the width of the `boundingBox`.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _uiSetWidth
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @param {String|Number} width CSS width value or number of pixels
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _uiSetWidth: function (width) {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith var scrollable = this._xScrollNode || this._yScrollNode;
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith if (isNumber(width)) {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith width += this.DEF_UNIT;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._uiSetDim('width', width);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._tableNode.setStyle('width', scrollable ? '' : width);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith if (scrollable) {
9f61355243edf6ed98ab0e2994fb132ffd47dd66Luke Smith this._mergeXScrollContent();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._mergeYScrollContent();
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this._syncScrollUI();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Assigns the appropriate class to the `boundingBox` to identify the DataTable
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith as horizontally scrolling, vertically scrolling, or both (adds both classes).
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Classes added are "yui3-datatable-scrollable-x" or "...-y"
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @method _uiSetScrollable
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith _uiSetScrollable: function () {
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // Initially add classes. These may be purged by _syncScrollUI.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith this.get('boundingBox')
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith .toggleClass(this.getClassName('scrollable','x'), this._xScroll)
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith .toggleClass(this.getClassName('scrollable','y'), this._yScroll);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Indicates horizontal table scrolling is enabled.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @property _xScroll
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @type {Boolean}
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @default undefined (not initially set)
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @private
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith //_xScroll,
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Indicates vertical table scrolling is enabled.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @property _yScroll
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @type {Boolean}
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @default undefined (not initially set)
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @private
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith //_yScroll,
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith /**
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith Overflow Node used to contain the data rows in a vertically scrolling table.
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @property _yScrollNode
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @type {Node}
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @default undefined (not initially set)
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith @protected
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith **/
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith //_yScrollNode
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith // TODO: Add _xScrollNode
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith}, true);
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke SmithY.Base.mix(Y.DataTable, [Scrollable]);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
820d7f2eab2a78412c9803335bb10a2974e7fbf5Luke Smith}, '@VERSION@' ,{skinnable:true, requires:['datatable-base', 'dom-screen']});