1 /**
  2  * Originally from: http://extjs.com/forum/showthread.php?t=38809
  3  */
  4 
  5 Ext.PagingToolbar = Ext.extend(Ext.Toolbar,
  6 {
  7    autoLoad: false,
  8    mode: 'buttons',
  9    includeTextbox: true,
 10    pageSize: 20,
 11    displayMsg : 'Displaying {0} - {1} of {2}',
 12    emptyMsg : 'No data to display',
 13    beforePageText : "Page",
 14    afterPageText : "of {0}",
 15    firstText : "First Page",
 16    prevText : "Previous Page",
 17    nextText : "Next Page",
 18    lastText : "Last Page",
 19    refreshText : "Refresh",
 20    paramNames : {start: 'start', limit: 'limit'},
 21    
 22    initComponent: function()
 23    {
 24       Ext.PagingToolbar.superclass.initComponent.call(this);
 25       this.current = 0;
 26       this.bind(this.store);
 27       this.addEvents('beforepagechange', 'pagechange');
 28    },
 29    
 30    onRender: function(ct, position)
 31    {
 32       Ext.PagingToolbar.superclass.onRender.call(this, ct, position);
 33       
 34          this.first = this.addButton(
 35          {
 36             tooltip: this.firstText,
 37             iconCls: "x-tbar-page-first",
 38             disabled: true,
 39             scope: this,
 40             handler: this.moveFirst
 41         }
 42         );
 43         this.prev = this.addButton(
 44         {
 45            tooltip: this.prevText,
 46            iconCls: "x-tbar-page-prev",
 47            disabled: true,
 48            scope: this,
 49            handler: this.movePrevious
 50         }
 51         );
 52         this.setupTextBox();
 53         this.addSeparator();
 54         this.next = this.addButton(
 55         {
 56            tooltip: this.nextText,
 57            iconCls: "x-tbar-page-next",
 58            disabled: true,
 59            scope: this,
 60            handler: this.moveNext
 61         }
 62         );
 63         this.last = this.addButton(
 64         {
 65            tooltip: this.lastText,
 66            iconCls: "x-tbar-page-last",
 67            disabled: true,
 68            scope: this,
 69            handler: this.moveLast
 70         }
 71         );
 72       
 73       this.addSeparator();
 74       this.loading = this.addButton(
 75       {
 76          tooltip: this.refreshText,
 77          iconCls: "x-tbar-loading",
 78          scope: this,
 79          handler: this.refresh
 80       }
 81       );
 82       
 83       if (this.displayInfo)
 84          this.displayEl = Ext.fly(this.el.dom).createChild({cls:'x-paging-info'});
 85 
 86       if (this.autoLoad)
 87          this.doLoad(0);
 88       else if (this.dsLoaded)
 89          this.onLoad.apply(this, this.dsLoaded);
 90    },
 91    
 92    getPageSize: function()
 93    {
 94       return this.pageSize;
 95    },
 96    
 97    setPageSize: function(size)
 98    {
 99       this.pageSize = size;
100       this.moveFirst();
101    },
102    
103    getActivePage: function()
104    {
105       return this.current;
106    },
107    
108    setActivePage: function(page)
109    {
110       if (!isNaN(page))
111       {
112          if (page >= 0 && page <= this.getLastPage())
113          {
114             this.doLoad(page);
115             return true;
116          }
117       }
118       return false;
119    },
120    
121    refresh: function()
122    {
123       this.doLoad(this.current);
124    },
125    
126    moveFirst: function()
127    {
128       return this.setActivePage(0);
129    },
130    
131    movePrevious: function()
132    {
133       return this.setActivePage(this.current - 1);
134    },
135    
136    moveNext: function()
137    {
138       return this.setActivePage(this.current + 1);
139    },
140    
141    moveLast: function()
142    {
143       return this.setActivePage(this.getLastPage());
144    },
145    
146    unbind: function(store)
147    {
148       store = Ext.StoreMgr.lookup(store);
149       store.un("beforeload", this.beforeLoad, this);
150       store.un("load", this.onLoad, this);
151       store.un("loadexception", this.onLoadError, this);
152       this.store = undefined;
153    },
154 
155    bind : function(store)
156    {
157       store = Ext.StoreMgr.lookup(store);
158       store.on("beforeload", this.beforeLoad, this);
159       store.on("load", this.onLoad, this);
160       store.on("loadexception", this.onLoadError, this);
161       this.store = store;
162    },
163    
164    //private
165    setupTextBox: function()
166    {
167       if (this.includeTextbox)
168       {
169          this.addSeparator();
170          this.add(this.beforePageText);
171          this.field = Ext.get(this.addDom(
172          {
173             tag: "input",
174             type: "text",
175             size: "3",
176             value: "1",
177             cls: "x-tbar-page-number"
178          }).el);
179          this.field.on("keydown", this.onPagingKeydown, this);
180          this.field.on("focus", function()
181          {
182             this.dom.select();
183          }
184          );
185          this.afterTextEl = this.addText(String.format(this.afterPageText, 1));
186          this.field.setHeight(18);
187       }
188    },
189    
190    //private
191    updateInfo: function()
192    {
193       if (this.displayEl)
194       {
195          var count = this.store.getCount();
196          var disp = (this.current * this.pageSize) + 1;
197          var msg = count == 0 ? this.emptyMsg : String.format(this.displayMsg, disp, disp + count - 1, this.store.getTotalCount());
198          this.displayEl.update(msg);
199       }
200     },
201     
202     //private
203     getPageData: function()
204     {
205        var total = this.store.getTotalCount();
206        return {
207           total: total,
208           pages:  total < this.pageSize ? 1 : Math.ceil(total / this.pageSize)
209        };
210     },
211    
212    //private
213    onLoad: function(store, r, o)
214    {
215       if (!this.rendered)
216       {
217          this.dsLoaded = [store, r, o];
218          return;
219       }
220       
221       var p = o.params;
222       this.current = p ? Math.floor(p[this.paramNames.start] / p[this.paramNames.limit]) : 0;
223       this.fireEvent('pagechange', this, this.current)
224       var pages = this.getPageData().pages;
225       if (this.includeTextbox)
226       {
227          this.afterTextEl.el.innerHTML = String.format(this.afterPageText, pages);
228          this.field.dom.value = this.current + 1;
229       }
230       
231          this.first.setDisabled(this.current == 0);
232          this.prev.setDisabled(this.current == 0);
233          this.next.setDisabled(this.current == pages - 1);
234          this.last.setDisabled(this.current == pages - 1);
235       this.loading.enable();
236       this.updateInfo();
237    },
238    
239    //private
240    onLoadError: function()
241    {
242       if (!this.rendered)
243          return;
244 
245       this.loading.enable();
246    },
247    
248    //private
249    beforeLoad: function()
250    {
251       if (this.rendered && this.loading)
252          this.loading.disable();
253    },
254    
255    //private
256    doLoad: function(start)
257    {
258       if (this.fireEvent('beforepagechange', this, start) !== false)
259       {
260          var o = {}, pn = this.paramNames;
261          o[pn.start] = start * this.pageSize;
262          o[pn.limit] = this.pageSize;
263          this.store.load({params:o});
264       }
265       else
266       {
267          if (this.useTextBox)
268             this.field.dom.value = this.current + 1;
269       }
270    },
271    
272    //private
273    readPage : function()
274    {
275       var v = this.field.dom.value, pageNum;
276       if (!v || isNaN(pageNum = parseInt(v, 10))) 
277       {
278          this.field.dom.value = this.current + 1;
279          return false;
280       }
281       return pageNum;
282    },
283    
284    //private
285    onPagingKeydown: function(e)
286    {
287       var k = e.getKey(), pages = this.getPageData().pages, pageNum;
288       if (k == e.RETURN) 
289       {
290          e.stopEvent();
291          if (pageNum = this.readPage())
292          {
293             pageNum = Math.min(Math.max(1, pageNum), pages) - 1;
294             this.loadOrSet(pageNum);
295          }
296       }
297       else if (k == e.HOME || k == e.END)
298       {
299          e.stopEvent();
300          pageNum = k == e.HOME ? 1 : pages;
301          this.field.dom.value = pageNum;
302          this.loadOrSet(pageNum - 1);
303       }
304       else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN)
305       {
306          e.stopEvent();
307          if (pageNum = this.readPage())
308          {
309             var increment = e.shiftKey ? 10 : 1;
310             if (k == e.DOWN || k == e.PAGEDOWN)
311                increment *= -1;
312                
313             pageNum += increment;
314             if (pageNum > pages)
315                pageNum = pages;
316             else if (pageNum < 1)
317                pageNum = 1;
318                
319             this.field.dom.value = pageNum;
320             this.loadOrSet(pageNum - 1);
321          }
322       }
323    },
324    
325    //private
326    loadOrSet: function(num)
327    {
328       this.doLoad(num);
329    },
330    
331    //private
332    getLastPage: function()
333    {
334       return this.getPageData().pages - 1;
335    }
336 }
337 );
338 
339 Ext.namespace('Ext.ux');
340 
341 Ext.ux.PageSizePlugin = function() {
342     Ext.ux.PageSizePlugin.superclass.constructor.call(this, {
343         store: new Ext.data.SimpleStore({
344             fields: ['text', 'value'],
345             data: [['10', 10], ['20', 20], ['30', 30], ['50', 50], ['100', 100],['200','200']]
346         }),
347         mode: 'local',
348         displayField: 'text',
349         valueField: 'value',
350         triggerAction: 'all',
351         width: 45,
352         regex: /^\d+$/,
353         regexText: 'Please enter numerals only.',
354         editable: true,
355         forceSelection: false
356     });
357 };
358 
359 Ext.extend(Ext.ux.PageSizePlugin, Ext.form.ComboBox, {
360     init: function(paging) {
361         paging.on('render', this.onInitView, this);
362     },
363 
364     onInitView: function(paging) {
365         paging.add('-',this,'Items per page','-');
366         this.setValue(paging.pageSize);
367         this.on('select', this.onPageSizeChanged, paging);
368         this.on('change', this.onPageSizeChanged, paging);
369     },
370     
371     onPageSizeChanged: function(combo) {
372         if (combo.isValid()) {
373             this.pageSize = parseInt(combo.getValue());
374             this.doLoad(0);
375         }
376     }
377 });
378