swluken / TouchTreeGrid

Sencha Touch Tree Grid, Basic Grid and Accordion Component with Examples
52 stars 20 forks source link

Hide Root if "rootVisble: true" on TreeStore #1

Closed p5hema2 closed 10 years ago

p5hema2 commented 10 years ago

Hi,

i don't know if have have done something wrong but i have the problem. That i oculd get anything displayed without

rootVisible: true,

when i where loading my data from

http://www.json-generator.com/j/bPBVAqubvS?indent=4 (it is a little modified version of your example data).

My Store:

Ext.define('fly.store.left.Abo', {
    extend: 'Ext.data.TreeStore',
    config: {
        storeId: 'aboStore',
        model: 'fly.model.left.Abo',
        rootVisible: true,
        proxy: {
            timeout: 120000,
            type: 'ajax',
            reader: 'fly.store.left.Abo.Reader',
            reader: {
                type: 'json',
                rootProperty: 'items'
            },
            url: 'http://www.json-generator.com/j/bPBVAqubvS?indent=4'
        }
    }
});

My List:

Ext.define('fly.view.all.all.left.Abo', {
    extend: 'Ext.ux.touch.TouchTreeGrid',
    xtype: 'left_abo',
    config: {
        store: 'aboStore',
//        onItemDisclosure: true,
//        disclosureProperty: 'leaf',
//        includeHeader: false,
//        includeFooter: false,
        defaultCollapseLevel: 2,
//        disableExpandCollapse: true,
        hideRoot: true, // new config implemented from me
        categDepthColors: true,
        categDepthColorsArr: [
            '#808127',
            '#949569',
            '#C5C678',
            '#D5C678',
            '#E5C678'
        ],
        columns: [
            {
                header: 'Label',
                dataIndex: 'text',
                width: '60%',
                style: 'text-align: left;',
                categStyle: 'font-weight: bold; text-align: left; color: #f4f4f4;',
                headerStyle: 'text-align: left; color: #ccc;'
            }
        ]
    }
});

So i edited your plugin to get it working with

rootVisible: true,

Here is my edited version of your plugin: changes: line 22 --> added hideRoot: false, line 126-129 --> calling method replaceIsVisible line 1212-1243 --> replaceIsVisible method

/*
 * File: app/view/TouchTreeGrid.js
 *
 * This file was generated by Sencha Architect version 2.2.3.
 * http://www.sencha.com/products/architect/
 *
 * This file requires use of the Sencha Touch 2.2.x library, under independent license.
 * License of Sencha Architect does not include license for Sencha Touch 2.2.x. For more
 * details see http://www.sencha.com/license or contact license@sencha.com.
 *
 * This file will be auto-generated each and everytime you save your project.
 *
 * Do NOT hand edit this file.
 */

