Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / Scroller.html
index 14ecf7a..126cc1b 100644 (file)
@@ -3,8 +3,8 @@
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   <title>The source code</title>
-  <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
-  <script type="text/javascript" src="../prettify/prettify.js"></script>
+  <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>
 </head>
 <body onload="prettyPrint(); highlight();">
   <pre class="prettyprint lang-js"><span id='Ext-grid-Scroller'>/**
-</span> * @class Ext.grid.Scroller
- * @extends Ext.Component
- *
- * Docked in an Ext.grid.Panel, controls virtualized scrolling and synchronization
+</span> * Docked in an Ext.grid.Panel, controls virtualized scrolling and synchronization
  * across different sections.
- *
- * @private
  */
 Ext.define('Ext.grid.Scroller', {
     extend: 'Ext.Component',
     alias: 'widget.gridscroller',
     weight: 110,
-    cls: Ext.baseCSSPrefix + 'scroller',
+    baseCls: Ext.baseCSSPrefix + 'scroller',
     focusable: false,
-    
-    renderTpl: ['&lt;div class=&quot;' + Ext.baseCSSPrefix + 'stretcher&quot;&gt;&lt;/div&gt;'],
-    
+    reservedSpace: 0,
+
+    renderTpl: [
+        '&lt;div class=&quot;' + Ext.baseCSSPrefix + 'scroller-ct&quot; id=&quot;{baseId}_ct&quot;&gt;',
+            '&lt;div class=&quot;' + Ext.baseCSSPrefix + 'stretcher&quot; id=&quot;{baseId}_stretch&quot;&gt;&lt;/div&gt;',
+        '&lt;/div&gt;'
+    ],
+
     initComponent: function() {
         var me       = this,
             dock     = me.dock,
-            cls      = Ext.baseCSSPrefix + 'scroller-vertical',
-            sizeProp = 'width',
-            // Subtracting 2px would give us a perfect fit of the scroller
-            // however, some browsers wont allow us to scroll content thats not
-            // visible, therefore we use 1px.
-            // Note: This 1px offset matches code in Ext.grid.ColumnLayout when
-            // reserving room for the scrollbar
-            scrollbarWidth = Ext.getScrollBarWidth() + (Ext.isIE ? 1 : -1);
+            cls      = Ext.baseCSSPrefix + 'scroller-vertical';
 
         me.offsets = {bottom: 0};
+        me.scrollProp = 'scrollTop';
+        me.vertical = true;
+        me.sizeProp = 'width';
 
         if (dock === 'top' || dock === 'bottom') {
             cls = Ext.baseCSSPrefix + 'scroller-horizontal';
-            sizeProp = 'height';
+            me.sizeProp = 'height';
+            me.scrollProp = 'scrollLeft';
+            me.vertical = false;
+            me.weight += 5;
         }
-        me[sizeProp] = scrollbarWidth;
-        
+
         me.cls += (' ' + cls);
-        
+
         Ext.applyIf(me.renderSelectors, {
-            stretchEl: '.' + Ext.baseCSSPrefix + 'stretcher'
+            stretchEl: '.' + Ext.baseCSSPrefix + 'stretcher',
+            scrollEl: '.' + Ext.baseCSSPrefix + 'scroller-ct'
         });
         me.callParent();
     },
     
-    
+    ensureDimension: function(){
+        var me = this,
+            sizeProp = me.sizeProp;
+            
+        me[sizeProp] = me.scrollerSize = Ext.getScrollbarSize()[sizeProp];  
+    },
+
+    initRenderData: function () {
+        var me = this,
+            ret = me.callParent(arguments) || {};
+
+        ret.baseId = me.id;
+
+        return ret;
+    },
+
     afterRender: function() {
         var me = this;
         me.callParent();
-        me.ownerCt.on('afterlayout', me.onOwnerAfterLayout, me);
-        me.mon(me.el, 'scroll', me.onElScroll, me);
+        
+        me.mon(me.scrollEl, 'scroll', me.onElScroll, me);
         Ext.cache[me.el.id].skipGarbageCollection = true;
     },
-    
+
+    onAdded: function(container) {
+        // Capture the controlling grid Panel so that we can use it even when we are undocked, and don't have an ownerCt
+        this.ownerGrid = container;
+        this.callParent(arguments);
+    },
+
     getSizeCalculation: function() {
-        var owner  = this.getPanel(),
-            dock   = this.dock,
-            elDom  = this.el.dom,
+        var me     = this,
+            owner  = me.getPanel(),
             width  = 1,
             height = 1,
             view, tbl;
-            
-        if (dock === 'top' || dock === 'bottom') {
+
+        if (!me.vertical) {
             // TODO: Must gravitate to a single region..
             // Horizontal scrolling only scrolls virtualized region
             var items  = owner.query('tableview'),
                 center = items[1] || items[0];
-            
+
             if (!center) {
                 return false;
             }
@@ -91,25 +110,23 @@ Ext.define('Ext.grid.Scroller', {
             // are zero rows in the grid/tree. We read the width from the
             // headerCt instead.
             width = center.headerCt.getFullWidth();
-            
+
             if (Ext.isIEQuirks) {
                 width--;
             }
-            // Account for the 1px removed in Scroller.
-            width--;
-        } else {            
+        } else {
             view = owner.down('tableview:not([lockableInjected])');
-            if (!view) {
+            if (!view || !view.el) {
                 return false;
             }
-            tbl = view.el;
+            tbl = view.el.child('table', true);
             if (!tbl) {
                 return false;
             }
-            
+
             // needs to also account for header and scroller (if still in picture)
             // should calculate from headerCt.
-            height = tbl.dom.scrollHeight;
+            height = tbl.offsetHeight;
         }
         if (isNaN(width)) {
             width = 1;
@@ -122,34 +139,88 @@ Ext.define('Ext.grid.Scroller', {
             height: height
         };
     },
-    
+
     invalidate: function(firstPass) {
-        if (!this.stretchEl || !this.ownerCt) {
+        var me = this,
+            stretchEl = me.stretchEl;
+
+        if (!stretchEl || !me.ownerCt) {
             return;
         }
-        var size  = this.getSizeCalculation(),
-            elDom = this.el.dom;
+
+        var size  = me.getSizeCalculation(),
+            scrollEl = me.scrollEl,
+            elDom = scrollEl.dom,
+            reservedSpace = me.reservedSpace,
+            pos,
+            extra = 5;
+
         if (size) {
-            this.stretchEl.setSize(size);
-        
+            stretchEl.setSize(size);
+
+            size = me.el.getSize(true);
+
+            if (me.vertical) {
+                size.width += extra;
+                size.height -= reservedSpace;
+                pos = 'left';
+            } else {
+                size.width -= reservedSpace;
+                size.height += extra;
+                pos = 'top';
+            }
+
+            scrollEl.setSize(size);
+            elDom.style[pos] = (-extra) + 'px';
+
             // BrowserBug: IE7
             // This makes the scroller enabled, when initially rendering.
             elDom.scrollTop = elDom.scrollTop;
         }
     },
 
-    onOwnerAfterLayout: function(owner, layout) {
+    afterComponentLayout: function() {
+        this.callParent(arguments);
         this.invalidate();
     },
 
+    restoreScrollPos: function () {
+        var me = this,
+            el = this.scrollEl,
+            elDom = el &amp;&amp; el.dom;
+
+        if (me._scrollPos !== null &amp;&amp; elDom) {
+            elDom[me.scrollProp] = me._scrollPos;
+            me._scrollPos = null;
+        }
+    },
+
+    setReservedSpace: function (reservedSpace) {
+        var me = this;
+        if (me.reservedSpace !== reservedSpace) {
+            me.reservedSpace = reservedSpace;
+            me.invalidate();
+        }
+    },
+
+    saveScrollPos: function () {
+        var me = this,
+            el = this.scrollEl,
+            elDom = el &amp;&amp; el.dom;
+
+        me._scrollPos = elDom ? elDom[me.scrollProp] : null;
+    },
+
 <span id='Ext-grid-Scroller-method-setScrollTop'>    /**
 </span>     * Sets the scrollTop and constrains the value between 0 and max.
      * @param {Number} scrollTop
      * @return {Number} The resulting scrollTop value after being constrained
      */
     setScrollTop: function(scrollTop) {
-        if (this.el) {
-            var elDom = this.el.dom;
+        var el = this.scrollEl,
+            elDom = el &amp;&amp; el.dom;
+
+        if (elDom) {
             return elDom.scrollTop = Ext.Number.constrain(scrollTop, 0, elDom.scrollHeight - elDom.clientHeight);
         }
     },
@@ -160,8 +231,10 @@ Ext.define('Ext.grid.Scroller', {
      * @return {Number} The resulting scrollLeft value after being constrained
      */
     setScrollLeft: function(scrollLeft) {
-        if (this.el) {
-            var elDom = this.el.dom;
+        var el = this.scrollEl,
+            elDom = el &amp;&amp; el.dom;
+
+        if (elDom) {
             return elDom.scrollLeft = Ext.Number.constrain(scrollLeft, 0, elDom.scrollWidth - elDom.clientWidth);
         }
     },
@@ -172,8 +245,10 @@ Ext.define('Ext.grid.Scroller', {
      * @return {Number} The resulting scrollTop value
      */
     scrollByDeltaY: function(delta) {
-        if (this.el) {
-            var elDom = this.el.dom;
+        var el = this.scrollEl,
+            elDom = el &amp;&amp; el.dom;
+
+        if (elDom) {
             return this.setScrollTop(elDom.scrollTop + delta);
         }
     },
@@ -184,20 +259,22 @@ Ext.define('Ext.grid.Scroller', {
      * @return {Number} The resulting scrollLeft value
      */
     scrollByDeltaX: function(delta) {
-        if (this.el) {
-            var elDom = this.el.dom;
+        var el = this.scrollEl,
+            elDom = el &amp;&amp; el.dom;
+
+        if (elDom) {
             return this.setScrollLeft(elDom.scrollLeft + delta);
         }
     },
-    
-    
+
+
 <span id='Ext-grid-Scroller-method-scrollToTop'>    /**
 </span>     * Scroll to the top.
      */
     scrollToTop : function(){
         this.setScrollTop(0);
     },
-    
+
     // synchronize the scroller with the bound gridviews
     onElScroll: function(event, target) {
         this.fireEvent('bodyscroll', event, target);