Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / examples / grid / multiple-sorting.js
index 21e13be..82d4231 100644 (file)
-/*!
- * Ext JS Library 3.2.1
- * Copyright(c) 2006-2010 Ext JS, Inc.
- * licensing@extjs.com
- * http://www.extjs.com/license
- */
-/*!
- * Ext JS Library 3.2.0
- * Copyright(c) 2006-2010 Ext JS, LLC
- * licensing@extjs.com
- * http://www.extjs.com/license
- */
-Ext.onReady(function() {
-    // create the data store
-    var store = new Ext.data.ArrayStore({
-        fields: [
-           {name: 'rating', type: 'int'},
-           {name: 'salary', type: 'float'},
-           {name: 'name'}
-        ]
-    });
+/*
 
-    // manually load local fake data
-    store.loadData(createFakeData(25));
-    
-    var reorderer = new Ext.ux.ToolbarReorderer();
-    var droppable = new Ext.ux.ToolbarDroppable({
-        /**
-         * Creates the new toolbar item from the drop event
-         */
-        createItem: function(data) {
-            var column = this.getColumnFromDragDrop(data);
-            
-            return createSorterButton({
-                text    : column.header,
-                sortData: {
-                    field: column.dataIndex,
-                    direction: "ASC"
-                }
-            });
-        },
+This file is part of Ext JS 4
 
-        /**
-         * Custom canDrop implementation which returns true if a column can be added to the toolbar
-         * @param {Object} data Arbitrary data from the drag source
-         * @return {Boolean} True if the drop is allowed
-         */
-        canDrop: function(dragSource, event, data) {
-            var sorters = getSorters(),
-                column  = this.getColumnFromDragDrop(data);
+Copyright (c) 2011 Sencha Inc
 
-            for (var i=0; i < sorters.length; i++) {
-                if (sorters[i].field == column.dataIndex) return false;
-            }
+Contact:  http://www.sencha.com/contact
 
-            return true;
-        },
-        
-        afterLayout: doSort,
+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.
 
-        /**
-         * Helper function used to find the column that was dragged
-         * @param {Object} data Arbitrary data from
-         */
-        getColumnFromDragDrop: function(data) {
-            var index    = data.header.cellIndex,
-                colModel = grid.colModel,
-                column   = colModel.getColumnById(colModel.getColumnId(index));
+If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
 
-            return column;
-        }
-    });
-    
-    //create the toolbar with the 2 plugins
-    var tbar = new Ext.Toolbar({
-        items  : ['Sorting order:', '-'],
-        plugins: [reorderer, droppable],
-        listeners: {
-            scope    : this,
-            reordered: function(button) {
-                changeSortDirection(button, false);
-            }
-        }
-    });
-    
-    // create the Grid
-    var grid = new Ext.grid.GridPanel({
-        tbar : tbar,
-        store: store,
-        
-        columns: [
-            {header: 'Name',   width: 160, sortable: false, dataIndex: 'name',   id:'company'},
-            {header: 'Rating', width: 125, sortable: false, dataIndex: 'rating'},
-            {header: 'Salary', width: 125, sortable: false, dataIndex: 'salary', renderer: 'usMoney'}
-        ],
-        autoExpandColumn: 'company',
-        stripeRows: true,
-        
-        height: 350,
-        width : 600,
-        title : 'Array Grid',
-        
-        listeners: {
-            scope: this,
-            
-            //here we tell the toolbar's droppable plugin that it can accept items from the columns' dragdrop group
-            render: function() {
-                var dragProxy = grid.getView().columnDrag,
-                    ddGroup   = dragProxy.ddGroup;
-                
-                droppable.addDDGroup(ddGroup);
-            }
-        }
-    });
-    
-    tbar.add(createSorterButton({
-        text: 'Rating',
-        sortData: {
-            field: 'rating',
-            direction: 'DESC'
-        }
-    }));
-    
-    tbar.add(createSorterButton({
-        text: 'Salary',
-        sortData: {
-            field: 'salary',
-            direction: 'ASC'
-        }
-    }));
-    
-    // render the grid to the specified div in the page
-    grid.render('grid-example');
-    doSort();
-    
-    //The following functions are used to get the sorting data from the toolbar and apply it to the store
-    
+*/
+Ext.Loader.setConfig({enabled: true});
+
+Ext.Loader.setPath('Ext.ux', '../ux/');
+
+Ext.require([
+    'Ext.data.*',
+    'Ext.grid.*',
+    'Ext.util.*',
+    'Ext.toolbar.*',
+    'Ext.ux.ToolbarDroppable',
+    'Ext.ux.BoxReorderer'
+]);
+
+Ext.onReady(function() {
+   //The following functions are used to get the sorting data from the toolbar and apply it to the store
     /**
      * Tells the store to sort itself according to our sort data
      */
     function doSort() {
-        store.sort(getSorters(), "ASC");
-    };
-    
+        store.sort(getSorters());
+    }
+
     /**
      * Callback handler used when a sorter button is clicked or reordered
      * @param {Ext.Button} button The button that was clicked
@@ -152,65 +44,63 @@ Ext.onReady(function() {
         var sortData = button.sortData,
             iconCls  = button.iconCls;
         
-        if (sortData != undefined) {
+        if (sortData) {
             if (changeDirection !== false) {
-                button.sortData.direction = button.sortData.direction.toggle("ASC", "DESC");
-                button.setIconClass(iconCls.toggle("sort-asc", "sort-desc"));
+                button.sortData.direction = Ext.String.toggle(button.sortData.direction, "ASC", "DESC");
+                button.setIconCls(Ext.String.toggle(iconCls, "sort-asc", "sort-desc"));
             }
-            
             store.clearFilter();
             doSort();
         }
-    };
-    
+    }
+
     /**
      * Returns an array of sortData from the sorter buttons
      * @return {Array} Ordered sort data from each of the sorter buttons
      */
     function getSorters() {
         var sorters = [];
-        
-        Ext.each(tbar.findByType('button'), function(button) {
+        Ext.each(tbar.query('button'), function(button) {
             sorters.push(button.sortData);
         }, this);
-        
+
         return sorters;
     }
-    
+
     /**
      * Convenience function for creating Toolbar Buttons that are tied to sorters
      * @param {Object} config Optional config object
-     * @return {Ext.Button} The new Button object
+     * @return {Object} The new Button configuration
      */
-    function createSorterButton(config) {
+    function createSorterButtonConfig(config) {
         config = config || {};
-              
         Ext.applyIf(config, {
             listeners: {
                 click: function(button, e) {
-                    changeSortDirection(button, true);                    
+                    changeSortDirection(button, true);
                 }
             },
             iconCls: 'sort-' + config.sortData.direction.toLowerCase(),
-            reorderable: true
+            reorderable: true,
+            xtype: 'button'
         });
-        
-        return new Ext.Button(config);
-    };
-    
+        return config;
+    }
+
     /**
      * Returns an array of fake data
      * @param {Number} count The number of fake rows to create data for
      * @return {Array} The fake record data, suitable for usage with an ArrayReader
      */
     function createFakeData(count) {
-        var firstNames   = ['Ed', 'Tommy', 'Aaron', 'Abe', 'Jamie', 'Adam', 'Dave', 'David', 'Jay'],
-            lastNames    = ['Spencer', 'Maintz', 'Conran', 'Elias', 'Avins', 'Mishcon', 'Kaneda', 'Davis', 'Robinson'],
+        var firstNames   = ['Ed', 'Tommy', 'Aaron', 'Abe', 'Jamie', 'Adam', 'Dave', 'David', 'Jay', 'Nicolas', 'Nige'],
+            lastNames    = ['Spencer', 'Maintz', 'Conran', 'Elias', 'Avins', 'Mishcon', 'Kaneda', 'Davis', 'Robinson', 'Ferrero', 'White'],
             ratings      = [1, 2, 3, 4, 5],
             salaries     = [100, 400, 900, 1500, 1000000];
 
         var data = [];
-        for (var i=0; i < (count || 25); i++) {
+        for (var i = 0; i < (count || 25); i++) {
             var ratingId    = Math.floor(Math.random() * ratings.length),
                 salaryId    = Math.floor(Math.random() * salaries.length),
                 firstNameId = Math.floor(Math.random() * firstNames.length),
@@ -218,11 +108,164 @@ Ext.onReady(function() {
 
                 rating      = ratings[ratingId],
                 salary      = salaries[salaryId],
-                name        = String.format("{0} {1}", firstNames[firstNameId], lastNames[lastNameId]);
+                name        = Ext.String.format("{0} {1}", firstNames[firstNameId], lastNames[lastNameId]);
 
             data.push([rating, salary, name]);
         }
-        
         return data;
     }
-});
\ No newline at end of file
+
+    // create the data store
+    Ext.define('Employee', {
+        extend: 'Ext.data.Model',
+        fields: [
+           {name: 'rating', type: 'int'},
+           {name: 'salary', type: 'float'},
+           {name: 'name'}
+        ]
+    });
+
+    var store = Ext.create('Ext.data.Store', {
+        model: 'Employee',
+        proxy: {
+            type: 'memory',
+            data: createFakeData(25),
+            reader: {
+                type: 'array'
+            }
+        },
+        autoLoad: true
+    });
+
+    var reorderer = Ext.create('Ext.ux.BoxReorderer', {
+        listeners: {
+            scope: this,
+            Drop: function(r, c, button) { //update sort direction when button is dropped
+                changeSortDirection(button, false);
+            }
+        }
+    });
+
+    var droppable = Ext.create('Ext.ux.ToolbarDroppable', {
+        /**
+         * Creates the new toolbar item from the drop event
+         */
+        createItem: function(data) {
+            var header = data.header,
+                headerCt = header.ownerCt,
+                reorderer = headerCt.reorderer;
+            
+            // Hide the drop indicators of the standard HeaderDropZone
+            // in case user had a pending valid drop in 
+            if (reorderer) {
+                reorderer.dropZone.invalidateDrop();
+            }
+
+            return createSorterButtonConfig({
+                text: header.text,
+                sortData: {
+                    property: header.dataIndex,
+                    direction: "ASC"
+                }
+            });
+        },
+
+        /**
+         * Custom canDrop implementation which returns true if a column can be added to the toolbar
+         * @param {Object} data Arbitrary data from the drag source. For a HeaderContainer, it will
+         * contain a header property which is the Header being dragged.
+         * @return {Boolean} True if the drop is allowed
+         */
+        canDrop: function(dragSource, event, data) {
+            var sorters = getSorters(),
+                header  = data.header,
+                length = sorters.length,
+                entryIndex = this.calculateEntryIndex(event),
+                targetItem = this.toolbar.getComponent(entryIndex),
+                i;
+
+            // Group columns have no dataIndex and therefore cannot be sorted
+            // If target isn't reorderable it could not be replaced
+            if (!header.dataIndex || (targetItem && targetItem.reorderable === false)) {
+                return false;
+            }
+
+            for (i = 0; i < length; i++) {
+                if (sorters[i].property == header.dataIndex) {
+                    return false;
+                }
+            }
+            return true;
+        },
+
+        afterLayout: doSort
+    });
+
+    //create the toolbar with the 2 plugins
+    var tbar = Ext.create('Ext.toolbar.Toolbar', {
+        items  : [{
+            xtype: 'tbtext',
+            text: 'Sorting order:',
+            reorderable: false
+        }, '-'],
+        plugins: [reorderer, droppable]
+    });
+
+    tbar.add(createSorterButtonConfig({
+        text: 'Rating',
+        sortData: {
+            property: 'rating',
+            direction: 'DESC'
+        }
+    }));
+
+    tbar.add(createSorterButtonConfig({
+        text: 'Salary',
+        sortData: {
+            property: 'salary',
+            direction: 'ASC'
+        }
+    }));
+
+    // create the Grid
+    var grid = Ext.create('Ext.grid.Panel', {
+        tbar : tbar,
+        store: store,
+        columns: [
+            {
+                text: 'Name',
+                flex:1 ,
+                sortable: false,
+                dataIndex: 'name'
+            },{
+                text: 'Rating',
+                width: 125,
+                sortable: false,
+                dataIndex: 'rating'
+            },{
+                text: 'Salary',
+                width: 125,
+                sortable: false,
+                dataIndex: 'salary',
+                align: 'right',
+                renderer: Ext.util.Format.usMoney
+            }
+        ],
+        stripeRows: true,
+        height: 350,
+        width : 600,
+        title : 'Array Grid',
+        renderTo: 'grid-example',
+        listeners: {
+            scope: this,
+            // wait for the first layout to access the headerCt (we only want this once):
+            single: true,
+            // tell the toolbar's droppable plugin that it accepts items from the columns' dragdrop group
+            afterlayout: function(grid) {
+                var headerCt = grid.child("headercontainer");
+                droppable.addDDGroup(headerCt.reorderer.dragZone.ddGroup);
+                doSort();
+            }
+        }
+    });
+});