| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947 | 
							- <!DOCTYPE html>
 
- <html>
 
- <head>
 
-   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 
-   <title>The source code</title>
 
-   <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
 
-   <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
 
-   <style type="text/css">
 
-     .highlight { display: block; background-color: #ddd; }
 
-   </style>
 
-   <script type="text/javascript">
 
-     function highlight() {
 
-       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
 
-     }
 
-   </script>
 
- </head>
 
- <body onload="prettyPrint(); highlight();">
 
-   <pre class="prettyprint lang-js"><span id='Ext-grid-Lockable'>/**
 
- </span> * @private
 
-  *
 
-  * Lockable is a private mixin which injects lockable behavior into any
 
-  * TablePanel subclass such as GridPanel or TreePanel. TablePanel will
 
-  * automatically inject the Ext.grid.Lockable mixin in when one of the
 
-  * these conditions are met:
 
-  *
 
-  *  - The TablePanel has the lockable configuration set to true
 
-  *  - One of the columns in the TablePanel has locked set to true/false
 
-  *
 
-  * Each TablePanel subclass must register an alias. It should have an array
 
-  * of configurations to copy to the 2 separate tablepanel's that will be generated
 
-  * to note what configurations should be copied. These are named normalCfgCopy and
 
-  * lockedCfgCopy respectively.
 
-  *
 
-  * Columns which are locked must specify a fixed width. They do NOT support a
 
-  * flex width.
 
-  *
 
-  * Configurations which are specified in this class will be available on any grid or
 
-  * tree which is using the lockable functionality.
 
-  */
 
- Ext.define('Ext.grid.Lockable', {
 
-     requires: [
 
-         'Ext.grid.LockingView',
 
-         'Ext.view.Table'
 
-     ],
 
- <span id='Ext-grid-Lockable-cfg-syncRowHeight'>    /**
 
- </span>     * @cfg {Boolean} syncRowHeight Synchronize rowHeight between the normal and
 
-      * locked grid view. This is turned on by default. If your grid is guaranteed
 
-      * to have rows of all the same height, you should set this to false to
 
-      * optimize performance.
 
-      */
 
-     syncRowHeight: true,
 
- <span id='Ext-grid-Lockable-cfg-subGridXType'>    /**
 
- </span>     * @cfg {String} subGridXType The xtype of the subgrid to specify. If this is
 
-      * not specified lockable will determine the subgrid xtype to create by the
 
-      * following rule. Use the superclasses xtype if the superclass is NOT
 
-      * tablepanel, otherwise use the xtype itself.
 
-      */
 
- <span id='Ext-grid-Lockable-cfg-lockedViewConfig'>    /**
 
- </span>     * @cfg {Object} lockedViewConfig A view configuration to be applied to the
 
-      * locked side of the grid. Any conflicting configurations between lockedViewConfig
 
-      * and viewConfig will be overwritten by the lockedViewConfig.
 
-      */
 
- <span id='Ext-grid-Lockable-cfg-normalViewConfig'>    /**
 
- </span>     * @cfg {Object} normalViewConfig A view configuration to be applied to the
 
-      * normal/unlocked side of the grid. Any conflicting configurations between normalViewConfig
 
-      * and viewConfig will be overwritten by the normalViewConfig.
 
-      */
 
-     headerCounter: 0,
 
- <span id='Ext-grid-Lockable-cfg-scrollDelta'>    /**
 
- </span>     * @cfg {Number} scrollDelta
 
-      * Number of pixels to scroll when scrolling the locked section with mousewheel.
 
-      */
 
-     scrollDelta: 40,
 
-     
 
- <span id='Ext-grid-Lockable-cfg-lockedGridConfig'>    /**
 
- </span>     * @cfg {Object} lockedGridConfig
 
-      * Any special configuration options for the locked part of the grid
 
-      */
 
-     
 
- <span id='Ext-grid-Lockable-cfg-normalGridConfig'>    /**
 
- </span>     * @cfg {Object} normalGridConfig
 
-      * Any special configuration options for the normal part of the grid
 
-      */
 
-     // i8n text
 
-     //<locale>
 
-     unlockText: 'Unlock',
 
-     //</locale>
 
-     //<locale>
 
-     lockText: 'Lock',
 
-     //</locale>
 
-     determineXTypeToCreate: function() {
 
-         var me = this,
 
-             typeToCreate,
 
-             xtypes, xtypesLn, xtype, superxtype;
 
-         if (me.subGridXType) {
 
-             typeToCreate = me.subGridXType;
 
-         } else {
 
-             xtypes     = this.getXTypes().split('/');
 
-             xtypesLn   = xtypes.length;
 
-             xtype      = xtypes[xtypesLn - 1];
 
-             superxtype = xtypes[xtypesLn - 2];
 
-             if (superxtype !== 'tablepanel') {
 
-                 typeToCreate = superxtype;
 
-             } else {
 
-                 typeToCreate = xtype;
 
-             }
 
-         }
 
-         return typeToCreate;
 
-     },
 
-     // injectLockable will be invoked before initComponent's parent class implementation
 
-     // is called, so throughout this method this. are configurations
 
-     injectLockable: function() {
 
-         // ensure lockable is set to true in the TablePanel
 
-         this.lockable = true;
 
-         // Instruct the TablePanel it already has a view and not to create one.
 
-         // We are going to aggregate 2 copies of whatever TablePanel we are using
 
-         this.hasView = true;
 
-         var me = this,
 
-             // If the OS does not show a space-taking scrollbar, the locked view can be overflow:auto
 
-             scrollLocked = Ext.getScrollbarSize().width === 0,
 
-             store = me.store = Ext.StoreManager.lookup(me.store),
 
-             // xtype of this class, 'treepanel' or 'gridpanel'
 
-             // (Note: this makes it a requirement that any subclass that wants to use lockable functionality needs to register an
 
-             // alias.)
 
-             xtype = me.determineXTypeToCreate(),
 
-             // share the selection model
 
-             selModel = me.getSelectionModel(),
 
-             lockedFeatures,
 
-             normalFeatures,
 
-             lockedPlugins,
 
-             normalPlugins,
 
-             lockedGrid,
 
-             normalGrid,
 
-             i, len,
 
-             columns,
 
-             lockedHeaderCt,
 
-             normalHeaderCt,
 
-             lockedView,
 
-             normalView,
 
-             listeners;
 
-         lockedFeatures = me.constructFeatures();
 
-         // Clone any Features in the Array which are already instantiated
 
-         me.cloneFeatures();
 
-         normalFeatures = me.constructFeatures();
 
-         lockedPlugins = me.constructPlugins();
 
-         // Clone any Plugins in the Array which are already instantiated
 
-         me.clonePlugins();
 
-         normalPlugins = me.constructPlugins();
 
-         // The "shell" Panel which just acts as a Container for the two grids must not use the features and plugins
 
-         delete me.features;
 
-         delete me.plugins;
 
-         // Each Feature must have a reference to its counterpart on the opposite side of the locking view
 
-         for (i = 0, len = (lockedFeatures ? lockedFeatures.length : 0); i < len; i++) {
 
-             lockedFeatures[i].lockingPartner = normalFeatures[i];
 
-             normalFeatures[i].lockingPartner = lockedFeatures[i];
 
-         }
 
-         lockedGrid = Ext.apply({
 
-             xtype: xtype,
 
-             store: store,
 
-             scrollerOwner: false,
 
-             // Lockable does NOT support animations for Tree
 
-             enableAnimations: false,
 
-             scroll: scrollLocked ? 'vertical' : false,
 
-             selModel: selModel,
 
-             border: false,
 
-             cls: Ext.baseCSSPrefix + 'grid-inner-locked',
 
-             isLayoutRoot: function() {
 
-                 return false;
 
-             },
 
-             features: lockedFeatures,
 
-             plugins: lockedPlugins
 
-         }, me.lockedGridConfig);
 
-         normalGrid = Ext.apply({
 
-             xtype: xtype,
 
-             store: store,
 
-             scrollerOwner: false,
 
-             enableAnimations: false,
 
-             selModel: selModel,
 
-             border: false,
 
-             isLayoutRoot: function() {
 
-                 return false;
 
-             },
 
-             features: normalFeatures,
 
-             plugins: normalPlugins
 
-         }, me.normalGridConfig);
 
-         me.addCls(Ext.baseCSSPrefix + 'grid-locked');
 
-         // copy appropriate configurations to the respective
 
-         // aggregated tablepanel instances and then delete them
 
-         // from the master tablepanel.
 
-         Ext.copyTo(normalGrid, me, me.bothCfgCopy);
 
-         Ext.copyTo(lockedGrid, me, me.bothCfgCopy);
 
-         Ext.copyTo(normalGrid, me, me.normalCfgCopy);
 
-         Ext.copyTo(lockedGrid, me, me.lockedCfgCopy);
 
-         for (i = 0; i < me.normalCfgCopy.length; i++) {
 
-             delete me[me.normalCfgCopy[i]];
 
-         }
 
-         for (i = 0; i < me.lockedCfgCopy.length; i++) {
 
-             delete me[me.lockedCfgCopy[i]];
 
-         }
 
-         me.addEvents(
 
- <span id='Ext-grid-Lockable-event-lockcolumn'>            /**
 
- </span>             * @event lockcolumn
 
-              * Fires when a column is locked.
 
-              * @param {Ext.grid.Panel} this The gridpanel.
 
-              * @param {Ext.grid.column.Column} column The column being locked.
 
-              */
 
-             'lockcolumn',
 
- <span id='Ext-grid-Lockable-event-unlockcolumn'>            /**
 
- </span>             * @event unlockcolumn
 
-              * Fires when a column is unlocked.
 
-              * @param {Ext.grid.Panel} this The gridpanel.
 
-              * @param {Ext.grid.column.Column} column The column being unlocked.
 
-              */
 
-             'unlockcolumn'
 
-         );
 
-         me.addStateEvents(['lockcolumn', 'unlockcolumn']);
 
-         me.lockedHeights = [];
 
-         me.normalHeights = [];
 
-         columns = me.processColumns(me.columns);
 
-         lockedGrid.width = columns.lockedWidth + Ext.num(selModel.headerWidth, 0);
 
-         lockedGrid.columns = columns.locked;
 
-         normalGrid.columns = columns.normal;
 
-         // normal grid should flex the rest of the width
 
-         normalGrid.flex = 1;
 
-         lockedGrid.viewConfig = me.lockedViewConfig || {};
 
-         lockedGrid.viewConfig.loadingUseMsg = false;
 
-         normalGrid.viewConfig = me.normalViewConfig || {};
 
-         Ext.applyIf(lockedGrid.viewConfig, me.viewConfig);
 
-         Ext.applyIf(normalGrid.viewConfig, me.viewConfig);
 
-         me.lockedGrid = Ext.ComponentManager.create(lockedGrid);
 
-         lockedView = me.lockedGrid.getView();
 
-         
 
-         normalGrid.viewConfig.lockingPartner = lockedView;
 
-         me.normalGrid = Ext.ComponentManager.create(normalGrid);
 
-         normalView = me.normalGrid.getView();
 
-         me.view = new Ext.grid.LockingView({
 
-             locked: me.lockedGrid,
 
-             normal: me.normalGrid,
 
-             panel: me
 
-         });
 
-         // Set up listeners for the locked view. If its SelModel ever scrolls it, the normal view must sync
 
-         listeners = {
 
-             scroll: {
 
-                 fn: me.onLockedViewScroll,
 
-                 element: 'el',
 
-                 scope: me
 
-             }
 
-         };
 
-         // If there are system scrollbars, we have to monitor the mousewheel and fake a scroll
 
-         if (!scrollLocked) {
 
-             listeners.mousewheel = {
 
-                 fn: me.onLockedViewMouseWheel,
 
-                 element: 'el',
 
-                 scope: me
 
-             };
 
-         }
 
-         if (me.syncRowHeight) {
 
-             listeners.refresh = me.onLockedViewRefresh;
 
-             listeners.itemupdate = me.onLockedViewItemUpdate;
 
-             listeners.scope = me;
 
-         }
 
-         lockedView.on(listeners);
 
-         // Set up listeners for the normal view
 
-         listeners = {
 
-             scroll: {
 
-                 fn: me.onNormalViewScroll,
 
-                 element: 'el',
 
-                 scope: me
 
-             },
 
-             refresh: me.syncRowHeight ? me.onNormalViewRefresh : me.updateSpacer,
 
-             scope: me
 
-         };
 
-         normalView.on(listeners);
 
-         lockedHeaderCt = me.lockedGrid.headerCt;
 
-         normalHeaderCt = me.normalGrid.headerCt;
 
-         lockedHeaderCt.lockedCt = true;
 
-         lockedHeaderCt.lockableInjected = true;
 
-         normalHeaderCt.lockableInjected = true;
 
-         lockedHeaderCt.on({
 
-             columnshow: me.onLockedHeaderShow,
 
-             columnhide: me.onLockedHeaderHide,
 
-             columnmove: me.onLockedHeaderMove,
 
-             sortchange: me.onLockedHeaderSortChange,
 
-             columnresize: me.onLockedHeaderResize,
 
-             scope: me
 
-         });
 
-         normalHeaderCt.on({
 
-             columnmove: me.onNormalHeaderMove,
 
-             sortchange: me.onNormalHeaderSortChange,
 
-             scope: me
 
-         });
 
-         me.modifyHeaderCt();
 
-         me.items = [me.lockedGrid, me.normalGrid];
 
-         me.relayHeaderCtEvents(lockedHeaderCt);
 
-         me.relayHeaderCtEvents(normalHeaderCt);
 
-         me.layout = {
 
-             type: 'hbox',
 
-             align: 'stretch'
 
-         };
 
-     },
 
-     processColumns: function(columns){
 
-         // split apart normal and lockedWidths
 
-         var i = 0,
 
-             len = columns.length,
 
-             lockedWidth = 0,
 
-             lockedHeaders = [],
 
-             normalHeaders = [],
 
-             column;
 
-         for (; i < len; ++i) {
 
-             column = columns[i];
 
-             // MUST clone the column config because we mutate it, and we must not mutate passed in config objects in case they are re-used
 
-             // eg, in an extend-to-configure scenario.
 
-             if (!column.isComponent) {
 
-                 column = Ext.apply({}, columns[i]);
 
-             }
 
-             // mark the column as processed so that the locked attribute does not
 
-             // trigger trying to aggregate the columns again.
 
-             column.processed = true;
 
-             if (column.locked) {
 
-                 // <debug>
 
-                 if (column.flex) {
 
-                     Ext.Error.raise("Columns which are locked do NOT support a flex width. You must set a width on the " + columns[i].text + "column.");
 
-                 }
 
-                 // </debug>
 
-                 if (!column.hidden) {
 
-                     lockedWidth += column.width || Ext.grid.header.Container.prototype.defaultWidth;
 
-                 }
 
-                 lockedHeaders.push(column);
 
-             } else {
 
-                 normalHeaders.push(column);
 
-             }
 
-             if (!column.headerId) {
 
-                 column.headerId = (column.initialConfig || column).id || ('L' + (++this.headerCounter));
 
-             }
 
-         }
 
-         return {
 
-             lockedWidth: lockedWidth,
 
-             locked: {
 
-                 items: lockedHeaders,
 
-                 itemId: 'lockedHeaderCt',
 
-                 stretchMaxPartner: '^^>>#normalHeaderCt'
 
-             },
 
-             normal: {
 
-                 items: normalHeaders,
 
-                 itemId: 'normalHeaderCt',
 
-                 stretchMaxPartner: '^^>>#lockedHeaderCt'
 
-             }
 
-         };
 
-     },
 
- <span id='Ext-grid-Lockable-method-onLockedViewMouseWheel'>    /**
 
- </span>     * @private
 
-      * Listen for mousewheel events on the locked section which does not scroll.
 
-      * Scroll it in response, and the other section will automatically sync.
 
-      */
 
-     onLockedViewMouseWheel: function(e) {
 
-         var me = this,
 
-             scrollDelta = -me.scrollDelta,
 
-             deltaY = scrollDelta * e.getWheelDeltas().y,
 
-             vertScrollerEl = me.lockedGrid.getView().el.dom,
 
-             verticalCanScrollDown, verticalCanScrollUp;
 
-         if (vertScrollerEl) {
 
-             verticalCanScrollDown = vertScrollerEl.scrollTop !== vertScrollerEl.scrollHeight - vertScrollerEl.clientHeight;
 
-             verticalCanScrollUp   = vertScrollerEl.scrollTop !== 0;
 
-         }
 
-         if ((deltaY < 0 && verticalCanScrollUp) || (deltaY > 0 && verticalCanScrollDown)) {
 
-             e.stopEvent();
 
-             // Inhibit processing of any scroll events we *may* cause here.
 
-             // Some OSs do not fire a scroll event when we set the scrollTop of an overflow:hidden element,
 
-             // so we invoke the scroll handler programatically below.
 
-             me.scrolling = true;
 
-             vertScrollerEl.scrollTop += deltaY;
 
-             me.normalGrid.getView().el.dom.scrollTop = vertScrollerEl.scrollTop;
 
-             me.scrolling = false;
 
-             // Invoke the scroll event handler programatically to sync everything.
 
-             me.onNormalViewScroll();
 
-         }
 
-     },
 
-     onLockedViewScroll: function() {
 
-         var me = this,
 
-             lockedView = me.lockedGrid.getView(),
 
-             normalView = me.normalGrid.getView(),
 
-             normalTable,
 
-             lockedTable;
 
-         // Set a flag so that the scroll even doesn't bounce back when we set the normal view's scroll position
 
-         if (!me.scrolling) {
 
-             me.scrolling = true;
 
-             normalView.el.dom.scrollTop = lockedView.el.dom.scrollTop;
 
-     
 
-             // For buffered views, the absolute position is important as well as scrollTop
 
-             if (me.store.buffered) {
 
-                 lockedTable = lockedView.el.child('table', true);
 
-                 normalTable = normalView.el.child('table', true);
 
-                 lockedTable.style.position = 'absolute';
 
-             }
 
-             me.scrolling = false;
 
-         }
 
-     },
 
-     
 
-     onNormalViewScroll: function() {
 
-         var me = this,
 
-             lockedView = me.lockedGrid.getView(),
 
-             normalView = me.normalGrid.getView(),
 
-             normalTable,
 
-             lockedTable;
 
-         // Set a flag so that the scroll even doesn't bounce back when we set the locked view's scroll position
 
-         if (!me.scrolling) {
 
-             me.scrolling = true;
 
-             lockedView.el.dom.scrollTop = normalView.el.dom.scrollTop;
 
-     
 
-             // For buffered views, the absolute position is important as well as scrollTop
 
-             if (me.store.buffered) {
 
-                 lockedTable = lockedView.el.child('table', true);
 
-                 normalTable = normalView.el.child('table', true);
 
-                 lockedTable.style.position = 'absolute';
 
-                 lockedTable.style.top = normalTable.style.top;
 
-             }
 
-             me.scrolling = false;
 
-         }
 
-     },
 
-     // trigger a pseudo refresh on the normal side
 
-     onLockedHeaderMove: function() {
 
-         if (this.syncRowHeight) {
 
-             this.onNormalViewRefresh();
 
-         }
 
-     },
 
-     // trigger a pseudo refresh on the locked side
 
-     onNormalHeaderMove: function() {
 
-         if (this.syncRowHeight) {
 
-             this.onLockedViewRefresh();
 
-         }
 
-     },
 
-     
 
-     // Create a spacer in lockedsection and store a reference.
 
-     // This is to allow the locked section to scroll past the bottom to
 
-     // take the mormal section's horizontal scrollbar into account
 
-     // TODO: Should destroy before refreshing content
 
-     updateSpacer: function() {
 
-         var me   = this,
 
-             // This affects scrolling all the way to the bottom of a locked grid
 
-             // additional test, sort a column and make sure it synchronizes
 
-             lockedViewEl   = me.lockedGrid.getView().el,
 
-             normalViewEl = me.normalGrid.getView().el.dom,
 
-             spacerId = lockedViewEl.dom.id + '-spacer',
 
-             spacerHeight = (normalViewEl.offsetHeight - normalViewEl.clientHeight) + 'px';
 
-         me.spacerEl = Ext.getDom(spacerId);
 
-         if (me.spacerEl) {
 
-             me.spacerEl.style.height = spacerHeight;
 
-         } else {
 
-             Ext.core.DomHelper.append(lockedViewEl, {
 
-                 id: spacerId,
 
-                 style: 'height: ' + spacerHeight
 
-             });
 
-         }
 
-     },
 
-     // cache the heights of all locked rows and sync rowheights
 
-     onLockedViewRefresh: function() {
 
-         // Only bother if there are some columns in the normal grid to sync
 
-         if (this.normalGrid.headerCt.getGridColumns().length) {
 
-             var me     = this,
 
-                 view   = me.lockedGrid.getView(),
 
-                 el     = view.el,
 
-                 rowEls = el.query(view.getItemSelector()),
 
-                 ln     = rowEls.length,
 
-                 i = 0;
 
-     
 
-             // reset heights each time.
 
-             me.lockedHeights = [];
 
-             for (; i < ln; i++) {
 
-                 me.lockedHeights[i] = rowEls[i].offsetHeight;
 
-             }
 
-             me.syncRowHeights();
 
-             me.updateSpacer();
 
-         }
 
-     },
 
-     // cache the heights of all normal rows and sync rowheights
 
-     onNormalViewRefresh: function() {
 
-         // Only bother if there are some columns in the locked grid to sync
 
-         if (this.lockedGrid.headerCt.getGridColumns().length) {
 
-             var me     = this,
 
-                 view   = me.normalGrid.getView(),
 
-                 el     = view.el,
 
-                 rowEls = el.query(view.getItemSelector()),
 
-                 ln     = rowEls.length,
 
-                 i = 0;
 
-     
 
-             // reset heights each time.
 
-             me.normalHeights = [];
 
-     
 
-             for (; i < ln; i++) {
 
-                 me.normalHeights[i] = rowEls[i].offsetHeight;
 
-             }
 
-             me.syncRowHeights();
 
-             me.updateSpacer();
 
-         }
 
-     },
 
-     // rows can get bigger/smaller
 
-     onLockedViewItemUpdate: function(record, index, node) {
 
-         // Only bother if there are some columns in the normal grid to sync
 
-         if (this.normalGrid.headerCt.getGridColumns().length) {
 
-             this.lockedHeights[index] = node.offsetHeight;
 
-             this.syncRowHeights();
 
-         }
 
-     },
 
-     // rows can get bigger/smaller
 
-     onNormalViewItemUpdate: function(record, index, node) {
 
-     
 
-         // Only bother if there are some columns in the locked grid to sync
 
-         if (this.lockedGrid.headerCt.getGridColumns().length) {
 
-             this.normalHeights[index] = node.offsetHeight;
 
-             this.syncRowHeights();
 
-         }
 
-     },
 
- <span id='Ext-grid-Lockable-method-syncRowHeights'>    /**
 
- </span>     * Synchronizes the row heights between the locked and non locked portion of the grid for each
 
-      * row. If one row is smaller than the other, the height will be increased to match the larger one.
 
-      */
 
-     syncRowHeights: function() {
 
-         var me = this,
 
-             lockedHeights = me.lockedHeights,
 
-             normalHeights = me.normalHeights,
 
-             ln = lockedHeights.length,
 
-             i  = 0,
 
-             lockedView, normalView,
 
-             lockedRowEls, normalRowEls,
 
-             scrollTop;
 
-         // ensure there are an equal num of locked and normal
 
-         // rows before synchronization
 
-         if (lockedHeights.length && normalHeights.length) {
 
-             lockedView = me.lockedGrid.getView();
 
-             normalView = me.normalGrid.getView();
 
-             lockedRowEls = lockedView.el.query(lockedView.getItemSelector());
 
-             normalRowEls = normalView.el.query(normalView.getItemSelector());
 
-             // loop thru all of the heights and sync to the other side
 
-             for (; i < ln; i++) {
 
-                 // ensure both are numbers
 
-                 if (!isNaN(lockedHeights[i]) && !isNaN(normalHeights[i])) {
 
-                     if (lockedHeights[i] > normalHeights[i]) {
 
-                         Ext.fly(normalRowEls[i]).setHeight(lockedHeights[i]);
 
-                     } else if (lockedHeights[i] < normalHeights[i]) {
 
-                         Ext.fly(lockedRowEls[i]).setHeight(normalHeights[i]);
 
-                     }
 
-                 }
 
-             }
 
-             // Synchronize the scrollTop positions of the two views
 
-             scrollTop = normalView.el.dom.scrollTop;
 
-             normalView.el.dom.scrollTop = scrollTop;
 
-             lockedView.el.dom.scrollTop = scrollTop;
 
-             
 
-             // reset the heights
 
-             me.lockedHeights = [];
 
-             me.normalHeights = [];
 
-         }
 
-     },
 
-     // inject Lock and Unlock text
 
-     modifyHeaderCt: function() {
 
-         var me = this;
 
-         me.lockedGrid.headerCt.getMenuItems = me.getMenuItems(me.lockedGrid.headerCt.getMenuItems, true);
 
-         me.normalGrid.headerCt.getMenuItems = me.getMenuItems(me.normalGrid.headerCt.getMenuItems, false);
 
-     },
 
-     onUnlockMenuClick: function() {
 
-         this.unlock();
 
-     },
 
-     onLockMenuClick: function() {
 
-         this.lock();
 
-     },
 
-     getMenuItems: function(getMenuItems, locked) {
 
-         var me            = this,
 
-             unlockText    = me.unlockText,
 
-             lockText      = me.lockText,
 
-             unlockCls     = Ext.baseCSSPrefix + 'hmenu-unlock',
 
-             lockCls       = Ext.baseCSSPrefix + 'hmenu-lock',
 
-             unlockHandler = Ext.Function.bind(me.onUnlockMenuClick, me),
 
-             lockHandler   = Ext.Function.bind(me.onLockMenuClick, me);
 
-         // runs in the scope of headerCt
 
-         return function() {
 
-             // We cannot use the method from HeaderContainer's prototype here
 
-             // because other plugins or features may already have injected an implementation
 
-             var o = getMenuItems.call(this);
 
-             o.push('-', {
 
-                 cls: unlockCls,
 
-                 text: unlockText,
 
-                 handler: unlockHandler,
 
-                 disabled: !locked
 
-             });
 
-             o.push({
 
-                 cls: lockCls,
 
-                 text: lockText,
 
-                 handler: lockHandler,
 
-                 disabled: locked
 
-             });
 
-             return o;
 
-         };
 
-     },
 
-     // going from unlocked section to locked
 
- <span id='Ext-grid-Lockable-method-lock'>    /**
 
- </span>     * Locks the activeHeader as determined by which menu is open OR a header
 
-      * as specified.
 
-      * @param {Ext.grid.column.Column} [header] Header to unlock from the locked section.
 
-      * Defaults to the header which has the menu open currently.
 
-      * @param {Number} [toIdx] The index to move the unlocked header to.
 
-      * Defaults to appending as the last item.
 
-      * @private
 
-      */
 
-     lock: function(activeHd, toIdx) {
 
-         var me         = this,
 
-             normalGrid = me.normalGrid,
 
-             lockedGrid = me.lockedGrid,
 
-             normalHCt  = normalGrid.headerCt,
 
-             lockedHCt  = lockedGrid.headerCt;
 
-         activeHd = activeHd || normalHCt.getMenu().activeHeader;
 
-         // if column was previously flexed, get/set current width
 
-         // and remove the flex
 
-         if (activeHd.flex) {
 
-             activeHd.width = activeHd.getWidth();
 
-             delete activeHd.flex;
 
-         }
 
-         Ext.suspendLayouts();
 
-         activeHd.ownerCt.remove(activeHd, false);
 
-         activeHd.locked = true;
 
-         if (Ext.isDefined(toIdx)) {
 
-             lockedHCt.insert(toIdx, activeHd);
 
-         } else {
 
-             lockedHCt.add(activeHd);
 
-         }
 
-         me.syncLockedSection();
 
-         Ext.resumeLayouts(true);
 
-         me.updateSpacer();
 
-         me.fireEvent('lockcolumn', me, activeHd);
 
-     },
 
-     syncLockedSection: function() {
 
-         var me = this;
 
-         me.syncLockedWidth();
 
-         me.lockedGrid.getView().refresh();
 
-         me.normalGrid.getView().refresh();
 
-     },
 
-     // adjust the locked section to the width of its respective
 
-     // headerCt
 
-     syncLockedWidth: function() {
 
-         var me = this,
 
-             locked = me.lockedGrid,
 
-             width = locked.headerCt.getFullWidth(true);
 
-             
 
-         Ext.suspendLayouts();
 
-         if (width > 0) {
 
-             locked.setWidth(width);
 
-             locked.show();
 
-         } else {
 
-             locked.hide();
 
-         }
 
-         Ext.resumeLayouts(true);
 
-         
 
-         return width > 0;
 
-     },
 
-     onLockedHeaderResize: function() {
 
-         this.syncLockedWidth();
 
-     },
 
-     onLockedHeaderHide: function() {
 
-         this.syncLockedWidth();
 
-     },
 
-     onLockedHeaderShow: function() {
 
-         this.syncLockedWidth();
 
-     },
 
-     onLockedHeaderSortChange: function(headerCt, header, sortState) {
 
-         if (sortState) {
 
-             // no real header, and silence the event so we dont get into an
 
-             // infinite loop
 
-             this.normalGrid.headerCt.clearOtherSortStates(null, true);
 
-         }
 
-     },
 
-     onNormalHeaderSortChange: function(headerCt, header, sortState) {
 
-         if (sortState) {
 
-             // no real header, and silence the event so we dont get into an
 
-             // infinite loop
 
-             this.lockedGrid.headerCt.clearOtherSortStates(null, true);
 
-         }
 
-     },
 
-     // going from locked section to unlocked
 
- <span id='Ext-grid-Lockable-method-unlock'>    /**
 
- </span>     * Unlocks the activeHeader as determined by which menu is open OR a header
 
-      * as specified.
 
-      * @param {Ext.grid.column.Column} [header] Header to unlock from the locked section.
 
-      * Defaults to the header which has the menu open currently.
 
-      * @param {Number} [toIdx=0] The index to move the unlocked header to.
 
-      * @private
 
-      */
 
-     unlock: function(activeHd, toIdx) {
 
-         var me         = this,
 
-             normalGrid = me.normalGrid,
 
-             lockedGrid = me.lockedGrid,
 
-             normalHCt  = normalGrid.headerCt,
 
-             lockedHCt  = lockedGrid.headerCt,
 
-             refreshLocked = false;
 
-         if (!Ext.isDefined(toIdx)) {
 
-             toIdx = 0;
 
-         }
 
-         activeHd = activeHd || lockedHCt.getMenu().activeHeader;
 
-         Ext.suspendLayouts();
 
-         activeHd.ownerCt.remove(activeHd, false);
 
-         if (me.syncLockedWidth()) {
 
-             refreshLocked = true;
 
-         }
 
-         activeHd.locked = false;
 
-         // Refresh the locked section first in case it was empty
 
-         normalHCt.insert(toIdx, activeHd);
 
-         me.normalGrid.getView().refresh();
 
-         if (refreshLocked) {
 
-             me.lockedGrid.getView().refresh();
 
-         }
 
-         Ext.resumeLayouts(true);
 
-         me.fireEvent('unlockcolumn', me, activeHd);
 
-     },
 
-     applyColumnsState: function (columns) {
 
-         var me             = this,
 
-             lockedGrid     = me.lockedGrid,
 
-             lockedHeaderCt = lockedGrid.headerCt,
 
-             normalHeaderCt = me.normalGrid.headerCt,
 
-             lockedCols     = Ext.Array.toMap(lockedHeaderCt.items, 'headerId'),
 
-             normalCols     = Ext.Array.toMap(normalHeaderCt.items, 'headerId'),
 
-             locked         = [],
 
-             normal         = [],
 
-             lockedWidth    = 1,
 
-             length         = columns.length,
 
-             i, existing,
 
-             lockedDefault,
 
-             col;
 
-         for (i = 0; i < length; i++) {
 
-             col = columns[i];
 
-             lockedDefault = lockedCols[col.id];
 
-             existing = lockedDefault || normalCols[col.id];
 
-             if (existing) {
 
-                 if (existing.applyColumnState) {
 
-                     existing.applyColumnState(col);
 
-                 }
 
-                 if (existing.locked === undefined) {
 
-                     existing.locked = !!lockedDefault;
 
-                 }
 
-                 if (existing.locked) {
 
-                     locked.push(existing);
 
-                     if (!existing.hidden && typeof existing.width == 'number') {
 
-                         lockedWidth += existing.width;
 
-                     }
 
-                 } else {
 
-                     normal.push(existing);
 
-                 }
 
-             }
 
-         }
 
-         // state and config must have the same columns (compare counts for now):
 
-         if (locked.length + normal.length == lockedHeaderCt.items.getCount() + normalHeaderCt.items.getCount()) {
 
-             lockedHeaderCt.removeAll(false);
 
-             normalHeaderCt.removeAll(false);
 
-             lockedHeaderCt.add(locked);
 
-             normalHeaderCt.add(normal);
 
-             lockedGrid.setWidth(lockedWidth);
 
-         }
 
-     },
 
-     getColumnsState: function () {
 
-         var me = this,
 
-             locked = me.lockedGrid.headerCt.getColumnsState(),
 
-             normal = me.normalGrid.headerCt.getColumnsState();
 
-         return locked.concat(normal);
 
-     },
 
-     // we want to totally override the reconfigure behaviour here, since we're creating 2 sub-grids
 
-     reconfigureLockable: function(store, columns) {
 
-         var me = this,
 
-             lockedGrid = me.lockedGrid,
 
-             normalGrid = me.normalGrid;
 
-         if (columns) {
 
-             Ext.suspendLayouts();
 
-             lockedGrid.headerCt.removeAll();
 
-             normalGrid.headerCt.removeAll();
 
-             columns = me.processColumns(columns);
 
-             lockedGrid.setWidth(columns.lockedWidth);
 
-             lockedGrid.headerCt.add(columns.locked.items);
 
-             normalGrid.headerCt.add(columns.normal.items);
 
-             Ext.resumeLayouts(true);
 
-         }
 
-         if (store) {
 
-             store = Ext.data.StoreManager.lookup(store);
 
-             me.store = store;
 
-             lockedGrid.bindStore(store);
 
-             normalGrid.bindStore(store);
 
-         } else {
 
-             lockedGrid.getView().refresh();
 
-             normalGrid.getView().refresh();
 
-         }
 
-     },
 
- <span id='Ext-grid-Lockable-method-cloneFeatures'>    /**
 
- </span>     * Clones items in the features array if they are instantiated Features. If an item
 
-      * is just a feature config, it leaves it alone.
 
-      *
 
-      * This is so that features can be replicated on both sides of the LockingView
 
-      *
 
-      */
 
-     cloneFeatures: function() {
 
-         var me = this,
 
-             features = me.features,
 
-             feature,
 
-             i = 0, len;
 
-         
 
-         if (features) {
 
-             len = features.length;
 
-             for (; i < len; i++) {
 
-                 feature = features[i];
 
-                 if (feature.isFeature) {
 
-                     features[i] = feature.clone();
 
-                 }
 
-             }
 
-         }
 
-     },
 
- <span id='Ext-grid-Lockable-method-clonePlugins'>    /**
 
- </span>     * Clones items in the plugins array if they are instantiated Plugins. If an item
 
-      * is just a plugin config, it leaves it alone.
 
-      *
 
-      * This is so that plugins can be replicated on both sides of the LockingView
 
-      *
 
-      */
 
-     clonePlugins: function() {
 
-         var me = this,
 
-             plugins = me.plugins,
 
-             plugin,
 
-             i = 0, len;
 
-         
 
-         if (plugins) {
 
-             len = plugins.length;
 
-             for (; i < len; i++) {
 
-                 plugin = plugins[i];
 
-                 if (typeof plugin.init === 'function') {
 
-                     plugins[i] = plugin.clone();
 
-                 }
 
-             }
 
-         }
 
-     }
 
- }, function() {
 
-     this.borrow(Ext.view.Table, ['constructFeatures']);
 
-     this.borrow(Ext.AbstractComponent, ['constructPlugins', 'constructPlugin']);
 
- });
 
- </pre>
 
- </body>
 
- </html>
 
 
  |