Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / grid / feature / Grouping.js
index ca3c83e..c53bb94 100644 (file)
@@ -1,3 +1,17 @@
+/*
+
+This file is part of Ext JS 4
+
+Copyright (c) 2011 Sencha Inc
+
+Contact:  http://www.sencha.com/contact
+
+GNU General Public License Usage
+This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
+
+If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
+
+*/
 /**
  * @class Ext.grid.feature.Grouping
  * @extends Ext.grid.feature.Feature
@@ -42,16 +56,17 @@ Ext.define('Ext.grid.feature.Grouping', {
     eventSelector: '.' + Ext.baseCSSPrefix + 'grid-group-hd',
 
     constructor: function() {
-        this.collapsedState = {};
-        this.callParent(arguments);
+        var me = this;
+        
+        me.collapsedState = {};
+        me.callParent(arguments);
     },
     
     /**
      * @event groupclick
      * @param {Ext.view.Table} view
      * @param {HTMLElement} node
-     * @param {Number} unused
-     * @param {Number} unused
+     * @param {String} group The name of the group
      * @param {Ext.EventObject} e
      */
 
@@ -59,8 +74,7 @@ Ext.define('Ext.grid.feature.Grouping', {
      * @event groupdblclick
      * @param {Ext.view.Table} view
      * @param {HTMLElement} node
-     * @param {Number} unused
-     * @param {Number} unused
+     * @param {String} group The name of the group
      * @param {Ext.EventObject} e
      */
 
@@ -68,8 +82,7 @@ Ext.define('Ext.grid.feature.Grouping', {
      * @event groupcontextmenu
      * @param {Ext.view.Table} view
      * @param {HTMLElement} node
-     * @param {Number} unused
-     * @param {Number} unused
+     * @param {String} group The name of the group
      * @param {Ext.EventObject} e
      */
 
@@ -77,8 +90,7 @@ Ext.define('Ext.grid.feature.Grouping', {
      * @event groupcollapse
      * @param {Ext.view.Table} view
      * @param {HTMLElement} node
-     * @param {Number} unused
-     * @param {Number} unused
+     * @param {String} group The name of the group
      * @param {Ext.EventObject} e
      */
 
@@ -86,8 +98,7 @@ Ext.define('Ext.grid.feature.Grouping', {
      * @event groupexpand
      * @param {Ext.view.Table} view
      * @param {HTMLElement} node
-     * @param {Number} unused
-     * @param {Number} unused
+     * @param {String} group The name of the group
      * @param {Ext.EventObject} e
      */
 
@@ -108,33 +119,31 @@ Ext.define('Ext.grid.feature.Grouping', {
     hdCollapsedCls: Ext.baseCSSPrefix + 'grid-group-hd-collapsed',
 
     /**
-     * @cfg {String} groupByText Text displayed in the grid header menu for grouping by header
-     * (defaults to 'Group By This Field').
+     * @cfg {String} groupByText Text displayed in the grid header menu for grouping by header.
      */
     groupByText : 'Group By This Field',
     /**
-     * @cfg {String} showGroupsText Text displayed in the grid header for enabling/disabling grouping
-     * (defaults to 'Show in Groups').
+     * @cfg {String} showGroupsText Text displayed in the grid header for enabling/disabling grouping.
      */
     showGroupsText : 'Show in Groups',
 
     /**
-     * @cfg {Boolean} hideGroupedHeader<tt>true</tt> to hide the header that is currently grouped (defaults to <tt>false</tt>)
+     * @cfg {Boolean} hideGroupedHeader<tt>true</tt> to hide the header that is currently grouped.
      */
     hideGroupedHeader : false,
 
     /**
-     * @cfg {Boolean} startCollapsed <tt>true</tt> to start all groups collapsed (defaults to <tt>false</tt>)
+     * @cfg {Boolean} startCollapsed <tt>true</tt> to start all groups collapsed
      */
     startCollapsed : false,
 
     /**
-     * @cfg {Boolean} enableGroupingMenu <tt>true</tt> to enable the grouping control in the header menu (defaults to <tt>true</tt>)
+     * @cfg {Boolean} enableGroupingMenu <tt>true</tt> to enable the grouping control in the header menu
      */
     enableGroupingMenu : true,
 
     /**
-     * @cfg {Boolean} enableNoGroups <tt>true</tt> to allow the user to turn off grouping (defaults to <tt>true</tt>)
+     * @cfg {Boolean} enableNoGroups <tt>true</tt> to allow the user to turn off grouping
      */
     enableNoGroups : true,
     
@@ -144,33 +153,46 @@ Ext.define('Ext.grid.feature.Grouping', {
             store = view.store,
             groupToggleMenuItem;
             
+        me.lastGroupField = me.getGroupField();
+
         if (me.lastGroupIndex) {
             store.group(me.lastGroupIndex);
         }
         me.callParent();
         groupToggleMenuItem = me.view.headerCt.getMenu().down('#groupToggleMenuItem');
         groupToggleMenuItem.setChecked(true, true);
-        view.refresh();
+        me.refreshIf();
     },
 
     disable: function() {
         var me    = this,
             view  = me.view,
             store = view.store,
+            remote = store.remoteGroup,
             groupToggleMenuItem,
             lastGroup;
             
         lastGroup = store.groupers.first();
         if (lastGroup) {
             me.lastGroupIndex = lastGroup.property;
-            store.groupers.clear();
+            me.block();
+            store.clearGrouping();
+            me.unblock();
         }
         
         me.callParent();
         groupToggleMenuItem = me.view.headerCt.getMenu().down('#groupToggleMenuItem');
         groupToggleMenuItem.setChecked(true, true);
         groupToggleMenuItem.setChecked(false, true);
-        view.refresh();
+        if (!remote) {
+            view.refresh();
+        }
+    },
+    
+    refreshIf: function() {
+        if (this.blockRefresh !== true) {
+            this.view.refresh();
+        }    
     },
 
     getFeatureTpl: function(values, parent, x, xcount) {
@@ -210,8 +232,7 @@ Ext.define('Ext.grid.feature.Grouping', {
     // perhaps rename to afterViewRender
     attachEvents: function() {
         var me = this,
-            view = me.view,
-            header, headerId, menu, menuItem;
+            view = me.view;
 
         view.on({
             scope: me,
@@ -225,16 +246,10 @@ Ext.define('Ext.grid.feature.Grouping', {
         if (me.enableGroupingMenu) {
             me.injectGroupingMenu();
         }
-
-        if (me.hideGroupedHeader) {
-            header = view.headerCt.down('gridcolumn[dataIndex=' + me.getGroupField() + ']');
-            headerId = header.id;
-            menu = view.headerCt.getMenu();
-            menuItem = menu.down('menuitem[headerId='+ headerId +']');
-            if (menuItem) {
-                menuItem.setChecked(false);
-            }
-        }
+        me.lastGroupField = me.getGroupField();
+        me.block();
+        me.onGroupChange();
+        me.unblock();
     },
     
     injectGroupingMenu: function() {
@@ -261,12 +276,13 @@ Ext.define('Ext.grid.feature.Grouping', {
             showGroupsText     = me.showGroupsText,
             enableNoGroups     = me.enableNoGroups,
             groupMenuItemClick = Ext.Function.bind(me.onGroupMenuItemClick, me),
-            groupToggleMenuItemClick = Ext.Function.bind(me.onGroupToggleMenuItemClick, me)
+            groupToggleMenuItemClick = Ext.Function.bind(me.onGroupToggleMenuItemClick, me);
         
         // runs in the scope of headerCt
         return function() {
             var o = Ext.grid.header.Container.prototype.getMenuItems.call(this);
             o.push('-', {
+                iconCls: Ext.baseCSSPrefix + 'group-by-icon',
                 itemId: 'groupMenuItem',
                 text: groupByText,
                 handler: groupMenuItemClick
@@ -289,15 +305,30 @@ Ext.define('Ext.grid.feature.Grouping', {
      * @private
      */
     onGroupMenuItemClick: function(menuItem, e) {
-        var menu = menuItem.parentMenu,
+        var me = this,
+            menu = menuItem.parentMenu,
             hdr  = menu.activeHeader,
-            view = this.view;
+            view = me.view,
+            store = view.store,
+            remote = store.remoteGroup;
 
-        delete this.lastGroupIndex;
-        this.enable();
-        view.store.group(hdr.dataIndex);
-        this.pruneGroupedHeader();
-        
+        delete me.lastGroupIndex;
+        me.block();
+        me.enable();
+        store.group(hdr.dataIndex);
+        me.pruneGroupedHeader();
+        me.unblock();
+        if (!remote) {
+            view.refresh();
+        }  
+    },
+    
+    block: function(){
+        this.blockRefresh = this.view.blockRefresh = true;
+    },
+    
+    unblock: function(){
+        this.blockRefresh = this.view.blockRefresh = false;
     },
 
     /**
@@ -354,7 +385,7 @@ Ext.define('Ext.grid.feature.Grouping', {
 
     /**
      * Expand a group by the groupBody
-     * @param {Ext.core.Element} groupBd
+     * @param {Ext.Element} groupBd
      * @private
      */
     expand: function(groupBd) {
@@ -375,7 +406,7 @@ Ext.define('Ext.grid.feature.Grouping', {
 
     /**
      * Collapse a group by the groupBody
-     * @param {Ext.core.Element} groupBd
+     * @param {Ext.Element} groupBd
      * @private
      */
     collapse: function(groupBd) {
@@ -395,7 +426,41 @@ Ext.define('Ext.grid.feature.Grouping', {
     },
     
     onGroupChange: function(){
-        this.view.refresh();
+        var me = this,
+            field = me.getGroupField(),
+            menuItem;
+            
+        if (me.hideGroupedHeader) {
+            if (me.lastGroupField) {
+                menuItem = me.getMenuItem(me.lastGroupField);
+                if (menuItem) {
+                    menuItem.setChecked(true);
+                }
+            }
+            if (field) {
+                menuItem = me.getMenuItem(field);
+                if (menuItem) {
+                    menuItem.setChecked(false);
+                }
+            }
+        }
+        if (me.blockRefresh !== true) {
+            me.view.refresh();
+        }
+        me.lastGroupField = field;
+    },
+    
+    /**
+     * Gets the related menu item for a dataIndex
+     * @private
+     * @return {Ext.grid.header.Container} The header
+     */
+    getMenuItem: function(dataIndex){
+        var view = this.view,
+            header = view.headerCt.down('gridcolumn[dataIndex=' + dataIndex + ']'),
+            menu = view.headerCt.getMenu();
+            
+        return menu.down('menuitem[headerId='+ header.id +']');
     },
 
     /**
@@ -504,15 +569,16 @@ Ext.define('Ext.grid.feature.Grouping', {
     // events that are fired on the view. Chose not to return the actual
     // group itself because of its expense and because developers can simply
     // grab the group via store.getGroups(groupName)
-    getFireEventArgs: function(type, view, featureTarget) {
+    getFireEventArgs: function(type, view, featureTarget, e) {
         var returnArray = [type, view, featureTarget],
             groupBd     = Ext.fly(featureTarget.nextSibling, '_grouping'),
             groupBdId   = Ext.getDom(groupBd).id,
             prefix      = view.id + '-gp-',
             groupName   = groupBdId.substr(prefix.length);
         
-        returnArray.push(groupName);
+        returnArray.push(groupName, e);
         
         return returnArray;
     }
 });
+