Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / examples / grid / multiple-sorting.js
index 7b6b17f..6797e77 100644 (file)
-/*!
- * Ext JS Library 3.3.1
- * Copyright(c) 2006-2010 Sencha Inc.
- * licensing@sencha.com
- * http://www.sencha.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"
-                }
-            });
-        },
-
-        /**
-         * 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);
+Ext.Loader.setConfig({enabled: true});
 
-            for (var i=0; i < sorters.length; i++) {
-                if (sorters[i].field == column.dataIndex) return false;
-            }
+Ext.Loader.setPath('Ext.ux', '../ux/');
 
-            return true;
-        },
-        
-        afterLayout: doSort,
+Ext.require([
+    'Ext.data.*',
+    'Ext.grid.*',
+    'Ext.util.*',
+    'Ext.toolbar.*',
+    'Ext.ux.ToolbarDroppable',
+    'Ext.ux.BoxReorderer'
+]);
 
-        /**
-         * 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));
-
-            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.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
@@ -146,65 +30,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),
@@ -212,11 +94,165 @@ 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;
     }
+
+    // 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,
+            //here we tell the toolbar's droppable plugin that it can accept items from the columns' dragdrop group
+            afterrender: function(grid) {
+                var headerCt = grid.child("headercontainer"),
+                    //the plugin position depends on browser see Ext.grid.header.Container sources
+                    dragProxy = headerCt.plugins[0].dragZone || headerCt.plugins[1].dragZone;
+
+                droppable.addDDGroup(dragProxy.ddGroup);
+                doSort();
+            }
+        }
+    });
 });
\ No newline at end of file