source: Dev/trunk/src/client/dojox/widget/Pager.js @ 529

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

Added Dojo 1.9.3 release.

File size: 16.5 KB
Line 
1define(["dojo/aspect", "dojo/_base/array", "dojo/_base/declare", "dojo/dom", "dojo/dom-attr", "dojo/dom-class", "dojo/dom-construct", "dojo/dom-geometry", "dojo/dom-style", "dojo/fx", "dojo/_base/kernel", "dojo/keys",
2        "dojo/_base/lang", "dojo/on", "dijit/_WidgetBase", "dijit/_TemplatedMixin", "./PagerItem", "dojo/text!./Pager/Pager.html"],
3        function(aspect, array, declare, dom, attr, domClass, domConstruct, geometry, style, fx, kernel, keys, lang, on, _WidgetBase, _TemplatedMixin, PagerItem, template){
4
5kernel.experimental("dojox.widget.Pager");
6
7return declare("dojox.widget.Pager",
8        [_WidgetBase, _TemplatedMixin],
9        {
10        // summary:
11        //              A Pager, displaying a list of sized nodes
12
13
14        templateString: template,
15
16
17        // iconPrevious: String?
18        //              The url of the previous page icon
19        iconPrevious: "",
20
21        // iconNext: String?
22        //              The url of the next page icon
23        iconNext: "",
24
25        iconPage: require.toUrl("dojox/widget/Pager/images/pageInactive.png"),
26        iconPageActive: require.toUrl("dojox/widget/Pager/images/pageActive.png"),
27
28        // store: Object
29        //              A dojo.data Data store
30        store: null, // data store for items
31
32        // orientation: String
33        //              Either "horizontal or "vertical" to define the direction the pages will slide
34        orientation: "horizontal", // or vertical
35
36        // statusPos: String
37        //              A string describing where to put the Pager "current page" indicator. Options are
38        //              "leading" or "trailing". In the case of horiztonal orientation, "leading" indicates
39        //              positioned above the PageItems. In the case of vertical, "leading" indicates "before".
40        statusPos: "leading",
41
42        // pagerPos: String
43        //              TODOC
44        pagerPos: "center",
45
46        // duration: Integer
47        //              Time in milliseconds to transition the pages
48        duration: 500,
49
50        // itemSpace: Integer
51        //              Spacing between items? TODOC
52        itemSpace: 2,
53
54        // resizeChildren: Boolean
55        //              TODOC
56        resizeChildren: true,
57
58        // itemClass: String|Widget
59        //              The full dotted named of a Class or Widget constructor to use for the internal Pager Items.
60        itemClass: PagerItem,
61
62        // itemsPage: Integer
63        //              The numbers of items to display in each "Page"
64        itemsPage: 3,
65
66        postMixInProperties: function(){
67                var h = (this.orientation == "horizontal");
68                lang.mixin(this,{
69                        _totalPages:0,
70                        _currentPage:1,
71                        dirClass: "pager" + (h ? "Horizontal" : "Vertical"),
72                        iconNext: require.toUrl("dojox/widget/Pager/images/" + (h ? "h" : "v") + "Next.png"),
73                        iconPrevious: require.toUrl("dojox/widget/Pager/images/" + (h ? "h" : "v") + "Previous.png")
74                });
75        },
76
77        postCreate: function(){
78                this.inherited(arguments);
79                this.store.fetch({
80                        onComplete: lang.hitch(this, "_init")
81                });
82
83        },
84
85        _a11yStyle: function(e){
86                // summary:
87                //              top level onfocus/onblur listen to set a class "pagerFocus" on some node
88                //              and remove it onblur
89                domClass.toggle(e.target, "pagerFocus", (e.type == "focus"));
90        },
91
92        _handleKey: function(e){
93                // summary:
94                //              Handle keyboard navigation internally
95
96                var key = (e.charCode == keys.SPACE ? keys.SPACE : e.keyCode);
97                switch(key){
98
99                        case keys.UP_ARROW:
100                        case keys.RIGHT_ARROW:
101                        case 110:
102                        case 78: // key "n"
103                                e.preventDefault();
104                                this._pagerNext();
105                                break;
106
107                        case keys.DOWN_ARROW:
108                        case keys.LEFT_ARROW:
109                        case 112:
110                        case 80: // key "p"
111                                e.preventDefault();
112                                this._pagerPrevious();
113                                break;
114
115                        case keys.ENTER:
116                                switch(e.target){
117                                        case this.pagerNext : this._pagerNext(); break;
118                                        case this.pagerPrevious : this._pagerPrevious(); break;
119                                }
120                                break;
121                }
122        },
123
124        _init: function(items) {
125                this.items = items;
126                this._renderPages();
127                this._renderStatus();
128                this._renderPager();
129        },
130
131        generatePagerItem: function(/*item */ item, /* Number */ cnt){
132                // summary:
133                //              this method instantiates pagerItems to be used by the pager, it is overridable to allow
134                //              customizing these items
135
136                // only use getObject if its not the default _PagerItem value
137                var itemClass = this.itemClass,
138                        pagerItem = (typeof itemClass == "string" ? lang.getObject(itemClass) : itemClass);
139
140                var contentContainer = domConstruct.create('div', {
141                                innerHTML: item.content
142                        });
143
144                return new pagerItem({
145                          id: this.id + '-item-' + (cnt + 1)
146                  }, contentContainer);
147        },
148
149        _renderPages: function(){
150                var pcv = this.pagerContainerView,
151                        _h = (this.orientation == "horizontal");
152
153                if(_h){
154                        var pagerH = geometry.getMarginBox(this.pagerContainerPager).h,
155                                statusH = geometry.getMarginBox(this.pagerContainerStatus).h;
156
157                        if (this.pagerPos != 'center'){
158                                var addonHeight = pagerH+statusH;
159                        }else{
160                                var addonHeight = statusH;
161
162                                var     widthSub = this.pagerIconNext.width,
163                                        containerWidth = style.get(pcv, 'width'),
164                                        newWidth = containerWidth-(2*widthSub);
165
166                                style.set(pcv, {
167                                        width: newWidth+'px',
168                                        marginLeft: this.pagerIconNext.width+'px',
169                                        marginRight: this.pagerIconNext.width+'px'
170                                });
171                        }
172                        var totalH = style.get(this.pagerContainer, 'height') - addonHeight;
173                        style.set(this.pagerContainerView, 'height', totalH+'px');
174
175                        var itemSpace = Math.floor(style.get(pcv, 'width') / this.itemsPage);
176                        if(this.statusPos == 'trailing'){
177                                if(this.pagerPos != 'center'){
178                                        style.set(pcv, 'marginTop', pagerH+'px');
179                                }
180                                style.set(pcv, 'marginBottom', statusH+'px');
181                        }else{
182                                style.set(pcv, 'marginTop', statusH+'px');
183                                if (this.pagerPos != 'center'){
184                                        style.set(pcv, 'marginTop', pagerH+'px');
185                                }
186                        }
187                }else{
188                        var pagerW = geometry.getMarginBox(this.pagerContainerPager).w,
189                                statusW = geometry.getMarginBox(this.pagerContainerStatus).w,
190                                containerW = style.get(this.pagerContainer, 'width');
191
192                        if(this.pagerPos != 'center'){
193                                var addonWidth = pagerW + statusW;
194                        }else{
195                                var addonWidth = statusW,
196                                        heightSub = this.pagerIconNext.height,
197                                        containerHeight = style.get(pcv, 'height'),
198                                        newHeight = containerHeight - (2 * heightSub);
199
200                                style.set(pcv,{
201                                        height: newHeight+'px',
202                                        marginTop: this.pagerIconNext.height+'px',
203                                        marginBottom: this.pagerIconNext.height+'px'
204                                });
205                        }
206                        var totalW = style.get(this.pagerContainer, 'width') - addonWidth;
207                        style.set(pcv, 'width', totalW+'px');
208
209                        var itemSpace = Math.floor(style.get(pcv, 'height') / this.itemsPage);
210                        if(this.statusPos == 'trailing'){
211                                if (this.pagerPos != 'center'){
212                                        style.set(pcv, 'marginLeft', pagerW + 'px');
213                                }
214                                style.set(pcv, 'marginRight', statusW + 'px');
215                        }else{
216                                style.set(pcv, 'marginLeft', statusW + 'px');
217                                if(this.pagerPos != 'center'){
218                                        style.set(pcv, 'marginRight', pagerW+'px');
219                                }
220                        }
221                }
222                var paddingLead = "padding" + (_h ? "Left" : "Top"),
223                        paddingTrail = "padding" + (_h ? "Right" : "Bottom");
224
225                array.forEach(this.items, function(item, cnt){
226                        var pagerItem = this.generatePagerItem(item, cnt),
227                                containerProps = {};
228
229                        this.pagerItems.appendChild(pagerItem.domNode);
230
231                        containerProps[(_h ? "width" : "height")] = (itemSpace - this.itemSpace) + "px";
232                        var p = (_h ? "height" : "width");
233                        containerProps[p] = style.get(pcv, p) + "px";
234                        style.set(pagerItem.containerNode, containerProps);
235
236                        if(this.resizeChildren){
237                                pagerItem.resizeChildren();
238                        }
239                        pagerItem.parseChildren();
240
241                        // only display amount of items as defined in itemsPage
242                        style.set(pagerItem.domNode, "position", "absolute");
243
244                        if (cnt < this.itemsPage){
245                                var pos = (cnt) * itemSpace,
246                                        trailingDir = (_h ? "left" : "top"),
247                                        dir = (_h ? "top" : "left");
248
249                                style.set(pagerItem.domNode, dir, "0px");
250                                style.set(pagerItem.domNode, trailingDir, pos+"px");
251                        }else{
252                                style.set(pagerItem.domNode, "top", "-1000px");
253                                style.set(pagerItem.domNode, "left", "-1000px");
254                        }
255
256                        style.set(pagerItem.domNode, paddingTrail, (this.itemSpace/2)+"px");
257                        style.set(pagerItem.domNode, paddingLead, (this.itemSpace/2)+"px");
258
259                }, this);
260        },
261
262        _renderPager: function() {
263                var tcp = this.pagerContainerPager,
264                        zero = "0px",
265                        _h = (this.orientation == "horizontal");
266
267                if(_h){
268
269                        if(this.statusPos == 'center'){
270
271                        }else if (this.statusPos == 'trailing'){
272                                style.set(tcp, 'top', zero);
273                        }else{
274                                style.set(tcp, 'bottom', zero);
275                        }
276                        style.set(this.pagerNext, 'right', zero);
277                        style.set(this.pagerPrevious, 'left', zero);
278
279                }else{
280
281                        if (this.statusPos == 'trailing'){
282                                style.set(tcp, 'left', zero);
283                        }else{
284                                style.set(tcp, 'right', zero);
285                        }
286                        style.set(this.pagerNext, 'bottom', zero);
287                        style.set(this.pagerPrevious, 'top', zero);
288                }
289
290        },
291
292        _renderStatus: function() {
293                this._totalPages = Math.ceil(this.items.length / this.itemsPage);
294                // FIXME!!
295                this.iconWidth = 0;
296                this.iconHeight = 0;
297                this.iconsLoaded = 0;
298                this._iconConnects = [];
299
300                for (var i = 1; i <= this._totalPages; i++){
301                        var icon = new Image();
302
303                        var pointer = i;
304                        on(icon, 'click', lang.hitch(this, "_pagerSkip", pointer));
305
306                        this._iconConnects[pointer] = on(icon, 'load', lang.hitch(this, function(pointer){
307                                this.iconWidth += icon.width;
308                                this.iconHeight += icon.height;
309                                this.iconsLoaded++;
310
311                                if (this._totalPages == this.iconsLoaded){
312                                        if (this.orientation == "horizontal"){
313                                                if (this.statusPos == 'trailing'){
314                                                        if (this.pagerPos == 'center'){
315                                                                var containerHeight = style.get(this.pagerContainer, 'height'),
316                                                                        statusHeight = style.get(this.pagerContainerStatus, 'height');
317
318                                                                style.set(this.pagerContainerPager, 'top', ((containerHeight/2)-(statusHeight/2))+'px');
319                                                        }
320                                                        style.set(this.pagerContainerStatus, 'bottom', '0px');
321                                                }else{
322                                                        if (this.pagerPos == 'center'){
323                                                                var containerHeight = style.get(this.pagerContainer, 'height'),
324                                                                        statusHeight = style.get(this.pagerContainerStatus, 'height');
325
326                                                                style.set(this.pagerContainerPager, 'bottom', ((containerHeight/2)-(statusHeight/2))+'px');
327                                                        }
328                                                        style.set(this.pagerContainerStatus, 'top', '0px');
329                                                }
330
331                                                var position = (style.get(this.pagerContainer, 'width')/2)-(this.iconWidth/2);
332                                                style.set(this.pagerContainerStatus, 'paddingLeft', position+'px');
333                                        }else{
334                                                if (this.statusPos == 'trailing'){
335                                                        if (this.pagerPos == 'center'){
336                                                                var containerWidth = style.get(this.pagerContainer, 'width'),
337                                                                        statusWidth = style.get(this.pagerContainerStatus, 'width');
338
339                                                                style.set(this.pagerContainerPager, 'left', ((containerWidth/2)-(statusWidth/2))+'px');
340                                                        }
341                                                        style.set(this.pagerContainerStatus, 'right', '0px');
342                                                }else{
343                                                        if (this.pagerPos == 'center'){
344                                                                var containerWidth = style.get(this.pagerContainer, 'width'),
345                                                                        statusWidth = style.get(this.pagerContainerStatus, 'width');
346
347                                                                style.set(this.pagerContainerPager, 'right', ((containerWidth/2)-(statusWidth/2))+'px');
348                                                        }
349                                                        style.set(this.pagerContainerStatus, 'left', '0px');
350                                                }
351                                                var position = (style.get(this.pagerContainer, 'height')/2)-(this.iconHeight/2);
352                                                style.set(this.pagerContainerStatus, 'paddingTop', position+'px');
353                                        }
354                                }
355                                this._iconConnects[pointer].remove();
356                        }, pointer));
357
358                        if (i==this._currentPage){
359                                icon.src=this.iconPageActive;
360                        }else{
361                                icon.src=this.iconPage;
362                        }
363                        var pointer = i;
364
365                        domClass.add(icon, this.orientation+'PagerIcon');
366                        attr.set(icon, 'id', this.id+'-status-'+i);
367                        this.pagerContainerStatus.appendChild(icon);
368
369                        if (this.orientation == "vertical"){
370                                style.set(icon, 'display', 'block');
371                        }
372                }
373        },
374
375        _pagerSkip: function(page){
376                if (this._currentPage == page){
377                        return;
378                }else{
379                        // calculate whether to go left or right, take shortest way
380                        var distanceP; var distanceN;
381                        if (page < this._currentPage){
382                                distanceP = this._currentPage - page;
383                                distanceN = (this._totalPages + page) - this._currentPage;
384                        }else{
385                                distanceP = (this._totalPages + this._currentPage) - page;
386                                distanceN = page - this._currentPage;
387                        }
388
389                        var b = (distanceN > distanceP);
390                        this._toScroll = (b ? distanceP : distanceN);
391                        var cmd = (b ? "_pagerPrevious" : "_pagerNext"),
392                                handle = aspect.after(this, "onScrollEnd", lang.hitch(this, function(){
393                                        this._toScroll--;
394                                        if(this._toScroll < 1){
395                                                handle.remove();
396                                        }else{
397                                                this[cmd]();
398                                        }
399                                }), true);
400
401                        this[cmd]();
402                }
403        },
404
405        _pagerNext: function(){
406                if(this._anim) return;
407
408                /**
409                 * fade slide out current items
410                 * make sure that next items are ligned up nicely before sliding them in
411                 */
412                var _anims = [];
413                for (var i = this._currentPage * this.itemsPage; i > (this._currentPage - 1) * this.itemsPage; i--){
414                        if (!dom.byId(this.id+'-item-'+i)) continue;
415
416                        var currentItem = dom.byId(this.id+'-item-'+i);
417                        var marginBox = geometry.getMarginBox(currentItem);
418                        if (this.orientation == "horizontal") {
419                                var move = marginBox.l - (this.itemsPage * marginBox.w);
420                                _anims.push(fx.slideTo({node: currentItem, left: move, duration: this.duration}));
421                        }else{
422                                var move = marginBox.t - (this.itemsPage * marginBox.h);
423                                _anims.push(fx.slideTo({node: currentItem, top: move, duration: this.duration}));
424                        }
425
426                }
427                var previousPage = this._currentPage;
428                if (this._currentPage == this._totalPages){
429                        this._currentPage = 1;
430                }else{
431                        this._currentPage++;
432                }
433
434                var cnt = this.itemsPage;
435                for (var i=this._currentPage*this.itemsPage; i>(this._currentPage-1)*this.itemsPage; i--){
436                        if (dom.byId(this.id+'-item-'+i)){
437                                var currentItem = dom.byId(this.id+'-item-'+i);
438                                var marginBox = geometry.getMarginBox(currentItem);
439                                if (this.orientation == "horizontal") {
440                                        var newPos = (style.get(this.pagerContainerView, 'width')+((cnt-1)*marginBox.w))-1;
441                                        style.set(currentItem, 'left', newPos+'px');
442                                        style.set(currentItem, 'top', '0px');
443
444                                        var move = newPos-(this.itemsPage*marginBox.w);
445                                        _anims.push(fx.slideTo({node: currentItem, left: move, duration: this.duration}));
446                                }else{
447                                        newPos = (style.get(this.pagerContainerView, 'height')+((cnt-1)*marginBox.h))-1;
448                                        style.set(currentItem, 'top', newPos+'px');
449                                        style.set(currentItem, 'left', '0px');
450
451                                        var move = newPos-(this.itemsPage*marginBox.h);
452                                        _anims.push(fx.slideTo({ node: currentItem, top: move, duration: this.duration}));
453                                }
454                        }
455                        cnt--;
456                }
457
458                this._anim = fx.combine(_anims);
459                var animHandle = aspect.after(this._anim, "onEnd", lang.hitch(this, function(){
460                        delete this._anim;
461                        this.onScrollEnd();
462                        animHandle.remove();
463                }), true);
464
465                this._anim.play();
466
467                // set pager icons
468                dom.byId(this.id+'-status-'+previousPage).src = this.iconPage;
469                dom.byId(this.id+'-status-'+this._currentPage).src = this.iconPageActive;
470        },
471
472        _pagerPrevious: function(){
473                if(this._anim) return;
474
475                var _anims = [];
476                for (var i=this._currentPage*this.itemsPage; i>(this._currentPage-1)*this.itemsPage; i--){
477                                if (!dom.byId(this.id+'-item-'+i)) continue;
478
479                                var currentItem = dom.byId(this.id+'-item-'+i);
480                                var marginBox = geometry.getMarginBox(currentItem);
481                                if (this.orientation == "horizontal") {
482                                                var move = style.get(currentItem, 'left')+(this.itemsPage*marginBox.w);
483                                                _anims.push(fx.slideTo({node: currentItem, left: move, duration: this.duration}));
484                                }else{
485                                                var move = style.get(currentItem, 'top')+(this.itemsPage*marginBox.h);
486                                                _anims.push(fx.slideTo({node: currentItem, top: move, duration: this.duration}));
487                                }
488                }
489
490                var previousPage = this._currentPage;
491                if (this._currentPage == 1){
492                                this._currentPage = this._totalPages;
493                }else{
494                                this._currentPage--;
495                }
496
497                var cnt = this.itemsPage;
498                var j=1;
499                for (var i=this._currentPage*this.itemsPage; i>(this._currentPage-1)*this.itemsPage; i--){
500                        if(dom.byId(this.id+'-item-'+i)){
501                                var currentItem = dom.byId(this.id+'-item-'+i),
502                                        marginBox = geometry.getMarginBox(currentItem);
503
504                                if (this.orientation == "horizontal") {
505                                        var newPos = -(j * marginBox.w) + 1;
506                                        style.set(currentItem, 'left', newPos+'px');
507                                        style.set(currentItem, 'top', '0px');
508
509                                        var move = ((cnt - 1) * marginBox.w);
510                                        _anims.push(fx.slideTo({node: currentItem, left: move, duration: this.duration}));
511
512                                        var move = newPos+(this.itemsPage * marginBox.w);
513                                        _anims.push(fx.slideTo({node: currentItem, left: move, duration: this.duration}));
514                                }else{
515                                        newPos = -((j * marginBox.h) + 1);
516                                        style.set(currentItem, 'top', newPos+'px');
517                                        style.set(currentItem, 'left', '0px');
518
519                                        var move = ((cnt - 1) * marginBox.h);
520                                        _anims.push(fx.slideTo({node: currentItem, top: move, duration: this.duration}));
521                                }
522
523                        }
524                        cnt--;
525                        j++;
526                }
527
528                this._anim = fx.combine(_anims);
529                var animHandle = aspect.after(this._anim, "onEnd", lang.hitch(this, function(){
530                        delete this._anim;
531                        this.onScrollEnd();
532                        animHandle.remove();
533                }), true);
534
535                this._anim.play();
536
537                // set pager icons
538                dom.byId(this.id + '-status-' + previousPage).src = this.iconPage;
539                dom.byId(this.id + '-status-' + this._currentPage).src = this.iconPageActive;
540
541        },
542
543        onScrollEnd: function(){
544                // summary:
545                //              Stub Function. Fired after the slide is complete. Override or connect.
546        }
547
548});
549
550});
Note: See TracBrowser for help on using the repository browser.