Ext.define('Ext.ux.touch.TouchTreeGrid', {
    extend: 'Ext.Container',
    alias: 'widget.touchtreegrid',

    config: {
        store: '',
        hideRoot: false,
        listScrollable: true,
        contentItemTpl: '',
        disableSelection: true,
        onItemDisclosure: false,
        headerTpl: '',
        variableHeights: true,
        itemHeight: 47,
        disclosureProperty: 'disclose',
        listItemId: 'touchtreegridlist',
        categItemTpl: '',
        includeFooter: true,
        categIndentPct: '3',
        colNumberToTruncateForIndents: 1,
        includeFooterLevels: true,
        categDepthColors: false,
        customExpCollapseEvent: '',
        categDepthColorButtons: true,
        categItemTplOverride: '',
        contentItemTplOverride: '',
        headerTplOverride: '',
        includeHeader: true,
        applyDefaultCollapseLevel: true,
        defaultCollapseLevel: 99,
        landscapeIcon: '',
        helpHtml: '',
        pressedCls: 'touchtreegrid-item-pressed',
        simpleList: false,
        columnSorting: false,
        styleContentRow: '',
        styleCategRow: '',
        styleHeaderRow: '',
        singleExpand: false,
        selectedCls: 'touchtreegrid-item-selected',
        mode: 'SINGLE',
        useSimpleItems: true,
        infinite: true,
        arrowPctWidth: '4',
        customColumnSortEvent: '',
        disableExpandCollapse: false,
        cssContentRow: 'css-content-row ',
        cssCategRow: 'css-categ-row ',
        cssHeaderRow: 'css-header-row ',
        includeCustomFooterItems: false,
        footerDock: 'bottom',
        hideExpandCollapseBtns: false,
        linkedGridsParentItemId: '',
        cls: 'x-touchtreegrid-list',
        layout: {
            type: 'vbox'
        },
        list: {

        },
        columns: [

        ],
        header: {
            xtype: 'toolbar',
            docked: 'top',
            cls: 'touchtreegrid-header'
        },
        footer: {
            xtype: 'toolbar',
            docked: 'bottom',
            ui: 'light',
            cls: 'touchtreegrid-footer'
        },
        listPlugins: {

        },
        categDepthColorsArr: [
            '#a6a6a6',
            '#dddddd',
            'white'
        ],
        renderers: {

        },
        additionalListConfigs: {

        },
        categColumns: [

        ],
        categCssArr: [

        ],
        customFooterItems: {

        },
        onScrollOptions: {

        },
        linkedGridsArr: [

        ]
    },

    initialize: function(config) {
        var me = this;

        me.callParent(arguments);

        if (this.getHideRoot()) {
            this.replaceIsVisible();
        }

        this.doRefreshList();

        // Process linked grids for synchronized scrolling if applicables
        if (me.getLinkedGridsArr().length>0) {
            var listItemId = me.getListItemId();
            var gridlist = me.down('#'+listItemId);
            var scroller = gridlist.getScrollable().getScroller();
            scroller.on('scroll',   me.onScroll, me, me.getOnScrollOptions());   
        }

    },

    updateColumns: function() {
        // UPDATE functions on config items execute prior to INITIALIZE (and before UPDATESTORE) so 
        // insert logic here to build ItemTpl components
        // NOTE:  Columns updated in this Class as [initialize] to force execution of this function.

        var me = this, myWidth, myWidthVal;

        var simpleList = me.getSimpleList();

        // Proceed to build TPL for header row
        var styleStr = '', rendStr='', cssStr='', idxStr = '';
        var categ = me.getCategItemTplOverride();
        var indent = me.getCategIndentPct().toString().replace("%", ""); // % of window to indent per level (starting at 0% ... default =3%)
        var arrowWid = me.getArrowPctWidth().toString().replace("%", ""); // allow control over percent screen width that category arrow consumes (def = 4%)

        var categStyle = Ext.isEmpty(me.getStyleCategRow()) ? '' : ' style="' + me.getStyleCategRow() + '"';
        var contentStyle = Ext.isEmpty(me.getStyleContentRow()) ? '' : ' style="' + me.getStyleContentRow() + '"';

        var categCss = Ext.isEmpty(me.getCssCategRow()) ? '' : ' class="' + me.getCssCategRow() + '"';
        var contentCss = Ext.isEmpty(me.getCssContentRow()) ? '' : ' class="' + me.getCssContentRow() + '"';

        var indentCol = me.getColNumberToTruncateForIndents()-1; // This column width value will be truncated to account for indent
        // Subtract 1 from column number to array index # applied below.
        // Width expected to be in pct format as last '%' character will be stripped for computation : '25%'

        var data = me.getColumns(); // single dimention array of objects defining each column
        var categData = me.getCategColumns(); // optional multi-dimension array of objects of category columns defs by level

        if (this.isObjectEmpty(data)) {  
            // Initialize column data for scenario where column array updated within controller after component initialization
            data ={header: '', dataIndex: '', width: '', style: '', categStyle: '', headerStyle: ''};
        }

        var shellArr=[], i, k, categArr=[],
            prefixArr = ['<div' + categStyle + categCss + '>'];

        if (parseInt(indent) > 0) {
            prefixArr.push('<div align="left" style="width:{[(values.depth-1)*'+indent+']}%;"></div>');  // 3% per depth starting at 0% 
        }
        if (parseInt(arrowWid) > 0) {
            prefixArr = prefixArr.concat([    
            '<div align="left" style="width:'+arrowWid+'%;min-width:'+arrowWid+'%;max-width:'+arrowWid+'%;white-space: nowrap;overflow:hidden;text-overflow:ellipsis;">', 
            '<span class="touchtreegrid-details-img ',
            '<tpl if="this.isExpanded(values)">',   
            'touchtreegrid-details-img-open' ,
            '<tpl else>',  
            'touchtreegrid-details-img-close' ,
            '</tpl>',
            '"</span>',
            '</div>'
            ]);
        }    

        if (categ==='' && !simpleList && Ext.isEmpty(categData)) {   
            // Process category row TPL (same TPL for all category rows defined via Columns array)

            shellArr.push(prefixArr.join(''));
            for (i=0; i<data.length; i++) {

                // Use categStyle if exists, else apply detail row style to category row
                if (!Ext.isEmpty(data[i].categStyle) && data[i].categStyle > '') {styleStr = data[i].categStyle;}
                else if (!Ext.isEmpty(data[i].style)) {styleStr = data[i].style;}
                else {styleStr = '';}

                // Use categCss if exists, else apply detail row css to category row (if defined)
                if (!Ext.isEmpty(data[i].categCss) && data[i].categCss > '') {cssStr = data[i].categCss;}
                else if (!Ext.isEmpty(data[i].css)) {cssStr = data[i].css;}
                else {cssStr = '';}

                // Substitute user-defined renderer string from Columns array if defined
                rendStr = (Ext.isEmpty(data[i].renderer) ? (Ext.isEmpty(data[i].dataIndex) ? '' : data[i].dataIndex) : '[' + data[i].renderer + ']');

                // Add dataIndex attribute to this DIV if requested in Columns array (for purposes of trapping cell tap)
                idxStr = ((!data[i].addDataIndexToDiv) ? '' : ' dataIndex="' + data[i].dataIndex + '"');        

                if (i===indentCol) {    
                    // Subtract percentage width based on level          
                    shellArr.push('<div class="touchtreegrid-list-categ-cell ' + cssStr + '" style="' +
                    'min-width:{[' + data[i].width.replace("%", "") + '-((values.depth-1)*'+indent+')]}% !important;' + 
                    'max-width:{[' + data[i].width.replace("%", "") + '-((values.depth-1)*'+indent+')]}% !important;' + 
                    'width:{[' + data[i].width.replace("%", "") + '-((values.depth-1)*'+indent+')]}% !important;' + 
                    styleStr + '"' + idxStr + ' >{' + rendStr + '}</div>');                       
                } else {           
                    shellArr.push('<div class="touchtreegrid-list-categ-cell " style="' +
                    'min-width:' + data[i].width + ' !important;' + 
                    'max-width:' + data[i].width + ' !important;' + 
                    'width:' + data[i].width + ' !important;' + 
                    styleStr + '"' + idxStr + ' >{' + rendStr + '}</div>');
                }  
            }

            shellArr.push('</div>');  
            categ=shellArr.join('');
            me.setCategItemTpl(categ);
        }
        else if (categ==='' && !simpleList && !Ext.isEmpty(categData)) {
            // Process category row TPL as defined in categColumns.  

            shellArr = []; 
            shellArr.push(prefixArr.join(''));  // Initialize with arrow and row style definitions

            for (i=0; i<categData.length; i++) {  // loop for each object defined in current sub-array

                // Use categStyle if exists, else apply detail row style to category row
                if (!Ext.isEmpty(categData[i].categStyle) && categData[i].categStyle > '') {styleStr = categData[i].categStyle;}
                else if (!Ext.isEmpty(categData[i].style)) {styleStr = categData[i].style;}
                else {styleStr = '';}

                // Use categCss if exists, else apply detail row css to category row (if defined)
                if (!Ext.isEmpty(categData[i].categCss) && categData[i].categCss > '') {cssStr = categData[i].categCss;}
                else if (!Ext.isEmpty(categData[i].css)) {cssStr = categData[i].css;}
                else {cssStr = '';}

                // Substitute user-defined renderer string from Columns array if defined
                rendStr = ((!categData[i].renderer) ? (Ext.isEmpty(categData[i].dataIndex) ? '' : categData[i].dataIndex) : '[' + categData[i].renderer + ']');

                // Add dataIndex attribute to this DIV if requested in Columns array (for purposes of trapping cell tap)
                idxStr = ((!categData[i].addDataIndexToDiv) ? '' : ' dataIndex="' + categData[i].dataIndex + '"');

                if (i===indentCol) {     
                    // Subtract percentage width based on level             
                    shellArr.push('<div class="touchtreegrid-list-categ-cell ' + cssStr + '" style="' +
                    'min-width:{[' + categData[i].width.replace("%", "") + '-((values.depth-1)*'+indent+')]}% !important;' + 
                    'max-width:{[' + categData[i].width.replace("%", "") + '-((values.depth-1)*'+indent+')]}% !important;' + 
                    'width:{[' + categData[i].width.replace("%", "") + '-((values.depth-1)*'+indent+')]}% !important;' + 
                    styleStr + '"' + idxStr + ' >{' + rendStr + '}</div>');                       
                } else {           
                    shellArr.push('<div class="touchtreegrid-list-categ-cell ' + cssStr + '" style="' +
                    'min-width:' + categData[i].width + ' !important;' + 
                    'max-width:' + categData[i].width + ' !important;' + 
                    'width:' + categData[i].width + ' !important;' + 
                    styleStr + '"' + idxStr + ' >{' + rendStr + '}</div>');
                }  
            }

            shellArr.push('</div>');  
            categArr=shellArr.join('');

            me.setCategItemTpl(categArr);  

        }
        else {me.setCategItemTpl(categ);}  // simply update with TPL provided in CategItemTplOverride config (ignored for simpleList=true)

        var detail = me.getContentItemTplOverride();
        var detailArr, j;
        if (detail==='' && !simpleList) {
            detailArr = ['<div' + contentStyle + contentCss + '>'];  
            if (parseInt(indent) > 0) {
                detailArr.push('<div align="left" style="width:{[(values.depth-1)*'+indent+']}%;"></div>');    // 3% per depth starting at 0%         
            }
            if (parseInt(arrowWid) > 0) {
                detailArr.push('<div align="left" style="width:'+arrowWid+'%;min-width:'+arrowWid+'%;max-width:'+arrowWid+'%;white-space: nowrap;overflow:hidden;text-overflow:ellipsis;">&nbsp;</div>');
            }

            for (j=0; j<data.length; j++) {

                // Substitute user-defined renderer string from Columns array if defined
                rendStr = ((!data[j].renderer) ? (Ext.isEmpty(data[j].dataIndex) ? '' : data[j].dataIndex) : '[' + data[j].renderer + ']');

                // Add dataIndex attribute to this DIV if requested in Columns array (for purposes of trapping cell tap)
                idxStr = ((!data[j].addDataIndexToDiv) ? '' : ' dataIndex="' + data[j].dataIndex + '"');

                cssStr = (Ext.isEmpty(data[j].css)) ? '' : data[j].css;        

                if (j===indentCol) {     
                    // Subtract percentage width based on level
                    detailArr.push('<div class="touchtreegrid-list-content-cell ' + cssStr + '" style="' +
                    'min-width:{[' + data[j].width.replace("%", "") + '-((values.depth-1)*'+indent+')]}% !important;' + 
                    'max-width:{[' + data[j].width.replace("%", "") + '-((values.depth-1)*'+indent+')]}% !important;' + 
                    'width:{[' + data[j].width.replace("%", "") + '-((values.depth-1)*'+indent+')]}% !important;' + 
                    (Ext.isEmpty(data[j].style) ? '' : data[j].style) + '" ' + idxStr +
                    '>{' + rendStr + '}</div>');                  
                } else {           
                    detailArr.push('<div class="touchtreegrid-list-content-cell ' + cssStr + '" style="' +
                    'min-width:' + data[j].width + ' !important;' + 
                    'max-width:' + data[j].width + ' !important;' + 
                    'width:' + data[j].width + ' !important;' + 
                    (Ext.isEmpty(data[j].style) ? '' : data[j].style) + '" ' + idxStr + 
                    '>{' + rendStr + '}</div>');
                }          

            }

            detailArr.push('</div>');  
            detail=detailArr.join('');    
        }   
        if (detail==='' && simpleList) {
            detailArr = [
            // webkit-box handled by  "display : inline-block;" in TouchTreeGrid.css 
            //   '<div style="display: -webkit-box;-webkit-box-orient: horizontal;">',
            ];

            for (j=0; j<data.length; j++) {

                // Substitute user-defined renderer string from Columns array if defined
                rendStr = ((!data[j].renderer) ? data[j].dataIndex : '[' + data[j].renderer + ']');

                // Add dataIndex attribute to this DIV if requested in Columns array (for purposes of trapping cell tap)
                idxStr = ((!data[j].addDataIndexToDiv) ? '' : ' dataIndex="' + data[j].dataIndex + '"');

                cssStr = (Ext.isEmpty(data[j].css)) ? '' : data[j].css;        

                detailArr.push('<div class="touchtreegrid-simplelist-cell ' + cssStr + '" style="' +
                'min-width:' + data[j].width + ' !important;' + 
                'max-width:' + data[j].width + ' !important;' + 
                'width:' + data[j].width + ' !important;' + 
                (Ext.isEmpty(data[j].style) ? '' : data[j].style) + '" ' + idxStr +
                '>{' + rendStr + '}</div>');
            }

            //   detailArr.push('</div>');  
            detail=detailArr.join('');    
        }   
        var content = me.setContentItemTpl(detail);    

    },

    updateStore: function(newStore, oldStore) {
        var me = this;

        var list = me.getList();
        var disableSel = me.getDisableSelection();
        var pressedCls = (disableSel ? '' : me.getPressedCls());  // Don't apply pressing class if selection disabled
        var selectedCls = me.getSelectedCls();
        var mode = me.getMode();
        var disclose = me.getOnItemDisclosure();
        var discloseProp = me.getDisclosureProperty();
        var itemHeight = me.getItemHeight();
        var variableHeights = me.getVariableHeights();
        var infinite = me.getInfinite();
        var useSimpleItems = me.getUseSimpleItems();

        // Added 6/28/2013
        if (newStore === "") {
            // Assume we are implementing dynamic grid and create temporary store to allow creation of List component
            newStore = Ext.create('Ext.data.Store', {fields: {"name" : "dynamic"}});
        }

        if (this.isObjectEmpty(list)) {

            list = Ext.create('Ext.dataview.List', {   
                disableSelection: disableSel,
                onItemDisclosure : disclose,
                disclosureProperty : discloseProp,  // 'disclose' for all rows (default), 'leaf' for leafs only
                itemHeight: itemHeight,
                variableHeights: variableHeights,
                store: newStore,
                masked: false,
                itemCls: 'x-touchtreegrid-item',
                pressedCls : pressedCls,
                selectedCls : selectedCls,
                useSimpleItems: useSimpleItems,
                infinite: infinite,
                mode: mode,
                height: '100%'
            });

            // Support application of width, minWidth, height, minHeight overrides from linked instance for Horizontal scrolling
            var height = me.getHeight(); // Horiz scrolling doesn't work with 100% for some reason so any pixel setting
            // larger than expected works.  Example: 1000 (not sure why)
            if (!Ext.isEmpty(height)) {list.setHeight(height);}
            var minHeight = me.getMinHeight();
            if (!Ext.isEmpty(minHeight)) {list.setMinHeight(minHeight);}
            var width = me.getWidth();
            if (!Ext.isEmpty(width)) {list.setWidth(width);}
            var minWidth = me.getMinWidth();
            if (!Ext.isEmpty(minWidth)) {list.setMinWidth(minWidth);}                                                              

            list.on('itemtap', me.onItemTap, me);

            var plugins = me.getListPlugins();
            if (!this.isObjectEmpty(plugins)) {
                list.setPlugins(plugins);
            }

            me.setList(list);

            if (!me.getListScrollable()) {
                list.setScrollable({disabled: true});  // false doesn't seem to work
            } else {
                list.setScrollable(me.getListScrollable());
            }

            var listItemId = me.getListItemId();
            if (listItemId !== '') {
                list.setItemId(listItemId);
            }

            // Update list with any additional configs defined in user-defined additionalListConfigs object
            // (this allows all configs supported by Ext.dataview.List component to be applied to TouchTreeGrid list
            // Note:  any duplicated configs already supported by TouchTreeGrid will overwrite those and could have 
            //        unexpected behaviour !!
            var addlConfigs = me.getAdditionalListConfigs();
            if (!me.isObjectEmpty(addlConfigs)) {
                for (cfg in addlConfigs) {
                    list.config[cfg] = addlConfigs[cfg];
                    list['_'+cfg] = addlConfigs[cfg];
                }
            }

            me.add(list);
        }
        else {
            list.setStore(newStore);
        }    

    },

    onItemTap: function(list, index, target, record, e) {
        /**
        * Called when an list item has been tapped
        * @param list: {Ext.List}  The subList the item is on
        * @param index: {Number} The id of the item tapped
        * @param target: {Ext.Element} The list item tapped
        * @param record: {Ext.data.Record} The record whichw as tapped
        * @param e: {Ext.event.Event} The event
        */

        var store = list.getStore(),
            node = store.getAt(index),
            disabledExpColl = this.getDisableExpandCollapse();

        if (this.getOnItemDisclosure() && !Ext.isEmpty(e.getTarget('div.x-list-disclosure'))) {
            return;  // Ref:  http://www.sencha.com/forum/showthread.php?261518-List-onItemDisclosure-ST-2.2
        }

        if (this.getSimpleList() || node.isLeaf()) {
            this.fireEvent('leafItemTap', this, list, index, target, record, e);

        } 
        else if (this.getSingleExpand() && !node.isExpanded()) {
            // If node collapsed, then expand this one and collapse all sibling nodes
            this.fireEvent('nodeItemTap', this, list, index, target, record, e);

            if (!disabledExpColl) {
                node.expand(false);
                var parent = node.parentNode;
                var children = parent.childNodes;
                for (var i=0; i<children.length; i++) {
                    if (children[i] !== node && children[i].isExpanded()) {
                        children[i].collapse();
                    }
                }
            }
        }
        else {
            this.fireEvent('nodeItemTap', this, list, index, target, record, e);  

            if (!disabledExpColl && node.isExpandable()) {
                var xPosition = list.getScrollable().getScroller().position.x;
                var yPosition = list.getScrollable().getScroller().position.y;

                if (node.isExpanded()) {
                    node.collapse();
                } else {
                    node.expand(false); 
                }

                list.getScrollable().getScroller().scrollTo(xPosition, yPosition, {duration: 0});
            }

        }
    },

    applyHeader: function(config) {
        if (this.getIncludeHeader()) {
            Ext.apply(config, {
                docked : 'top',
                cls    : 'touchtreegrid-header',
                itemId : 'touchtreegridheader'
            });

            return Ext.factory(config, Ext.Toolbar);
        }    
    },

    updateHeader: function(header) {
        var me = this;
        if (me.getIncludeHeader()) {
            me.insert(0, header);

            if (this.getColumnSorting()) {  // add tap event listener to header toolbar
                header.element.on('tap', me["handleColumnSort"], me, {});
            }
        }    
    },

    applyFooter: function(config) {
        var me = this;
        var footerDock = me.getFooterDock();
        var hideExpandCollapseBtns = me.getHideExpandCollapseBtns();
        var img = me.getLandscapeIcon();
        if (this.getIncludeFooter() && !this.getSimpleList()) {
            Ext.apply(config, {
                docked : footerDock,
                cls    : 'touchtreegrid-footer',
                itemId : 'touchtreegridbuttons',

                items: [
                {
                    xtype: 'label',
                    docked: 'right',
                    html: '',
                    itemId: 'touchtreegridlabel',
                    cls  : 'touchtreegrid-landscape-label',                       
                    style: 'color : white'
                },            
                {
                    xtype: 'image',
                    docked: 'right',
                    hidden: true,
                    itemId: 'touchtreegridicon',
                    cls: 'touchtreegrid-landscape-icon',
                    src: img
                },
                {
                    xtype: 'segmentedbutton',
                    itemId : 'touchtreegridsegmentedbuttons',
                    hidden: hideExpandCollapseBtns,
                    items: [
                    {
                        xtype: 'button',
                        itemId: 'touchtreegridexpand',
                        cls  : 'touchtreegrid-expand-collapse-buttons',
                        text: 'Expand',
                        listeners : {
                            tap: function (button, e, options) {
                                me.doExpandDepth(99);
                            }
                        }
                    },
                    {
                        xtype: 'button',
                        itemId: 'touchtreegridcollapse',
                        cls  : 'touchtreegrid-expand-collapse-buttons',
                        text: 'Collapse',
                        listeners : {
                            tap: function (button, e, options) {
                                me.doExpandDepth(0);
                            }
                        }
                    }
                    ]

                }]
            });

            return Ext.factory(config, Ext.Toolbar);
        }
    },

    doExpandDepth: function(depth, btn) {
        var list = this.getList(),
            store = list.getStore();

        /* Unpress Expand/Collapse buttons in event they were pressed */
        if (!Ext.isEmpty(btn)) {
            var btns  = this.down('#touchtreegridsegmentedbuttons');
            btns.setPressedButtons([]);
        }

        // Fire custom event for expand/collapse if specified
        var customEvent = this.getCustomExpCollapseEvent();
        if (customEvent !== '') {
            this.fireEvent(customEvent, {collapseLevel: depth, list: list, gridcont: this});
            return;
        }

        store.each(function(item, index, list) {item.collapse(true);});

        function expandDepth(node) {
            if (!node.isLeaf() && node.data.depth <depth) {
                node.expand(false);

                node.childNodes.forEach(expandDepth, this);
            }
        }
        store.each(expandDepth, this);

        // Added 8/19/2013
        var scroller = list.getScrollable().getScroller();
        scroller.scrollTo(0,1);  

    },

    doRefreshList: function(skipApplyDefaultCollapseLevel) {
        // Refreshes TPL in grid and in Header

        var me = this;

        var simpleList = me.getSimpleList();

        var list = me.getList();
        var disclose = me.getOnItemDisclosure();
        var colorArr = me.getCategDepthColorsArr();
        var categCssArr = me.getCategCssArr();
        var colorDepth = me.getCategDepthColors();
        var colorDepthButtons = me.getCategDepthColorButtons();
        var arrowWid = me.getArrowPctWidth(); // allow control over percent screen width that category arrow consumes (def = 4%)

        var itemTpl;

        // Customize TPL to change colors by category depth as defined in colorArr
        var colorStyle = (colorDepth ? ' style="background-color: {[this.depthColor(values)]} !important;"' : '');
        var categCss = '{[this.depthCategCss(values)]}';

        var tpl;
        if (!simpleList) {

            tpl = [
            '<tpl if="leaf">',
            '<div class="touchtreegrid-list-content">',
            me.getContentItemTpl(),
            '</div>', 
            '<tpl else>',
            '<div class="' + categCss + '" ' + colorStyle + '> ',
            me.getCategItemTpl(),
            '</div>',  
            '</tpl>'
            ].join('');

        } else {
            tpl = [
            //    '<div class="touchtreegrid-list-content">',
            me.getContentItemTpl()
            //   '</div>'
            ].join('');
        }

        var renderers = {};
        renderers.scope = me;
        renderers.isExpanded = function(values) {return values.expanded;};
        renderers.depthColor = function(values) {return (!colorArr[values.depth-1] ? 'white' : colorArr[values.depth-1]);};
        renderers.depthCategCss = function(values) {return (!categCssArr[values.depth-1] ? ' touchtreegrid-list-categ' : ' '+categCssArr[values.depth-1]);};
        renderers.formatNumbers = function(n, decPlaces, prefix, thouSeparator, decSeparator) {return me.formatNumbers(n, decPlaces, prefix, thouSeparator, decSeparator);};

        var customRenderers = me.getRenderers();
        for (var prop in customRenderers) {
            renderers[prop] = customRenderers[prop];
        }

        itemTpl = Ext.create('Ext.XTemplate', tpl, renderers);

        itemTpl.compile();

        list.setItemTpl(itemTpl);

        if (simpleList) list.refresh();

        /* Build Header TPL */
        var header = me.getHeader();
        var data = me.getColumns();

        var styleStr='', cssStr='';
        var headerStyle = Ext.isEmpty(me.getStyleHeaderRow()) ? '' : ' style="' + me.getStyleHeaderRow() + '"';
        var headerCss = Ext.isEmpty(me.getCssHeaderRow()) ? '' : ' class="' + me.getCssHeaderRow() + '"';

        var headerTpl = me.getHeaderTplOverride();
        if (headerTpl==='') {

            var headerTplArr = [
            '<div' + headerStyle + headerCss + '>'
            ];
            if (!simpleList) {
                // Include spacer width for category arrow
                headerTplArr.push('<p align="left" style="width:'+arrowWid+'%;min-width:'+arrowWid+'%;max-width:'+arrowWid+
                '%;white-space: nowrap;overflow:hidden;text-overflow:ellipsis;">&nbsp;</p>');
            }

            for (var j=0; j<data.length; j++) {

                // Use headerStyle if exists, else apply detail row style to category row
                if (data[j].headerStyle && data[j].headerStyle > '') {styleStr = data[j].headerStyle;}
                else if (data[j].style) {styleStr = data[j].style;}
                else {styleStr = '';}        

                // Use headerCss if exists, else apply detail row css to header row (if defined)
                if (!Ext.isEmpty(data[j].headerCss) && data[j].headerCss > '') {cssStr = data[j].headerCss;}
                else if (!Ext.isEmpty(data[j].css)) {cssStr = data[j].css;}
                else {cssStr = '';}        

                headerTplArr.push('<div class="touchtreegrid-header-cell ' + cssStr + 
                (!Ext.isEmpty(data[j].initSortCls) ? ' '+data[j].initSortCls : '') + // see comments in handleColumnSort()
                '" style="min-width:' + data[j].width +' !important;' +
                'max-width:'+data[j].width + ' !important; width:' + data[j].width + ' !important;' +
                styleStr + '" dataIndex="'+data[j].dataIndex+'">' + data[j].header + '</div>');               
            }
            headerTplArr.push('</div>');  

            // Wrap with spacer to accomodate for disclosure icon(lines up columns better)
            var headerTplArr2 = [];
            if (disclose) {
                headerTplArr2.push('<div class="touchtreegrid-disclose-spacer">');
                headerTplArr2 = headerTplArr2.concat(headerTplArr);
                headerTplArr2.push('</div>');  
            } else {
                headerTplArr2 = headerTplArr;
            }

            headerTpl=headerTplArr2.join('');    
        }
        if (this.getIncludeHeader()) {
            header.setHtml(headerTpl);
        }    

        if (me.getApplyDefaultCollapseLevel() && !skipApplyDefaultCollapseLevel && !simpleList) {
            // custom implementations can request not to change collapse levels when refreshing
            me.doExpandDepth(me.getDefaultCollapseLevel());
        }

        var btns = me.down('#touchtreegridbuttons');
        var customFooterItems = me.getCustomFooterItems();
        var includeCustomFooterItems = me.getIncludeCustomFooterItems();

        if (me.getIncludeFooter() && !simpleList && !me.isObjectEmpty(customFooterItems) && !Ext.isEmpty(btns) &&
        Ext.isEmpty(btns.down('#'+customFooterItems.itemId)) && includeCustomFooterItems) {
            btns.add(customFooterItems);
        }

        if (me.getIncludeFooter() && me.getIncludeFooterLevels() && !simpleList) {
            // Proceed to add expand/collapse levels  (horizontal scrolling toolbar LATER)

            // First get total depth of treestore
            var store = list.getStore();
            maxDepth=0;

            function doDrillDown(node) {
                if (!node.isLeaf()) {
                    maxDepth = ((node.data.depth>maxDepth) ? node.data.depth : maxDepth);

                    node.childNodes.forEach(doDrillDown, me);
                }
            }
            store.each(doDrillDown, me);   

            if (maxDepth>1 && !Ext.isEmpty(btns)) {
                // Remove button items 1+ if they exist

                var itms = btns.getItems();
                var itmsOrigLength = itms.items.length;
                var thisItemId, k;

                for (k = 2; k<10; k++) {  // blindly loop to delete up to 8 category level buttons with matching ItemId names
                    thisItem = btns.down('#touchtreegriddepth'+k.toString());
                    if (!Ext.isEmpty(thisItem)) {
                        btns.remove(thisItem, true);
                    }
                }

                var btnStyle = {};

                // Add buton for each additional level
                var newbtn;
                for (var i=2; i <= maxDepth; i++) {
                    if (colorDepth && colorDepthButtons) {
                        btnStyle = {'background' : (!colorArr[i-1] ? 'white' : colorArr[i-1]),
                        'color' : 'black'};
                    }
                    newbtn = {
                        xtype: 'button',
                        itemId: 'touchtreegriddepth'+i.toString(),
                        cls  : 'touchtreegrid-expand-collapse-buttons',
                        style : btnStyle,
                        depth : i,
                        text: i.toString(),
                        listeners : {tap: function (button, e, options) {me.doExpandDepth(button.config.depth, button);}}
                    };

                    btns.add(newbtn);
                }

            }
        }

    },

    formatNumbers: function(n, decPlaces, prefix, suffix, thouSeparator, decSeparator) {
        if (Ext.isEmpty(n)) {return n;};  // Don't format empty strings  =="" || !n || isNaN(n)
        decPlaces = (isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces);
        prefix = (prefix == undefined ? "" : prefix);   // Example pass "$" sign for currency
        suffix = (suffix == undefined ? "" : suffix);   // Example pass "%" sign for percents

        decSeparator = (decSeparator == undefined ? "." : decSeparator);
        thouSeparator = (thouSeparator == undefined ? "," : thouSeparator);
        sign = (n < 0 ? "-" : "");
        i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "";
        j = (((j = i.length) > 3) ? (j % 3) : 0);
        return prefix + sign + (j ? i.substr(0, j) + thouSeparator : "") + 
        i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + 
        (decPlaces ? decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) : "") + suffix;
    },

    isObjectEmpty: function(myObj) {
        for(var key in myObj) {
            if (myObj.hasOwnProperty(key)) {
                return false;
            }
        }
        return true;
    },

    handleColumnSort: function(e,t) {
        // Refer to updateHeader() for code to add tap listener on header toolbar
        //  header.element.on('tap', me["handleColumnSort"], me, {});

        var me        = this,
            list      = me.getList(),
            grouped   = list.getGrouped(),
            columns   = me.getColumns(),
            cNum      = columns.length,
            store     = list.getStore(),
            el        = Ext.get(t),
            headerEl  = me.down('#touchtreegridheader').element,
            dataIndex = el.getAttribute('dataIndex'),
            sorters   = store.getSorters(),
            asc       = 'x-grid-sort-asc',
            desc      = 'x-grid-sort-desc',
            myEvent   = me.getCustomColumnSortEvent(),
            columnsUpdated = false,
            c, i, colIndex, column, columnsUpd=[], colEl, sorter, dir,
            grouper, grouperSortProperty, grouperDirection, grouperProperty, mySortIdx, newDirCls;

        if (!dataIndex) return;  //Included in event of tap on extra toolbar space at far right

        for (c=0; c < cNum; c++) {
            column = columns[c];
            if (column.dataIndex === dataIndex) {break;}
        }
        colIndex = c;

        if (myEvent !== '') {
            // Custom event specified to be fired in lieu of default processing
            me.fireEvent(myEvent,{me: me, e: e, t: t,  el: el, headerEl: headerEl,
            dataIndex: dataIndex, column: column});
            return;    
        }

        if (!column.sortable) return;

        grouper = store.getGrouper();
        if (!Ext.isEmpty(grouper)) {
            grouperProperty = grouper.getProperty();
            grouperSortProperty = grouper.getSortProperty();
            grouperDirection = Ext.isEmpty(grouper.getDirection()) ? 'ASC' : grouper.getDirection();
        }

        // sorters array may be prefilled with grouper-related sorts, last index is one for my current column sort
        mySortIdx = sorters.length-1;
        sorter    = sorters[mySortIdx];
        dir       = sorter ? sorter.getDirection() : 'ASC';    
        newDirCls = (dir === 'DESC' ? desc : asc);

        // Sort items within grouper if defined
        if (Ext.isEmpty(grouper)){
            store.sort([{property: dataIndex, direction: dir === 'DESC' ? 'ASC' : 'DESC'}]);    
        } else {
            store.sort([{property: grouperSortProperty, direction: grouperDirection},
            {property: dataIndex, direction: dir === 'DESC' ? 'ASC' : 'DESC'}]);
        }    

        // Copy columns[], update the copy then restore so that updateColumns() method isn't 
        // invoked via updateColumns() method until all updates are complete
        columnsUpd = Ext.clone(columns); 

        // Remove any prior sort indicators 
        for (c=0; c < cNum; c++) {
            colEl = Ext.get(headerEl.down('div.touchtreegrid-header-cell[dataIndex=' + columns[c].dataIndex + ']'));
            if (!me.isObjectEmpty(colEl)) {
                colEl.removeCls(asc);
                colEl.removeCls(desc);
            } 

            // Process column shading if sorted properties are defined in columns[] array:
            // => headerStyleSorted, categStyleSorted, styleSorted
            if (c===colIndex) {
                // Save Original styles and update with sorted styles  (STYLE will override CSS if defined)
                if (!Ext.isEmpty(columnsUpd[c].headerCssSorted) && !Ext.isEmpty(columnsUpd[c].headerCss)) {
                    if (Ext.isEmpty(columnsUpd[c].headerCssOrig)) {
                        columnsUpd[c].headerCssOrig = columnsUpd[c].headerCss;
                    }
                    if (columnsUpd[c].headerCss !== columnsUpd[c].headerCssSorted) {
                        columnsUpd[c].headerCss = columnsUpd[c].headerCssSorted;
                        columnsUpd[c].initSortCls = newDirCls;   // Store new CLS to array so that doRefreshList() will render sort arrow correctly when redrawing         
                        columnsUpdated = true;
                    }                
                }        
                if (!Ext.isEmpty(columnsUpd[c].headerStyleSorted) && !Ext.isEmpty(columnsUpd[c].headerStyle)) {
                    if (Ext.isEmpty(columnsUpd[c].headerStyleOrig)) {
                        columnsUpd[c].headerStyleOrig = columnsUpd[c].headerStyle;
                    }
                    if (columnsUpd[c].headerStyle !== columnsUpd[c].headerStyleSorted) {
                        columnsUpd[c].headerStyle = columnsUpd[c].headerStyleSorted;
                        columnsUpd[c].initSortCls = newDirCls;   // Store new CLS to array so that doRefreshList() will render sort arrow correctly when redrawing         
                        columnsUpdated = true;
                    }                
                }

                if (!Ext.isEmpty(columnsUpd[c].categCssSorted) && !Ext.isEmpty(columnsUpd[c].categCss)) {
                    if (Ext.isEmpty(columnsUpd[c].categCssOrig)) {
                        columnsUpd[c].categCssOrig = columnsUpd[c].categCss;
                    }
                    if (columnsUpd[c].categCss !== columnsUpd[c].categCssSorted) {
                        columnsUpd[c].categCss = columnsUpd[c].categCssSorted;
                        columnsUpdated = true;
                    }                
                } 
                if (!Ext.isEmpty(columnsUpd[c].categStyleSorted) && !Ext.isEmpty(columnsUpd[c].categStyle)) {
                    if (Ext.isEmpty(columnsUpd[c].categStyleOrig)) {
                        columnsUpd[c].categStyleOrig = columnsUpd[c].categStyle;
                    }
                    if (columnsUpd[c].categStyle !== columnsUpd[c].categStyleSorted) {
                        columnsUpd[c].categStyle = columnsUpd[c].categStyleSorted;
                        columnsUpdated = true;
                    }                
                }       

                if (!Ext.isEmpty(columnsUpd[c].cssSorted) && !Ext.isEmpty(columnsUpd[c].css)) {
                    if (Ext.isEmpty(columnsUpd[c].cssOrig)) {
                        columnsUpd[c].cssOrig = columnsUpd[c].css;
                    }
                    if (columnsUpd[c].css !== columnsUpd[c].cssSorted) {
                        columnsUpd[c].css = columnsUpd[c].cssSorted;
                        columnsUpdated = true;
                    }                
                }
                if (!Ext.isEmpty(columnsUpd[c].styleSorted) && !Ext.isEmpty(columnsUpd[c].style)) {
                    if (Ext.isEmpty(columnsUpd[c].styleOrig)) {
                        columnsUpd[c].styleOrig = columnsUpd[c].style;
                    }
                    if (columnsUpd[c].style !== columnsUpd[c].styleSorted) {
                        columnsUpd[c].style = columnsUpd[c].styleSorted;
                        columnsUpdated = true;
                    }                
                }

            } else {
                // Restore Original styles for non-sorted columnsUpd
                if (!Ext.isEmpty(columnsUpd[c].headerCssOrig) && !Ext.isEmpty(columnsUpd[c].headerCss)) {
                    if (columnsUpd[c].headerCss !== columnsUpd[c].headerCssOrig) {
                        columnsUpd[c].headerCss = columnsUpd[c].headerCssOrig;
                        columnsUpd[c].initSortCls = '';      // reset                       
                        columnsUpdated = true;
                    }                
                }        
                if (!Ext.isEmpty(columnsUpd[c].headerStyleOrig) && !Ext.isEmpty(columnsUpd[c].headerStyle)) {
                    if (columnsUpd[c].headerStyle !== columnsUpd[c].headerStyleOrig) {
                        columnsUpd[c].headerStyle = columnsUpd[c].headerStyleOrig;
                        columnsUpd[c].initSortCls = '';      // reset                       
                        columnsUpdated = true;
                    }                
                }

                if (!Ext.isEmpty(columnsUpd[c].categCssOrig) && !Ext.isEmpty(columnsUpd[c].categCss)) {
                    if (columnsUpd[c].categCss !== columnsUpd[c].categCssOrig) {
                        columnsUpd[c].categCss = columnsUpd[c].categCssOrig;
                        columnsUpdated = true;
                    }                
                }   
                if (!Ext.isEmpty(columnsUpd[c].categStyleOrig) && !Ext.isEmpty(columnsUpd[c].categStyle)) {
                    if (columnsUpd[c].categStyle !== columnsUpd[c].categStyleOrig) {
                        columnsUpd[c].categStyle = columnsUpd[c].categStyleOrig;
                        columnsUpdated = true;
                    }                
                }   

                if (!Ext.isEmpty(columnsUpd[c].cssOrig) && !Ext.isEmpty(columnsUpd[c].css)) {
                    if (columnsUpd[c].css !== columnsUpd[c].cssOrig) {
                        columnsUpd[c].css = columnsUpd[c].cssOrig;
                        columnsUpdated = true;
                    }                
                }        
                if (!Ext.isEmpty(columnsUpd[c].styleOrig) && !Ext.isEmpty(columnsUpd[c].style)) {
                    if (columnsUpd[c].style !== columnsUpd[c].styleOrig) {
                        columnsUpd[c].style = columnsUpd[c].styleOrig;
                        columnsUpdated = true;
                    }                
                }        
            }
        }

        if (columnsUpdated) {
            me.setColumns(columnsUpd);  
            me.doRefreshList();
        }
        else {list.refresh();}

        // Apply sort indicator to tapped column  (need this after doRefreshList() called .. but also handled in doRefreshList do to race conditioons)
        var newEl = el.addCls(newDirCls);  

        // Added 10/3/13
        var linkedGridsArr = me.prepLinkedGridsArr();
        if (linkedGridsArr.length > 0) {
            // Remove any existing sort indicators and styling for linked grids
            for (i=0; i<linkedGridsArr.length; i++) {
                linkedGridsArr[i].item.suspendEvents();  // item updated in onScroll()
            }    

            for (i=0; i<linkedGridsArr.length; i++) {
                linkedGridsArr[i].item.removeColumnSorts();
            }   

            for (i=0; i<linkedGridsArr.length; i++) {
                linkedGridsArr[i].item.resumeEvents(true);
            }   
        }

    },

    updateFooter: function(footer) {
        if (this.getIncludeFooter() && !this.getSimpleList()) {
            this.insert(0, footer);
        }
    },

    removeColumnSorts: function() {
        // Added 10/3/13

        // Called to clear all header and column sort-related CLS/Styles.  
        // Introduced to support column sorting across freeze column panels.
        var
        me        = this, 
        headerEl  = me.down('#touchtreegridheader').element,
        columns   = me.getColumns(),
        cNum      = columns.length,
        list      = me.getList(),  
        asc       = 'x-grid-sort-asc',
        desc      = 'x-grid-sort-desc',    
        c, colEl, columnsUpdated;

        var columnsUpd = Ext.clone(columns); 

        for (c=0; c < cNum; c++) {
            colEl = Ext.get(headerEl.down('div.touchtreegrid-header-cell[dataIndex=' + columns[c].dataIndex + ']'));
            if (!me.isObjectEmpty(colEl)) {
                colEl.removeCls(asc);
                colEl.removeCls(desc);
            } 

            // Restore Original styles for non-sorted columnsUpd
            if (!Ext.isEmpty(columnsUpd[c].headerCssOrig) && !Ext.isEmpty(columnsUpd[c].headerCss)) {
                if (columnsUpd[c].headerCss !== columnsUpd[c].headerCssOrig) {
                    columnsUpd[c].headerCss = columnsUpd[c].headerCssOrig;
                    columnsUpd[c].initSortCls = '';      // reset                       
                    columnsUpdated = true;
                }                
            }        
            if (!Ext.isEmpty(columnsUpd[c].headerStyleOrig) && !Ext.isEmpty(columnsUpd[c].headerStyle)) {
                if (columnsUpd[c].headerStyle !== columnsUpd[c].headerStyleOrig) {
                    columnsUpd[c].headerStyle = columnsUpd[c].headerStyleOrig;
                    columnsUpd[c].initSortCls = '';      // reset                       
                    columnsUpdated = true;
                }                
            }

            if (!Ext.isEmpty(columnsUpd[c].categCssOrig) && !Ext.isEmpty(columnsUpd[c].categCss)) {
                if (columnsUpd[c].categCss !== columnsUpd[c].categCssOrig) {
                    columnsUpd[c].categCss = columnsUpd[c].categCssOrig;
                    columnsUpdated = true;
                }                
            }   
            if (!Ext.isEmpty(columnsUpd[c].categStyleOrig) && !Ext.isEmpty(columnsUpd[c].categStyle)) {
                if (columnsUpd[c].categStyle !== columnsUpd[c].categStyleOrig) {
                    columnsUpd[c].categStyle = columnsUpd[c].categStyleOrig;
                    columnsUpdated = true;
                }                
            }   

            if (!Ext.isEmpty(columnsUpd[c].cssOrig) && !Ext.isEmpty(columnsUpd[c].css)) {
                if (columnsUpd[c].css !== columnsUpd[c].cssOrig) {
                    columnsUpd[c].css = columnsUpd[c].cssOrig;
                    columnsUpdated = true;
                }                
            }        
            if (!Ext.isEmpty(columnsUpd[c].styleOrig) && !Ext.isEmpty(columnsUpd[c].style)) {
                if (columnsUpd[c].style !== columnsUpd[c].styleOrig) {
                    columnsUpd[c].style = columnsUpd[c].styleOrig;
                    columnsUpdated = true;
                }                
            }        
        }

        if (columnsUpdated) {
            me.setColumns(columnsUpd);  
            me.doRefreshList();
        }
        else {list.refresh();}

    },

    onScroll: function(scroller, x, y) {
        // Scroll all linked grids
        var me = this, i, linkedGridsArr;

        linkedGridsArr = me.prepLinkedGridsArr();
        if (linkedGridsArr.length === 0) {return;}

        scroller.suspendEvents();
        for (i=0; i<linkedGridsArr.length; i++) {
            //    linkedGridsArr[i].scroller.suspendEvents();
        }    

        for (i=0; i<linkedGridsArr.length; i++) {
            otherX = linkedGridsArr[i].scroller.position.x;
            linkedGridsArr[i].scroller.scrollTo(otherX,y);
        }   

        scroller.resumeEvents(true);
        for (i=0; i<linkedGridsArr.length; i++) {
            //    linkedGridsArr[i].scroller.resumeEvents(true);
        }   

    },

    prepLinkedGridsArr: function(skipRecurse) {
        // Adds object references to linkdedGridsArr from itemId's of linked grids for faster scrolling and sorting performance across the grids
        var me = this, i, listItemId, otherList, otherScroller, parcont, linkedGridsArr, gridcont;

        linkedGridsArr = me.getLinkedGridsArr();
        if (linkedGridsArr.length === 0) {return [];}

        parcont = me.up('#'+me.getLinkedGridsParentItemId());
        if (Ext.isEmpty(parcont)) {
            console.log(me.getLinkedGridsParentItemId() + ' not found !');
            return [];
        }

        if (Ext.isEmpty(linkedGridsArr[0].scroller)) {
            // One-time update of linked scroller and gridcont objects for current linked instance of TouchTreeGrid
            for (i=0; i<linkedGridsArr.length; i++) {
                gridcont = parcont.down('#'+linkedGridsArr[i].itemId);
                if (Ext.isEmpty(gridcont)) {
                    console.log('Unable to find ' + linkedGridsArr[i].itemId);
                    return;
                }
                listItemId = gridcont.getListItemId();
                otherList = gridcont.down('#'+listItemId);
                otherScroller = otherList.getScrollable().getScroller();
                linkedGridsArr[i].item = gridcont;
                linkedGridsArr[i].scroller = otherScroller;

                // Similarly update each linked grid
                if (!skipRecurse) {
                    gridcont.prepLinkedGridsArr(true);
                }
            }
            me.setLinkedGridsArr(linkedGridsArr);    
        }

        return linkedGridsArr;
    },

    replaceIsVisible: function() {
        // setRootVisible to true that the root node is Expanded
        this.getList().getStore().setRootVisible(true);
        // replace isSvisble function to hide root (which is now true) and keep all childsnodes arcordingly to their expanded value
        this.getList().getStore().isVisible = function (node) {
            var parent = node.parentNode;
            if (node.isRoot()) {
                return false
            }
            if (!this.getRecursive() && parent !== this.getNode()) {
                return false;
            }

            while (parent) {
                if (!parent.isExpanded() && !parent.isRoot()) {
                    return false;
                }

                //we need to check this because for a nodestore the node is not likely to be the root
                //so we stop going up the chain when we hit the original node as we don't care about any
                //ancestors above the configured node
                if (parent === this.getNode()) {
                    break;
                }

                parent = parent.parentNode;
            }
            return true;
        }
    }
});

