1. #1
    Sencha User
    Join Date
    Jun 2011
    Posts
    17
    Vote Rating
    0
    trvd1707 is on a distinguished road

      0  

    Default Multigrouping in ExtJS 3.2.1

    Multigrouping in ExtJS 3.2.1


    Hi,

    I found this code on this forum, but it had some problems when I tried to use. I made some changes to fix it to work when the group field is a date and when the group field is boolean. The changes were done just in the multiGroupingView, in the doRender function.

    Here is the fixed code:
    Code:
    /**
     * @author chander, adapted by SIDGEY
     * Changes made by Teresa Van Dusen: groups by date and by boolean values
     */
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////
     //------------------------------------- MULTI GROUPING STORE ----------------------------------------------------------------
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////
    Ext.ux.MultiGroupingStore = Ext.extend(Ext.data.GroupingStore, {
        constructor: function(config){Ext.ux.MultiGroupingStore.superclass.constructor.apply(this, arguments);},
        sortInfo: [],
        sort: function(field, dir){
            var f = [];
            if (Ext.isArray(field)) {for (var i = 0, len = field.length; i < len; ++i) {f.push(this.fields.get(field[i]));}} 
            else {f.push(this.fields.get(field));}
            if (f.length < 1) {return false;}
            if (!dir) {
                if (this.sortInfo && this.sortInfo.length > 0 && this.sortInfo[0].field == f[0].name)
                {
                    // toggle sort direction
                    dir = (this.sortToggle[f[0].name] || "ASC").toggle("ASC", "DESC");
                }
                else
                    dir = f[0].sortDir;
            }
            var st = (this.sortToggle) ? this.sortToggle[f[0].name] : null;
            var si = (this.sortInfo) ? this.sortInfo : null;
            this.sortToggle[f[0].name] = dir;
            this.sortInfo = [];
            for (i=0, len=f.length; i < len; ++i) {
                this.sortInfo.push({field: f[i].name,direction: dir});
            }
            if (!this.remoteSort) {
                this.applySort();
                this.fireEvent("datachanged", this);
            } 
            else {
                if (!this.load(this.lastOptions)){
                    if (st){this.sortToggle[f[0].name] = st;}
                    if (si){this.sortInfo = si;}
                }
            }
            return true;
        },
        setDefaultSort: function (field, dir){
            dir = dir ? dir.toUpperCase() : "ASC";
            this.sortInfo = [];
            if (!Ext.isArray(field)){this.sortInfo.push({field: field, direction: dir});}
            else {
                for (var i = 0, len = field.length; i < len; ++i) {
                    this.sortInfo.push({field: field[i].field,direction: dir});
                    this.sortToggle[field[i]] = dir;
                }
            }
        },
        groupBy: function (field, forceRegroup){
            if (!forceRegroup && this.groupField == field)
                return; // already grouped by this field
            if (this.groupField)
            {
                for (var z = 0; z < this.groupField.length; z++)
                {
                    if (field == this.groupField[z])
                        return;
                }
                this.groupField.push(field);
            }
            else {this.groupField = [field];}
            if (this.remoteGroup) {
                if (!this.baseParams) {this.baseParams = {};}
                this.baseParams['groupBy'] = field;
            }
            if (this.groupOnSort) {this.sort(field); return;}
            if (this.remoteGroup) { this.reload(); }
            else {
                var si = this.sortInfo || [];
                if (si.field != field) {this.applySort();}
                else { this.sortData(field);}
                this.fireEvent('datachanged', this);
            }
        },
        applySort: function (){
            var si = this.sortInfo;
            if (si && si.length > 0 && !this.remoteSort) {this.sortData(si, si[0].direction); }
            if (!this.groupOnSort && !this.remoteGroup) {
                var gs = this.getGroupState();
                if (gs && gs != this.sortInfo) {this.sortData(this.groupField);}
            }
        },
        getGroupState: function (){
            return this.groupOnSort && this.groupField !== false ? (this.sortInfo ? this.sortInfo : undefined) : this.groupField;
        },
        sortData: function (flist, direction){
            direction = direction || 'ASC';
            var st = [];
            var o;
            for (var i = 0, len = flist.length; i < len; ++i) {
                o = flist[i];
                st.push(this.fields.get(o.field ? o.field : o).sortType);
            }
            var fn = function (r1, r2){
                var v1 = [];
                var v2 = [];
                var len = flist.length;
                var o;
                var name;
                for (i = 0; i < len; ++i) {
                    o = flist[i];
                    name = o.field ? o.field : o;
                    v1.push(st[i](r1.data[name]));
                    v2.push(st[i](r2.data[name]));
                }
                var result=0;
                for (i = 0; i < len; ++i) {
                    result = v1[i] > v2[i] ? 1 : (v1[i] < v2[i] ? -1 : 0);
                    if (result !== 0){return result;}
                }
                return result; // if it gets here, that means all fields are equal
            };
            this.data.sort(direction, fn);
            if (this.snapshot && this.snapshot != this.data) {this.snapshot.sort(direction, fn);}
        }
    });
    
    
    Ext.ux.MultiGroupingView = Ext.extend(Ext.grid.GroupingView, {
        constructor: function(config){
            Ext.ux.MultiGroupingView.superclass.constructor.apply(this, arguments);
            // Added so we can clear cached rows each time the view is refreshed
            this.on("beforerefresh", function() {
                if (this.rowsCache)
                    delete rowsCache;
            }, this);
        },
        /* updated version of the updateGroupWidths from GroupingView:
         * improve performance by keeping value of this.el.dom.offsetWidth
         * in member of this class.
         */
        offsetWidth: 0,
        updateGroupWidths : function(){
            if(!this.enableGrouping || !this.hasRows()){
                return;
            }
            if (!this.offsetWidth)
                this.offsetWidth = this.el.dom.offsetWidth;
            var tw = Math.max(this.cm.getTotalWidth(),
            this.offsetWidth-this.getScrollOffset()) +'px';
            var gs = this.getGroups();
            for(var i = 0, len = gs.length; i < len; i++){
                gs[i].firstChild.style.width = tw;
            }
        },
        /* updated version of GridView::syncHeaderScroll */
        headerScrollSynced: false,
        syncHeaderScroll : function(){
           // if (this.headerScrollSynced)
           //     return;
            this.headerScrollSynced = true;
            var mb = this.scroller.dom;
            this.innerHd.scrollLeft = mb.scrollLeft;
            this.innerHd.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore)
        },
    
    
        get_column_by_id: function(id)
        {
            for (i in this.cm.lookup)
            {
                if (this.cm.lookup[i].dataIndex == id)
                    return this.cm.lookup[i];
            }
            return null;
        },
        getGroups: function()
        {
            return Ext.DomQuery.select("div.x-grid-group", this.mainBody.dom);
        }
        ,displayEmptyFields: false
        ,displayFieldSeperator: ', '
        ,renderRows: function(){
            var groupField = this.getGroupField();
            var eg = !!groupField;
            // if they turned off grouping and the last grouped field is hidden
            if (this.hideGroupedColumn) {
                var colIndexes = [];
                for (var i = 0, len = groupField.length; i < len; ++i) {
                    var cidx=this.cm.findColumnIndex(groupField[i]);
                    if(cidx>=0){colIndexes.push(cidx);}
                }
                if (!eg && this.lastGroupField !== undefined) {
                    this.mainBody.update('');
                    for (var i = 0, len = this.lastGroupField.length; i < len; ++i) {
                        var cidx=this.cm.findColumnIndex(this.lastGroupField[i]);
                        if(cidx>=0){this.cm.setHidden(cidx, false);}
                    }
                    delete this.lastGroupField;
                    delete this.lgflen;
                }
                else if (eg && colIndexes.length > 0 && this.lastGroupField === undefined) {
                    this.lastGroupField = groupField;
                    this.lgflen = groupField.length;
                    for (var i = 0, len = colIndexes.length; i < len; ++i)
                        this.cm.setHidden(colIndexes[i], true);
                }
                else if (eg && this.lastGroupField !== undefined &&
                    (groupField !== this.lastGroupField || this.lgflen != this.lastGroupField.length))
                {
                    this.mainBody.update('');
                    for (var i = 0, len = this.lastGroupField.length; i < len; ++i) {
                        var cidx=this.cm.findColumnIndex(this.lastGroupField[i]);
                        if(cidx>=0){this.cm.setHidden(cidx, false);}
                    }
                    this.lastGroupField = groupField;
                    this.lgflen = groupField.length;
                    for (var i = 0, len = colIndexes.length; i < len; ++i) {
                        this.cm.setHidden(colIndexes[i], true);
                    }
                }
            }
            return Ext.ux.MultiGroupingView.superclass.renderRows.apply(this, arguments);
        }
        ,
        // this collection keeps a fast reference for group memberships for each record
        // it is not kept in the record since it would be destroyed during edit
        // it is used to do a fast update of summaries
        record_memberships: []
       /** This sets up the toolbar for the grid based on what is grouped
        * It also iterates over all the rows and figures out where each group should appeaer
        * The store at this point is already stored based on the groups.
        */
        ,doRender: function(cs, rs, ds, startRow, colCount, stripe){
            var ss = this.grid.getTopToolbar();
            if (rs.length < 1) {return '';}
            var groupField = this.getGroupField();
            var gfLen = groupField.length;
            for (var i = 0; i < cs.length; i++)
                cs[i].style = this.getColumnStyle(i, false);
    
    
            ss.removeAll();
            // Remove all entries alreay in the toolbar
            //for (var hh = 0; hh < ss.items.length; hh++)
            //    Ext.removeNode(Ext.getDom(ss.items.itemAt(hh).id));
    
    
            if (gfLen==0)
                ss.addItem(new Ext.Toolbar.TextItem("Drop Columns Here To Group"));
            else {
                // Add back all entries to toolbar from GroupField[]    
                ss.addItem(new Ext.Toolbar.TextItem("Grouped By:"));
                for (var gfi = 0; gfi < gfLen; gfi++) {
                    var t = groupField[gfi];
                    if (gfi>=0) {
                        ss.addItem(new Ext.Toolbar.Separator());
                        var b = new Ext.Toolbar.Button({
                            text: this.get_column_by_id(t).header
                        });
                        b.fieldName = t;
                        ss.addItem(b);
                    }
                }
            }
            ss.doLayout();
            
            this.enableGrouping = !!groupField;
            if (!this.enableGrouping || this.isUpdating)
                return Ext.grid.GroupingView.superclass.doRender.apply(this, arguments);
    
    
            var gstyle = 'width:' + this.getTotalWidth() + ';';
            var gidPrefix = this.grid.getGridEl().id;
            var groups = [], curGroup, i, len, gid;
            var lastvalues = [];
            var added = 0;
            var currGroups = [];
    
    
            // Create a specific style
            var st = Ext.get(gidPrefix+"-style");
            if(st)
                st.remove();
            var html_code =
                "div#" + gidPrefix +
                " div.x-grid3-row {padding-left:" + (gfLen*12) + "px}" +
                "div#" + gidPrefix + " div.x-grid3-header {padding-left:" + (gfLen*12) + "px}";
            Ext.getDoc().child("head").createChild({
                tag: 'style',
                id: gidPrefix + "-style",
                html: html_code
            });
            // traverse all rows in grid
            for (var i = 0, len = rs.length; i < len; i++) {
                added = 0;
                var rowIndex = startRow + i;
                var r = rs[i];
                var differ = 0;
                var gvalue = [];
                var fieldName;
                var fieldLabel;
                var grpFieldNames = [];
                var grpFieldLabels = [];
                var v;
                var changed = 0;
                var addGroup = [];
                var member_of_groups = [];
                this.record_memberships[r.id] = member_of_groups;
                // check group fields to see if we have a different group
                for (var j = 0; j < gfLen; j++) {
                    fieldName = groupField[j];
                    fieldLabel = this.get_column_by_id(fieldName).header;
                    v = r.data[fieldName];
                    if ((v && typeof v != 'boolean') || typeof v == 'boolean') {
                        if (i == 0) {
                            // First record always starts a new group
                            addGroup.push({idx:j,dataIndex:fieldName,header:fieldLabel,value:v});
                            lastvalues[j] = v;
                            gvalue.push(v);
                            grpFieldNames.push(fieldName);
                            grpFieldLabels.push(fieldLabel + ': ' + v);
                        } 
                        else {
                            if ( (!(v instanceof Date) && lastvalues[j]!== v)&& typeof v !='boolean'
                                    ||( v instanceof Date && (lastvalues[j]-v)!=0)) {
                                // This record is not in same group as previous one
                               addGroup.push({idx:j,dataIndex:fieldName,header:fieldLabel,value:v});
                               lastvalues[j] = v;
                               changed = 1;
                               gvalue.push(v);
                               grpFieldNames.push(fieldName);
                               grpFieldLabels.push(fieldLabel + ': ' + v);
                            } else if (typeof v == 'boolean' &&  typeof lastvalues[j]== 'boolean' && ((lastvalues[j] && !v) || (!lastvalues[j]&& v))){
                                addGroup.push({idx:j,dataIndex:fieldName,header:fieldLabel,value:v});
                                lastvalues[j] = v;
                                changed = 1;
                                gvalue.push(v);
                                grpFieldNames.push(fieldName);
                                grpFieldLabels.push(fieldLabel + ': ' + v);
                                
                            }else{
                                if (gfLen-1 == j && changed != 1)
                                {
                                    // This row is in all the same groups to the previous group
                                    curGroup.rs.push(r);
                                    member_of_groups.push(curGroup);
                                }
                                else if (changed == 1) {
                                    // This group has changed because an earlier group changed.
                                    addGroup.push({idx:j,dataIndex:fieldName,header:fieldLabel,value:v});
                                    gvalue.push(v);
                                    grpFieldNames.push(fieldName);
                                    grpFieldLabels.push(fieldLabel + ': ' + v);
                                } 
                                else if(j<gfLen-1) {
                                    var parent_group = currGroups[fieldName];
                                    // This is a parent group, and this record is part of this parent so add it
                                    if (parent_group)
                                    {
                                        parent_group.rs.push(r);
                                        member_of_groups.push(parent_group);
                                    }
                                }
                            }
                        }
                    } 
                    else { 
                        if (this.displayEmptyFields) {
                            addGroup.push({idx:j,dataIndex:fieldName,header:fieldLabel,value:this.emptyGroupText||'(none)'});
                            grpFieldNames.push(fieldName);
                            grpFieldLabels.push(fieldLabel + ': ');
                        }
                    }  
                } // end of "for j"
    
    
                // build current group record
                for (var k = 0; k < addGroup.length; k++) {
                    var gp = addGroup[k];
                    g = gp.dataIndex;
                    var glbl = addGroup[k].header;
                    N = this.cm.findColumnIndex(g);
                    var F = this.cm.config[N];
                    var B = F.groupRenderer||F.renderer;
                    var S = this.showGroupName ? (F.groupName || F.header) + ": " : "";
                    V = this.getGroup(gp.value, r, B, i, N, ds);
                    gid = gidPrefix + '-gp-' + gp.dataIndex + '-' +
                        Ext.util.Format.htmlEncode(gp.value);
    
    
                    // if state is defined use it, however state is in terms of expanded
                    // so negate it, otherwise use the default.
                    var isCollapsed = typeof this.state[gid] !== 'undefined' ?
                        !this.state[gid] : this.startCollapsed;
    
    
                    var gcls = isCollapsed ? 'x-grid-group-collapsed' : '';
                    curGroup = {
                        group: gp.dataIndex,
                        gvalue: V,
                        key: r.data[gp.dataIndex], // current grouping key
                        text: gp.header,
                        groupId: gid,
                        group_level: gp.idx,
                        startRow: rowIndex,
                        rs: [r],
                        cls: gcls,
                        style: gstyle + 'padding-left:' + (gp.idx * 12) + 'px;'
                    };
                    currGroups[gp.dataIndex] = curGroup;
                    groups.push(curGroup);
                    r._groupId = gid; // Associate this row to a group
                    member_of_groups.push(curGroup);
                    if (typeof this.groups == "undefined")
                        this.groups = new Array();
                    this.groups.push(curGroup);
                } // end of "for k"
            } // end of "for i"
    
    
            var buf = [];
            var parents_queued = [];
            var queue_count = 0;
            for (var ilen = 0, len = groups.length; ilen < len; ilen++) {
                var g = groups[ilen];
                var next_group = groups[ilen + 1];
                var cur_level = g.group_level;
                var next_level = next_group == null ? -1 : next_group.group_level;
                var leaf = g.group == groupField[gfLen - 1] 
                this.doGroupStart(buf, g, cs, ds, colCount);
                if (g.rs.length != 0 && leaf)
                {
                    buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
                        this, cs, g.rs, ds, g.startRow, colCount, stripe);
                }
                if (leaf) {
                    // do summaries on all grouping levels for this group
                    this.doGroupEnd(buf, g, cs, ds, colCount);
                }
                else
                    parents_queued.push(g);
                if (next_level >= cur_level)
                    continue;
                // going back from leaf - pop parents from queue
                // and call doGroupEnd for each
                while (cur_level > next_level && cur_level > 0)
                {
                    g = parents_queued.pop();
                    this.doGroupEnd(buf, g, cs, ds, colCount);
                    cur_level--;
                }
            }
            return buf.join('');
        },
        getGroup:function(A,D,F,G,B,E)
        {
            var C = F ? F(A,{},D,G,B,E) : String(A);
            if (C==="")
                C = this.cm.config[B].emptyGroupText || this.emptyGroupText;
            return C;
        },
       /** Should return an array of all elements that represent a row, it should bypass
        *  all grouping sections
        */
        getRows: function(){
            if (!this.enableGrouping)
                return Ext.grid.GroupingView.superclass.getRows.call(this);
    
    
            return Ext.DomQuery.select("div.x-grid3-row", this.mainBody.dom);
        },
        getGroupById: function(gid)
        {
            var g = null;
            for (var i = 0; i < this.groups.length; i++)
            {
                group = this.groups[i];
                if (group.groupId == gid)
                    return group;
            }
            return g;
        },
        /* override the processEvent function of groupingView to handle groupField
         * which is an array of fields
         */
        processEvent: function(name, e)
        {
            Ext.grid.GroupingView.superclass.processEvent.call(this, name, e);
            var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
            if (hd)
            {
                // group value is at the end of the string
                var field = this.getGroupField();
                // in MultiGrouping field is an array of field names, so take just
                // the last field name
                if (typeof field == "object" && field.length)
                    field = field[field.length-1];
                var prefix = this.getPrefix(field);
                var groupValue = hd.id.substring(prefix.length);
                var emptyRe = new RegExp('gp-' + Ext.escapeRe(field) + '--hd');
                // remove trailing '-hd'
                groupValue = groupValue.substr(0, groupValue.length - 3);
    
    
                // also need to check for empty groups
                if(groupValue || emptyRe.test(hd.id)){
                    this.grid.fireEvent('group' + name, this.grid, field, groupValue, e);
                }
                if(name == 'mousedown' && e.button == 0){
                    this.toggleGroup(hd.parentNode);
                }
            }
        }
    });
    
    
    Ext.ux.MultiGroupingPanelEditor = function(config) {
        config = config||{};
        config.tbar = new Ext.Toolbar({id:'grid-tbr'});
        Ext.ux.MultiGroupingPanelEditor.superclass.constructor.call(this, config);
    };
    
    
    Ext.extend(Ext.ux.MultiGroupingPanelEditor, Ext.grid.GridPanel,{
        isEditor:true,
        detectEdit:false,
        autoEncode:false,
        trackMouseOver:false,
        initComponent:function(){
            Ext.ux.MultiGroupingPanelEditor.superclass.initComponent.call(this);
            if(!this.selModel){
                this.selModel=new Ext.grid.CellSelectionModel()
            }
            this.activeEditor=null;
            this.addEvents("beforeedit","afteredit","validateedit")
        }
        ,initEvents:function(){
            Ext.ux.MultiGroupingPanelEditor.superclass.initEvents.call(this);
            this.on("bodyscroll",this.stopEditing,this,[true]);
            if(this.clicksToEdit==1){
                this.on("cellclick",this.onCellDblClick,this)
            }
            else{
                if(this.clicksToEdit=="auto"&&this.view.mainBody){this.view.mainBody.on("mousedown",this.onAutoEditClick,this)}
                this.on("celldblclick",this.onCellDblClick,this)
            }this.getGridEl().addClass("xedit-grid")
        }
        ,onCellDblClick:function(B,C,A){this.startEditing(C,A)}
        ,onAutoEditClick:function(C,B){
            if(C.button!==0){return }
            var E=this.view.findRowIndex(B);
            var A=this.view.findCellIndex(B);
            if(E!==false&&A!==false){
                this.stopEditing();
                if(this.selModel.getSelectedCell){
                    var D=this.selModel.getSelectedCell();
                    if(D&&D.cell[0]===E&&D.cell[1]===A){this.startEditing(E,A)}
                }
                else{if(this.selModel.isSelected(E)){ this.startEditing(E,A)}}
            }
        }
        ,onEditComplete:function(B,D,A){
            this.editing=false;
            this.activeEditor=null;
            B.un("specialkey",this.selModel.onEditorKey,this.selModel);
            var C=B.record;
            var F=this.colModel.getDataIndex(B.col);
            D=this.postEditValue(D,A,C,F);
            if(String(D)!==String(A))
            {
                var E={
                    grid:this,
                    record:C,
                    field:F,
                    originalValue:A,
                    value:D,
                    row:B.row,
                    column:B.col,
                    cancel:false
                };
                if (this.fireEvent("validateedit",E) !== false && !E.cancel)
                {
                    C.set(F,E.value);
                    delete E.cancel;
                    this.fireEvent("afteredit",E);
                }
            }
            this.view.focusCell(B.row,B.col)
        }
        ,startEditing:function(F,B)
         {
            this.stopEditing();
            if(this.colModel.isCellEditable(B,F))
            {
                this.view.ensureVisible(F,B,true);
                var C=this.store.getAt(F);
                var E=this.colModel.getDataIndex(B);
                var D = {
                    grid:this,
                    record:C,
                    field:E,
                    value:C.data[E],
                    row:F,
                    column:B,
                    cancel:false
                };
                if (this.fireEvent("beforeedit",D)!==false&&!D.cancel)
                {
                    this.editing=true;
                    var A = this.colModel.getCellEditor(B,F);
                    if (!A.rendered)
                        A.render(this.view.getEditorParent(A));
    
    
                    (function()
                    {
                        A.row=F;
                        A.col=B;
                        A.record=C;
                        A.on("complete", this.onEditComplete, this, {single:true});
                        A.on("specialkey", this.selModel.onEditorKey, this.selModel);
                        this.activeEditor=A;
                        var G = this.preEditValue(C,E);
                        A.startEdit(this.view.getCell(F,B),G);
                    }).defer(50,this);
                }
            }
        }
        ,preEditValue:function(A,B){return this.autoEncode&&typeof value=="string"?Ext.util.Format.htmlDecode(A.data[B]):A.data[B]}
        ,postEditValue:function(C,A,B,D){return this.autoEncode&&typeof C=="string"?Ext.util.Format.htmlEncode(C):C}
        ,stopEditing:function(A){if(this.activeEditor){this.activeEditor[A===true?"cancelEdit":"completeEdit"]()}this.activeEditor=null}
        ,setUpDragging: function( ){
            this.dragZone = new Ext.dd.DragZone(this.getTopToolbar().getEl(), {
                ddGroup:"grid-body"
               ,panel:this 
               ,scroll:false
               ,onInitDrag : function(e) {
                    var clone = this.dragData.ddel;
                    clone.id = Ext.id('ven');
                    this.proxy.update(clone);
                    return true;
                }
               ,getDragData: function(e) {
                    var target = Ext.get(e.getTarget().id);
                    if(target.hasClass('x-toolbar x-small-editor')) { return false;}
                    d = e.getTarget().cloneNode(true);
                    d.id = Ext.id();
                    this.dragData = {
                        repairXY: Ext.fly(target).getXY(),
                        ddel: d,
                        btn:e.getTarget()
                    };
                    return this.dragData;
                }
               ,getRepairXY: function() {return this.dragData.repairXY;}
            });
            this.dropTarget2s = new Ext.dd.DropTarget('grid-tbr', {
                ddGroup: "gridHeader" + this.getGridEl().id
               ,panel:this 
               ,notifyDrop: function(dd, e, data) {
                    var btname= this.panel.getColumnModel().getDataIndex( this.panel.getView().getCellIndex(data.header));
                    this.panel.store.groupBy(btname);
                    return true;
                }
            });
            this.dropTarget22s = new Ext.dd.DropTarget(this.getView().el.dom.childNodes[0].childNodes[1], {
                ddGroup: "grid-body"
               ,panel:this 
               ,notifyDrop: function(dd, e, data) {
                    var txt = Ext.get(data.btn).dom.innerHTML;
                    var tb = this.panel.getTopToolbar();
                    var bidx = tb.items.findIndexBy(function(b) {
                        return b.text==txt;
                    },this);
                    if(bidx<0) return false;
                    var fld = tb.items.get(bidx).fieldName;
                    Ext.removeNode(Ext.getDom(tb.items.get(bidx).id));
                    if(bidx>0) Ext.removeNode(Ext.getDom(tb.items.get(bidx-1).id));;
                    var cidx=this.panel.view.cm.findColumnIndex(fld);
                    if(cidx<0){}
                    this.panel.view.cm.setHidden(cidx, false);
                    var temp=[];
                    for(var i=this.panel.store.groupField.length-1;i>=0;i--) {
                        if(this.panel.store.groupField[i]==fld) {
                            this.panel.store.groupField.pop();
                            break;
                        }
                        temp.push(this.panel.store.groupField[i]);
                        this.panel.store.groupField.pop();
                    }
                    for(var i=temp.length-1;i>=0;i--) {this.panel.store.groupField.push(temp[i]);}
                    if(this.panel.store.groupField.length==0){this.panel.store.groupField=false;}
                    this.panel.store.fireEvent('datachanged', this);
                    return true;
                }
            }); 
        }
    });
    Ext.reg("editorgrid",Ext.ux.MultiGroupingPanelEditor);
    
    
    Ext.ux.MultiGroupingPanel = function(config) {
        config = config||{};
        config.tbar = new Ext.Toolbar({id:'grid-tbr'});
        Ext.ux.MultiGroupingPanel.superclass.constructor.call(this, config);
    };
    
    
    Ext.extend(Ext.ux.MultiGroupingPanel, Ext.grid.GridPanel, {
        initComponent : function(){
            Ext.ux.MultiGroupingPanel.superclass.initComponent.call(this);
            this.on("render", this.setUpDragging, this);
        }
        ,setUpDragging: function() {
            this.dragZone = new Ext.dd.DragZone(this.getTopToolbar().getEl(), {
                ddGroup:"grid-body"
               ,panel:this 
               ,scroll:false
               ,onInitDrag : function(e) {
                    var clone = this.dragData.ddel;
                    clone.id = Ext.id('ven');
                    this.proxy.update(clone);
                    return true;
                }
               ,getDragData: function(e) {
                    var target = Ext.get(e.getTarget().id);
                    if (target === undefined) return false;
                    if(target.hasClass('x-toolbar x-small-editor')) {
                        return false;
                    }
                    d = e.getTarget().cloneNode(true);
                    d.id = Ext.id();
                    this.dragData = {
                        repairXY: Ext.fly(target).getXY(),
                        ddel: d,
                        btn:e.getTarget()
                    };
                    return this.dragData;
                }
               ,getRepairXY: function() { return this.dragData.repairXY; }
            });
            this.dropTarget2s = new Ext.dd.DropTarget('grid-tbr', {
                ddGroup: "gridHeader" + this.getGridEl().id
               ,panel:this 
               ,notifyDrop: function(dd, e, data) {
                    var btname= this.panel.getColumnModel().getDataIndex( this.panel.getView().getCellIndex(data.header));
                    this.panel.store.groupBy(btname);
                    return true;
                }
            });
            this.dropTarget22s = new Ext.dd.DropTarget(this.getView().el.dom.childNodes[0].childNodes[1], {
                ddGroup: "grid-body"
               ,panel:this 
               ,notifyDrop: function(dd, e, data) {
                    var txt = Ext.get(data.btn).dom.innerHTML;
                    var tb = this.panel.getTopToolbar();
                    var bidx = tb.items.findIndexBy(function(b) {
                        return b.text==txt;
                    },this);
                    if(bidx<0) return false;
                    var fld = tb.items.get(bidx).fieldName;
                    Ext.removeNode(Ext.getDom(tb.items.get(bidx).id));
                    if(bidx>0) Ext.removeNode(Ext.getDom(tb.items.get(bidx-1).id));;
                    var cidx=this.panel.view.cm.findColumnIndex(fld);
                    if(cidx<0){}
                    this.panel.view.cm.setHidden(cidx, false);
                    var temp=[];
                    for(var i=this.panel.store.groupField.length-1;i>=0;i--) {
                        if(this.panel.store.groupField[i]==fld) {
                            this.panel.store.groupField.pop();
                            break;
                        }
                        temp.push(this.panel.store.groupField[i]);
                        this.panel.store.groupField.pop();
                    }
                    for(var i=temp.length-1;i>=0;i--) {this.panel.store.groupField.push(temp[i]);}
                    if(this.panel.store.groupField.length==0){this.panel.store.groupField=false;}
    
    
                    this.panel.store.fireEvent('datachanged', this);
                    return true;
                }
            }); 
        }
    });
    
    
    Ext.ux.MultiGroupingGrid = function(config) {
        config = config||{};
        
        // Cache the orignal column model, before state is applied
        if(config.cm)
          this.origColModel = Ext.ux.util.clone(config.cm.config);
        else if(config.colModel)
          this.origColModel = Ext.ux.util.clone(config.colModel.config);
          
        config.tbar = [{
           xtype:'tbtext'
          ,text:this.emptyToolbarText
        },{
           xtype:'tbfill'
          ,noDelete:true
        },{
           xtype:'tbbutton'
          ,text:'Options'
          ,noDelete:true
          ,menu:{
             items: [{
               text:'Columns Reset',
               scope: this,
               disabled: !this.origColModel,
               handler: function() {
                 this.getColumnModel().setConfig(this.origColModel,false);
                 this.saveState();
                 return true;
               }
             },{
               text:'Show columns grouped'
              ,checked: !config.view.hideGroupedColumn
              ,scope:this
              ,checkHandler: function (item, checked) {
                 this.view.hideGroupedColumn = !checked;
                 this.view.refresh(true);
               }
             },{
               text: 'Clean filters' // Labels.get('label.jaffa.jaffaRIA.jaffa.finder.grid.deactivateFilters')
              ,scope: this
              ,handler: function () {
                 //@TODO use the clearFilters() method!
                 this.plugins.filters.each(function(flt) {
                   flt.setActive(false); 
                 });
               }  
             }]     
           }
        }];
        Ext.ux.MultiGroupingGrid.superclass.constructor.call(this, config);
        //console.debug("Create MultiGroupingGrid",config);
    };
    
    
    //Ext.extend(Ext.ux.MultiGroupingGrid, Ext.grid.GridPanel, {
    //modified by jesus, extend a  Ext.grid.EditorGridPanel class
    Ext.extend(Ext.ux.MultiGroupingGrid, Ext.grid.EditorGridPanel, {
    
    
    
    
       initComponent : function(){
         //console.debug("MultiGroupingGrid.initComponent",this);
         Ext.ux.MultiGroupingGrid.superclass.initComponent.call(this);
         
         // Initialise DragZone
         this.on("render", this.setUpDragging, this);
       }
       
       /** @cfg emptyToolbarText String to display on tool bar when there are no groups
        */   
      ,emptyToolbarText : "Drag the columns to group here" 
       /** Extend basic version so the Grouping Columns State is remebered
        */   
      ,getState : function(){
         var s = Ext.ux.MultiGroupingGrid.superclass.getState.call(this);
         s.groupFields = this.store.getGroupState();
         return s;
       }
       
       /** Extend basic version so the Grouping Columns State is applied
        */   
      ,applyState : function(state){
         Ext.ux.MultiGroupingGrid.superclass.applyState.call(this,state);
         if(state.groupFields) {
            this.store.groupBy(state.groupFields,true);
            if (typeof console != "undefined")
                console.debug("Grid.applyState: Groups=",state.groupFields);
         }
       }  
        
      ,setUpDragging: function() {
         //console.debug("SetUpDragging", this);
         this.dragZone = new Ext.dd.DragZone(this.getTopToolbar().getEl(), {
           ddGroup:"grid-body" + this.getGridEl().id //FIXME - does this need to be unique to support multiple independant panels on the same page
          ,panel:this 
          ,scroll:false
           // @todo - docs
          ,onInitDrag : function(e) {
             // alert('init');
             var clone = this.dragData.ddel;
             clone.id = Ext.id('ven'); //FIXME??
             // clone.class='x-btn button';
             this.proxy.update(clone);
             return true;
           }
    
    
           // @todo - docs
          ,getDragData: function(e) {
             var target = Ext.get(e.getTarget().id);
             //console.debug("DragZone: ",e,target);
             if(!target || target.hasClass('x-toolbar x-small-editor')) {
               return false;
             }
               
             d = e.getTarget().cloneNode(true);
             d.id = Ext.id();
             if (typeof console != "undefined")
                 console.debug("getDragData",this, target);
               
             this.dragData = {
               repairXY: Ext.fly(target).getXY(),
               ddel: d,
               btn:e.getTarget()
             };
             return this.dragData;
           }
    
    
           //Provide coordinates for the proxy to slide back to on failed drag.
           //This is the original XY coordinates of the draggable element.
          ,getRepairXY: function() {
             return this.dragData.repairXY;
           }
         });
         
         // This is the target when columns are dropped onto the toolbar (ie added to the group)
         this.dropTarget2s = new Ext.dd.DropTarget(this.getTopToolbar().getEl(), {
           ddGroup: "gridHeader" + this.getGridEl().id
          ,panel:this 
          ,notifyDrop: function(dd, e, data) {
             if (this.panel.getColumnModel().config[this.panel.getView().getCellIndex(data.header)].groupable) {
                 if (typeof console != "undefined")
                     console.debug("Adding Filter", data);
                 var btname = this.panel.getColumnModel().getDataIndex(this.panel.getView().getCellIndex(data.header));
                 this.panel.store.groupBy(btname);
                 return true;
             }
             else {
                 return false;
             }
           }
           ,notifyOver: function(dd,e,data){
             if (this.panel.getColumnModel().config[this.panel.getView().getCellIndex(data.header)].groupable) {
                 return this.dropAllowed;
             }
             else {
                 return this.dropNotAllowed;
             }
           }
         });
    
    
         // This is the target when columns are dropped onto the grid (ie removed from the group)
         this.dropTarget22s = new Ext.dd.DropTarget(this.getView().el.dom.childNodes[0].childNodes[1], {
           ddGroup: "grid-body" + this.getGridEl().id  //FIXME - does this need to be unique to support multiple independant panels on the same page
          ,panel:this 
          ,notifyDrop: function(dd, e, data) {
             var txt = Ext.get(data.btn).dom.innerHTML;
             var tb = this.panel.getTopToolbar();
             if (typeof console != "undefined")
                 console.debug("Removing Filter", txt);
             var bidx = tb.items.findIndexBy(function(b) {
               if (typeof console != "undefined")
                   console.debug("Match button ",b.text);
               return b.text==txt;
             },this);
             if (typeof console != "undefined")
                 console.debug("Found matching button", bidx);
             if(bidx<0) return false; // Error!
             var fld = tb.items.get(bidx).fieldName;
             
             // Remove from toolbar
             Ext.removeNode(Ext.getDom(tb.items.get(bidx).id));
             if(bidx>0) Ext.removeNode(Ext.getDom(tb.items.get(bidx-1).id));;
    
    
             if (typeof console != "undefined")
                 console.debug("Remove button", fld);
             //console.dir(button);
             var cidx=this.panel.view.cm.findColumnIndex(fld);
             
             if(cidx<0)
               console.error("Can't find column for field ", fld);
             
             this.panel.view.cm.setHidden(cidx, false);
    
    
             //Ext.removeNode(Ext.getDom(data.btn.id));
    
    
             // Remove this group from the groupField array
             // @todo - replace with method on store
             // this.panel.store.removeGroupField(fld);
             var temp=[];
             for(var i=this.panel.store.groupField.length-1;i>=0;i--) {
               if(this.panel.store.groupField[i]==fld) {
                 this.panel.store.groupField.pop();
                 break;
               }
               temp.push(this.panel.store.groupField[i]);
               this.panel.store.groupField.pop();
             }
    
    
             for(var i=temp.length-1;i>=0;i--) {
               this.panel.store.groupField.push(temp[i]);
             }
    
    
             if(this.panel.store.groupField.length==0)
               this.panel.store.groupField=false;
    
    
             this.panel.store.fireEvent('datachanged', this);
             return true;
           }
         }); 
       }
    
    
      ,buildFilters: function (columns, record) {
         //console.debug("Grid.buildFilters: Created Filters from ", columns, record);
         var config = [];
         for(var i=0;i<columns.length;i++) {
           var col = columns[i];
           var meta = record.getField(col.dataIndex);
           //console.debug("Meta Data For ", col.dataIndex, meta)
           if(meta && (meta.filter || meta.filterFieldName)) {
             var dt = meta.dataType || 'string';
             if (dt=='int' || dt=='long' || dt=='float' || dt=='double')
               dt=='numeric';
             else if (dt=='dateonly' || dt=='datetime')
               dt='date';
             //FIXME pass caseType on this filter definition, so it can be applied to the filter field  
             var f = {dataIndex:col.dataIndex, type:dt, paramName:col.filterFieldName};
             config[config.length] = f;
           }
         }
         if (typeof console != "undefined")
             console.debug("Grid.buildFilters: Created Filters for ", config);
         if(config.length==0)
           return null;
         else  
           return new Ext.ux.GridFilters({filters:config, local:false});
       }
    
    
      ,buildColumnModel: function (columns, record) {
         var config = [];
         for(var i=0;i<columns.length;i++) {
           var col = columns[i];
           var meta = record.getField(col.dataIndex);
           var cm = Ext.apply({},col);
           if(meta) {
             // Apply stuff from the Record's Meta Data
             if(!cm.hidden && meta.hidden==true) cm.hidden = true;   
             if(!cm.header && meta.label) cm.header = meta.label;
             if(!cm.renderer && meta.renderer) cm.renderer = meta.renderer;
             cm.sortable=(meta.sortable===true || (meta.sortFieldName&&meta.sortFieldName!=''));
    
    
             // Apply more metadata from associated ClassMetaData
             var mc = meta.metaClass || record.defaultMetaClass;
             var mfn = (meta.mapping||col.dataIndex).match(/.*\b(\w+)$/)[1];
             var mf = ClassMetaData[mc]?ClassMetaData[mc].fields[mfn]:undefined;
             if(!mf) mf = ClassMetaData[mc]?ClassMetaData[mc].fields[col.dataIndex]:undefined;
             if (typeof console != "undefined")
                 console.debug("Meta Class=",mc,ClassMetaData[mc],', dataIndex=',col.dataIndex,', mapping=',meta.mapping,', mfn=',mfn,', mf=',mf,', meta=',meta);
             if(mf) {
               // Default the header text
               if(!cm.header && mf.label) cm.header=mf.label;
               // Default the column width
               if(!cm.width) {
                 if(mf.maxLength) cm.width = Math.min(Math.max(mf.maxLength,5),40)*8;
                 else if(mf.type) {
                   if(mf.type=='dateonly') cm.width=100;
                   else if(mf.type=='datetime') cm.width=140;
                   else if(mf.type=='boolean') cm.width=50;
                 }
               }
               // Default the alignment
               if(!cm.align && mf.type && (mf.type=='float'||mf.type=='int'))
                 cm.align = 'right';
               // Default standard renderers  
               if(!cm.renderer && mf.type) {
                 if(mf.type=='dateonly') cm.renderer = Ext.util.Format.dateRenderer();
                 else if(mf.type=='datetime') cm.renderer = Ext.util.Format.dateTimeRenderer();
               }
               if(mf.hidden==true) cm.hidden = true;   
             }
           }  
           if(!cm.header) cm.header = col.dataIndex;
           cm.groupable = (cm.groupable==true || cm.sortable==true);
           config[config.length] = cm;
           if (typeof console != "undefined")
               console.debug("Grid.buildColumnModel: Width", cm.dataIndex, cm.width);
    
    
         }
         if (typeof console != "undefined")
             console.debug("Grid.buildColumnModel: Created Columns for ", config);
         return new Ext.grid.ColumnModel(config);
      }
    
    
    });
    
    
    Ext.ux.MultiGroupingPagingGrid = Ext.extend(Ext.ux.MultiGroupingGrid, {
    
    
      /** When creating the store, register an internal callback for post load processing
       */  
        constructor: function(config) {
          config = config||{};
          config.bbar = [].concat(config.bbar);
          config.bbar = config.bbar.concat([
            {xtype:'tbfill'}
           ,{xtype:'tbtext',id:'counter', text: '? of ?'}
           ,{xtype:'tbspacer'}
           ,{xtype:'tbbutton',id:'loading',hidden: true,iconCls: "x-tbar-loading"}
           ,{xtype:'tbseparator'}
           ,{xtype:'tbbutton',id:'more',text: '>>',handler: function() { this.store.loadMore(false); }, scope: this}
          ]);
          
          Ext.ux.MultiGroupingPagingGrid.superclass.constructor.apply(this, arguments);
          
          // Create Event that asks for more data when we scroll to the end
          this.on("bodyscroll",  function() {
                var s = this.view.scroller.dom;
                if( (s.offsetHeight+s.scrollTop+5 > s.scrollHeight) && !this.isLoading) {
                    if (typeof console != "undefined")
                        console.debug("Grid.on.bodyscroll: Get more...");
                  this.store.loadMore(false);
                }  
          }, this);
          
          // When the grid start loading, display a loading icon    
          this.store.on("beforeload", function(store,o) {
            if(this.isLoading) {
                if (typeof console != "undefined")
                    console.debug("Store.on.beforeload: Reject Load, one is in progress");
              return false;
            }
            this.isLoading = true;
            if(this.rendered) {
              this.barLoading.show();
            }
            if (typeof console != "undefined")
                console.debug("Store.on.beforeload: options=",o, this);
            return true;
          }, this);
          
          // When loading has finished, disable the loading icon, and update the row count  
          this.store.on("load", function() {
            delete this.isLoading;
            if(this.rendered) {
              this.barLoading.hide();
              if (typeof console != "undefined")
                  console.debug("Store.on.load: Finished loading.. ",this.store.totalCount);
              this.barCounter.getEl().innerHTML = "Mostrando " + this.store.getCount()+' de ' +
                    (this.store.totalCount?this.store.totalCount:'?');
              if(this.store.totalCount)
                this.barMore.disable();
              else
                this.barMore.enable();  
            }
            return true;
          }, this);
    
    
          // When a loading error occurs, disable the loading icon and display error  
          this.store.on("loadexception", function(store, e) {
                  if (typeof console != "undefined")
                      console.debug("Store.loadexception.Event:",arguments);
            delete this.isLoading;
            if(this.rendered) {
              this.barLoading.hide();
            }
            if(e)
              Ext.Msg.show({
                title:'Show Details',
                msg: "Error cargando registros - " + e,
                buttons: Ext.Msg.OK,
                icon: Ext.MessageBox.ERROR
              });
            return false;
          }, this);
    
    
          // As the default onLoad to refocus on the first row has been disabled,
          // This has been added so if a load does happen, and its an initial load
          // it refocuses. If this is a refresh caused by a sort/group or a new page
          // of data being loaded, it does not refocus  
          this.store.on("load", function(r,o) {
             if(o&&o.initial==true)
               Ext.ux.MultiGroupingView.superclass.onLoad.call(this);        
          }, this.view);
        }
        
        // private
       ,onRender : function(ct, position){
            Ext.ux.MultiGroupingPagingGrid.superclass.onRender.call(this, ct, position);
            var bb=this.getBottomToolbar();
            this.barCounter = bb.items.itemAt(bb.items.length-5);
            this.barMore = bb.items.itemAt(bb.items.length-1);
            this.barLoading = bb.items.itemAt(bb.items.length-3);
        }
    });

  2. #2
    Ext Premium Member yyogev's Avatar
    Join Date
    Jun 2009
    Location
    Shoham, Israel
    Posts
    196
    Vote Rating
    6
    yyogev is on a distinguished road

      0  

    Default Would be nice to get this as a patch

    Would be nice to get this as a patch


    Since this code is not checked in and there are several versions floating around, it would be nicer to get your fixes as a patch.

    Thanks,
    Yaron Yogev

    IT Software Developer

  3. #3
    Sencha User
    Join Date
    Jun 2011
    Posts
    17
    Vote Rating
    0
    trvd1707 is on a distinguished road

      0  

    Default


    I don't know how to do that.

  4. #4
    Ext Premium Member yyogev's Avatar
    Join Date
    Jun 2009
    Location
    Shoham, Israel
    Posts
    196
    Vote Rating
    6
    yyogev is on a distinguished road

      0  

    Default


    In Unix/Linux, a simple "diff -u file1 file2" would produce the required output, where file1 contains the code before the change, and file2 has the code after the change.
    In Windows, you can use GNU Diffutils.
    Yaron Yogev

    IT Software Developer

  5. #5
    Sencha User
    Join Date
    Jan 2012
    Posts
    1
    Vote Rating
    0
    tsreenath1985 is on a distinguished road

      0  

    Default need a working example

    need a working example


    Hi,
    I am new to ExtJS. I am using ExtJS 4. I am trying to implement Multigrouping. Could you please provide me a working code of multigrouping which i can run it on my pc. thanks.

  6. #6
    Ext Premium Member yyogev's Avatar
    Join Date
    Jun 2009
    Location
    Shoham, Israel
    Posts
    196
    Vote Rating
    6
    yyogev is on a distinguished road

      1  

    Default


    Quote Originally Posted by tsreenath1985 View Post
    Hi,
    I am new to ExtJS. I am using ExtJS 4. I am trying to implement Multigrouping. Could you please provide me a working code of multigrouping which i can run it on my pc. thanks.
    Please read the posts above: the multigrouping user extension was written for ExtJS 2. and later fixed so it can work on ExtJS 3. It does not work on ExtJS 4.
    If you do decide to take a shot at making it work on ExtJS, may the force be with you!. I would recommend to create a new extension based on the ExtJS 4 Ext.grid.feature.Grouping, rather than trying to fix the existing extension.
    Last edited by yyogev; 12 Feb 2012 at 9:31 PM. Reason: fix broken English
    Yaron Yogev

    IT Software Developer

Thread Participants: 2

film izle

hd film izle

film sitesi

takipci kazanma sitesi

takipci kazanma sitesi

güzel olan herşey

takipci alma sitesi

komik eğlenceli videolar