Monday, March 10, 2014

Sencha Touch List Find Top Visible Item Index

Recently in one of my project we have a Sencha Touch list and top banner. Each list item have certain banner text to show. When user scrolls up or down we have to show the banner text of list item which is on top position in the top banner panel. It should change as user moves up or down.  For that we have to find top visible item index or record of list. So here is my logic for that. 

As we know that all the list item have certain fix height that we can specify with itemHeight config. Each list is scrollable with scroll view. We can simply calculate top visible item by dividing y offset of scrollview with item height of the list. This will give us top visible item index. Here is the logic to do that. Add reference of your list to controller and bind initialize event of the list.

myList:{
                initialize: 'onMyListInit'
 },

No we will bind scroll event to this list scroller.

onMyListInit: function(list){
          var listItemHeight = 53;
          var scroller = list.getScrollable().getScroller();
          scroller.on({
            scroll: function(scroller, x, y, e){
                          var currentVisibleItemOnTopIndex = parseInt(y/listItemHeight);
                }
          });
}

This logic will give us top visible item index. You can find record from index using getAt method of list store. In my case I get the record and use it's banner text to display on top banner above the list. It keeps changing as you scroll up or down the list. Please note that this trick will only work if you have simple list with fixed height of the item. If you have variable heights or group list.  This trick will not work. As in group list we have items arranged in groups so their indexes changed. We might have to find some other solution for that. If you have any idea post a comment.

Friday, March 7, 2014

Sencha Touch List Expand and Collapse All Items

Recently in one of our Sencha Touch project we have a requirement to have expand and collapse all button on top of like to expand and collapse all the items of the list. Here is how we implemented it.

First add events of the buttons to your controller.

btnExpandAll: {
        tap: 'expandAll'
      },
btnCollapseAll: {
         tap: 'collapseAll'
        }

Now add above two functions in controller.

expandAll: function(){
    var list = this.getItemsList();
    var items = list.getViewItems();
        var itemsLn = items.length;
        for (i = 0; i < itemsLn; i++) {
            item = items[i];
            Ext.Animator.run({
element: item.element,
duration: 500,
easing: 'ease-in',
preserveEndState: true,
from: {
height: 60
},
to: {
height: 190
}
});
        }
    }

collapseAll: function(){
    var list = this.getItemsList();
    var items = list.getViewItems();
        var itemsLn = items.length;
        for (i = 0; i < itemsLn; i++) {
            item = items[i];
            Ext.Animator.run({
element: item.element,
duration: 500,
easing: 'ease-in',
preserveEndState: true,
from: {
height: 190
},
to: {
height: 60
}
});
        }
    }

You can set your own from and to height according to your requirement.


Wednesday, March 5, 2014

Sencha Touch List, Different background colors for Group Header

Recently in one of my project we have a Sencha Touch list with grouped headers. We know that we can control group header styles by CSS or we can change it by overriding base css class. In this case we will have one same color for each group header, while in my case the requirement was to have different background colors for each group header. This blog is about how how I implement it, you may have better idea. Feel free to comment.

Here I added background color in each items of the list and then grouped it based in certain field. For example.

Ext.define('MyApp.model.MyModel', {
    extend: 'Ext.data.Model',
    config:{
        fields: [
            { name:'id', type:'int'},
            { name:'group_background_color', type:'string'},
            { name:'item_name', type:'auto'},
            { name: 'group', type: 'string'}
        ]
    }
})

Then we have following Store definition.

Ext.define('MyApp.store.MyStore', {
    extend: 'Ext.data.Store',
    config: {
        model: 'MyApp.model.MyModel',
        autoLoad: true,
        grouper: {
        groupFn: function (item) {
            return item.get('group');
            }
        },
        proxy: {
            type:'ajax',
            actionMethods:{
                read: 'POST'
            },
            url:'items.json',
            reader:{
                type:'json',
                rootProperty:'items'
            }
        }
    }
});

Now we have our list where we will show this data.

{
        xtype: 'list',
        id:'myList',
itemId:'myList',
scrollable: true,
grouped: true,
itemTpl:'<div>{item_name}</div>' ,
        store: 'MyStore'
}

This will create list with groups and group header. If you use default Sencha Theme the group header will have blue as background color. We have to change it to our colors dynamically. For that we will update on list refresh. List refresh event is fired when list is visible first time and there is some change in data in store or list store is loaded. Add refresh event in controller.

control:{
            '#myList':{
                refresh: 'refreshListHeaders'
            }
}

And here is the function.

refreshListHeaders: function(list){
    if(list.groups){
    var groupElements  = document.getElementsByClassName('x-list-header');
    for(var i=0;i < groupElements.length i++){     
       var firstChild = list.groups[i].children[0];
    var backGroundColor = firstChild.data.banner_background_color;
    groupElements[i+1].style.setProperty('background-color', backGroundColor, '!important');
    }
    }
    }

So our logic is very simple. We get all the elements with class name "x-list-header" . That gives us all the header elements.  Now for each group we are getting background color from the first item of the group and set it as background color to group header.