` of the configured width for "x"
scrolling.
@method _syncXScrollUI
@param {Boolean} xy True if the table is configured with scrollable ="xy"
@protected
@since 3.5.0
**/
_syncXScrollUI: function (xy) {
var scroller = this._xScrollNode,
yScroller = this._yScrollContainer,
table = this._tableNode,
width = this.get('width'),
bbWidth = this.get('boundingBox').get('offsetWidth'),
scrollbarWidth = Y.DOM.getScrollbarWidth(),
borderWidth, tableWidth;
if (!scroller) {
scroller = this._createXScrollNode();
// Not using table.wrap() because IE went all crazy, wrapping the
// table in the last td in the table itself.
(yScroller || table).replace(scroller).appendTo(scroller);
}
// Can't use offsetHeight - clientHeight because IE6 returns
// clientHeight of 0 intially.
borderWidth = styleDim(scroller, 'borderLeftWidth') +
styleDim(scroller, 'borderRightWidth');
scroller.setStyle('width', '');
this._uiSetDim('width', '');
if (xy && this._yScrollContainer) {
this._yScrollContainer.setStyle('width', '');
}
// Lock the table's unconstrained width to avoid configured column
// widths being ignored
if (Y.UA.ie && Y.UA.ie < 8) {
// Have to assign a style and trigger a reflow to allow the
// subsequent clearing of width + reflow to expand the table to
// natural width in IE 6
table.setStyle('width', width);
table.get('offsetWidth');
}
table.setStyle('width', '');
tableWidth = table.get('offsetWidth');
table.setStyle('width', tableWidth + 'px');
this._uiSetDim('width', width);
// Can't use 100% width because the borders add additional width
// TODO: Cache the border widths, though it won't prevent a reflow
scroller.setStyle('width', (bbWidth - borderWidth) + 'px');
// expand the table to fill the assigned width if it doesn't
// already overflow the configured width
if ((scroller.get('offsetWidth') - borderWidth) > tableWidth) {
// Assumes the wrapped table doesn't have borders
if (xy) {
table.setStyle('width', (scroller.get('offsetWidth') -
borderWidth - scrollbarWidth) + 'px');
} else {
table.setStyle('width', '100%');
}
}
},
/**
Wraps the table in a scrolling `
` of the configured height (accounting
for the caption if there is one) if "y" scrolling is enabled. Otherwise,
unwraps the table if necessary.
@method _syncYScrollUI
@param {Boolean} xy True if the table is configured with scrollable = "xy"
@protected
@since 3.5.0
**/
_syncYScrollUI: function (xy) {
var yScroller = this._yScrollContainer,
yScrollNode = this._yScrollNode,
xScroller = this._xScrollNode,
fixedHeader = this._yScrollHeader,
scrollbar = this._scrollbarNode,
table = this._tableNode,
thead = this._theadNode,
captionTable = this._captionTable,
boundingBox = this.get('boundingBox'),
contentBox = this.get('contentBox'),
width = this.get('width'),
height = boundingBox.get('offsetHeight'),
scrollbarWidth = Y.DOM.getScrollbarWidth(),
outerScroller;
if (captionTable && !xy) {
captionTable.setStyle('width', width || '100%');
}
if (!yScroller) {
yScroller = this._createYScrollNode();
yScrollNode = this._yScrollNode;
table.replace(yScroller).appendTo(yScrollNode);
}
outerScroller = xy ? xScroller : yScroller;
if (!xy) {
table.setStyle('width', '');
}
// Set the scroller height
if (xy) {
// Account for the horizontal scrollbar in the overall height
height -= scrollbarWidth;
}
yScrollNode.setStyle('height',
(height - outerScroller.get('offsetTop') -
// because IE6 is returning clientHeight 0 initially
styleDim(outerScroller, 'borderTopWidth') -
styleDim(outerScroller, 'borderBottomWidth')) + 'px');
// Set the scroller width
if (xy) {
// For xy scrolling tables, the table should expand freely within
// the x scroller
yScroller.setStyle('width',
(table.get('offsetWidth') + scrollbarWidth) + 'px');
} else {
this._uiSetYScrollWidth(width);
}
if (captionTable && !xy) {
captionTable.setStyle('width', yScroller.get('offsetWidth') + 'px');
}
// Allow headerless scrolling
if (thead && !fixedHeader) {
fixedHeader = this._createYScrollHeader();
yScroller.prepend(fixedHeader);
this._syncScrollHeaders();
}
if (fixedHeader) {
this._syncScrollColumnWidths();
fixedHeader.setStyle('display', '');
// This might need to come back if FF has issues
//fixedHeader.setStyle('width', '100%');
//(yScroller.get('clientWidth') + scrollbarWidth) + 'px');
if (!scrollbar) {
scrollbar = this._createScrollbar();
this._bindScrollbar();
contentBox.prepend(scrollbar);
}
this._uiSetScrollbarHeight();
this._uiSetScrollbarPosition(outerScroller);
}
},
/**
Assigns the appropriate class to the `boundingBox` to identify the DataTable
as horizontally scrolling, vertically scrolling, or both (adds both classes).
Classes added are "yui3-datatable-scrollable-x" or "...-y"
@method _uiSetScrollable
@protected
@since 3.5.0
**/
_uiSetScrollable: function () {
this.get('boundingBox')
.toggleClass(this.getClassName('scrollable','x'), this._xScroll)
.toggleClass(this.getClassName('scrollable','y'), this._yScroll);
},
/**
Updates the virtual scrollbar's height to avoid overlapping with the fixed
headers.
@method _uiSetScrollbarHeight
@protected
@since 3.5.0
**/
_uiSetScrollbarHeight: function () {
var scrollbar = this._scrollbarNode,
scroller = this._yScrollNode,
fixedHeader = this._yScrollHeader;
if (scrollbar && scroller && fixedHeader) {
scrollbar.get('firstChild').setStyle('height',
this._tbodyNode.get('scrollHeight') + 'px');
scrollbar.setStyle('height',
(parseFloat(scroller.getComputedStyle('height')) -
parseFloat(fixedHeader.getComputedStyle('height'))) + 'px');
}
},
/**
Updates the virtual scrollbar's placement to avoid overlapping the fixed
headers or the data table.
@method _uiSetScrollbarPosition
@param {Node} scroller Reference node to position the scrollbar over
@protected
@since 3.5.0
**/
_uiSetScrollbarPosition: function (scroller) {
var scrollbar = this._scrollbarNode,
fixedHeader = this._yScrollHeader;
if (scrollbar && scroller && fixedHeader) {
scrollbar.setStyles({
// Using getCS instead of offsetHeight because FF uses
// fractional values, but reports ints to offsetHeight, so
// offsetHeight is unreliable. It is probably fine to use
// offsetHeight in this case but this was left in place after
// fixing an off-by-1px issue in FF 10- by fixing the caption
// font style so FF picked it up.
top: (parseFloat(fixedHeader.getComputedStyle('height')) +
styleDim(scroller, 'borderTopWidth') +
scroller.get('offsetTop')) + 'px',
// Minus 1 because IE 6-10 require the scrolled area to be
// visible by at least 1px or it won't respond to clicks on the
// scrollbar rail or endcap arrows.
left: (scroller.get('offsetWidth') -
Y.DOM.getScrollbarWidth() - 1 -
styleDim(scroller, 'borderRightWidth')) + 'px'
});
}
},
/**
Assigns the width of the `
` wrapping the data table in vertically
scrolling tables.
If the table can't compress to the specified width, the container is
expanded accordingly.
@method _uiSetYScrollWidth
@param {String} width The CSS width to attempt to set
@protected
@since 3.5.0
**/
_uiSetYScrollWidth: function (width) {
var scroller = this._yScrollContainer,
table = this._tableNode,
tableWidth, borderWidth, scrollerWidth, scrollbarWidth;
if (scroller && table) {
scrollbarWidth = Y.DOM.getScrollbarWidth();
if (width) {
// Assumes no table border
borderWidth = scroller.get('offsetWidth') -
scroller.get('clientWidth') +
scrollbarWidth; // added back at the end
// The table's rendered width might be greater than the
// configured width
scroller.setStyle('width', width);
// Have to subtract the border width from the configured width
// because the scroller's width will need to be reduced by the
// border width as well during the width reassignment below.
scrollerWidth = scroller.get('clientWidth') - borderWidth;
// Assumes no table borders
table.setStyle('width', scrollerWidth + 'px');
tableWidth = table.get('offsetWidth');
// Expand the scroll node width if the table can't fit.
// Otherwise, reassign the scroller a pixel width that
// accounts for the borders.
scroller.setStyle('width',
(tableWidth + scrollbarWidth) + 'px');
} else {
// Allow the table to expand naturally
table.setStyle('width', '');
scroller.setStyle('width', '');
scroller.setStyle('width',
(table.get('offsetWidth') + scrollbarWidth) + 'px');
}
}
},
/**
Detaches the scroll event subscriptions used to maintain scroll position
parity between the scrollable `
` wrapper around the data table and the
virtual scrollbar for vertically scrolling tables.
@method _unbindScrollbar
@protected
@since 3.5.0
**/
_unbindScrollbar: function () {
if (this._scrollbarEventHandle) {
this._scrollbarEventHandle.detach();
}
},
/**
Detaches the resize event subscription used to maintain column parity for
vertically scrolling tables with percentage widths.
@method _unbindScrollResize
@protected
@since 3.5.0
**/
_unbindScrollResize: function () {
if (this._scrollResizeHandle) {
this._scrollResizeHandle.detach();
delete this._scrollResizeHandle;
}
}
/**
Indicates horizontal table scrolling is enabled.
@property _xScroll
@type {Boolean}
@default undefined (not initially set)
@private
@since 3.5.0
**/
//_xScroll: null,
/**
Indicates vertical table scrolling is enabled.
@property _yScroll
@type {Boolean}
@default undefined (not initially set)
@private
@since 3.5.0
**/
//_yScroll: null,
/**
Fixed column header `
` Node for vertical scrolling tables.
@property _yScrollHeader
@type {Node}
@default undefined (not initially set)
@protected
@since 3.5.0
**/
//_yScrollHeader: null,
/**
Overflow Node used to contain the data rows in a vertically scrolling table.
@property _yScrollNode
@type {Node}
@default undefined (not initially set)
@protected
@since 3.5.0
**/
//_yScrollNode: null,
/**
Overflow Node used to contain the table headers and data in a horizontally
scrolling table.
@property _xScrollNode
@type {Node}
@default undefined (not initially set)
@protected
@since 3.5.0
**/
//_xScrollNode: null
}, true);
Y.Base.mix(Y.DataTable, [Scrollable]);
}, '3.17.2', {"requires": ["datatable-base", "datatable-column-widths", "dom-screen"], "skinnable": true});