2
YUI 3.13.0 (build 508226d)
3
Copyright 2013 Yahoo! Inc. All rights reserved.
4
Licensed under the BSD License.
5
http://yuilibrary.com/license/
8
YUI.add('scrollview-scrollbars', function (Y, NAME) {
11
* Provides a plugin, which adds support for a scroll indicator to ScrollView instances
14
* @submodule scrollview-scrollbars
17
var getClassName = Y.ClassNameManager.getClassName,
20
Transition = Y.Transition,
21
NATIVE_TRANSITIONS = Transition.useNative,
22
SCROLLBAR = 'scrollbar',
23
SCROLLVIEW = 'scrollview',
25
VERTICAL_NODE = "verticalNode",
26
HORIZONTAL_NODE = "horizontalNode",
28
CHILD_CACHE = "childCache",
38
TRANSITION_PROPERTY = Y.ScrollView._TRANSITION.PROPERTY,
39
TRANSFORM = "transform",
41
TRANSLATE_X = "translateX(",
42
TRANSLATE_Y = "translateY(",
52
PX_CLOSE = PX + CLOSE;
55
* ScrollView plugin that adds scroll indicators to ScrollView instances
57
* @class ScrollViewScrollbars
59
* @extends Plugin.Base
62
function ScrollbarsPlugin() {
63
ScrollbarsPlugin.superclass.constructor.apply(this, arguments);
66
ScrollbarsPlugin.CLASS_NAMES = {
67
showing: getClassName(SCROLLVIEW, SCROLLBAR, 'showing'),
68
scrollbar: getClassName(SCROLLVIEW, SCROLLBAR),
69
scrollbarV: getClassName(SCROLLVIEW, SCROLLBAR, 'vert'),
70
scrollbarH: getClassName(SCROLLVIEW, SCROLLBAR, 'horiz'),
71
scrollbarVB: getClassName(SCROLLVIEW, SCROLLBAR, 'vert', 'basic'),
72
scrollbarHB: getClassName(SCROLLVIEW, SCROLLBAR, 'horiz', 'basic'),
73
child: getClassName(SCROLLVIEW, 'child'),
74
first: getClassName(SCROLLVIEW, 'first'),
75
middle: getClassName(SCROLLVIEW, 'middle'),
76
last: getClassName(SCROLLVIEW, 'last')
79
_classNames = ScrollbarsPlugin.CLASS_NAMES;
82
* The identity of the plugin
86
* @default 'pluginScrollViewScrollbars'
89
ScrollbarsPlugin.NAME = 'pluginScrollViewScrollbars';
92
* The namespace on which the plugin will reside.
96
* @default 'scrollbars'
99
ScrollbarsPlugin.NS = 'scrollbars';
102
* HTML template for the scrollbar
104
* @property SCROLLBAR_TEMPLATE
108
ScrollbarsPlugin.SCROLLBAR_TEMPLATE = [
110
'<span class="' + _classNames.child + ' ' + _classNames.first + '"></span>',
111
'<span class="' + _classNames.child + ' ' + _classNames.middle + '"></span>',
112
'<span class="' + _classNames.child + ' ' + _classNames.last + '"></span>',
117
* The default attribute configuration for the plugin
123
ScrollbarsPlugin.ATTRS = {
126
* Vertical scrollbar node
128
* @attribute verticalNode
133
valueFn: '_defaultNode'
137
* Horizontal scrollbar node
139
* @attribute horizontalNode
144
valueFn: '_defaultNode'
148
Y.namespace("Plugin").ScrollViewScrollbars = Y.extend(ScrollbarsPlugin, Y.Plugin.Base, {
151
* Designated initializer
153
* @method initializer
155
initializer: function() {
156
this._host = this.get("host");
158
this.afterHostEvent('scrollEnd', this._hostScrollEnd);
159
this.afterHostMethod('scrollTo', this._update);
160
this.afterHostMethod('_uiDimensionsChange', this._hostDimensionsChange);
164
* Set up the DOM nodes for the scrollbars. This method is invoked whenever the
165
* host's _uiDimensionsChange fires, giving us the opportunity to remove un-needed
166
* scrollbars, as well as add one if necessary.
168
* @method _hostDimensionsChange
171
_hostDimensionsChange: function() {
172
var host = this._host,
174
scrollX = host.get(SCROLL_X),
175
scrollY = host.get(SCROLL_Y);
177
this._dims = host._getScrollDims();
179
if (axis && axis.y) {
180
this._renderBar(this.get(VERTICAL_NODE), true, 'vert');
183
if (axis && axis.x) {
184
this._renderBar(this.get(HORIZONTAL_NODE), true, 'horiz');
187
this._update(scrollX, scrollY);
189
Y.later(500, this, 'flash', true);
193
* Handler for the scrollEnd event fired by the host. Default implementation flashes the scrollbar
195
* @method _hostScrollEnd
196
* @param {Event.Facade} e The event facade.
199
_hostScrollEnd : function() {
200
var host = this._host,
201
scrollX = host.get(SCROLL_X),
202
scrollY = host.get(SCROLL_Y);
206
this._update(scrollX, scrollY);
210
* Adds or removes a scrollbar node from the document.
214
* @param {Node} bar The scrollbar node
215
* @param {boolean} add true, to add the node, false to remove it
217
_renderBar: function(bar, add) {
218
var inDoc = bar.inDoc(),
220
className = bar.getData("isHoriz") ? _classNames.scrollbarHB : _classNames.scrollbarVB;
224
bar.toggleClass(className, this._basic);
225
this._setChildCache(bar);
226
} else if(!add && inDoc) {
228
this._clearChildCache(bar);
233
* Caches scrollbar child element information,
234
* to optimize _update implementation
236
* @method _setChildCache
240
_setChildCache : function(node) {
241
var c = node.get("children"),
245
size = node.getData("isHoriz") ? "offsetWidth" : "offsetHeight";
247
node.setStyle(TRANSITION_PROPERTY, TRANSFORM);
248
mc.setStyle(TRANSITION_PROPERTY, TRANSFORM);
249
lc.setStyle(TRANSITION_PROPERTY, TRANSFORM);
251
node.setData(CHILD_CACHE, {
255
fcSize : fc && fc.get(size),
256
lcSize : lc && lc.get(size)
263
* @method _clearChildCache
267
_clearChildCache : function(node) {
268
node.clearData(CHILD_CACHE);
272
* Utility method, to move/resize either vertical or horizontal scrollbars
277
* @param {Node} scrollbar The scrollbar node.
278
* @param {Number} current The current scroll position.
279
* @param {Number} duration The transition duration.
280
* @param {boolean} horiz true if horizontal, false if vertical.
282
_updateBar : function(scrollbar, current, duration, horiz) {
284
var host = this._host,
290
childCache = scrollbar.getData(CHILD_CACHE),
291
lastChild = childCache.lc,
292
middleChild = childCache.mc,
293
firstChildSize = childCache.fcSize,
294
lastChildSize = childCache.lcSize,
311
dimCache = HORIZ_CACHE;
312
widgetSize = this._dims.offsetWidth;
313
contentSize = this._dims.scrollWidth;
314
translate = TRANSLATE_X;
316
current = (current !== undefined) ? current : host.get(SCROLL_X);
320
dimCache = VERT_CACHE;
321
widgetSize = this._dims.offsetHeight;
322
contentSize = this._dims.scrollHeight;
323
translate = TRANSLATE_Y;
325
current = (current !== undefined) ? current : host.get(SCROLL_Y);
328
scrollbarSize = Math.floor(widgetSize * (widgetSize/contentSize));
329
scrollbarPos = Math.floor((current/(contentSize - widgetSize)) * (widgetSize - scrollbarSize));
330
if (scrollbarSize > widgetSize) {
334
if (scrollbarPos > (widgetSize - scrollbarSize)) {
335
scrollbarSize = scrollbarSize - (scrollbarPos - (widgetSize - scrollbarSize));
336
} else if (scrollbarPos < 0) {
337
scrollbarSize = scrollbarPos + scrollbarSize;
339
} else if (isNaN(scrollbarPos)) {
343
middleChildSize = (scrollbarSize - (firstChildSize + lastChildSize));
345
if (middleChildSize < 0) {
349
if (middleChildSize === 0 && scrollbarPos !== 0) {
350
scrollbarPos = widgetSize - (firstChildSize + lastChildSize) - 1;
353
if (duration !== 0) {
354
// Position Scrollbar
359
if (NATIVE_TRANSITIONS) {
360
transition.transform = translate + scrollbarPos + PX_CLOSE;
362
transition[dimOffset] = scrollbarPos + PX;
365
scrollbar.transition(transition);
368
if (NATIVE_TRANSITIONS) {
369
scrollbar.setStyle(TRANSFORM, translate + scrollbarPos + PX_CLOSE);
371
scrollbar.setStyle(dimOffset, scrollbarPos + PX);
375
// Resize Scrollbar Middle Child
376
if (this[dimCache] !== middleChildSize) {
377
this[dimCache] = middleChildSize;
379
if (middleChildSize > 0) {
381
if (duration !== 0) {
386
if(NATIVE_TRANSITIONS) {
387
transition.transform = scale + middleChildSize + CLOSE;
389
transition[dim] = middleChildSize + PX;
392
middleChild.transition(transition);
394
if (NATIVE_TRANSITIONS) {
395
middleChild.setStyle(TRANSFORM, scale + middleChildSize + CLOSE);
397
middleChild.setStyle(dim, middleChildSize + PX);
401
// Position Last Child
402
if (!horiz || !basic) {
404
lastChildPosition = scrollbarSize - lastChildSize;
411
if (NATIVE_TRANSITIONS) {
412
transition.transform = translate + lastChildPosition + PX_CLOSE;
414
transition[dimOffset] = lastChildPosition;
417
lastChild.transition(transition);
419
if (NATIVE_TRANSITIONS) {
420
lastChild.setStyle(TRANSFORM, translate + lastChildPosition + PX_CLOSE);
422
lastChild.setStyle(dimOffset, lastChildPosition + PX);
431
* AOP method, invoked after the host's _uiScrollTo method,
432
* to position and resize the scroll bars
435
* @param x {Number} The current scrollX value
436
* @param y {Number} The current scrollY value
437
* @param duration {Number} Number of ms of animation (optional) - used when snapping to bounds
438
* @param easing {String} Optional easing equation to use during the animation, if duration is set
441
_update: function(x, y, duration) {
442
var vNode = this.get(VERTICAL_NODE),
443
hNode = this.get(HORIZONTAL_NODE),
447
duration = (duration || 0)/1000;
449
if (!this._showing) {
453
if (axis && axis.y && vNode && y !== null) {
454
this._updateBar(vNode, y, duration, false);
457
if (axis && axis.x && hNode && x !== null) {
458
this._updateBar(hNode, x, duration, true);
463
* Show the scroll bar indicators
466
* @param animated {Boolean} Whether or not to animate the showing
468
show: function(animated) {
469
this._show(true, animated);
473
* Hide the scroll bar indicators
476
* @param animated {Boolean} Whether or not to animate the hiding
478
hide: function(animated) {
479
this._show(false, animated);
483
* Internal hide/show implementation utility method
486
* @param {boolean} show Whether to show or hide the scrollbar
487
* @param {bolean} animated Whether or not to animate while showing/hide
490
_show : function(show, animated) {
492
var verticalNode = this.get(VERTICAL_NODE),
493
horizontalNode = this.get(HORIZONTAL_NODE),
495
duration = (animated) ? 0.6 : 0,
496
opacity = (show) ? 1 : 0,
500
this._showing = show;
502
if (this._flashTimer) {
503
this._flashTimer.cancel();
511
if (verticalNode && verticalNode._node) {
512
verticalNode.transition(transition);
515
if (horizontalNode && horizontalNode._node) {
516
horizontalNode.transition(transition);
521
* Momentarily flash the scroll bars to indicate current scroll position
527
this._flashTimer = Y.later(800, this, 'hide', true);
531
* Setter for the verticalNode and horizontalNode attributes
534
* @param node {Node} The Y.Node instance for the scrollbar
535
* @param name {String} The attribute name
536
* @return {Node} The Y.Node instance for the scrollbar
540
_setNode: function(node, name) {
541
var horiz = (name === HORIZONTAL_NODE);
545
node.addClass(_classNames.scrollbar);
546
node.addClass( (horiz) ? _classNames.scrollbarH : _classNames.scrollbarV );
547
node.setData("isHoriz", horiz);
554
* Creates default node instances for scrollbars
556
* @method _defaultNode
557
* @return {Node} The Y.Node instance for the scrollbar
561
_defaultNode: function() {
562
return Y.Node.create(ScrollbarsPlugin.SCROLLBAR_TEMPLATE);
565
_basic: Y.UA.ie && Y.UA.ie <= 8
570
}, '3.13.0', {"requires": ["classnamemanager", "transition", "plugin"], "skinnable": true});