3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * @class Ext.grid.PagingScroller
17 * @extends Ext.grid.Scroller
21 Ext.define('Ext.grid.PagingScroller', {
22 extend: 'Ext.grid.Scroller',
23 alias: 'widget.paginggridscroller',
26 // '<tpl for="pages">',
27 // '<div class="' + Ext.baseCSSPrefix + 'stretcher" style="width: {width}px;height: {height}px;"></div>',
31 * @cfg {Number} percentageFromEdge This is a number above 0 and less than 1 which specifies
32 * at what percentage to begin fetching the next page. For example if the pageSize is 100
33 * and the percentageFromEdge is the default of 0.35, the paging scroller will prefetch pages
34 * when scrolling up between records 0 and 34 and when scrolling down between records 65 and 99.
36 percentageFromEdge: 0.35,
39 * @cfg {Number} scrollToLoadBuffer This is the time in milliseconds to buffer load requests
40 * when scrolling the PagingScrollbar.
42 scrollToLoadBuffer: 200,
51 initComponent: function() {
55 ds.on('guaranteedrange', this.onGuaranteedRange, this);
56 this.callParent(arguments);
59 onGuaranteedRange: function(range, start, end) {
63 // this should never happen
64 if (range.length && me.visibleStart < range[0].index) {
68 ds.loadRecords(range);
74 me.on('afterrender', this.invalidate, this, {single: true});
87 scrollerElDom = this.scrollEl.dom,
88 rowOffset = me.visibleStart - store.guaranteedStart,
89 scrollBy = rowOffset * me.rowHeight,
90 scrollHeight = scrollerElDom.scrollHeight,
91 clientHeight = scrollerElDom.clientHeight,
92 scrollTop = scrollerElDom.scrollTop,
95 // BrowserBug: clientHeight reports 0 in IE9 StrictMode
96 // Instead we are using offsetHeight and hardcoding borders
97 if (Ext.isIE9 && Ext.isStrict) {
98 clientHeight = scrollerElDom.offsetHeight + 2;
101 // This should always be zero or greater than zero but staying
102 // safe and less than 0 we'll scroll to the bottom.
103 useMaximum = (scrollHeight - clientHeight - scrollTop <= 0);
104 this.setViewScrollTop(scrollBy, useMaximum);
107 getPageData : function(){
108 var panel = this.getPanel(),
110 totalCount = store.getTotalCount();
114 currentPage : store.currentPage,
115 pageCount: Math.ceil(totalCount / store.pageSize),
116 fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
117 toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
121 onElScroll: function(e, t) {
123 panel = me.getPanel(),
125 pageSize = store.pageSize,
126 guaranteedStart = store.guaranteedStart,
127 guaranteedEnd = store.guaranteedEnd,
128 totalCount = store.getTotalCount(),
129 numFromEdge = Math.ceil(me.percentageFromEdge * store.pageSize),
130 position = t.scrollTop,
131 visibleStart = Math.floor(position / me.rowHeight),
132 view = panel.down('tableview'),
134 visibleHeight = viewEl.getHeight(),
135 visibleAhead = Math.ceil(visibleHeight / me.rowHeight),
136 visibleEnd = visibleStart + visibleAhead,
137 prevPage = Math.floor(visibleStart / store.pageSize),
138 nextPage = Math.floor(visibleEnd / store.pageSize) + 2,
139 lastPage = Math.ceil(totalCount / store.pageSize),
140 //requestStart = visibleStart,
141 requestStart = Math.floor(visibleStart / me.snapIncrement) * me.snapIncrement,
142 requestEnd = requestStart + pageSize - 1,
143 activePrefetch = me.activePrefetch;
145 me.visibleStart = visibleStart;
146 me.visibleEnd = visibleEnd;
148 me.syncScroll = true;
149 if (totalCount >= pageSize) {
150 // end of request was past what the total is, grab from the end back a pageSize
151 if (requestEnd > totalCount - 1) {
153 if (store.rangeSatisfied(totalCount - pageSize, totalCount - 1)) {
154 me.syncScroll = true;
156 store.guaranteeRange(totalCount - pageSize, totalCount - 1);
157 // Out of range, need to reset the current data set
158 } else if (visibleStart < guaranteedStart || visibleEnd > guaranteedEnd) {
159 if (store.rangeSatisfied(requestStart, requestEnd)) {
161 store.guaranteeRange(requestStart, requestEnd);
164 me.attemptLoad(requestStart, requestEnd);
166 // dont sync the scroll view immediately, sync after the range has been guaranteed
167 me.syncScroll = false;
168 } else if (activePrefetch && visibleStart < (guaranteedStart + numFromEdge) && prevPage > 0) {
169 me.syncScroll = true;
170 store.prefetchPage(prevPage);
171 } else if (activePrefetch && visibleEnd > (guaranteedEnd - numFromEdge) && nextPage < lastPage) {
172 me.syncScroll = true;
173 store.prefetchPage(nextPage);
182 getSizeCalculation: function() {
183 // Use the direct ownerCt here rather than the scrollerOwner
184 // because we are calculating widths/heights.
185 var owner = this.ownerGrid,
186 view = owner.getView(),
193 if (!this.rowHeight) {
194 this.rowHeight = view.el.down(view.getItemSelector()).getHeight(false, true);
197 // If the Store is *locally* filtered, use the filtered count from getCount.
198 height = store[(!store.remoteFilter && store.isFiltered()) ? 'getCount' : 'getTotalCount']() * this.rowHeight;
212 attemptLoad: function(start, end) {
215 me.loadTask = Ext.create('Ext.util.DelayedTask', me.doAttemptLoad, me, []);
217 me.loadTask.delay(me.scrollToLoadBuffer, me.doAttemptLoad, me, [start, end]);
220 cancelLoad: function() {
222 this.loadTask.cancel();
226 doAttemptLoad: function(start, end) {
227 var store = this.getPanel().store;
228 store.guaranteeRange(start, end);
231 setViewScrollTop: function(scrollTop, useMax) {
232 var owner = this.getPanel(),
233 items = owner.query('tableview'),
240 scrollerElDom = this.el.dom;
242 owner.virtualScrollTop = scrollTop;
244 center = items[1] || items[0];
245 centerEl = center.el.dom;
247 maxScrollTop = ((owner.store.pageSize * this.rowHeight) - centerEl.clientHeight);
248 calcScrollTop = (scrollTop % ((owner.store.pageSize * this.rowHeight) + 1));
250 calcScrollTop = maxScrollTop;
252 if (calcScrollTop > maxScrollTop) {
253 //Ext.Error.raise("Calculated scrollTop was larger than maxScrollTop");
255 // calcScrollTop = maxScrollTop;
257 for (; i < len; i++) {
258 items[i].el.dom.scrollTop = calcScrollTop;