2 * Ext JS Library 2.2.1
\r
3 * Copyright(c) 2006-2009, Ext JS, LLC.
\r
4 * licensing@extjs.com
\r
6 * http://extjs.com/license
\r
10 * @class Ext.PagingToolbar
\r
11 * @extends Ext.Toolbar
\r
12 * <p>A specialized toolbar that is bound to a {@link Ext.data.Store} and provides automatic paging control. This
\r
13 * Component {@link Ext.data.Store#load load}s blocks of data into the Store passing parameters who's names are
\r
14 * specified by the store's {@link Ext.data.Store#paramNames paramNames} property.</p>
\r
16 * Create a new PagingToolbar
\r
17 * @param {Object} config The config object
\r
19 Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
\r
21 * @cfg {Ext.data.Store} store The {@link Ext.data.Store} the paging toolbar should use as its data source (required).
\r
24 * @cfg {Boolean} displayInfo
\r
25 * True to display the displayMsg (defaults to false)
\r
28 * @cfg {Number} pageSize
\r
29 * The number of records to display per page (defaults to 20)
\r
33 * @cfg {String} displayMsg
\r
34 * The paging status message to display (defaults to "Displaying {0} - {1} of {2}"). Note that this string is
\r
35 * formatted using the braced numbers 0-2 as tokens that are replaced by the values for start, end and total
\r
36 * respectively. These tokens should be preserved when overriding this string if showing those values is desired.
\r
38 displayMsg : 'Displaying {0} - {1} of {2}',
\r
40 * @cfg {String} emptyMsg
\r
41 * The message to display when no records are found (defaults to "No data to display")
\r
43 emptyMsg : 'No data to display',
\r
45 * Customizable piece of the default paging text (defaults to "Page")
\r
48 beforePageText : "Page",
\r
50 * Customizable piece of the default paging text (defaults to "of {0}"). Note that this string is
\r
51 * formatted using {0} as a token that is replaced by the number of total pages. This token should be
\r
52 * preserved when overriding this string if showing the total page count is desired.
\r
55 afterPageText : "of {0}",
\r
57 * Customizable piece of the default paging text (defaults to "First Page")
\r
60 firstText : "First Page",
\r
62 * Customizable piece of the default paging text (defaults to "Previous Page")
\r
65 prevText : "Previous Page",
\r
67 * Customizable piece of the default paging text (defaults to "Next Page")
\r
70 nextText : "Next Page",
\r
72 * Customizable piece of the default paging text (defaults to "Last Page")
\r
75 lastText : "Last Page",
\r
77 * Customizable piece of the default paging text (defaults to "Refresh")
\r
80 refreshText : "Refresh",
\r
83 * Object mapping of parameter names for load calls (defaults to {start: 'start', limit: 'limit'})
\r
85 paramNames : {start: 'start', limit: 'limit'},
\r
88 initComponent : function(){
\r
92 * Fires after the active page has been changed.
\r
93 * @param {Ext.PagingToolbar} this
\r
94 * @param {Object} changeEvent An object that has these properties:<ul>
\r
95 * <li><code>total</code> : Number <div class="sub-desc">The total number of records in the dataset as
\r
96 * returned by the server</div></li>
\r
97 * <li><code>activePage</code> : Number <div class="sub-desc">The current page number</div></li>
\r
98 * <li><code>pages</code> : Number <div class="sub-desc">The total number of pages (calculated from
\r
99 * the total number of records in the dataset as returned by the server and the current {@link #pageSize})</div></li>
\r
104 * @event beforechange
\r
105 * Fires just before the active page is changed.
\r
106 * Return false to prevent the active page from being changed.
\r
107 * @param {Ext.PagingToolbar} this
\r
108 * @param {Object} beforeChangeEvent An object that has these properties:<ul>
\r
109 * <li><code>start</code> : Number <div class="sub-desc">The starting row number for the next page of records to
\r
110 * be retrieved from the server</div></li>
\r
111 * <li><code>limit</code> : Number <div class="sub-desc">The number of records to be retrieved from the server</div></li>
\r
113 * (note: the names of the <b>start</b> and <b>limit</b> properties are determined
\r
114 * by the store's {@link Ext.data.Store#paramNames paramNames} property.)
\r
118 Ext.PagingToolbar.superclass.initComponent.call(this);
\r
120 this.bind(this.store);
\r
124 onRender : function(ct, position){
\r
125 Ext.PagingToolbar.superclass.onRender.call(this, ct, position);
\r
126 this.first = this.addButton({
\r
127 tooltip: this.firstText,
\r
128 iconCls: "x-tbar-page-first",
\r
130 handler: this.onClick.createDelegate(this, ["first"])
\r
132 this.prev = this.addButton({
\r
133 tooltip: this.prevText,
\r
134 iconCls: "x-tbar-page-prev",
\r
136 handler: this.onClick.createDelegate(this, ["prev"])
\r
138 this.addSeparator();
\r
139 this.add(this.beforePageText);
\r
140 this.field = Ext.get(this.addDom({
\r
145 cls: "x-tbar-page-number"
\r
147 this.field.on("keydown", this.onPagingKeydown, this);
\r
148 this.field.on("focus", function(){this.dom.select();});
\r
149 this.field.on("blur", this.onPagingBlur, this);
\r
150 this.afterTextEl = this.addText(String.format(this.afterPageText, 1));
\r
151 this.field.setHeight(18);
\r
152 this.addSeparator();
\r
153 this.next = this.addButton({
\r
154 tooltip: this.nextText,
\r
155 iconCls: "x-tbar-page-next",
\r
157 handler: this.onClick.createDelegate(this, ["next"])
\r
159 this.last = this.addButton({
\r
160 tooltip: this.lastText,
\r
161 iconCls: "x-tbar-page-last",
\r
163 handler: this.onClick.createDelegate(this, ["last"])
\r
165 this.addSeparator();
\r
166 this.loading = this.addButton({
\r
167 tooltip: this.refreshText,
\r
168 iconCls: "x-tbar-loading",
\r
169 handler: this.onClick.createDelegate(this, ["refresh"])
\r
172 if(this.displayInfo){
\r
173 this.displayEl = Ext.fly(this.el.dom).createChild({cls:'x-paging-info'});
\r
176 this.onLoad.apply(this, this.dsLoaded);
\r
181 updateInfo : function(){
\r
182 if(this.displayEl){
\r
183 var count = this.store.getCount();
\r
184 var msg = count == 0 ?
\r
188 this.cursor+1, this.cursor+count, this.store.getTotalCount()
\r
190 this.displayEl.update(msg);
\r
195 onLoad : function(store, r, o){
\r
196 if(!this.rendered){
\r
197 this.dsLoaded = [store, r, o];
\r
200 this.cursor = o.params ? o.params[this.paramNames.start] : 0;
\r
201 var d = this.getPageData(), ap = d.activePage, ps = d.pages;
\r
203 this.afterTextEl.el.innerHTML = String.format(this.afterPageText, d.pages);
\r
204 this.field.dom.value = ap;
\r
205 this.first.setDisabled(ap == 1);
\r
206 this.prev.setDisabled(ap == 1);
\r
207 this.next.setDisabled(ap == ps);
\r
208 this.last.setDisabled(ap == ps);
\r
209 this.loading.enable();
\r
211 this.fireEvent('change', this, d);
\r
215 getPageData : function(){
\r
216 var total = this.store.getTotalCount();
\r
219 activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
\r
220 pages : total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
\r
225 onLoadError : function(){
\r
226 if(!this.rendered){
\r
229 this.loading.enable();
\r
233 readPage : function(d){
\r
234 var v = this.field.dom.value, pageNum;
\r
235 if (!v || isNaN(pageNum = parseInt(v, 10))) {
\r
236 this.field.dom.value = d.activePage;
\r
243 onPagingBlur: function(e){
\r
244 this.field.dom.value = this.getPageData().activePage;
\r
248 onPagingKeydown : function(e){
\r
249 var k = e.getKey(), d = this.getPageData(), pageNum;
\r
250 if (k == e.RETURN) {
\r
252 pageNum = this.readPage(d);
\r
253 if(pageNum !== false){
\r
254 pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
\r
255 this.doLoad(pageNum * this.pageSize);
\r
257 }else if (k == e.HOME || k == e.END){
\r
259 pageNum = k == e.HOME ? 1 : d.pages;
\r
260 this.field.dom.value = pageNum;
\r
261 }else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN){
\r
263 if(pageNum = this.readPage(d)){
\r
264 var increment = e.shiftKey ? 10 : 1;
\r
265 if(k == e.DOWN || k == e.PAGEDOWN){
\r
268 pageNum += increment;
\r
269 if(pageNum >= 1 & pageNum <= d.pages){
\r
270 this.field.dom.value = pageNum;
\r
277 beforeLoad : function(){
\r
278 if(this.rendered && this.loading){
\r
279 this.loading.disable();
\r
284 doLoad : function(start){
\r
285 var o = {}, pn = this.paramNames;
\r
286 o[pn.start] = start;
\r
287 o[pn.limit] = this.pageSize;
\r
288 if(this.fireEvent('beforechange', this, o) !== false){
\r
289 this.store.load({params:o});
\r
294 * Change the active page
\r
295 * @param {Integer} page The page to display
\r
297 changePage: function(page){
\r
298 this.doLoad(((page-1) * this.pageSize).constrain(0, this.store.getTotalCount()));
\r
302 onClick : function(which){
\r
303 var store = this.store;
\r
309 this.doLoad(Math.max(0, this.cursor-this.pageSize));
\r
312 this.doLoad(this.cursor+this.pageSize);
\r
315 var total = store.getTotalCount();
\r
316 var extra = total % this.pageSize;
\r
317 var lastStart = extra ? (total - extra) : total-this.pageSize;
\r
318 this.doLoad(lastStart);
\r
321 this.doLoad(this.cursor);
\r
327 * Unbinds the paging toolbar from the specified {@link Ext.data.Store}
\r
328 * @param {Ext.data.Store} store The data store to unbind
\r
330 unbind : function(store){
\r
331 store = Ext.StoreMgr.lookup(store);
\r
332 store.un("beforeload", this.beforeLoad, this);
\r
333 store.un("load", this.onLoad, this);
\r
334 store.un("loadexception", this.onLoadError, this);
\r
335 this.store = undefined;
\r
339 * Binds the paging toolbar to the specified {@link Ext.data.Store}
\r
340 * @param {Ext.data.Store} store The data store to bind
\r
342 bind : function(store){
\r
343 store = Ext.StoreMgr.lookup(store);
\r
344 store.on("beforeload", this.beforeLoad, this);
\r
345 store.on("load", this.onLoad, this);
\r
346 store.on("loadexception", this.onLoadError, this);
\r
347 this.store = store;
\r
351 onDestroy : function(){
\r
353 this.unbind(this.store);
\r
355 Ext.PagingToolbar.superclass.onDestroy.call(this);
\r
358 Ext.reg('paging', Ext.PagingToolbar);