1. #1
    Sencha Premium Member Matt Jenkins's Avatar
    Join Date
    Mar 2013
    Location
    Insch, Aberdeenshire, Scotland
    Posts
    24
    Vote Rating
    3
    Matt Jenkins is on a distinguished road

      1  

    Default Always show scrollbar

    Always show scrollbar


    I know there is some debate over the question of always showing the scrollbar but I recently worked on a project that needed to display the scroller when there is scrollable content.

    I've only hacked the source but I thought I'd post it here for those interested (ST 2.2.1). All feedback welcome!

    src/scroll/View.js
    Code:
    Ext.define('Ext.scroll.View', {
        extend: 'Ext.Evented',
        alternateClassName: 'Ext.util.ScrollView',
        requires: [
            'Ext.scroll.Scroller',
            'Ext.scroll.Indicator'
        ],
        config: {
            /**
             * @cfg {String} indicatorsUi
             * The style of the indicators of this view. Available options are `dark` or `light`.
             */
            indicatorsUi: 'dark',
            element: null,
            scroller: {},
            indicators: {
                x: {
                    axis: 'x'
                },
                y: {
                    axis: 'y'
                }
            },
            indicatorsHidingDelay: 100,
            cls: Ext.baseCSSPrefix + 'scroll-view',
            alwaysShow: false
        },
        /**
         * @method getScroller
         * Returns the scroller instance in this view. Checkout the documentation of {@link Ext.scroll.Scroller} and
         * {@link Ext.Container#getScrollable} for more information.
         * @return {Ext.scroll.View} The scroller
         */
    
    
        /**
         * @private
         */
        processConfig: function(config) {
            if (!config) {
                return null;
            }
    
    
            if (typeof config == 'string') {
                config = {
                    direction: config
                };
            }
    
    
            config = Ext.merge({}, config);
    
    
            var scrollerConfig = config.scroller,
                    name;
    
    
            if (!scrollerConfig) {
                config.scroller = scrollerConfig = {};
            }
    
    
            for (name in config) {
                if (config.hasOwnProperty(name)) {
                    if (!this.hasConfig(name)) {
                        scrollerConfig[name] = config[name];
                        delete config[name];
                    }
                }
            }
    
    
            return config;
        },
        constructor: function(config) {
            config = this.processConfig(config);
    
    
            this.useIndicators = {x: true, y: true};
    
    
            this.doHideIndicators = Ext.Function.bind(this.doHideIndicators, this);
    
    
            this.initConfig(config);
        },
        setConfig: function(config) {
            return this.callParent([this.processConfig(config)]);
        },
        updateIndicatorsUi: function(newUi) {
    
    
            var indicators = this.getIndicators();
            indicators.x.setUi(newUi);
            indicators.y.setUi(newUi);
    
    
    
    
    
    
        },
        applyScroller: function(config, currentScroller) {
            return Ext.factory(config, Ext.scroll.Scroller, currentScroller);
        },
        applyIndicators: function(config, indicators) {
            var defaultClass = Ext.scroll.Indicator,
                    useIndicators = this.useIndicators;
    
    
            if (!config) {
                config = {};
            }
    
    
            if (!config.x) {
                useIndicators.x = false;
                config.x = {};
            }
    
    
            if (!config.y) {
                useIndicators.y = false;
                config.y = {};
            }
    
    
            return {
                x: Ext.factory(config.x, defaultClass, indicators && indicators.x),
                y: Ext.factory(config.y, defaultClass, indicators && indicators.y)
            };
    
    
    
    
        },
        updateIndicators: function(indicators) {
            this.indicatorsGrid = Ext.Element.create({
                className: 'x-scroll-bar-grid-wrapper',
                children: [{
                        className: 'x-scroll-bar-grid',
                        children: [
                            {
                                children: [{}, {
                                        children: [indicators.y.barElement]
                                    }]
                            },
                            {
                                children: [{
                                        children: [indicators.x.barElement]
                                    }, {}]
                            }
                        ]
                    }]
            });
        },
        updateScroller: function(scroller) {
            scroller.on({
                scope: this,
                scrollstart: 'onScrollStart',
                scroll: 'onScroll',
                scrollend: 'onScrollEnd',
                refresh: 'refreshIndicators'
            });
        },
        isAxisEnabled: function(axis) {
            return this.getScroller().isAxisEnabled(axis) && this.useIndicators[axis];
        },
        applyElement: function(element) {
            if (element) {
                return Ext.get(element);
            }
        },
        updateElement: function(element) {
            var scroller = this.getScroller(),
                    scrollerElement;
    
    
    
    
            scrollerElement = element.getFirstChild().getFirstChild();
            if (this.FixedHBoxStretching) {
                scrollerElement = scrollerElement.getFirstChild();
            }
    
    
            element.addCls(this.getCls());
            element.insertFirst(this.indicatorsGrid);
    
    
            scroller.setElement(scrollerElement);
    
    
            this.refreshIndicators();
    
    
            return this;
        },
        showIndicators: function() {
            var indicators = this.getIndicators();
    
    
            if (this.hasOwnProperty('indicatorsHidingTimer')) {
                clearTimeout(this.indicatorsHidingTimer);
                delete this.indicatorsHidingTimer;
            }
    
    
            if (this.isAxisEnabled('x')) {
                indicators.x.show();
            }
    
    
            if (this.isAxisEnabled('y')) {
                indicators.y.show();
            }
        },
        hideIndicators: function() {
            var delay = this.getIndicatorsHidingDelay();
    
    
            if (delay > 0) {
                this.indicatorsHidingTimer = setTimeout(this.doHideIndicators, delay);
            }
            else {
                this.doHideIndicators();
            }
        },
        doHideIndicators: function() {
            
            var indicators = this.getIndicators();
            
            if (!this.getAlwaysShow() || ((indicators.x.gapLength === 0) && (indicators.y.gapLength === 0))) {            
    
    
                if (this.isAxisEnabled('x')) {
                    indicators.x.hide();
                }
    
    
                if (this.isAxisEnabled('y')) {
                    indicators.y.hide();
                }
            }
        },
        onScrollStart: function() {
            this.onScroll.apply(this, arguments);
            this.showIndicators();
        },
        onScrollEnd: function() {
            this.hideIndicators();
        },
        onScroll: function(scroller, x, y) {
            this.setIndicatorValue('x', x);
            this.setIndicatorValue('y', y);
    
    
            //<debug>
            if (this.isBenchmarking) {
                this.framesCount++;
            }
            //</debug>
        },
        //<debug>
        isBenchmarking: false,
        framesCount: 0,
        getCurrentFps: function() {
            var now = Date.now(),
                    fps;
    
    
            if (!this.isBenchmarking) {
                this.isBenchmarking = true;
                fps = 0;
            }
            else {
                fps = Math.round(this.framesCount * 1000 / (now - this.framesCountStartTime));
            }
    
    
            this.framesCountStartTime = now;
            this.framesCount = 0;
    
    
            return fps;
        },
        //</debug>
    
    
        setIndicatorValue: function(axis, scrollerPosition) {
            if (!this.isAxisEnabled(axis)) {
                return this;
            }
    
    
            var scroller = this.getScroller(),
                    scrollerMaxPosition = scroller.getMaxPosition()[axis],
                    scrollerContainerSize = scroller.getContainerSize()[axis],
                    value;
    
    
            if (scrollerMaxPosition === 0) {
                value = scrollerPosition / scrollerContainerSize;
    
    
                if (scrollerPosition >= 0) {
                    value += 1;
                }
            }
            else {
                if (scrollerPosition > scrollerMaxPosition) {
                    value = 1 + ((scrollerPosition - scrollerMaxPosition) / scrollerContainerSize);
                }
                else if (scrollerPosition < 0) {
                    value = scrollerPosition / scrollerContainerSize;
                }
                else {
                    value = scrollerPosition / scrollerMaxPosition;
                }
            }
    
    
            this.getIndicators()[axis].setValue(value);
        },
        refreshIndicator: function(axis) {
            if (!this.isAxisEnabled(axis)) {
                return this;
            }
    
    
            var scroller = this.getScroller(),
                    indicator = this.getIndicators()[axis],
                    scrollerContainerSize = scroller.getContainerSize()[axis],
                    scrollerSize = scroller.getSize()[axis],
                    ratio = scrollerContainerSize / scrollerSize;
    
    
            indicator.setRatio(ratio);
            indicator.refresh();
        },
        refresh: function() {
            return this.getScroller().refresh();
        },
        refreshIndicators: function() {
            var indicators = this.getIndicators();
    
    
            indicators.x.setActive(this.isAxisEnabled('x'));
            indicators.y.setActive(this.isAxisEnabled('y'));
    
    
            this.refreshIndicator('x');
            this.refreshIndicator('y');
    
    
            if (this.getAlwaysShow() && (indicators.x.gapLength || indicators.y.gapLength)) {
                this.showIndicators();
            }
        },
        destroy: function() {
            var element = this.getElement(),
                    indicators = this.getIndicators();
    
    
            Ext.destroy(this.getScroller(), this.indicatorsGrid);
    
    
            if (this.hasOwnProperty('indicatorsHidingTimer')) {
                clearTimeout(this.indicatorsHidingTimer);
                delete this.indicatorsHidingTimer;
            }
    
    
            if (element && !element.isDestroyed) {
                element.removeCls(this.getCls());
            }
    
    
            indicators.x.destroy();
            indicators.y.destroy();
    
    
            delete this.indicatorsGrid;
    
    
            this.callParent(arguments);
        }
    });
    Usage
    Code:
    scrollable: {
        alwaysShow: true
    }

  2. #2
    Sencha - Support Team
    Join Date
    Oct 2011
    Posts
    3,704
    Vote Rating
    117
    fmoseley is a name known to all fmoseley is a name known to all fmoseley is a name known to all fmoseley is a name known to all fmoseley is a name known to all fmoseley is a name known to all

      0  

    Default


    Thank you for sharing.

Thread Participants: 1