src/cm/media/js/lib/yui/yui_3.10.3/build/node-scroll-info/node-scroll-info-debug.js
changeset 525 89ef5ed3c48b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cm/media/js/lib/yui/yui_3.10.3/build/node-scroll-info/node-scroll-info-debug.js	Tue Jul 16 14:29:46 2013 +0200
@@ -0,0 +1,587 @@
+/*
+YUI 3.10.3 (build 2fb5187)
+Copyright 2013 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+
+YUI.add('node-scroll-info', function (Y, NAME) {
+
+/**
+Provides the ScrollInfo Node plugin, which exposes convenient events and methods
+related to scrolling.
+
+@module node-scroll-info
+@since 3.7.0
+**/
+
+/**
+Provides convenient events and methods related to scrolling. This could be used,
+for example, to implement infinite scrolling, or to lazy-load content based on
+the current scroll position.
+
+### Example
+
+    var body = Y.one('body');
+
+    body.plug(Y.Plugin.ScrollInfo);
+
+    body.scrollInfo.on('scrollToBottom', function (e) {
+        // Load more content when the user scrolls to the bottom of the page.
+    });
+
+@class Plugin.ScrollInfo
+@extends Plugin.Base
+@since 3.7.0
+**/
+
+/**
+Fired when the user scrolls within the host node.
+
+This event (like all scroll events exposed by ScrollInfo) is throttled and fired
+only after the number of milliseconds specified by the `scrollDelay` attribute
+have passed in order to prevent thrashing.
+
+This event passes along the event facade for the standard DOM `scroll` event and
+mixes in the following additional properties.
+
+@event scroll
+@param {Boolean} atBottom Whether the current scroll position is at the bottom
+    of the scrollable region.
+@param {Boolean} atLeft Whether the current scroll position is at the extreme
+    left of the scrollable region.
+@param {Boolean} atRight Whether the current scroll position is at the extreme
+    right of the scrollable region.
+@param {Boolean} atTop Whether the current scroll position is at the top of the
+    scrollable region.
+@param {Boolean} isScrollDown `true` if the user scrolled down.
+@param {Boolean} isScrollLeft `true` if the user scrolled left.
+@param {Boolean} isScrollRight `true` if the user scrolled right.
+@param {Boolean} isScrollUp `true` if the user scrolled up.
+@param {Number} scrollBottom Y value of the bottom-most onscreen pixel of the
+    scrollable region.
+@param {Number} scrollHeight Total height in pixels of the scrollable region,
+    including offscreen pixels.
+@param {Number} scrollLeft X value of the left-most onscreen pixel of the
+    scrollable region.
+@param {Number} scrollRight X value of the right-most onscreen pixel of the
+    scrollable region.
+@param {Number} scrollTop Y value of the top-most onscreen pixel of the
+    scrollable region.
+@param {Number} scrollWidth Total width in pixels of the scrollable region,
+    including offscreen pixels.
+@see scrollDelay
+@see scrollMargin
+**/
+var EVT_SCROLL = 'scroll',
+
+    /**
+    Fired when the user scrolls down within the host node.
+
+    This event provides the same event facade as the `scroll` event. See that
+    event for details.
+
+    @event scrollDown
+    @see scroll
+    **/
+    EVT_SCROLL_DOWN = 'scrollDown',
+
+    /**
+    Fired when the user scrolls left within the host node.
+
+    This event provides the same event facade as the `scroll` event. See that
+    event for details.
+
+    @event scrollLeft
+    @see scroll
+    **/
+    EVT_SCROLL_LEFT = 'scrollLeft',
+
+    /**
+    Fired when the user scrolls right within the host node.
+
+    This event provides the same event facade as the `scroll` event. See that
+    event for details.
+
+    @event scrollRight
+    @see scroll
+    **/
+    EVT_SCROLL_RIGHT = 'scrollRight',
+
+    /**
+    Fired when the user scrolls up within the host node.
+
+    This event provides the same event facade as the `scroll` event. See that
+    event for details.
+
+    @event scrollUp
+    @see scroll
+    **/
+    EVT_SCROLL_UP = 'scrollUp',
+
+    /**
+    Fired when the user scrolls to the bottom of the scrollable region within
+    the host node.
+
+    This event provides the same event facade as the `scroll` event. See that
+    event for details.
+
+    @event scrollToBottom
+    @see scroll
+    **/
+    EVT_SCROLL_TO_BOTTOM = 'scrollToBottom',
+
+    /**
+    Fired when the user scrolls to the extreme left of the scrollable region
+    within the host node.
+
+    This event provides the same event facade as the `scroll` event. See that
+    event for details.
+
+    @event scrollToLeft
+    @see scroll
+    **/
+    EVT_SCROLL_TO_LEFT = 'scrollToLeft',
+
+    /**
+    Fired when the user scrolls to the extreme right of the scrollable region
+    within the host node.
+
+    This event provides the same event facade as the `scroll` event. See that
+    event for details.
+
+    @event scrollToRight
+    @see scroll
+    **/
+    EVT_SCROLL_TO_RIGHT = 'scrollToRight',
+
+    /**
+    Fired when the user scrolls to the top of the scrollable region within the
+    host node.
+
+    This event provides the same event facade as the `scroll` event. See that
+    event for details.
+
+    @event scrollToTop
+    @see scroll
+    **/
+    EVT_SCROLL_TO_TOP = 'scrollToTop';
+
+Y.Plugin.ScrollInfo = Y.Base.create('scrollInfoPlugin', Y.Plugin.Base, [], {
+    // -- Lifecycle Methods ----------------------------------------------------
+    initializer: function (config) {
+        // Cache for quicker lookups in the critical path.
+        this._host         = config.host;
+        this._hostIsBody   = this._host.get('nodeName').toLowerCase() === 'body';
+        this._scrollDelay  = this.get('scrollDelay');
+        this._scrollMargin = this.get('scrollMargin');
+        this._scrollNode   = this._getScrollNode();
+
+        this.refreshDimensions();
+
+        this._lastScroll = this.getScrollInfo();
+
+        this._bind();
+    },
+
+    destructor: function () {
+        (new Y.EventHandle(this._events)).detach();
+        delete this._events;
+    },
+
+    // -- Public Methods -------------------------------------------------------
+
+    /**
+    Returns a NodeList containing all offscreen nodes inside the host node that
+    match the given CSS selector. An offscreen node is any node that is entirely
+    outside the visible (onscreen) region of the host node based on the current
+    scroll location.
+
+    @method getOffscreenNodes
+    @param {String} [selector] CSS selector. If omitted, all offscreen nodes
+        will be returned.
+    @param {Number} [margin] Additional margin in pixels beyond the actual
+        onscreen region that should be considered "onscreen" for the purposes of
+        this query. Defaults to the value of the `scrollMargin` attribute.
+    @return {NodeList} Offscreen nodes matching _selector_.
+    @see scrollMargin
+    **/
+    getOffscreenNodes: function (selector, margin) {
+        if (typeof margin === 'undefined') {
+            margin = this._scrollMargin;
+        }
+
+        var lastScroll = this._lastScroll,
+            nodes      = this._host.all(selector || '*'),
+
+            scrollBottom = lastScroll.scrollBottom + margin,
+            scrollLeft   = lastScroll.scrollLeft - margin,
+            scrollRight  = lastScroll.scrollRight + margin,
+            scrollTop    = lastScroll.scrollTop - margin,
+
+            self = this;
+
+        return nodes.filter(function (el) {
+            var xy     = Y.DOM.getXY(el),
+                elLeft = xy[0] - self._left,
+                elTop  = xy[1] - self._top,
+                elBottom, elRight;
+
+            // Check whether the element's top left point is within the
+            // viewport. This is the least expensive check.
+            if (elLeft >= scrollLeft && elLeft < scrollRight &&
+                    elTop >= scrollTop && elTop < scrollBottom) {
+
+                return false;
+            }
+
+            // Check whether the element's bottom right point is within the
+            // viewport. This check is more expensive since we have to get the
+            // element's height and width.
+            elBottom = elTop + el.offsetHeight;
+            elRight  = elLeft + el.offsetWidth;
+
+            if (elRight < scrollRight && elRight >= scrollLeft &&
+                    elBottom < scrollBottom && elBottom >= scrollTop) {
+
+                return false;
+            }
+
+            // If we get here, the element isn't within the viewport.
+            return true;
+        });
+    },
+
+    /**
+    Returns a NodeList containing all onscreen nodes inside the host node that
+    match the given CSS selector. An onscreen node is any node that is fully or
+    partially within the visible (onscreen) region of the host node based on the
+    current scroll location.
+
+    @method getOnscreenNodes
+    @param {String} [selector] CSS selector. If omitted, all onscreen nodes will
+        be returned.
+    @param {Number} [margin] Additional margin in pixels beyond the actual
+        onscreen region that should be considered "onscreen" for the purposes of
+        this query. Defaults to the value of the `scrollMargin` attribute.
+    @return {NodeList} Onscreen nodes matching _selector_.
+    @see scrollMargin
+    **/
+    getOnscreenNodes: function (selector, margin) {
+        if (typeof margin === 'undefined') {
+            margin = this._scrollMargin;
+        }
+
+        var lastScroll = this._lastScroll,
+            nodes      = this._host.all(selector || '*'),
+
+            scrollBottom = lastScroll.scrollBottom + margin,
+            scrollLeft   = lastScroll.scrollLeft - margin,
+            scrollRight  = lastScroll.scrollRight + margin,
+            scrollTop    = lastScroll.scrollTop - margin,
+
+            self = this;
+
+        return nodes.filter(function (el) {
+            var xy     = Y.DOM.getXY(el),
+                elLeft = xy[0] - self._left,
+                elTop  = xy[1] - self._top,
+                elBottom, elRight;
+
+            // Check whether the element's top left point is within the
+            // viewport. This is the least expensive check.
+            if (elLeft >= scrollLeft && elLeft < scrollRight &&
+                    elTop >= scrollTop && elTop < scrollBottom) {
+
+                return true;
+            }
+
+            // Check whether the element's bottom right point is within the
+            // viewport. This check is more expensive since we have to get the
+            // element's height and width.
+            elBottom = elTop + el.offsetHeight;
+            elRight  = elLeft + el.offsetWidth;
+
+            if (elRight < scrollRight && elRight >= scrollLeft &&
+                    elBottom < scrollBottom && elBottom >= scrollTop) {
+
+                return true;
+            }
+
+            // If we get here, the element isn't within the viewport.
+            return false;
+        });
+    },
+
+    /**
+    Returns an object hash containing information about the current scroll
+    position of the host node. This is the same information that's mixed into
+    the event facade of the `scroll` event and other scroll-related events.
+
+    @method getScrollInfo
+    @return {Object} Object hash containing information about the current scroll
+        position. See the `scroll` event for details on what properties this
+        object contains.
+    @see scroll
+    **/
+    getScrollInfo: function () {
+        var domNode    = this._scrollNode,
+            lastScroll = this._lastScroll,
+            margin     = this._scrollMargin,
+
+            scrollLeft   = domNode.scrollLeft,
+            scrollHeight = domNode.scrollHeight,
+            scrollTop    = domNode.scrollTop,
+            scrollWidth  = domNode.scrollWidth,
+
+            scrollBottom = scrollTop + this._height,
+            scrollRight  = scrollLeft + this._width;
+
+        return {
+            atBottom: scrollBottom > (scrollHeight - margin),
+            atLeft  : scrollLeft < margin,
+            atRight : scrollRight > (scrollWidth - margin),
+            atTop   : scrollTop < margin,
+
+            isScrollDown : lastScroll && scrollTop > lastScroll.scrollTop,
+            isScrollLeft : lastScroll && scrollLeft < lastScroll.scrollLeft,
+            isScrollRight: lastScroll && scrollLeft > lastScroll.scrollLeft,
+            isScrollUp   : lastScroll && scrollTop < lastScroll.scrollTop,
+
+            scrollBottom: scrollBottom,
+            scrollHeight: scrollHeight,
+            scrollLeft  : scrollLeft,
+            scrollRight : scrollRight,
+            scrollTop   : scrollTop,
+            scrollWidth : scrollWidth
+        };
+    },
+
+    /**
+    Refreshes cached position, height, and width dimensions for the host node.
+    If the host node is the body, then the viewport height and width will be
+    used.
+
+    This info is cached to improve performance during scroll events, since it's
+    expensive to touch the DOM for these values. Dimensions are automatically
+    refreshed whenever the browser is resized, but if you change the dimensions
+    or position of the host node in JS, you may need to call
+    `refreshDimensions()` manually to cache the new dimensions.
+
+    @method refreshDimensions
+    **/
+    refreshDimensions: function () {
+        // WebKit only returns reliable scroll info on the body, and only
+        // returns reliable height/width info on the documentElement, so we
+        // have to special-case it (see the other special case in
+        // _getScrollNode()).
+        //
+        // On iOS devices, documentElement.clientHeight/Width aren't reliable,
+        // but window.innerHeight/Width are. And no, dom-screen's viewport size
+        // methods don't account for this, which is why we do it here.
+
+        var hostIsBody = this._hostIsBody,
+            iosHack    = hostIsBody && Y.UA.ios,
+            win        = Y.config.win,
+            el;
+
+        if (hostIsBody && Y.UA.webkit) {
+            el = Y.config.doc.documentElement;
+        } else {
+            el = this._scrollNode;
+        }
+
+        this._height = iosHack ? win.innerHeight : el.clientHeight;
+        this._left   = el.offsetLeft;
+        this._top    = el.offsetTop;
+        this._width  = iosHack ? win.innerWidth : el.clientWidth;
+    },
+
+    // -- Protected Methods ----------------------------------------------------
+
+    /**
+    Binds event handlers.
+
+    @method _bind
+    @protected
+    **/
+    _bind: function () {
+        var winNode = Y.one('win');
+
+        this._events = [
+            this.after({
+                scrollDelayChange : this._afterScrollDelayChange,
+                scrollMarginChange: this._afterScrollMarginChange
+            }),
+
+            winNode.on('windowresize', this._afterResize, this),
+
+            // If we're attached to the body, listen for the scroll event on the
+            // window, since <body> doesn't have a scroll event.
+            (this._hostIsBody ? winNode : this._host).after(
+                'scroll', this._afterScroll, this)
+        ];
+    },
+
+    /**
+    Returns the DOM node that should be used to lookup scroll coordinates. In
+    some browsers, the `<body>` element doesn't return scroll coordinates, and
+    the documentElement must be used instead; this method takes care of
+    determining which node should be used.
+
+    @method _getScrollNode
+    @return {HTMLElement} DOM node.
+    @protected
+    **/
+    _getScrollNode: function () {
+        // WebKit returns scroll coordinates on the body element, but other
+        // browsers don't, so we have to use the documentElement.
+        return this._hostIsBody && !Y.UA.webkit ? Y.config.doc.documentElement :
+                Y.Node.getDOMNode(this._host);
+    },
+
+    /**
+    Mixes detailed scroll information into the given DOM `scroll` event facade
+    and fires appropriate local events.
+
+    @method _triggerScroll
+    @param {EventFacade} e Event facade from the DOM `scroll` event.
+    @protected
+    **/
+    _triggerScroll: function (e) {
+        var info       = this.getScrollInfo(),
+            facade     = Y.merge(e, info),
+            lastScroll = this._lastScroll;
+
+        this._lastScroll = info;
+
+        this.fire(EVT_SCROLL, facade);
+
+        if (info.isScrollLeft) {
+            this.fire(EVT_SCROLL_LEFT, facade);
+        } else if (info.isScrollRight) {
+            this.fire(EVT_SCROLL_RIGHT, facade);
+        }
+
+        if (info.isScrollUp) {
+            this.fire(EVT_SCROLL_UP, facade);
+        } else if (info.isScrollDown) {
+            this.fire(EVT_SCROLL_DOWN, facade);
+        }
+
+        if (info.atBottom && (!lastScroll.atBottom ||
+                info.scrollHeight > lastScroll.scrollHeight)) {
+
+            this.fire(EVT_SCROLL_TO_BOTTOM, facade);
+        }
+
+        if (info.atLeft && !lastScroll.atLeft) {
+            this.fire(EVT_SCROLL_TO_LEFT, facade);
+        }
+
+        if (info.atRight && (!lastScroll.atRight ||
+                info.scrollWidth > lastScroll.scrollWidth)) {
+
+            this.fire(EVT_SCROLL_TO_RIGHT, facade);
+        }
+
+        if (info.atTop && !lastScroll.atTop) {
+            this.fire(EVT_SCROLL_TO_TOP, facade);
+        }
+    },
+
+    // -- Protected Event Handlers ---------------------------------------------
+
+    /**
+    Handles browser resize events.
+
+    @method _afterResize
+    @param {EventFacade} e
+    @protected
+    **/
+    _afterResize: function (e) {
+        this.refreshDimensions();
+    },
+
+    /**
+    Handles DOM `scroll` events.
+
+    @method _afterScroll
+    @param {EventFacade} e
+    @protected
+    **/
+    _afterScroll: function (e) {
+        var self = this;
+
+        clearTimeout(this._scrollTimeout);
+
+        this._scrollTimeout = setTimeout(function () {
+            self._triggerScroll(e);
+        }, this._scrollDelay);
+    },
+
+    /**
+    Caches the `scrollDelay` value after that attribute changes to allow
+    quicker lookups in critical path code.
+
+    @method _afterScrollDelayChange
+    @param {EventFacade} e
+    @protected
+    **/
+    _afterScrollDelayChange: function (e) {
+        this._scrollDelay = e.newVal;
+    },
+
+    /**
+    Caches the `scrollMargin` value after that attribute changes to allow
+    quicker lookups in critical path code.
+
+    @method _afterScrollMarginChange
+    @param {EventFacade} e
+    @protected
+    **/
+    _afterScrollMarginChange: function (e) {
+        this._scrollMargin = e.newVal;
+    }
+}, {
+    NS: 'scrollInfo',
+
+    ATTRS: {
+        /**
+        Number of milliseconds to wait after a native `scroll` event before
+        firing local scroll events. If another native scroll event occurs during
+        this time, previous events will be ignored. This ensures that we don't
+        fire thousands of events when the user is scrolling quickly.
+
+        @attribute scrollDelay
+        @type Number
+        @default 50
+        **/
+        scrollDelay: {
+            value: 50
+        },
+
+        /**
+        Additional margin in pixels beyond the onscreen region of the host node
+        that should be considered "onscreen".
+
+        For example, if set to 50, then a `scrollToBottom` event would be fired
+        when the user scrolls to within 50 pixels of the bottom of the
+        scrollable region, even if they don't actually scroll completely to the
+        very bottom pixel.
+
+        This margin also applies to the `getOffscreenNodes()` and
+        `getOnscreenNodes()` methods by default.
+
+        @attribute scrollMargin
+        @type Number
+        @default 50
+        **/
+        scrollMargin: {
+            value: 50
+        }
+    }
+});
+
+
+}, '3.10.3', {"requires": ["base-build", "dom-screen", "event-resize", "node-pluginhost", "plugin"]});