//>>built define("dojox/mobile/Carousel", [ "dojo/_base/kernel", "dojo/_base/array", "dojo/_base/connect", "dojo/_base/declare", "dojo/_base/event", "dojo/_base/lang", "dojo/_base/sniff", "dojo/dom-class", "dojo/dom-construct", "dojo/dom-style", "dijit/_Contained", "dijit/_Container", "dijit/_WidgetBase", "./PageIndicator", "./SwapView", "require" ], function(kernel, array, connect, declare, event, lang, has, domClass, domConstruct, domStyle, Contained, Container, WidgetBase, PageIndicator, SwapView, require){ /*===== var Contained = dijit._Contained; var Container = dijit._Container; var WidgetBase = dijit._WidgetBase; var PageIndicator = dojox.mobile.PageIndicator; var SwapView = dojox.mobile.SwapView; =====*/ // module: // dojox/mobile/Carousel // summary: // A carousel widget that manages a list of images kernel.experimental("dojox.mobile.Carousel"); return declare("dojox.mobile.Carousel", [WidgetBase, Container, Contained], { // summary: // A carousel widget that manages a list of images // description: // The carousel widget manages a list of images that can be // displayed horizontally, and allows the user to scroll through // the list and select a single item. // numVisible: Number // The number of visible items. numVisible: 3, // title: String // A title of the carousel to be displayed on the title bar. title: "", // pageIndicator: Boolean // If true, a page indicator, a series of small dots that indicate // the current page, is displayed on the title bar. pageIndicator: true, // navButton: Boolean // If true, navigation buttons are displyaed on the title bar. navButton: false, // height: String // Explicitly specified height of the widget (ex. "300px"). If // "inherit" is specified, the height is inherited from its offset // parent. height: "300px", // store: Object // Reference to data provider object used by this widget. store: null, // query: Object // A query that can be passed to 'store' to initially filter the // items. query: null, // queryOptions: Object // An optional parameter for the query. queryOptions: null, buildRendering: function(){ this.inherited(arguments); this.domNode.className = "mblCarousel"; var h; if(this.height === "inherit"){ if(this.domNode.offsetParent){ h = this.domNode.offsetParent.offsetHeight + "px"; } }else if(this.height){ h = this.height; } this.domNode.style.height = h; this.headerNode = domConstruct.create("DIV", {className:"mblCarouselHeaderBar"}, this.domNode); if(this.navButton){ this.btnContainerNode = domConstruct.create("DIV", { className: "mblCarouselBtnContainer" }, this.headerNode); domStyle.set(this.btnContainerNode, "float", "right"); // workaround for webkit rendering problem this.prevBtnNode = domConstruct.create("BUTTON", { className: "mblCarouselBtn", title: "Previous", innerHTML: "<" }, this.btnContainerNode); this.nextBtnNode = domConstruct.create("BUTTON", { className: "mblCarouselBtn", title: "Next", innerHTML: ">" }, this.btnContainerNode); this.connect(this.prevBtnNode, "onclick", "onPrevBtnClick"); this.connect(this.nextBtnNode, "onclick", "onNextBtnClick"); } if(this.pageIndicator){ if(!this.title){ this.title = " "; } this.piw = new PageIndicator(); domStyle.set(this.piw, "float", "right"); // workaround for webkit rendering problem this.headerNode.appendChild(this.piw.domNode); } this.titleNode = domConstruct.create("DIV", { className: "mblCarouselTitle" }, this.headerNode); this.containerNode = domConstruct.create("DIV", {className:"mblCarouselPages"}, this.domNode); connect.subscribe("/dojox/mobile/viewChanged", this, "handleViewChanged"); }, startup: function(){ if(this._started){ return; } if(this.store){ var store = this.store; this.store = null; this.setStore(store, this.query, this.queryOptions); } this.inherited(arguments); }, setStore: function(store, query, queryOptions){ // summary: // Sets the store to use with this widget. if(store === this.store){ return; } this.store = store; this.query = query; this.queryOptions = queryOptions; this.refresh(); }, refresh: function(){ if(!this.store){ return; } this.store.fetch({ query: this.query, queryOptions: this.queryOptions, onComplete: lang.hitch(this, "generate"), onError: lang.hitch(this, "onError") }); }, generate: function(/*Array*/items, /*Object*/ dataObject){ array.forEach(this.getChildren(), function(child){ if(child instanceof SwapView){ child.destroyRecursive(); } }); this.items = items; this.swapViews = []; this.images = []; var nPages = Math.ceil(items.length / this.numVisible); var h = this.domNode.offsetHeight - this.headerNode.offsetHeight; for(var i = 0; i < nPages; i++){ var w = new SwapView({height:h+"px"}); this.addChild(w); this.swapViews.push(w); w._carouselImages = []; if(i === 0 && this.piw){ this.piw.refId = w.id; } for(var j = 0; j < this.numVisible; j++){ var idx = i * this.numVisible + j; var item = idx < items.length ? items[idx] : {src:require.toUrl("dojo/resources/blank.gif"), height:"1px"}; var disp = w.domNode.style.display; w.domNode.style.display = ""; // need to be visible during the size calculation var box = this.createBox(item, h); w.containerNode.appendChild(box); box.appendChild(this.createHeaderText(item)); var img = this.createContent(item, idx); box.appendChild(img); box.appendChild(this.createFooterText(item)); this.resizeContent(item, box, img); w.domNode.style.display = disp; if(item.height !== "1px"){ this.images.push(img); w._carouselImages.push(img); } } } if(this.swapViews[0]){ this.loadImages(this.swapViews[0]); } if(this.swapViews[1]){ this.loadImages(this.swapViews[1]); // pre-fetch the next view images } this.currentView = this.swapViews[0]; if(this.piw){ this.piw.reset(); } }, createBox: function(item, h){ var width = item.width || (90/this.numVisible + "%"); var height = item.height || h + "px"; var m = has("ie") ? 5/this.numVisible-1 : 5/this.numVisible; var margin = item.margin || (m + "%"); var box = domConstruct.create("DIV", { className: "mblCarouselBox" }); domStyle.set(box, { margin: "0px " + margin, width: width, height: height }); return box; }, createHeaderText: function(item){ this.headerTextNode = domConstruct.create("DIV", { className: "mblCarouselImgHeaderText", innerHTML: item.headerText ? item.headerText : " " }); return this.headerTextNode; }, createContent: function(item, idx){ var props = { alt: item.alt || "", tabIndex: "0", // for keyboard navigation on a desktop browser className: "mblCarouselImg" }; var img = domConstruct.create("IMG", props); img._idx = idx; if(item.height !== "1px"){ this.connect(img, "onclick", "onClick"); this.connect(img, "onkeydown", "onClick"); connect.connect(img, "ondragstart", event.stop); }else{ img.style.visibility = "hidden"; } return img; }, createFooterText: function(item){ this.footerTextNode = domConstruct.create("DIV", { className: "mblCarouselImgFooterText", innerHTML: item.footerText ? item.footerText : " " }); return this.footerTextNode; }, resizeContent: function(item, box, img){ if(item.height !== "1px"){ img.style.height = (box.offsetHeight - this.headerTextNode.offsetHeight - this.footerTextNode.offsetHeight) + "px"; } }, onError: function(errText){ }, onPrevBtnClick: function(e){ if(this.currentView){ this.currentView.goTo(-1); } }, onNextBtnClick: function(e){ if(this.currentView){ this.currentView.goTo(1); } }, onClick: function(e){ if(e && e.type === "keydown" && e.keyCode !== 13){ return; } var img = e.currentTarget; for(var i = 0; i < this.images.length; i++){ if(this.images[i] === img){ domClass.add(img, "mblCarouselImgSelected"); }else{ domClass.remove(this.images[i], "mblCarouselImgSelected"); } } domStyle.set(img, "opacity", 0.4); setTimeout(function(){ domStyle.set(img, "opacity", 1); }, 1000); connect.publish("/dojox/mobile/carouselSelect", [this, img, this.items[img._idx], img._idx]); }, loadImages: function(view){ if(!view){ return; } var imgs = view._carouselImages; array.forEach(imgs, function(img){ if(!img.src){ var item = this.items[img._idx]; img.src = item.src; } }, this); }, handleViewChanged: function(view){ if(view.getParent() !== this){ return; } this.currentView = view; // lazy-load images in the next view this.loadImages(view.nextView(view.domNode)); }, _setTitleAttr: function(/*String*/title){ this.title = title; this.titleNode.innerHTML = this._cv ? this._cv(title) : title; } }); });