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