I hope you can give me any hint if i had done something wrong, or you may want to add the feature to your plugin. It is up to you.

With best Regards, Martin Heß

p5hema2 commented 10 years ago

p.s. your plugin is working fine with the exaplestores. you may notice that i have changed the classnames...

swluken commented 10 years ago

Hi, it seems that url: 'http://www.json-generator.com/j/bPBVAqubvS?indent=4' is returning an array and not an object? I see your treestore has rootProperty: 'items', so I would expect you to receive an object similar to this:

{items: <= your data is missing this and closing brace below [ { text: "Today", expanded: true, items: [ { text: "MowGrass1", items: [ { text: "MowGrass2", items: [ { text: "MowGrass3", items: [ { text: "MowGrass4", leaf: true }, { text: "BuyGroceries", leaf: true }, { text: "WatchGame", leaf: true } ] }, { text: "BuyGroceries", leaf: true }, { text: "WatchGame", leaf: true } ] }, { text: "BuyGroceries", leaf: true }, { text: "WatchGame", leaf: true } ] }, { text: "BuyGroceries", leaf: true }, { text: "WatchGame", leaf: true } ] }, { text: "Tomorrow", items: [ { text: "Frisbee", leaf: true }, { text: "Cookout", leaf: true } ] } ] }

Look at .\TouchTreeGrid-master\TouchTreeGrid_Advanced_22\data\treegrid.json for sample format that works without root node (Project Example). In this case ProjectsStore doesn't specify rootProperty because 'children' is the default.

I didn't test my theory with your data, but I've implemented tons of examples in this way that work without displaying root node.

Hope this helps, Steve

p5hema2 commented 10 years ago

I'll try it today at work.