ExtJS: Horizontal sliding style paging for long panel using jQuery

Here we will see Horizontal sliding style paging for long panel using jQuery. Though in Horizontal sliding style paging for long panel [Part-2] and Horizontal sliding style paging for long panel [Part-1] we saw sliding with having scroll bar as viewable. In this part we will see how we implement a Horizontal sliding style paging for long panel without scroll bar.

There must have some other way. But, using jQuery seems easy and efficient to me. You can have a look How to use jQuery with ExtJS. Because, here I will show just the codes I used.

In my previous tutorials I told that the inner contents (Grid panels for my case) is dynamically added. So i don’t know the exact width.

So what i have to do is:

  1. Calculate the window width
  2. Calculate how many grids can be showing per slide
  3. Shift the Left position to slide the Inner Grids

Now, lets start coding.

ExtJS view Settings:

    Ext.define('MyProj.view.AllPacksPanel', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.allpackspanel',
    title: 'All Packs',
    layout: 'hbox',
    id: 'allpackspanel',
    ...

overflowX: 'scroll' has been removed, because default value is hidden.

And the buttons:

    dockedItems: [{
        xtype: 'toolbar',
        dock:'bottom',
        items: [
        {
            text: '',
            iconCls: 'icon-page-prev',
            id:'allpackspanel-page-prev'

        },
        '->',
        {
            xtype : 'tbtext',
            text : 'Page 1 of 1',
            id:'allpackspanel-page-number'
        },
        '->',
        {
            text: '',
            iconCls: 'icon-page-next',
            id:'allpackspanel-page-next'
        }
        ]
    }]

You may have noticed all handler we have removed.

For jQuery add an anonymous function, which will protect inner codes from outer scope and we will be able to avoid conflict.

(function (jQuery) {
    //my codes will go here...
})(jQuery);

Now I will add some variable so that in future we can use less effort to modify anything.

    var prevEl = '#allpackspanel-page-prev-btnEl'; //next button id
    var nextEl = '#allpackspanel-page-next-btnEl'; //prev button id
    var pageNumberEl = '#allpackspanel-page-number'; //id for: in the middle of these 2 button page number shows.
    var showButtonEl = '#show-packs-btnEl'; // this button was used to load the grids inside the panel
    var gridEl = '.x-panel.x-grid'; //common grid classes
    var viewContainerEl;
    var viewContainerElId='#allpackspanel-body';  //parent panel body
    var viewableWidth;
    var totalInnerWidth;
    var innerViewEl;
    var innerViewElId='#allpackspanel-innerCt'; //inner div in the panel body
    var positionLeftX = 0;
    var elWidth = 300; //width for each grid
    var moveDelta = 5; // how much grid will be moved per slide
    var totalEl=0;  //totla grids
    var currPage = 1;
    var totalPage = 1;
    var moveFactor = parseInt(moveDelta * elWidth); //the exact pixel to move finally

Now adding button actions.
As contents are adding dynamically, we will use jQuery on() function to bind elements dynamically.

    //grid loading button action
    jQuery(document).on('click', showButtonEl, function(){
        updateEl();
        updateVars();
        currPage = 1;
        updateViewableArea();
    });
    //next button action
    jQuery(document).on('click', nextEl, function(){
        updateEl();
        updateVars(); 
        if(++currPage <= totalPage){
            updateViewableArea();
        }else{
            currPage = totalPage;
        }
    });
    //prev button action
    jQuery(document).on('click', prevEl, function(){
        updateEl();
        updateVars();
        if(--currPage > 0){
            updateViewableArea(-1);
        }else{
            currPage = 1;
        }
    });

We see here few functions (updateEl(), updateVars() and updateViewableArea()) which are still not defined. So lets define those.

    function updateEl() {
        //each time we need update the elements
        //because element may replaced with new one.
        //if you are sure then you can use only in loader button's action
        viewContainerEl = jQuery(viewContainerElId);
        innerViewEl = jQuery(innerViewElId);
    }
    
    function updateVars() {
        totalEl = viewContainerEl.find(gridEl).length;
        
        viewableWidth = parseInt(viewContainerEl.width(),10);
        moveDelta = parseInt(viewableWidth / elWidth);
        
        totalPage = parseInt((totalEl / moveDelta),10);
        if(totalEl % moveDelta) totalPage++;
    }

    function updateViewableArea(direction) {
        if (typeof direction == "undefined" ) 
            direction = 1;

        var prevPos = viewableWidth * direction;

        var show = 0;
        for(var i=0; i < totalEl; i++){
            if(i < (currPage * moveDelta) && i >= ((currPage - 1) * moveDelta)){
                viewContainerEl.find('.x-panel.x-grid').eq(i).css({
                    'left':prevPos+'px'
                }).show().animate({
                    'left':(show * elWidth)+'px'
                },500);
                show++;
            }else{
                viewContainerEl.find('.x-panel.x-grid').eq(i).hide();
            }
        }
        jQuery(pageNumberEl).text('Page '+currPage+' of '+totalPage);
    }

We are done. But, if the inner contents are grid panels then the hidden grids will miss something. Like header and footer buttons etc.

But if we show hide with the EXT object then it wont happened.

    var id = viewContainerEl.find('.x-panel.x-grid').eq(i).attr('id');
    Ext.getCmp(id).show();
    Ext.getCmp(id).hide();   

So lets change the code:

    function updateViewableArea(direction) {
        if (typeof direction == "undefined" ) 
            direction = 1;

        var prevPos = viewableWidth * direction;

        var show = 0;
        for(var i=0; i < totalEl; i++){
            var id = viewContainerEl.find('.x-panel.x-grid').eq(i).attr('id');
            if(i < (currPage * moveDelta) && i >= ((currPage - 1) * moveDelta)){
                Ext.getCmp(id).css({
                    'left':prevPos+'px'
                }).show().animate({
                    'left':(show * elWidth)+'px'
                },500);
                show++;
            }else{
                Ext.getCmp(id).hide();
            }
        }
        jQuery(pageNumberEl).text('Page '+currPage+' of '+totalPage);
    }

Now, we can see fully animated and functional Horizontal sliding style paging..

Please, feel free for any kind of suggestion or discussion….

Advertisements

ExtJS: Horizontal sliding style paging for long panel [part-1]

There are several ways to achieve Horizontal sliding style paging for a panel which is horizontally larger than window. Here in part-1 I will show how to use scrollBy() . For my case there are more than 20 Grid panel was added in a Panel. FYI: I used the MVC architecture of ExtJS.

I have added two button at bottom (Next and Prev) to move the scroll. So the code was like bellow:

Panel settings was:

Ext.define('MyProj.view.AllPacksPanel', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.allpackspanel',
    title: 'All Packs',
    layout: 'hbox',
    id: 'allpackspanel',  //this is the ID we will use to get the component in button handler
    overflowX: 'scroll',  //horizontal scroll will be shown
    ...
    ...

And code for button with handler:

    dockedItems: [{
        xtype: 'toolbar',
        dock:'bottom',
        ui: 'footer',
        items: [
        {
            text: 'prev'
           iconCls: 'icon-prev'
           handler: function() {
               var cmp = Ext.getCmp("allpackspanel");
               cmp.scrollBy(-300,0,true);
           }
        },
        '->',
        {
            text: 'next'
           iconCls: 'icon-next'
           handler: function() {
               var cmp = Ext.getCmp("allpackspanel");
               cmp.scrollBy(300,0,true);  //300 as I want it will scroll by inner inner grid where inner grid panel size is 300
           }
        }
        ]
    }]

We will see in Part-2 how we can do the same with the position.