source: Dev/branches/rest-dojo-ui/client/dojox/mobile/Carousel.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 9.0 KB
Line 
1define([
2        "dojo/_base/kernel",
3        "dojo/_base/array",
4        "dojo/_base/connect",
5        "dojo/_base/declare",
6        "dojo/_base/event",
7        "dojo/_base/lang",
8        "dojo/_base/sniff",
9        "dojo/dom-class",
10        "dojo/dom-construct",
11        "dojo/dom-style",
12        "dijit/_Contained",
13        "dijit/_Container",
14        "dijit/_WidgetBase",
15        "./PageIndicator",
16        "./SwapView",
17        "require"
18], function(kernel, array, connect, declare, event, lang, has, domClass, domConstruct, domStyle, Contained, Container, WidgetBase, PageIndicator, SwapView, require){
19
20/*=====
21        var Contained = dijit._Contained;
22        var Container = dijit._Container;
23        var WidgetBase = dijit._WidgetBase;
24        var PageIndicator = dojox.mobile.PageIndicator;
25        var SwapView = dojox.mobile.SwapView;
26=====*/
27
28        // module:
29        //              dojox/mobile/Carousel
30        // summary:
31        //              A carousel widget that manages a list of images
32
33        kernel.experimental("dojox.mobile.Carousel");
34
35        return declare("dojox.mobile.Carousel", [WidgetBase, Container, Contained], {
36                // summary:
37                //              A carousel widget that manages a list of images
38                // description:
39                //              The carousel widget manages a list of images that can be
40                //              displayed horizontally, and allows the user to scroll through
41                //              the list and select a single item.
42
43                // numVisible: Number
44                //              The number of visible items.
45                numVisible: 3,
46
47                // title: String
48                //              A title of the carousel to be displayed on the title bar.
49                title: "",
50
51                // pageIndicator: Boolean
52                //              If true, a page indicator, a series of small dots that indicate
53                //              the current page, is displayed on the title bar.
54                pageIndicator: true,
55
56                // navButton: Boolean
57                //              If true, navigation buttons are displyaed on the title bar.
58                navButton: false,
59
60                // height: String
61                //              Explicitly specified height of the widget (ex. "300px"). If
62                //              "inherit" is specified, the height is inherited from its offset
63                //              parent.
64                height: "300px",
65
66                // store: Object
67                //              Reference to data provider object used by this widget.
68                store: null,
69
70                // query: Object
71                //              A query that can be passed to 'store' to initially filter the
72                //              items.
73                query: null,
74
75                // queryOptions: Object
76                //              An optional parameter for the query.
77                queryOptions: null,
78
79                buildRendering: function(){
80                        this.inherited(arguments);
81                        this.domNode.className = "mblCarousel";
82                        var h;
83                        if(this.height === "inherit"){
84                                if(this.domNode.offsetParent){
85                                        h = this.domNode.offsetParent.offsetHeight + "px";
86                                }
87                        }else if(this.height){
88                                h = this.height;
89                        }
90                        this.domNode.style.height = h;
91                        this.headerNode = domConstruct.create("DIV", {className:"mblCarouselHeaderBar"}, this.domNode);
92
93                        if(this.navButton){
94                                this.btnContainerNode = domConstruct.create("DIV", {
95                                        className: "mblCarouselBtnContainer"
96                                }, this.headerNode);
97                                domStyle.set(this.btnContainerNode, "float", "right"); // workaround for webkit rendering problem
98                                this.prevBtnNode = domConstruct.create("BUTTON", {
99                                        className: "mblCarouselBtn",
100                                        title: "Previous",
101                                        innerHTML: "<"
102                                }, this.btnContainerNode);
103                                this.nextBtnNode = domConstruct.create("BUTTON", {
104                                        className: "mblCarouselBtn",
105                                        title: "Next",
106                                        innerHTML: ">"
107                                }, this.btnContainerNode);
108                                this.connect(this.prevBtnNode, "onclick", "onPrevBtnClick");
109                                this.connect(this.nextBtnNode, "onclick", "onNextBtnClick");
110                        }
111
112                        if(this.pageIndicator){
113                                if(!this.title){
114                                        this.title = " ";
115                                }
116                                this.piw = new PageIndicator();
117                                domStyle.set(this.piw, "float", "right"); // workaround for webkit rendering problem
118                                this.headerNode.appendChild(this.piw.domNode);
119                        }
120
121                        this.titleNode = domConstruct.create("DIV", {
122                                className: "mblCarouselTitle"
123                        }, this.headerNode);
124
125                        this.containerNode = domConstruct.create("DIV", {className:"mblCarouselPages"}, this.domNode);
126                        connect.subscribe("/dojox/mobile/viewChanged", this, "handleViewChanged");
127                },
128
129                startup: function(){
130                        if(this._started){ return; }
131                        if(this.store){
132                                var store = this.store;
133                                this.store = null;
134                                this.setStore(store, this.query, this.queryOptions);
135                        }
136                        this.inherited(arguments);
137                },
138
139                setStore: function(store, query, queryOptions){
140                        // summary:
141                        //              Sets the store to use with this widget.
142                        if(store === this.store){ return; }
143                        this.store = store;
144                        this.query = query;
145                        this.queryOptions = queryOptions;
146                        this.refresh();
147                },
148
149                refresh: function(){
150                        if(!this.store){ return; }
151                        this.store.fetch({
152                                query: this.query,
153                                queryOptions: this.queryOptions,
154                                onComplete: lang.hitch(this, "generate"),
155                                onError: lang.hitch(this, "onError")
156                        });
157                },
158
159                generate: function(/*Array*/items, /*Object*/ dataObject){
160                        array.forEach(this.getChildren(), function(child){
161                                if(child instanceof SwapView){
162                                        child.destroyRecursive();
163                                }
164                        });
165                        this.items = items;
166                        this.swapViews = [];
167                        this.images = [];
168                        var nPages = Math.ceil(items.length / this.numVisible);
169                        var h = this.domNode.offsetHeight - this.headerNode.offsetHeight;
170                        for(var i = 0; i < nPages; i++){
171                                var w = new SwapView({height:h+"px"});
172                                this.addChild(w);
173                                this.swapViews.push(w);
174                                w._carouselImages = [];
175                                if(i === 0 && this.piw){
176                                        this.piw.refId = w.id;
177                                }
178                                for(var j = 0; j < this.numVisible; j++){
179                                        var idx = i * this.numVisible + j;
180                                        var item = idx < items.length ? items[idx] :
181                                                {src:require.toUrl("dojo/resources/blank.gif"), height:"1px"};
182                                        var disp = w.domNode.style.display;
183                                        w.domNode.style.display = ""; // need to be visible during the size calculation
184                                        var box = this.createBox(item, h);
185                                        w.containerNode.appendChild(box);
186                                        box.appendChild(this.createHeaderText(item));
187                                        var img = this.createContent(item, idx);
188                                        box.appendChild(img);
189                                        box.appendChild(this.createFooterText(item));
190                                        this.resizeContent(item, box, img);
191                                        w.domNode.style.display = disp;
192
193                                        if(item.height !== "1px"){
194                                                this.images.push(img);
195                                                w._carouselImages.push(img);
196                                        }
197                                }
198                        }
199                        if(this.swapViews[0]){
200                                this.loadImages(this.swapViews[0]);
201                        }
202                        if(this.swapViews[1]){
203                                this.loadImages(this.swapViews[1]); // pre-fetch the next view images
204                        }
205                        this.currentView = this.swapViews[0];
206                        if(this.piw){
207                                this.piw.reset();
208                        }
209                },
210
211                createBox: function(item, h){
212                        var width = item.width || (90/this.numVisible + "%");
213                        var height = item.height || h + "px";
214                        var m = has("ie") ? 5/this.numVisible-1 : 5/this.numVisible;
215                        var margin = item.margin || (m + "%");
216                        var box = domConstruct.create("DIV", {
217                                className: "mblCarouselBox"
218                        });
219                        domStyle.set(box, {
220                                margin: "0px " + margin,
221                                width: width,
222                                height: height
223                        });
224                        return box;
225                },
226
227                createHeaderText: function(item){
228                        this.headerTextNode = domConstruct.create("DIV", {
229                                className: "mblCarouselImgHeaderText",
230                                innerHTML: item.headerText ? item.headerText : "&nbsp;"
231                        });
232                        return this.headerTextNode;
233                },
234
235                createContent: function(item, idx){
236                        var props = {
237                                alt: item.alt || "",
238                                tabIndex: "0", // for keyboard navigation on a desktop browser
239                                className: "mblCarouselImg"
240                        };
241                        var img = domConstruct.create("IMG", props);
242                        img._idx = idx;
243                        if(item.height !== "1px"){
244                                this.connect(img, "onclick", "onClick");
245                                this.connect(img, "onkeydown", "onClick");
246                                connect.connect(img, "ondragstart", event.stop);
247                        }else{
248                                img.style.visibility = "hidden";
249                        }
250                        return img;
251                },
252
253                createFooterText: function(item){
254                        this.footerTextNode = domConstruct.create("DIV", {
255                                className: "mblCarouselImgFooterText",
256                                innerHTML: item.footerText ? item.footerText : "&nbsp;"
257                        });
258                        return this.footerTextNode;
259                },
260
261                resizeContent: function(item, box, img){
262                        if(item.height !== "1px"){
263                                img.style.height = (box.offsetHeight  - this.headerTextNode.offsetHeight - this.footerTextNode.offsetHeight) + "px";
264                        }
265                },
266
267                onError: function(errText){
268                },
269
270                onPrevBtnClick: function(e){
271                        if(this.currentView){
272                                this.currentView.goTo(-1);
273                        }
274                },
275
276                onNextBtnClick: function(e){
277                        if(this.currentView){
278                                this.currentView.goTo(1);
279                        }
280                },
281
282                onClick: function(e){
283                        if(e && e.type === "keydown" && e.keyCode !== 13){ return; }
284                        var img = e.currentTarget;
285                        for(var i = 0; i < this.images.length; i++){
286                                if(this.images[i] === img){
287                                        domClass.add(img, "mblCarouselImgSelected");
288                                }else{
289                                        domClass.remove(this.images[i], "mblCarouselImgSelected");
290                                }
291                        }
292                        domStyle.set(img, "opacity", 0.4);
293                        setTimeout(function(){
294                                domStyle.set(img, "opacity", 1);
295                        }, 1000);
296                        connect.publish("/dojox/mobile/carouselSelect", [this, img, this.items[img._idx], img._idx]);
297                },
298
299                loadImages: function(view){
300                        if(!view){ return; }
301                        var imgs = view._carouselImages;
302                        array.forEach(imgs, function(img){
303                                if(!img.src){
304                                        var item = this.items[img._idx];
305                                        img.src = item.src;
306                                }
307                        }, this);
308                },
309
310                handleViewChanged: function(view){
311                        if(view.getParent() !== this){ return; }
312                        this.currentView = view;
313                        // lazy-load images in the next view
314                        this.loadImages(view.nextView(view.domNode));
315                },
316
317                _setTitleAttr: function(/*String*/title){
318                        this.title = title;
319                        this.titleNode.innerHTML = this._cv ? this._cv(title) : title;
320                }
321        });
322});
Note: See TracBrowser for help on using the repository browser.