/* Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ /* This is an optimized version of Dojo, built for deployment and not for development. To get sources and documentation, please visit: http://dojotoolkit.org */ //>>built require({cache:{ 'dojo/uacss':function(){ define(["./dom-geometry", "./_base/lang", "./ready", "./_base/sniff", "./_base/window"], function(geometry, lang, ready, has, baseWindow){ // module: // dojo/uacss // summary: // Applies pre-set CSS classes to the top-level HTML node, based on: // - browser (ex: dj_ie) // - browser version (ex: dj_ie6) // - box model (ex: dj_contentBox) // - text direction (ex: dijitRtl) // // In addition, browser, browser version, and box model are // combined with an RTL flag when browser text is RTL. ex: dj_ie-rtl. var html = baseWindow.doc.documentElement, ie = has("ie"), opera = has("opera"), maj = Math.floor, ff = has("ff"), boxModel = geometry.boxModel.replace(/-/,''), classes = { "dj_ie": ie, "dj_ie6": maj(ie) == 6, "dj_ie7": maj(ie) == 7, "dj_ie8": maj(ie) == 8, "dj_ie9": maj(ie) == 9, "dj_quirks": has("quirks"), "dj_iequirks": ie && has("quirks"), // NOTE: Opera not supported by dijit "dj_opera": opera, "dj_khtml": has("khtml"), "dj_webkit": has("webkit"), "dj_safari": has("safari"), "dj_chrome": has("chrome"), "dj_gecko": has("mozilla"), "dj_ff3": maj(ff) == 3 }; // no dojo unsupported browsers classes["dj_" + boxModel] = true; // apply browser, browser version, and box model class names var classStr = ""; for(var clz in classes){ if(classes[clz]){ classStr += clz + " "; } } html.className = lang.trim(html.className + " " + classStr); // If RTL mode, then add dj_rtl flag plus repeat existing classes with -rtl extension. // We can't run the code below until the tag has loaded (so we can check for dir=rtl). // priority is 90 to run ahead of parser priority of 100 ready(90, function(){ if(!geometry.isBodyLtr()){ var rtlClassStr = "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl "); html.className = lang.trim(html.className + " " + rtlClassStr + "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl ")); } }); return has; }); }, 'dojox/mobile/app/_Widget':function(){ // wrapped by build app define(["dijit","dojo","dojox","dojo/require!dijit/_WidgetBase"], function(dijit,dojo,dojox){ dojo.provide("dojox.mobile.app._Widget"); dojo.experimental("dojox.mobile.app._Widget"); dojo.require("dijit._WidgetBase"); dojo.declare("dojox.mobile.app._Widget", dijit._WidgetBase, { // summary: // The base mobile app widget. getScroll: function(){ // summary: // Returns the scroll position. return { x: dojo.global.scrollX, y: dojo.global.scrollY }; }, connect: function(target, event, fn){ if(event.toLowerCase() == "dblclick" || event.toLowerCase() == "ondblclick"){ if(dojo.global["Mojo"]){ // Handle webOS tap event return this.connect(target, Mojo.Event.tap, fn); } } return this.inherited(arguments); } }); }); }, 'dojox/mobile/app/ImageThumbView':function(){ // wrapped by build app define(["dijit","dojo","dojox","dojo/require!dijit/_WidgetBase,dojo/string"], function(dijit,dojo,dojox){ dojo.provide("dojox.mobile.app.ImageThumbView"); dojo.experimental("dojox.mobile.app.ImageThumbView"); dojo.require("dijit._WidgetBase"); dojo.require("dojo.string"); dojo.declare("dojox.mobile.app.ImageThumbView", dijit._WidgetBase, { // summary: // An image thumbnail gallery // items: Array // The data items from which the image urls are retrieved. // If an item is a string, it is expected to be a URL. Otherwise // by default it is expected to have a 'url' member. This can // be configured using the 'urlParam' attribute on this widget. items: [], // urlParam: String // The paramter name used to retrieve an image url from a JSON object urlParam: "url", labelParam: null, itemTemplate: '
' + '
' + '
' + '
' + '
' + '
', minPadding: 4, maxPerRow: 3, maxRows: -1, baseClass: "mblImageThumbView", thumbSize: "medium", animationEnabled: true, selectedIndex: -1, cache: null, cacheMustMatch: false, clickEvent: "onclick", cacheBust: false, disableHide: false, constructor: function(params, node){ }, postCreate: function(){ this.inherited(arguments); var _this = this; var hoverCls = "mblThumbHover"; this.addThumb = dojo.hitch(this, this.addThumb); this.handleImgLoad = dojo.hitch(this, this.handleImgLoad); this.hideCached = dojo.hitch(this, this.hideCached); this._onLoadImages = {}; this.cache = []; this.visibleImages = []; this._cacheCounter = 0; this.connect(this.domNode, this.clickEvent, function(event){ var itemNode = _this._getItemNodeFromEvent(event); if(itemNode && !itemNode._cached){ _this.onSelect(itemNode._item, itemNode._index, _this.items); dojo.query(".selected", this.domNode).removeClass("selected"); dojo.addClass(itemNode, "selected"); } }); dojo.addClass(this.domNode, this.thumbSize); this.resize(); this.render(); }, onSelect: function(item, index, items){ // summary: // Dummy function that is triggered when an image is selected. }, _setAnimationEnabledAttr: function(value){ this.animationEnabled = value; dojo[value ? "addClass" : "removeClass"](this.domNode, "animated"); }, _setItemsAttr: function(items){ this.items = items || []; var urls = {}; var i; for(i = 0; i < this.items.length; i++){ urls[this.items[i][this.urlParam]] = 1; } var clearedUrls = []; for(var url in this._onLoadImages){ if(!urls[url] && this._onLoadImages[url]._conn){ dojo.disconnect(this._onLoadImages[url]._conn); this._onLoadImages[url].src = null; clearedUrls.push(url); } } for(i = 0; i < clearedUrls.length; i++){ delete this._onLoadImages[url]; } this.render(); }, _getItemNode: function(node){ while(node && !dojo.hasClass(node, "mblThumb") && node != this.domNode){ node = node.parentNode; } return (node == this.domNode) ? null : node; }, _getItemNodeFromEvent: function(event){ if(event.touches && event.touches.length > 0){ event = event.touches[0]; } return this._getItemNode(event.target); }, resize: function(){ this._thumbSize = null; this._size = dojo.contentBox(this.domNode); this.disableHide = true; this.render(); this.disableHide = false; }, hideCached: function(){ // summary: // Hides all cached nodes, so that they're no invisible and overlaying // other screen elements. for(var i = 0; i < this.cache.length; i++){ if (this.cache[i]) { dojo.style(this.cache[i], "display", "none"); } } }, render: function(){ var i; var url; var item; var thumb; while(this.visibleImages && this.visibleImages.length > 0){ thumb = this.visibleImages.pop(); this.cache.push(thumb); if (!this.disableHide) { dojo.addClass(thumb, "hidden"); } thumb._cached = true; } if(this.cache && this.cache.length > 0){ setTimeout(this.hideCached, 1000); } if(!this.items || this.items.length == 0){ return; } for(i = 0; i < this.items.length; i++){ item = this.items[i]; url = (dojo.isString(item) ? item : item[this.urlParam]); this.addThumb(item, url, i); if(this.maxRows > 0 && (i + 1) / this.maxPerRow >= this.maxRows){ break; } } if(!this._thumbSize){ return; } var column = 0; var row = -1; var totalThumbWidth = this._thumbSize.w + (this.padding * 2); var totalThumbHeight = this._thumbSize.h + (this.padding * 2); var nodes = this.thumbNodes = dojo.query(".mblThumb", this.domNode); var pos = 0; nodes = this.visibleImages; for(i = 0; i < nodes.length; i++){ if(nodes[i]._cached){ continue; } if(pos % this.maxPerRow == 0){ row ++; } column = pos % this.maxPerRow; this.place( nodes[i], (column * totalThumbWidth) + this.padding, // x position (row * totalThumbHeight) + this.padding // y position ); if(!nodes[i]._loading){ dojo.removeClass(nodes[i], "hidden"); } if(pos == this.selectedIndex){ dojo[pos == this.selectedIndex ? "addClass" : "removeClass"] (nodes[i], "selected"); } pos++; } var numRows = Math.ceil(pos / this.maxPerRow); this._numRows = numRows; this.setContainerHeight((numRows * (this._thumbSize.h + this.padding * 2))); }, setContainerHeight: function(amount){ dojo.style(this.domNode, "height", amount + "px"); }, addThumb: function(item, url, index){ var thumbDiv; var cacheHit = false; if(this.cache.length > 0){ // Reuse a previously created node if possible var found = false; // Search for an image with the same url first for(var i = 0; i < this.cache.length; i++){ if(this.cache[i]._url == url){ thumbDiv = this.cache.splice(i, 1)[0]; found = true; break } } // if no image with the same url is found, just take the last one if(!thumbDiv && !this.cacheMustMatch){ thumbDiv = this.cache.pop(); dojo.removeClass(thumbDiv, "selected"); } else { cacheHit = true; } } if(!thumbDiv){ // Create a new thumb thumbDiv = dojo.create("div", { "class": "mblThumb hidden", innerHTML: dojo.string.substitute(this.itemTemplate, { url: url }, null, this) }, this.domNode); } if(this.labelParam) { var labelNode = dojo.query(".mblThumbLabel", thumbDiv)[0]; if(!labelNode) { labelNode = dojo.create("div", { "class": "mblThumbLabel" }, thumbDiv); } labelNode.innerHTML = item[this.labelParam] || ""; } dojo.style(thumbDiv, "display", ""); if (!this.disableHide) { dojo.addClass(thumbDiv, "hidden"); } if (!cacheHit) { var loader = dojo.create("img", {}); loader._thumbDiv = thumbDiv; loader._conn = dojo.connect(loader, "onload", this.handleImgLoad); loader._url = url; thumbDiv._loading = true; this._onLoadImages[url] = loader; if (loader) { loader.src = url; } } this.visibleImages.push(thumbDiv); thumbDiv._index = index; thumbDiv._item = item; thumbDiv._url = url; thumbDiv._cached = false; if(!this._thumbSize){ this._thumbSize = dojo.marginBox(thumbDiv); if(this._thumbSize.h == 0){ this._thumbSize.h = 100; this._thumbSize.w = 100; } if(this.labelParam){ this._thumbSize.h += 8; } this.calcPadding(); } }, handleImgLoad: function(event){ var img = event.target; dojo.disconnect(img._conn); dojo.removeClass(img._thumbDiv, "hidden"); img._thumbDiv._loading = false; img._conn = null; var url = img._url; if(this.cacheBust){ url += (url.indexOf("?") > -1 ? "&" : "?") + "cacheBust=" + (new Date()).getTime() + "_" + (this._cacheCounter++); } dojo.query(".mblThumbSrc", img._thumbDiv) .style("backgroundImage", "url(" + url + ")"); delete this._onLoadImages[img._url]; }, calcPadding: function(){ var width = this._size.w; var thumbWidth = this._thumbSize.w; var imgBounds = thumbWidth + this.minPadding; this.maxPerRow = Math.floor(width / imgBounds); this.padding = Math.floor((width - (thumbWidth * this.maxPerRow)) / (this.maxPerRow * 2)); }, place: function(node, x, y){ dojo.style(node, { "-webkit-transform" :"translate(" + x + "px," + y + "px)" }); }, destroy: function(){ // Stop the loading of any more images var img; var counter = 0; for (var url in this._onLoadImages){ img = this._onLoadImages[url]; if (img) { img.src = null; counter++; } } this.inherited(arguments); } }); }); }, 'dojox/mobile/TransitionEvent':function(){ define("dojox/mobile/TransitionEvent", [ "dojo/_base/declare", "dojo/_base/Deferred", "dojo/_base/lang", "dojo/on", "./transition" ], function(declare, Deferred, lang, on, transitDeferred){ return declare("dojox.mobile.TransitionEvent", null, { constructor: function(target, transitionOptions, triggerEvent){ this.transitionOptions=transitionOptions; this.target = target; this.triggerEvent=triggerEvent||null; }, dispatch: function(){ var opts = {bubbles:true, cancelable:true, detail: this.transitionOptions, triggerEvent: this.triggerEvent}; //console.log("Target: ", this.target, " opts: ", opts); var evt = on.emit(this.target,"startTransition", opts); //console.log('evt: ', evt); if(evt){ Deferred.when(transitDeferred, lang.hitch(this, function(transition){ Deferred.when(transition.call(this, evt), lang.hitch(this, function(results){ this.endTransition(results); })); })); } }, endTransition: function(results){ on.emit(this.target, "endTransition" , {detail: results.transitionOptions}); } }); }); }, 'dojox/mobile/ViewController':function(){ define([ "dojo/_base/kernel", "dojo/_base/array", "dojo/_base/connect", "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/window", "dojo/dom", "dojo/dom-class", "dojo/dom-construct", // "dojo/hash", // optionally prereq'ed "dojo/on", "dojo/ready", "dijit/registry", // registry.byId "./ProgressIndicator", "./TransitionEvent" ], function(dojo, array, connect, declare, lang, win, dom, domClass, domConstruct, on, ready, registry, ProgressIndicator, TransitionEvent){ // module: // dojox/mobile/ViewController // summary: // A singleton class that controlls view transition. var dm = lang.getObject("dojox.mobile", true); var Controller = declare("dojox.mobile.ViewController", null, { // summary: // A singleton class that controlls view transition. // description: // This class listens to the "startTransition" events and performs // view transitions. If the transition destination is an external // view specified with the url parameter, retrieves the view // content and parses it to create a new target view. constructor: function(){ this.viewMap={}; this.currentView=null; this.defaultView=null; ready(lang.hitch(this, function(){ on(win.body(), "startTransition", lang.hitch(this, "onStartTransition")); })); }, findCurrentView: function(moveTo,src){ // summary: // Searches for the currently showing view. if(moveTo){ var w = registry.byId(moveTo); if(w && w.getShowingView){ return w.getShowingView(); } } if(dm.currentView){ return dm.currentView; //TODO:1.8 may not return an expected result especially when views are nested } //TODO:1.8 probably never reaches here w = src; while(true){ w = w.getParent(); if(!w){ return null; } if(domClass.contains(w.domNode, "mblView")){ break; } } return w; }, onStartTransition: function(evt){ // summary: // A handler that performs view transition. evt.preventDefault(); if(!evt.detail || (evt.detail && !evt.detail.moveTo && !evt.detail.href && !evt.detail.url && !evt.detail.scene)){ return; } var w = this.findCurrentView(evt.detail.moveTo, (evt.target && evt.target.id)?registry.byId(evt.target.id):registry.byId(evt.target)); // the current view widget if(!w || (evt.detail && evt.detail.moveTo && w === registry.byId(evt.detail.moveTo))){ return; } if(evt.detail.href){ var t = registry.byId(evt.target.id).hrefTarget; if(t){ dm.openWindow(evt.detail.href, t); }else{ w.performTransition(null, evt.detail.transitionDir, evt.detail.transition, evt.target, function(){location.href = evt.detail.href;}); } return; } else if(evt.detail.scene){ connect.publish("/dojox/mobile/app/pushScene", [evt.detail.scene]); return; } var moveTo = evt.detail.moveTo; if(evt.detail.url){ var id; if(dm._viewMap && dm._viewMap[evt.detail.url]){ // external view has already been loaded id = dm._viewMap[evt.detail.url]; }else{ // get the specified external view and append it to the var text = this._text; if(!text){ if(registry.byId(evt.target.id).sync){ // We do not add explicit dependency on dojo/_base/xhr to this module // to be able to create a build that does not contain dojo/_base/xhr. // User applications that do sync loading here need to explicitly // require dojo/_base/xhr up front. dojo.xhrGet({url:evt.detail.url, sync:true, load:function(result){ text = lang.trim(result); }}); }else{ var s = "dojo/_base/xhr"; // assign to a variable so as not to be picked up by the build tool require([s], lang.hitch(this, function(xhr){ var prog = ProgressIndicator.getInstance(); win.body().appendChild(prog.domNode); prog.start(); var obj = xhr.get({ url: evt.detail.url, handleAs: "text" }); obj.addCallback(lang.hitch(this, function(response, ioArgs){ prog.stop(); if(response){ this._text = response; new TransitionEvent(evt.target, { transition: evt.detail.transition, transitionDir: evt.detail.transitionDir, moveTo: moveTo, href: evt.detail.href, url: evt.detail.url, scene: evt.detail.scene}, evt.detail) .dispatch(); } })); obj.addErrback(function(error){ prog.stop(); console.log("Failed to load "+evt.detail.url+"\n"+(error.description||error)); }); })); return; } } this._text = null; id = this._parse(text, registry.byId(evt.target.id).urlTarget); if(!dm._viewMap){ dm._viewMap = []; } dm._viewMap[evt.detail.url] = id; } moveTo = id; w = this.findCurrentView(moveTo,registry.byId(evt.target.id)) || w; // the current view widget } w.performTransition(moveTo, evt.detail.transitionDir, evt.detail.transition, null, null); }, _parse: function(text, id){ // summary: // Parses the given view content. // description: // If the content is html fragment, constructs dom tree with it // and runs the parser. If the content is json data, passes it // to _instantiate(). var container, view, i, j, len; var currentView = this.findCurrentView(); var target = registry.byId(id) && registry.byId(id).containerNode || dom.byId(id) || currentView && currentView.domNode.parentNode || win.body(); // if a fixed bottom bar exists, a new view should be placed before it. var refNode = null; for(j = target.childNodes.length - 1; j >= 0; j--){ var c = target.childNodes[j]; if(c.nodeType === 1){ if(c.getAttribute("fixed") === "bottom"){ refNode = c; } break; } } if(text.charAt(0) === "<"){ // html markup container = domConstruct.create("DIV", {innerHTML: text}); for(i = 0; i < container.childNodes.length; i++){ var n = container.childNodes[i]; if(n.nodeType === 1){ view = n; // expecting
break; } } if(!view){ console.log("dojox.mobile.ViewController#_parse: invalid view content"); return; } view.style.visibility = "hidden"; target.insertBefore(container, refNode); var ws = dojo.parser.parse(container); array.forEach(ws, function(w){ if(w && !w._started && w.startup){ w.startup(); } }); // allows multiple root nodes in the fragment, // but transition will be performed to the 1st view. for(i = 0, len = container.childNodes.length; i < len; i++){ target.insertBefore(container.firstChild, refNode); // reparent } target.removeChild(container); registry.byNode(view)._visible = true; }else if(text.charAt(0) === "{"){ // json container = domConstruct.create("DIV"); target.insertBefore(container, refNode); this._ws = []; view = this._instantiate(eval('('+text+')'), container); for(i = 0; i < this._ws.length; i++){ var w = this._ws[i]; w.startup && !w._started && (!w.getParent || !w.getParent()) && w.startup(); } this._ws = null; } view.style.display = "none"; view.style.visibility = "visible"; return dojo.hash ? "#" + view.id : view.id; }, _instantiate: function(/*Object*/obj, /*DomNode*/node, /*Widget*/parent){ // summary: // Given the evaluated json data, does the same thing as what // the parser does. var widget; for(var key in obj){ if(key.charAt(0) == "@"){ continue; } var cls = lang.getObject(key); if(!cls){ continue; } var params = {}; var proto = cls.prototype; var objs = lang.isArray(obj[key]) ? obj[key] : [obj[key]]; for(var i = 0; i < objs.length; i++){ for(var prop in objs[i]){ if(prop.charAt(0) == "@"){ var val = objs[i][prop]; prop = prop.substring(1); if(typeof proto[prop] == "string"){ params[prop] = val; }else if(typeof proto[prop] == "number"){ params[prop] = val - 0; }else if(typeof proto[prop] == "boolean"){ params[prop] = (val != "false"); }else if(typeof proto[prop] == "object"){ params[prop] = eval("(" + val + ")"); } } } widget = new cls(params, node); if(node){ // to call View's startup() widget._visible = true; this._ws.push(widget); } if(parent && parent.addChild){ parent.addChild(widget); } this._instantiate(objs[i], null, widget); } } return widget && widget.domNode; } }); new Controller(); // singleton return Controller; }); }, 'dojox/mobile/ToolBarButton':function(){ define("dojox/mobile/ToolBarButton", [ "dojo/_base/declare", "dojo/_base/window", "dojo/dom-class", "dojo/dom-construct", "dojo/dom-style", "./common", "./_ItemBase" ], function(declare, win, domClass, domConstruct, domStyle, common, ItemBase){ /*===== var ItemBase = dojox.mobile._ItemBase; =====*/ // module: // dojox/mobile/ToolBarButton // summary: // A button widget that is placed in the Heading widget. return declare("dojox.mobile.ToolBarButton", ItemBase, { // summary: // A button widget that is placed in the Heading widget. // description: // ToolBarButton is a button that is placed in the Heading // widget. It is a subclass of dojox.mobile._ItemBase just like // ListItem or IconItem. So, unlike Button, it has basically the // same capability as ListItem or IconItem, such as icon support, // transition, etc. // selected: Boolean // If true, the button is in the selected status. selected: false, // btnClass: String // Deprecated. btnClass: "", /* internal properties */ _defaultColor: "mblColorDefault", _selColor: "mblColorDefaultSel", buildRendering: function(){ this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement("div"); this.inheritParams(); domClass.add(this.domNode, "mblToolBarButton mblArrowButtonText"); var color; if(this.selected){ color = this._selColor; }else if(this.domNode.className.indexOf("mblColor") == -1){ color = this._defaultColor; } domClass.add(this.domNode, color); if(!this.label){ this.label = this.domNode.innerHTML; } if(this.icon && this.icon != "none"){ this.iconNode = domConstruct.create("div", {className:"mblToolBarButtonIcon"}, this.domNode); common.createIcon(this.icon, this.iconPos, null, this.alt, this.iconNode); if(this.iconPos){ domClass.add(this.iconNode.firstChild, "mblToolBarButtonSpriteIcon"); } }else{ if(common.createDomButton(this.domNode)){ domClass.add(this.domNode, "mblToolBarButtonDomButton"); }else{ domClass.add(this.domNode, "mblToolBarButtonText"); } } this.connect(this.domNode, "onclick", "onClick"); }, select: function(){ // summary: // Makes this widget in the selected state. domClass.toggle(this.domNode, this._selColor, !arguments[0]); this.selected = !arguments[0]; }, deselect: function(){ // summary: // Makes this widget in the deselected state. this.select(true); }, onClick: function(e){ this.setTransitionPos(e); this.defaultClickAction(); }, _setBtnClassAttr: function(/*String*/btnClass){ var node = this.domNode; if(node.className.match(/(mblDomButton\w+)/)){ domClass.remove(node, RegExp.$1); } domClass.add(node, btnClass); if(common.createDomButton(this.domNode)){ domClass.add(this.domNode, "mblToolBarButtonDomButton"); } }, _setLabelAttr: function(/*String*/text){ this.label = text; this.domNode.innerHTML = this._cv ? this._cv(text) : text; } }); }); }, 'dojox/mobile/_ItemBase':function(){ define("dojox/mobile/_ItemBase", [ "dojo/_base/kernel", "dojo/_base/config", "dojo/_base/declare", "dijit/registry", // registry.getEnclosingWidget "dijit/_Contained", "dijit/_Container", "dijit/_WidgetBase", "./TransitionEvent", "./View" ], function(kernel, config, declare, registry, Contained, Container, WidgetBase, TransitionEvent, View){ /*===== var Contained = dijit._Contained; var Container = dijit._Container; var WidgetBase = dijit._WidgetBase; var TransitionEvent = dojox.mobile.TransitionEvent; var View = dojox.mobile.View; =====*/ // module: // dojox/mobile/_ItemBase // summary: // A base class for item classes (e.g. ListItem, IconItem, etc.) return declare("dojox.mobile._ItemBase", [WidgetBase, Container, Contained],{ // summary: // A base class for item classes (e.g. ListItem, IconItem, etc.) // description: // _ItemBase is a base class for widgets that have capability to // make a view transition when clicked. // icon: String // An icon image to display. The value can be either a path for an // image file or a class name of a DOM button. If icon is not // specified, the iconBase parameter of the parent widget is used. icon: "", // iconPos: String // The position of an aggregated icon. IconPos is comma separated // values like top,left,width,height (ex. "0,0,29,29"). If iconPos // is not specified, the iconPos parameter of the parent widget is // used. iconPos: "", // top,left,width,height (ex. "0,0,29,29") // alt: String // An alt text for the icon image. alt: "", // href: String // A URL of another web page to go to. href: "", // hrefTarget: String // A target that specifies where to open a page specified by // href. The value will be passed to the 2nd argument of // window.open(). hrefTarget: "", // moveTo: String // The id of the transition destination view which resides in the // current page. // // If the value has a hash sign ('#') before the id (e.g. #view1) // and the dojo.hash module is loaded by the user application, the // view transition updates the hash in the browser URL so that the // user can bookmark the destination view. In this case, the user // can also use the browser's back/forward button to navigate // through the views in the browser history. // // If null, transitions to a blank view. // If '#', returns immediately without transition. moveTo: "", // scene: String // The name of a scene. Used from dojox.mobile.app. scene: "", // clickable: Boolean // If true, this item becomes clickable even if a transition // destination (moveTo, etc.) is not specified. clickable: false, // url: String // A URL of an html fragment page or JSON data that represents a // new view content. The view content is loaded with XHR and // inserted in the current page. Then a view transition occurs to // the newly created view. The view is cached so that subsequent // requests would not load the content again. url: "", // urlTarget: String // Node id under which a new view will be created according to the // url parameter. If not specified, The new view will be created as // a sibling of the current view. urlTarget: "", // transition: String // A type of animated transition effect. You can choose from the // standard transition types, "slide", "fade", "flip", or from the // extended transition types, "cover", "coverv", "dissolve", // "reveal", "revealv", "scaleIn", "scaleOut", "slidev", // "swirl", "zoomIn", "zoomOut". If "none" is specified, transition // occurs immediately without animation. transition: "", // transitionDir: Number // The transition direction. If 1, transition forward. If -1, // transition backward. For example, the slide transition slides // the view from right to left when dir == 1, and from left to // right when dir == -1. transitionDir: 1, // transitionOptions: Object // A hash object that holds transition options. transitionOptions: null, // callback: Function|String // A callback function that is called when the transition has been // finished. A function reference, or name of a function in // context. callback: null, // sync: Boolean // If true, XHR for the view content specified with the url // parameter is performed synchronously. If false, it is done // asynchronously and the progress indicator is displayed while // loading the content. This parameter is effective only when the // url parameter is used. sync: true, // label: String // A label of the item. If the label is not specified, innerHTML is // used as a label. label: "", // toggle: Boolean // If true, the item acts like a toggle button. toggle: false, // _duration: Number // Duration of selection, milliseconds. _duration: 800, inheritParams: function(){ var parent = this.getParent(); if(parent){ if(!this.transition){ this.transition = parent.transition; } if(this.icon && parent.iconBase && parent.iconBase.charAt(parent.iconBase.length - 1) === '/'){ this.icon = parent.iconBase + this.icon; } if(!this.icon){ this.icon = parent.iconBase; } if(!this.iconPos){ this.iconPos = parent.iconPos; } } }, select: function(){ // summary: // Makes this widget in the selected state. // description: // Subclass must implement. }, deselect: function(){ // summary: // Makes this widget in the deselected state. // description: // Subclass must implement. }, defaultClickAction: function(e){ if(this.toggle){ if(this.selected){ this.deselect(); }else{ this.select(); } }else if(!this.selected){ this.select(); if(!this.selectOne){ var _this = this; setTimeout(function(){ _this.deselect(); }, this._duration); } var transOpts; if(this.moveTo || this.href || this.url || this.scene){ transOpts = {moveTo: this.moveTo, href: this.href, url: this.url, scene: this.scene, transition: this.transition, transitionDir: this.transitionDir}; }else if(this.transitionOptions){ transOpts = this.transitionOptions; } if(transOpts){ return new TransitionEvent(this.domNode,transOpts,e).dispatch(); } } }, getParent: function(){ // summary: // Gets the parent widget. // description: // Almost equivalent to _Contained#getParent, but this method // does not cause a script error even if this widget has no // parent yet. var ref = this.srcNodeRef || this.domNode; return ref && ref.parentNode ? registry.getEnclosingWidget(ref.parentNode) : null; }, setTransitionPos: function(e){ // summary: // Stores the clicked position for later use. // description: // Some of the transition animations (e.g. ScaleIn) needs the // clicked position. var w = this; while(true){ w = w.getParent(); if(!w || w instanceof View){ break; } } if(w){ w.clickedPosX = e.clientX; w.clickedPosY = e.clientY; } }, transitionTo: function(moveTo, href, url, scene){ // summary: // Performs a view transition. // description: // Given a transition destination, this method performs a view // transition. This method is typically called when this item // is clicked. if(config.isDebug){ var alreadyCalledHash = arguments.callee._ach || (arguments.callee._ach = {}), caller = (arguments.callee.caller || "unknown caller").toString(); if(!alreadyCalledHash[caller]){ kernel.deprecated(this.declaredClass + "::transitionTo() is deprecated." + caller, "", "2.0"); alreadyCalledHash[caller] = true; } } new TransitionEvent(this.domNode, {moveTo: moveTo, href: href, url: url, scene: scene, transition: this.transition, transitionDir: this.transitionDir}).dispatch(); } }); }); }, 'dijit/hccss':function(){ define("dijit/hccss", [ "require", // require.toUrl "dojo/_base/config", // config.blankGif "dojo/dom-class", // domClass.add domConstruct.create domStyle.getComputedStyle "dojo/dom-construct", // domClass.add domConstruct.create domStyle.getComputedStyle "dojo/dom-style", // domClass.add domConstruct.create domStyle.getComputedStyle "dojo/ready", // ready "dojo/_base/sniff", // has("ie") has("mozilla") "dojo/_base/window" // win.body ], function(require, config, domClass, domConstruct, domStyle, ready, has, win){ // module: // dijit/hccss // summary: // Test if computer is in high contrast mode, and sets dijit_a11y flag on if it is. if(has("ie") || has("mozilla")){ // NOTE: checking in Safari messes things up // priority is 90 to run ahead of parser priority of 100 ready(90, function(){ // summary: // Detects if we are in high-contrast mode or not // create div for testing if high contrast mode is on or images are turned off var div = domConstruct.create("div",{ id: "a11yTestNode", style:{ cssText:'border: 1px solid;' + 'border-color:red green;' + 'position: absolute;' + 'height: 5px;' + 'top: -999px;' + 'background-image: url("' + (config.blankGif || require.toUrl("dojo/resources/blank.gif")) + '");' } }, win.body()); // test it var cs = domStyle.getComputedStyle(div); if(cs){ var bkImg = cs.backgroundImage; var needsA11y = (cs.borderTopColor == cs.borderRightColor) || (bkImg != null && (bkImg == "none" || bkImg == "url(invalid-url:)" )); if(needsA11y){ domClass.add(win.body(), "dijit_a11y"); } if(has("ie")){ div.outerHTML = ""; // prevent mixed-content warning, see http://support.microsoft.com/kb/925014 }else{ win.body().removeChild(div); } } }); } }); }, 'dijit/_Contained':function(){ define("dijit/_Contained", [ "dojo/_base/declare", // declare "./registry" // registry.getEnclosingWidget(), registry.byNode() ], function(declare, registry){ // module: // dijit/_Contained // summary: // Mixin for widgets that are children of a container widget return declare("dijit._Contained", null, { // summary: // Mixin for widgets that are children of a container widget // // example: // | // make a basic custom widget that knows about it's parents // | declare("my.customClass",[dijit._Widget,dijit._Contained],{}); _getSibling: function(/*String*/ which){ // summary: // Returns next or previous sibling // which: // Either "next" or "previous" // tags: // private var node = this.domNode; do{ node = node[which+"Sibling"]; }while(node && node.nodeType != 1); return node && registry.byNode(node); // dijit._Widget }, getPreviousSibling: function(){ // summary: // Returns null if this is the first child of the parent, // otherwise returns the next element sibling to the "left". return this._getSibling("previous"); // dijit._Widget }, getNextSibling: function(){ // summary: // Returns null if this is the last child of the parent, // otherwise returns the next element sibling to the "right". return this._getSibling("next"); // dijit._Widget }, getIndexInParent: function(){ // summary: // Returns the index of this widget within its container parent. // It returns -1 if the parent does not exist, or if the parent // is not a dijit._Container var p = this.getParent(); if(!p || !p.getIndexOfChild){ return -1; // int } return p.getIndexOfChild(this); // int } }); }); }, 'dijit/form/_TextBoxMixin':function(){ define("dijit/form/_TextBoxMixin", [ "dojo/_base/array", // array.forEach "dojo/_base/declare", // declare "dojo/dom", // dom.byId "dojo/_base/event", // event.stop "dojo/keys", // keys.ALT keys.CAPS_LOCK keys.CTRL keys.META keys.SHIFT "dojo/_base/lang", // lang.mixin ".." // for exporting dijit._setSelectionRange, dijit.selectInputText ], function(array, declare, dom, event, keys, lang, dijit){ // module: // dijit/form/_TextBoxMixin // summary: // A mixin for textbox form input widgets var _TextBoxMixin = declare("dijit.form._TextBoxMixin", null, { // summary: // A mixin for textbox form input widgets // trim: Boolean // Removes leading and trailing whitespace if true. Default is false. trim: false, // uppercase: Boolean // Converts all characters to uppercase if true. Default is false. uppercase: false, // lowercase: Boolean // Converts all characters to lowercase if true. Default is false. lowercase: false, // propercase: Boolean // Converts the first character of each word to uppercase if true. propercase: false, // maxLength: String // HTML INPUT tag maxLength declaration. maxLength: "", // selectOnClick: [const] Boolean // If true, all text will be selected when focused with mouse selectOnClick: false, // placeHolder: String // Defines a hint to help users fill out the input field (as defined in HTML 5). // This should only contain plain text (no html markup). placeHolder: "", _getValueAttr: function(){ // summary: // Hook so get('value') works as we like. // description: // For `dijit.form.TextBox` this basically returns the value of the . // // For `dijit.form.MappedTextBox` subclasses, which have both // a "displayed value" and a separate "submit value", // This treats the "displayed value" as the master value, computing the // submit value from it via this.parse(). return this.parse(this.get('displayedValue'), this.constraints); }, _setValueAttr: function(value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){ // summary: // Hook so set('value', ...) works. // // description: // Sets the value of the widget to "value" which can be of // any type as determined by the widget. // // value: // The visual element value is also set to a corresponding, // but not necessarily the same, value. // // formattedValue: // If specified, used to set the visual element value, // otherwise a computed visual value is used. // // priorityChange: // If true, an onChange event is fired immediately instead of // waiting for the next blur event. var filteredValue; if(value !== undefined){ // TODO: this is calling filter() on both the display value and the actual value. // I added a comment to the filter() definition about this, but it should be changed. filteredValue = this.filter(value); if(typeof formattedValue != "string"){ if(filteredValue !== null && ((typeof filteredValue != "number") || !isNaN(filteredValue))){ formattedValue = this.filter(this.format(filteredValue, this.constraints)); }else{ formattedValue = ''; } } } if(formattedValue != null && formattedValue != undefined && ((typeof formattedValue) != "number" || !isNaN(formattedValue)) && this.textbox.value != formattedValue){ this.textbox.value = formattedValue; this._set("displayedValue", this.get("displayedValue")); } if(this.textDir == "auto"){ this.applyTextDir(this.focusNode, formattedValue); } this.inherited(arguments, [filteredValue, priorityChange]); }, // displayedValue: String // For subclasses like ComboBox where the displayed value // (ex: Kentucky) and the serialized value (ex: KY) are different, // this represents the displayed value. // // Setting 'displayedValue' through set('displayedValue', ...) // updates 'value', and vice-versa. Otherwise 'value' is updated // from 'displayedValue' periodically, like onBlur etc. // // TODO: move declaration to MappedTextBox? // Problem is that ComboBox references displayedValue, // for benefit of FilteringSelect. displayedValue: "", _getDisplayedValueAttr: function(){ // summary: // Hook so get('displayedValue') works. // description: // Returns the displayed value (what the user sees on the screen), // after filtering (ie, trimming spaces etc.). // // For some subclasses of TextBox (like ComboBox), the displayed value // is different from the serialized value that's actually // sent to the server (see dijit.form.ValidationTextBox.serialize) // TODO: maybe we should update this.displayedValue on every keystroke so that we don't need // this method // TODO: this isn't really the displayed value when the user is typing return this.filter(this.textbox.value); }, _setDisplayedValueAttr: function(/*String*/ value){ // summary: // Hook so set('displayedValue', ...) works. // description: // Sets the value of the visual element to the string "value". // The widget value is also set to a corresponding, // but not necessarily the same, value. if(value === null || value === undefined){ value = '' } else if(typeof value != "string"){ value = String(value) } this.textbox.value = value; // sets the serialized value to something corresponding to specified displayedValue // (if possible), and also updates the textbox.value, for example converting "123" // to "123.00" this._setValueAttr(this.get('value'), undefined); this._set("displayedValue", this.get('displayedValue')); // textDir support if(this.textDir == "auto"){ this.applyTextDir(this.focusNode, value); } }, format: function(value /*=====, constraints =====*/){ // summary: // Replaceable function to convert a value to a properly formatted string. // value: String // constraints: Object // tags: // protected extension return ((value == null || value == undefined) ? "" : (value.toString ? value.toString() : value)); }, parse: function(value /*=====, constraints =====*/){ // summary: // Replaceable function to convert a formatted string to a value // value: String // constraints: Object // tags: // protected extension return value; // String }, _refreshState: function(){ // summary: // After the user types some characters, etc., this method is // called to check the field for validity etc. The base method // in `dijit.form.TextBox` does nothing, but subclasses override. // tags: // protected }, /*===== onInput: function(event){ // summary: // Connect to this function to receive notifications of various user data-input events. // Return false to cancel the event and prevent it from being processed. // event: // keydown | keypress | cut | paste | input // tags: // callback }, =====*/ onInput: function(){}, __skipInputEvent: false, _onInput: function(){ // summary: // Called AFTER the input event has happened // set text direction according to textDir that was defined in creation if(this.textDir == "auto"){ this.applyTextDir(this.focusNode, this.focusNode.value); } this._refreshState(); // In case someone is watch()'ing for changes to displayedValue this._set("displayedValue", this.get("displayedValue")); }, postCreate: function(){ // setting the value here is needed since value="" in the template causes "undefined" // and setting in the DOM (instead of the JS object) helps with form reset actions this.textbox.setAttribute("value", this.textbox.value); // DOM and JS values should be the same this.inherited(arguments); // normalize input events to reduce spurious event processing // onkeydown: do not forward modifier keys // set charOrCode to numeric keycode // onkeypress: do not forward numeric charOrCode keys (already sent through onkeydown) // onpaste & oncut: set charOrCode to 229 (IME) // oninput: if primary event not already processed, set charOrCode to 229 (IME), else do not forward var handleEvent = function(e){ var charCode = e.charOrCode || e.keyCode || 229; if(e.type == "keydown"){ switch(charCode){ // ignore "state" keys case keys.SHIFT: case keys.ALT: case keys.CTRL: case keys.META: case keys.CAPS_LOCK: return; default: if(charCode >= 65 && charCode <= 90){ return; } // keydown for A-Z can be processed with keypress } } if(e.type == "keypress" && typeof charCode != "string"){ return; } if(e.type == "input"){ if(this.__skipInputEvent){ // duplicate event this.__skipInputEvent = false; return; } }else{ this.__skipInputEvent = true; } // create fake event to set charOrCode and to know if preventDefault() was called var faux = lang.mixin({}, e, { charOrCode: charCode, wasConsumed: false, preventDefault: function(){ faux.wasConsumed = true; e.preventDefault(); }, stopPropagation: function(){ e.stopPropagation(); } }); // give web page author a chance to consume the event if(this.onInput(faux) === false){ event.stop(faux); // return false means stop } if(faux.wasConsumed){ return; } // if preventDefault was called setTimeout(lang.hitch(this, "_onInput", faux), 0); // widget notification after key has posted }; array.forEach([ "onkeydown", "onkeypress", "onpaste", "oncut", "oninput" ], function(event){ this.connect(this.textbox, event, handleEvent); }, this); }, _blankValue: '', // if the textbox is blank, what value should be reported filter: function(val){ // summary: // Auto-corrections (such as trimming) that are applied to textbox // value on blur or form submit. // description: // For MappedTextBox subclasses, this is called twice // - once with the display value // - once the value as set/returned by set('value', ...) // and get('value'), ex: a Number for NumberTextBox. // // In the latter case it does corrections like converting null to NaN. In // the former case the NumberTextBox.filter() method calls this.inherited() // to execute standard trimming code in TextBox.filter(). // // TODO: break this into two methods in 2.0 // // tags: // protected extension if(val === null){ return this._blankValue; } if(typeof val != "string"){ return val; } if(this.trim){ val = lang.trim(val); } if(this.uppercase){ val = val.toUpperCase(); } if(this.lowercase){ val = val.toLowerCase(); } if(this.propercase){ val = val.replace(/[^\s]+/g, function(word){ return word.substring(0,1).toUpperCase() + word.substring(1); }); } return val; }, _setBlurValue: function(){ this._setValueAttr(this.get('value'), true); }, _onBlur: function(e){ if(this.disabled){ return; } this._setBlurValue(); this.inherited(arguments); if(this._selectOnClickHandle){ this.disconnect(this._selectOnClickHandle); } }, _isTextSelected: function(){ return this.textbox.selectionStart == this.textbox.selectionEnd; }, _onFocus: function(/*String*/ by){ if(this.disabled || this.readOnly){ return; } // Select all text on focus via click if nothing already selected. // Since mouse-up will clear the selection need to defer selection until after mouse-up. // Don't do anything on focus by tabbing into the widget since there's no associated mouse-up event. if(this.selectOnClick && by == "mouse"){ this._selectOnClickHandle = this.connect(this.domNode, "onmouseup", function(){ // Only select all text on first click; otherwise users would have no way to clear // the selection. this.disconnect(this._selectOnClickHandle); // Check if the user selected some text manually (mouse-down, mouse-move, mouse-up) // and if not, then select all the text if(this._isTextSelected()){ _TextBoxMixin.selectInputText(this.textbox); } }); } // call this.inherited() before refreshState(), since this.inherited() will possibly scroll the viewport // (to scroll the TextBox into view), which will affect how _refreshState() positions the tooltip this.inherited(arguments); this._refreshState(); }, reset: function(){ // Overrides dijit._FormWidget.reset(). // Additionally resets the displayed textbox value to '' this.textbox.value = ''; this.inherited(arguments); }, _setTextDirAttr: function(/*String*/ textDir){ // summary: // Setter for textDir. // description: // Users shouldn't call this function; they should be calling // set('textDir', value) // tags: // private // only if new textDir is different from the old one // and on widgets creation. if(!this._created || this.textDir != textDir){ this._set("textDir", textDir); // so the change of the textDir will take place immediately. this.applyTextDir(this.focusNode, this.focusNode.value); } } }); _TextBoxMixin._setSelectionRange = dijit._setSelectionRange = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){ if(element.setSelectionRange){ element.setSelectionRange(start, stop); } }; _TextBoxMixin.selectInputText = dijit.selectInputText = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){ // summary: // Select text in the input element argument, from start (default 0), to stop (default end). // TODO: use functions in _editor/selection.js? element = dom.byId(element); if(isNaN(start)){ start = 0; } if(isNaN(stop)){ stop = element.value ? element.value.length : 0; } try{ element.focus(); _TextBoxMixin._setSelectionRange(element, start, stop); }catch(e){ /* squelch random errors (esp. on IE) from unexpected focus changes or DOM nodes being hidden */ } }; return _TextBoxMixin; }); }, 'dojox/mobile/parser':function(){ define([ "dojo/_base/kernel", "dojo/_base/config", "dojo/_base/lang", "dojo/_base/window", "dojo/ready" ], function(dojo, config, lang, win, ready){ // module: // dojox/mobile/parser // summary: // A lightweight parser. var dm = lang.getObject("dojox.mobile", true); var parser = new function(){ // summary: // A lightweight parser. // description: // dojox.mobile.parser is an extremely small subset of // dojo.parser. It has no extended features over dojo.parser, so // there is no reason you have to use dojox.mobile.parser instead // of dojo.parser. However, if dojox.mobile.parser's capability is // enough for your application, use of it could reduce the total // code size. this.instantiate = function(/* Array */nodes, /* Object? */mixin, /* Object? */args){ // summary: // Function for instantiating a list of widget nodes. // nodes: // The list of DOMNodes to walk and instantiate widgets on. mixin = mixin || {}; args = args || {}; var i, ws = []; if(nodes){ for(i = 0; i < nodes.length; i++){ var n = nodes[i]; var cls = lang.getObject(n.getAttribute("dojoType") || n.getAttribute("data-dojo-type")); var proto = cls.prototype; var params = {}, prop, v, t; lang.mixin(params, eval('({'+(n.getAttribute("data-dojo-props")||"")+'})')); lang.mixin(params, args.defaults); lang.mixin(params, mixin); for(prop in proto){ v = n.getAttributeNode(prop); v = v && v.nodeValue; t = typeof proto[prop]; if(!v && (t !== "boolean" || v !== "")){ continue; } if(t === "string"){ params[prop] = v; }else if(t === "number"){ params[prop] = v - 0; }else if(t === "boolean"){ params[prop] = (v !== "false"); }else if(t === "object"){ params[prop] = eval("(" + v + ")"); } } params["class"] = n.className; params.style = n.style && n.style.cssText; v = n.getAttribute("data-dojo-attach-point"); if(v){ params.dojoAttachPoint = v; } v = n.getAttribute("data-dojo-attach-event"); if(v){ params.dojoAttachEvent = v; } var instance = new cls(params, n); ws.push(instance); var jsId = n.getAttribute("jsId") || n.getAttribute("data-dojo-id"); if(jsId){ lang.setObject(jsId, instance); } } for(i = 0; i < ws.length; i++){ var w = ws[i]; !args.noStart && w.startup && !w._started && w.startup(); } } return ws; }; this.parse = function(rootNode, args){ // summary: // Function to handle parsing for widgets in the current document. // It is not as powerful as the full parser, but it will handle basic // use cases fine. // rootNode: // The root node in the document to parse from if(!rootNode){ rootNode = win.body(); }else if(!args && rootNode.rootNode){ // Case where 'rootNode' is really a params object. args = rootNode; rootNode = rootNode.rootNode; } var nodes = rootNode.getElementsByTagName("*"); var i, list = []; for(i = 0; i < nodes.length; i++){ var n = nodes[i]; if(n.getAttribute("dojoType") || n.getAttribute("data-dojo-type")){ list.push(n); } } var mixin = args && args.template ? {template: true} : null; return this.instantiate(list, mixin, args); }; }(); if(config.parseOnLoad){ ready(100, parser, "parse"); } dm.parser = parser; // for backward compatibility dojo.parser = parser; // in case user application calls dojo.parser return parser; }); }, 'dijit/_Container':function(){ define("dijit/_Container", [ "dojo/_base/array", // array.forEach array.indexOf "dojo/_base/declare", // declare "dojo/dom-construct", // domConstruct.place "./registry" // registry.byNode() ], function(array, declare, domConstruct, registry){ // module: // dijit/_Container // summary: // Mixin for widgets that contain a set of widget children. return declare("dijit._Container", null, { // summary: // Mixin for widgets that contain a set of widget children. // description: // Use this mixin for widgets that needs to know about and // keep track of their widget children. Suitable for widgets like BorderContainer // and TabContainer which contain (only) a set of child widgets. // // It's not suitable for widgets like ContentPane // which contains mixed HTML (plain DOM nodes in addition to widgets), // and where contained widgets are not necessarily directly below // this.containerNode. In that case calls like addChild(node, position) // wouldn't make sense. buildRendering: function(){ this.inherited(arguments); if(!this.containerNode){ // all widgets with descendants must set containerNode this.containerNode = this.domNode; } }, addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){ // summary: // Makes the given widget a child of this widget. // description: // Inserts specified child widget's dom node as a child of this widget's // container node, and possibly does other processing (such as layout). var refNode = this.containerNode; if(insertIndex && typeof insertIndex == "number"){ var children = this.getChildren(); if(children && children.length >= insertIndex){ refNode = children[insertIndex-1].domNode; insertIndex = "after"; } } domConstruct.place(widget.domNode, refNode, insertIndex); // If I've been started but the child widget hasn't been started, // start it now. Make sure to do this after widget has been // inserted into the DOM tree, so it can see that it's being controlled by me, // so it doesn't try to size itself. if(this._started && !widget._started){ widget.startup(); } }, removeChild: function(/*Widget|int*/ widget){ // summary: // Removes the passed widget instance from this widget but does // not destroy it. You can also pass in an integer indicating // the index within the container to remove if(typeof widget == "number"){ widget = this.getChildren()[widget]; } if(widget){ var node = widget.domNode; if(node && node.parentNode){ node.parentNode.removeChild(node); // detach but don't destroy } } }, hasChildren: function(){ // summary: // Returns true if widget has children, i.e. if this.containerNode contains something. return this.getChildren().length > 0; // Boolean }, _getSiblingOfChild: function(/*dijit._Widget*/ child, /*int*/ dir){ // summary: // Get the next or previous widget sibling of child // dir: // if 1, get the next sibling // if -1, get the previous sibling // tags: // private var node = child.domNode, which = (dir>0 ? "nextSibling" : "previousSibling"); do{ node = node[which]; }while(node && (node.nodeType != 1 || !registry.byNode(node))); return node && registry.byNode(node); // dijit._Widget }, getIndexOfChild: function(/*dijit._Widget*/ child){ // summary: // Gets the index of the child in this container or -1 if not found return array.indexOf(this.getChildren(), child); // int } }); }); }, 'dojox/mobile/app/SceneController':function(){ // wrapped by build app define(["dijit","dojo","dojox","dojo/require!dojox/mobile/_base"], function(dijit,dojo,dojox){ dojo.provide("dojox.mobile.app.SceneController"); dojo.experimental("dojox.mobile.app.SceneController"); dojo.require("dojox.mobile._base"); (function(){ var app = dojox.mobile.app; var templates = {}; dojo.declare("dojox.mobile.app.SceneController", dojox.mobile.View, { stageController: null, keepScrollPos: false, init: function(sceneName, params){ // summary: // Initializes the scene by loading the HTML template and code, if it has // not already been loaded this.sceneName = sceneName; this.params = params; var templateUrl = app.resolveTemplate(sceneName); this._deferredInit = new dojo.Deferred(); if(templates[sceneName]){ // If the template has been cached, do not load it again. this._setContents(templates[sceneName]); }else{ // Otherwise load the template dojo.xhrGet({ url: templateUrl, handleAs: "text" }).addCallback(dojo.hitch(this, this._setContents)); } return this._deferredInit; }, _setContents: function(templateHtml){ // summary: // Sets the content of the View, and invokes either the loading or // initialization of the scene assistant. templates[this.sceneName] = templateHtml; this.domNode.innerHTML = "
" + templateHtml + "
"; var sceneAssistantName = ""; var nameParts = this.sceneName.split("-"); for(var i = 0; i < nameParts.length; i++){ sceneAssistantName += nameParts[i].substring(0, 1).toUpperCase() + nameParts[i].substring(1); } sceneAssistantName += "Assistant"; this.sceneAssistantName = sceneAssistantName; var _this = this; dojox.mobile.app.loadResourcesForScene(this.sceneName, function(){ console.log("All resources for ",_this.sceneName," loaded"); var assistant; if(typeof(dojo.global[sceneAssistantName]) != "undefined"){ _this._initAssistant(); }else{ var assistantUrl = app.resolveAssistant(_this.sceneName); dojo.xhrGet({ url: assistantUrl, handleAs: "text" }).addCallback(function(text){ try{ dojo.eval(text); }catch(e){ console.log("Error initializing code for scene " + _this.sceneName + '. Please check for syntax errors'); throw e; } _this._initAssistant(); }); } }); }, _initAssistant: function(){ // summary: // Initializes the scene assistant. At this point, the View is // populated with the HTML template, and the scene assistant type // is declared. console.log("Instantiating the scene assistant " + this.sceneAssistantName); var cls = dojo.getObject(this.sceneAssistantName); if(!cls){ throw Error("Unable to resolve scene assistant " + this.sceneAssistantName); } this.assistant = new cls(this.params); this.assistant.controller = this; this.assistant.domNode = this.domNode.firstChild; this.assistant.setup(); this._deferredInit.callback(); }, query: function(selector, node){ // summary: // Queries for DOM nodes within either the node passed in as an argument // or within this view. return dojo.query(selector, node || this.domNode) }, parse: function(node){ var widgets = this._widgets = dojox.mobile.parser.parse(node || this.domNode, { controller: this }); // Tell all widgets what their controller is. for(var i = 0; i < widgets.length; i++){ widgets[i].set("controller", this); } }, getWindowSize: function(){ // TODO, this needs cross browser testing return { w: dojo.global.innerWidth, h: dojo.global.innerHeight } }, showAlertDialog: function(props){ var size = dojo.marginBox(this.assistant.domNode); var dialog = new dojox.mobile.app.AlertDialog( dojo.mixin(props, {controller: this})); this.assistant.domNode.appendChild(dialog.domNode); console.log("Appended " , dialog.domNode, " to ", this.assistant.domNode); dialog.show(); }, popupSubMenu: function(info){ var widget = new dojox.mobile.app.ListSelector({ controller: this, destroyOnHide: true, onChoose: info.onChoose }); this.assistant.domNode.appendChild(widget.domNode); widget.set("data", info.choices); widget.show(info.fromNode); } }); })(); }); }, 'dojox/mobile/app/_base':function(){ // wrapped by build app define(["dijit","dojo","dojox","dojo/require!dijit/_base,dijit/_WidgetBase,dojox/mobile,dojox/mobile/parser,dojox/mobile/Button,dojox/mobile/app/_event,dojox/mobile/app/_Widget,dojox/mobile/app/StageController,dojox/mobile/app/SceneController,dojox/mobile/app/SceneAssistant,dojox/mobile/app/AlertDialog,dojox/mobile/app/List,dojox/mobile/app/ListSelector,dojox/mobile/app/TextBox,dojox/mobile/app/ImageView,dojox/mobile/app/ImageThumbView"], function(dijit,dojo,dojox){ dojo.provide("dojox.mobile.app._base"); dojo.experimental("dojox.mobile.app._base"); dojo.require("dijit._base"); dojo.require("dijit._WidgetBase"); dojo.require("dojox.mobile"); dojo.require("dojox.mobile.parser"); dojo.require("dojox.mobile.Button"); dojo.require("dojox.mobile.app._event"); dojo.require("dojox.mobile.app._Widget"); dojo.require("dojox.mobile.app.StageController"); dojo.require("dojox.mobile.app.SceneController"); dojo.require("dojox.mobile.app.SceneAssistant"); dojo.require("dojox.mobile.app.AlertDialog"); dojo.require("dojox.mobile.app.List"); dojo.require("dojox.mobile.app.ListSelector"); dojo.require("dojox.mobile.app.TextBox"); dojo.require("dojox.mobile.app.ImageView"); dojo.require("dojox.mobile.app.ImageThumbView"); (function(){ var stageController; var appInfo; var jsDependencies = [ "dojox.mobile", "dojox.mobile.parser" ]; var loadedResources = {}; var loadingDependencies; var rootNode; var sceneResources = []; // Load the required resources asynchronously, since not all mobile OSes // support dojo.require and sync XHR function loadResources(resources, callback){ // summary: // Loads one or more JavaScript files asynchronously. When complete, // the first scene is pushed onto the stack. // resources: // An array of module names, e.g. 'dojox.mobile.AlertDialog' var resource; var url; do { resource = resources.pop(); if (resource.source) { url = resource.source; }else if (resource.module) { url= dojo.moduleUrl(resource.module)+".js"; }else { console.log("Error: invalid JavaScript resource " + dojo.toJson(resource)); return; } }while (resources.length > 0 && loadedResources[url]); if(resources.length < 1 && loadedResources[url]){ // All resources have already been loaded callback(); return; } dojo.xhrGet({ url: url, sync: false }).addCallbacks(function(text){ dojo["eval"](text); loadedResources[url] = true; if(resources.length > 0){ loadResources(resources, callback); }else{ callback(); } }, function(){ console.log("Failed to load resource " + url); }); } var pushFirstScene = function(){ // summary: // Pushes the first scene onto the stack. stageController = new dojox.mobile.app.StageController(rootNode); var defaultInfo = { id: "com.test.app", version: "1.0.0", initialScene: "main" }; // If the application info has been defined, as it should be, // use it. if(dojo.global["appInfo"]){ dojo.mixin(defaultInfo, dojo.global["appInfo"]); } appInfo = dojox.mobile.app.info = defaultInfo; // Set the document title from the app info title if it exists if(appInfo.title){ var titleNode = dojo.query("head title")[0] || dojo.create("title", {},dojo.query("head")[0]); document.title = appInfo.title; } stageController.pushScene(appInfo.initialScene); }; var initBackButton = function(){ var hasNativeBack = false; if(dojo.global.BackButton){ // Android phonegap support BackButton.override(); dojo.connect(document, 'backKeyDown', function(e) { dojo.publish("/dojox/mobile/app/goback"); }); hasNativeBack = true; }else if(dojo.global.Mojo){ // TODO: add webOS support } if(hasNativeBack){ dojo.addClass(dojo.body(), "mblNativeBack"); } }; dojo.mixin(dojox.mobile.app, { init: function(node){ // summary: // Initializes the mobile app. Creates the rootNode = node || dojo.body(); dojox.mobile.app.STAGE_CONTROLLER_ACTIVE = true; dojo.subscribe("/dojox/mobile/app/goback", function(){ stageController.popScene(); }); dojo.subscribe("/dojox/mobile/app/alert", function(params){ dojox.mobile.app.getActiveSceneController().showAlertDialog(params); }); dojo.subscribe("/dojox/mobile/app/pushScene", function(sceneName, params){ stageController.pushScene(sceneName, params || {}); }); // Get the list of files to load per scene/view dojo.xhrGet({ url: "view-resources.json", load: function(data){ var resources = []; if(data){ // Should be an array sceneResources = data = dojo.fromJson(data); // Get the list of files to load that have no scene // specified, and therefore should be loaded on // startup for(var i = 0; i < data.length; i++){ if(!data[i].scene){ resources.push(data[i]); } } } if(resources.length > 0){ loadResources(resources, pushFirstScene); }else{ pushFirstScene(); } }, error: pushFirstScene }); initBackButton(); }, getActiveSceneController: function(){ // summary: // Gets the controller for the active scene. return stageController.getActiveSceneController(); }, getStageController: function(){ // summary: // Gets the stage controller. return stageController; }, loadResources: function(resources, callback){ loadResources(resources, callback); }, loadResourcesForScene: function(sceneName, callback){ var resources = []; // Get the list of files to load that have no scene // specified, and therefore should be loaded on // startup for(var i = 0; i < sceneResources.length; i++){ if(sceneResources[i].scene == sceneName){ resources.push(sceneResources[i]); } } if(resources.length > 0){ loadResources(resources, callback); }else{ callback(); } }, resolveTemplate: function(sceneName){ // summary: // Given the name of a scene, returns the path to it's template // file. For example, for a scene named 'main', the file // returned is 'app/views/main/main-scene.html' // This function can be overridden if it is desired to have // a different name to file mapping. return "app/views/" + sceneName + "/" + sceneName + "-scene.html"; }, resolveAssistant: function(sceneName){ // summary: // Given the name of a scene, returns the path to it's assistant // file. For example, for a scene named 'main', the file // returned is 'app/assistants/main-assistant.js' // This function can be overridden if it is desired to have // a different name to file mapping. return "app/assistants/" + sceneName + "-assistant.js"; } }); })(); }); }, 'dijit/_base/scroll':function(){ define("dijit/_base/scroll", [ "dojo/window", // windowUtils.scrollIntoView ".." // export symbol to dijit ], function(windowUtils, dijit){ // module: // dijit/_base/scroll // summary: // Back compatibility module, new code should use windowUtils directly instead of using this module. dijit.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){ // summary: // Scroll the passed node into view, if it is not already. // Deprecated, use `windowUtils.scrollIntoView` instead. windowUtils.scrollIntoView(node, pos); }; }); }, 'dojo/fx':function(){ define([ "./_base/lang", "./Evented", "./_base/kernel", "./_base/array", "./_base/connect", "./_base/fx", "./dom", "./dom-style", "./dom-geometry", "./ready", "require" // for context sensitive loading of Toggler ], function(lang, Evented, dojo, arrayUtil, connect, baseFx, dom, domStyle, geom, ready, require) { // module: // dojo/fx // summary: // TODOC /*===== dojo.fx = { // summary: Effects library on top of Base animations }; var coreFx = dojo.fx; =====*/ // For back-compat, remove in 2.0. if(!dojo.isAsync){ ready(0, function(){ var requires = ["./fx/Toggler"]; require(requires); // use indirection so modules not rolled into a build }); } var coreFx = dojo.fx = {}; var _baseObj = { _fire: function(evt, args){ if(this[evt]){ this[evt].apply(this, args||[]); } return this; } }; var _chain = function(animations){ this._index = -1; this._animations = animations||[]; this._current = this._onAnimateCtx = this._onEndCtx = null; this.duration = 0; arrayUtil.forEach(this._animations, function(a){ this.duration += a.duration; if(a.delay){ this.duration += a.delay; } }, this); }; _chain.prototype = new Evented(); lang.extend(_chain, { _onAnimate: function(){ this._fire("onAnimate", arguments); }, _onEnd: function(){ connect.disconnect(this._onAnimateCtx); connect.disconnect(this._onEndCtx); this._onAnimateCtx = this._onEndCtx = null; if(this._index + 1 == this._animations.length){ this._fire("onEnd"); }else{ // switch animations this._current = this._animations[++this._index]; this._onAnimateCtx = connect.connect(this._current, "onAnimate", this, "_onAnimate"); this._onEndCtx = connect.connect(this._current, "onEnd", this, "_onEnd"); this._current.play(0, true); } }, play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){ if(!this._current){ this._current = this._animations[this._index = 0]; } if(!gotoStart && this._current.status() == "playing"){ return this; } var beforeBegin = connect.connect(this._current, "beforeBegin", this, function(){ this._fire("beforeBegin"); }), onBegin = connect.connect(this._current, "onBegin", this, function(arg){ this._fire("onBegin", arguments); }), onPlay = connect.connect(this._current, "onPlay", this, function(arg){ this._fire("onPlay", arguments); connect.disconnect(beforeBegin); connect.disconnect(onBegin); connect.disconnect(onPlay); }); if(this._onAnimateCtx){ connect.disconnect(this._onAnimateCtx); } this._onAnimateCtx = connect.connect(this._current, "onAnimate", this, "_onAnimate"); if(this._onEndCtx){ connect.disconnect(this._onEndCtx); } this._onEndCtx = connect.connect(this._current, "onEnd", this, "_onEnd"); this._current.play.apply(this._current, arguments); return this; }, pause: function(){ if(this._current){ var e = connect.connect(this._current, "onPause", this, function(arg){ this._fire("onPause", arguments); connect.disconnect(e); }); this._current.pause(); } return this; }, gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){ this.pause(); var offset = this.duration * percent; this._current = null; arrayUtil.some(this._animations, function(a){ if(a.duration <= offset){ this._current = a; return true; } offset -= a.duration; return false; }); if(this._current){ this._current.gotoPercent(offset / this._current.duration, andPlay); } return this; }, stop: function(/*boolean?*/ gotoEnd){ if(this._current){ if(gotoEnd){ for(; this._index + 1 < this._animations.length; ++this._index){ this._animations[this._index].stop(true); } this._current = this._animations[this._index]; } var e = connect.connect(this._current, "onStop", this, function(arg){ this._fire("onStop", arguments); connect.disconnect(e); }); this._current.stop(); } return this; }, status: function(){ return this._current ? this._current.status() : "stopped"; }, destroy: function(){ if(this._onAnimateCtx){ connect.disconnect(this._onAnimateCtx); } if(this._onEndCtx){ connect.disconnect(this._onEndCtx); } } }); lang.extend(_chain, _baseObj); coreFx.chain = /*===== dojo.fx.chain = =====*/ function(/*dojo.Animation[]*/ animations){ // summary: // Chain a list of `dojo.Animation`s to run in sequence // // description: // Return a `dojo.Animation` which will play all passed // `dojo.Animation` instances in sequence, firing its own // synthesized events simulating a single animation. (eg: // onEnd of this animation means the end of the chain, // not the individual animations within) // // example: // Once `node` is faded out, fade in `otherNode` // | dojo.fx.chain([ // | dojo.fadeIn({ node:node }), // | dojo.fadeOut({ node:otherNode }) // | ]).play(); // return new _chain(animations); // dojo.Animation }; var _combine = function(animations){ this._animations = animations||[]; this._connects = []; this._finished = 0; this.duration = 0; arrayUtil.forEach(animations, function(a){ var duration = a.duration; if(a.delay){ duration += a.delay; } if(this.duration < duration){ this.duration = duration; } this._connects.push(connect.connect(a, "onEnd", this, "_onEnd")); }, this); this._pseudoAnimation = new baseFx.Animation({curve: [0, 1], duration: this.duration}); var self = this; arrayUtil.forEach(["beforeBegin", "onBegin", "onPlay", "onAnimate", "onPause", "onStop", "onEnd"], function(evt){ self._connects.push(connect.connect(self._pseudoAnimation, evt, function(){ self._fire(evt, arguments); } )); } ); }; lang.extend(_combine, { _doAction: function(action, args){ arrayUtil.forEach(this._animations, function(a){ a[action].apply(a, args); }); return this; }, _onEnd: function(){ if(++this._finished > this._animations.length){ this._fire("onEnd"); } }, _call: function(action, args){ var t = this._pseudoAnimation; t[action].apply(t, args); }, play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){ this._finished = 0; this._doAction("play", arguments); this._call("play", arguments); return this; }, pause: function(){ this._doAction("pause", arguments); this._call("pause", arguments); return this; }, gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){ var ms = this.duration * percent; arrayUtil.forEach(this._animations, function(a){ a.gotoPercent(a.duration < ms ? 1 : (ms / a.duration), andPlay); }); this._call("gotoPercent", arguments); return this; }, stop: function(/*boolean?*/ gotoEnd){ this._doAction("stop", arguments); this._call("stop", arguments); return this; }, status: function(){ return this._pseudoAnimation.status(); }, destroy: function(){ arrayUtil.forEach(this._connects, connect.disconnect); } }); lang.extend(_combine, _baseObj); coreFx.combine = /*===== dojo.fx.combine = =====*/ function(/*dojo.Animation[]*/ animations){ // summary: // Combine a list of `dojo.Animation`s to run in parallel // // description: // Combine an array of `dojo.Animation`s to run in parallel, // providing a new `dojo.Animation` instance encompasing each // animation, firing standard animation events. // // example: // Fade out `node` while fading in `otherNode` simultaneously // | dojo.fx.combine([ // | dojo.fadeIn({ node:node }), // | dojo.fadeOut({ node:otherNode }) // | ]).play(); // // example: // When the longest animation ends, execute a function: // | var anim = dojo.fx.combine([ // | dojo.fadeIn({ node: n, duration:700 }), // | dojo.fadeOut({ node: otherNode, duration: 300 }) // | ]); // | dojo.connect(anim, "onEnd", function(){ // | // overall animation is done. // | }); // | anim.play(); // play the animation // return new _combine(animations); // dojo.Animation }; coreFx.wipeIn = /*===== dojo.fx.wipeIn = =====*/ function(/*Object*/ args){ // summary: // Expand a node to it's natural height. // // description: // Returns an animation that will expand the // node defined in 'args' object from it's current height to // it's natural height (with no scrollbar). // Node must have no margin/border/padding. // // args: Object // A hash-map of standard `dojo.Animation` constructor properties // (such as easing: node: duration: and so on) // // example: // | dojo.fx.wipeIn({ // | node:"someId" // | }).play() var node = args.node = dom.byId(args.node), s = node.style, o; var anim = baseFx.animateProperty(lang.mixin({ properties: { height: { // wrapped in functions so we wait till the last second to query (in case value has changed) start: function(){ // start at current [computed] height, but use 1px rather than 0 // because 0 causes IE to display the whole panel o = s.overflow; s.overflow = "hidden"; if(s.visibility == "hidden" || s.display == "none"){ s.height = "1px"; s.display = ""; s.visibility = ""; return 1; }else{ var height = domStyle.get(node, "height"); return Math.max(height, 1); } }, end: function(){ return node.scrollHeight; } } } }, args)); var fini = function(){ s.height = "auto"; s.overflow = o; }; connect.connect(anim, "onStop", fini); connect.connect(anim, "onEnd", fini); return anim; // dojo.Animation }; coreFx.wipeOut = /*===== dojo.fx.wipeOut = =====*/ function(/*Object*/ args){ // summary: // Shrink a node to nothing and hide it. // // description: // Returns an animation that will shrink node defined in "args" // from it's current height to 1px, and then hide it. // // args: Object // A hash-map of standard `dojo.Animation` constructor properties // (such as easing: node: duration: and so on) // // example: // | dojo.fx.wipeOut({ node:"someId" }).play() var node = args.node = dom.byId(args.node), s = node.style, o; var anim = baseFx.animateProperty(lang.mixin({ properties: { height: { end: 1 // 0 causes IE to display the whole panel } } }, args)); connect.connect(anim, "beforeBegin", function(){ o = s.overflow; s.overflow = "hidden"; s.display = ""; }); var fini = function(){ s.overflow = o; s.height = "auto"; s.display = "none"; }; connect.connect(anim, "onStop", fini); connect.connect(anim, "onEnd", fini); return anim; // dojo.Animation }; coreFx.slideTo = /*===== dojo.fx.slideTo = =====*/ function(/*Object*/ args){ // summary: // Slide a node to a new top/left position // // description: // Returns an animation that will slide "node" // defined in args Object from its current position to // the position defined by (args.left, args.top). // // args: Object // A hash-map of standard `dojo.Animation` constructor properties // (such as easing: node: duration: and so on). Special args members // are `top` and `left`, which indicate the new position to slide to. // // example: // | .slideTo({ node: node, left:"40", top:"50", units:"px" }).play() var node = args.node = dom.byId(args.node), top = null, left = null; var init = (function(n){ return function(){ var cs = domStyle.getComputedStyle(n); var pos = cs.position; top = (pos == 'absolute' ? n.offsetTop : parseInt(cs.top) || 0); left = (pos == 'absolute' ? n.offsetLeft : parseInt(cs.left) || 0); if(pos != 'absolute' && pos != 'relative'){ var ret = geom.position(n, true); top = ret.y; left = ret.x; n.style.position="absolute"; n.style.top=top+"px"; n.style.left=left+"px"; } }; })(node); init(); var anim = baseFx.animateProperty(lang.mixin({ properties: { top: args.top || 0, left: args.left || 0 } }, args)); connect.connect(anim, "beforeBegin", anim, init); return anim; // dojo.Animation }; return coreFx; }); }, 'dijit/_base':function(){ define("dijit/_base", [ ".", "./a11y", // used to be in dijit/_base/manager "./WidgetSet", // used to be in dijit/_base/manager "./_base/focus", "./_base/manager", "./_base/place", "./_base/popup", "./_base/scroll", "./_base/sniff", "./_base/typematic", "./_base/wai", "./_base/window" ], function(dijit){ // module: // dijit/_base // summary: // Includes all the modules in dijit/_base return dijit._base; }); }, 'dojox/mobile/sniff':function(){ define("dojox/mobile/sniff", [ "dojo/_base/window", "dojo/_base/sniff" ], function(win, has){ var ua = navigator.userAgent; // BlackBerry (OS 6 or later only) has.add("bb", ua.indexOf("BlackBerry") >= 0 && parseFloat(ua.split("Version/")[1]) || undefined, undefined, true); // Android has.add("android", parseFloat(ua.split("Android ")[1]) || undefined, undefined, true); // iPhone, iPod, or iPad // If iPod or iPad is detected, in addition to has("ipod") or has("ipad"), // has("iphone") will also have iOS version number. if(ua.match(/(iPhone|iPod|iPad)/)){ var p = RegExp.$1.replace(/P/, 'p'); var v = ua.match(/OS ([\d_]+)/) ? RegExp.$1 : "1"; var os = parseFloat(v.replace(/_/, '.').replace(/_/g, '')); has.add(p, os, undefined, true); has.add("iphone", os, undefined, true); } if(has("webkit")){ has.add("touch", (typeof win.doc.documentElement.ontouchstart != "undefined" && navigator.appVersion.indexOf("Mobile") != -1) || !!has("android"), undefined, true); } return has; }); }, 'dojox/mobile/ProgressIndicator':function(){ define("dojox/mobile/ProgressIndicator", [ "dojo/_base/config", "dojo/_base/declare", "dojo/dom-construct", "dojo/dom-style", "dojo/has" ], function(config, declare, domConstruct, domStyle, has){ // module: // dojox/mobile/ProgressIndicator // summary: // A progress indication widget. var cls = declare("dojox.mobile.ProgressIndicator", null, { // summary: // A progress indication widget. // description: // ProgressIndicator is a round spinning graphical representation // that indicates the current task is on-going. // interval: Number // The time interval in milliseconds for updating the spinning // indicator. interval: 100, // colors: Array // An array of indicator colors. colors: [ "#C0C0C0", "#C0C0C0", "#C0C0C0", "#C0C0C0", "#C0C0C0", "#C0C0C0", "#B8B9B8", "#AEAFAE", "#A4A5A4", "#9A9A9A", "#8E8E8E", "#838383" ], constructor: function(){ this._bars = []; this.domNode = domConstruct.create("DIV"); this.domNode.className = "mblProgContainer"; if(config["mblAndroidWorkaround"] !== false && has("android") >= 2.2 && has("android") < 3){ // workaround to avoid the side effects of the fixes for android screen flicker problem domStyle.set(this.domNode, "webkitTransform", "translate3d(0,0,0)"); } this.spinnerNode = domConstruct.create("DIV", null, this.domNode); for(var i = 0; i < this.colors.length; i++){ var div = domConstruct.create("DIV", {className:"mblProg mblProg"+i}, this.spinnerNode); this._bars.push(div); } }, start: function(){ // summary: // Starts the ProgressIndicator spinning. if(this.imageNode){ var img = this.imageNode; var l = Math.round((this.domNode.offsetWidth - img.offsetWidth) / 2); var t = Math.round((this.domNode.offsetHeight - img.offsetHeight) / 2); img.style.margin = t+"px "+l+"px"; return; } var cntr = 0; var _this = this; var n = this.colors.length; this.timer = setInterval(function(){ cntr--; cntr = cntr < 0 ? n - 1 : cntr; var c = _this.colors; for(var i = 0; i < n; i++){ var idx = (cntr + i) % n; _this._bars[i].style.backgroundColor = c[idx]; } }, this.interval); }, stop: function(){ // summary: // Stops the ProgressIndicator spinning. if(this.timer){ clearInterval(this.timer); } this.timer = null; if(this.domNode.parentNode){ this.domNode.parentNode.removeChild(this.domNode); } }, setImage: function(/*String*/file){ // summary: // Sets an indicator icon image file (typically animated GIF). // If null is specified, restores the default spinner. if(file){ this.imageNode = domConstruct.create("IMG", {src:file}, this.domNode); this.spinnerNode.style.display = "none"; }else{ if(this.imageNode){ this.domNode.removeChild(this.imageNode); this.imageNode = null; } this.spinnerNode.style.display = ""; } } }); cls._instance = null; cls.getInstance = function(){ if(!cls._instance){ cls._instance = new cls(); } return cls._instance; }; return cls; }); }, 'dijit/form/_FormWidgetMixin':function(){ define("dijit/form/_FormWidgetMixin", [ "dojo/_base/array", // array.forEach "dojo/_base/declare", // declare "dojo/dom-attr", // domAttr.set "dojo/dom-style", // domStyle.get "dojo/_base/lang", // lang.hitch lang.isArray "dojo/mouse", // mouse.isLeft "dojo/_base/sniff", // has("webkit") "dojo/_base/window", // win.body "dojo/window", // winUtils.scrollIntoView "../a11y" // a11y.hasDefaultTabStop ], function(array, declare, domAttr, domStyle, lang, mouse, has, win, winUtils, a11y){ // module: // dijit/form/_FormWidgetMixin // summary: // Mixin for widgets corresponding to native HTML elements such as or