Upgrade to ExtJS 3.2.0 - Released 03/30/2010
[extjs.git] / examples / ux / RowExpander.js
index a799ad1..34bdd79 100644 (file)
 /*!
- * Ext JS Library 3.1.1
- * Copyright(c) 2006-2010 Ext JS, LLC
+ * Ext JS Library 3.2.0
+ * Copyright(c) 2006-2010 Ext JS, Inc.
  * licensing@extjs.com
  * http://www.extjs.com/license
  */
-Ext.ns('Ext.ux.grid');\r
-\r
-/**\r
- * @class Ext.ux.grid.RowExpander\r
- * @extends Ext.util.Observable\r
- * Plugin (ptype = 'rowexpander') that adds the ability to have a Column in a grid which enables\r
- * a second row body which expands/contracts.  The expand/contract behavior is configurable to react\r
- * on clicking of the column, double click of the row, and/or hitting enter while a row is selected.\r
- *\r
- * @ptype rowexpander\r
- */\r
-Ext.ux.grid.RowExpander = Ext.extend(Ext.util.Observable, {\r
-    /**\r
-     * @cfg {Boolean} expandOnEnter\r
-     * <tt>true</tt> to toggle selected row(s) between expanded/collapsed when the enter\r
-     * key is pressed (defaults to <tt>true</tt>).\r
-     */\r
-    expandOnEnter : true,\r
-    /**\r
-     * @cfg {Boolean} expandOnDblClick\r
-     * <tt>true</tt> to toggle a row between expanded/collapsed when double clicked\r
-     * (defaults to <tt>true</tt>).\r
-     */\r
-    expandOnDblClick : true,\r
-\r
-    header : '',\r
-    width : 20,\r
-    sortable : false,\r
-    fixed : true,\r
-    menuDisabled : true,\r
-    dataIndex : '',\r
-    id : 'expander',\r
-    lazyRender : true,\r
-    enableCaching : true,\r
-\r
-    constructor: function(config){\r
-        Ext.apply(this, config);\r
-\r
-        this.addEvents({\r
-            /**\r
-             * @event beforeexpand\r
-             * Fires before the row expands. Have the listener return false to prevent the row from expanding.\r
-             * @param {Object} this RowExpander object.\r
-             * @param {Object} Ext.data.Record Record for the selected row.\r
-             * @param {Object} body body element for the secondary row.\r
-             * @param {Number} rowIndex The current row index.\r
-             */\r
-            beforeexpand: true,\r
-            /**\r
-             * @event expand\r
-             * Fires after the row expands.\r
-             * @param {Object} this RowExpander object.\r
-             * @param {Object} Ext.data.Record Record for the selected row.\r
-             * @param {Object} body body element for the secondary row.\r
-             * @param {Number} rowIndex The current row index.\r
-             */\r
-            expand: true,\r
-            /**\r
-             * @event beforecollapse\r
-             * Fires before the row collapses. Have the listener return false to prevent the row from collapsing.\r
-             * @param {Object} this RowExpander object.\r
-             * @param {Object} Ext.data.Record Record for the selected row.\r
-             * @param {Object} body body element for the secondary row.\r
-             * @param {Number} rowIndex The current row index.\r
-             */\r
-            beforecollapse: true,\r
-            /**\r
-             * @event collapse\r
-             * Fires after the row collapses.\r
-             * @param {Object} this RowExpander object.\r
-             * @param {Object} Ext.data.Record Record for the selected row.\r
-             * @param {Object} body body element for the secondary row.\r
-             * @param {Number} rowIndex The current row index.\r
-             */\r
-            collapse: true\r
-        });\r
-\r
-        Ext.ux.grid.RowExpander.superclass.constructor.call(this);\r
-\r
-        if(this.tpl){\r
-            if(typeof this.tpl == 'string'){\r
-                this.tpl = new Ext.Template(this.tpl);\r
-            }\r
-            this.tpl.compile();\r
-        }\r
-\r
-        this.state = {};\r
-        this.bodyContent = {};\r
-    },\r
-\r
-    getRowClass : function(record, rowIndex, p, ds){\r
-        p.cols = p.cols-1;\r
-        var content = this.bodyContent[record.id];\r
-        if(!content && !this.lazyRender){\r
-            content = this.getBodyContent(record, rowIndex);\r
-        }\r
-        if(content){\r
-            p.body = content;\r
-        }\r
-        return this.state[record.id] ? 'x-grid3-row-expanded' : 'x-grid3-row-collapsed';\r
-    },\r
-\r
-    init : function(grid){\r
-        this.grid = grid;\r
-\r
-        var view = grid.getView();\r
-        view.getRowClass = this.getRowClass.createDelegate(this);\r
-\r
-        view.enableRowBody = true;\r
-\r
-\r
-        grid.on('render', this.onRender, this);\r
-        grid.on('destroy', this.onDestroy, this);\r
-    },\r
-\r
-    // @private\r
-    onRender: function() {\r
-        var grid = this.grid;\r
-        var mainBody = grid.getView().mainBody;\r
-        mainBody.on('mousedown', this.onMouseDown, this, {delegate: '.x-grid3-row-expander'});\r
-        if (this.expandOnEnter) {\r
-            this.keyNav = new Ext.KeyNav(this.grid.getGridEl(), {\r
-                'enter' : this.onEnter,\r
-                scope: this\r
-            });\r
-        }\r
-        if (this.expandOnDblClick) {\r
-            grid.on('rowdblclick', this.onRowDblClick, this);\r
-        }\r
-    },\r
-    \r
-    // @private    \r
-    onDestroy: function() {\r
-        if(this.keyNav){\r
-            this.keyNav.disable();\r
-            delete this.keyNav;\r
-        }\r
-        /*\r
-         * A majority of the time, the plugin will be destroyed along with the grid,\r
-         * which means the mainBody won't be available. On the off chance that the plugin\r
-         * isn't destroyed with the grid, take care of removing the listener.\r
-         */\r
-        var mainBody = this.grid.getView().mainBody;\r
-        if(mainBody){\r
-            mainBody.un('mousedown', this.onMouseDown, this);\r
-        }\r
-    },\r
-    // @private\r
-    onRowDblClick: function(grid, rowIdx, e) {\r
-        this.toggleRow(rowIdx);\r
-    },\r
-\r
-    onEnter: function(e) {\r
-        var g = this.grid;\r
-        var sm = g.getSelectionModel();\r
-        var sels = sm.getSelections();\r
-        for (var i = 0, len = sels.length; i < len; i++) {\r
-            var rowIdx = g.getStore().indexOf(sels[i]);\r
-            this.toggleRow(rowIdx);\r
-        }\r
-    },\r
-\r
-    getBodyContent : function(record, index){\r
-        if(!this.enableCaching){\r
-            return this.tpl.apply(record.data);\r
-        }\r
-        var content = this.bodyContent[record.id];\r
-        if(!content){\r
-            content = this.tpl.apply(record.data);\r
-            this.bodyContent[record.id] = content;\r
-        }\r
-        return content;\r
-    },\r
-\r
-    onMouseDown : function(e, t){\r
-        e.stopEvent();\r
-        var row = e.getTarget('.x-grid3-row');\r
-        this.toggleRow(row);\r
-    },\r
-\r
-    renderer : function(v, p, record){\r
-        p.cellAttr = 'rowspan="2"';\r
-        return '<div class="x-grid3-row-expander">&#160;</div>';\r
-    },\r
-\r
-    beforeExpand : function(record, body, rowIndex){\r
-        if(this.fireEvent('beforeexpand', this, record, body, rowIndex) !== false){\r
-            if(this.tpl && this.lazyRender){\r
-                body.innerHTML = this.getBodyContent(record, rowIndex);\r
-            }\r
-            return true;\r
-        }else{\r
-            return false;\r
-        }\r
-    },\r
-\r
-    toggleRow : function(row){\r
-        if(typeof row == 'number'){\r
-            row = this.grid.view.getRow(row);\r
-        }\r
-        this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'collapseRow'](row);\r
-    },\r
-\r
-    expandRow : function(row){\r
-        if(typeof row == 'number'){\r
-            row = this.grid.view.getRow(row);\r
-        }\r
-        var record = this.grid.store.getAt(row.rowIndex);\r
-        var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row);\r
-        if(this.beforeExpand(record, body, row.rowIndex)){\r
-            this.state[record.id] = true;\r
-            Ext.fly(row).replaceClass('x-grid3-row-collapsed', 'x-grid3-row-expanded');\r
-            this.fireEvent('expand', this, record, body, row.rowIndex);\r
-        }\r
-    },\r
-\r
-    collapseRow : function(row){\r
-        if(typeof row == 'number'){\r
-            row = this.grid.view.getRow(row);\r
-        }\r
-        var record = this.grid.store.getAt(row.rowIndex);\r
-        var body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true);\r
-        if(this.fireEvent('beforecollapse', this, record, body, row.rowIndex) !== false){\r
-            this.state[record.id] = false;\r
-            Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed');\r
-            this.fireEvent('collapse', this, record, body, row.rowIndex);\r
-        }\r
-    }\r
-});\r
-\r
-Ext.preg('rowexpander', Ext.ux.grid.RowExpander);\r
-\r
-//backwards compat\r
+Ext.ns('Ext.ux.grid');
+
+/**
+ * @class Ext.ux.grid.RowExpander
+ * @extends Ext.util.Observable
+ * Plugin (ptype = 'rowexpander') that adds the ability to have a Column in a grid which enables
+ * a second row body which expands/contracts.  The expand/contract behavior is configurable to react
+ * on clicking of the column, double click of the row, and/or hitting enter while a row is selected.
+ *
+ * @ptype rowexpander
+ */
+Ext.ux.grid.RowExpander = Ext.extend(Ext.util.Observable, {
+    /**
+     * @cfg {Boolean} expandOnEnter
+     * <tt>true</tt> to toggle selected row(s) between expanded/collapsed when the enter
+     * key is pressed (defaults to <tt>true</tt>).
+     */
+    expandOnEnter : true,
+    /**
+     * @cfg {Boolean} expandOnDblClick
+     * <tt>true</tt> to toggle a row between expanded/collapsed when double clicked
+     * (defaults to <tt>true</tt>).
+     */
+    expandOnDblClick : true,
+
+    header : '',
+    width : 20,
+    sortable : false,
+    fixed : true,
+    hideable: false,
+    menuDisabled : true,
+    dataIndex : '',
+    id : 'expander',
+    lazyRender : true,
+    enableCaching : true,
+
+    constructor: function(config){
+        Ext.apply(this, config);
+
+        this.addEvents({
+            /**
+             * @event beforeexpand
+             * Fires before the row expands. Have the listener return false to prevent the row from expanding.
+             * @param {Object} this RowExpander object.
+             * @param {Object} Ext.data.Record Record for the selected row.
+             * @param {Object} body body element for the secondary row.
+             * @param {Number} rowIndex The current row index.
+             */
+            beforeexpand: true,
+            /**
+             * @event expand
+             * Fires after the row expands.
+             * @param {Object} this RowExpander object.
+             * @param {Object} Ext.data.Record Record for the selected row.
+             * @param {Object} body body element for the secondary row.
+             * @param {Number} rowIndex The current row index.
+             */
+            expand: true,
+            /**
+             * @event beforecollapse
+             * Fires before the row collapses. Have the listener return false to prevent the row from collapsing.
+             * @param {Object} this RowExpander object.
+             * @param {Object} Ext.data.Record Record for the selected row.
+             * @param {Object} body body element for the secondary row.
+             * @param {Number} rowIndex The current row index.
+             */
+            beforecollapse: true,
+            /**
+             * @event collapse
+             * Fires after the row collapses.
+             * @param {Object} this RowExpander object.
+             * @param {Object} Ext.data.Record Record for the selected row.
+             * @param {Object} body body element for the secondary row.
+             * @param {Number} rowIndex The current row index.
+             */
+            collapse: true
+        });
+
+        Ext.ux.grid.RowExpander.superclass.constructor.call(this);
+
+        if(this.tpl){
+            if(typeof this.tpl == 'string'){
+                this.tpl = new Ext.Template(this.tpl);
+            }
+            this.tpl.compile();
+        }
+
+        this.state = {};
+        this.bodyContent = {};
+    },
+
+    getRowClass : function(record, rowIndex, p, ds){
+        p.cols = p.cols-1;
+        var content = this.bodyContent[record.id];
+        if(!content && !this.lazyRender){
+            content = this.getBodyContent(record, rowIndex);
+        }
+        if(content){
+            p.body = content;
+        }
+        return this.state[record.id] ? 'x-grid3-row-expanded' : 'x-grid3-row-collapsed';
+    },
+
+    init : function(grid){
+        this.grid = grid;
+
+        var view = grid.getView();
+        view.getRowClass = this.getRowClass.createDelegate(this);
+
+        view.enableRowBody = true;
+
+
+        grid.on('render', this.onRender, this);
+        grid.on('destroy', this.onDestroy, this);
+    },
+
+    // @private
+    onRender: function() {
+        var grid = this.grid;
+        var mainBody = grid.getView().mainBody;
+        mainBody.on('mousedown', this.onMouseDown, this, {delegate: '.x-grid3-row-expander'});
+        if (this.expandOnEnter) {
+            this.keyNav = new Ext.KeyNav(this.grid.getGridEl(), {
+                'enter' : this.onEnter,
+                scope: this
+            });
+        }
+        if (this.expandOnDblClick) {
+            grid.on('rowdblclick', this.onRowDblClick, this);
+        }
+    },
+    
+    // @private    
+    onDestroy: function() {
+        if(this.keyNav){
+            this.keyNav.disable();
+            delete this.keyNav;
+        }
+        /*
+         * A majority of the time, the plugin will be destroyed along with the grid,
+         * which means the mainBody won't be available. On the off chance that the plugin
+         * isn't destroyed with the grid, take care of removing the listener.
+         */
+        var mainBody = this.grid.getView().mainBody;
+        if(mainBody){
+            mainBody.un('mousedown', this.onMouseDown, this);
+        }
+    },
+    // @private
+    onRowDblClick: function(grid, rowIdx, e) {
+        this.toggleRow(rowIdx);
+    },
+
+    onEnter: function(e) {
+        var g = this.grid;
+        var sm = g.getSelectionModel();
+        var sels = sm.getSelections();
+        for (var i = 0, len = sels.length; i < len; i++) {
+            var rowIdx = g.getStore().indexOf(sels[i]);
+            this.toggleRow(rowIdx);
+        }
+    },
+
+    getBodyContent : function(record, index){
+        if(!this.enableCaching){
+            return this.tpl.apply(record.data);
+        }
+        var content = this.bodyContent[record.id];
+        if(!content){
+            content = this.tpl.apply(record.data);
+            this.bodyContent[record.id] = content;
+        }
+        return content;
+    },
+
+    onMouseDown : function(e, t){
+        e.stopEvent();
+        var row = e.getTarget('.x-grid3-row');
+        this.toggleRow(row);
+    },
+
+    renderer : function(v, p, record){
+        p.cellAttr = 'rowspan="2"';
+        return '<div class="x-grid3-row-expander">&#160;</div>';
+    },
+
+    beforeExpand : function(record, body, rowIndex){
+        if(this.fireEvent('beforeexpand', this, record, body, rowIndex) !== false){
+            if(this.tpl && this.lazyRender){
+                body.innerHTML = this.getBodyContent(record, rowIndex);
+            }
+            return true;
+        }else{
+            return false;
+        }
+    },
+
+    toggleRow : function(row){
+        if(typeof row == 'number'){
+            row = this.grid.view.getRow(row);
+        }
+        this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'collapseRow'](row);
+    },
+
+    expandRow : function(row){
+        if(typeof row == 'number'){
+            row = this.grid.view.getRow(row);
+        }
+        var record = this.grid.store.getAt(row.rowIndex);
+        var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row);
+        if(this.beforeExpand(record, body, row.rowIndex)){
+            this.state[record.id] = true;
+            Ext.fly(row).replaceClass('x-grid3-row-collapsed', 'x-grid3-row-expanded');
+            this.fireEvent('expand', this, record, body, row.rowIndex);
+        }
+    },
+
+    collapseRow : function(row){
+        if(typeof row == 'number'){
+            row = this.grid.view.getRow(row);
+        }
+        var record = this.grid.store.getAt(row.rowIndex);
+        var body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true);
+        if(this.fireEvent('beforecollapse', this, record, body, row.rowIndex) !== false){
+            this.state[record.id] = false;
+            Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed');
+            this.fireEvent('collapse', this, record, body, row.rowIndex);
+        }
+    }
+});
+
+Ext.preg('rowexpander', Ext.ux.grid.RowExpander);
+
+//backwards compat
 Ext.grid.RowExpander = Ext.ux.grid.RowExpander;
\ No newline at end of file