4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith/**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithAdds the ability to make the table rows scrollable while preserving the header
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smithplacement.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith@module datatable-scroll
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith@for DataTable
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith@since 3.5.0
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith**/
53c97f474022b2633bdeccab063f518c4015f27aLuke Smithvar YLang = Y.Lang,
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith isString = YLang.isString,
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith isNumber = YLang.isNumber,
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith isArray = YLang.isArray,
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith Scrollable;
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith// Returns the numeric value portion of the computed style, defaulting to 0
53c97f474022b2633bdeccab063f518c4015f27aLuke Smithfunction styleDim(node, style) {
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith return parseInt(node.getComputedStyle(style), 10) | 0;
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith}
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith/**
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith_API docs for this extension are included in the DataTable class._
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith
53c97f474022b2633bdeccab063f518c4015f27aLuke SmithAdds the ability to make the table rows scrollable while preserving the header
53c97f474022b2633bdeccab063f518c4015f27aLuke Smithplacement.
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith
53c97f474022b2633bdeccab063f518c4015f27aLuke SmithThere are two types of scrolling, horizontal (x) and vertical (y). Horizontal
53c97f474022b2633bdeccab063f518c4015f27aLuke Smithscrolling is achieved by wrapping the entire table in a scrollable container.
53c97f474022b2633bdeccab063f518c4015f27aLuke SmithVertical scrolling is achieved by splitting the table headers and data into two
53c97f474022b2633bdeccab063f518c4015f27aLuke Smithseparate tables, the latter of which is wrapped in a vertically scrolling
53c97f474022b2633bdeccab063f518c4015f27aLuke Smithcontainer. In this case, column widths of header cells and data cells are kept
53c97f474022b2633bdeccab063f518c4015f27aLuke Smithin sync programmatically.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke 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.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithTo activate or deactivate scrolling, set the `scrollable` attribute to one of
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smiththe following values:
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * `false` - (default) Scrolling is disabled.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * `true` or 'xy' - If `height` is set, vertical scrolling will be activated, if
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith `width` is set, horizontal scrolling will be activated.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * 'x' - Activate horizontal scrolling only. Requires the `width` attribute is
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith also set.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * 'y' - Activate vertical scrolling only. Requires the `height` attribute is
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith also set.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith@class DataTable.Scrollable
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith@for DataTable
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith@since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith**/
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithY.DataTable.Scrollable = Scrollable = function () {};
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithScrollable.ATTRS = {
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith /**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Activates or deactivates scrolling in the table. Acceptable values are:
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * `false` - (default) Scrolling is disabled.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * `true` or 'xy' - If `height` is set, vertical scrolling will be
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith activated, if `width` is set, horizontal scrolling will be activated.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * 'x' - Activate horizontal scrolling only. Requires the `width` attribute
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith is also set.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * 'y' - Activate vertical scrolling only. Requires the `height` attribute
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith is also set.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @attribute scrollable
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @type {String|Boolean}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @value false
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith **/
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith scrollable: {
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith value: false,
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith setter: '_setScrollable'
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith }
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith};
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithY.mix(Scrollable.prototype, {
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith /**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Scrolls a given row or cell into view if the table is scrolling. Pass the
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith `clientId` of a Model from the DataTable's `data` ModelList or its row
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith index to scroll to a row or a [row index, column index] array to scroll to
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith a cell. Alternately, to scroll to any element contained within the table's
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith scrolling areas, pass its ID, or the Node itself (though you could just as
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith well call `node.scrollIntoView()` yourself, but hey, whatever).
0dd0e79d3ecf5e1dcfd4748537e50c65f757429eLuke Smith
0dd0e79d3ecf5e1dcfd4748537e50c65f757429eLuke Smith @method scrollTo
0dd0e79d3ecf5e1dcfd4748537e50c65f757429eLuke Smith @param {String|Number|Number[]|Node} id A row clientId, row index, cell
0dd0e79d3ecf5e1dcfd4748537e50c65f757429eLuke Smith coordinate array, id string, or Node
0dd0e79d3ecf5e1dcfd4748537e50c65f757429eLuke Smith @return {DataTable}
0dd0e79d3ecf5e1dcfd4748537e50c65f757429eLuke Smith @chainable
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith **/
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith scrollTo: function (id) {
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith var target;
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith if (id && this._tbodyNode && (this._yScrollNode || this._xScrollNode)) {
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith if (isArray(id)) {
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith target = this.getCell(id);
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith } else if (isNumber(id)) {
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith target = this.getRow(id);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith } else if (isString(id)) {
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith target = this._tbodyNode.one('#' + id);
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith } else if (id instanceof Y.Node &&
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith // TODO: ancestor(yScrollNode, xScrollNode)
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith id.ancestor('.yui3-datatable') === this.get('boundingBox')) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith target = id;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith target && target.scrollIntoView();
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith }
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith return this;
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith },
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith //--------------------------------------------------------------------------
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith // Protected properties and methods
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith //--------------------------------------------------------------------------
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith /**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Template for the `<table>` that is used to fix the caption in place when
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith the table is horizontally scrolling.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @property _CAPTION_TABLE_TEMPLATE
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @type {HTML}
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith @value '<table class="{className}" role="presentation"></table>'
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @protected
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _CAPTION_TABLE_TEMPLATE: '<table class="{className}" role="presentation"></table>',
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith /**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Template used to create sizable element liners around header content to
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith synchronize fixed header column widths.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @property _SCROLL_LINER_TEMPLATE
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @type {HTML}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @value '<div class="{className}"></div>'
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @protected
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith **/
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith _SCROLL_LINER_TEMPLATE: '<div class="{className}"></div>',
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith /**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Template for the virtual scrollbar needed in "y" and "xy" scrolling setups.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @property _SCROLLBAR_TEMPLATE
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @type {HTML}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @value '<div class="{className}"><div></div></div>'
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @protected
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith **/
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith _SCROLLBAR_TEMPLATE: '<div class="{className}"><div></div></div>',
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith /**
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith Template for the `<div>` that is used to contain the table when the table is
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith horizontally scrolling.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @property _X_SCROLLER_TEMPLATE
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @type {HTML}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @value '<div class="{className}"></div>'
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @protected
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith **/
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith _X_SCROLLER_TEMPLATE: '<div class="{className}"></div>',
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith /**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Template for the `<table>` used to contain the fixed column headers for
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith vertically scrolling tables.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @property _Y_SCROLL_HEADER_TEMPLATE
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @type {HTML}
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @value '<table cellspacing="0" role="presentation" aria-hidden="true" class="{className}"></table>'
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @protected
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith **/
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith _Y_SCROLL_HEADER_TEMPLATE: '<table cellspacing="0" aria-hidden="true" class="{className}"></table>',
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith /**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Template for the `<div>` that is used to contain the rows when the table is
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith vertically scrolling.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @property _Y_SCROLLER_TEMPLATE
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @type {HTML}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @value '<div class="{className}"><div class="{scrollerClassName}"></div></div>'
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @protected
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith **/
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith _Y_SCROLLER_TEMPLATE: '<div class="{className}"><div class="{scrollerClassName}"></div></div>',
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith /**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Adds padding to the last cells in the fixed header for vertically scrolling
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith tables. This padding is equal in width to the scrollbar, so can't be
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith relegated to a stylesheet.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _addScrollbarPadding
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @protected
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith **/
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith _addScrollbarPadding: function () {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith var fixedHeader = this._yScrollHeader,
0c11eb686fb26ed5ccb04d1beb4e91952fce0bcbLuke Smith headerClass = '.' + this.getClassName('header'),
0c11eb686fb26ed5ccb04d1beb4e91952fce0bcbLuke Smith scrollbarWidth, rows, header, i, len;
0c11eb686fb26ed5ccb04d1beb4e91952fce0bcbLuke Smith
0c11eb686fb26ed5ccb04d1beb4e91952fce0bcbLuke Smith if (fixedHeader) {
0c11eb686fb26ed5ccb04d1beb4e91952fce0bcbLuke Smith scrollbarWidth = Y.DOM.getScrollbarWidth() + 'px';
0c11eb686fb26ed5ccb04d1beb4e91952fce0bcbLuke Smith rows = fixedHeader.all('tr');
0c11eb686fb26ed5ccb04d1beb4e91952fce0bcbLuke Smith
0c11eb686fb26ed5ccb04d1beb4e91952fce0bcbLuke Smith for (i = 0, len = rows.size(); i < len; i += +header.get('rowSpan')) {
0c11eb686fb26ed5ccb04d1beb4e91952fce0bcbLuke Smith header = rows.item(i).all(headerClass).pop();
0c11eb686fb26ed5ccb04d1beb4e91952fce0bcbLuke Smith header.setStyle('paddingRight', scrollbarWidth);
0c11eb686fb26ed5ccb04d1beb4e91952fce0bcbLuke Smith }
0c11eb686fb26ed5ccb04d1beb4e91952fce0bcbLuke Smith }
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith },
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith /**
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith Reacts to changes in the `scrollable` attribute by updating the `_xScroll`
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith and `_yScroll` properties and syncing the scrolling structure accordingly.
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith @method _afterScrollableChange
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith @param {EventFacade} e The relevant change event (ignored)
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith @protected
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith @since 3.5.0
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith **/
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith _afterScrollableChange: function (e) {
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith var scroller = this._xScrollNode;
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith if (this._xScroll && scroller) {
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith if (this._yScroll && !this._yScrollNode) {
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith scroller.setStyle('paddingRight',
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Y.DOM.getScrollbarWidth() + 'px');
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith } else if (!this._yScroll && this._yScrollNode) {
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith scroller.setStyle('paddingRight', '');
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith }
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith }
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith this._syncScrollUI();
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith },
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith /**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Reacts to changes in the `caption` attribute by adding, removing, or
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith syncing the caption table when the table is set to scroll.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _afterScrollCaptionChange
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @param {EventFacade} e The relevant change event (ignored)
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @protected
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith **/
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith _afterScrollCaptionChange: function (e) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (this._xScroll || this._yScroll) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith this._syncScrollUI();
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith },
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith /**
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith Reacts to changes in the `columns` attribute of vertically scrolling tables
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith by refreshing the fixed headers, scroll container, and virtual scrollbar
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith position.
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @method _afterScrollColumnsChange
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @param {EventFacade} e The relevant change event (ignored)
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @protected
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @since 3.5.0
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith **/
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith _afterScrollColumnsChange: function (e) {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith if (this._xScroll || this._yScroll) {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith if (this._yScroll && this._yScrollHeader) {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith this._syncScrollHeaders();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith this._syncScrollUI();
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith },
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith /**
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Reacts to changes in vertically scrolling table's `data` ModelList by
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith synchronizing the fixed column header widths and virtual scrollbar height.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _afterScrollDataChange
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @param {EventFacade} e The relevant change event (ignored)
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @protected
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @since 3.5.0
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _afterScrollDataChange: function (e) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith if (this._xScroll || this._yScroll) {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith this._syncScrollUI();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith },
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith /**
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith Reacts to changes in the `height` attribute of vertically scrolling tables
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith by updating the height of the `<div>` wrapping the data table and the
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith virtual scrollbar. If `scrollable` was set to "y" or "xy" but lacking a
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith declared `height` until the received change, `_syncScrollUI` is called to
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith create the fixed headers etc.
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith @method _afterScrollHeightChange
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith @param {EventFacade} e The relevant change event (ignored)
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith @protected
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith @since 3.5.0
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith **/
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith _afterScrollHeightChange: function (e) {
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith if (this._yScroll) {
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith this._syncScrollUI();
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith }
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith },
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith /* (not an API doc comment on purpose)
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith Reacts to the sort event (if the table is also sortable) by updating the
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith fixed header classes to match the data table's headers.
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith THIS IS A HACK that will be removed immediately after the 3.5.0 release.
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith If you're reading this and the current version is greater than 3.5.0, I
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith should be publicly scolded.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith */
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith _afterScrollSort: function (e) {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith var headers, headerClass;
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith if (this._yScroll && this._yScrollHeader) {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith headerClass = '.' + this.getClassName('header');
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith headers = this._theadNode.all(headerClass);
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith this._yScrollHeader.all(headerClass).each(function (header, i) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith header.set('className', headers.item(i).get('className'));
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith });
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith /**
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith Reacts to changes in the width of scrolling tables by expanding the width of
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith the `<div>` wrapping the data table for horizontally scrolling tables or
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith upding the position of the virtual scrollbar for vertically scrolling
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith tables.
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith @method _afterScrollWidthChange
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {EventFacade} e The relevant change event (ignored)
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith @protected
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith @since 3.5.0
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith _afterScrollWidthChange: function (e) {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith if (this._xScroll || this._yScroll) {
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith this._syncScrollUI();
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith },
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith /**
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith Binds virtual scrollbar interaction to the `_yScrollNode`'s `scrollTop` and
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith vice versa.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @method _bindScrollbar
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @protected
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith _bindScrollbar: function () {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith var scrollbar = this._scrollbarNode,
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith scroller = this._yScrollNode;
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith if (scrollbar && scroller && !this._scrollbarEventHandle) {
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith this._scrollbarEventHandle = new Y.Event.Handle([
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith scrollbar.on('scroll', this._syncScrollPosition, this, 'virtual'),
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith scroller.on('scroll', this._syncScrollPosition, this)
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith ]);
8a6a44314c3b8b5125191793d3f3e0baa8d31b7cLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
adad741345a668146507029dd5fe56905b10abdeLuke Smith /**
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Binds to the window resize event to update the vertical scrolling table
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith headers and wrapper `<div>` dimensions.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _bindScrollResize
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @since 3.5.0
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith _bindScrollResize: function () {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith if (!this._scrollResizeHandle) {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // TODO: sync header widths and scrollbar position. If the height
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // of the headers has changed, update the scrollbar dims as well.
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith this._scrollResizeHandle = Y.on('resize',
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith this._syncScrollUI, null, this);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith },
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Attaches internal subscriptions to keep the scrolling structure up to date
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith with changes in the table's `data`, `columns`, `caption`, or `height`. The
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith `width` is taken care of already.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith This executes after the table's native `bindUI` method.
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _bindScrollUI
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @protected
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @since 3.5.0
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith **/
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith _bindScrollUI: function () {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this.after({
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith columnsChange: Y.bind('_afterScrollColumnsChange', this),
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith heightChange : Y.bind('_afterScrollHeightChange', this),
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith widthChange : Y.bind('_afterScrollWidthChange', this),
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith captionChange: Y.bind('_afterScrollCaptionChange', this),
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith scrollableChange: Y.bind('_afterScrollableChange', this),
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // FIXME: this is a last minute hack to work around the fact that
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // DT doesn't use a tableView to render table content that can be
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // replaced with a scrolling table view. This must be removed asap!
55e462437cab83f4f545bfd864f3296cd2a0e806Luke Smith sort : Y.bind('_afterScrollSort', this)
55e462437cab83f4f545bfd864f3296cd2a0e806Luke Smith });
55e462437cab83f4f545bfd864f3296cd2a0e806Luke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith this.after(['dataChange', '*:add', '*:remove', '*:reset', '*:change'],
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Y.bind('_afterScrollDataChange', this));
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith },
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Clears the lock and timer used to manage synchronizing the scroll position
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith between the vertical scroll container and the virtual scrollbar.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _clearScrollLock
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @since 3.5.0
55e462437cab83f4f545bfd864f3296cd2a0e806Luke Smith **/
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith _clearScrollLock: function () {
55e462437cab83f4f545bfd864f3296cd2a0e806Luke Smith if (this._scrollLock) {
55e462437cab83f4f545bfd864f3296cd2a0e806Luke Smith this._scrollLock.cancel();
55e462437cab83f4f545bfd864f3296cd2a0e806Luke Smith delete this._scrollLock;
55e462437cab83f4f545bfd864f3296cd2a0e806Luke Smith }
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith },
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith /**
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Creates a virtual scrollbar from the `_SCROLLBAR_TEMPLATE`, assigning it to
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith the `_scrollbarNode` property.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @method _createScrollbar
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @return {Node} The created Node
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @protected
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @since 3.5.0
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith **/
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith _createScrollbar: function () {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith var scrollbar = this._scrollbarNode;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (!scrollbar) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith scrollbar = this._scrollbarNode = Y.Node.create(
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Y.Lang.sub(this._SCROLLBAR_TEMPLATE, {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith className: this.getClassName('scrollbar')
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }));
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // IE 6-10 require the scrolled area to be visible (at least 1px)
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // or they don't respond to clicking on the scrollbar rail or arrows
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith scrollbar.setStyle('width', (Y.DOM.getScrollbarWidth() + 1) + 'px');
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith return scrollbar;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith },
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Creates a separate table to contain the caption when the table is
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith configured to scroll vertically or horizontally.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _createScrollCaptionTable
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith @return {Node} The created Node
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _createScrollCaptionTable: function () {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith if (!this._captionTable) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._captionTable = Y.Node.create(
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Y.Lang.sub(this._CAPTION_TABLE_TEMPLATE, {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith className: this.getClassName('caption', 'table')
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }));
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith this._captionTable.empty();
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith return this._captionTable;
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith },
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith /**
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith Populates the `_xScrollNode` property by creating the `<div>` Node described
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith by the `_X_SCROLLER_TEMPLATE`.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _createXScrollNode
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @return {Node} The created Node
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @protected
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _createXScrollNode: function () {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith if (!this._xScrollNode) {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith this._xScrollNode = Y.Node.create(
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Y.Lang.sub(this._X_SCROLLER_TEMPLATE, {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith className: this.getClassName('x','scroller')
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith }));
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith }
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith return this._xScrollNode;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith /**
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith Populates the `_yScrollHeader` property by creating the `<table>` Node
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith described by the `_Y_SCROLL_HEADER_TEMPLATE`.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _createYScrollHeader
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @return {Node} The created Node
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @protected
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _createYScrollHeader: function () {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith var fixedHeader = this._yScrollHeader;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (!fixedHeader) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith fixedHeader = this._yScrollHeader = Y.Node.create(
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith Y.Lang.sub(this._Y_SCROLL_HEADER_TEMPLATE, {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith className: this.getClassName('scroll','columns')
0dd0e79d3ecf5e1dcfd4748537e50c65f757429eLuke Smith }));
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith return fixedHeader;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith /**
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith Populates the `_yScrollNode` property by creating the `<div>` Node described
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith by the `_Y_SCROLLER_TEMPLATE`.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _createYScrollNode
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @return {Node} The created Node
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _createYScrollNode: function () {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith var scrollerClass;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith if (!this._yScrollNode) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith scrollerClass = this.getClassName('y', 'scroller');
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._yScrollContainer = Y.Node.create(
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith Y.Lang.sub(this._Y_SCROLLER_TEMPLATE, {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith className: this.getClassName('y','scroller','container'),
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith scrollerClassName: scrollerClass
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith }));
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith this._yScrollNode = this._yScrollContainer
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith .one('.' + scrollerClass);
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith }
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith return this._yScrollContainer;
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith },
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith /**
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith Removes the nodes used to create horizontal and vertical scrolling and
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith rejoins the caption to the main table if needed.
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _disableScrolling
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @since 3.5.0
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith _disableScrolling: function () {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith this._removeScrollCaptionTable();
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith this._disableXScrolling();
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith this._disableYScrolling();
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith this._unbindScrollResize();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
8a6a44314c3b8b5125191793d3f3e0baa8d31b7cLuke Smith this._uiSetWidth(this.get('width'));
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith },
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith /**
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith Removes the nodes used to allow horizontal scrolling.
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @method _disableXScrolling
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @protected
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith **/
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith _disableXScrolling: function () {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith this._removeXScrollNode();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
8a6a44314c3b8b5125191793d3f3e0baa8d31b7cLuke Smith
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith /**
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith Removes the nodes used to allow vertical scrolling.
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @method _disableYScrolling
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @protected
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @since 3.5.0
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith **/
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith _disableYScrolling: function () {
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith this._removeYScrollHeader();
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith this._removeYScrollNode();
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith this._removeYScrollContainer();
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith this._removeScrollbar();
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith },
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith /**
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith Cleans up external event subscriptions.
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @method destructor
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @protected
8a6a44314c3b8b5125191793d3f3e0baa8d31b7cLuke Smith @since 3.5.0
8a6a44314c3b8b5125191793d3f3e0baa8d31b7cLuke Smith **/
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith destructor: function () {
8a6a44314c3b8b5125191793d3f3e0baa8d31b7cLuke Smith this._unbindScrollbar();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._unbindScrollResize();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._clearScrollLock();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Sets up event handlers and AOP advice methods to bind the DataTable's natural
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith behaviors with the scrolling APIs and state.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method initializer
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith @param {Object} config The config object passed to the constructor (ignored)
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith initializer: function () {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._setScrollProperties();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this.after(['scrollableChange', 'heightChange', 'widthChange'],
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._setScrollProperties);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith Y.Do.after(this._bindScrollUI, this, 'bindUI');
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith Y.Do.after(this._syncScrollUI, this, 'syncUI');
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith /**
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith Removes the table used to house the caption when the table is scrolling.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _removeScrollCaptionTable
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _removeScrollCaptionTable: function () {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith if (this._captionTable) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith if (this._captionNode) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._tableNode.prepend(this._captionNode);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._captionTable.remove().destroy(true);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith delete this._captionTable;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith /**
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith Removes the `<div>` wrapper used to contain the data table when the table
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith is horizontally scrolling.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _removeXScrollNode
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @since 3.5.0
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith _removeXScrollNode: function () {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith var scroller = this._xScrollNode;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith if (scroller) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith scroller.replace(scroller.get('childNodes').toFrag());
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith scroller.remove().destroy(true);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith delete this._xScrollNode;
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith }
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith },
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Removes the `<div>` wrapper used to contain the data table and fixed header
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith when the table is vertically scrolling.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith @method _removeYScrollContainer
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @since 3.5.0
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith **/
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith _removeYScrollContainer: function () {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith var scroller = this._yScrollContainer;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (scroller) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith scroller.replace(scroller.get('childNodes').toFrag());
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith scroller.remove().destroy(true);
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith delete this._yScrollContainer;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith },
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith /**
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Removes the `<table>` used to contain the fixed column headers when the
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith table is vertically scrolling.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @method _removeYScrollHeader
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @protected
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @since 3.5.0
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith **/
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith _removeYScrollHeader: function () {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (this._yScrollHeader) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith this._yScrollHeader.remove().destroy(true);
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith delete this._yScrollHeader;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith },
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith /**
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Removes the `<div>` wrapper used to contain the data table when the table
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith is vertically scrolling.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @method _removeYScrollNode
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @protected
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @since 3.5.0
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith **/
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith _removeYScrollNode: function () {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith var scroller = this._yScrollNode;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (scroller) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith scroller.replace(scroller.get('childNodes').toFrag());
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith scroller.remove().destroy(true);
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith delete this._yScrollNode;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith },
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith /**
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Removes the virtual scrollbar used by scrolling tables.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @method _removeScrollbar
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @protected
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @since 3.5.0
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith **/
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith _removeScrollbar: function () {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (this._scrollbarNode) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith this._scrollbarNode.remove().destroy(true);
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith delete this._scrollbarNode;
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith }
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith if (this._scrollbarEventHandle) {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith this._scrollbarEventHandle.detach();
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith delete this._scrollbarEventHandle;
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith }
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith },
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Accepts (case insensitive) values "x", "y", "xy", `true`, and `false`.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith `true` is translated to "xy" and upper case values are converted to lower
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith case. All other values are invalid.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _setScrollable
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {String|Boolea} val Incoming value for the `scrollable` attribute
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @return {String}
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @since 3.5.0
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith **/
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith _setScrollable: function (val) {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith if (val === true) {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith val = 'xy';
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith }
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith if (isString(val)) {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith val = val.toLowerCase();
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith }
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith return (val === false || val === 'y' || val === 'x' || val === 'xy') ?
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith val :
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith Y.Attribute.INVALID_VALUE;
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith },
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith /**
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Assigns the `_xScroll` and `_yScroll` properties to true if an
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith appropriate value is set in the `scrollable` attribute and the `height`
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith and/or `width` is set.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _setScrollProperties
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @since 3.5.0
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith _setScrollProperties: function () {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith var scrollable = this.get('scrollable') || '',
55e462437cab83f4f545bfd864f3296cd2a0e806Luke Smith width = this.get('width'),
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith height = this.get('height');
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith this._xScroll = width && scrollable.indexOf('x') > -1;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._yScroll = height && scrollable.indexOf('y') > -1;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith },
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith /**
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Keeps the virtual scrollbar and the scrolling `<div>` wrapper around the
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith data table in vertically scrolling tables in sync.
7a40ce4f121af8aa648db1d17f5b09be0b55df4bLuke Smith
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @method _syncScrollPosition
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith @param {DOMEventFacade} e The scroll event
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @param {String} [source] The string "virtual" if the event originated from
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith the virtual scrollbar
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @protected
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @since 3.5.0
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith **/
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith _syncScrollPosition: function (e, source) {
b2c3f7ee9595487fa2c245134423177b4421db5dLuke Smith var scrollbar = this._scrollbarNode,
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith scroller = this._yScrollNode;
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (scrollbar && scroller) {
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith if (this._scrollLock && this._scrollLock.source !== source) {
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith return;
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith }
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith this._clearScrollLock();
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith this._scrollLock = Y.later(300, this, this._clearScrollLock);
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith this._scrollLock.source = source;
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith if (source === 'virtual') {
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith scroller.set('scrollTop', scrollbar.get('scrollTop'));
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith } else {
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith scrollbar.set('scrollTop', scroller.get('scrollTop'));
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith }
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith }
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith },
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith /**
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith Splits the caption from the data `<table>` if the table is configured to
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith scroll. If not, rejoins the caption to the data `<table>` if it needs to
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith be.
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @method _syncScrollCaptionUI
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @protected
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @since 3.5.0
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith **/
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith _syncScrollCaptionUI: function () {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith var caption = this._captionNode,
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith table = this._tableNode,
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith captionTable = this._captionTable,
b2c3f7ee9595487fa2c245134423177b4421db5dLuke Smith id;
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (caption) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith id = caption.getAttribute('id');
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith if (!captionTable) {
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith captionTable = this._createScrollCaptionTable();
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith this.get('contentBox').prepend(captionTable);
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith if (!caption.get('parentNode').compareTo(captionTable)) {
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith captionTable.empty().insert(caption);
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith if (!id) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith id = Y.stamp(caption);
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith caption.setAttribute('id', id);
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith }
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith table.setAttribute('aria-describedby', id);
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith }
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith } else if (captionTable) {
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith this._removeScrollCaptionTable();
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith }
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith },
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith /**
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith Assigns widths to the fixed header columns to match the columns in the data
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith table.
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith @method _syncScrollColumnWidths
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith @protected
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith @since 3.5.0
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith **/
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith _syncScrollColumnWidths: function () {
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith var widths = [];
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith if (this._theadNode && this._yScrollHeader) {
b2c3f7ee9595487fa2c245134423177b4421db5dLuke Smith // Capture dims and assign widths in two passes to avoid reflows for
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // each access of clientWidth/getComputedStyle
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith this._theadNode.all('.' + this.getClassName('header'))
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith .each(function (header) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith widths.push(
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // FIXME: IE returns the col.style.width from
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // getComputedStyle even if the column has been
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // compressed below that width, so it must use
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // clientWidth. FF requires getComputedStyle because it
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // uses fractional widths that round up to an overall
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // cell/table width 1px greater than the data table's
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // cell/table width, resulting in misaligned columns or
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith // fixed header bleed through. I can't think of a
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // *reasonable* way to capture the correct width without
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // a sniff. Math.min(cW - p, getCS(w)) was imperfect
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // and punished all browsers, anyway.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith (Y.UA.ie && Y.UA.ie < 8) ?
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith (header.get('clientWidth') -
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith styleDim(header, 'paddingLeft') -
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith styleDim(header, 'paddingRight')) + 'px' :
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith header.getComputedStyle('width'));
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith });
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith this._yScrollHeader.all('.' + this.getClassName('scroll', 'liner'))
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith .each(function (liner, i) {
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith liner.setStyle('width', widths[i]);
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith });
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith },
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith /**
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Creates matching headers in the fixed header table for vertically scrolling
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith tables and synchronizes the column widths.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _syncScrollHeaders
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @protected
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _syncScrollHeaders: function () {
var fixedHeader = this._yScrollHeader,
linerTemplate = this._SCROLL_LINER_TEMPLATE,
linerClass = this.getClassName('scroll', 'liner'),
headerClass = this.getClassName('header'),
headers = this._theadNode.all('.' + headerClass);
if (this._theadNode && fixedHeader) {
fixedHeader.empty().appendChild(
this._theadNode.cloneNode(true));
// Prevent duplicate IDs and assign ARIA attributes to hide
// from screen readers
fixedHeader.all('[id]').removeAttribute('id');
fixedHeader.all('.' + headerClass).each(function (header, i) {
var liner = Y.Node.create(Y.Lang.sub(linerTemplate, {
className: linerClass
})),
refHeader = headers.item(i);
// Can't assign via skin css because sort (and potentially
// others) might override the padding values.
liner.setStyle('padding',
refHeader.getComputedStyle('paddingTop') + ' ' +
refHeader.getComputedStyle('paddingRight') + ' ' +
refHeader.getComputedStyle('paddingBottom') + ' ' +
refHeader.getComputedStyle('paddingLeft'));
liner.appendChild(header.get('childNodes').toFrag());
header.appendChild(liner);
}, this);
this._syncScrollColumnWidths();
this._addScrollbarPadding();
}
},
/**
Wraps the table for X and Y scrolling, if necessary, if the `scrollable`
attribute is set. Synchronizes dimensions and DOM placement of all
scrolling related nodes.
@method _syncScrollUI
@protected
@since 3.5.0
**/
_syncScrollUI: function () {
var x = this._xScroll,
y = this._yScroll,
xScroller = this._xScrollNode,
yScroller = this._yScrollNode,
scrollLeft = xScroller && xScroller.get('scrollLeft'),
scrollTop = yScroller && yScroller.get('scrollTop');
this._uiSetScrollable();
// TODO: Probably should split this up into syncX, syncY, and syncXY
if (x || y) {
if ((this.get('width') || '').slice(-1) === '%') {
this._bindScrollResize();
} else {
this._unbindScrollResize();
}
this._syncScrollCaptionUI();
} else {
this._disableScrolling();
}
if (this._yScrollHeader) {
this._yScrollHeader.setStyle('display', 'none');
}
if (x) {
if (!y) {
this._disableYScrolling();
}
this._syncXScrollUI(y);
}
if (y) {
if (!x) {
this._disableXScrolling();
}
this._syncYScrollUI(x);
}
// Restore scroll position
if (scrollLeft && this._xScrollNode) {
this._xScrollNode.set('scrollLeft', scrollLeft);
}
if (scrollTop && this._yScrollNode) {
this._yScrollNode.set('scrollTop', scrollTop);
}
},
/**
Wraps the table in a scrolling `<div>` of the configured width for "x"
scrolling.
@method _syncXScrollUI
@param {Boolean} xy True if the table is configured with scrollable ="xy"
@protected
@since 3.5.0
**/
_syncXScrollUI: function (xy) {
var scroller = this._xScrollNode,
yScroller = this._yScrollContainer,
table = this._tableNode,
width = this.get('width'),
bbWidth = this.get('boundingBox').get('offsetWidth'),
scrollbarWidth = Y.DOM.getScrollbarWidth(),
borderWidth, tableWidth;
if (!scroller) {
scroller = this._createXScrollNode();
// Not using table.wrap() because IE went all crazy, wrapping the
// table in the last td in the table itself.
(yScroller || table).replace(scroller).appendTo(scroller);
}
// Can't use offsetHeight - clientHeight because IE6 returns
// clientHeight of 0 intially.
borderWidth = styleDim(scroller, 'borderLeftWidth') +
styleDim(scroller, 'borderRightWidth');
scroller.setStyle('width', '');
this._uiSetDim('width', '');
if (xy && this._yScrollContainer) {
this._yScrollContainer.setStyle('width', '');
}
// Lock the table's unconstrained width to avoid configured column
// widths being ignored
if (Y.UA.ie && Y.UA.ie < 8) {
// Have to assign a style and trigger a reflow to allow the
// subsequent clearing of width + reflow to expand the table to
// natural width in IE 6
table.setStyle('width', width);
table.get('offsetWidth');
}
table.setStyle('width', '');
tableWidth = table.get('offsetWidth');
table.setStyle('width', tableWidth + 'px');
this._uiSetDim('width', width);
// Can't use 100% width because the borders add additional width
// TODO: Cache the border widths, though it won't prevent a reflow
scroller.setStyle('width', (bbWidth - borderWidth) + 'px');
// expand the table to fill the assigned width if it doesn't
// already overflow the configured width
if ((scroller.get('offsetWidth') - borderWidth) > tableWidth) {
// Assumes the wrapped table doesn't have borders
if (xy) {
table.setStyle('width', (scroller.get('offsetWidth') -
borderWidth - scrollbarWidth) + 'px');
} else {
table.setStyle('width', '100%');
}
}
},
/**
Wraps the table in a scrolling `<div>` of the configured height (accounting
for the caption if there is one) if "y" scrolling is enabled. Otherwise,
unwraps the table if necessary.
@method _syncYScrollUI
@param {Boolean} xy True if the table is configured with scrollable = "xy"
@protected
@since 3.5.0
**/
_syncYScrollUI: function (xy) {
var yScroller = this._yScrollContainer,
yScrollNode = this._yScrollNode,
xScroller = this._xScrollNode,
fixedHeader = this._yScrollHeader,
scrollbar = this._scrollbarNode,
table = this._tableNode,
thead = this._theadNode,
captionTable = this._captionTable,
boundingBox = this.get('boundingBox'),
contentBox = this.get('contentBox'),
width = this.get('width'),
height = boundingBox.get('offsetHeight'),
scrollbarWidth = Y.DOM.getScrollbarWidth(),
outerScroller;
if (captionTable && !xy) {
captionTable.setStyle('width', width || '100%');
}
if (!yScroller) {
yScroller = this._createYScrollNode();
yScrollNode = this._yScrollNode;
table.replace(yScroller).appendTo(yScrollNode);
}
outerScroller = xy ? xScroller : yScroller;
if (!xy) {
table.setStyle('width', '');
}
// Set the scroller height
if (xy) {
// Account for the horizontal scrollbar in the overall height
height -= scrollbarWidth;
}
yScrollNode.setStyle('height',
(height - outerScroller.get('offsetTop') -
// because IE6 is returning clientHeight 0 initially
styleDim(outerScroller, 'borderTopWidth') -
styleDim(outerScroller, 'borderBottomWidth')) + 'px');
// Set the scroller width
if (xy) {
// For xy scrolling tables, the table should expand freely within
// the x scroller
yScroller.setStyle('width',
(table.get('offsetWidth') + scrollbarWidth) + 'px');
} else {
this._uiSetYScrollWidth(width);
}
if (captionTable && !xy) {
captionTable.setStyle('width', yScroller.get('offsetWidth') + 'px');
}
// Allow headerless scrolling
if (thead && !fixedHeader) {
fixedHeader = this._createYScrollHeader();
yScroller.prepend(fixedHeader);
this._syncScrollHeaders();
}
if (fixedHeader) {
this._syncScrollColumnWidths();
fixedHeader.setStyle('display', '');
// This might need to come back if FF has issues
//fixedHeader.setStyle('width', '100%');
//(yScroller.get('clientWidth') + scrollbarWidth) + 'px');
if (!scrollbar) {
scrollbar = this._createScrollbar();
this._bindScrollbar();
contentBox.prepend(scrollbar);
}
this._uiSetScrollbarHeight();
this._uiSetScrollbarPosition(outerScroller);
}
},
/**
Assigns the appropriate class to the `boundingBox` to identify the DataTable
as horizontally scrolling, vertically scrolling, or both (adds both classes).
Classes added are "yui3-datatable-scrollable-x" or "...-y"
@method _uiSetScrollable
@protected
@since 3.5.0
**/
_uiSetScrollable: function () {
this.get('boundingBox')
.toggleClass(this.getClassName('scrollable','x'), this._xScroll)
.toggleClass(this.getClassName('scrollable','y'), this._yScroll);
},
/**
Updates the virtual scrollbar's height to avoid overlapping with the fixed
headers.
@method _uiSetScrollbarHeight
@protected
@since 3.5.0
**/
_uiSetScrollbarHeight: function () {
var scrollbar = this._scrollbarNode,
scroller = this._yScrollNode,
fixedHeader = this._yScrollHeader;
if (scrollbar && scroller && fixedHeader) {
scrollbar.get('firstChild').setStyle('height',
this._tbodyNode.get('scrollHeight') + 'px');
scrollbar.setStyle('height',
(parseFloat(scroller.getComputedStyle('height')) -
parseFloat(fixedHeader.getComputedStyle('height'))) + 'px');
}
},
/**
Updates the virtual scrollbar's placement to avoid overlapping the fixed
headers or the data table.
@method _uiSetScrollbarPosition
@param {Node} scroller Reference node to position the scrollbar over
@protected
@since 3.5.0
**/
_uiSetScrollbarPosition: function (scroller) {
var scrollbar = this._scrollbarNode,
fixedHeader = this._yScrollHeader;
if (scrollbar && scroller && fixedHeader) {
scrollbar.setStyles({
// Using getCS instead of offsetHeight because FF uses
// fractional values, but reports ints to offsetHeight, so
// offsetHeight is unreliable. It is probably fine to use
// offsetHeight in this case but this was left in place after
// fixing an off-by-1px issue in FF 10- by fixing the caption
// font style so FF picked it up.
top: (parseFloat(fixedHeader.getComputedStyle('height')) +
styleDim(scroller, 'borderTopWidth') +
scroller.get('offsetTop')) + 'px',
// Minus 1 because IE 6-10 require the scrolled area to be
// visible by at least 1px or it won't respond to clicks on the
// scrollbar rail or endcap arrows.
left: (scroller.get('offsetWidth') -
Y.DOM.getScrollbarWidth() - 1 -
styleDim(scroller, 'borderRightWidth')) + 'px'
});
}
},
/**
Assigns the width of the `<div>` wrapping the data table in vertically
scrolling tables.
If the table can't compress to the specified width, the container is
expanded accordingly.
@method _uiSetYScrollWidth
@param {String} width The CSS width to attempt to set
@protected
@since 3.5.0
**/
_uiSetYScrollWidth: function (width) {
var scroller = this._yScrollContainer,
table = this._tableNode,
tableWidth, borderWidth, scrollerWidth, scrollbarWidth;
if (scroller && table) {
scrollbarWidth = Y.DOM.getScrollbarWidth();
if (width) {
// Assumes no table border
borderWidth = scroller.get('offsetWidth') -
scroller.get('clientWidth') +
scrollbarWidth; // added back at the end
// The table's rendered width might be greater than the
// configured width
scroller.setStyle('width', width);
// Have to subtract the border width from the configured width
// because the scroller's width will need to be reduced by the
// border width as well during the width reassignment below.
scrollerWidth = scroller.get('clientWidth') - borderWidth;
// Assumes no table borders
table.setStyle('width', scrollerWidth + 'px');
tableWidth = table.get('offsetWidth');
// Expand the scroll node width if the table can't fit.
// Otherwise, reassign the scroller a pixel width that
// accounts for the borders.
scroller.setStyle('width',
(tableWidth + scrollbarWidth) + 'px');
} else {
// Allow the table to expand naturally
table.setStyle('width', '');
scroller.setStyle('width', '');
scroller.setStyle('width',
(table.get('offsetWidth') + scrollbarWidth) + 'px');
}
}
},
/**
Detaches the scroll event subscriptions used to maintain scroll position
parity between the scrollable `<div>` wrapper around the data table and the
virtual scrollbar for vertically scrolling tables.
@method _unbindScrollbar
@protected
@since 3.5.0
**/
_unbindScrollbar: function () {
if (this._scrollbarEventHandle) {
this._scrollbarEventHandle.detach();
}
},
/**
Detaches the resize event subscription used to maintain column parity for
vertically scrolling tables with percentage widths.
@method _unbindScrollResize
@protected
@since 3.5.0
**/
_unbindScrollResize: function () {
if (this._scrollResizeHandle) {
this._scrollResizeHandle.detach();
delete this._scrollResizeHandle;
}
}
/**
Indicates horizontal table scrolling is enabled.
@property _xScroll
@type {Boolean}
@default undefined (not initially set)
@private
@since 3.5.0
**/
//_xScroll: null,
/**
Indicates vertical table scrolling is enabled.
@property _yScroll
@type {Boolean}
@default undefined (not initially set)
@private
@since 3.5.0
**/
//_yScroll: null,
/**
Fixed column header `<table>` Node for vertical scrolling tables.
@property _yScrollHeader
@type {Node}
@default undefined (not initially set)
@protected
@since 3.5.0
**/
//_yScrollHeader: null,
/**
Overflow Node used to contain the data rows in a vertically scrolling table.
@property _yScrollNode
@type {Node}
@default undefined (not initially set)
@protected
@since 3.5.0
**/
//_yScrollNode: null,
/**
Overflow Node used to contain the table headers and data in a horizontally
scrolling table.
@property _xScrollNode
@type {Node}
@default undefined (not initially set)
@protected
@since 3.5.0
**/
//_xScrollNode: null
}, true);
Y.Base.mix(Y.DataTable, [Scrollable]);