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 `