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