require({cache:{ 'dojo/uacss':function(){ define(["./dom-geometry", "./_base/lang", "./ready", "./sniff", "./_base/window"], function(geometry, lang, ready, has, baseWindow){ // module: // dojo/uacss /*===== return { // 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. // // Returns the has() method. }; =====*/ 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("dojox/mobile/app/_Widget", ["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("dojox/mobile/app/ImageThumbView", ["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, { // summary: // A class used to trigger view transitions. constructor: function(/*DomNode*/target, /*Object*/transitionOptions, /*Event?*/triggerEvent){ // summary: // Creates a transition event. // target: // The DOM node that initiates the transition (for example a ListItem). // transitionOptions: // Contains the transition options. // triggerEvent: // The event that triggered the transition (for example a touch event on a ListItem). this.transitionOptions=transitionOptions; this.target = target; this.triggerEvent=triggerEvent||null; }, dispatch: function(){ // summary: // Dispatches this transition event. Emits a "startTransition" event on the target. 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){ // summary: // Called when the transition ends. Emits a "endTransition" event on the target. 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/_base/Deferred", "dojo/dom", "dojo/dom-class", "dojo/dom-construct", "dojo/on", "dojo/ready", "dijit/registry", "./ProgressIndicator", "./TransitionEvent", "./viewRegistry" ], function(dojo, array, connect, declare, lang, win, Deferred, dom, domClass, domConstruct, on, ready, registry, ProgressIndicator, TransitionEvent, viewRegistry){ // module: // dojox/mobile/ViewController var Controller = declare("dojox.mobile.ViewController", null, { // summary: // A singleton class that controls 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, the view content is // retrieved and parsed to create a new target view. // dataHandlerClass: Object // The data handler class used to load external views, // by default "dojox/mobile/dh/DataHandler" // (see the Data Handlers page in the reference documentation). dataHandlerClass: "dojox/mobile/dh/DataHandler", // dataSourceClass: Object // The data source class used to load external views, // by default "dojox/mobile/dh/UrlDataSource" // (see the Data Handlers page in the reference documentation). dataSourceClass: "dojox/mobile/dh/UrlDataSource", // fileTypeMapClass: Object // The file type map class used to load external views, // by default "dojox/mobile/dh/SuffixFileTypeMap" // (see the Data Handlers page in the reference documentation). fileTypeMapClass: "dojox/mobile/dh/SuffixFileTypeMap", constructor: function(){ // summary: // Creates a new instance of the class. // tags: // private this.viewMap = {}; ready(lang.hitch(this, function(){ on(win.body(), "startTransition", lang.hitch(this, "onStartTransition")); })); }, findTransitionViews: function(/*String*/moveTo){ // summary: // Parses the moveTo argument and determines a starting view and a destination view. // returns: Array // An array containing the currently showing view, the destination view // and the transition parameters, or an empty array if the moveTo argument // could not be parsed. if(!moveTo){ return []; } // removes a leading hash mark (#) and params if exists // ex. "#bar&myParam=0003" -> "bar" moveTo.match(/^#?([^&?]+)(.*)/); var params = RegExp.$2; var view = registry.byId(RegExp.$1); if(!view){ return []; } for(var v = view.getParent(); v; v = v.getParent()){ // search for the topmost invisible parent node if(v.isVisible && !v.isVisible()){ var sv = view.getShowingView(); if(sv && sv.id !== view.id){ view.show(); } view = v; } } return [view.getShowingView(), view, params]; // fromView, toView, params }, openExternalView: function(/*Object*/ transOpts, /*DomNode*/ target){ // summary: // Loads an external view and performs a transition to it. // returns: dojo/_base/Deferred // Deferred object that resolves when the external view is // ready and a transition starts. Note that it resolves before // the transition is complete. // description: // This method loads external view content through the // dojox/mobile data handlers, creates a new View instance with // the loaded content, and performs a view transition to the // new view. The external view content can be specified with // the url property of transOpts. The new view is created under // a DOM node specified by target. // // example: // This example loads view1.html, creates a new view under // ``, and performs a transition to the new view with the // slide animation. // // | var vc = ViewController.getInstance(); // | vc.openExternalView({ // | url: "view1.html", // | transition: "slide" // | }, win.body()); // // // example: // If you want to perform a view transition without animation, // you can give transition:"none" to transOpts. // // | var vc = ViewController.getInstance(); // | vc.openExternalView({ // | url: "view1.html", // | transition: "none" // | }, win.body()); // // example: // If you want to dynamically create an external view, but do // not want to perform a view transition to it, you can give noTransition:true to transOpts. // This may be useful when you want to preload external views before the user starts using them. // // | var vc = ViewController.getInstance(); // | vc.openExternalView({ // | url: "view1.html", // | noTransition: true // | }, win.body()); // // example: // To do something when the external view is ready: // // | var vc = ViewController.getInstance(); // | Deferred.when(vc.openExternalView({...}, win.body()), function(){ // | doSomething(); // | }); var d = new Deferred(); var id = this.viewMap[transOpts.url]; if(id){ transOpts.moveTo = id; if(transOpts.noTransition){ registry.byId(id).hide(); }else{ new TransitionEvent(win.body(), transOpts).dispatch(); } d.resolve(true); return d; } // if a fixed bottom bar exists, a new view should be placed before it. var refNode = null; for(var i = target.childNodes.length - 1; i >= 0; i--){ var c = target.childNodes[i]; if(c.nodeType === 1){ var fixed = c.getAttribute("fixed") || (registry.byNode(c) && registry.byNode(c).fixed); if(fixed === "bottom"){ refNode = c; break; } } } var dh = transOpts.dataHandlerClass || this.dataHandlerClass; var ds = transOpts.dataSourceClass || this.dataSourceClass; var ft = transOpts.fileTypeMapClass || this.fileTypeMapClass; require([dh, ds, ft], lang.hitch(this, function(DataHandler, DataSource, FileTypeMap){ var handler = new DataHandler(new DataSource(transOpts.data || transOpts.url), target, refNode); var contentType = transOpts.contentType || FileTypeMap.getContentType(transOpts.url) || "html"; handler.processData(contentType, lang.hitch(this, function(id){ if(id){ this.viewMap[transOpts.url] = transOpts.moveTo = id; if(transOpts.noTransition){ registry.byId(id).hide(); }else{ new TransitionEvent(win.body(), transOpts).dispatch(); } d.resolve(true); }else{ d.reject("Failed to load "+transOpts.url); } })); })); return d; }, onStartTransition: function(evt){ // summary: // A handler that performs view transition. evt.preventDefault(); if(!evt.detail){ return; } var detail = evt.detail; if(!detail.moveTo && !detail.href && !detail.url && !detail.scene){ return; } if(detail.url && !detail.moveTo){ var urlTarget = detail.urlTarget; var w = registry.byId(urlTarget); var target = w && w.containerNode || dom.byId(urlTarget); if(!target){ w = viewRegistry.getEnclosingView(evt.target); target = w && w.domNode.parentNode || win.body(); } this.openExternalView(detail, target); return; }else if(detail.href){ if(detail.hrefTarget){ win.global.open(detail.href, detail.hrefTarget); }else{ var view; // find top level visible view for(var v = viewRegistry.getEnclosingView(evt.target); v; v = viewRegistry.getParentView(v)){ view = v; } if(view){ view.performTransition(null, detail.transitionDir, detail.transition, evt.target, function(){location.href = detail.href;}); } } return; }else if(detail.scene){ connect.publish("/dojox/mobile/app/pushScene", [detail.scene]); return; } var arr = this.findTransitionViews(detail.moveTo), fromView = arr[0], toView = arr[1], params = arr[2]; if(!location.hash && !detail.hashchange){ viewRegistry.initialView = fromView; } if(detail.moveTo && toView){ detail.moveTo = (detail.moveTo.charAt(0) === '#' ? '#' + toView.id : toView.id) + params; } if(!fromView || (detail.moveTo && fromView === registry.byId(detail.moveTo.replace(/^#?([^&?]+).*/, "$1")))){ return; } var src = registry.getEnclosingWidget(evt.target); if(src && src.callback){ detail.context = src; detail.method = src.callback; } fromView.performTransition(detail); } }); Controller._instance = new Controller(); // singleton Controller.getInstance = function(){ return Controller._instance; }; return Controller; }); }, 'dojox/mobile/ToolBarButton':function(){ define("dojox/mobile/ToolBarButton", [ "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/window", "dojo/dom-class", "dojo/dom-construct", "dojo/dom-style", "./sniff", "./_ItemBase" ], function(declare, lang, win, domClass, domConstruct, domStyle, has, ItemBase){ // module: // dojox/mobile/ToolBarButton return declare("dojox.mobile.ToolBarButton", ItemBase, { // summary: // A button widget which is placed in the Heading widget. // description: // ToolBarButton is a button which is typically 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 state. selected: false, // arrow: String // Specifies "right" or "left" to be an arrow button. arrow: "", // light: Boolean // If true, this widget produces only a single `` node when it // has only an icon or only a label, and has no arrow. In that // case, you cannot have both icon and label, or arrow even if you // try to set them. light: true, // defaultColor: String // CSS class for the default color. // Note: If this button has an arrow (typically back buttons on iOS), // the class selector used for it is the value of defaultColor + "45". // For example, by default the arrow selector is "mblColorDefault45". defaultColor: "mblColorDefault", // selColor: String // CSS class for the selected color. // Note: If this button has an arrow (typically back buttons on iOS), // the class selector used for it is the value of selColor + "45". // For example, by default the selected arrow selector is "mblColorDefaultSel45". selColor: "mblColorDefaultSel", /* internal properties */ baseClass: "mblToolBarButton", _selStartMethod: "touch", _selEndMethod: "touch", buildRendering: function(){ if(!this.label && this.srcNodeRef){ this.label = this.srcNodeRef.innerHTML; } this.label = lang.trim(this.label); this.domNode = (this.srcNodeRef && this.srcNodeRef.tagName === "SPAN") ? this.srcNodeRef : domConstruct.create("span"); this.inherited(arguments); if(this.light && !this.arrow && (!this.icon || !this.label)){ this.labelNode = this.tableNode = this.bodyNode = this.iconParentNode = this.domNode; domClass.add(this.domNode, this.defaultColor + " mblToolBarButtonBody" + (this.icon ? " mblToolBarButtonLightIcon" : " mblToolBarButtonLightText")); return; } this.domNode.innerHTML = ""; if(this.arrow === "left" || this.arrow === "right"){ this.arrowNode = domConstruct.create("span", { className: "mblToolBarButtonArrow mblToolBarButton" + (this.arrow === "left" ? "Left" : "Right") + "Arrow " + (has("ie") ? "" : (this.defaultColor + " " + this.defaultColor + "45")) }, this.domNode); domClass.add(this.domNode, "mblToolBarButtonHas" + (this.arrow === "left" ? "Left" : "Right") + "Arrow"); } this.bodyNode = domConstruct.create("span", {className:"mblToolBarButtonBody"}, this.domNode); this.tableNode = domConstruct.create("table", {cellPadding:"0",cellSpacing:"0",border:"0"}, this.bodyNode); var row = this.tableNode.insertRow(-1); this.iconParentNode = row.insertCell(-1); this.labelNode = row.insertCell(-1); this.iconParentNode.className = "mblToolBarButtonIcon"; this.labelNode.className = "mblToolBarButtonLabel"; if(this.icon && this.icon !== "none" && this.label){ domClass.add(this.domNode, "mblToolBarButtonHasIcon"); domClass.add(this.bodyNode, "mblToolBarButtonLabeledIcon"); } domClass.add(this.bodyNode, this.defaultColor); }, startup: function(){ if(this._started){ return; } this._keydownHandle = this.connect(this.domNode, "onkeydown", "_onClick"); // for desktop browsers this.inherited(arguments); if(!this._isOnLine){ this._isOnLine = true; this.set("icon", this.icon); // retry applying the attribute } }, _onClick: function(e){ // summary: // Internal handler for click events. // tags: // private if(e && e.type === "keydown" && e.keyCode !== 13){ return; } if(this.onClick(e) === false){ return; } // user's click action this.defaultClickAction(e); }, onClick: function(/*Event*/ /*===== e =====*/){ // summary: // User defined function to handle clicks // tags: // callback }, _setLabelAttr: function(/*String*/text){ // summary: // Sets the button label text. this.inherited(arguments); domClass.toggle(this.tableNode, "mblToolBarButtonText", text); }, _setSelectedAttr: function(/*Boolean*/selected){ // summary: // Makes this widget in the selected or unselected state. var replace = function(node, a, b){ domClass.replace(node, a + " " + a + "45", b + " " + b + "45"); } this.inherited(arguments); if(selected){ domClass.replace(this.bodyNode, this.selColor, this.defaultColor); if(!has("ie") && this.arrowNode){ replace(this.arrowNode, this.selColor, this.defaultColor); } }else{ domClass.replace(this.bodyNode, this.defaultColor, this.selColor); if(!has("ie") && this.arrowNode){ replace(this.arrowNode, this.defaultColor, this.selColor); } } domClass.toggle(this.domNode, "mblToolBarButtonSelected", selected); domClass.toggle(this.bodyNode, "mblToolBarButtonBodySelected", selected); } }); }); }, 'dojox/mobile/_ItemBase':function(){ define("dojox/mobile/_ItemBase", [ "dojo/_base/array", "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/window", "dojo/dom-class", "dojo/touch", "dijit/registry", "dijit/_Contained", "dijit/_Container", "dijit/_WidgetBase", "./TransitionEvent", "./iconUtils" ], function(array, declare, lang, win, domClass, touch, registry, Contained, Container, WidgetBase, TransitionEvent, iconUtils){ // module: // dojox/mobile/_ItemBase 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 alternate 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: "", // back: Boolean // If true, history.back() is called when clicked. back: false, // 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", "cube", and "swap". 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, // 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, // selected: Boolean // If true, the item is highlighted to indicate it is selected. selected: false, // tabIndex: String // Tabindex setting for the item so users can hit the tab key to // focus on it. tabIndex: "0", // _setTabIndexAttr: [private] String // Sets tabIndex to domNode. _setTabIndexAttr: "", /* internal properties */ // paramsToInherit: String // Comma separated parameters to inherit from the parent. paramsToInherit: "transition,icon", // _selStartMethod: String // Specifies how the item enters the selected state. // // - "touch": Use touch events to enter the selected state. // - "none": Do not change the selected state. _selStartMethod: "none", // touch or none // _selEndMethod: String // Specifies how the item leaves the selected state. // // - "touch": Use touch events to leave the selected state. // - "timer": Use setTimeout to leave the selected state. // - "none": Do not change the selected state. _selEndMethod: "none", // touch, timer, or none // _delayedSelection: Boolean // If true, selection is delayed 100ms and canceled if dragged in // order to avoid selection when flick operation is performed. _delayedSelection: false, // _duration: Number // Duration of selection, milliseconds. _duration: 800, // _handleClick: Boolean // If true, this widget listens to touch events. _handleClick: true, buildRendering: function(){ this.inherited(arguments); this._isOnLine = this.inheritParams(); }, startup: function(){ if(this._started){ return; } if(!this._isOnLine){ this.inheritParams(); } if(this._handleClick && this._selStartMethod === "touch"){ this._onTouchStartHandle = this.connect(this.domNode, touch.press, "_onTouchStart"); } this.inherited(arguments); }, inheritParams: function(){ // summary: // Copies from the parent the values of parameters specified // by the property paramsToInherit. var parent = this.getParent(); if(parent){ array.forEach(this.paramsToInherit.split(/,/), function(p){ if(p.match(/icon/i)){ var base = p + "Base", pos = p + "Pos"; if(this[p] && parent[base] && parent[base].charAt(parent[base].length - 1) === '/'){ this[p] = parent[base] + this[p]; } if(!this[p]){ this[p] = parent[base]; } if(!this[pos]){ this[pos] = parent[pos]; } } if(!this[p]){ this[p] = parent[p]; } }, this); } return !!parent; }, getTransOpts: function(){ // summary: // Copies from the parent and returns the values of parameters // specified by the property paramsToInherit. var opts = this.transitionOptions || {}; array.forEach(["moveTo", "href", "hrefTarget", "url", "target", "urlTarget", "scene", "transition", "transitionDir"], function(p){ opts[p] = opts[p] || this[p]; }, this); return opts; // Object }, userClickAction: function(/*Event*/ /*===== e =====*/){ // summary: // User-defined click action. }, defaultClickAction: function(/*Event*/e){ // summary: // The default action of this item. this.handleSelection(e); if(this.userClickAction(e) === false){ return; } // user's click action this.makeTransition(e); }, handleSelection: function(/*Event*/e){ // summary: // Handles this items selection state. if(this._onTouchEndHandle){ this.disconnect(this._onTouchEndHandle); this._onTouchEndHandle = null; } var p = this.getParent(); if(this.toggle){ this.set("selected", !this._currentSel); }else if(p && p.selectOne){ this.set("selected", true); }else{ if(this._selEndMethod === "touch"){ this.set("selected", false); }else if(this._selEndMethod === "timer"){ var _this = this; this.defer(function(){ _this.set("selected", false); }, this._duration); } } }, makeTransition: function(/*Event*/e){ // summary: // Makes a transition. if(this.back && history){ history.back(); return; } if (this.href && this.hrefTarget) { win.global.open(this.href, this.hrefTarget || "_blank"); this._onNewWindowOpened(e); return; } var opts = this.getTransOpts(); var doTransition = !!(opts.moveTo || opts.href || opts.url || opts.target || opts.scene); if(this._prepareForTransition(e, doTransition ? opts : null) === false){ return; } if(doTransition){ this.setTransitionPos(e); new TransitionEvent(this.domNode, opts, e).dispatch(); } }, _onNewWindowOpened: function(/*Event*/ /*===== e =====*/){ // summary: // Subclasses may want to implement it. }, _prepareForTransition: function(/*Event*/e, /*Object*/transOpts){ // summary: // Subclasses may want to implement it. }, _onTouchStart: function(e){ // tags: // private if(this.getParent().isEditing || this.onTouchStart(e) === false){ return; } // user's touchStart action if(!this._onTouchEndHandle && this._selStartMethod === "touch"){ // Connect to the entire window. Otherwise, fail to receive // events if operation is performed outside this widget. // Expose both connect handlers in case the user has interest. this._onTouchMoveHandle = this.connect(win.body(), touch.move, "_onTouchMove"); this._onTouchEndHandle = this.connect(win.body(), touch.release, "_onTouchEnd"); } this.touchStartX = e.touches ? e.touches[0].pageX : e.clientX; this.touchStartY = e.touches ? e.touches[0].pageY : e.clientY; this._currentSel = this.selected; if(this._delayedSelection){ // so as not to make selection when the user flicks on ScrollableView this._selTimer = setTimeout(lang.hitch(this, function(){ this.set("selected", true); }), 100); }else{ this.set("selected", true); } }, onTouchStart: function(/*Event*/ /*===== e =====*/){ // summary: // User-defined function to handle touchStart events. // tags: // callback }, _onTouchMove: function(e){ // tags: // private var x = e.touches ? e.touches[0].pageX : e.clientX; var y = e.touches ? e.touches[0].pageY : e.clientY; if(Math.abs(x - this.touchStartX) >= 4 || Math.abs(y - this.touchStartY) >= 4){ // dojox/mobile/scrollable.threshold this.cancel(); var p = this.getParent(); if(p && p.selectOne){ this._prevSel && this._prevSel.set("selected", true); }else{ this.set("selected", false); } } }, _disconnect: function(){ // tags: // private this.disconnect(this._onTouchMoveHandle); this.disconnect(this._onTouchEndHandle); this._onTouchMoveHandle = this._onTouchEndHandle = null; }, cancel: function(){ // summary: // Cancels an ongoing selection (if any). if(this._selTimer){ clearTimeout(this._selTimer); this._selTimer = null; } this._disconnect(); }, _onTouchEnd: function(e){ // tags: // private if(!this._selTimer && this._delayedSelection){ return; } this.cancel(); this._onClick(e); }, setTransitionPos: function(e){ // summary: // Stores the clicked position for later use. // description: // Some of the transition animations (e.g. ScaleIn) need the // clicked position. var w = this; while(true){ w = w.getParent(); if(!w || domClass.contains(w.domNode, "mblView")){ break; } } if(w){ w.clickedPosX = e.clientX; w.clickedPosY = e.clientY; } }, transitionTo: function(/*String|Object*/moveTo, /*String*/href, /*String*/url, /*String*/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. var opts = (moveTo && typeof(moveTo) === "object") ? moveTo : {moveTo: moveTo, href: href, url: url, scene: scene, transition: this.transition, transitionDir: this.transitionDir}; new TransitionEvent(this.domNode, opts).dispatch(); }, _setIconAttr: function(icon){ // tags: // private if(!this._isOnLine){ return; } // icon may be invalid because inheritParams is not called yet this._set("icon", icon); this.iconNode = iconUtils.setIcon(icon, this.iconPos, this.iconNode, this.alt, this.iconParentNode, this.refNode, this.position); }, _setLabelAttr: function(/*String*/text){ // tags: // private this._set("label", text); this.labelNode.innerHTML = this._cv ? this._cv(text) : text; }, _setSelectedAttr: function(/*Boolean*/selected){ // summary: // Makes this widget in the selected or unselected state. // description: // Subclass should override. // tags: // private if(selected){ var p = this.getParent(); if(p && p.selectOne){ // deselect the currently selected item var arr = array.filter(p.getChildren(), function(w){ return w.selected; }); array.forEach(arr, function(c){ this._prevSel = c; c.set("selected", false); }, this); } } this._set("selected", selected); } }); }); }, 'dijit/hccss':function(){ define("dijit/hccss", ["dojo/dom-class", "dojo/hccss", "dojo/ready", "dojo/_base/window"], function(domClass, has, ready, win){ // module: // dijit/hccss /*===== return function(){ // summary: // Test if computer is in high contrast mode, and sets `dijit_a11y` flag on `` if it is. // Deprecated, use ``dojo/hccss`` instead. }; =====*/ // Priority is 90 to run ahead of parser priority of 100. For 2.0, remove the ready() call and instead // change this module to depend on dojo/domReady! ready(90, function(){ if(has("highcontrast")){ domClass.add(win.body(), "dijit_a11y"); } }); return has; }); }, 'dojox/mobile/Container':function(){ define("dojox/mobile/Container", [ "dojo/_base/declare", "dijit/_Container", "./Pane" ], function(declare, Container, Pane){ // module: // dojox/mobile/Container return declare("dojox.mobile.Container", [Pane, Container], { // summary: // A simple container-type widget. // description: // Container is a simple general-purpose container widget. // It is a widget, but can be regarded as a simple `
` element. // baseClass: String // The name of the CSS class of this widget. baseClass: "mblContainer" }); }); }, 'dijit/_Contained':function(){ define("dijit/_Contained", [ "dojo/_base/declare", // declare "./registry" // registry.getEnclosingWidget(), registry.byNode() ], function(declare, registry){ // module: // dijit/_Contained 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/_WidgetBase }, 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/_WidgetBase }, 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/_WidgetBase }, 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 "dojo/on", // on "../main" // for exporting dijit._setSelectionRange, dijit.selectInputText ], function(array, declare, dom, event, keys, lang, on, dijit){ // module: // dijit/form/_TextBoxMixin 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 /* and !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 /* or 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 /* or 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(/*Event*/ evt){ // 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._processInput(evt); }, _processInput: function(/*Event*/ evt){ // summary: // Default action handler for user input events 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 charOrCode; if(e.type == "keydown"){ charOrCode = e.keyCode; switch(charOrCode){ // ignore state keys case keys.SHIFT: case keys.ALT: case keys.CTRL: case keys.META: case keys.CAPS_LOCK: case keys.NUM_LOCK: case keys.SCROLL_LOCK: return; } if(!e.ctrlKey && !e.metaKey && !e.altKey){ // no modifiers switch(charOrCode){ // ignore location keys case keys.NUMPAD_0: case keys.NUMPAD_1: case keys.NUMPAD_2: case keys.NUMPAD_3: case keys.NUMPAD_4: case keys.NUMPAD_5: case keys.NUMPAD_6: case keys.NUMPAD_7: case keys.NUMPAD_8: case keys.NUMPAD_9: case keys.NUMPAD_MULTIPLY: case keys.NUMPAD_PLUS: case keys.NUMPAD_ENTER: case keys.NUMPAD_MINUS: case keys.NUMPAD_PERIOD: case keys.NUMPAD_DIVIDE: return; } if((charOrCode >= 65 && charOrCode <= 90) || (charOrCode >= 48 && charOrCode <= 57) || charOrCode == keys.SPACE){ return; // keypress will handle simple non-modified printable keys } var named = false; for(var i in keys){ if(keys[i] === e.keyCode){ named = true; break; } } if(!named){ return; } // only allow named ones through } } charOrCode = e.charCode >= 32 ? String.fromCharCode(e.charCode) : e.charCode; if(!charOrCode){ charOrCode = (e.keyCode >= 65 && e.keyCode <= 90) || (e.keyCode >= 48 && e.keyCode <= 57) || e.keyCode == keys.SPACE ? String.fromCharCode(e.keyCode) : e.keyCode; } if(!charOrCode){ charOrCode = 229; // IME } if(e.type == "keypress"){ if(typeof charOrCode != "string"){ return; } if((charOrCode >= 'a' && charOrCode <= 'z') || (charOrCode >= 'A' && charOrCode <= 'Z') || (charOrCode >= '0' && charOrCode <= '9') || (charOrCode === ' ')){ if(e.ctrlKey || e.metaKey || e.altKey){ return; } // can only be stopped reliably in keydown } } 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 = { faux: true }, attr; for(attr in e){ if(attr != "layerX" && attr != "layerY"){ // prevent WebKit warnings var v = e[attr]; if(typeof v != "function" && typeof v != "undefined"){ faux[attr] = v; } } } lang.mixin(faux, { charOrCode: charOrCode, _wasConsumed: false, preventDefault: function(){ faux._wasConsumed = true; e.preventDefault(); }, stopPropagation: function(){ e.stopPropagation(); } }); // give web page author a chance to consume the event //console.log(faux.type + ', charOrCode = (' + (typeof charOrCode) + ') ' + charOrCode + ', ctrl ' + !!faux.ctrlKey + ', alt ' + !!faux.altKey + ', meta ' + !!faux.metaKey + ', shift ' + !!faux.shiftKey); if(this.onInput(faux) === false){ // return false means stop faux.preventDefault(); faux.stopPropagation(); } if(faux._wasConsumed){ return; } // if preventDefault was called this.defer(function(){ this._onInput(faux); }); // widget notification after key has posted }; this.own(on(this.textbox, "keydown, keypress, paste, cut, input, compositionend", lang.hitch(this, handleEvent))); }, _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); }, _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); this._selectOnClickHandle = null; // 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); } }); // in case the mouseup never comes this.defer(function(){ if(this._selectOnClickHandle){ this.disconnect(this._selectOnClickHandle); this._selectOnClickHandle = null; } }, 500); // if mouseup not received soon, then treat it as some gesture } // 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("dojox/mobile/parser", [ "dojo/_base/kernel", "dojo/_base/array", "dojo/_base/config", "dojo/_base/lang", "dojo/_base/window", "dojo/ready" ], function(dojo, array, config, lang, win, ready){ // module: // dojox/mobile/parser var dm = lang.getObject("dojox.mobile", true); var Parser = function(){ // summary: // A lightweight parser. // description: // dojox/mobile/parser is an extremely small subset of dojo/parser. // It has no additional features over dojo/parser, so there is no // benefit in terms of features by using dojox/mobile/parser instead // of dojo/parser. However, if dojox/mobile/parser's capabilities are // enough for your application, using it could reduce the total code size. var _ctorMap = {}; var getCtor = function(type, mixins){ if(typeof(mixins) === "string"){ var t = type + ":" + mixins.replace(/ /g, ""); return _ctorMap[t] || (_ctorMap[t] = getCtor(type).createSubclass(array.map(mixins.split(/, */), getCtor))); } return _ctorMap[type] || (_ctorMap[type] = lang.getObject(type) || require(type)); }; var _eval = function(js){ return eval(js); }; this.instantiate = function(/* DomNode[] */nodes, /* Object? */mixin, /* Object? */options){ // summary: // Function for instantiating a list of widget nodes. // nodes: // The list of DomNodes to walk and instantiate widgets on. mixin = mixin || {}; options = options || {}; var i, ws = []; if(nodes){ for(i = 0; i < nodes.length; i++){ var n = nodes[i], type = n._type, ctor = getCtor(type, n.getAttribute("data-dojo-mixins")), proto = ctor.prototype, params = {}, prop, v, t; lang.mixin(params, _eval.call(options.propsThis, '({'+(n.getAttribute("data-dojo-props")||"")+'})')); lang.mixin(params, options.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(lang.isArray(proto[prop])){ params[prop] = v.split(/\s*,\s*/); }else 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 + ")"); }else if(t === "function"){ params[prop] = lang.getObject(v, false) || new Function(v); n.removeAttribute(prop); } } params["class"] = n.className; if(!params.style){ params.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 ctor(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]; !options.noStart && w.startup && !w._started && w.startup(); } } return ws; }; this.parse = function(/* DomNode */ rootNode, /* Object? */ options){ // 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(!options && rootNode.rootNode){ // Case where 'rootNode' is really a params object. options = rootNode; rootNode = rootNode.rootNode; } var nodes = rootNode.getElementsByTagName("*"); var i, j, list = []; for(i = 0; i < nodes.length; i++){ var n = nodes[i], type = (n._type = n.getAttribute("dojoType") || n.getAttribute("data-dojo-type")); if(type){ if(n._skip){ n._skip = ""; continue; } if(getCtor(type).prototype.stopParser && !(options && options.template)){ var arr = n.getElementsByTagName("*"); for(j = 0; j < arr.length; j++){ arr[j]._skip = "1"; } } list.push(n); } } var mixin = options && options.template ? {template: true} : null; return this.instantiate(list, mixin, options); }; }; // Singleton. (TODO: replace parser class and singleton w/a simple hash of functions) var parser = new Parser(); if(config.parseOnLoad){ ready(100, function(){ // Now that all the modules are loaded, check if the app loaded dojo/parser too. // If it did, let dojo/parser handle the parseOnLoad flag instead of me. try{ if(!require("dojo/parser")){ // IE6 takes this path when dojo/parser unavailable, rather than catch() block below, // due to http://support.microsoft.com/kb/944397 parser.parse(); } }catch(e){ // Other browsers (and later versions of IE) take this path when dojo/parser unavailable parser.parse(); } }); } dm.parser = parser; // for backward compatibility dojo.parser = 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 ], function(array, declare, domConstruct){ // module: // dijit/_Container return declare("dijit._Container", null, { // summary: // Mixin for widgets that contain HTML and/or a set of widget children. buildRendering: function(){ this.inherited(arguments); if(!this.containerNode){ // all widgets with descendants must set containerNode this.containerNode = this.domNode; } }, addChild: function(/*dijit/_WidgetBase*/ 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). // // Functionality is undefined if this widget contains anything besides // a list of child widgets (ie, if it contains arbitrary non-widget HTML). 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 (ie, removeChild(5) removes the sixth widget). 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 child widgets, i.e. if this.containerNode contains widgets. return this.getChildren().length > 0; // Boolean }, _getSiblingOfChild: function(/*dijit/_WidgetBase*/ 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 children = this.getChildren(), idx = array.indexOf(this.getChildren(), child); // int return children[idx + dir]; }, getIndexOfChild: function(/*dijit/_WidgetBase*/ 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("dojox/mobile/app/_base", ["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 "../main" // export symbol to dijit ], function(windowUtils, dijit){ // module: // dijit/_base/scroll /*===== return { // 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 // 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 = { // summary: // Effects library on top of Base animations }; 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 = function(/*dojo/_base/fx.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` // | fx.chain([ // | dojo.fadeIn({ node:node }), // | dojo.fadeOut({ node:otherNode }) // | ]).play(); // return new _chain(animations); // dojo/_base/fx.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 = function(/*dojo/_base/fx.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 // | fx.combine([ // | dojo.fadeIn({ node:node }), // | dojo.fadeOut({ node:otherNode }) // | ]).play(); // // example: // When the longest animation ends, execute a function: // | var anim = 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/_base/fx.Animation }; coreFx.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: // | 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/_base/fx.Animation }; coreFx.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: // | 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/_base/fx.Animation }; coreFx.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/_base/fx.Animation }; return coreFx; }); }, 'dijit/_base':function(){ define("dijit/_base", [ "./main", "./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 /*===== return { // 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 { // summary: // This module sets has() flags based on the userAgent of the current browser. }; =====*/ return has; }); }, 'dojox/mobile/ProgressIndicator':function(){ define([ "dojo/_base/config", "dojo/_base/declare", "dojo/_base/lang", "dojo/dom-class", "dojo/dom-construct", "dojo/dom-geometry", "dojo/dom-style", "dojo/has", "dijit/_Contained", "dijit/_WidgetBase" ], function(config, declare, lang, domClass, domConstruct, domGeometry, domStyle, has, Contained, WidgetBase){ // module: // dojox/mobile/ProgressIndicator var cls = declare("dojox.mobile.ProgressIndicator", [WidgetBase, Contained], { // summary: // A progress indication widget. // description: // ProgressIndicator is a round spinning graphical representation // that indicates the current task is ongoing. // interval: Number // The time interval in milliseconds for updating the spinning // indicator. interval: 100, // size: Number // The size of the indicator in pixels. size: 40, // removeOnStop: Boolean // If true, this widget is removed from the parent node // when stop() is called. removeOnStop: true, // startSpinning: Boolean // If true, calls start() to run the indicator at startup. startSpinning: false, // center: Boolean // If true, the indicator is displayed as center aligned. center: true, // colors: String[] // An array of indicator colors. 12 colors have to be given. // If colors are not specified, CSS styles // (mblProg0Color - mblProg11Color) are used. colors: null, /* internal properties */ // baseClass: String // The name of the CSS class of this widget. baseClass: "mblProgressIndicator", constructor: function(){ // summary: // Creates a new instance of the class. this.colors = []; this._bars = []; }, buildRendering: function(){ this.inherited(arguments); if(this.center){ domClass.add(this.domNode, "mblProgressIndicatorCenter"); } this.containerNode = domConstruct.create("div", {className:"mblProgContainer"}, this.domNode); this.spinnerNode = domConstruct.create("div", null, this.containerNode); for(var i = 0; i < 12; i++){ var div = domConstruct.create("div", {className:"mblProg mblProg"+i}, this.spinnerNode); this._bars.push(div); } this.scale(this.size); if(this.startSpinning){ this.start(); } }, scale: function(/*Number*/size){ // summary: // Changes the size of the indicator. // size: // The size of the indicator in pixels. var scale = size / 40; domStyle.set(this.containerNode, { webkitTransform: "scale(" + scale + ")", webkitTransformOrigin: "0 0" }); domGeometry.setMarginBox(this.domNode, {w:size, h:size}); domGeometry.setMarginBox(this.containerNode, {w:size / scale, h:size / scale}); }, start: function(){ // summary: // Starts the spinning of the ProgressIndicator. if(this.imageNode){ var img = this.imageNode; var l = Math.round((this.containerNode.offsetWidth - img.offsetWidth) / 2); var t = Math.round((this.containerNode.offsetHeight - img.offsetHeight) / 2); img.style.margin = t+"px "+l+"px"; return; } var cntr = 0; var _this = this; var n = 12; 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; if(c[idx]){ _this._bars[i].style.backgroundColor = c[idx]; }else{ domClass.replace(_this._bars[i], "mblProg" + idx + "Color", "mblProg" + (idx === n - 1 ? 0 : idx + 1) + "Color"); } } }, this.interval); }, stop: function(){ // summary: // Stops the spinning of the ProgressIndicator. if(this.timer){ clearInterval(this.timer); } this.timer = null; if(this.removeOnStop && this.domNode && 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.containerNode); this.spinnerNode.style.display = "none"; }else{ if(this.imageNode){ this.containerNode.removeChild(this.imageNode); this.imageNode = null; } this.spinnerNode.style.display = ""; } } }); cls._instance = null; cls.getInstance = function(props){ if(!cls._instance){ cls._instance = new cls(props); } 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/sniff", // has("webkit") "dojo/window", // winUtils.scrollIntoView "../a11y" // a11y.hasDefaultTabStop ], function(array, declare, domAttr, domStyle, lang, mouse, has, winUtils, a11y){ // module: // dijit/form/_FormWidgetMixin return declare("dijit.form._FormWidgetMixin", null, { // summary: // Mixin for widgets corresponding to native HTML elements such as `` or `