source: Dev/trunk/src/client/dojox/grid/enhanced/plugins/Pagination.js

Last change on this file was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 31.7 KB
Line 
1define([
2        "dojo/_base/kernel",
3        "dojo/_base/declare",
4        "dojo/_base/array",
5        "dojo/_base/connect",
6        "dojo/_base/lang",
7        "dojo/_base/html",
8        "dojo/_base/event",
9        "dojo/query",
10        "dojo/string",
11        "dojo/keys",
12        "dojo/text!../templates/Pagination.html",
13        "./Dialog",
14        "./_StoreLayer",
15        "../_Plugin",
16        "../../EnhancedGrid",
17        "dijit/form/Button",
18        "dijit/form/NumberTextBox",
19        "dijit/focus",
20        "dijit/_Widget",
21        "dijit/_TemplatedMixin",
22        "dijit/_WidgetsInTemplateMixin",
23        "dojox/html/metrics",
24        "dojo/i18n!../nls/Pagination"
25], function(kernel, declare, array, connect, lang, html, event, query,
26        string, keys, template, Dialog, layers, _Plugin, EnhancedGrid,
27        Button, NumberTextBox, dijitFocus, _Widget, _TemplatedMixin, _WidgetsInTemplateMixin, metrics, nls){
28               
29var _GotoPagePane = declare("dojox.grid.enhanced.plugins.pagination._GotoPagePane", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin], {
30        templateString: "<div>" +
31                                                "<div class='dojoxGridDialogMargin' dojoAttachPoint='_mainMsgNode'></div>" +
32                                                "<div class='dojoxGridDialogMargin'>" +
33                                                        "<input dojoType='dijit.form.NumberTextBox' style='width: 50px;' dojoAttachPoint='_pageInputBox' dojoAttachEvent='onKeyUp: _onKey'></input>" +
34                                                        "<label dojoAttachPoint='_pageLabelNode'></label>" +
35                                                "</div>" +
36                                                "<div class='dojoxGridDialogButton'>" +
37                                                        "<button dojoType='dijit.form.Button' dojoAttachPoint='_confirmBtn' dojoAttachEvent='onClick: _onConfirm'></button>" +
38                                                        "<button dojoType='dijit.form.Button' dojoAttachPoint='_cancelBtn' dojoAttachEvent='onClick: _onCancel'></button>" +
39                                                "</div>" +
40                                        "</div>",
41        widgetsInTemplate: true,
42        dlg: null,
43        postMixInProperties: function(){
44                this.plugin = this.dlg.plugin;
45        },
46        postCreate: function(){
47                this.inherited(arguments);
48                this._mainMsgNode.innerHTML = this.plugin._nls[12];
49                this._confirmBtn.set("label", this.plugin._nls[14]);
50                this._confirmBtn.set("disabled", true);
51                this._cancelBtn.set("label", this.plugin._nls[15]);
52        },
53        _onConfirm: function(evt){
54                if(this._pageInputBox.isValid() && this._pageInputBox.getDisplayedValue() !== ""){
55                        this.plugin.currentPage(this._pageInputBox.parse(this._pageInputBox.getDisplayedValue()));
56                        this.dlg._gotoPageDialog.hide();
57                        this._pageInputBox.reset();
58                }
59                stopEvent(evt);
60        },
61        _onCancel: function(evt){
62                this._pageInputBox.reset();
63                this.dlg._gotoPageDialog.hide();
64                stopEvent(evt);
65        },
66        _onKey: function(evt){
67                this._confirmBtn.set("disabled", !this._pageInputBox.isValid() || this._pageInputBox.getDisplayedValue() == "");
68                if(!evt.altKey && !evt.metaKey && evt.keyCode === keys.ENTER){
69                        this._onConfirm(evt);
70                }
71        }
72});
73
74var _GotoPageDialog = declare("dojox.grid.enhanced.plugins.pagination._GotoPageDialog", null, {
75        pageCount: 0,
76        dlgPane: null,
77        constructor: function(plugin){
78                this.plugin = plugin;
79                this.dlgPane = new _GotoPagePane({"dlg": this});
80                this.dlgPane.startup();
81                this._gotoPageDialog = new Dialog({
82                        "refNode": plugin.grid.domNode,
83                        "title": this.plugin._nls[11],
84                        "content": this.dlgPane
85                });
86                this._gotoPageDialog.startup();
87        },
88        _updatePageCount: function(){
89                this.pageCount = this.plugin.getTotalPageNum();
90                this.dlgPane._pageInputBox.constraints = {fractional:false, min:1, max:this.pageCount};
91                this.dlgPane._pageLabelNode.innerHTML = string.substitute(this.plugin._nls[13], [this.pageCount]);
92        },
93        showDialog: function(){
94                this._updatePageCount();
95                this._gotoPageDialog.show();
96        },
97        destroy: function(){
98                this._gotoPageDialog.destroy();
99        }
100});
101
102var _ForcedPageStoreLayer = declare("dojox.grid.enhanced.plugins._ForcedPageStoreLayer", layers._StoreLayer, {
103        tags: ["presentation"],
104        constructor: function(plugin){
105                this._plugin = plugin;
106        },
107        _fetch: function(request){
108                var _this = this,
109                        plugin = _this._plugin,
110                        grid = plugin.grid,
111                        scope = request.scope || kernel.global,
112                        onBegin = request.onBegin;
113                request.start = (plugin._currentPage - 1) * plugin._currentPageSize + request.start;
114                _this.startIdx = request.start;
115                _this.endIdx = request.start + plugin._currentPageSize - 1;
116                var p = plugin._paginator;
117                if(!plugin._showAll){
118                        plugin._showAll = !p.sizeSwitch && !p.pageStepper && !p.gotoButton;
119                }
120                if(onBegin && plugin._showAll){
121                        request.onBegin = function(size, req){
122                                plugin._maxSize = plugin._currentPageSize = size;
123                                _this.startIdx = 0;
124                                _this.endIdx = size - 1;
125                                plugin._paginator._update();
126                                req.onBegin = onBegin;
127                                req.onBegin.call(scope, size, req);
128                        };
129                }else if(onBegin){
130                        request.onBegin = function(size, req){
131                                req.start = 0;
132                                req.count = plugin._currentPageSize;
133                                plugin._maxSize = size;
134                                _this.endIdx = _this.endIdx >= size ? (size - 1) : _this.endIdx;
135                                if(_this.startIdx > size && size !== 0){
136                                        grid._pending_requests[req.start] = false;
137                                        plugin.firstPage();
138                                }
139                                plugin._paginator._update();
140                                req.onBegin = onBegin;
141                                req.onBegin.call(scope, Math.min(plugin._currentPageSize, (size - _this.startIdx)), req);
142                        };
143                }
144                return lang.hitch(this._store, this._originFetch)(request);
145        }
146});
147
148var stopEvent = function(evt){
149        try{
150                if(evt){
151                        event.stop(evt);
152                }
153        }catch(e){}
154};
155
156var _Focus = declare("dojox.grid.enhanced.plugins.pagination._Focus", null, {
157        _focusedNode: null,
158        _isFocused: false,
159        constructor: function(paginator){
160                this._pager = paginator;
161                var focusMgr =  paginator.plugin.grid.focus;
162                paginator.plugin.connect(paginator, 'onSwitchPageSize', lang.hitch(this, '_onActive'));
163                paginator.plugin.connect(paginator, 'onPageStep', lang.hitch(this, '_onActive'));
164                paginator.plugin.connect(paginator, 'onShowGotoPageDialog', lang.hitch(this, '_onActive'));
165                paginator.plugin.connect(paginator, '_update', lang.hitch(this, '_moveFocus'));
166        },
167        _onFocus: function(evt, step){
168                var node, nodes;
169                if(!this._isFocused){
170                        node = this._focusedNode || query('[tabindex]', this._pager.domNode)[0];
171                }else if(step && this._focusedNode){
172                        var dir = step > 0 ? -1 : 1,
173                                tabindex = parseInt(this._focusedNode.getAttribute('tabindex'), 10) + dir;
174                        while(tabindex >= -3 && tabindex < 0){
175                                node = query('[tabindex=' + tabindex + ']', this._pager.domNode)[0];
176                                if(node){
177                                        break;
178                                }else{
179                                        tabindex += dir;
180                                }
181                        }
182                }
183                return this._focus(node, evt);
184        },
185        _onBlur: function(evt, step){
186                if(!step || !this._focusedNode){
187                        this._isFocused = false;
188                        if(this._focusedNode && html.hasClass(this._focusedNode, 'dojoxGridButtonFocus')){
189                                html.removeClass(this._focusedNode, 'dojoxGridButtonFocus');
190                        }
191                        return true;
192                }
193                var node, dir = step > 0 ? -1 : 1,
194                        tabindex = parseInt(this._focusedNode.getAttribute('tabindex'), 10) + dir;
195                while(tabindex >= -3 && tabindex < 0){
196                        node = query('[tabindex=' + tabindex + ']', this._pager.domNode)[0];
197                        if(node){
198                                break;
199                        }else{
200                                tabindex += dir;
201                        }
202                }
203                if(!node){
204                        this._isFocused = false;
205                        if(html.hasClass(this._focusedNode, 'dojoxGridButtonFocus')){
206                                html.removeClass(this._focusedNode, 'dojoxGridButtonFocus');
207                        }
208                }
209                return node ? false : true;
210        },
211        _onMove: function(rowDelta, colDelta, evt){
212                if(this._focusedNode){
213                        var tabindex = this._focusedNode.getAttribute('tabindex'),
214                                delta = colDelta == 1 ? "nextSibling" : "previousSibling",
215                                node = this._focusedNode[delta];
216                        while(node){
217                                if(node.getAttribute('tabindex') == tabindex){
218                                        this._focus(node);
219                                        break;
220                                }
221                                node = node[delta];
222                        }
223                }
224        },
225        _focus: function(node, evt){
226                if(node){
227                        this._isFocused = true;
228                        if(kernel.isIE && this._focusedNode){
229                                html.removeClass(this._focusedNode, 'dojoxGridButtonFocus');
230                        }
231                        this._focusedNode = node;
232                        node.focus();
233                        if(kernel.isIE){
234                                html.addClass(node, 'dojoxGridButtonFocus');
235                        }
236                        stopEvent(evt);
237                        return true;
238                }
239                return false;
240        },
241        _onActive: function(e){
242                this._focusedNode = e.target;
243                if(!this._isFocused){
244                        this._pager.plugin.grid.focus.focusArea('pagination' + this._pager.position);
245                }
246        },
247        _moveFocus: function(){
248                if(this._focusedNode && !this._focusedNode.getAttribute('tabindex')){
249                        var next = this._focusedNode.nextSibling;
250                        while(next){
251                                if(next.getAttribute('tabindex')){
252                                        this._focus(next);
253                                        return;
254                                }
255                                next = next.nextSibling;
256                        }
257                        var prev = this._focusedNode.previousSibling;
258                        while(prev){
259                                if(prev.getAttribute('tabindex')){
260                                        this._focus(prev);
261                                        return;
262                                }
263                                prev = prev.previousSibling;
264                        }
265                        this._focusedNode = null;
266                        this._onBlur();
267                }else if(kernel.isIE && this._focusedNode){
268                        html.addClass(this._focusedNode, 'dojoxGridButtonFocus');
269                }
270        }
271});
272
273var _Paginator = declare("dojox.grid.enhanced.plugins._Paginator", [_Widget, _TemplatedMixin], {
274        templateString: template,
275        constructor: function(params){
276                lang.mixin(this, params);
277                this.grid = this.plugin.grid;
278        },
279        postCreate: function(){
280                this.inherited(arguments);
281                var _this = this, g = this.grid;
282                this.plugin.connect(g, "_resize", lang.hitch(this, "_resetGridHeight"));
283                this._originalResize = g.resize;
284                g.resize = function(changeSize, resultSize){
285                        _this._changeSize = changeSize;
286                        _this._resultSize = resultSize;
287                        _this._originalResize.apply(g, arguments);
288                };
289                this.focus = _Focus(this);
290                this._placeSelf();
291        },
292        destroy: function(){
293                this.inherited(arguments);
294                this.grid.focus.removeArea("pagination" + this.position);
295                if(this._gotoPageDialog){
296                        this._gotoPageDialog.destroy();
297                }
298                this.grid.resize = this._originalResize;
299        },
300        onSwitchPageSize: function(/*Event*/evt){
301
302        },
303        onPageStep: function(/*Event*/evt){
304
305        },
306        onShowGotoPageDialog: function(/*Event*/evt){
307
308        },
309        _update: function(){
310                // summary:
311                //              Function to update paging information and update
312                //              pagination bar display.
313                this._updateDescription();
314                this._updatePageStepper();
315                this._updateSizeSwitch();
316                this._updateGotoButton();
317        },
318        _registerFocus: function(isTop){
319                // summary:
320                //              Function to register pagination bar to focus manager.
321                var focusMgr = this.grid.focus,
322                        name = "pagination" + this.position,
323                        f = this.focus;
324                focusMgr.addArea({
325                        name: name,
326                        onFocus: lang.hitch(this.focus, "_onFocus"),
327                        onBlur: lang.hitch(this.focus, "_onBlur"),
328                        onMove: lang.hitch(this.focus, "_onMove")
329                });
330                focusMgr.placeArea(name, isTop ? "before" : "after", isTop ? "header" : "content");
331        },
332        _placeSelf: function(){
333                // summary:
334                //              Place pagination bar to a position.
335                //              There are two options, top of the grid, bottom of the grid.
336                var g = this.grid,
337                        isTop = this.position == "top";
338                this.placeAt(isTop ? g.viewsHeaderNode : g.viewsNode, isTop ? "before" : "after");
339                this._registerFocus(isTop);
340        },
341        _resetGridHeight: function(changeSize, resultSize){
342                // summary:
343                //              Function of resize grid height to place this pagination bar.
344                //              Since the grid would be able to add other element in its domNode, we have
345                //              change the grid view size to place the pagination bar.
346                //              This function will resize the grid viewsNode height, scorllboxNode height
347                var g = this.grid;
348                changeSize = changeSize || this._changeSize;
349                resultSize = resultSize || this._resultSize;
350                delete this._changeSize;
351                delete this._resultSize;
352                if(g._autoHeight){
353                        return;
354                }
355                var padBorder = g._getPadBorder().h;
356                if(!this.plugin.gh){
357                        this.plugin.gh = (g.domNode.clientHeight || html.style(g.domNode, 'height')) + 2 * padBorder;
358                }
359                if(resultSize){
360                        changeSize = resultSize;
361                }
362                if(changeSize){
363                        this.plugin.gh = html.contentBox(g.domNode).h + 2 * padBorder;
364                }
365                var gh = this.plugin.gh,
366                        hh = g._getHeaderHeight(),
367                        ph = html.marginBox(this.domNode).h;
368                // ph = this.plugin._paginator.position == "bottom" ? ph * 2 : ph;
369                if(typeof g.autoHeight === "number"){
370                        var cgh = gh + ph - padBorder;
371                        html.style(g.domNode, "height", cgh + "px");
372                        html.style(g.viewsNode, "height", (cgh - ph - hh) + "px");
373                        this._styleMsgNode(hh, html.marginBox(g.viewsNode).w, cgh - ph - hh);
374                }else{
375                        var h = gh - ph - hh - padBorder;
376                        html.style(g.viewsNode, "height", h + "px");
377                        var hasHScroller = array.some(g.views.views, function(v){
378                                return v.hasHScrollbar();
379                        });
380                        array.forEach(g.viewsNode.childNodes, function(c){
381                                html.style(c, "height", h + "px");
382                        });
383                        array.forEach(g.views.views, function(v){
384                                if(v.scrollboxNode){
385                                        if(!v.hasHScrollbar() && hasHScroller){
386                                                html.style(v.scrollboxNode, "height", (h - metrics.getScrollbar().h) + "px");
387                                        }else{
388                                                html.style(v.scrollboxNode, "height", h + "px");
389                                        }
390                                }
391                        });
392                        this._styleMsgNode(hh, html.marginBox(g.viewsNode).w, h);
393                }
394        },
395        _styleMsgNode: function(top, width, height){
396                var messagesNode = this.grid.messagesNode;
397                html.style(messagesNode, {"position": "absolute", "top": top + "px", "width": width + "px", "height": height + "px", "z-Index": "100"});
398        },
399        _updateDescription: function(){
400                // summary:
401                //              Update size information.
402                var s = this.plugin.forcePageStoreLayer,
403                        maxSize = this.plugin._maxSize,
404                        nls = this.plugin._nls,
405                        getItemTitle = function(){
406                                return maxSize <= 0 || maxSize == 1 ? nls[5] : nls[4];
407                        };
408                if(this.description && this.descriptionDiv){
409                        this.descriptionDiv.innerHTML = maxSize > 0 ? string.substitute(nls[0], [getItemTitle(), maxSize, s.startIdx + 1, s.endIdx + 1]) : "0 " + getItemTitle();
410                }
411        },
412        _updateSizeSwitch: function(){
413                // summary:
414                //              Update "items per page" information.
415                html.style(this.sizeSwitchTd, "display", this.sizeSwitch ? "" : "none");
416                if(!this.sizeSwitch){
417                        return;
418                }
419                if(this.sizeSwitchTd.childNodes.length < 1){
420                        this._createSizeSwitchNodes();
421                }
422                this._updateSwitchNodesStyle();
423        },
424        _createSizeSwitchNodes: function(){
425                // summary:
426                //              The function to create the size switch nodes
427                var node = null,
428                        nls = this.plugin._nls,
429                        connect = lang.hitch(this.plugin, 'connect');
430                array.forEach(this.pageSizes, function(size){
431                        // create page size switch node
432                        var labelValue = isFinite(size) ? string.substitute(nls[2], [size]) : nls[1],
433                                value = isFinite(size) ? size : nls[16];
434                        node = html.create("span", {innerHTML: value, title: labelValue, value: size, tabindex: "-1"}, this.sizeSwitchTd, "last");
435                        // for accessibility
436                        node.setAttribute("aria-label", labelValue);
437                        // connect event
438                        connect(node, "onclick", lang.hitch(this, "_onSwitchPageSize"));
439                        connect(node, "onkeydown", lang.hitch(this, "_onSwitchPageSize"));
440                        connect(node, "onmouseover", function(e){
441                                html.addClass(e.target, "dojoxGridPageTextHover");
442                        });
443                        connect(node, "onmouseout", function(e){
444                                html.removeClass(e.target, "dojoxGridPageTextHover");
445                        });
446                        // create a separation node
447                        node = html.create("span", {innerHTML: "|"}, this.sizeSwitchTd, "last");
448                        html.addClass(node, "dojoxGridSeparator");
449                }, this);
450                // delete last separation node
451                html.destroy(node);
452        },
453        _updateSwitchNodesStyle: function(){
454                // summary:
455                //              Update the switch nodes style
456                var size = null;
457                var styleNode = function(node, status){
458                        if(status){
459                                html.addClass(node, "dojoxGridActivedSwitch");
460                                html.removeAttr(node, "tabindex");
461                        }else{
462                                html.addClass(node, "dojoxGridInactiveSwitch");
463                                node.setAttribute("tabindex", "-1");
464                        }
465                };
466                array.forEach(this.sizeSwitchTd.childNodes, function(node){
467                        if(node.value){
468                                html.removeClass(node);
469                                size = node.value;
470                                if(this.plugin._showAll){
471                                        styleNode(node, isNaN(parseInt(size, 10)));
472                                }else{
473                                        styleNode(node, this.plugin._currentPageSize == size);
474                                }
475                        }
476                }, this);
477        },
478        _updatePageStepper: function(){
479                // summary:
480                //              Update the page step nodes
481                html.style(this.pageStepperTd, "display", this.pageStepper ? "" : "none");
482                if(!this.pageStepper){
483                        return;
484                }
485                if(this.pageStepperDiv.childNodes.length < 1){
486                        this._createPageStepNodes();
487                        this._createWardBtns();
488                }else{
489                        this._resetPageStepNodes();
490                }
491                this._updatePageStepNodesStyle();
492        },
493        _createPageStepNodes: function(){
494                // summary:
495                //              Create the page step nodes if they do not exist
496                var startPage = this._getStartPage(),
497                        stepSize = this._getStepPageSize(),
498                        label = "", node = null, i = startPage,
499                        connect = lang.hitch(this.plugin, 'connect');
500                for(; i < startPage + this.maxPageStep + 1; i++){
501                        label = string.substitute(this.plugin._nls[3], [i]);
502                        node = html.create("div", {innerHTML: i, value: i, title: label}, this.pageStepperDiv, "last");
503                        node.setAttribute("aria-label", label);
504                        // connect event
505                        connect(node, "onclick", lang.hitch(this, "_onPageStep"));
506                        connect(node, "onkeydown", lang.hitch(this, "_onPageStep"));
507                        connect(node, "onmouseover", function(e){
508                                html.addClass(e.target, "dojoxGridPageTextHover");
509                        });
510                        connect(node, "onmouseout", function(e){
511                                html.removeClass(e.target, "dojoxGridPageTextHover");
512                        });
513                        html.style(node, "display", i < startPage + stepSize ? "" : "none");
514                }
515        },
516        _createWardBtns: function(){
517                // summary:
518                //              Create the previous/next/first/last button
519                var _this = this, nls = this.plugin._nls;
520                var highContrastLabel = {prevPage: "&#60;", firstPage: "&#171;", nextPage: "&#62;", lastPage: "&#187;"};
521                var createWardBtn = function(value, label, position){
522                        var node = html.create("div", {value: value, title: label, tabindex: "-2"}, _this.pageStepperDiv, position);
523                        _this.plugin.connect(node, "onclick", lang.hitch(_this, "_onPageStep"));
524                        _this.plugin.connect(node, "onkeydown", lang.hitch(_this, "_onPageStep"));
525                        node.setAttribute("aria-label", label);
526                        // for high contrast
527                        var highConrastNode = html.create("span", {value: value, title: label, innerHTML: highContrastLabel[value]}, node, position);
528                        html.addClass(highConrastNode, "dojoxGridWardButtonInner");
529                };
530                createWardBtn("prevPage", nls[6], "first");
531                createWardBtn("firstPage", nls[7], "first");
532                createWardBtn("nextPage", nls[8], "last");
533                createWardBtn("lastPage", nls[9], "last");
534        },
535        _resetPageStepNodes: function(){
536                // summary:
537                //              The page step nodes might be changed when fetch data, we need to
538                //              update/reset them
539                var startPage = this._getStartPage(),
540                        stepSize = this._getStepPageSize(),
541                        stepNodes = this.pageStepperDiv.childNodes,
542                        node = null, i = startPage, j = 2, tip;
543                for(; j < stepNodes.length - 2; j++, i++){
544                        node = stepNodes[j];
545                        if(i < startPage + stepSize){
546                                tip = string.substitute(this.plugin._nls[3], [i]);
547                                html.attr(node, {
548                                        "innerHTML": i,
549                                        "title": tip,
550                                        "value": i
551                                });
552                                html.style(node, "display", "");
553                                node.setAttribute("aria-label", tip);
554                        }else{
555                                html.style(node, "display", "none");
556                        }
557                }
558        },
559        _updatePageStepNodesStyle: function(){
560                // summary:
561                //              Update the style of the page step nodes
562                var value = null,
563                        curPage = this.plugin.currentPage(),
564                        pageCount = this.plugin.getTotalPageNum();
565                var updateClass = function(node, isWardBtn, status){
566                        var value = node.value,
567                                enableClass = isWardBtn ? "dojoxGrid" + value + "Btn" : "dojoxGridInactived",
568                                disableClass = isWardBtn ? "dojoxGrid" + value + "BtnDisable" : "dojoxGridActived";
569                        if(status){
570                                html.addClass(node, disableClass);
571                                html.removeAttr(node, "tabindex");
572                        }else{
573                                html.addClass(node, enableClass);
574                                node.setAttribute("tabindex", "-2");
575                        }
576                };
577                array.forEach(this.pageStepperDiv.childNodes, function(node){
578                        html.removeClass(node);
579                        if(isNaN(parseInt(node.value, 10))){
580                                html.addClass(node, "dojoxGridWardButton");
581                                var disablePageNum = node.value == "prevPage" || node.value == "firstPage" ? 1 : pageCount;
582                                updateClass(node, true, (curPage === disablePageNum));
583                        }else{
584                                value = parseInt(node.value, 10);
585                                updateClass(node, false, (value === curPage || html.style(node, "display") === "none"));
586                        }
587                }, this);
588        },
589        _showGotoButton: function(flag){
590                this.gotoButton = flag;
591                this._updateGotoButton();
592        },
593        _updateGotoButton: function(){
594                // summary:
595                //              Create/destroy the goto page button
596                if(!this.gotoButton){
597                        if(this._gotoPageDialog){
598                                this._gotoPageDialog.destroy();
599                        }
600                        html.removeAttr(this.gotoPageDiv, "tabindex");
601                        html.style(this.gotoPageTd, 'display', 'none');
602                        return;
603                }
604                if(html.style(this.gotoPageTd, 'display') == 'none'){
605                        html.style(this.gotoPageTd, 'display', '');
606                }
607                this.gotoPageDiv.setAttribute('title', this.plugin._nls[10]);
608                html.toggleClass(this.gotoPageDiv, "dojoxGridPaginatorGotoDivDisabled", this.plugin.getTotalPageNum() <= 1);
609                if(this.plugin.getTotalPageNum() <= 1){
610                        html.removeAttr(this.gotoPageDiv, "tabindex");
611                }else{
612                        this.gotoPageDiv.setAttribute("tabindex", "-3");
613                }
614        },
615        _openGotopageDialog: function(e){
616                // summary:
617                //              Show the goto page dialog
618                if(this.plugin.getTotalPageNum() <= 1){
619                        return;
620                }
621                if(e.type === "keydown" && e.keyCode !== keys.ENTER && e.keyCode !== keys.SPACE){
622                        return;
623                }
624                if(!this._gotoPageDialog){
625                        this._gotoPageDialog = new _GotoPageDialog(this.plugin);
626                }
627                this._gotoPageDialog.showDialog();
628                this.onShowGotoPageDialog(e);
629        },
630        _onSwitchPageSize: function(/*Event*/e){
631                // summary:
632                //              The handler of switch the page size
633                if(e.type === "keydown" && e.keyCode !== keys.ENTER && e.keyCode !== keys.SPACE){
634                        return;
635                }
636                this.onSwitchPageSize(e);
637                this.plugin.currentPageSize(e.target.value);
638        },
639        _onPageStep: function(/*Event*/e){
640                // summary:
641                //              The handler jump page event
642                if(e.type === "keydown" && e.keyCode !== keys.ENTER && e.keyCode !== keys.SPACE){
643                        return;
644                }
645                var p = this.plugin,
646                        value = e.target.value;
647                this.onPageStep(e);
648                if(!isNaN(parseInt(value, 10))){
649                        p.currentPage(parseInt(value, 10));
650                }else{
651                        p[value]();
652                }
653        },
654        _getStartPage: function(){
655                var cp = this.plugin.currentPage(),
656                        ms = this.maxPageStep,
657                        hs = parseInt(ms / 2, 10),
658                        tp = this.plugin.getTotalPageNum();
659                if(cp < hs || (cp - hs) < 1 || tp <= ms){
660                        return 1;
661                }else{
662                        return tp - cp < hs && cp - ms >= 0 ? tp - ms + 1 : cp - hs;
663                }
664        },
665        _getStepPageSize: function(){
666                var sp = this._getStartPage(),
667                        tp = this.plugin.getTotalPageNum(),
668                        ms = this.maxPageStep;
669                return sp + ms > tp ? tp - sp + 1 : ms;
670        }
671});
672
673var Pagination = declare("dojox.grid.enhanced.plugins.Pagination", _Plugin, {
674        // summary:
675        //              The typical pagination way to deal with huge dataset
676        //              an alternative for the default virtual scrolling manner.
677        name: "pagination",
678
679        // defaultPageSize: Integer
680        //              Number of rows in a page, 25 by default.
681        defaultPageSize: 25,
682
683        // defaultPage: Integer
684        //              Which page will be displayed initially, 1st page by default.
685        defaultPage: 1,
686
687        // description: boolean
688        //              Whether the description information will be displayed, true by default.
689        description: true,
690
691        // sizeSwitch: boolean
692        //              Whether the page size switch options will be displayed, true by default.
693        sizeSwitch: true,
694
695        // pageStepper: boolean
696        //              Whether the page switch options will be displayed, true by default.
697        pageStepper: true,
698
699        // gotoButton: boolean
700        //              Whether the goto page button will be displayed, false by default.
701        gotoButton: false,
702
703        // pageSizes: Array
704        //              Array of page sizes for switching, e.g. [10, 25, 50, 100, Infinity] by default,
705        //              Infinity or any NaN value will be treated as "all".
706        pageSizes: [10, 25, 50, 100, Infinity],
707
708        // maxPageStep: Integer
709        //              The max number of page sizes to be displayed, 7 by default.
710        maxPageStep: 7,
711
712        // position: string
713        //              The position of the pagination bar - "top"|"bottom", "bottom" by default.
714        position: 'bottom',
715       
716        init: function(){
717                var g = this.grid;
718                g.usingPagination = true;
719                this._initOptions();
720                this._currentPage = this.defaultPage;
721                this._currentPageSize = this.grid.rowsPerPage = this.defaultPageSize;
722                // wrap store layer
723                this._store = g.store;
724                this.forcePageStoreLayer = new _ForcedPageStoreLayer(this);
725                layers.wrap(g, "_storeLayerFetch", this.forcePageStoreLayer);
726                // create pagination bar
727                this._paginator = this.option.position != "top" ?
728                        new _Paginator(lang.mixin(this.option, {position: "bottom", plugin: this})) :
729                        new _Paginator(lang.mixin(this.option, {position: "top", plugin: this}));
730                this._regApis();
731        },
732        destroy: function(){
733                this.inherited(arguments);
734                this._paginator.destroy();
735                var g = this.grid;
736                g.unwrap(this.forcePageStoreLayer.name());
737                g.scrollToRow = this._gridOriginalfuncs[0];
738                g._onNew = this._gridOriginalfuncs[1];
739                g.removeSelectedRows = this._gridOriginalfuncs[2];
740                this._paginator = null;
741                this._nls = null;
742        },
743        currentPage: function(page){
744                // summary:
745                //              Shift to the given page, return current page number. If there
746                //              is no valid page was passed in, just return current page num.
747                // page: Integer
748                //              The page to go to, starting at 1.
749                // returns:
750                //              Current page number
751                if(page <= this.getTotalPageNum() && page > 0 && this._currentPage !== page){
752                        this._currentPage = page;
753                        this.grid._refresh(true);
754                        this.grid.resize();
755                }
756                return this._currentPage;
757        },
758        nextPage: function(){
759                // summary:
760                //              Go to the next page.
761                this.currentPage(this._currentPage + 1);
762        },
763        prevPage: function(){
764                // summary:
765                //              Go to the previous page.
766                this.currentPage(this._currentPage - 1);
767        },
768        firstPage: function(){
769                // summary:
770                //              Go to the first page
771                this.currentPage(1);
772        },
773        lastPage: function(){
774                // summary:
775                //              Go to the last page
776                this.currentPage(this.getTotalPageNum());
777        },
778        currentPageSize: function(size){
779                // summary:
780                //              Change the size of current page or return the current page size.
781                // size: Integer|null
782                //              An integer identifying the number of rows per page. If the size
783                //              is an Infinity, all rows will be displayed; if an invalid value passed
784                //              in, the current page size will be returned.
785                // returns:
786                //              Current size of items per page. 
787                if(!isNaN(size)){
788                        var g = this.grid,
789                                startIndex = this._currentPageSize * (this._currentPage - 1), endIndex;
790                        this._showAll = !isFinite(size);
791                        this.grid.usingPagination = !this._showAll;
792                        this._currentPageSize = this._showAll ? this._maxSize : size;
793                        g.rowsPerPage = this._showAll ? this._defaultRowsPerPage : size;
794                        endIndex = startIndex + Math.min(this._currentPageSize, this._maxSize);
795                        if(endIndex > this._maxSize){
796                                this.lastPage();
797                        }else{
798                                var cp = Math.ceil(startIndex / this._currentPageSize) + 1;
799                                if(cp !== this._currentPage){
800                                        this.currentPage(cp);
801                                }else{
802                                        this.grid._refresh(true);
803                                }
804                        }
805                        this.grid.resize();
806                }
807                return this._currentPageSize;
808        },
809        getTotalPageNum: function(){
810                // summary:
811                //              Get total page number
812                return Math.ceil(this._maxSize / this._currentPageSize);
813        },
814        getTotalRowCount: function(){
815                // summary:
816                //              Function for get total row count
817                return this._maxSize;
818        },
819        scrollToRow: function(inRowIndex){
820                // summary:
821                //              Override the grid.scrollToRow(), could jump to the right page
822                //              and scroll to the specific row
823                // inRowIndex: integer
824                //              The row index
825                var page = parseInt(inRowIndex / this._currentPageSize, 10) + 1;
826                if(page > this.getTotalPageNum()){
827                        return;
828                }
829                this.currentPage(page);
830                var rowIdx = inRowIndex % this._currentPageSize;
831                return this._gridOriginalfuncs[0](rowIdx);
832        },
833        removeSelectedRows: function(){
834                this._multiRemoving = true;
835                this._gridOriginalfuncs[2].apply();
836                this._multiRemoving = false;
837                if(this.grid.store.save){
838                        this.grid.store.save();
839                }
840                this.grid.resize();
841                this.grid._refresh();
842        },
843        showGotoPageButton: function(flag){
844                // summary:
845                //              For show/hide the go to page button dynamically
846                // flag: boolean
847                //              Show the go to page button when flag is true, otherwise hide it
848                this._paginator.gotoButton = flag;
849                this._paginator._updateGotoButton();
850        },
851        // [DEPRECATED] ============
852        gotoPage: function(page){
853                kernel.deprecated("dojox.grid.enhanced.EnhancedGrid.gotoPage(page)", "use dojox.grid.enhanced.EnhancedGrid.currentPage(page) instead", "1.8");
854                this.currentPage(page);
855        },
856        gotoFirstPage: function(){
857                kernel.deprecated("dojox.grid.enhanced.EnhancedGrid.gotoFirstPage()", "use dojox.grid.enhanced.EnhancedGrid.firstPage() instead", "1.8");
858                this.firstPage();
859        },
860        gotoLastPage: function(){
861                kernel.deprecated("dojox.grid.enhanced.EnhancedGrid.gotoLastPage()", "use dojox.grid.enhanced.EnhancedGrid.lastPage() instead", "1.8");
862                this.lastPage();
863        },
864        changePageSize: function(size){
865                kernel.deprecated("dojox.grid.enhanced.EnhancedGrid.changePageSize(size)", "use dojox.grid.enhanced.EnhancedGrid.currentPageSize(size) instead", "1.8");
866                this.currentPageSize(size);
867        },
868        // =============== Protected ================
869        _nls: null,
870        _showAll: false,
871        _maxSize: 0,
872        // =============== Private ===============
873        _defaultRowsPerPage: 25,
874        _currentPage: 1,
875        _currentPageSize: 25,
876       
877        _initOptions: function(){
878                this._defaultRowsPerPage = this.grid.rowsPerPage || 25;
879                this.defaultPage = this.option.defaultPage >= 1 ? parseInt(this.option.defaultPage, 10) : 1;
880                this.option.description = this.option.description !== undefined ? !!this.option.description : this.description;
881                this.option.sizeSwitch = this.option.sizeSwitch !== undefined ? !!this.option.sizeSwitch : this.sizeSwitch;
882                this.option.pageStepper = this.option.pageStepper !== undefined ? !!this.option.pageStepper : this.pageStepper;
883                this.option.gotoButton = this.option.gotoButton !== undefined ? !!this.option.gotoButton : this.gotoButton;
884                if(lang.isArray(this.option.pageSizes)){
885                        var pageSizes = [];
886                        array.forEach(this.option.pageSizes, function(size){
887                                size = typeof size == 'number' ? size : parseInt(size, 10);
888                                if(!isNaN(size) && size > 0){
889                                        pageSizes.push(size);
890                                }else if(array.indexOf(pageSizes, Infinity) < 0){
891                                        pageSizes.push(Infinity);
892                                }
893                        }, this);
894                        this.option.pageSizes = pageSizes.sort(function(a, b){return a - b;});
895                }else{
896                        this.option.pageSizes = this.pageSizes;
897                }
898                this.defaultPageSize = this.option.defaultPageSize >= 1 ? parseInt(this.option.defaultPageSize, 10) : this.pageSizes[0];
899                this.option.maxPageStep = this.option.maxPageStep > 0 ? this.option.maxPageStep : this.maxPageStep;
900                this.option.position = lang.isString(this.option.position) ? this.option.position.toLowerCase() : this.position;
901                this._nls = [
902                        nls.descTemplate,
903                        nls.allItemsLabelTemplate,
904                        nls.pageSizeLabelTemplate,
905                        nls.pageStepLabelTemplate,
906                        nls.itemTitle,
907                        nls.singularItemTitle,
908                        nls.prevTip,
909                        nls.firstTip,
910                        nls.nextTip,
911                        nls.lastTip,
912                        nls.gotoButtonTitle,
913                        nls.dialogTitle,
914                        nls.dialogIndication,
915                        nls.pageCountIndication,
916                        nls.dialogConfirm,
917                        nls.dialogCancel,
918                        nls.all
919                ];
920        },
921        _regApis: function(){
922                var g = this.grid;
923                // New added APIs
924                g.currentPage = lang.hitch(this, this.currentPage);
925                g.nextPage = lang.hitch(this, this.nextPage);
926                g.prevPage = lang.hitch(this, this.prevPage);
927                g.firstPage = lang.hitch(this, this.firstPage);
928                g.lastPage = lang.hitch(this, this.lastPage);
929                g.currentPageSize = lang.hitch(this, this.currentPageSize);
930                g.showGotoPageButton = lang.hitch(this, this.showGotoPageButton);
931                g.getTotalRowCount = lang.hitch(this, this.getTotalRowCount);
932                g.getTotalPageNum = lang.hitch(this, this.getTotalPageNum);
933               
934                g.gotoPage = lang.hitch(this, this.gotoPage);
935                g.gotoFirstPage = lang.hitch(this, this.gotoFirstPage);
936                g.gotoLastPage = lang.hitch(this, this.gotoLastPage);
937                g.changePageSize = lang.hitch(this, this.changePageSize);
938                // Changed APIs
939                this._gridOriginalfuncs = [
940                        lang.hitch(g, g.scrollToRow),
941                        lang.hitch(g, g._onNew),               
942                        lang.hitch(g, g.removeSelectedRows)
943                ];
944                g.scrollToRow = lang.hitch(this, this.scrollToRow);
945                g.removeSelectedRows = lang.hitch(this, this.removeSelectedRows);
946                g._onNew = lang.hitch(this, this._onNew);
947                this.connect(g, "_onDelete", lang.hitch(this, this._onDelete));
948        },
949        _onNew: function(item, parentInfo){
950                var totalPages = this.getTotalPageNum();
951                if(((this._currentPage === totalPages || totalPages === 0) && this.grid.get('rowCount') < this._currentPageSize) || this._showAll){
952                        lang.hitch(this.grid, this._gridOriginalfuncs[1])(item, parentInfo);
953                        this.forcePageStoreLayer.endIdx++;
954                }
955                this._maxSize++;
956                if(this._showAll){
957                        this._currentPageSize++;
958                }
959                if(this._showAll && this.grid.autoHeight){
960                        this.grid._refresh();
961                }else{
962                        this._paginator._update();
963                }
964        },
965        _onDelete: function(){
966                if(!this._multiRemoving){
967                        this.grid.resize();
968                        if(this._showAll){
969                                this.grid._refresh();
970                        }
971                }
972                if(this.grid.get('rowCount') === 0){
973                        this.prevPage();
974                }
975        }
976});
977
978EnhancedGrid.registerPlugin(Pagination/*name:'pagination'*/);
979
980return Pagination;
981
982});
Note: See TracBrowser for help on using the repository browser.