2 * @class Ext.grid.PagingScroller
3 * @extends Ext.grid.Scroller
7 Ext.define('Ext.grid.PagingScroller', {
8 extend: 'Ext.grid.Scroller',
9 alias: 'widget.paginggridscroller',
12 // '<tpl for="pages">',
13 // '<div class="' + Ext.baseCSSPrefix + 'stretcher" style="width: {width}px;height: {height}px;"></div>',
17 * @cfg {Number} percentageFromEdge This is a number above 0 and less than 1 which specifies
18 * at what percentage to begin fetching the next page. For example if the pageSize is 100
19 * and the percentageFromEdge is the default of 0.35, the paging scroller will prefetch pages
20 * when scrolling up between records 0 and 34 and when scrolling down between records 65 and 99.
22 percentageFromEdge: 0.35,
25 * @cfg {Number} scrollToLoadBuffer This is the time in milliseconds to buffer load requests
26 * when scrolling the PagingScrollbar.
28 scrollToLoadBuffer: 200,
37 initComponent: function() {
41 ds.on('guaranteedrange', this.onGuaranteedRange, this);
42 this.callParent(arguments);
46 onGuaranteedRange: function(range, start, end) {
50 // this should never happen
51 if (range.length && me.visibleStart < range[0].index) {
55 ds.loadRecords(range);
61 me.on('afterrender', this.invalidate, this, {single: true});
74 scrollerElDom = this.el.dom,
75 rowOffset = me.visibleStart - store.guaranteedStart,
76 scrollBy = rowOffset * me.rowHeight,
77 scrollHeight = scrollerElDom.scrollHeight,
78 clientHeight = scrollerElDom.clientHeight,
79 scrollTop = scrollerElDom.scrollTop,
82 // BrowserBug: clientHeight reports 0 in IE9 StrictMode
83 // Instead we are using offsetHeight and hardcoding borders
84 if (Ext.isIE9 && Ext.isStrict) {
85 clientHeight = scrollerElDom.offsetHeight + 2;
88 // This should always be zero or greater than zero but staying
89 // safe and less than 0 we'll scroll to the bottom.
90 useMaximum = (scrollHeight - clientHeight - scrollTop <= 0);
91 this.setViewScrollTop(scrollBy, useMaximum);
94 getPageData : function(){
95 var panel = this.getPanel(),
97 totalCount = store.getTotalCount();
101 currentPage : store.currentPage,
102 pageCount: Math.ceil(totalCount / store.pageSize),
103 fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
104 toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
108 onElScroll: function(e, t) {
110 panel = me.getPanel(),
112 pageSize = store.pageSize,
113 guaranteedStart = store.guaranteedStart,
114 guaranteedEnd = store.guaranteedEnd,
115 totalCount = store.getTotalCount(),
116 numFromEdge = Math.ceil(me.percentageFromEdge * store.pageSize),
117 position = t.scrollTop,
118 visibleStart = Math.floor(position / me.rowHeight),
119 view = panel.down('tableview'),
121 visibleHeight = viewEl.getHeight(),
122 visibleAhead = Math.ceil(visibleHeight / me.rowHeight),
123 visibleEnd = visibleStart + visibleAhead,
124 prevPage = Math.floor(visibleStart / store.pageSize),
125 nextPage = Math.floor(visibleEnd / store.pageSize) + 2,
126 lastPage = Math.ceil(totalCount / store.pageSize),
127 //requestStart = visibleStart,
128 requestStart = Math.floor(visibleStart / me.snapIncrement) * me.snapIncrement,
129 requestEnd = requestStart + pageSize - 1,
130 activePrefetch = me.activePrefetch;
132 me.visibleStart = visibleStart;
133 me.visibleEnd = visibleEnd;
136 me.syncScroll = true;
137 if (totalCount >= pageSize) {
138 // end of request was past what the total is, grab from the end back a pageSize
139 if (requestEnd > totalCount - 1) {
141 if (store.rangeSatisfied(totalCount - pageSize, totalCount - 1)) {
142 me.syncScroll = true;
144 store.guaranteeRange(totalCount - pageSize, totalCount - 1);
145 // Out of range, need to reset the current data set
146 } else if (visibleStart < guaranteedStart || visibleEnd > guaranteedEnd) {
147 if (store.rangeSatisfied(requestStart, requestEnd)) {
149 store.guaranteeRange(requestStart, requestEnd);
152 me.attemptLoad(requestStart, requestEnd);
154 // dont sync the scroll view immediately, sync after the range has been guaranteed
155 me.syncScroll = false;
156 } else if (activePrefetch && visibleStart < (guaranteedStart + numFromEdge) && prevPage > 0) {
157 me.syncScroll = true;
158 store.prefetchPage(prevPage);
159 } else if (activePrefetch && visibleEnd > (guaranteedEnd - numFromEdge) && nextPage < lastPage) {
160 me.syncScroll = true;
161 store.prefetchPage(nextPage);
171 getSizeCalculation: function() {
172 // Use the direct ownerCt here rather than the scrollerOwner
173 // because we are calculating widths/heights.
174 var owner = this.ownerCt,
175 view = owner.getView(),
182 if (!this.rowHeight) {
183 this.rowHeight = view.el.down(view.getItemSelector()).getHeight(false, true);
186 height = store.getTotalCount() * this.rowHeight;
200 attemptLoad: function(start, end) {
203 me.loadTask = Ext.create('Ext.util.DelayedTask', me.doAttemptLoad, me, []);
205 me.loadTask.delay(me.scrollToLoadBuffer, me.doAttemptLoad, me, [start, end]);
208 cancelLoad: function() {
210 this.loadTask.cancel();
214 doAttemptLoad: function(start, end) {
215 var store = this.getPanel().store;
216 store.guaranteeRange(start, end);
219 setViewScrollTop: function(scrollTop, useMax) {
220 var owner = this.getPanel(),
221 items = owner.query('tableview'),
228 scrollerElDom = this.el.dom;
230 owner.virtualScrollTop = scrollTop;
232 center = items[1] || items[0];
233 centerEl = center.el.dom;
235 maxScrollTop = ((owner.store.pageSize * this.rowHeight) - centerEl.clientHeight);
236 calcScrollTop = (scrollTop % ((owner.store.pageSize * this.rowHeight) + 1));
238 calcScrollTop = maxScrollTop;
240 if (calcScrollTop > maxScrollTop) {
241 //Ext.Error.raise("Calculated scrollTop was larger than maxScrollTop");
243 // calcScrollTop = maxScrollTop;
245 for (; i < len; i++) {
246 items[i].el.dom.scrollTop = calcScrollTop;