Upgrade to ExtJS 4.0.2 - Released 06/09/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     onGuaranteedRange: function(range, start, end) {
63         var me = this,
64             ds = me.store,
65             rs;
66         // this should never happen
67         if (range.length &amp;&amp; me.visibleStart &lt; range[0].index) {
68             return;
69         }
70
71         ds.loadRecords(range);
72
73         if (!me.firstLoad) {
74             if (me.rendered) {
75                 me.invalidate();
76             } else {
77                 me.on('afterrender', this.invalidate, this, {single: true});
78             }
79             me.firstLoad = true;
80         } else {
81             // adjust to visible
82             me.syncTo();
83         }
84     },
85
86     syncTo: function() {
87         var me            = this,
88             pnl           = me.getPanel(),
89             store         = pnl.store,
90             scrollerElDom = this.scrollEl.dom,
91             rowOffset     = me.visibleStart - store.guaranteedStart,
92             scrollBy      = rowOffset * me.rowHeight,
93             scrollHeight  = scrollerElDom.scrollHeight,
94             clientHeight  = scrollerElDom.clientHeight,
95             scrollTop     = scrollerElDom.scrollTop,
96             useMaximum;
97
98         // BrowserBug: clientHeight reports 0 in IE9 StrictMode
99         // Instead we are using offsetHeight and hardcoding borders
100         if (Ext.isIE9 &amp;&amp; Ext.isStrict) {
101             clientHeight = scrollerElDom.offsetHeight + 2;
102         }
103
104         // This should always be zero or greater than zero but staying
105         // safe and less than 0 we'll scroll to the bottom.
106         useMaximum = (scrollHeight - clientHeight - scrollTop &lt;= 0);
107         this.setViewScrollTop(scrollBy, useMaximum);
108     },
109
110     getPageData : function(){
111         var panel = this.getPanel(),
112             store = panel.store,
113             totalCount = store.getTotalCount();
114
115         return {
116             total : totalCount,
117             currentPage : store.currentPage,
118             pageCount: Math.ceil(totalCount / store.pageSize),
119             fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
120             toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
121         };
122     },
123
124     onElScroll: function(e, t) {
125         var me = this,
126             panel = me.getPanel(),
127             store = panel.store,
128             pageSize = store.pageSize,
129             guaranteedStart = store.guaranteedStart,
130             guaranteedEnd = store.guaranteedEnd,
131             totalCount = store.getTotalCount(),
132             numFromEdge = Math.ceil(me.percentageFromEdge * store.pageSize),
133             position = t.scrollTop,
134             visibleStart = Math.floor(position / me.rowHeight),
135             view = panel.down('tableview'),
136             viewEl = view.el,
137             visibleHeight = viewEl.getHeight(),
138             visibleAhead = Math.ceil(visibleHeight / me.rowHeight),
139             visibleEnd = visibleStart + visibleAhead,
140             prevPage = Math.floor(visibleStart / store.pageSize),
141             nextPage = Math.floor(visibleEnd / store.pageSize) + 2,
142             lastPage = Math.ceil(totalCount / store.pageSize),
143             //requestStart = visibleStart,
144             requestStart = Math.floor(visibleStart / me.snapIncrement) * me.snapIncrement,
145             requestEnd = requestStart + pageSize - 1,
146             activePrefetch = me.activePrefetch;
147
148         me.visibleStart = visibleStart;
149         me.visibleEnd = visibleEnd;
150
151         me.syncScroll = true;
152         if (totalCount &gt;= pageSize) {
153             // end of request was past what the total is, grab from the end back a pageSize
154             if (requestEnd &gt; totalCount - 1) {
155                 this.cancelLoad();
156                 if (store.rangeSatisfied(totalCount - pageSize, totalCount - 1)) {
157                     me.syncScroll = true;
158                 }
159                 store.guaranteeRange(totalCount - pageSize, totalCount - 1);
160             // Out of range, need to reset the current data set
161             } else if (visibleStart &lt; guaranteedStart || visibleEnd &gt; guaranteedEnd) {
162                 if (store.rangeSatisfied(requestStart, requestEnd)) {
163                     this.cancelLoad();
164                     store.guaranteeRange(requestStart, requestEnd);
165                 } else {
166                     store.mask();
167                     me.attemptLoad(requestStart, requestEnd);
168                 }
169                 // dont sync the scroll view immediately, sync after the range has been guaranteed
170                 me.syncScroll = false;
171             } else if (activePrefetch &amp;&amp; visibleStart &lt; (guaranteedStart + numFromEdge) &amp;&amp; prevPage &gt; 0) {
172                 me.syncScroll = true;
173                 store.prefetchPage(prevPage);
174             } else if (activePrefetch &amp;&amp; visibleEnd &gt; (guaranteedEnd - numFromEdge) &amp;&amp; nextPage &lt; lastPage) {
175                 me.syncScroll = true;
176                 store.prefetchPage(nextPage);
177             }
178         }
179
180         if (me.syncScroll) {
181             me.syncTo();
182         }
183     },
184
185     getSizeCalculation: function() {
186         // Use the direct ownerCt here rather than the scrollerOwner
187         // because we are calculating widths/heights.
188         var owner = this.ownerGrid,
189             view   = owner.getView(),
190             store  = this.store,
191             dock   = this.dock,
192             elDom  = this.el.dom,
193             width  = 1,
194             height = 1;
195
196         if (!this.rowHeight) {
197             this.rowHeight = view.el.down(view.getItemSelector()).getHeight(false, true);
198         }
199
200         // If the Store is *locally* filtered, use the filtered count from getCount.
201         height = store[(!store.remoteFilter &amp;&amp; store.isFiltered()) ? 'getCount' : 'getTotalCount']() * this.rowHeight;
202
203         if (isNaN(width)) {
204             width = 1;
205         }
206         if (isNaN(height)) {
207             height = 1;
208         }
209         return {
210             width: width,
211             height: height
212         };
213     },
214
215     attemptLoad: function(start, end) {
216         var me = this;
217         if (!me.loadTask) {
218             me.loadTask = Ext.create('Ext.util.DelayedTask', me.doAttemptLoad, me, []);
219         }
220         me.loadTask.delay(me.scrollToLoadBuffer, me.doAttemptLoad, me, [start, end]);
221     },
222
223     cancelLoad: function() {
224         if (this.loadTask) {
225             this.loadTask.cancel();
226         }
227     },
228
229     doAttemptLoad:  function(start, end) {
230         var store = this.getPanel().store;
231         store.guaranteeRange(start, end);
232     },
233
234     setViewScrollTop: function(scrollTop, useMax) {
235         var owner = this.getPanel(),
236             items = owner.query('tableview'),
237             i = 0,
238             len = items.length,
239             center,
240             centerEl,
241             calcScrollTop,
242             maxScrollTop,
243             scrollerElDom = this.el.dom;
244
245         owner.virtualScrollTop = scrollTop;
246
247         center = items[1] || items[0];
248         centerEl = center.el.dom;
249
250         maxScrollTop = ((owner.store.pageSize * this.rowHeight) - centerEl.clientHeight);
251         calcScrollTop = (scrollTop % ((owner.store.pageSize * this.rowHeight) + 1));
252         if (useMax) {
253             calcScrollTop = maxScrollTop;
254         }
255         if (calcScrollTop &gt; maxScrollTop) {
256             //Ext.Error.raise(&quot;Calculated scrollTop was larger than maxScrollTop&quot;);
257             return;
258             // calcScrollTop = maxScrollTop;
259         }
260         for (; i &lt; len; i++) {
261             items[i].el.dom.scrollTop = calcScrollTop;
262         }
263     }
264 });</pre>
265 </body>
266 </html>