Upgrade to ExtJS 4.0.1 - Released 05/18/2011
[extjs.git] / docs / source / PagingScroller.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5   <title>The source code</title>
6   <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../prettify/prettify.js"></script>
8   <style type="text/css">
9     .highlight { display: block; background-color: #ddd; }
10   </style>
11   <script type="text/javascript">
12     function highlight() {
13       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14     }
15   </script>
16 </head>
17 <body onload="prettyPrint(); highlight();">
18   <pre class="prettyprint lang-js"><span id='Ext-grid-PagingScroller'>/**
19 </span> * @class Ext.grid.PagingScroller
20  * @extends Ext.grid.Scroller
21  *
22  * @private
23  */
24 Ext.define('Ext.grid.PagingScroller', {
25     extend: 'Ext.grid.Scroller',
26     alias: 'widget.paginggridscroller',
27     //renderTpl: null,
28     //tpl: [
29     //    '&lt;tpl for=&quot;pages&quot;&gt;',
30     //        '&lt;div class=&quot;' + Ext.baseCSSPrefix + 'stretcher&quot; style=&quot;width: {width}px;height: {height}px;&quot;&gt;&lt;/div&gt;',
31     //    '&lt;/tpl&gt;'
32     //],
33 <span id='Ext-grid-PagingScroller-cfg-percentageFromEdge'>    /**
34 </span>     * @cfg {Number} percentageFromEdge This is a number above 0 and less than 1 which specifies
35      * at what percentage to begin fetching the next page. For example if the pageSize is 100
36      * and the percentageFromEdge is the default of 0.35, the paging scroller will prefetch pages
37      * when scrolling up between records 0 and 34 and when scrolling down between records 65 and 99.
38      */
39     percentageFromEdge: 0.35,
40     
41 <span id='Ext-grid-PagingScroller-cfg-scrollToLoadBuffer'>    /**
42 </span>     * @cfg {Number} scrollToLoadBuffer This is the time in milliseconds to buffer load requests
43      * when scrolling the PagingScrollbar.
44      */
45     scrollToLoadBuffer: 200,
46     
47     activePrefetch: true,
48     
49     chunkSize: 50,
50     snapIncrement: 25,
51     
52     syncScroll: true,
53     
54     initComponent: function() {
55         var me = this,
56             ds = me.store;
57
58         ds.on('guaranteedrange', this.onGuaranteedRange, this);
59         this.callParent(arguments);
60     },
61     
62     
63     onGuaranteedRange: function(range, start, end) {
64         var me = this,
65             ds = me.store,
66             rs;
67         // this should never happen
68         if (range.length &amp;&amp; me.visibleStart &lt; range[0].index) {
69             return;
70         }
71         
72         ds.loadRecords(range);
73
74         if (!me.firstLoad) {
75             if (me.rendered) {
76                 me.invalidate();
77             } else {
78                 me.on('afterrender', this.invalidate, this, {single: true});
79             }
80             me.firstLoad = true;
81         } else {
82             // adjust to visible
83             me.syncTo();
84         }
85     },
86     
87     syncTo: function() {
88         var me            = this,
89             pnl           = me.getPanel(),
90             store         = pnl.store,
91             scrollerElDom = this.el.dom,
92             rowOffset     = me.visibleStart - store.guaranteedStart,
93             scrollBy      = rowOffset * me.rowHeight,
94             scrollHeight  = scrollerElDom.scrollHeight,
95             clientHeight  = scrollerElDom.clientHeight,
96             scrollTop     = scrollerElDom.scrollTop,
97             useMaximum;
98         
99         // BrowserBug: clientHeight reports 0 in IE9 StrictMode
100         // Instead we are using offsetHeight and hardcoding borders
101         if (Ext.isIE9 &amp;&amp; Ext.isStrict) {
102             clientHeight = scrollerElDom.offsetHeight + 2;
103         }
104
105         // This should always be zero or greater than zero but staying
106         // safe and less than 0 we'll scroll to the bottom.        
107         useMaximum = (scrollHeight - clientHeight - scrollTop &lt;= 0);
108         this.setViewScrollTop(scrollBy, useMaximum);
109     },
110     
111     getPageData : function(){
112         var panel = this.getPanel(),
113             store = panel.store,
114             totalCount = store.getTotalCount();
115             
116         return {
117             total : totalCount,
118             currentPage : store.currentPage,
119             pageCount: Math.ceil(totalCount / store.pageSize),
120             fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
121             toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
122         };
123     },
124     
125     onElScroll: function(e, t) {
126         var me = this,
127             panel = me.getPanel(),
128             store = panel.store,
129             pageSize = store.pageSize,
130             guaranteedStart = store.guaranteedStart,
131             guaranteedEnd = store.guaranteedEnd,
132             totalCount = store.getTotalCount(),
133             numFromEdge = Math.ceil(me.percentageFromEdge * store.pageSize),
134             position = t.scrollTop,
135             visibleStart = Math.floor(position / me.rowHeight),
136             view = panel.down('tableview'),
137             viewEl = view.el,
138             visibleHeight = viewEl.getHeight(),
139             visibleAhead = Math.ceil(visibleHeight / me.rowHeight),
140             visibleEnd = visibleStart + visibleAhead,
141             prevPage = Math.floor(visibleStart / store.pageSize),
142             nextPage = Math.floor(visibleEnd / store.pageSize) + 2,
143             lastPage = Math.ceil(totalCount / store.pageSize),
144             //requestStart = visibleStart,
145             requestStart = Math.floor(visibleStart / me.snapIncrement) * me.snapIncrement,
146             requestEnd = requestStart + pageSize - 1,
147             activePrefetch = me.activePrefetch;
148
149         me.visibleStart = visibleStart;
150         me.visibleEnd = visibleEnd;
151         
152         
153         me.syncScroll = true;
154         if (totalCount &gt;= pageSize) {
155             // end of request was past what the total is, grab from the end back a pageSize
156             if (requestEnd &gt; totalCount - 1) {
157                 this.cancelLoad();
158                 if (store.rangeSatisfied(totalCount - pageSize, totalCount - 1)) {
159                     me.syncScroll = true;
160                 }
161                 store.guaranteeRange(totalCount - pageSize, totalCount - 1);
162             // Out of range, need to reset the current data set
163             } else if (visibleStart &lt; guaranteedStart || visibleEnd &gt; guaranteedEnd) {
164                 if (store.rangeSatisfied(requestStart, requestEnd)) {
165                     this.cancelLoad();
166                     store.guaranteeRange(requestStart, requestEnd);
167                 } else {
168                     store.mask();
169                     me.attemptLoad(requestStart, requestEnd);
170                 }
171                 // dont sync the scroll view immediately, sync after the range has been guaranteed
172                 me.syncScroll = false;
173             } else if (activePrefetch &amp;&amp; visibleStart &lt; (guaranteedStart + numFromEdge) &amp;&amp; prevPage &gt; 0) {
174                 me.syncScroll = true;
175                 store.prefetchPage(prevPage);
176             } else if (activePrefetch &amp;&amp; visibleEnd &gt; (guaranteedEnd - numFromEdge) &amp;&amp; nextPage &lt; lastPage) {
177                 me.syncScroll = true;
178                 store.prefetchPage(nextPage);
179             }
180         }
181     
182     
183         if (me.syncScroll) {
184             me.syncTo();
185         }
186     },
187     
188     getSizeCalculation: function() {
189         // Use the direct ownerCt here rather than the scrollerOwner
190         // because we are calculating widths/heights.
191         var owner = this.ownerCt,
192             view   = owner.getView(),
193             store  = this.store,
194             dock   = this.dock,
195             elDom  = this.el.dom,
196             width  = 1,
197             height = 1;
198         
199         if (!this.rowHeight) {
200             this.rowHeight = view.el.down(view.getItemSelector()).getHeight(false, true);
201         }
202
203         height = store.getTotalCount() * this.rowHeight;
204
205         if (isNaN(width)) {
206             width = 1;
207         }
208         if (isNaN(height)) {
209             height = 1;
210         }
211         return {
212             width: width,
213             height: height
214         };
215     },
216     
217     attemptLoad: function(start, end) {
218         var me = this;
219         if (!me.loadTask) {
220             me.loadTask = Ext.create('Ext.util.DelayedTask', me.doAttemptLoad, me, []);
221         }
222         me.loadTask.delay(me.scrollToLoadBuffer, me.doAttemptLoad, me, [start, end]);
223     },
224     
225     cancelLoad: function() {
226         if (this.loadTask) {
227             this.loadTask.cancel();
228         }
229     },
230     
231     doAttemptLoad:  function(start, end) {
232         var store = this.getPanel().store;
233         store.guaranteeRange(start, end);
234     },
235     
236     setViewScrollTop: function(scrollTop, useMax) {
237         var owner = this.getPanel(),
238             items = owner.query('tableview'),
239             i = 0,
240             len = items.length,
241             center,
242             centerEl,
243             calcScrollTop,
244             maxScrollTop,
245             scrollerElDom = this.el.dom;
246             
247         owner.virtualScrollTop = scrollTop;
248             
249         center = items[1] || items[0];
250         centerEl = center.el.dom;
251         
252         maxScrollTop = ((owner.store.pageSize * this.rowHeight) - centerEl.clientHeight);
253         calcScrollTop = (scrollTop % ((owner.store.pageSize * this.rowHeight) + 1));
254         if (useMax) {
255             calcScrollTop = maxScrollTop;
256         }
257         if (calcScrollTop &gt; maxScrollTop) {
258             //Ext.Error.raise(&quot;Calculated scrollTop was larger than maxScrollTop&quot;);
259             return;
260             // calcScrollTop = maxScrollTop;
261         }
262         for (; i &lt; len; i++) {
263             items[i].el.dom.scrollTop = calcScrollTop;
264         }
265     }
266 });
267
268 </pre>
269 </body>
270 </html>