| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 | <!DOCTYPE html><html><head>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  <title>The source code</title>  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>  <style type="text/css">    .highlight { display: block; background-color: #ddd; }  </style>  <script type="text/javascript">    function highlight() {      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";    }  </script></head><body onload="prettyPrint(); highlight();">  <pre class="prettyprint lang-js"><span id='Ext-layout-container-boxOverflow-Scroller'>/**</span> * @private */Ext.define('Ext.layout.container.boxOverflow.Scroller', {    /* Begin Definitions */    extend: 'Ext.layout.container.boxOverflow.None',    requires: ['Ext.util.ClickRepeater', 'Ext.Element'],    alternateClassName: 'Ext.layout.boxOverflow.Scroller',    mixins: {        observable: 'Ext.util.Observable'    },        /* End Definitions */<span id='Ext-layout-container-boxOverflow-Scroller-cfg-animateScroll'>    /**</span>     * @cfg {Boolean} animateScroll     * True to animate the scrolling of items within the layout (ignored if enableScroll is false)     */    animateScroll: false,<span id='Ext-layout-container-boxOverflow-Scroller-cfg-scrollIncrement'>    /**</span>     * @cfg {Number} scrollIncrement     * The number of pixels to scroll by on scroller click     */    scrollIncrement: 20,<span id='Ext-layout-container-boxOverflow-Scroller-cfg-wheelIncrement'>    /**</span>     * @cfg {Number} wheelIncrement     * The number of pixels to increment on mouse wheel scrolling.     */    wheelIncrement: 10,<span id='Ext-layout-container-boxOverflow-Scroller-cfg-scrollRepeatInterval'>    /**</span>     * @cfg {Number} scrollRepeatInterval     * Number of milliseconds between each scroll while a scroller button is held down     */    scrollRepeatInterval: 60,<span id='Ext-layout-container-boxOverflow-Scroller-cfg-scrollDuration'>    /**</span>     * @cfg {Number} scrollDuration     * Number of milliseconds that each scroll animation lasts     */    scrollDuration: 400,<span id='Ext-layout-container-boxOverflow-Scroller-cfg-beforeCtCls'>    /**</span>     * @cfg {String} beforeCtCls     * CSS class added to the beforeCt element. This is the element that holds any special items such as scrollers,     * which must always be present at the leftmost edge of the Container     */<span id='Ext-layout-container-boxOverflow-Scroller-cfg-afterCtCls'>    /**</span>     * @cfg {String} afterCtCls     * CSS class added to the afterCt element. This is the element that holds any special items such as scrollers,     * which must always be present at the rightmost edge of the Container     */<span id='Ext-layout-container-boxOverflow-Scroller-cfg-scrollerCls'>    /**</span>     * @cfg {String} [scrollerCls='x-box-scroller']     * CSS class added to both scroller elements if enableScroll is used     */    scrollerCls: Ext.baseCSSPrefix + 'box-scroller',<span id='Ext-layout-container-boxOverflow-Scroller-cfg-beforeScrollerCls'>    /**</span>     * @cfg {String} beforeScrollerCls     * CSS class added to the left scroller element if enableScroll is used     */<span id='Ext-layout-container-boxOverflow-Scroller-cfg-afterScrollerCls'>    /**</span>     * @cfg {String} afterScrollerCls     * CSS class added to the right scroller element if enableScroll is used     */    constructor: function(layout, config) {        var me = this;        me.layout = layout;        Ext.apply(me, config || {});        // Dont pass the config so that it is not applied to 'this' again        me.mixins.observable.constructor.call(me);        me.addEvents(<span id='Ext-layout-container-boxOverflow-Scroller-event-scroll'>            /**</span>             * @event scroll             * @param {Ext.layout.container.boxOverflow.Scroller} scroller The layout scroller             * @param {Number} newPosition The new position of the scroller             * @param {Boolean/Object} animate If animating or not. If true, it will be a animation configuration, else it will be false             */            'scroll'        );        me.scrollPosition = 0;        me.scrollSize = 0;    },    getPrefixConfig: function() {        var me = this;        me.initCSSClasses();        return {            cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.beforeCtCls,            cn : {                id : me.layout.owner.id + '-before-scroller',                cls: me.scrollerCls + ' ' + me.beforeScrollerCls,                style: 'display:none'            }        };    },    getSuffixConfig: function() {        var me = this;        return {            cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.afterCtCls,            cn : {                id : me.layout.owner.id + '-after-scroller',                cls: me.scrollerCls + ' ' + me.afterScrollerCls,                style: 'display:none'            }        };    },    getOverflowCls: function() {        return Ext.baseCSSPrefix + this.layout.direction + '-box-overflow-body';    },    initCSSClasses: function() {        var me = this,            prefix = Ext.baseCSSPrefix,            layout = me.layout,            names = layout.getNames(),            leftName = names.left,            rightName = names.right,            type = me.getOwnerType(layout.owner);        me.beforeCtCls = me.beforeCtCls || prefix + 'box-scroller-' + leftName;        me.afterCtCls  = me.afterCtCls  || prefix + 'box-scroller-' + rightName;                me.beforeScrollerCls = me.beforeScrollerCls || prefix + type + '-scroll-' + leftName;        me.afterScrollerCls  = me.afterScrollerCls  || prefix + type + '-scroll-' + rightName;    },    beginLayout: function (ownerContext) {        var layout = this.layout,            names = layout.getNames();        ownerContext.innerCtScrollPos = layout.innerCt.dom['scroll' + names.leftCap];        this.callParent(arguments);    },    completeLayout: function (ownerContext) {        // capture this before callParent since it calls handle/clearOverflow:        this.scrollSize = ownerContext.props['content'+this.layout.getNames().widthCap];        this.callParent(arguments);    },        finishedLayout: function(ownerContext) {        var me = this,            layout = me.layout,            names = layout.getNames(),            scrollPos = Math.min(me.getMaxScrollPosition(), ownerContext.innerCtScrollPos);        layout.innerCt.dom['scroll' + names.leftCap] = scrollPos;    },    handleOverflow: function(ownerContext) {        var me = this,            layout = me.layout,            names = layout.getNames(),            methodName = 'get' + names.widthCap;        me.captureChildElements();        me.showScrollers();        return {            reservedSpace: me.beforeCt[methodName]() + me.afterCt[methodName]()        };    },<span id='Ext-layout-container-boxOverflow-Scroller-method-captureChildElements'>    /**</span>     * @private     * Gets references to the beforeCt and afterCt elements if they have not already been captured     * and creates click handlers for them.     */    captureChildElements: function() {        var me = this,            el = me.layout.owner.el,            before,            after;        // Grab the scroll click receiving elements        if (!me.beforeCt) {            before = me.beforeScroller = el.getById(me.layout.owner.id + '-before-scroller');            after = me.afterScroller = el.getById(me.layout.owner.id + '-after-scroller');            me.beforeCt = before.up('');            me.afterCt = after.up('');            me.createWheelListener();            before.addClsOnOver(me.beforeScrollerCls + '-hover');            after.addClsOnOver(me.afterScrollerCls + '-hover');            before.setVisibilityMode(Ext.Element.DISPLAY);            after.setVisibilityMode(Ext.Element.DISPLAY);            me.beforeRepeater = new Ext.util.ClickRepeater(before, {                interval: me.scrollRepeatInterval,                handler : me.scrollLeft,                scope   : me            });            me.afterRepeater = new Ext.util.ClickRepeater(after, {                interval: me.scrollRepeatInterval,                handler : me.scrollRight,                scope   : me            });        }    },<span id='Ext-layout-container-boxOverflow-Scroller-method-createWheelListener'>    /**</span>     * @private     * Sets up an listener to scroll on the layout's innerCt mousewheel event     */    createWheelListener: function() {        this.layout.innerCt.on({            mousewheel: function(e) {                this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false);            },            stopEvent: true,            scope: this        });    },<span id='Ext-layout-container-boxOverflow-Scroller-method-clearOverflow'>    /**</span>     * @private     */    clearOverflow: function () {        var layout = this.layout;        this.hideScrollers();    },<span id='Ext-layout-container-boxOverflow-Scroller-method-showScrollers'>    /**</span>     * @private     * Shows the scroller elements in the beforeCt and afterCt. Creates the scrollers first if they are not already     * present.      */    showScrollers: function() {        var me = this;        me.captureChildElements();        me.beforeScroller.show();        me.afterScroller.show();        me.updateScrollButtons();        me.layout.owner.addClsWithUI('scroller');        // TODO - this may invalidates data in the ContextItem's styleCache    },<span id='Ext-layout-container-boxOverflow-Scroller-method-hideScrollers'>    /**</span>     * @private     * Hides the scroller elements in the beforeCt and afterCt     */    hideScrollers: function() {        var me = this;        if (me.beforeScroller !== undefined) {            me.beforeScroller.hide();            me.afterScroller.hide();            me.layout.owner.removeClsWithUI('scroller');            // TODO - this may invalidates data in the ContextItem's styleCache        }    },<span id='Ext-layout-container-boxOverflow-Scroller-method-destroy'>    /**</span>     * @private     */    destroy: function() {        var me = this;        Ext.destroy(me.beforeRepeater, me.afterRepeater, me.beforeScroller, me.afterScroller, me.beforeCt, me.afterCt);    },<span id='Ext-layout-container-boxOverflow-Scroller-method-scrollBy'>    /**</span>     * @private     * Scrolls left or right by the number of pixels specified     * @param {Number} delta Number of pixels to scroll to the right by. Use a negative number to scroll left     */    scrollBy: function(delta, animate) {        this.scrollTo(this.getScrollPosition() + delta, animate);    },<span id='Ext-layout-container-boxOverflow-Scroller-method-getScrollAnim'>    /**</span>     * @private     * @return {Object} Object passed to scrollTo when scrolling     */    getScrollAnim: function() {        return {            duration: this.scrollDuration,             callback: this.updateScrollButtons,             scope   : this        };    },<span id='Ext-layout-container-boxOverflow-Scroller-method-updateScrollButtons'>    /**</span>     * @private     * Enables or disables each scroller button based on the current scroll position     */    updateScrollButtons: function() {        var me = this,            beforeMeth,            afterMeth,            beforeCls,            afterCls;                    if (me.beforeScroller === undefined || me.afterScroller === undefined) {            return;        }        beforeMeth = me.atExtremeBefore()  ? 'addCls' : 'removeCls';        afterMeth  = me.atExtremeAfter() ? 'addCls' : 'removeCls';        beforeCls  = me.beforeScrollerCls + '-disabled';        afterCls   = me.afterScrollerCls  + '-disabled';        me.beforeScroller[beforeMeth](beforeCls);        me.afterScroller[afterMeth](afterCls);        me.scrolling = false;    },<span id='Ext-layout-container-boxOverflow-Scroller-method-atExtremeBefore'>    /**</span>     * @private     * Returns true if the innerCt scroll is already at its left-most point     * @return {Boolean} True if already at furthest left point     */    atExtremeBefore: function() {        return !this.getScrollPosition();    },<span id='Ext-layout-container-boxOverflow-Scroller-method-scrollLeft'>    /**</span>     * @private     * Scrolls to the left by the configured amount     */    scrollLeft: function() {        this.scrollBy(-this.scrollIncrement, false);    },<span id='Ext-layout-container-boxOverflow-Scroller-method-scrollRight'>    /**</span>     * @private     * Scrolls to the right by the configured amount     */    scrollRight: function() {        this.scrollBy(this.scrollIncrement, false);    },<span id='Ext-layout-container-boxOverflow-Scroller-method-getScrollPosition'>    /**</span>     * Returns the current scroll position of the innerCt element     * @return {Number} The current scroll position     */    getScrollPosition: function(){        var me = this,            layout = me.layout,            result;        // Until we actually scroll, the scroll[Top|Left] is stored as zero to avoid DOM hits.        if (me.hasOwnProperty('scrollPosition')) {            result = me.scrollPosition;        } else {            result = parseInt(layout.innerCt.dom['scroll' + layout.getNames().leftCap], 10) || 0;        }        return result;    },<span id='Ext-layout-container-boxOverflow-Scroller-method-getMaxScrollPosition'>    /**</span>     * @private     * Returns the maximum value we can scrollTo     * @return {Number} The max scroll value     */    getMaxScrollPosition: function() {        var me = this,            layout = me.layout,            names = layout.getNames(),            maxScrollPos = me.scrollSize - layout.innerCt['get'+names.widthCap]();        return (maxScrollPos < 0) ? 0 : maxScrollPos;    },<span id='Ext-layout-container-boxOverflow-Scroller-method-atExtremeAfter'>    /**</span>     * @private     * Returns true if the innerCt scroll is already at its right-most point     * @return {Boolean} True if already at furthest right point     */    atExtremeAfter: function() {        return this.getScrollPosition() >= this.getMaxScrollPosition();    },<span id='Ext-layout-container-boxOverflow-Scroller-method-scrollTo'>    /**</span>     * @private     * Scrolls to the given position. Performs bounds checking.     * @param {Number} position The position to scroll to. This is constrained.     * @param {Boolean} animate True to animate. If undefined, falls back to value of this.animateScroll     */    scrollTo: function(position, animate) {        var me = this,            layout = me.layout,            names = layout.getNames(),            oldPosition = me.getScrollPosition(),            newPosition = Ext.Number.constrain(position, 0, me.getMaxScrollPosition());        if (newPosition != oldPosition && !me.scrolling) {            delete me.scrollPosition;            if (animate === undefined) {                animate = me.animateScroll;            }            layout.innerCt.scrollTo(names.left, newPosition, animate ? me.getScrollAnim() : false);            if (animate) {                me.scrolling = true;            } else {                me.updateScrollButtons();            }            me.fireEvent('scroll', me, newPosition, animate ? me.getScrollAnim() : false);        }    },<span id='Ext-layout-container-boxOverflow-Scroller-method-scrollToItem'>    /**</span>     * Scrolls to the given component.     * @param {String/Number/Ext.Component} item The item to scroll to. Can be a numerical index, component id      * or a reference to the component itself.     * @param {Boolean} animate True to animate the scrolling     */    scrollToItem: function(item, animate) {        var me = this,            layout = me.layout,            names = layout.getNames(),            visibility,            box,            newPos;        item = me.getItem(item);        if (item !== undefined) {            visibility = me.getItemVisibility(item);            if (!visibility.fullyVisible) {                box  = item.getBox(true, true);                newPos = box[names.x];                if (visibility.hiddenEnd) {                    newPos -= (me.layout.innerCt['get' + names.widthCap]() - box[names.width]);                }                me.scrollTo(newPos, animate);            }        }    },<span id='Ext-layout-container-boxOverflow-Scroller-method-getItemVisibility'>    /**</span>     * @private     * For a given item in the container, return an object with information on whether the item is visible     * with the current innerCt scroll value.     * @param {Ext.Component} item The item     * @return {Object} Values for fullyVisible, hiddenStart and hiddenEnd     */    getItemVisibility: function(item) {        var me          = this,            box         = me.getItem(item).getBox(true, true),            layout      = me.layout,            names       = layout.getNames(),            itemStart   = box[names.x],            itemEnd     = itemStart + box[names.width],            scrollStart = me.getScrollPosition(),            scrollEnd   = scrollStart + layout.innerCt['get' + names.widthCap]();        return {            hiddenStart : itemStart < scrollStart,            hiddenEnd   : itemEnd > scrollEnd,            fullyVisible: itemStart > scrollStart && itemEnd < scrollEnd        };    }});</pre></body></html>
 |