59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithAdds the ability to make the table rows scrollable while preserving the header
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith@module datatable-scroll
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith@for DataTable
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith// Returns the numeric value portion of the computed style, defaulting to 0
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith return parseInt(node.getComputedStyle(style), 10) | 0;
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith_API docs for this extension are included in the DataTable class._
53c97f474022b2633bdeccab063f518c4015f27aLuke SmithAdds the ability to make the table rows scrollable while preserving the header
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 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 SmithTo activate or deactivate scrolling, set the `scrollable` attribute to one of
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smiththe following values:
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 * 'y' - Activate vertical scrolling only. Requires the `height` attribute is
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith@class DataTable.Scrollable
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith@for DataTable
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithY.DataTable.Scrollable = Scrollable = function () {};
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Activates or deactivates scrolling in the table. Acceptable values are:
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 @attribute scrollable
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @type {String|Boolean}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @value false
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
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 @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}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith if (id && this._tbodyNode && (this._yScrollNode || this._xScrollNode)) {
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith // TODO: ancestor(yScrollNode, xScrollNode)
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith id.ancestor('.yui3-datatable') === this.get('boundingBox')) {
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith return this;
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith //--------------------------------------------------------------------------
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith // Protected properties and methods
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 @property _CAPTION_TABLE_TEMPLATE
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @type {HTML}
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith @value '<table class="{className}" role="presentation"></table>'
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _CAPTION_TABLE_TEMPLATE: '<table class="{className}" role="presentation"></table>',
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Template used to create sizable element liners around header content to
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith synchronize fixed header column widths.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @property _SCROLL_LINER_TEMPLATE
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @type {HTML}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @value '<div class="{className}"></div>'
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith _SCROLL_LINER_TEMPLATE: '<div class="{className}"></div>',
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Template for the virtual scrollbar needed in "y" and "xy" scrolling setups.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @property _SCROLLBAR_TEMPLATE
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @type {HTML}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @value '<div class="{className}"><div></div></div>'
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith _SCROLLBAR_TEMPLATE: '<div class="{className}"><div></div></div>',
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith Template for the `<div>` that is used to contain the table when the table is
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith horizontally scrolling.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @property _X_SCROLLER_TEMPLATE
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @type {HTML}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @value '<div class="{className}"></div>'
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith _X_SCROLLER_TEMPLATE: '<div class="{className}"></div>',
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Template for the `<table>` used to contain the fixed column headers for
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith vertically scrolling tables.
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 @since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith _Y_SCROLL_HEADER_TEMPLATE: '<table cellspacing="0" aria-hidden="true" class="{className}"></table>',
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Template for the `<div>` that is used to contain the rows when the table is
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith vertically scrolling.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @property _Y_SCROLLER_TEMPLATE
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @type {HTML}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @value '<div class="{className}"><div class="{scrollerClassName}"></div></div>'
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith _Y_SCROLLER_TEMPLATE: '<div class="{className}"><div class="{scrollerClassName}"></div></div>',
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.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _addScrollbarPadding
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @since 3.5.0
0c11eb686fb26ed5ccb04d1beb4e91952fce0bcbLuke Smith scrollbarWidth = Y.DOM.getScrollbarWidth() + 'px';
0c11eb686fb26ed5ccb04d1beb4e91952fce0bcbLuke Smith for (i = 0, len = rows.size(); i < len; i += +header.get('rowSpan')) {
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 @method _afterScrollableChange
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith @param {EventFacade} e The relevant change event (ignored)
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith @since 3.5.0
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith } else if (!this._yScroll && this._yScrollNode) {
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.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _afterScrollCaptionChange
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @param {EventFacade} e The relevant change event (ignored)
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @since 3.5.0
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
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @method _afterScrollColumnsChange
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @param {EventFacade} e The relevant change event (ignored)
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @since 3.5.0
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 @method _afterScrollDataChange
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @param {EventFacade} e The relevant change event (ignored)
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @since 3.5.0
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 @method _afterScrollHeightChange
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith @param {EventFacade} e The relevant change event (ignored)
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith @since 3.5.0
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 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 _afterScrollSort: function (e) {
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith this._yScrollHeader.all(headerClass).each(function (header, i) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith header.set('className', headers.item(i).get('className'));
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
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith @method _afterScrollWidthChange
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {EventFacade} e The relevant change event (ignored)
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith @since 3.5.0
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith Binds virtual scrollbar interaction to the `_yScrollNode`'s `scrollTop` and
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @method _bindScrollbar
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith _bindScrollbar: function () {
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)
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Binds to the window resize event to update the vertical scrolling table
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith headers and wrapper `<div>` dimensions.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _bindScrollResize
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @since 3.5.0
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.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith this._syncScrollUI, null, this);
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 This executes after the table's native `bindUI` method.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _bindScrollUI
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @since 3.5.0
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith _bindScrollUI: function () {
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!
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith this.after(['dataChange', '*:add', '*:remove', '*:reset', '*:change'],
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 @method _clearScrollLock
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @since 3.5.0
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Creates a virtual scrollbar from the `_SCROLLBAR_TEMPLATE`, assigning it to
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith the `_scrollbarNode` property.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @method _createScrollbar
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @return {Node} The created Node
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @since 3.5.0
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');
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Creates a separate table to contain the caption when the table is
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith configured to scroll vertically or horizontally.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _createScrollCaptionTable
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith @return {Node} The created Node
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith Populates the `_xScrollNode` property by creating the `<div>` Node described
771b101c1b151cb6c431aceafc4c95cdd8d2a4e1Luke Smith by the `_X_SCROLLER_TEMPLATE`.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _createXScrollNode
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @return {Node} The created Node
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith Populates the `_yScrollHeader` property by creating the `<table>` Node
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith described by the `_Y_SCROLL_HEADER_TEMPLATE`.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _createYScrollHeader
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @return {Node} The created Node
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith fixedHeader = this._yScrollHeader = Y.Node.create(
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith Populates the `_yScrollNode` property by creating the `<div>` Node described
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith by the `_Y_SCROLLER_TEMPLATE`.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _createYScrollNode
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @return {Node} The created Node
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith scrollerClass = this.getClassName('y', 'scroller');
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith className: this.getClassName('y','scroller','container'),
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith Removes the nodes used to create horizontal and vertical scrolling and
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith rejoins the caption to the main table if needed.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _disableScrolling
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @since 3.5.0
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith Removes the nodes used to allow horizontal scrolling.
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @method _disableXScrolling
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith Removes the nodes used to allow vertical scrolling.
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @method _disableYScrolling
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @since 3.5.0
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith Cleans up external event subscriptions.
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @method destructor
8a6a44314c3b8b5125191793d3f3e0baa8d31b7cLuke Smith @since 3.5.0
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith destructor: function () {
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 @method initializer
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith @param {Object} config The config object passed to the constructor (ignored)
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith initializer: function () {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this.after(['scrollableChange', 'heightChange', 'widthChange'],
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith Removes the table used to house the caption when the table is scrolling.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _removeScrollCaptionTable
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith Removes the `<div>` wrapper used to contain the data table when the table
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith is horizontally scrolling.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _removeXScrollNode
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @since 3.5.0
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith scroller.replace(scroller.get('childNodes').toFrag());
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Removes the `<div>` wrapper used to contain the data table and fixed header
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith when the table is vertically scrolling.
53c97f474022b2633bdeccab063f518c4015f27aLuke Smith @method _removeYScrollContainer
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @since 3.5.0
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith scroller.replace(scroller.get('childNodes').toFrag());
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Removes the `<table>` used to contain the fixed column headers when the
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith table is vertically scrolling.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @method _removeYScrollHeader
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @since 3.5.0
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Removes the `<div>` wrapper used to contain the data table when the table
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith is vertically scrolling.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @method _removeYScrollNode
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @since 3.5.0
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith scroller.replace(scroller.get('childNodes').toFrag());
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Removes the virtual scrollbar used by scrolling tables.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @method _removeScrollbar
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith @since 3.5.0
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 @method _setScrollable
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {String|Boolea} val Incoming value for the `scrollable` attribute
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @return {String}
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @since 3.5.0
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith if (val === true) {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith return (val === false || val === 'y' || val === 'x' || val === 'xy') ?
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 @method _setScrollProperties
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @since 3.5.0
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith this._xScroll = width && scrollable.indexOf('x') > -1;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._yScroll = height && scrollable.indexOf('y') > -1;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Keeps the virtual scrollbar and the scrolling `<div>` wrapper around the
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith data table in vertically scrolling tables in sync.
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
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith @since 3.5.0
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith if (this._scrollLock && this._scrollLock.source !== source) {
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith this._scrollLock = Y.later(300, this, this._clearScrollLock);
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith scroller.set('scrollTop', scrollbar.get('scrollTop'));
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith scrollbar.set('scrollTop', scroller.get('scrollTop'));
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
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @method _syncScrollCaptionUI
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith @since 3.5.0
7517febf3436a32039d125a66566b1c7be2f6b26Luke Smith if (!caption.get('parentNode').compareTo(captionTable)) {
2b9aa50d4077b548fa76a5d5330265ab397caad3Luke Smith Assigns widths to the fixed header columns to match the columns in the data
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith @method _syncScrollColumnWidths
6fe31db087e6c93b1df3a96b888b55344e039a23Luke Smith @since 3.5.0
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'))
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 this._yScrollHeader.all('.' + this.getClassName('scroll', 'liner'))
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Creates matching headers in the fixed header table for vertically scrolling
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith tables and synchronizes the column widths.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @method _syncScrollHeaders
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith @since 3.5.0
this._syncScrollColumnWidths();
this._addScrollbarPadding();
_syncScrollUI: function () {
var x = this._xScroll,
y = this._yScroll,
this._uiSetScrollable();
this._bindScrollResize();
this._unbindScrollResize();
this._syncScrollCaptionUI();
this._disableScrolling();
if (this._yScrollHeader) {
this._disableYScrolling();
this._syncXScrollUI(y);
this._disableXScrolling();
this._syncYScrollUI(x);
if (!scroller) {
if (xy) {
if (!yScroller) {
if (!xy) {
if (xy) {
if (xy) {
this._syncScrollHeaders();
if (fixedHeader) {
this._syncScrollColumnWidths();
if (!scrollbar) {
this._bindScrollbar();
this._uiSetScrollbarHeight();
_uiSetScrollable: function () {
_uiSetScrollbarHeight: function () {
if (width) {
_unbindScrollbar: function () {
if (this._scrollbarEventHandle) {
_unbindScrollResize: function () {
if (this._scrollResizeHandle) {
delete this._scrollResizeHandle;