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
19 Ext.define('Ext.grid.PagingScroller', {
20 extend: 'Ext.grid.Scroller',
21 alias: 'widget.paginggridscroller',
24 // '<tpl for="pages">',
25 // '<div class="' + Ext.baseCSSPrefix + 'stretcher" style="width: {width}px;height: {height}px;"></div>',
29 * @cfg {Number} percentageFromEdge This is a number above 0 and less than 1 which specifies
30 * at what percentage to begin fetching the next page. For example if the pageSize is 100
31 * and the percentageFromEdge is the default of 0.35, the paging scroller will prefetch pages
32 * when scrolling up between records 0 and 34 and when scrolling down between records 65 and 99.
34 percentageFromEdge: 0.35,
37 * @cfg {Number} scrollToLoadBuffer This is the time in milliseconds to buffer load requests
38 * when scrolling the PagingScrollbar.
40 scrollToLoadBuffer: 200,
49 initComponent: function() {
53 ds.on('guaranteedrange', me.onGuaranteedRange, me);
54 me.callParent(arguments);
57 onGuaranteedRange: function(range, start, end) {
61 // this should never happen
62 if (range.length && me.visibleStart < range[0].index) {
66 ds.loadRecords(range);
72 me.on('afterrender', me.invalidate, me, {single: true});
77 // only sync if there is a paging scrollbar element and it has a scroll height (meaning it's currently in the DOM)
78 if (me.scrollEl && me.scrollEl.dom && me.scrollEl.dom.scrollHeight) {
88 scrollerElDom = this.scrollEl.dom,
89 rowOffset = me.visibleStart - store.guaranteedStart,
90 scrollBy = rowOffset * me.rowHeight,
91 scrollHeight = scrollerElDom.scrollHeight,
92 clientHeight = scrollerElDom.clientHeight,
93 scrollTop = scrollerElDom.scrollTop,
97 // BrowserBug: clientHeight reports 0 in IE9 StrictMode
98 // Instead we are using offsetHeight and hardcoding borders
99 if (Ext.isIE9 && Ext.isStrict) {
100 clientHeight = scrollerElDom.offsetHeight + 2;
103 // This should always be zero or greater than zero but staying
104 // safe and less than 0 we'll scroll to the bottom.
105 useMaximum = (scrollHeight - clientHeight - scrollTop <= 0);
106 this.setViewScrollTop(scrollBy, useMaximum);
109 getPageData : function(){
110 var panel = this.getPanel(),
112 totalCount = store.getTotalCount();
116 currentPage : store.currentPage,
117 pageCount: Math.ceil(totalCount / store.pageSize),
118 fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
119 toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
123 onElScroll: function(e, t) {
125 panel = me.getPanel(),
127 pageSize = store.pageSize,
128 guaranteedStart = store.guaranteedStart,
129 guaranteedEnd = store.guaranteedEnd,
130 totalCount = store.getTotalCount(),
131 numFromEdge = Math.ceil(me.percentageFromEdge * pageSize),
132 position = t.scrollTop,
133 visibleStart = Math.floor(position / me.rowHeight),
134 view = panel.down('tableview'),
136 visibleHeight = viewEl.getHeight(),
137 visibleAhead = Math.ceil(visibleHeight / me.rowHeight),
138 visibleEnd = visibleStart + visibleAhead,
139 prevPage = Math.floor(visibleStart / pageSize),
140 nextPage = Math.floor(visibleEnd / pageSize) + 2,
141 lastPage = Math.ceil(totalCount / pageSize),
142 snap = me.snapIncrement,
143 requestStart = Math.floor(visibleStart / snap) * snap,
144 requestEnd = requestStart + pageSize - 1,
145 activePrefetch = me.activePrefetch;
147 me.visibleStart = visibleStart;
148 me.visibleEnd = visibleEnd;
151 me.syncScroll = true;
152 if (totalCount >= pageSize) {
153 // end of request was past what the total is, grab from the end back a pageSize
154 if (requestEnd > totalCount - 1) {
156 if (store.rangeSatisfied(totalCount - pageSize, totalCount - 1)) {
157 me.syncScroll = true;
159 store.guaranteeRange(totalCount - pageSize, totalCount - 1);
160 // Out of range, need to reset the current data set
161 } else if (visibleStart <= guaranteedStart || visibleEnd > guaranteedEnd) {
162 if (visibleStart <= guaranteedStart) {
164 requestStart -= snap;
167 if (requestStart < 0) {
169 requestEnd = pageSize;
172 if (store.rangeSatisfied(requestStart, requestEnd)) {
174 store.guaranteeRange(requestStart, requestEnd);
177 me.attemptLoad(requestStart, requestEnd);
179 // dont sync the scroll view immediately, sync after the range has been guaranteed
180 me.syncScroll = false;
181 } else if (activePrefetch && visibleStart < (guaranteedStart + numFromEdge) && prevPage > 0) {
182 me.syncScroll = true;
183 store.prefetchPage(prevPage);
184 } else if (activePrefetch && visibleEnd > (guaranteedEnd - numFromEdge) && nextPage < lastPage) {
185 me.syncScroll = true;
186 store.prefetchPage(nextPage);
195 getSizeCalculation: function() {
196 // Use the direct ownerCt here rather than the scrollerOwner
197 // because we are calculating widths/heights.
199 owner = me.ownerGrid,
200 view = owner.getView(),
208 me.rowHeight = view.el.down(view.getItemSelector()).getHeight(false, true);
211 // If the Store is *locally* filtered, use the filtered count from getCount.
212 height = store[(!store.remoteFilter && store.isFiltered()) ? 'getCount' : 'getTotalCount']() * me.rowHeight;
226 attemptLoad: function(start, end) {
229 me.loadTask = Ext.create('Ext.util.DelayedTask', me.doAttemptLoad, me, []);
231 me.loadTask.delay(me.scrollToLoadBuffer, me.doAttemptLoad, me, [start, end]);
234 cancelLoad: function() {
236 this.loadTask.cancel();
240 doAttemptLoad: function(start, end) {
241 var store = this.getPanel().store;
242 store.guaranteeRange(start, end);
245 setViewScrollTop: function(scrollTop, useMax) {
247 owner = me.getPanel(),
248 items = owner.query('tableview'),
255 scrollerElDom = me.el.dom;
257 owner.virtualScrollTop = scrollTop;
259 center = items[1] || items[0];
260 centerEl = center.el.dom;
262 maxScrollTop = ((owner.store.pageSize * me.rowHeight) - centerEl.clientHeight);
263 calcScrollTop = (scrollTop % ((owner.store.pageSize * me.rowHeight) + 1));
265 calcScrollTop = maxScrollTop;
267 if (calcScrollTop > maxScrollTop) {
268 //Ext.Error.raise("Calculated scrollTop was larger than maxScrollTop");
270 // calcScrollTop = maxScrollTop;
272 for (; i < len; i++) {
273 items[i].el.dom.scrollTop = calcScrollTop;