1. #1
    Sencha User
    Join Date
    Jan 2008
    Posts
    12
    Vote Rating
    0
    shprota is on a distinguished road

      0  

    Default RTL and Grid horizontal scrolling. Couple of homebrewed solutions.

    RTL and Grid horizontal scrolling. Couple of homebrewed solutions.


    Developing an RTL application with ExtJS I have found a few annoying glitches.
    First of all, it appears that in ExtJS 4.2.1 when an RTL grid with cell selection model is placed inside an RTL container, it would not scroll horizontally upon moving to leftmost cells.
    Another rather annoying problem is that when you scroll such a grid, it's column headers scroll differently and cease aligning right above the columns.
    After reading the code and some debugging I could provide solutions that solve those problems for me.
    I am not sure that these solutions are ultimate but one can take an idea.
    The common thing is when dealing with horizontal scrolling ExtJS directly modifies the DOM scrollLeft property of elements which is not working for RTL: should use rtlSetScrollLeft() method.
    Same goes to getting the current scroll position: use rtlGetScrollLeft() instead of reading the scrollLeft property directly.

    So I have created two extension classes to help with these things:

    1. Extend the Table panel to handle scrolling in the RTL way:
    Code:
    Ext.define('MyApp.rtl.Table', {
        override: 'Ext.panel.Table'
        ,onHorizontalScroll: function(event, target) {
            this.syncHorizontalScroll(Ext.get(target).rtlGetScrollLeft());
        }
        ,syncHorizontalScroll: function(left, setBody) {
            var me = this,
                scrollTarget;
    
            setBody = setBody === true;
            // Only set the horizontal scroll if we've changed position,
            // so that we don't set this on vertical scrolls
            if (me.rendered && (setBody || left !== me.scrollLeftPos)) {
                // Only set the body position if we're reacting to a refresh, otherwise
                // we just need to set the header.
                if (setBody) {
                    scrollTarget = me.getScrollTarget();
                    scrollTarget.el.rtlSetScrollLeft(left);
                }
                //me.headerCt.el.dom.scrollLeft = left;
                me.headerCt.el.rtlSetScrollLeft(left);
                me.scrollLeftPos = left;
            }
        }
        ,delayScroll: function(){
            var target = this.getScrollTarget().el;
            if (target) {
                this.scrollTask.delay(10, null, null, [target.rtlGetScrollLeft()]);
            }
        }
    });
    2. Extend the Element to fix the scrolling glitch:
    Code:
    Ext.define('MyApp.rtl.Element_scroll', {
        override: 'Ext.dom.Element'
       /**
         * Scrolls this element into view within the passed container.
         * @param {String/HTMLElement/Ext.Element} [container=document.body] The container element
         * to scroll.  Should be a string (id), dom node, or Ext.Element.
         * @param {Boolean} [hscroll=true] False to disable horizontal scroll.
         * @param {Boolean/Object} [animate] true for the default animation or a standard Element
         * @param {Boolean} [highlight=false] true to {@link #highlight} the element when it is in view.
         * animation config object
         * @return {Ext.dom.Element} this
         */
        ,scrollIntoView: function(container, hscroll, animate, highlight) {
            var me = this,
                dom = me.dom,
                offsets = me.getOffsetsTo(Ext.getDom(container) || Ext.getBody().dom),
            // el's box
                left = offsets[0] + container.rtlGetScrollLeft(),
                top = offsets[1] + container.dom.scrollTop,
                bottom = top + dom.offsetHeight,
                right = left + dom.offsetWidth,
            // ct's box
                ctClientHeight = container.dom.clientHeight,
                ctScrollTop = parseInt(container.dom.scrollTop, 10),
                ctScrollLeft = parseInt(container.rtlGetScrollLeft(), 10),
                ctBottom = ctScrollTop + ctClientHeight,
                ctRight = ctScrollLeft + container.dom.clientWidth,
                newPos;
            container = Ext.getDom(container);
    
            // Highlight upon end of scroll
            if (highlight) {
                if (animate) {
                    animate = Ext.apply({
                        listeners: {
                            afteranimate: function() {
                                me.scrollChildFly.attach(dom).highlight();
                            }
                        }
                    }, animate);
                } else {
                    me.scrollChildFly.attach(dom).highlight();
                }
            }
    
            if (dom.offsetHeight > ctClientHeight || top < ctScrollTop) {
                newPos = top;
            } else if (bottom > ctBottom) {
                newPos = bottom - ctClientHeight;
            }
            if (newPos != null) {
                me.scrollChildFly.attach(container).scrollTo('top', newPos, animate);
            }
    
            if (hscroll !== false) {
                newPos = null;
                if (dom.offsetWidth > container.clientWidth || left < ctScrollLeft) {
                    newPos = left;
                } else if (right > ctRight) {
                    newPos = right - container.clientWidth;
                }
                if (newPos != null) {
                    me.scrollChildFly.attach(container).rtlScrollTo('left', newPos, animate);
                }
            }
            return me;
        }
    });
    To use them just put the appropriate require lines right after the Ext.rtl.*

    I hope, this might help someone to avoid fighting the code to make it work right.

  2. #2
    Sencha - Support Team
    Join Date
    Feb 2013
    Location
    California
    Posts
    3,850
    Vote Rating
    66
    Gary Schlosberg has a spectacular aura about Gary Schlosberg has a spectacular aura about Gary Schlosberg has a spectacular aura about

      1  

    Default


    Thanks for sharing this with the community!

Thread Participants: 1

Tags for this Thread