4555 lines
141 KiB
JavaScript
4555 lines
141 KiB
JavaScript
|
/*
|
||
|
Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
|
||
|
Available via Academic Free License >= 2.1 OR the modified BSD license.
|
||
|
see: http://dojotoolkit.org/license for details
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
This is an optimized version of Dojo, built for deployment and not for
|
||
|
development. To get sources and documentation, please visit:
|
||
|
|
||
|
http://dojotoolkit.org
|
||
|
*/
|
||
|
|
||
|
//>>built
|
||
|
require({cache:{
|
||
|
'dojox/mobile/ViewController':function(){
|
||
|
define([
|
||
|
"dojo/_base/kernel",
|
||
|
"dojo/_base/array",
|
||
|
"dojo/_base/connect",
|
||
|
"dojo/_base/declare",
|
||
|
"dojo/_base/lang",
|
||
|
"dojo/_base/window",
|
||
|
"dojo/dom",
|
||
|
"dojo/dom-class",
|
||
|
"dojo/dom-construct",
|
||
|
// "dojo/hash", // optionally prereq'ed
|
||
|
"dojo/on",
|
||
|
"dojo/ready",
|
||
|
"dijit/registry", // registry.byId
|
||
|
"./ProgressIndicator",
|
||
|
"./TransitionEvent"
|
||
|
], function(dojo, array, connect, declare, lang, win, dom, domClass, domConstruct, on, ready, registry, ProgressIndicator, TransitionEvent){
|
||
|
|
||
|
// module:
|
||
|
// dojox/mobile/ViewController
|
||
|
// summary:
|
||
|
// A singleton class that controlls view transition.
|
||
|
|
||
|
var dm = lang.getObject("dojox.mobile", true);
|
||
|
|
||
|
var Controller = declare("dojox.mobile.ViewController", null, {
|
||
|
// summary:
|
||
|
// A singleton class that controlls view transition.
|
||
|
// description:
|
||
|
// This class listens to the "startTransition" events and performs
|
||
|
// view transitions. If the transition destination is an external
|
||
|
// view specified with the url parameter, retrieves the view
|
||
|
// content and parses it to create a new target view.
|
||
|
|
||
|
constructor: function(){
|
||
|
this.viewMap={};
|
||
|
this.currentView=null;
|
||
|
this.defaultView=null;
|
||
|
ready(lang.hitch(this, function(){
|
||
|
on(win.body(), "startTransition", lang.hitch(this, "onStartTransition"));
|
||
|
}));
|
||
|
},
|
||
|
|
||
|
findCurrentView: function(moveTo,src){
|
||
|
// summary:
|
||
|
// Searches for the currently showing view.
|
||
|
if(moveTo){
|
||
|
var w = registry.byId(moveTo);
|
||
|
if(w && w.getShowingView){ return w.getShowingView(); }
|
||
|
}
|
||
|
if(dm.currentView){
|
||
|
return dm.currentView; //TODO:1.8 may not return an expected result especially when views are nested
|
||
|
}
|
||
|
//TODO:1.8 probably never reaches here
|
||
|
w = src;
|
||
|
while(true){
|
||
|
w = w.getParent();
|
||
|
if(!w){ return null; }
|
||
|
if(domClass.contains(w.domNode, "mblView")){ break; }
|
||
|
}
|
||
|
return w;
|
||
|
},
|
||
|
|
||
|
onStartTransition: function(evt){
|
||
|
// summary:
|
||
|
// A handler that performs view transition.
|
||
|
|
||
|
evt.preventDefault();
|
||
|
if(!evt.detail || (evt.detail && !evt.detail.moveTo && !evt.detail.href && !evt.detail.url && !evt.detail.scene)){ return; }
|
||
|
var w = this.findCurrentView(evt.detail.moveTo, (evt.target && evt.target.id)?registry.byId(evt.target.id):registry.byId(evt.target)); // the current view widget
|
||
|
if(!w || (evt.detail && evt.detail.moveTo && w === registry.byId(evt.detail.moveTo))){ return; }
|
||
|
if(evt.detail.href){
|
||
|
var t = registry.byId(evt.target.id).hrefTarget;
|
||
|
if(t){
|
||
|
dm.openWindow(evt.detail.href, t);
|
||
|
}else{
|
||
|
w.performTransition(null, evt.detail.transitionDir, evt.detail.transition, evt.target, function(){location.href = evt.detail.href;});
|
||
|
}
|
||
|
return;
|
||
|
} else if(evt.detail.scene){
|
||
|
connect.publish("/dojox/mobile/app/pushScene", [evt.detail.scene]);
|
||
|
return;
|
||
|
}
|
||
|
var moveTo = evt.detail.moveTo;
|
||
|
if(evt.detail.url){
|
||
|
var id;
|
||
|
if(dm._viewMap && dm._viewMap[evt.detail.url]){
|
||
|
// external view has already been loaded
|
||
|
id = dm._viewMap[evt.detail.url];
|
||
|
}else{
|
||
|
// get the specified external view and append it to the <body>
|
||
|
var text = this._text;
|
||
|
if(!text){
|
||
|
if(registry.byId(evt.target.id).sync){
|
||
|
// We do not add explicit dependency on dojo/_base/xhr to this module
|
||
|
// to be able to create a build that does not contain dojo/_base/xhr.
|
||
|
// User applications that do sync loading here need to explicitly
|
||
|
// require dojo/_base/xhr up front.
|
||
|
dojo.xhrGet({url:evt.detail.url, sync:true, load:function(result){
|
||
|
text = lang.trim(result);
|
||
|
}});
|
||
|
}else{
|
||
|
var s = "dojo/_base/xhr"; // assign to a variable so as not to be picked up by the build tool
|
||
|
require([s], lang.hitch(this, function(xhr){
|
||
|
var prog = ProgressIndicator.getInstance();
|
||
|
win.body().appendChild(prog.domNode);
|
||
|
prog.start();
|
||
|
var obj = xhr.get({
|
||
|
url: evt.detail.url,
|
||
|
handleAs: "text"
|
||
|
});
|
||
|
obj.addCallback(lang.hitch(this, function(response, ioArgs){
|
||
|
prog.stop();
|
||
|
if(response){
|
||
|
this._text = response;
|
||
|
new TransitionEvent(evt.target, {
|
||
|
transition: evt.detail.transition,
|
||
|
transitionDir: evt.detail.transitionDir,
|
||
|
moveTo: moveTo,
|
||
|
href: evt.detail.href,
|
||
|
url: evt.detail.url,
|
||
|
scene: evt.detail.scene},
|
||
|
evt.detail)
|
||
|
.dispatch();
|
||
|
}
|
||
|
}));
|
||
|
obj.addErrback(function(error){
|
||
|
prog.stop();
|
||
|
console.log("Failed to load "+evt.detail.url+"\n"+(error.description||error));
|
||
|
});
|
||
|
}));
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
this._text = null;
|
||
|
id = this._parse(text, registry.byId(evt.target.id).urlTarget);
|
||
|
if(!dm._viewMap){
|
||
|
dm._viewMap = [];
|
||
|
}
|
||
|
dm._viewMap[evt.detail.url] = id;
|
||
|
}
|
||
|
moveTo = id;
|
||
|
w = this.findCurrentView(moveTo,registry.byId(evt.target.id)) || w; // the current view widget
|
||
|
}
|
||
|
w.performTransition(moveTo, evt.detail.transitionDir, evt.detail.transition, null, null);
|
||
|
},
|
||
|
|
||
|
_parse: function(text, id){
|
||
|
// summary:
|
||
|
// Parses the given view content.
|
||
|
// description:
|
||
|
// If the content is html fragment, constructs dom tree with it
|
||
|
// and runs the parser. If the content is json data, passes it
|
||
|
// to _instantiate().
|
||
|
var container, view, i, j, len;
|
||
|
var currentView = this.findCurrentView();
|
||
|
var target = registry.byId(id) && registry.byId(id).containerNode
|
||
|
|| dom.byId(id)
|
||
|
|| currentView && currentView.domNode.parentNode
|
||
|
|| win.body();
|
||
|
// if a fixed bottom bar exists, a new view should be placed before it.
|
||
|
var refNode = null;
|
||
|
for(j = target.childNodes.length - 1; j >= 0; j--){
|
||
|
var c = target.childNodes[j];
|
||
|
if(c.nodeType === 1){
|
||
|
if(c.getAttribute("fixed") === "bottom"){
|
||
|
refNode = c;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if(text.charAt(0) === "<"){ // html markup
|
||
|
container = domConstruct.create("DIV", {innerHTML: text});
|
||
|
for(i = 0; i < container.childNodes.length; i++){
|
||
|
var n = container.childNodes[i];
|
||
|
if(n.nodeType === 1){
|
||
|
view = n; // expecting <div dojoType="dojox.mobile.View">
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if(!view){
|
||
|
console.log("dojox.mobile.ViewController#_parse: invalid view content");
|
||
|
return;
|
||
|
}
|
||
|
view.style.visibility = "hidden";
|
||
|
target.insertBefore(container, refNode);
|
||
|
var ws = dojo.parser.parse(container);
|
||
|
array.forEach(ws, function(w){
|
||
|
if(w && !w._started && w.startup){
|
||
|
w.startup();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// allows multiple root nodes in the fragment,
|
||
|
// but transition will be performed to the 1st view.
|
||
|
for(i = 0, len = container.childNodes.length; i < len; i++){
|
||
|
target.insertBefore(container.firstChild, refNode); // reparent
|
||
|
}
|
||
|
target.removeChild(container);
|
||
|
|
||
|
registry.byNode(view)._visible = true;
|
||
|
}else if(text.charAt(0) === "{"){ // json
|
||
|
container = domConstruct.create("DIV");
|
||
|
target.insertBefore(container, refNode);
|
||
|
this._ws = [];
|
||
|
view = this._instantiate(eval('('+text+')'), container);
|
||
|
for(i = 0; i < this._ws.length; i++){
|
||
|
var w = this._ws[i];
|
||
|
w.startup && !w._started && (!w.getParent || !w.getParent()) && w.startup();
|
||
|
}
|
||
|
this._ws = null;
|
||
|
}
|
||
|
view.style.display = "none";
|
||
|
view.style.visibility = "visible";
|
||
|
return dojo.hash ? "#" + view.id : view.id;
|
||
|
},
|
||
|
|
||
|
_instantiate: function(/*Object*/obj, /*DomNode*/node, /*Widget*/parent){
|
||
|
// summary:
|
||
|
// Given the evaluated json data, does the same thing as what
|
||
|
// the parser does.
|
||
|
var widget;
|
||
|
for(var key in obj){
|
||
|
if(key.charAt(0) == "@"){ continue; }
|
||
|
var cls = lang.getObject(key);
|
||
|
if(!cls){ continue; }
|
||
|
var params = {};
|
||
|
var proto = cls.prototype;
|
||
|
var objs = lang.isArray(obj[key]) ? obj[key] : [obj[key]];
|
||
|
for(var i = 0; i < objs.length; i++){
|
||
|
for(var prop in objs[i]){
|
||
|
if(prop.charAt(0) == "@"){
|
||
|
var val = objs[i][prop];
|
||
|
prop = prop.substring(1);
|
||
|
if(typeof proto[prop] == "string"){
|
||
|
params[prop] = val;
|
||
|
}else if(typeof proto[prop] == "number"){
|
||
|
params[prop] = val - 0;
|
||
|
}else if(typeof proto[prop] == "boolean"){
|
||
|
params[prop] = (val != "false");
|
||
|
}else if(typeof proto[prop] == "object"){
|
||
|
params[prop] = eval("(" + val + ")");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
widget = new cls(params, node);
|
||
|
if(node){ // to call View's startup()
|
||
|
widget._visible = true;
|
||
|
this._ws.push(widget);
|
||
|
}
|
||
|
if(parent && parent.addChild){
|
||
|
parent.addChild(widget);
|
||
|
}
|
||
|
this._instantiate(objs[i], null, widget);
|
||
|
}
|
||
|
}
|
||
|
return widget && widget.domNode;
|
||
|
}
|
||
|
});
|
||
|
new Controller(); // singleton
|
||
|
return Controller;
|
||
|
});
|
||
|
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/RoundRect':function(){
|
||
|
define([
|
||
|
"dojo/_base/array",
|
||
|
"dojo/_base/declare",
|
||
|
"dojo/_base/window",
|
||
|
"dijit/_Contained",
|
||
|
"dijit/_Container",
|
||
|
"dijit/_WidgetBase"
|
||
|
], function(array, declare, win, Contained, Container, WidgetBase){
|
||
|
|
||
|
/*=====
|
||
|
var Contained = dijit._Contained;
|
||
|
var Container = dijit._Container;
|
||
|
var WidgetBase = dijit._WidgetBase;
|
||
|
=====*/
|
||
|
|
||
|
// module:
|
||
|
// dojox/mobile/RoundRect
|
||
|
// summary:
|
||
|
// A simple round rectangle container.
|
||
|
|
||
|
return declare("dojox.mobile.RoundRect", [WidgetBase, Container, Contained], {
|
||
|
// summary:
|
||
|
// A simple round rectangle container.
|
||
|
// description:
|
||
|
// RoundRect is a simple round rectangle container for any HTML
|
||
|
// and/or widgets. You can achieve the same appearance by just
|
||
|
// applying the -webkit-border-radius style to a div tag. However,
|
||
|
// if you use RoundRect, you can get a round rectangle even on
|
||
|
// non-CSS3 browsers such as (older) IE.
|
||
|
|
||
|
// shadow: Boolean
|
||
|
// If true, adds a shadow effect to the container element.
|
||
|
shadow: false,
|
||
|
|
||
|
buildRendering: function(){
|
||
|
this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement("DIV");
|
||
|
this.domNode.className = this.shadow ? "mblRoundRect mblShadow" : "mblRoundRect";
|
||
|
},
|
||
|
|
||
|
resize: function(){
|
||
|
// summary:
|
||
|
// Calls resize() of each child widget.
|
||
|
array.forEach(this.getChildren(), function(child){
|
||
|
if(child.resize){ child.resize(); }
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/RoundRectList':function(){
|
||
|
define([
|
||
|
"dojo/_base/array",
|
||
|
"dojo/_base/declare",
|
||
|
"dojo/_base/window",
|
||
|
"dijit/_Contained",
|
||
|
"dijit/_Container",
|
||
|
"dijit/_WidgetBase"
|
||
|
], function(array, declare, win, Contained, Container, WidgetBase){
|
||
|
|
||
|
/*=====
|
||
|
var Contained = dijit._Contained;
|
||
|
var Container = dijit._Container;
|
||
|
var WidgetBase = dijit._WidgetBase;
|
||
|
=====*/
|
||
|
|
||
|
// module:
|
||
|
// dojox/mobile/RoundRectList
|
||
|
// summary:
|
||
|
// A rounded rectangle list.
|
||
|
|
||
|
return declare("dojox.mobile.RoundRectList", [WidgetBase, Container, Contained], {
|
||
|
// summary:
|
||
|
// A rounded rectangle list.
|
||
|
// description:
|
||
|
// RoundRectList is a rounded rectangle list, which can be used to
|
||
|
// display a group of items. Each item must be
|
||
|
// dojox.mobile.ListItem.
|
||
|
|
||
|
// transition: String
|
||
|
// The default animated transition effect for child items.
|
||
|
transition: "slide",
|
||
|
|
||
|
// iconBase: String
|
||
|
// The default icon path for child items.
|
||
|
iconBase: "",
|
||
|
|
||
|
// iconPos: String
|
||
|
// The default icon position for child items.
|
||
|
iconPos: "",
|
||
|
|
||
|
// select: String
|
||
|
// Selection mode of the list. The check mark is shown for the
|
||
|
// selected list item(s). The value can be "single", "multiple", or
|
||
|
// "". If "single", there can be only one selected item at a time.
|
||
|
// If "multiple", there can be multiple selected items at a time.
|
||
|
select: "",
|
||
|
|
||
|
// stateful: String
|
||
|
// If true, the last selected item remains highlighted.
|
||
|
stateful: false,
|
||
|
|
||
|
buildRendering: function(){
|
||
|
this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement("UL");
|
||
|
this.domNode.className = "mblRoundRectList";
|
||
|
},
|
||
|
|
||
|
resize: function(){
|
||
|
// summary:
|
||
|
// Calls resize() of each child widget.
|
||
|
array.forEach(this.getChildren(), function(child){
|
||
|
if(child.resize){ child.resize(); }
|
||
|
});
|
||
|
},
|
||
|
|
||
|
onCheckStateChanged: function(/*Widget*/listItem, /*String*/newState){
|
||
|
// summary:
|
||
|
// Stub function to connect to from your application.
|
||
|
// description:
|
||
|
// Called when the check state has been changed.
|
||
|
},
|
||
|
|
||
|
_setStatefulAttr: function(stateful){
|
||
|
this.stateful = stateful;
|
||
|
array.forEach(this.getChildren(), function(child){
|
||
|
child.setArrow && child.setArrow();
|
||
|
});
|
||
|
},
|
||
|
|
||
|
deselectItem: function(/*ListItem*/item){
|
||
|
// summary:
|
||
|
// Deselects the given item.
|
||
|
item.deselect();
|
||
|
},
|
||
|
|
||
|
deselectAll: function(){
|
||
|
// summary:
|
||
|
// Deselects all the items.
|
||
|
array.forEach(this.getChildren(), function(child){
|
||
|
child.deselect && child.deselect();
|
||
|
});
|
||
|
},
|
||
|
|
||
|
selectItem: function(/*ListItem*/item){
|
||
|
// summary:
|
||
|
// Selects the given item.
|
||
|
item.select();
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/sniff':function(){
|
||
|
define([
|
||
|
"dojo/_base/window",
|
||
|
"dojo/_base/sniff"
|
||
|
], function(win, has){
|
||
|
|
||
|
var ua = navigator.userAgent;
|
||
|
|
||
|
// BlackBerry (OS 6 or later only)
|
||
|
has.add("bb", ua.indexOf("BlackBerry") >= 0 && parseFloat(ua.split("Version/")[1]) || undefined, undefined, true);
|
||
|
|
||
|
// Android
|
||
|
has.add("android", parseFloat(ua.split("Android ")[1]) || undefined, undefined, true);
|
||
|
|
||
|
// iPhone, iPod, or iPad
|
||
|
// If iPod or iPad is detected, in addition to has("ipod") or has("ipad"),
|
||
|
// has("iphone") will also have iOS version number.
|
||
|
if(ua.match(/(iPhone|iPod|iPad)/)){
|
||
|
var p = RegExp.$1.replace(/P/, 'p');
|
||
|
var v = ua.match(/OS ([\d_]+)/) ? RegExp.$1 : "1";
|
||
|
var os = parseFloat(v.replace(/_/, '.').replace(/_/g, ''));
|
||
|
has.add(p, os, undefined, true);
|
||
|
has.add("iphone", os, undefined, true);
|
||
|
}
|
||
|
|
||
|
if(has("webkit")){
|
||
|
has.add("touch", (typeof win.doc.documentElement.ontouchstart != "undefined" &&
|
||
|
navigator.appVersion.indexOf("Mobile") != -1) || !!has("android"), undefined, true);
|
||
|
}
|
||
|
|
||
|
return has;
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/TransitionEvent':function(){
|
||
|
define([
|
||
|
"dojo/_base/declare",
|
||
|
"dojo/_base/Deferred",
|
||
|
"dojo/_base/lang",
|
||
|
"dojo/on",
|
||
|
"./transition"
|
||
|
], function(declare, Deferred, lang, on, transitDeferred){
|
||
|
|
||
|
return declare("dojox.mobile.TransitionEvent", null, {
|
||
|
constructor: function(target, transitionOptions, triggerEvent){
|
||
|
this.transitionOptions=transitionOptions;
|
||
|
this.target = target;
|
||
|
this.triggerEvent=triggerEvent||null;
|
||
|
},
|
||
|
|
||
|
dispatch: function(){
|
||
|
var opts = {bubbles:true, cancelable:true, detail: this.transitionOptions, triggerEvent: this.triggerEvent};
|
||
|
//console.log("Target: ", this.target, " opts: ", opts);
|
||
|
|
||
|
var evt = on.emit(this.target,"startTransition", opts);
|
||
|
//console.log('evt: ', evt);
|
||
|
if(evt){
|
||
|
Deferred.when(transitDeferred, lang.hitch(this, function(transition){
|
||
|
Deferred.when(transition.call(this, evt), lang.hitch(this, function(results){
|
||
|
this.endTransition(results);
|
||
|
}));
|
||
|
}));
|
||
|
}
|
||
|
},
|
||
|
|
||
|
endTransition: function(results){
|
||
|
on.emit(this.target, "endTransition" , {detail: results.transitionOptions});
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dijit/_WidgetBase':function(){
|
||
|
define("dijit/_WidgetBase", [
|
||
|
"require", // require.toUrl
|
||
|
"dojo/_base/array", // array.forEach array.map
|
||
|
"dojo/aspect",
|
||
|
"dojo/_base/config", // config.blankGif
|
||
|
"dojo/_base/connect", // connect.connect
|
||
|
"dojo/_base/declare", // declare
|
||
|
"dojo/dom", // dom.byId
|
||
|
"dojo/dom-attr", // domAttr.set domAttr.remove
|
||
|
"dojo/dom-class", // domClass.add domClass.replace
|
||
|
"dojo/dom-construct", // domConstruct.create domConstruct.destroy domConstruct.place
|
||
|
"dojo/dom-geometry", // isBodyLtr
|
||
|
"dojo/dom-style", // domStyle.set, domStyle.get
|
||
|
"dojo/_base/kernel",
|
||
|
"dojo/_base/lang", // mixin(), isArray(), etc.
|
||
|
"dojo/on",
|
||
|
"dojo/ready",
|
||
|
"dojo/Stateful", // Stateful
|
||
|
"dojo/topic",
|
||
|
"dojo/_base/window", // win.doc.createTextNode
|
||
|
"./registry" // registry.getUniqueId(), registry.findWidgets()
|
||
|
], function(require, array, aspect, config, connect, declare,
|
||
|
dom, domAttr, domClass, domConstruct, domGeometry, domStyle, kernel,
|
||
|
lang, on, ready, Stateful, topic, win, registry){
|
||
|
|
||
|
/*=====
|
||
|
var Stateful = dojo.Stateful;
|
||
|
=====*/
|
||
|
|
||
|
// module:
|
||
|
// dijit/_WidgetBase
|
||
|
// summary:
|
||
|
// Future base class for all Dijit widgets.
|
||
|
|
||
|
// For back-compat, remove in 2.0.
|
||
|
if(!kernel.isAsync){
|
||
|
ready(0, function(){
|
||
|
var requires = ["dijit/_base/manager"];
|
||
|
require(requires); // use indirection so modules not rolled into a build
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Nested hash listing attributes for each tag, all strings in lowercase.
|
||
|
// ex: {"div": {"style": true, "tabindex" true}, "form": { ...
|
||
|
var tagAttrs = {};
|
||
|
function getAttrs(obj){
|
||
|
var ret = {};
|
||
|
for(var attr in obj){
|
||
|
ret[attr.toLowerCase()] = true;
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
function nonEmptyAttrToDom(attr){
|
||
|
// summary:
|
||
|
// Returns a setter function that copies the attribute to this.domNode,
|
||
|
// or removes the attribute from this.domNode, depending on whether the
|
||
|
// value is defined or not.
|
||
|
return function(val){
|
||
|
domAttr[val ? "set" : "remove"](this.domNode, attr, val);
|
||
|
this._set(attr, val);
|
||
|
};
|
||
|
}
|
||
|
|
||
|
return declare("dijit._WidgetBase", Stateful, {
|
||
|
// summary:
|
||
|
// Future base class for all Dijit widgets.
|
||
|
// description:
|
||
|
// Future base class for all Dijit widgets.
|
||
|
// _Widget extends this class adding support for various features needed by desktop.
|
||
|
//
|
||
|
// Provides stubs for widget lifecycle methods for subclasses to extend, like postMixInProperties(), buildRendering(),
|
||
|
// postCreate(), startup(), and destroy(), and also public API methods like set(), get(), and watch().
|
||
|
//
|
||
|
// Widgets can provide custom setters/getters for widget attributes, which are called automatically by set(name, value).
|
||
|
// For an attribute XXX, define methods _setXXXAttr() and/or _getXXXAttr().
|
||
|
//
|
||
|
// _setXXXAttr can also be a string/hash/array mapping from a widget attribute XXX to the widget's DOMNodes:
|
||
|
//
|
||
|
// - DOM node attribute
|
||
|
// | _setFocusAttr: {node: "focusNode", type: "attribute"}
|
||
|
// | _setFocusAttr: "focusNode" (shorthand)
|
||
|
// | _setFocusAttr: "" (shorthand, maps to this.domNode)
|
||
|
// Maps this.focus to this.focusNode.focus, or (last example) this.domNode.focus
|
||
|
//
|
||
|
// - DOM node innerHTML
|
||
|
// | _setTitleAttr: { node: "titleNode", type: "innerHTML" }
|
||
|
// Maps this.title to this.titleNode.innerHTML
|
||
|
//
|
||
|
// - DOM node innerText
|
||
|
// | _setTitleAttr: { node: "titleNode", type: "innerText" }
|
||
|
// Maps this.title to this.titleNode.innerText
|
||
|
//
|
||
|
// - DOM node CSS class
|
||
|
// | _setMyClassAttr: { node: "domNode", type: "class" }
|
||
|
// Maps this.myClass to this.domNode.className
|
||
|
//
|
||
|
// If the value of _setXXXAttr is an array, then each element in the array matches one of the
|
||
|
// formats of the above list.
|
||
|
//
|
||
|
// If the custom setter is null, no action is performed other than saving the new value
|
||
|
// in the widget (in this).
|
||
|
//
|
||
|
// If no custom setter is defined for an attribute, then it will be copied
|
||
|
// to this.focusNode (if the widget defines a focusNode), or this.domNode otherwise.
|
||
|
// That's only done though for attributes that match DOMNode attributes (title,
|
||
|
// alt, aria-labelledby, etc.)
|
||
|
|
||
|
// id: [const] String
|
||
|
// A unique, opaque ID string that can be assigned by users or by the
|
||
|
// system. If the developer passes an ID which is known not to be
|
||
|
// unique, the specified ID is ignored and the system-generated ID is
|
||
|
// used instead.
|
||
|
id: "",
|
||
|
_setIdAttr: "domNode", // to copy to this.domNode even for auto-generated id's
|
||
|
|
||
|
// lang: [const] String
|
||
|
// Rarely used. Overrides the default Dojo locale used to render this widget,
|
||
|
// as defined by the [HTML LANG](http://www.w3.org/TR/html401/struct/dirlang.html#adef-lang) attribute.
|
||
|
// Value must be among the list of locales specified during by the Dojo bootstrap,
|
||
|
// formatted according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt) (like en-us).
|
||
|
lang: "",
|
||
|
// set on domNode even when there's a focus node. but don't set lang="", since that's invalid.
|
||
|
_setLangAttr: nonEmptyAttrToDom("lang"),
|
||
|
|
||
|
// dir: [const] String
|
||
|
// Bi-directional support, as defined by the [HTML DIR](http://www.w3.org/TR/html401/struct/dirlang.html#adef-dir)
|
||
|
// attribute. Either left-to-right "ltr" or right-to-left "rtl". If undefined, widgets renders in page's
|
||
|
// default direction.
|
||
|
dir: "",
|
||
|
// set on domNode even when there's a focus node. but don't set dir="", since that's invalid.
|
||
|
_setDirAttr: nonEmptyAttrToDom("dir"), // to set on domNode even when there's a focus node
|
||
|
|
||
|
// textDir: String
|
||
|
// Bi-directional support, the main variable which is responsible for the direction of the text.
|
||
|
// The text direction can be different than the GUI direction by using this parameter in creation
|
||
|
// of a widget.
|
||
|
// Allowed values:
|
||
|
// 1. "ltr"
|
||
|
// 2. "rtl"
|
||
|
// 3. "auto" - contextual the direction of a text defined by first strong letter.
|
||
|
// By default is as the page direction.
|
||
|
textDir: "",
|
||
|
|
||
|
// class: String
|
||
|
// HTML class attribute
|
||
|
"class": "",
|
||
|
_setClassAttr: { node: "domNode", type: "class" },
|
||
|
|
||
|
// style: String||Object
|
||
|
// HTML style attributes as cssText string or name/value hash
|
||
|
style: "",
|
||
|
|
||
|
// title: String
|
||
|
// HTML title attribute.
|
||
|
//
|
||
|
// For form widgets this specifies a tooltip to display when hovering over
|
||
|
// the widget (just like the native HTML title attribute).
|
||
|
//
|
||
|
// For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer,
|
||
|
// etc., it's used to specify the tab label, accordion pane title, etc.
|
||
|
title: "",
|
||
|
|
||
|
// tooltip: String
|
||
|
// When this widget's title attribute is used to for a tab label, accordion pane title, etc.,
|
||
|
// this specifies the tooltip to appear when the mouse is hovered over that text.
|
||
|
tooltip: "",
|
||
|
|
||
|
// baseClass: [protected] String
|
||
|
// Root CSS class of the widget (ex: dijitTextBox), used to construct CSS classes to indicate
|
||
|
// widget state.
|
||
|
baseClass: "",
|
||
|
|
||
|
// srcNodeRef: [readonly] DomNode
|
||
|
// pointer to original DOM node
|
||
|
srcNodeRef: null,
|
||
|
|
||
|
// domNode: [readonly] DomNode
|
||
|
// This is our visible representation of the widget! Other DOM
|
||
|
// Nodes may by assigned to other properties, usually through the
|
||
|
// template system's data-dojo-attach-point syntax, but the domNode
|
||
|
// property is the canonical "top level" node in widget UI.
|
||
|
domNode: null,
|
||
|
|
||
|
// containerNode: [readonly] DomNode
|
||
|
// Designates where children of the source DOM node will be placed.
|
||
|
// "Children" in this case refers to both DOM nodes and widgets.
|
||
|
// For example, for myWidget:
|
||
|
//
|
||
|
// | <div data-dojo-type=myWidget>
|
||
|
// | <b> here's a plain DOM node
|
||
|
// | <span data-dojo-type=subWidget>and a widget</span>
|
||
|
// | <i> and another plain DOM node </i>
|
||
|
// | </div>
|
||
|
//
|
||
|
// containerNode would point to:
|
||
|
//
|
||
|
// | <b> here's a plain DOM node
|
||
|
// | <span data-dojo-type=subWidget>and a widget</span>
|
||
|
// | <i> and another plain DOM node </i>
|
||
|
//
|
||
|
// In templated widgets, "containerNode" is set via a
|
||
|
// data-dojo-attach-point assignment.
|
||
|
//
|
||
|
// containerNode must be defined for any widget that accepts innerHTML
|
||
|
// (like ContentPane or BorderContainer or even Button), and conversely
|
||
|
// is null for widgets that don't, like TextBox.
|
||
|
containerNode: null,
|
||
|
|
||
|
/*=====
|
||
|
// _started: Boolean
|
||
|
// startup() has completed.
|
||
|
_started: false,
|
||
|
=====*/
|
||
|
|
||
|
// attributeMap: [protected] Object
|
||
|
// Deprecated. Instead of attributeMap, widget should have a _setXXXAttr attribute
|
||
|
// for each XXX attribute to be mapped to the DOM.
|
||
|
//
|
||
|
// attributeMap sets up a "binding" between attributes (aka properties)
|
||
|
// of the widget and the widget's DOM.
|
||
|
// Changes to widget attributes listed in attributeMap will be
|
||
|
// reflected into the DOM.
|
||
|
//
|
||
|
// For example, calling set('title', 'hello')
|
||
|
// on a TitlePane will automatically cause the TitlePane's DOM to update
|
||
|
// with the new title.
|
||
|
//
|
||
|
// attributeMap is a hash where the key is an attribute of the widget,
|
||
|
// and the value reflects a binding to a:
|
||
|
//
|
||
|
// - DOM node attribute
|
||
|
// | focus: {node: "focusNode", type: "attribute"}
|
||
|
// Maps this.focus to this.focusNode.focus
|
||
|
//
|
||
|
// - DOM node innerHTML
|
||
|
// | title: { node: "titleNode", type: "innerHTML" }
|
||
|
// Maps this.title to this.titleNode.innerHTML
|
||
|
//
|
||
|
// - DOM node innerText
|
||
|
// | title: { node: "titleNode", type: "innerText" }
|
||
|
// Maps this.title to this.titleNode.innerText
|
||
|
//
|
||
|
// - DOM node CSS class
|
||
|
// | myClass: { node: "domNode", type: "class" }
|
||
|
// Maps this.myClass to this.domNode.className
|
||
|
//
|
||
|
// If the value is an array, then each element in the array matches one of the
|
||
|
// formats of the above list.
|
||
|
//
|
||
|
// There are also some shorthands for backwards compatibility:
|
||
|
// - string --> { node: string, type: "attribute" }, for example:
|
||
|
// | "focusNode" ---> { node: "focusNode", type: "attribute" }
|
||
|
// - "" --> { node: "domNode", type: "attribute" }
|
||
|
attributeMap: {},
|
||
|
|
||
|
// _blankGif: [protected] String
|
||
|
// Path to a blank 1x1 image.
|
||
|
// Used by <img> nodes in templates that really get their image via CSS background-image.
|
||
|
_blankGif: config.blankGif || require.toUrl("dojo/resources/blank.gif"),
|
||
|
|
||
|
//////////// INITIALIZATION METHODS ///////////////////////////////////////
|
||
|
|
||
|
postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){
|
||
|
// summary:
|
||
|
// Kicks off widget instantiation. See create() for details.
|
||
|
// tags:
|
||
|
// private
|
||
|
this.create(params, srcNodeRef);
|
||
|
},
|
||
|
|
||
|
create: function(/*Object?*/params, /*DomNode|String?*/srcNodeRef){
|
||
|
// summary:
|
||
|
// Kick off the life-cycle of a widget
|
||
|
// params:
|
||
|
// Hash of initialization parameters for widget, including
|
||
|
// scalar values (like title, duration etc.) and functions,
|
||
|
// typically callbacks like onClick.
|
||
|
// srcNodeRef:
|
||
|
// If a srcNodeRef (DOM node) is specified:
|
||
|
// - use srcNodeRef.innerHTML as my contents
|
||
|
// - if this is a behavioral widget then apply behavior
|
||
|
// to that srcNodeRef
|
||
|
// - otherwise, replace srcNodeRef with my generated DOM
|
||
|
// tree
|
||
|
// description:
|
||
|
// Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate,
|
||
|
// etc.), some of which of you'll want to override. See http://dojotoolkit.org/reference-guide/dijit/_WidgetBase.html
|
||
|
// for a discussion of the widget creation lifecycle.
|
||
|
//
|
||
|
// Of course, adventurous developers could override create entirely, but this should
|
||
|
// only be done as a last resort.
|
||
|
// tags:
|
||
|
// private
|
||
|
|
||
|
// store pointer to original DOM tree
|
||
|
this.srcNodeRef = dom.byId(srcNodeRef);
|
||
|
|
||
|
// For garbage collection. An array of listener handles returned by this.connect() / this.subscribe()
|
||
|
this._connects = [];
|
||
|
|
||
|
// For widgets internal to this widget, invisible to calling code
|
||
|
this._supportingWidgets = [];
|
||
|
|
||
|
// this is here for back-compat, remove in 2.0 (but check NodeList-instantiate.html test)
|
||
|
if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; }
|
||
|
|
||
|
// mix in our passed parameters
|
||
|
if(params){
|
||
|
this.params = params;
|
||
|
lang.mixin(this, params);
|
||
|
}
|
||
|
this.postMixInProperties();
|
||
|
|
||
|
// generate an id for the widget if one wasn't specified
|
||
|
// (be sure to do this before buildRendering() because that function might
|
||
|
// expect the id to be there.)
|
||
|
if(!this.id){
|
||
|
this.id = registry.getUniqueId(this.declaredClass.replace(/\./g,"_"));
|
||
|
}
|
||
|
registry.add(this);
|
||
|
|
||
|
this.buildRendering();
|
||
|
|
||
|
if(this.domNode){
|
||
|
// Copy attributes listed in attributeMap into the [newly created] DOM for the widget.
|
||
|
// Also calls custom setters for all attributes with custom setters.
|
||
|
this._applyAttributes();
|
||
|
|
||
|
// If srcNodeRef was specified, then swap out original srcNode for this widget's DOM tree.
|
||
|
// For 2.0, move this after postCreate(). postCreate() shouldn't depend on the
|
||
|
// widget being attached to the DOM since it isn't when a widget is created programmatically like
|
||
|
// new MyWidget({}). See #11635.
|
||
|
var source = this.srcNodeRef;
|
||
|
if(source && source.parentNode && this.domNode !== source){
|
||
|
source.parentNode.replaceChild(this.domNode, source);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(this.domNode){
|
||
|
// Note: for 2.0 may want to rename widgetId to dojo._scopeName + "_widgetId",
|
||
|
// assuming that dojo._scopeName even exists in 2.0
|
||
|
this.domNode.setAttribute("widgetId", this.id);
|
||
|
}
|
||
|
this.postCreate();
|
||
|
|
||
|
// If srcNodeRef has been processed and removed from the DOM (e.g. TemplatedWidget) then delete it to allow GC.
|
||
|
if(this.srcNodeRef && !this.srcNodeRef.parentNode){
|
||
|
delete this.srcNodeRef;
|
||
|
}
|
||
|
|
||
|
this._created = true;
|
||
|
},
|
||
|
|
||
|
_applyAttributes: function(){
|
||
|
// summary:
|
||
|
// Step during widget creation to copy widget attributes to the
|
||
|
// DOM according to attributeMap and _setXXXAttr objects, and also to call
|
||
|
// custom _setXXXAttr() methods.
|
||
|
//
|
||
|
// Skips over blank/false attribute values, unless they were explicitly specified
|
||
|
// as parameters to the widget, since those are the default anyway,
|
||
|
// and setting tabIndex="" is different than not setting tabIndex at all.
|
||
|
//
|
||
|
// For backwards-compatibility reasons attributeMap overrides _setXXXAttr when
|
||
|
// _setXXXAttr is a hash/string/array, but _setXXXAttr as a functions override attributeMap.
|
||
|
// tags:
|
||
|
// private
|
||
|
|
||
|
// Get list of attributes where this.set(name, value) will do something beyond
|
||
|
// setting this[name] = value. Specifically, attributes that have:
|
||
|
// - associated _setXXXAttr() method/hash/string/array
|
||
|
// - entries in attributeMap.
|
||
|
var ctor = this.constructor,
|
||
|
list = ctor._setterAttrs;
|
||
|
if(!list){
|
||
|
list = (ctor._setterAttrs = []);
|
||
|
for(var attr in this.attributeMap){
|
||
|
list.push(attr);
|
||
|
}
|
||
|
|
||
|
var proto = ctor.prototype;
|
||
|
for(var fxName in proto){
|
||
|
if(fxName in this.attributeMap){ continue; }
|
||
|
var setterName = "_set" + fxName.replace(/^[a-z]|-[a-zA-Z]/g, function(c){ return c.charAt(c.length-1).toUpperCase(); }) + "Attr";
|
||
|
if(setterName in proto){
|
||
|
list.push(fxName);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Call this.set() for each attribute that was either specified as parameter to constructor,
|
||
|
// or was found above and has a default non-null value. For correlated attributes like value and displayedValue, the one
|
||
|
// specified as a parameter should take precedence, so apply attributes in this.params last.
|
||
|
// Particularly important for new DateTextBox({displayedValue: ...}) since DateTextBox's default value is
|
||
|
// NaN and thus is not ignored like a default value of "".
|
||
|
array.forEach(list, function(attr){
|
||
|
if(this.params && attr in this.params){
|
||
|
// skip this one, do it below
|
||
|
}else if(this[attr]){
|
||
|
this.set(attr, this[attr]);
|
||
|
}
|
||
|
}, this);
|
||
|
for(var param in this.params){
|
||
|
this.set(param, this[param]);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
postMixInProperties: function(){
|
||
|
// summary:
|
||
|
// Called after the parameters to the widget have been read-in,
|
||
|
// but before the widget template is instantiated. Especially
|
||
|
// useful to set properties that are referenced in the widget
|
||
|
// template.
|
||
|
// tags:
|
||
|
// protected
|
||
|
},
|
||
|
|
||
|
buildRendering: function(){
|
||
|
// summary:
|
||
|
// Construct the UI for this widget, setting this.domNode.
|
||
|
// Most widgets will mixin `dijit._TemplatedMixin`, which implements this method.
|
||
|
// tags:
|
||
|
// protected
|
||
|
|
||
|
if(!this.domNode){
|
||
|
// Create root node if it wasn't created by _Templated
|
||
|
this.domNode = this.srcNodeRef || domConstruct.create('div');
|
||
|
}
|
||
|
|
||
|
// baseClass is a single class name or occasionally a space-separated list of names.
|
||
|
// Add those classes to the DOMNode. If RTL mode then also add with Rtl suffix.
|
||
|
// TODO: make baseClass custom setter
|
||
|
if(this.baseClass){
|
||
|
var classes = this.baseClass.split(" ");
|
||
|
if(!this.isLeftToRight()){
|
||
|
classes = classes.concat( array.map(classes, function(name){ return name+"Rtl"; }));
|
||
|
}
|
||
|
domClass.add(this.domNode, classes);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
postCreate: function(){
|
||
|
// summary:
|
||
|
// Processing after the DOM fragment is created
|
||
|
// description:
|
||
|
// Called after the DOM fragment has been created, but not necessarily
|
||
|
// added to the document. Do not include any operations which rely on
|
||
|
// node dimensions or placement.
|
||
|
// tags:
|
||
|
// protected
|
||
|
},
|
||
|
|
||
|
startup: function(){
|
||
|
// summary:
|
||
|
// Processing after the DOM fragment is added to the document
|
||
|
// description:
|
||
|
// Called after a widget and its children have been created and added to the page,
|
||
|
// and all related widgets have finished their create() cycle, up through postCreate().
|
||
|
// This is useful for composite widgets that need to control or layout sub-widgets.
|
||
|
// Many layout widgets can use this as a wiring phase.
|
||
|
if(this._started){ return; }
|
||
|
this._started = true;
|
||
|
array.forEach(this.getChildren(), function(obj){
|
||
|
if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){
|
||
|
obj.startup();
|
||
|
obj._started = true;
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
//////////// DESTROY FUNCTIONS ////////////////////////////////
|
||
|
|
||
|
destroyRecursive: function(/*Boolean?*/ preserveDom){
|
||
|
// summary:
|
||
|
// Destroy this widget and its descendants
|
||
|
// description:
|
||
|
// This is the generic "destructor" function that all widget users
|
||
|
// should call to cleanly discard with a widget. Once a widget is
|
||
|
// destroyed, it is removed from the manager object.
|
||
|
// preserveDom:
|
||
|
// If true, this method will leave the original DOM structure
|
||
|
// alone of descendant Widgets. Note: This will NOT work with
|
||
|
// dijit._Templated widgets.
|
||
|
|
||
|
this._beingDestroyed = true;
|
||
|
this.destroyDescendants(preserveDom);
|
||
|
this.destroy(preserveDom);
|
||
|
},
|
||
|
|
||
|
destroy: function(/*Boolean*/ preserveDom){
|
||
|
// summary:
|
||
|
// Destroy this widget, but not its descendants.
|
||
|
// This method will, however, destroy internal widgets such as those used within a template.
|
||
|
// preserveDom: Boolean
|
||
|
// If true, this method will leave the original DOM structure alone.
|
||
|
// Note: This will not yet work with _Templated widgets
|
||
|
|
||
|
this._beingDestroyed = true;
|
||
|
this.uninitialize();
|
||
|
|
||
|
// remove this.connect() and this.subscribe() listeners
|
||
|
var c;
|
||
|
while(c = this._connects.pop()){
|
||
|
c.remove();
|
||
|
}
|
||
|
|
||
|
// destroy widgets created as part of template, etc.
|
||
|
var w;
|
||
|
while(w = this._supportingWidgets.pop()){
|
||
|
if(w.destroyRecursive){
|
||
|
w.destroyRecursive();
|
||
|
}else if(w.destroy){
|
||
|
w.destroy();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.destroyRendering(preserveDom);
|
||
|
registry.remove(this.id);
|
||
|
this._destroyed = true;
|
||
|
},
|
||
|
|
||
|
destroyRendering: function(/*Boolean?*/ preserveDom){
|
||
|
// summary:
|
||
|
// Destroys the DOM nodes associated with this widget
|
||
|
// preserveDom:
|
||
|
// If true, this method will leave the original DOM structure alone
|
||
|
// during tear-down. Note: this will not work with _Templated
|
||
|
// widgets yet.
|
||
|
// tags:
|
||
|
// protected
|
||
|
|
||
|
if(this.bgIframe){
|
||
|
this.bgIframe.destroy(preserveDom);
|
||
|
delete this.bgIframe;
|
||
|
}
|
||
|
|
||
|
if(this.domNode){
|
||
|
if(preserveDom){
|
||
|
domAttr.remove(this.domNode, "widgetId");
|
||
|
}else{
|
||
|
domConstruct.destroy(this.domNode);
|
||
|
}
|
||
|
delete this.domNode;
|
||
|
}
|
||
|
|
||
|
if(this.srcNodeRef){
|
||
|
if(!preserveDom){
|
||
|
domConstruct.destroy(this.srcNodeRef);
|
||
|
}
|
||
|
delete this.srcNodeRef;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
destroyDescendants: function(/*Boolean?*/ preserveDom){
|
||
|
// summary:
|
||
|
// Recursively destroy the children of this widget and their
|
||
|
// descendants.
|
||
|
// preserveDom:
|
||
|
// If true, the preserveDom attribute is passed to all descendant
|
||
|
// widget's .destroy() method. Not for use with _Templated
|
||
|
// widgets.
|
||
|
|
||
|
// get all direct descendants and destroy them recursively
|
||
|
array.forEach(this.getChildren(), function(widget){
|
||
|
if(widget.destroyRecursive){
|
||
|
widget.destroyRecursive(preserveDom);
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
uninitialize: function(){
|
||
|
// summary:
|
||
|
// Stub function. Override to implement custom widget tear-down
|
||
|
// behavior.
|
||
|
// tags:
|
||
|
// protected
|
||
|
return false;
|
||
|
},
|
||
|
|
||
|
////////////////// GET/SET, CUSTOM SETTERS, ETC. ///////////////////
|
||
|
|
||
|
_setStyleAttr: function(/*String||Object*/ value){
|
||
|
// summary:
|
||
|
// Sets the style attribute of the widget according to value,
|
||
|
// which is either a hash like {height: "5px", width: "3px"}
|
||
|
// or a plain string
|
||
|
// description:
|
||
|
// Determines which node to set the style on based on style setting
|
||
|
// in attributeMap.
|
||
|
// tags:
|
||
|
// protected
|
||
|
|
||
|
var mapNode = this.domNode;
|
||
|
|
||
|
// Note: technically we should revert any style setting made in a previous call
|
||
|
// to his method, but that's difficult to keep track of.
|
||
|
|
||
|
if(lang.isObject(value)){
|
||
|
domStyle.set(mapNode, value);
|
||
|
}else{
|
||
|
if(mapNode.style.cssText){
|
||
|
mapNode.style.cssText += "; " + value;
|
||
|
}else{
|
||
|
mapNode.style.cssText = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this._set("style", value);
|
||
|
},
|
||
|
|
||
|
_attrToDom: function(/*String*/ attr, /*String*/ value, /*Object?*/ commands){
|
||
|
// summary:
|
||
|
// Reflect a widget attribute (title, tabIndex, duration etc.) to
|
||
|
// the widget DOM, as specified by commands parameter.
|
||
|
// If commands isn't specified then it's looked up from attributeMap.
|
||
|
// Note some attributes like "type"
|
||
|
// cannot be processed this way as they are not mutable.
|
||
|
//
|
||
|
// tags:
|
||
|
// private
|
||
|
|
||
|
commands = arguments.length >= 3 ? commands : this.attributeMap[attr];
|
||
|
|
||
|
array.forEach(lang.isArray(commands) ? commands : [commands], function(command){
|
||
|
|
||
|
// Get target node and what we are doing to that node
|
||
|
var mapNode = this[command.node || command || "domNode"]; // DOM node
|
||
|
var type = command.type || "attribute"; // class, innerHTML, innerText, or attribute
|
||
|
|
||
|
switch(type){
|
||
|
case "attribute":
|
||
|
if(lang.isFunction(value)){ // functions execute in the context of the widget
|
||
|
value = lang.hitch(this, value);
|
||
|
}
|
||
|
|
||
|
// Get the name of the DOM node attribute; usually it's the same
|
||
|
// as the name of the attribute in the widget (attr), but can be overridden.
|
||
|
// Also maps handler names to lowercase, like onSubmit --> onsubmit
|
||
|
var attrName = command.attribute ? command.attribute :
|
||
|
(/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr);
|
||
|
|
||
|
domAttr.set(mapNode, attrName, value);
|
||
|
break;
|
||
|
case "innerText":
|
||
|
mapNode.innerHTML = "";
|
||
|
mapNode.appendChild(win.doc.createTextNode(value));
|
||
|
break;
|
||
|
case "innerHTML":
|
||
|
mapNode.innerHTML = value;
|
||
|
break;
|
||
|
case "class":
|
||
|
domClass.replace(mapNode, value, this[attr]);
|
||
|
break;
|
||
|
}
|
||
|
}, this);
|
||
|
},
|
||
|
|
||
|
get: function(name){
|
||
|
// summary:
|
||
|
// Get a property from a widget.
|
||
|
// name:
|
||
|
// The property to get.
|
||
|
// description:
|
||
|
// Get a named property from a widget. The property may
|
||
|
// potentially be retrieved via a getter method. If no getter is defined, this
|
||
|
// just retrieves the object's property.
|
||
|
//
|
||
|
// For example, if the widget has properties `foo` and `bar`
|
||
|
// and a method named `_getFooAttr()`, calling:
|
||
|
// `myWidget.get("foo")` would be equivalent to calling
|
||
|
// `widget._getFooAttr()` and `myWidget.get("bar")`
|
||
|
// would be equivalent to the expression
|
||
|
// `widget.bar2`
|
||
|
var names = this._getAttrNames(name);
|
||
|
return this[names.g] ? this[names.g]() : this[name];
|
||
|
},
|
||
|
|
||
|
set: function(name, value){
|
||
|
// summary:
|
||
|
// Set a property on a widget
|
||
|
// name:
|
||
|
// The property to set.
|
||
|
// value:
|
||
|
// The value to set in the property.
|
||
|
// description:
|
||
|
// Sets named properties on a widget which may potentially be handled by a
|
||
|
// setter in the widget.
|
||
|
//
|
||
|
// For example, if the widget has properties `foo` and `bar`
|
||
|
// and a method named `_setFooAttr()`, calling
|
||
|
// `myWidget.set("foo", "Howdy!")` would be equivalent to calling
|
||
|
// `widget._setFooAttr("Howdy!")` and `myWidget.set("bar", 3)`
|
||
|
// would be equivalent to the statement `widget.bar = 3;`
|
||
|
//
|
||
|
// set() may also be called with a hash of name/value pairs, ex:
|
||
|
//
|
||
|
// | myWidget.set({
|
||
|
// | foo: "Howdy",
|
||
|
// | bar: 3
|
||
|
// | });
|
||
|
//
|
||
|
// This is equivalent to calling `set(foo, "Howdy")` and `set(bar, 3)`
|
||
|
|
||
|
if(typeof name === "object"){
|
||
|
for(var x in name){
|
||
|
this.set(x, name[x]);
|
||
|
}
|
||
|
return this;
|
||
|
}
|
||
|
var names = this._getAttrNames(name),
|
||
|
setter = this[names.s];
|
||
|
if(lang.isFunction(setter)){
|
||
|
// use the explicit setter
|
||
|
var result = setter.apply(this, Array.prototype.slice.call(arguments, 1));
|
||
|
}else{
|
||
|
// Mapping from widget attribute to DOMNode attribute/value/etc.
|
||
|
// Map according to:
|
||
|
// 1. attributeMap setting, if one exists (TODO: attributeMap deprecated, remove in 2.0)
|
||
|
// 2. _setFooAttr: {...} type attribute in the widget (if one exists)
|
||
|
// 3. apply to focusNode or domNode if standard attribute name, excluding funcs like onClick.
|
||
|
// Checks if an attribute is a "standard attribute" by whether the DOMNode JS object has a similar
|
||
|
// attribute name (ex: accept-charset attribute matches jsObject.acceptCharset).
|
||
|
// Note also that Tree.focusNode() is a function not a DOMNode, so test for that.
|
||
|
var defaultNode = this.focusNode && !lang.isFunction(this.focusNode) ? "focusNode" : "domNode",
|
||
|
tag = this[defaultNode].tagName,
|
||
|
attrsForTag = tagAttrs[tag] || (tagAttrs[tag] = getAttrs(this[defaultNode])),
|
||
|
map = name in this.attributeMap ? this.attributeMap[name] :
|
||
|
names.s in this ? this[names.s] :
|
||
|
((names.l in attrsForTag && typeof value != "function") ||
|
||
|
/^aria-|^data-|^role$/.test(name)) ? defaultNode : null;
|
||
|
if(map != null){
|
||
|
this._attrToDom(name, value, map);
|
||
|
}
|
||
|
this._set(name, value);
|
||
|
}
|
||
|
return result || this;
|
||
|
},
|
||
|
|
||
|
_attrPairNames: {}, // shared between all widgets
|
||
|
_getAttrNames: function(name){
|
||
|
// summary:
|
||
|
// Helper function for get() and set().
|
||
|
// Caches attribute name values so we don't do the string ops every time.
|
||
|
// tags:
|
||
|
// private
|
||
|
|
||
|
var apn = this._attrPairNames;
|
||
|
if(apn[name]){ return apn[name]; }
|
||
|
var uc = name.replace(/^[a-z]|-[a-zA-Z]/g, function(c){ return c.charAt(c.length-1).toUpperCase(); });
|
||
|
return (apn[name] = {
|
||
|
n: name+"Node",
|
||
|
s: "_set"+uc+"Attr", // converts dashes to camel case, ex: accept-charset --> _setAcceptCharsetAttr
|
||
|
g: "_get"+uc+"Attr",
|
||
|
l: uc.toLowerCase() // lowercase name w/out dashes, ex: acceptcharset
|
||
|
});
|
||
|
},
|
||
|
|
||
|
_set: function(/*String*/ name, /*anything*/ value){
|
||
|
// summary:
|
||
|
// Helper function to set new value for specified attribute, and call handlers
|
||
|
// registered with watch() if the value has changed.
|
||
|
var oldValue = this[name];
|
||
|
this[name] = value;
|
||
|
if(this._watchCallbacks && this._created && value !== oldValue){
|
||
|
this._watchCallbacks(name, oldValue, value);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
on: function(/*String*/ type, /*Function*/ func){
|
||
|
// summary:
|
||
|
// Call specified function when event occurs, ex: myWidget.on("click", function(){ ... }).
|
||
|
// description:
|
||
|
// Call specified function when event `type` occurs, ex: `myWidget.on("click", function(){ ... })`.
|
||
|
// Note that the function is not run in any particular scope, so if (for example) you want it to run in the
|
||
|
// widget's scope you must do `myWidget.on("click", lang.hitch(myWidget, func))`.
|
||
|
|
||
|
return aspect.after(this, this._onMap(type), func, true);
|
||
|
},
|
||
|
|
||
|
_onMap: function(/*String*/ type){
|
||
|
// summary:
|
||
|
// Maps on() type parameter (ex: "mousemove") to method name (ex: "onMouseMove")
|
||
|
var ctor = this.constructor, map = ctor._onMap;
|
||
|
if(!map){
|
||
|
map = (ctor._onMap = {});
|
||
|
for(var attr in ctor.prototype){
|
||
|
if(/^on/.test(attr)){
|
||
|
map[attr.replace(/^on/, "").toLowerCase()] = attr;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return map[type.toLowerCase()]; // String
|
||
|
},
|
||
|
|
||
|
toString: function(){
|
||
|
// summary:
|
||
|
// Returns a string that represents the widget
|
||
|
// description:
|
||
|
// When a widget is cast to a string, this method will be used to generate the
|
||
|
// output. Currently, it does not implement any sort of reversible
|
||
|
// serialization.
|
||
|
return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
|
||
|
},
|
||
|
|
||
|
getChildren: function(){
|
||
|
// summary:
|
||
|
// Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode.
|
||
|
// Does not return nested widgets, nor widgets that are part of this widget's template.
|
||
|
return this.containerNode ? registry.findWidgets(this.containerNode) : []; // dijit._Widget[]
|
||
|
},
|
||
|
|
||
|
getParent: function(){
|
||
|
// summary:
|
||
|
// Returns the parent widget of this widget
|
||
|
return registry.getEnclosingWidget(this.domNode.parentNode);
|
||
|
},
|
||
|
|
||
|
connect: function(
|
||
|
/*Object|null*/ obj,
|
||
|
/*String|Function*/ event,
|
||
|
/*String|Function*/ method){
|
||
|
// summary:
|
||
|
// Connects specified obj/event to specified method of this object
|
||
|
// and registers for disconnect() on widget destroy.
|
||
|
// description:
|
||
|
// Provide widget-specific analog to dojo.connect, except with the
|
||
|
// implicit use of this widget as the target object.
|
||
|
// Events connected with `this.connect` are disconnected upon
|
||
|
// destruction.
|
||
|
// returns:
|
||
|
// A handle that can be passed to `disconnect` in order to disconnect before
|
||
|
// the widget is destroyed.
|
||
|
// example:
|
||
|
// | var btn = new dijit.form.Button();
|
||
|
// | // when foo.bar() is called, call the listener we're going to
|
||
|
// | // provide in the scope of btn
|
||
|
// | btn.connect(foo, "bar", function(){
|
||
|
// | console.debug(this.toString());
|
||
|
// | });
|
||
|
// tags:
|
||
|
// protected
|
||
|
|
||
|
var handle = connect.connect(obj, event, this, method);
|
||
|
this._connects.push(handle);
|
||
|
return handle; // _Widget.Handle
|
||
|
},
|
||
|
|
||
|
disconnect: function(handle){
|
||
|
// summary:
|
||
|
// Disconnects handle created by `connect`.
|
||
|
// Also removes handle from this widget's list of connects.
|
||
|
// tags:
|
||
|
// protected
|
||
|
var i = array.indexOf(this._connects, handle);
|
||
|
if(i != -1){
|
||
|
handle.remove();
|
||
|
this._connects.splice(i, 1);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
subscribe: function(t, method){
|
||
|
// summary:
|
||
|
// Subscribes to the specified topic and calls the specified method
|
||
|
// of this object and registers for unsubscribe() on widget destroy.
|
||
|
// description:
|
||
|
// Provide widget-specific analog to dojo.subscribe, except with the
|
||
|
// implicit use of this widget as the target object.
|
||
|
// t: String
|
||
|
// The topic
|
||
|
// method: Function
|
||
|
// The callback
|
||
|
// example:
|
||
|
// | var btn = new dijit.form.Button();
|
||
|
// | // when /my/topic is published, this button changes its label to
|
||
|
// | // be the parameter of the topic.
|
||
|
// | btn.subscribe("/my/topic", function(v){
|
||
|
// | this.set("label", v);
|
||
|
// | });
|
||
|
// tags:
|
||
|
// protected
|
||
|
var handle = topic.subscribe(t, lang.hitch(this, method));
|
||
|
this._connects.push(handle);
|
||
|
return handle; // _Widget.Handle
|
||
|
},
|
||
|
|
||
|
unsubscribe: function(/*Object*/ handle){
|
||
|
// summary:
|
||
|
// Unsubscribes handle created by this.subscribe.
|
||
|
// Also removes handle from this widget's list of subscriptions
|
||
|
// tags:
|
||
|
// protected
|
||
|
this.disconnect(handle);
|
||
|
},
|
||
|
|
||
|
isLeftToRight: function(){
|
||
|
// summary:
|
||
|
// Return this widget's explicit or implicit orientation (true for LTR, false for RTL)
|
||
|
// tags:
|
||
|
// protected
|
||
|
return this.dir ? (this.dir == "ltr") : domGeometry.isBodyLtr(); //Boolean
|
||
|
},
|
||
|
|
||
|
isFocusable: function(){
|
||
|
// summary:
|
||
|
// Return true if this widget can currently be focused
|
||
|
// and false if not
|
||
|
return this.focus && (domStyle.get(this.domNode, "display") != "none");
|
||
|
},
|
||
|
|
||
|
placeAt: function(/* String|DomNode|_Widget */reference, /* String?|Int? */position){
|
||
|
// summary:
|
||
|
// Place this widget's domNode reference somewhere in the DOM based
|
||
|
// on standard domConstruct.place conventions, or passing a Widget reference that
|
||
|
// contains and addChild member.
|
||
|
//
|
||
|
// description:
|
||
|
// A convenience function provided in all _Widgets, providing a simple
|
||
|
// shorthand mechanism to put an existing (or newly created) Widget
|
||
|
// somewhere in the dom, and allow chaining.
|
||
|
//
|
||
|
// reference:
|
||
|
// The String id of a domNode, a domNode reference, or a reference to a Widget possessing
|
||
|
// an addChild method.
|
||
|
//
|
||
|
// position:
|
||
|
// If passed a string or domNode reference, the position argument
|
||
|
// accepts a string just as domConstruct.place does, one of: "first", "last",
|
||
|
// "before", or "after".
|
||
|
//
|
||
|
// If passed a _Widget reference, and that widget reference has an ".addChild" method,
|
||
|
// it will be called passing this widget instance into that method, supplying the optional
|
||
|
// position index passed.
|
||
|
//
|
||
|
// returns:
|
||
|
// dijit._Widget
|
||
|
// Provides a useful return of the newly created dijit._Widget instance so you
|
||
|
// can "chain" this function by instantiating, placing, then saving the return value
|
||
|
// to a variable.
|
||
|
//
|
||
|
// example:
|
||
|
// | // create a Button with no srcNodeRef, and place it in the body:
|
||
|
// | var button = new dijit.form.Button({ label:"click" }).placeAt(win.body());
|
||
|
// | // now, 'button' is still the widget reference to the newly created button
|
||
|
// | button.on("click", function(e){ console.log('click'); }));
|
||
|
//
|
||
|
// example:
|
||
|
// | // create a button out of a node with id="src" and append it to id="wrapper":
|
||
|
// | var button = new dijit.form.Button({},"src").placeAt("wrapper");
|
||
|
//
|
||
|
// example:
|
||
|
// | // place a new button as the first element of some div
|
||
|
// | var button = new dijit.form.Button({ label:"click" }).placeAt("wrapper","first");
|
||
|
//
|
||
|
// example:
|
||
|
// | // create a contentpane and add it to a TabContainer
|
||
|
// | var tc = dijit.byId("myTabs");
|
||
|
// | new dijit.layout.ContentPane({ href:"foo.html", title:"Wow!" }).placeAt(tc)
|
||
|
|
||
|
if(reference.declaredClass && reference.addChild){
|
||
|
reference.addChild(this, position);
|
||
|
}else{
|
||
|
domConstruct.place(this.domNode, reference, position);
|
||
|
}
|
||
|
return this;
|
||
|
},
|
||
|
|
||
|
getTextDir: function(/*String*/ text,/*String*/ originalDir){
|
||
|
// summary:
|
||
|
// Return direction of the text.
|
||
|
// The function overridden in the _BidiSupport module,
|
||
|
// its main purpose is to calculate the direction of the
|
||
|
// text, if was defined by the programmer through textDir.
|
||
|
// tags:
|
||
|
// protected.
|
||
|
return originalDir;
|
||
|
},
|
||
|
|
||
|
applyTextDir: function(/*===== element, text =====*/){
|
||
|
// summary:
|
||
|
// The function overridden in the _BidiSupport module,
|
||
|
// originally used for setting element.dir according to this.textDir.
|
||
|
// In this case does nothing.
|
||
|
// element: DOMNode
|
||
|
// text: String
|
||
|
// tags:
|
||
|
// protected.
|
||
|
}
|
||
|
});
|
||
|
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/View':function(){
|
||
|
define("dojox/mobile/View", [
|
||
|
"dojo/_base/kernel", // to test dojo.hash
|
||
|
"dojo/_base/array",
|
||
|
"dojo/_base/config",
|
||
|
"dojo/_base/connect",
|
||
|
"dojo/_base/declare",
|
||
|
"dojo/_base/lang",
|
||
|
"dojo/_base/sniff",
|
||
|
"dojo/_base/window",
|
||
|
"dojo/_base/Deferred",
|
||
|
"dojo/dom",
|
||
|
"dojo/dom-class",
|
||
|
"dojo/dom-geometry",
|
||
|
"dojo/dom-style",
|
||
|
// "dojo/hash", // optionally prereq'ed
|
||
|
"dijit/registry", // registry.byNode
|
||
|
"dijit/_Contained",
|
||
|
"dijit/_Container",
|
||
|
"dijit/_WidgetBase",
|
||
|
"./ViewController", // to load ViewController for you (no direct references)
|
||
|
"./transition"
|
||
|
], function(dojo, array, config, connect, declare, lang, has, win, Deferred, dom, domClass, domGeometry, domStyle, registry, Contained, Container, WidgetBase, ViewController, transitDeferred){
|
||
|
|
||
|
/*=====
|
||
|
var Contained = dijit._Contained;
|
||
|
var Container = dijit._Container;
|
||
|
var WidgetBase = dijit._WidgetBase;
|
||
|
var ViewController = dojox.mobile.ViewController;
|
||
|
=====*/
|
||
|
|
||
|
// module:
|
||
|
// dojox/mobile/View
|
||
|
// summary:
|
||
|
// A widget that represents a view that occupies the full screen
|
||
|
|
||
|
var dm = lang.getObject("dojox.mobile", true);
|
||
|
|
||
|
return declare("dojox.mobile.View", [WidgetBase, Container, Contained], {
|
||
|
// summary:
|
||
|
// A widget that represents a view that occupies the full screen
|
||
|
// description:
|
||
|
// View acts as a container for any HTML and/or widgets. An entire
|
||
|
// HTML page can have multiple View widgets and the user can
|
||
|
// navigate through the views back and forth without page
|
||
|
// transitions.
|
||
|
|
||
|
// selected: Boolean
|
||
|
// If true, the view is displayed at startup time.
|
||
|
selected: false,
|
||
|
|
||
|
// keepScrollPos: Boolean
|
||
|
// If true, the scroll position is kept between views.
|
||
|
keepScrollPos: true,
|
||
|
|
||
|
constructor: function(params, node){
|
||
|
if(node){
|
||
|
dom.byId(node).style.visibility = "hidden";
|
||
|
}
|
||
|
this._aw = has("android") >= 2.2 && has("android") < 3; // flag for android animation workaround
|
||
|
},
|
||
|
|
||
|
buildRendering: function(){
|
||
|
this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement("DIV");
|
||
|
this.domNode.className = "mblView";
|
||
|
this.connect(this.domNode, "webkitAnimationEnd", "onAnimationEnd");
|
||
|
this.connect(this.domNode, "webkitAnimationStart", "onAnimationStart");
|
||
|
if(!config['mblCSS3Transition']){
|
||
|
this.connect(this.domNode, "webkitTransitionEnd", "onAnimationEnd");
|
||
|
}
|
||
|
var id = location.href.match(/#(\w+)([^\w=]|$)/) ? RegExp.$1 : null;
|
||
|
|
||
|
this._visible = this.selected && !id || this.id == id;
|
||
|
|
||
|
if(this.selected){
|
||
|
dm._defaultView = this;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
startup: function(){
|
||
|
if(this._started){ return; }
|
||
|
var siblings = [];
|
||
|
var children = this.domNode.parentNode.childNodes;
|
||
|
var visible = false;
|
||
|
// check if a visible view exists
|
||
|
for(var i = 0; i < children.length; i++){
|
||
|
var c = children[i];
|
||
|
if(c.nodeType === 1 && domClass.contains(c, "mblView")){
|
||
|
siblings.push(c);
|
||
|
visible = visible || registry.byNode(c)._visible;
|
||
|
}
|
||
|
}
|
||
|
var _visible = this._visible;
|
||
|
// if no visible view exists, make the first view visible
|
||
|
if(siblings.length === 1 || (!visible && siblings[0] === this.domNode)){
|
||
|
_visible = true;
|
||
|
}
|
||
|
var _this = this;
|
||
|
setTimeout(function(){ // necessary to render the view correctly
|
||
|
if(!_visible){
|
||
|
_this.domNode.style.display = "none";
|
||
|
}else{
|
||
|
dm.currentView = _this; //TODO:1.8 reconsider this. currentView may not have a currently showing view when views are nested.
|
||
|
_this.onStartView();
|
||
|
connect.publish("/dojox/mobile/startView", [_this]);
|
||
|
}
|
||
|
if(_this.domNode.style.visibility != "visible"){ // this check is to avoid screen flickers
|
||
|
_this.domNode.style.visibility = "visible";
|
||
|
}
|
||
|
var parent = _this.getParent && _this.getParent();
|
||
|
if(!parent || !parent.resize){ // top level widget
|
||
|
_this.resize();
|
||
|
}
|
||
|
}, has("ie") ? 100 : 0); // give IE a little time to complete drawing
|
||
|
this.inherited(arguments);
|
||
|
},
|
||
|
|
||
|
resize: function(){
|
||
|
// summary:
|
||
|
// Calls resize() of each child widget.
|
||
|
array.forEach(this.getChildren(), function(child){
|
||
|
if(child.resize){ child.resize(); }
|
||
|
});
|
||
|
},
|
||
|
|
||
|
onStartView: function(){
|
||
|
// summary:
|
||
|
// Stub function to connect to from your application.
|
||
|
// description:
|
||
|
// Called only when this view is shown at startup time.
|
||
|
},
|
||
|
|
||
|
onBeforeTransitionIn: function(moveTo, dir, transition, context, method){
|
||
|
// summary:
|
||
|
// Stub function to connect to from your application.
|
||
|
// description:
|
||
|
// Called before the arriving transition occurs.
|
||
|
},
|
||
|
|
||
|
onAfterTransitionIn: function(moveTo, dir, transition, context, method){
|
||
|
// summary:
|
||
|
// Stub function to connect to from your application.
|
||
|
// description:
|
||
|
// Called after the arriving transition occurs.
|
||
|
},
|
||
|
|
||
|
onBeforeTransitionOut: function(moveTo, dir, transition, context, method){
|
||
|
// summary:
|
||
|
// Stub function to connect to from your application.
|
||
|
// description:
|
||
|
// Called before the leaving transition occurs.
|
||
|
},
|
||
|
|
||
|
onAfterTransitionOut: function(moveTo, dir, transition, context, method){
|
||
|
// summary:
|
||
|
// Stub function to connect to from your application.
|
||
|
// description:
|
||
|
// Called after the leaving transition occurs.
|
||
|
},
|
||
|
|
||
|
_saveState: function(moveTo, dir, transition, context, method){
|
||
|
this._context = context;
|
||
|
this._method = method;
|
||
|
if(transition == "none"){
|
||
|
transition = null;
|
||
|
}
|
||
|
this._moveTo = moveTo;
|
||
|
this._dir = dir;
|
||
|
this._transition = transition;
|
||
|
this._arguments = lang._toArray(arguments);
|
||
|
this._args = [];
|
||
|
if(context || method){
|
||
|
for(var i = 5; i < arguments.length; i++){
|
||
|
this._args.push(arguments[i]);
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_fixViewState: function(/*DomNode*/toNode){
|
||
|
// summary:
|
||
|
// Sanity check for view transition states.
|
||
|
// description:
|
||
|
// Sometimes uninitialization of Views fails after making view transition,
|
||
|
// and that results in failure of subsequent view transitions.
|
||
|
// This function does the uninitialization for all the sibling views.
|
||
|
var nodes = this.domNode.parentNode.childNodes;
|
||
|
for(var i = 0; i < nodes.length; i++){
|
||
|
var n = nodes[i];
|
||
|
if(n.nodeType === 1 && domClass.contains(n, "mblView")){
|
||
|
n.className = "mblView"; //TODO: Should remove classes one by one. This would clear user defined classes or even mblScrollableView.
|
||
|
}
|
||
|
}
|
||
|
toNode.className = "mblView"; // just in case toNode is a sibling of an ancestor.
|
||
|
},
|
||
|
|
||
|
convertToId: function(moveTo){
|
||
|
if(typeof(moveTo) == "string"){
|
||
|
// removes a leading hash mark (#) and params if exists
|
||
|
// ex. "#bar&myParam=0003" -> "bar"
|
||
|
moveTo.match(/^#?([^&?]+)/);
|
||
|
return RegExp.$1;
|
||
|
}
|
||
|
return moveTo;
|
||
|
},
|
||
|
|
||
|
performTransition: function(/*String*/moveTo, /*Number*/dir, /*String*/transition,
|
||
|
/*Object|null*/context, /*String|Function*/method /*optional args*/){
|
||
|
// summary:
|
||
|
// Function to perform the various types of view transitions, such as fade, slide, and flip.
|
||
|
// 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.
|
||
|
// dir: 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.
|
||
|
// transition: String
|
||
|
// A type of animated transition effect. You can choose from
|
||
|
// the standard transition types, "slide", "fade", "flip", or
|
||
|
// from the extended transition types, "cover", "coverv",
|
||
|
// "dissolve", "reveal", "revealv", "scaleIn",
|
||
|
// "scaleOut", "slidev", "swirl", "zoomIn", "zoomOut". If
|
||
|
// "none" is specified, transition occurs immediately without
|
||
|
// animation.
|
||
|
// context: Object
|
||
|
// The object that the callback function will receive as "this".
|
||
|
// method: String|Function
|
||
|
// A callback function that is called when the transition has been finished.
|
||
|
// A function reference, or name of a function in context.
|
||
|
// tags:
|
||
|
// public
|
||
|
//
|
||
|
// example:
|
||
|
// Transition backward to a view whose id is "foo" with the slide animation.
|
||
|
// | performTransition("foo", -1, "slide");
|
||
|
//
|
||
|
// example:
|
||
|
// Transition forward to a blank view, and then open another page.
|
||
|
// | performTransition(null, 1, "slide", null, function(){location.href = href;});
|
||
|
if(moveTo === "#"){ return; }
|
||
|
if(dojo.hash){
|
||
|
if(typeof(moveTo) == "string" && moveTo.charAt(0) == '#' && !dm._params){
|
||
|
dm._params = [];
|
||
|
for(var i = 0; i < arguments.length; i++){
|
||
|
dm._params.push(arguments[i]);
|
||
|
}
|
||
|
dojo.hash(moveTo);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
this._saveState.apply(this, arguments);
|
||
|
var toNode;
|
||
|
if(moveTo){
|
||
|
toNode = this.convertToId(moveTo);
|
||
|
}else{
|
||
|
if(!this._dummyNode){
|
||
|
this._dummyNode = win.doc.createElement("DIV");
|
||
|
win.body().appendChild(this._dummyNode);
|
||
|
}
|
||
|
toNode = this._dummyNode;
|
||
|
}
|
||
|
var fromNode = this.domNode;
|
||
|
var fromTop = fromNode.offsetTop;
|
||
|
toNode = this.toNode = dom.byId(toNode);
|
||
|
if(!toNode){ console.log("dojox.mobile.View#performTransition: destination view not found: "+moveTo); return; }
|
||
|
toNode.style.visibility = this._aw ? "visible" : "hidden";
|
||
|
toNode.style.display = "";
|
||
|
this._fixViewState(toNode);
|
||
|
var toWidget = registry.byNode(toNode);
|
||
|
if(toWidget){
|
||
|
// Now that the target view became visible, it's time to run resize()
|
||
|
if(config["mblAlwaysResizeOnTransition"] || !toWidget._resized){
|
||
|
dm.resizeAll(null, toWidget);
|
||
|
toWidget._resized = true;
|
||
|
}
|
||
|
|
||
|
if(transition && transition != "none"){
|
||
|
// Temporarily add padding to align with the fromNode while transition
|
||
|
toWidget.containerNode.style.paddingTop = fromTop + "px";
|
||
|
}
|
||
|
|
||
|
toWidget.movedFrom = fromNode.id;
|
||
|
}
|
||
|
|
||
|
this.onBeforeTransitionOut.apply(this, arguments);
|
||
|
connect.publish("/dojox/mobile/beforeTransitionOut", [this].concat(lang._toArray(arguments)));
|
||
|
if(toWidget){
|
||
|
// perform view transition keeping the scroll position
|
||
|
if(this.keepScrollPos && !this.getParent()){
|
||
|
var scrollTop = win.body().scrollTop || win.doc.documentElement.scrollTop || win.global.pageYOffset || 0;
|
||
|
fromNode._scrollTop = scrollTop;
|
||
|
var toTop = (dir == 1) ? 0 : (toNode._scrollTop || 0);
|
||
|
toNode.style.top = "0px";
|
||
|
if(scrollTop > 1 || toTop !== 0){
|
||
|
fromNode.style.top = toTop - scrollTop + "px";
|
||
|
if(config["mblHideAddressBar"] !== false){
|
||
|
setTimeout(function(){ // iPhone needs setTimeout
|
||
|
win.global.scrollTo(0, (toTop || 1));
|
||
|
}, 0);
|
||
|
}
|
||
|
}
|
||
|
}else{
|
||
|
toNode.style.top = "0px";
|
||
|
}
|
||
|
toWidget.onBeforeTransitionIn.apply(toWidget, arguments);
|
||
|
connect.publish("/dojox/mobile/beforeTransitionIn", [toWidget].concat(lang._toArray(arguments)));
|
||
|
}
|
||
|
if(!this._aw){
|
||
|
toNode.style.display = "none";
|
||
|
toNode.style.visibility = "visible";
|
||
|
}
|
||
|
|
||
|
if(dm._iw && dm.scrollable){ // Workaround for iPhone flicker issue (only when scrollable.js is loaded)
|
||
|
var ss = dm.getScreenSize();
|
||
|
// Show cover behind the view.
|
||
|
// cover's z-index is set to -10000, lower than z-index value specified in transition css.
|
||
|
win.body().appendChild(dm._iwBgCover);
|
||
|
domStyle.set(dm._iwBgCover, {
|
||
|
position: "absolute",
|
||
|
top: "0px",
|
||
|
left: "0px",
|
||
|
height: (ss.h + 1) + "px", // "+1" means the height of scrollTo(0,1)
|
||
|
width: ss.w + "px",
|
||
|
backgroundColor: domStyle.get(win.body(), "background-color"),
|
||
|
zIndex: -10000,
|
||
|
display: ""
|
||
|
});
|
||
|
// Show toNode behind the cover.
|
||
|
domStyle.set(toNode, {
|
||
|
position: "absolute",
|
||
|
zIndex: -10001,
|
||
|
visibility: "visible",
|
||
|
display: ""
|
||
|
});
|
||
|
// setTimeout seems to be necessary to avoid flicker.
|
||
|
// Also the duration of setTimeout should be long enough to avoid flicker.
|
||
|
// 0 is not effective. 50 sometimes causes flicker.
|
||
|
setTimeout(lang.hitch(this, function(){
|
||
|
this._doTransition(fromNode, toNode, transition, dir);
|
||
|
}), 80);
|
||
|
}else{
|
||
|
this._doTransition(fromNode, toNode, transition, dir);
|
||
|
}
|
||
|
},
|
||
|
_toCls: function(s){
|
||
|
// convert from transition name to corresponding class name
|
||
|
// ex. "slide" -> "mblSlide"
|
||
|
return "mbl"+s.charAt(0).toUpperCase() + s.substring(1);
|
||
|
},
|
||
|
|
||
|
_doTransition: function(fromNode, toNode, transition, dir){
|
||
|
var rev = (dir == -1) ? " mblReverse" : "";
|
||
|
if(dm._iw && dm.scrollable){ // Workaround for iPhone flicker issue (only when scrollable.js is loaded)
|
||
|
// Show toNode after flicker ends
|
||
|
domStyle.set(toNode, {
|
||
|
position: "",
|
||
|
zIndex: ""
|
||
|
});
|
||
|
// Remove cover
|
||
|
win.body().removeChild(dm._iwBgCover);
|
||
|
}else if(!this._aw){
|
||
|
toNode.style.display = "";
|
||
|
}
|
||
|
if(!transition || transition == "none"){
|
||
|
this.domNode.style.display = "none";
|
||
|
this.invokeCallback();
|
||
|
}else if(config['mblCSS3Transition']){
|
||
|
//get dojox/css3/transit first
|
||
|
Deferred.when(transitDeferred, lang.hitch(this, function(transit){
|
||
|
//follow the style of .mblView.mblIn in View.css
|
||
|
//need to set the toNode to absolute position
|
||
|
var toPosition = domStyle.get(toNode, "position");
|
||
|
domStyle.set(toNode, "position", "absolute");
|
||
|
Deferred.when(transit(fromNode, toNode, {transition: transition, reverse: (dir===-1)?true:false}),lang.hitch(this,function(){
|
||
|
domStyle.set(toNode, "position", toPosition);
|
||
|
this.invokeCallback();
|
||
|
}));
|
||
|
}));
|
||
|
}else{
|
||
|
var s = this._toCls(transition);
|
||
|
domClass.add(fromNode, s + " mblOut" + rev);
|
||
|
domClass.add(toNode, s + " mblIn" + rev);
|
||
|
setTimeout(function(){
|
||
|
domClass.add(fromNode, "mblTransition");
|
||
|
domClass.add(toNode, "mblTransition");
|
||
|
}, 100);
|
||
|
// set transform origin
|
||
|
var fromOrigin = "50% 50%";
|
||
|
var toOrigin = "50% 50%";
|
||
|
var scrollTop, posX, posY;
|
||
|
if(transition.indexOf("swirl") != -1 || transition.indexOf("zoom") != -1){
|
||
|
if(this.keepScrollPos && !this.getParent()){
|
||
|
scrollTop = win.body().scrollTop || win.doc.documentElement.scrollTop || win.global.pageYOffset || 0;
|
||
|
}else{
|
||
|
scrollTop = -domGeometry.position(fromNode, true).y;
|
||
|
}
|
||
|
posY = win.global.innerHeight / 2 + scrollTop;
|
||
|
fromOrigin = "50% " + posY + "px";
|
||
|
toOrigin = "50% " + posY + "px";
|
||
|
}else if(transition.indexOf("scale") != -1){
|
||
|
var viewPos = domGeometry.position(fromNode, true);
|
||
|
posX = ((this.clickedPosX !== undefined) ? this.clickedPosX : win.global.innerWidth / 2) - viewPos.x;
|
||
|
if(this.keepScrollPos && !this.getParent()){
|
||
|
scrollTop = win.body().scrollTop || win.doc.documentElement.scrollTop || win.global.pageYOffset || 0;
|
||
|
}else{
|
||
|
scrollTop = -viewPos.y;
|
||
|
}
|
||
|
posY = ((this.clickedPosY !== undefined) ? this.clickedPosY : win.global.innerHeight / 2) + scrollTop;
|
||
|
fromOrigin = posX + "px " + posY + "px";
|
||
|
toOrigin = posX + "px " + posY + "px";
|
||
|
}
|
||
|
domStyle.set(fromNode, {webkitTransformOrigin:fromOrigin});
|
||
|
domStyle.set(toNode, {webkitTransformOrigin:toOrigin});
|
||
|
}
|
||
|
dm.currentView = registry.byNode(toNode);
|
||
|
},
|
||
|
|
||
|
onAnimationStart: function(e){
|
||
|
},
|
||
|
|
||
|
|
||
|
onAnimationEnd: function(e){
|
||
|
var name = e.animationName || e.target.className;
|
||
|
if(name.indexOf("Out") === -1 &&
|
||
|
name.indexOf("In") === -1 &&
|
||
|
name.indexOf("Shrink") === -1){ return; }
|
||
|
var isOut = false;
|
||
|
if(domClass.contains(this.domNode, "mblOut")){
|
||
|
isOut = true;
|
||
|
this.domNode.style.display = "none";
|
||
|
domClass.remove(this.domNode, [this._toCls(this._transition), "mblIn", "mblOut", "mblReverse"]);
|
||
|
}else{
|
||
|
// Reset the temporary padding
|
||
|
this.containerNode.style.paddingTop = "";
|
||
|
}
|
||
|
domStyle.set(this.domNode, {webkitTransformOrigin:""});
|
||
|
if(name.indexOf("Shrink") !== -1){
|
||
|
var li = e.target;
|
||
|
li.style.display = "none";
|
||
|
domClass.remove(li, "mblCloseContent");
|
||
|
}
|
||
|
if(isOut){
|
||
|
this.invokeCallback();
|
||
|
}
|
||
|
// this.domNode may be destroyed as a result of invoking the callback,
|
||
|
// so check for that before accessing it.
|
||
|
this.domNode && (this.domNode.className = "mblView");
|
||
|
|
||
|
// clear the clicked position
|
||
|
this.clickedPosX = this.clickedPosY = undefined;
|
||
|
},
|
||
|
|
||
|
invokeCallback: function(){
|
||
|
this.onAfterTransitionOut.apply(this, this._arguments);
|
||
|
connect.publish("/dojox/mobile/afterTransitionOut", [this].concat(this._arguments));
|
||
|
var toWidget = registry.byNode(this.toNode);
|
||
|
if(toWidget){
|
||
|
toWidget.onAfterTransitionIn.apply(toWidget, this._arguments);
|
||
|
connect.publish("/dojox/mobile/afterTransitionIn", [toWidget].concat(this._arguments));
|
||
|
toWidget.movedFrom = undefined;
|
||
|
}
|
||
|
|
||
|
var c = this._context, m = this._method;
|
||
|
if(!c && !m){ return; }
|
||
|
if(!m){
|
||
|
m = c;
|
||
|
c = null;
|
||
|
}
|
||
|
c = c || win.global;
|
||
|
if(typeof(m) == "string"){
|
||
|
c[m].apply(c, this._args);
|
||
|
}else{
|
||
|
m.apply(c, this._args);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
getShowingView: function(){
|
||
|
// summary:
|
||
|
// Find the currently showing view from my sibling views.
|
||
|
// description:
|
||
|
// Note that dojox.mobile.currentView is the last shown view.
|
||
|
// If the page consists of a splitter, there are multiple showing views.
|
||
|
var nodes = this.domNode.parentNode.childNodes;
|
||
|
for(var i = 0; i < nodes.length; i++){
|
||
|
var n = nodes[i];
|
||
|
if(n.nodeType === 1 && domClass.contains(n, "mblView") && domStyle.get(n, "display") !== "none"){
|
||
|
return registry.byNode(n);
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
},
|
||
|
|
||
|
show: function(){
|
||
|
// summary:
|
||
|
// Shows this view without a transition animation.
|
||
|
var view = this.getShowingView();
|
||
|
if(view){
|
||
|
view.domNode.style.display = "none"; // from-style
|
||
|
}
|
||
|
this.domNode.style.display = ""; // to-style
|
||
|
dm.currentView = this;
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/main':function(){
|
||
|
define(["dojo/_base/kernel"], function(dojo) {
|
||
|
// module:
|
||
|
// dojox/main
|
||
|
// summary:
|
||
|
// The dojox package main module; dojox package is somewhat unusual in that the main module currently just provides an empty object.
|
||
|
|
||
|
return dojo.dojox;
|
||
|
});
|
||
|
},
|
||
|
'dojox/mobile/transition':function(){
|
||
|
define([
|
||
|
"dojo/_base/Deferred",
|
||
|
"dojo/_base/config"
|
||
|
], function(Deferred, config){
|
||
|
/* summary: this is the wrapper module which load
|
||
|
* dojox/css3/transit conditionally. If mblCSS3Transition
|
||
|
* is set to 'dojox/css3/transit', it will be loaded as
|
||
|
* the module to conduct the view transition.
|
||
|
*/
|
||
|
if(config['mblCSS3Transition']){
|
||
|
//require dojox/css3/transit and resolve it as the result of transitDeferred.
|
||
|
var transitDeferred = new Deferred();
|
||
|
require([config['mblCSS3Transition']], function(transit){
|
||
|
transitDeferred.resolve(transit);
|
||
|
});
|
||
|
return transitDeferred;
|
||
|
}
|
||
|
return null;
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojo/Stateful':function(){
|
||
|
define(["./_base/kernel", "./_base/declare", "./_base/lang", "./_base/array"], function(dojo, declare, lang, array) {
|
||
|
// module:
|
||
|
// dojo/Stateful
|
||
|
// summary:
|
||
|
// TODOC
|
||
|
|
||
|
return dojo.declare("dojo.Stateful", null, {
|
||
|
// summary:
|
||
|
// Base class for objects that provide named properties with optional getter/setter
|
||
|
// control and the ability to watch for property changes
|
||
|
// example:
|
||
|
// | var obj = new dojo.Stateful();
|
||
|
// | obj.watch("foo", function(){
|
||
|
// | console.log("foo changed to " + this.get("foo"));
|
||
|
// | });
|
||
|
// | obj.set("foo","bar");
|
||
|
postscript: function(mixin){
|
||
|
if(mixin){
|
||
|
lang.mixin(this, mixin);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
get: function(/*String*/name){
|
||
|
// summary:
|
||
|
// Get a property on a Stateful instance.
|
||
|
// name:
|
||
|
// The property to get.
|
||
|
// returns:
|
||
|
// The property value on this Stateful instance.
|
||
|
// description:
|
||
|
// Get a named property on a Stateful object. The property may
|
||
|
// potentially be retrieved via a getter method in subclasses. In the base class
|
||
|
// this just retrieves the object's property.
|
||
|
// For example:
|
||
|
// | stateful = new dojo.Stateful({foo: 3});
|
||
|
// | stateful.get("foo") // returns 3
|
||
|
// | stateful.foo // returns 3
|
||
|
|
||
|
return this[name]; //Any
|
||
|
},
|
||
|
set: function(/*String*/name, /*Object*/value){
|
||
|
// summary:
|
||
|
// Set a property on a Stateful instance
|
||
|
// name:
|
||
|
// The property to set.
|
||
|
// value:
|
||
|
// The value to set in the property.
|
||
|
// returns:
|
||
|
// The function returns this dojo.Stateful instance.
|
||
|
// description:
|
||
|
// Sets named properties on a stateful object and notifies any watchers of
|
||
|
// the property. A programmatic setter may be defined in subclasses.
|
||
|
// For example:
|
||
|
// | stateful = new dojo.Stateful();
|
||
|
// | stateful.watch(function(name, oldValue, value){
|
||
|
// | // this will be called on the set below
|
||
|
// | }
|
||
|
// | stateful.set(foo, 5);
|
||
|
//
|
||
|
// set() may also be called with a hash of name/value pairs, ex:
|
||
|
// | myObj.set({
|
||
|
// | foo: "Howdy",
|
||
|
// | bar: 3
|
||
|
// | })
|
||
|
// This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
|
||
|
if(typeof name === "object"){
|
||
|
for(var x in name){
|
||
|
this.set(x, name[x]);
|
||
|
}
|
||
|
return this;
|
||
|
}
|
||
|
var oldValue = this[name];
|
||
|
this[name] = value;
|
||
|
if(this._watchCallbacks){
|
||
|
this._watchCallbacks(name, oldValue, value);
|
||
|
}
|
||
|
return this; //dojo.Stateful
|
||
|
},
|
||
|
watch: function(/*String?*/name, /*Function*/callback){
|
||
|
// summary:
|
||
|
// Watches a property for changes
|
||
|
// name:
|
||
|
// Indicates the property to watch. This is optional (the callback may be the
|
||
|
// only parameter), and if omitted, all the properties will be watched
|
||
|
// returns:
|
||
|
// An object handle for the watch. The unwatch method of this object
|
||
|
// can be used to discontinue watching this property:
|
||
|
// | var watchHandle = obj.watch("foo", callback);
|
||
|
// | watchHandle.unwatch(); // callback won't be called now
|
||
|
// callback:
|
||
|
// The function to execute when the property changes. This will be called after
|
||
|
// the property has been changed. The callback will be called with the |this|
|
||
|
// set to the instance, the first argument as the name of the property, the
|
||
|
// second argument as the old value and the third argument as the new value.
|
||
|
|
||
|
var callbacks = this._watchCallbacks;
|
||
|
if(!callbacks){
|
||
|
var self = this;
|
||
|
callbacks = this._watchCallbacks = function(name, oldValue, value, ignoreCatchall){
|
||
|
var notify = function(propertyCallbacks){
|
||
|
if(propertyCallbacks){
|
||
|
propertyCallbacks = propertyCallbacks.slice();
|
||
|
for(var i = 0, l = propertyCallbacks.length; i < l; i++){
|
||
|
try{
|
||
|
propertyCallbacks[i].call(self, name, oldValue, value);
|
||
|
}catch(e){
|
||
|
console.error(e);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
notify(callbacks['_' + name]);
|
||
|
if(!ignoreCatchall){
|
||
|
notify(callbacks["*"]); // the catch-all
|
||
|
}
|
||
|
}; // we use a function instead of an object so it will be ignored by JSON conversion
|
||
|
}
|
||
|
if(!callback && typeof name === "function"){
|
||
|
callback = name;
|
||
|
name = "*";
|
||
|
}else{
|
||
|
// prepend with dash to prevent name conflicts with function (like "name" property)
|
||
|
name = '_' + name;
|
||
|
}
|
||
|
var propertyCallbacks = callbacks[name];
|
||
|
if(typeof propertyCallbacks !== "object"){
|
||
|
propertyCallbacks = callbacks[name] = [];
|
||
|
}
|
||
|
propertyCallbacks.push(callback);
|
||
|
return {
|
||
|
unwatch: function(){
|
||
|
propertyCallbacks.splice(array.indexOf(propertyCallbacks, callback), 1);
|
||
|
}
|
||
|
}; //Object
|
||
|
}
|
||
|
|
||
|
});
|
||
|
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/Heading':function(){
|
||
|
define([
|
||
|
"dojo/_base/array",
|
||
|
"dojo/_base/connect",
|
||
|
"dojo/_base/declare",
|
||
|
"dojo/_base/lang",
|
||
|
"dojo/_base/window",
|
||
|
"dojo/dom-class",
|
||
|
"dojo/dom-construct",
|
||
|
"dojo/dom-style",
|
||
|
"dijit/registry", // registry.byId
|
||
|
"dijit/_Contained",
|
||
|
"dijit/_Container",
|
||
|
"dijit/_WidgetBase",
|
||
|
"./View"
|
||
|
], function(array, connect, declare, lang, win, domClass, domConstruct, domStyle, registry, Contained, Container, WidgetBase, View){
|
||
|
|
||
|
var dm = lang.getObject("dojox.mobile", true);
|
||
|
|
||
|
/*=====
|
||
|
var Contained = dijit._Contained;
|
||
|
var Container = dijit._Container;
|
||
|
var WidgetBase = dijit._WidgetBase;
|
||
|
=====*/
|
||
|
|
||
|
// module:
|
||
|
// dojox/mobile/Heading
|
||
|
// summary:
|
||
|
// A widget that represents a navigation bar.
|
||
|
|
||
|
return declare("dojox.mobile.Heading", [WidgetBase, Container, Contained],{
|
||
|
// summary:
|
||
|
// A widget that represents a navigation bar.
|
||
|
// description:
|
||
|
// Heading is a widget that represents a navigation bar, which
|
||
|
// usually appears at the top of an application. It usually
|
||
|
// displays the title of the current view and can contain a
|
||
|
// navigational control. If you use it with
|
||
|
// dojox.mobile.ScrollableView, it can also be used as a fixed
|
||
|
// header bar or a fixed footer bar. In such cases, specify the
|
||
|
// fixed="top" attribute to be a fixed header bar or the
|
||
|
// fixed="bottom" attribute to be a fixed footer bar. Heading can
|
||
|
// have one or more ToolBarButton widgets as its children.
|
||
|
|
||
|
// back: String
|
||
|
// A label for the navigational control to return to the previous
|
||
|
// View.
|
||
|
back: "",
|
||
|
|
||
|
// href: String
|
||
|
// A URL to open when the navigational control is pressed.
|
||
|
href: "",
|
||
|
|
||
|
// 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: "",
|
||
|
|
||
|
// transition: String
|
||
|
// A type of animated transition effect. You can choose from the
|
||
|
// standard transition types, "slide", "fade", "flip", or from the
|
||
|
// extended transition types, "cover", "coverv", "dissolve",
|
||
|
// "reveal", "revealv", "scaleIn", "scaleOut", "slidev",
|
||
|
// "swirl", "zoomIn", "zoomOut". If "none" is specified, transition
|
||
|
// occurs immediately without animation.
|
||
|
transition: "slide",
|
||
|
|
||
|
// label: String
|
||
|
// A title text of the heading. If the label is not specified, the
|
||
|
// innerHTML of the node is used as a label.
|
||
|
label: "",
|
||
|
|
||
|
// iconBase: String
|
||
|
// The default icon path for child items.
|
||
|
iconBase: "",
|
||
|
|
||
|
// backProp: Object
|
||
|
// Properties for the back button.
|
||
|
backProp: {className: "mblArrowButton"},
|
||
|
|
||
|
// tag: String
|
||
|
// A name of html tag to create as domNode.
|
||
|
tag: "H1",
|
||
|
|
||
|
buildRendering: function(){
|
||
|
this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement(this.tag);
|
||
|
this.domNode.className = "mblHeading";
|
||
|
if(!this.label){
|
||
|
array.forEach(this.domNode.childNodes, function(n){
|
||
|
if(n.nodeType == 3){
|
||
|
var v = lang.trim(n.nodeValue);
|
||
|
if(v){
|
||
|
this.label = v;
|
||
|
this.labelNode = domConstruct.create("SPAN", {innerHTML:v}, n, "replace");
|
||
|
}
|
||
|
}
|
||
|
}, this);
|
||
|
}
|
||
|
if(!this.labelNode){
|
||
|
this.labelNode = domConstruct.create("SPAN", null, this.domNode);
|
||
|
}
|
||
|
this.labelNode.className = "mblHeadingSpanTitle";
|
||
|
this.labelDivNode = domConstruct.create("DIV", {
|
||
|
className: "mblHeadingDivTitle",
|
||
|
innerHTML: this.labelNode.innerHTML
|
||
|
}, this.domNode);
|
||
|
},
|
||
|
|
||
|
startup: function(){
|
||
|
if(this._started){ return; }
|
||
|
var parent = this.getParent && this.getParent();
|
||
|
if(!parent || !parent.resize){ // top level widget
|
||
|
var _this = this;
|
||
|
setTimeout(function(){ // necessary to render correctly
|
||
|
_this.resize();
|
||
|
}, 0);
|
||
|
}
|
||
|
this.inherited(arguments);
|
||
|
},
|
||
|
|
||
|
resize: function(){
|
||
|
if(this._btn){
|
||
|
this._btn.style.width = this._body.offsetWidth + this._head.offsetWidth + "px";
|
||
|
}
|
||
|
if(this.labelNode){
|
||
|
// find the rightmost left button (B), and leftmost right button (C)
|
||
|
// +-----------------------------+
|
||
|
// | |A| |B| |C| |D| |
|
||
|
// +-----------------------------+
|
||
|
var leftBtn, rightBtn;
|
||
|
var children = this.containerNode.childNodes;
|
||
|
for(var i = children.length - 1; i >= 0; i--){
|
||
|
var c = children[i];
|
||
|
if(c.nodeType === 1){
|
||
|
if(!rightBtn && domClass.contains(c, "mblToolBarButton") && domStyle.get(c, "float") === "right"){
|
||
|
rightBtn = c;
|
||
|
}
|
||
|
if(!leftBtn && (domClass.contains(c, "mblToolBarButton") && domStyle.get(c, "float") === "left" || c === this._btn)){
|
||
|
leftBtn = c;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(!this.labelNodeLen && this.label){
|
||
|
this.labelNode.style.display = "inline";
|
||
|
this.labelNodeLen = this.labelNode.offsetWidth;
|
||
|
this.labelNode.style.display = "";
|
||
|
}
|
||
|
|
||
|
var bw = this.domNode.offsetWidth; // bar width
|
||
|
var rw = rightBtn ? bw - rightBtn.offsetLeft + 5 : 0; // rightBtn width
|
||
|
var lw = leftBtn ? leftBtn.offsetLeft + leftBtn.offsetWidth + 5 : 0; // leftBtn width
|
||
|
var tw = this.labelNodeLen || 0; // title width
|
||
|
domClass[bw - Math.max(rw,lw)*2 > tw ? "add" : "remove"](this.domNode, "mblHeadingCenterTitle");
|
||
|
}
|
||
|
array.forEach(this.getChildren(), function(child){
|
||
|
if(child.resize){ child.resize(); }
|
||
|
});
|
||
|
},
|
||
|
|
||
|
_setBackAttr: function(/*String*/back){
|
||
|
if (!back){
|
||
|
domConstruct.destroy(this._btn);
|
||
|
this._btn = null;
|
||
|
this.back = "";
|
||
|
}else{
|
||
|
if(!this._btn){
|
||
|
var btn = domConstruct.create("DIV", this.backProp, this.domNode, "first");
|
||
|
var head = domConstruct.create("DIV", {className:"mblArrowButtonHead"}, btn);
|
||
|
var body = domConstruct.create("DIV", {className:"mblArrowButtonBody mblArrowButtonText"}, btn);
|
||
|
|
||
|
this._body = body;
|
||
|
this._head = head;
|
||
|
this._btn = btn;
|
||
|
this.backBtnNode = btn;
|
||
|
this.connect(body, "onclick", "onClick");
|
||
|
}
|
||
|
this.back = back;
|
||
|
this._body.innerHTML = this._cv ? this._cv(this.back) : this.back;
|
||
|
}
|
||
|
this.resize();
|
||
|
},
|
||
|
|
||
|
_setLabelAttr: function(/*String*/label){
|
||
|
this.label = label;
|
||
|
this.labelNode.innerHTML = this.labelDivNode.innerHTML = this._cv ? this._cv(label) : label;
|
||
|
},
|
||
|
|
||
|
findCurrentView: function(){
|
||
|
// summary:
|
||
|
// Search for the view widget that contains this widget.
|
||
|
var w = this;
|
||
|
while(true){
|
||
|
w = w.getParent();
|
||
|
if(!w){ return null; }
|
||
|
if(w instanceof View){ break; }
|
||
|
}
|
||
|
return w;
|
||
|
},
|
||
|
|
||
|
onClick: function(e){
|
||
|
var h1 = this.domNode;
|
||
|
domClass.add(h1, "mblArrowButtonSelected");
|
||
|
setTimeout(function(){
|
||
|
domClass.remove(h1, "mblArrowButtonSelected");
|
||
|
}, 1000);
|
||
|
|
||
|
if(this.back && !this.moveTo && !this.href && history){
|
||
|
history.back();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// keep the clicked position for transition animations
|
||
|
var view = this.findCurrentView();
|
||
|
if(view){
|
||
|
view.clickedPosX = e.clientX;
|
||
|
view.clickedPosY = e.clientY;
|
||
|
}
|
||
|
this.goTo(this.moveTo, this.href);
|
||
|
},
|
||
|
|
||
|
goTo: function(moveTo, href){
|
||
|
// summary:
|
||
|
// Given the destination, makes a view transition.
|
||
|
var view = this.findCurrentView();
|
||
|
if(!view){ return; }
|
||
|
if(href){
|
||
|
view.performTransition(null, -1, this.transition, this, function(){location.href = href;});
|
||
|
}else{
|
||
|
if(dm.app && dm.app.STAGE_CONTROLLER_ACTIVE){
|
||
|
// If in a full mobile app, then use its mechanisms to move back a scene
|
||
|
connect.publish("/dojox/mobile/app/goback");
|
||
|
}else{
|
||
|
// Basically transition should be performed between two
|
||
|
// siblings that share the same parent.
|
||
|
// However, when views are nested and transition occurs from
|
||
|
// an inner view, search for an ancestor view that is a sibling
|
||
|
// of the target view, and use it as a source view.
|
||
|
var node = registry.byId(view.convertToId(moveTo));
|
||
|
if(node){
|
||
|
var parent = node.getParent();
|
||
|
while(view){
|
||
|
var myParent = view.getParent();
|
||
|
if(parent === myParent){
|
||
|
break;
|
||
|
}
|
||
|
view = myParent;
|
||
|
}
|
||
|
}
|
||
|
if(view){
|
||
|
view.performTransition(moveTo, -1, this.transition);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/Switch':function(){
|
||
|
define([
|
||
|
"dojo/_base/array",
|
||
|
"dojo/_base/connect",
|
||
|
"dojo/_base/declare",
|
||
|
"dojo/_base/event",
|
||
|
"dojo/_base/window",
|
||
|
"dojo/dom-class",
|
||
|
"dijit/_Contained",
|
||
|
"dijit/_WidgetBase",
|
||
|
"./sniff"
|
||
|
], function(array, connect, declare, event, win, domClass, Contained, WidgetBase, has){
|
||
|
|
||
|
/*=====
|
||
|
Contained = dijit._Contained;
|
||
|
WidgetBase = dijit._WidgetBase;
|
||
|
=====*/
|
||
|
|
||
|
// module:
|
||
|
// dojox/mobile/Switch
|
||
|
// summary:
|
||
|
// A toggle switch with a sliding knob.
|
||
|
|
||
|
return declare("dojox.mobile.Switch", [WidgetBase, Contained],{
|
||
|
// summary:
|
||
|
// A toggle switch with a sliding knob.
|
||
|
// description:
|
||
|
// Switch is a toggle switch with a sliding knob. You can either
|
||
|
// tap or slide the knob to toggle the switch. The onStateChanged
|
||
|
// handler is called when the switch is manipulated.
|
||
|
|
||
|
// value: String
|
||
|
// The initial state of the switch. "on" or "off". The default
|
||
|
// value is "on".
|
||
|
value: "on",
|
||
|
|
||
|
// name: String
|
||
|
// A name for a hidden input field, which holds the current value.
|
||
|
name: "",
|
||
|
|
||
|
// leftLabel: String
|
||
|
// The left-side label of the switch.
|
||
|
leftLabel: "ON",
|
||
|
|
||
|
// rightLabel: String
|
||
|
// The right-side label of the switch.
|
||
|
rightLabel: "OFF",
|
||
|
|
||
|
/* internal properties */
|
||
|
_width: 53,
|
||
|
|
||
|
buildRendering: function(){
|
||
|
this.domNode = win.doc.createElement("DIV");
|
||
|
var c = (this.srcNodeRef && this.srcNodeRef.className) || this.className || this["class"];
|
||
|
this._swClass = (c || "").replace(/ .*/,"");
|
||
|
this.domNode.className = "mblSwitch";
|
||
|
var nameAttr = this.name ? " name=\"" + this.name + "\"" : "";
|
||
|
this.domNode.innerHTML =
|
||
|
'<div class="mblSwitchInner">'
|
||
|
+ '<div class="mblSwitchBg mblSwitchBgLeft">'
|
||
|
+ '<div class="mblSwitchText mblSwitchTextLeft"></div>'
|
||
|
+ '</div>'
|
||
|
+ '<div class="mblSwitchBg mblSwitchBgRight">'
|
||
|
+ '<div class="mblSwitchText mblSwitchTextRight"></div>'
|
||
|
+ '</div>'
|
||
|
+ '<div class="mblSwitchKnob"></div>'
|
||
|
+ '<input type="hidden"'+nameAttr+'></div>'
|
||
|
+ '</div>';
|
||
|
var n = this.inner = this.domNode.firstChild;
|
||
|
this.left = n.childNodes[0];
|
||
|
this.right = n.childNodes[1];
|
||
|
this.knob = n.childNodes[2];
|
||
|
this.input = n.childNodes[3];
|
||
|
},
|
||
|
|
||
|
postCreate: function(){
|
||
|
this.connect(this.domNode, "onclick", "onClick");
|
||
|
this.connect(this.domNode, has("touch") ? "touchstart" : "onmousedown", "onTouchStart");
|
||
|
this._initialValue = this.value; // for reset()
|
||
|
},
|
||
|
|
||
|
_changeState: function(/*String*/state, /*Boolean*/anim){
|
||
|
var on = (state === "on");
|
||
|
this.left.style.display = "";
|
||
|
this.right.style.display = "";
|
||
|
this.inner.style.left = "";
|
||
|
if(anim){
|
||
|
domClass.add(this.domNode, "mblSwitchAnimation");
|
||
|
}
|
||
|
domClass.remove(this.domNode, on ? "mblSwitchOff" : "mblSwitchOn");
|
||
|
domClass.add(this.domNode, on ? "mblSwitchOn" : "mblSwitchOff");
|
||
|
|
||
|
var _this = this;
|
||
|
setTimeout(function(){
|
||
|
_this.left.style.display = on ? "" : "none";
|
||
|
_this.right.style.display = !on ? "" : "none";
|
||
|
domClass.remove(_this.domNode, "mblSwitchAnimation");
|
||
|
}, anim ? 300 : 0);
|
||
|
},
|
||
|
|
||
|
startup: function(){
|
||
|
if(this._swClass.indexOf("Round") != -1){
|
||
|
var r = Math.round(this.domNode.offsetHeight / 2);
|
||
|
this.createRoundMask(this._swClass, r, this.domNode.offsetWidth);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
createRoundMask: function(className, r, w){
|
||
|
if(!has("webkit") || !className){ return; }
|
||
|
if(!this._createdMasks){ this._createdMasks = []; }
|
||
|
if(this._createdMasks[className]){ return; }
|
||
|
this._createdMasks[className] = 1;
|
||
|
|
||
|
var ctx = win.doc.getCSSCanvasContext("2d", className+"Mask", w, 100);
|
||
|
ctx.fillStyle = "#000000";
|
||
|
ctx.beginPath();
|
||
|
ctx.moveTo(r, 0);
|
||
|
ctx.arcTo(0, 0, 0, 2*r, r);
|
||
|
ctx.arcTo(0, 2*r, r, 2*r, r);
|
||
|
ctx.lineTo(w - r, 2*r);
|
||
|
ctx.arcTo(w, 2*r, w, r, r);
|
||
|
ctx.arcTo(w, 0, w - r, 0, r);
|
||
|
ctx.closePath();
|
||
|
ctx.fill();
|
||
|
},
|
||
|
|
||
|
onClick: function(e){
|
||
|
if(this._moved){ return; }
|
||
|
this.value = this.input.value = (this.value == "on") ? "off" : "on";
|
||
|
this._changeState(this.value, true);
|
||
|
this.onStateChanged(this.value);
|
||
|
},
|
||
|
|
||
|
onTouchStart: function(e){
|
||
|
// summary:
|
||
|
// Internal function to handle touchStart events.
|
||
|
this._moved = false;
|
||
|
this.innerStartX = this.inner.offsetLeft;
|
||
|
if(!this._conn){
|
||
|
this._conn = [];
|
||
|
this._conn.push(connect.connect(this.inner, has("touch") ? "touchmove" : "onmousemove", this, "onTouchMove"));
|
||
|
this._conn.push(connect.connect(this.inner, has("touch") ? "touchend" : "onmouseup", this, "onTouchEnd"));
|
||
|
}
|
||
|
this.touchStartX = e.touches ? e.touches[0].pageX : e.clientX;
|
||
|
this.left.style.display = "";
|
||
|
this.right.style.display = "";
|
||
|
event.stop(e);
|
||
|
},
|
||
|
|
||
|
onTouchMove: function(e){
|
||
|
// summary:
|
||
|
// Internal function to handle touchMove events.
|
||
|
e.preventDefault();
|
||
|
var dx;
|
||
|
if(e.targetTouches){
|
||
|
if(e.targetTouches.length != 1){ return false; }
|
||
|
dx = e.targetTouches[0].clientX - this.touchStartX;
|
||
|
}else{
|
||
|
dx = e.clientX - this.touchStartX;
|
||
|
}
|
||
|
var pos = this.innerStartX + dx;
|
||
|
var d = 10;
|
||
|
if(pos <= -(this._width-d)){ pos = -this._width; }
|
||
|
if(pos >= -d){ pos = 0; }
|
||
|
this.inner.style.left = pos + "px";
|
||
|
if(Math.abs(dx) > d){
|
||
|
this._moved = true;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
onTouchEnd: function(e){
|
||
|
// summary:
|
||
|
// Internal function to handle touchEnd events.
|
||
|
array.forEach(this._conn, connect.disconnect);
|
||
|
this._conn = null;
|
||
|
if(this.innerStartX == this.inner.offsetLeft){
|
||
|
if(has("touch")){
|
||
|
var ev = win.doc.createEvent("MouseEvents");
|
||
|
ev.initEvent("click", true, true);
|
||
|
this.inner.dispatchEvent(ev);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
var newState = (this.inner.offsetLeft < -(this._width/2)) ? "off" : "on";
|
||
|
this._changeState(newState, true);
|
||
|
if(newState != this.value){
|
||
|
this.value = this.input.value = newState;
|
||
|
this.onStateChanged(newState);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
onStateChanged: function(/*String*/newState){
|
||
|
// summary:
|
||
|
// Stub function to connect to from your application.
|
||
|
// description:
|
||
|
// Called when the state has been changed.
|
||
|
},
|
||
|
|
||
|
_setValueAttr: function(/*String*/value){
|
||
|
this._changeState(value, false);
|
||
|
if(this.value != value){
|
||
|
this.onStateChanged(value);
|
||
|
}
|
||
|
this.value = this.input.value = value;
|
||
|
},
|
||
|
|
||
|
_setLeftLabelAttr: function(/*String*/label){
|
||
|
this.leftLabel = label;
|
||
|
this.left.firstChild.innerHTML = this._cv ? this._cv(label) : label;
|
||
|
},
|
||
|
|
||
|
_setRightLabelAttr: function(/*String*/label){
|
||
|
this.rightLabel = label;
|
||
|
this.right.firstChild.innerHTML = this._cv ? this._cv(label) : label;
|
||
|
},
|
||
|
|
||
|
reset: function(){
|
||
|
// summary:
|
||
|
// Reset the widget's value to what it was at initialization time
|
||
|
this.set("value", this._initialValue);
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/ListItem':function(){
|
||
|
define("dojox/mobile/ListItem", [
|
||
|
"dojo/_base/array",
|
||
|
"dojo/_base/connect",
|
||
|
"dojo/_base/declare",
|
||
|
"dojo/_base/lang",
|
||
|
"dojo/dom-class",
|
||
|
"dojo/dom-construct",
|
||
|
"dojo/has",
|
||
|
"./common",
|
||
|
"./_ItemBase",
|
||
|
"./TransitionEvent"
|
||
|
], function(array, connect, declare, lang, domClass, domConstruct, has, common, ItemBase, TransitionEvent){
|
||
|
|
||
|
/*=====
|
||
|
var ItemBase = dojox.mobile._ItemBase;
|
||
|
=====*/
|
||
|
|
||
|
// module:
|
||
|
// dojox/mobile/ListItem
|
||
|
// summary:
|
||
|
// An item of either RoundRectList or EdgeToEdgeList.
|
||
|
|
||
|
return declare("dojox.mobile.ListItem", ItemBase, {
|
||
|
// summary:
|
||
|
// An item of either RoundRectList or EdgeToEdgeList.
|
||
|
// description:
|
||
|
// ListItem represents an item of either RoundRectList or
|
||
|
// EdgeToEdgeList. There are three ways to move to a different
|
||
|
// view, moveTo, href, and url. You can choose only one of them.
|
||
|
|
||
|
// rightText: String
|
||
|
// A right-aligned text to display on the item.
|
||
|
rightText: "",
|
||
|
|
||
|
// rightIcon: String
|
||
|
// An icon to display at the right hand side of the item. The value
|
||
|
// can be either a path for an image file or a class name of a DOM
|
||
|
// button.
|
||
|
rightIcon: "",
|
||
|
|
||
|
// rightIcon2: String
|
||
|
// An icon to display at the left of the rightIcon. The value can
|
||
|
// be either a path for an image file or a class name of a DOM
|
||
|
// button.
|
||
|
rightIcon2: "",
|
||
|
|
||
|
|
||
|
// anchorLabel: Boolean
|
||
|
// If true, the label text becomes a clickable anchor text. When
|
||
|
// the user clicks on the text, the onAnchorLabelClicked handler is
|
||
|
// called. You can override or connect to the handler and implement
|
||
|
// any action. The handler has no default action.
|
||
|
anchorLabel: false,
|
||
|
|
||
|
// noArrow: Boolean
|
||
|
// If true, the right hand side arrow is not displayed.
|
||
|
noArrow: false,
|
||
|
|
||
|
// selected: Boolean
|
||
|
// If true, the item is highlighted to indicate it is selected.
|
||
|
selected: false,
|
||
|
|
||
|
// checked: Boolean
|
||
|
// If true, a check mark is displayed at the right of the item.
|
||
|
checked: false,
|
||
|
|
||
|
// arrowClass: String
|
||
|
// An icon to display as an arrow. The value can be either a path
|
||
|
// for an image file or a class name of a DOM button.
|
||
|
arrowClass: "mblDomButtonArrow",
|
||
|
|
||
|
// checkClass: String
|
||
|
// An icon to display as a check mark. The value can be either a
|
||
|
// path for an image file or a class name of a DOM button.
|
||
|
checkClass: "mblDomButtonCheck",
|
||
|
|
||
|
// variableHeight: Boolean
|
||
|
// If true, the height of the item varies according to its
|
||
|
// content. In dojo 1.6 or older, the "mblVariableHeight" class was
|
||
|
// used for this purpose. In dojo 1.7, adding the mblVariableHeight
|
||
|
// class still works for backward compatibility.
|
||
|
variableHeight: false,
|
||
|
|
||
|
|
||
|
// rightIconTitle: String
|
||
|
// An alt text for the right icon.
|
||
|
rightIconTitle: "",
|
||
|
|
||
|
// rightIcon2Title: String
|
||
|
// An alt text for the right icon2.
|
||
|
rightIcon2Title: "",
|
||
|
|
||
|
|
||
|
// btnClass: String
|
||
|
// Deprecated. For backward compatibility.
|
||
|
btnClass: "",
|
||
|
|
||
|
// btnClass2: String
|
||
|
// Deprecated. For backward compatibility.
|
||
|
btnClass2: "",
|
||
|
|
||
|
// tag: String
|
||
|
// A name of html tag to create as domNode.
|
||
|
tag: "li",
|
||
|
|
||
|
postMixInProperties: function(){
|
||
|
// for backward compatibility
|
||
|
if(this.btnClass){
|
||
|
this.rightIcon = this.btnClass;
|
||
|
}
|
||
|
this._setBtnClassAttr = this._setRightIconAttr;
|
||
|
this._setBtnClass2Attr = this._setRightIcon2Attr;
|
||
|
},
|
||
|
|
||
|
buildRendering: function(){
|
||
|
this.domNode = this.srcNodeRef || domConstruct.create(this.tag);
|
||
|
this.inherited(arguments);
|
||
|
this.domNode.className = "mblListItem" + (this.selected ? " mblItemSelected" : "");
|
||
|
|
||
|
// label
|
||
|
var box = this.box = domConstruct.create("DIV");
|
||
|
box.className = "mblListItemTextBox";
|
||
|
if(this.anchorLabel){
|
||
|
box.style.cursor = "pointer";
|
||
|
}
|
||
|
var r = this.srcNodeRef;
|
||
|
if(r && !this.label){
|
||
|
this.label = "";
|
||
|
for(var i = 0, len = r.childNodes.length; i < len; i++){
|
||
|
var n = r.firstChild;
|
||
|
if(n.nodeType === 3 && lang.trim(n.nodeValue) !== ""){
|
||
|
n.nodeValue = this._cv ? this._cv(n.nodeValue) : n.nodeValue;
|
||
|
this.labelNode = domConstruct.create("SPAN", {className:"mblListItemLabel"});
|
||
|
this.labelNode.appendChild(n);
|
||
|
n = this.labelNode;
|
||
|
}
|
||
|
box.appendChild(n);
|
||
|
}
|
||
|
}
|
||
|
if(!this.labelNode){
|
||
|
this.labelNode = domConstruct.create("SPAN", {className:"mblListItemLabel"}, box);
|
||
|
}
|
||
|
if(this.anchorLabel){
|
||
|
box.style.display = "inline"; // to narrow the text region
|
||
|
}
|
||
|
|
||
|
var a = this.anchorNode = domConstruct.create("A");
|
||
|
a.className = "mblListItemAnchor";
|
||
|
this.domNode.appendChild(a);
|
||
|
a.appendChild(box);
|
||
|
},
|
||
|
|
||
|
startup: function(){
|
||
|
if(this._started){ return; }
|
||
|
this.inheritParams();
|
||
|
var parent = this.getParent();
|
||
|
if(this.moveTo || this.href || this.url || this.clickable || (parent && parent.select)){
|
||
|
this._onClickHandle = this.connect(this.anchorNode, "onclick", "onClick");
|
||
|
}
|
||
|
this.setArrow();
|
||
|
|
||
|
if(domClass.contains(this.domNode, "mblVariableHeight")){
|
||
|
this.variableHeight = true;
|
||
|
}
|
||
|
if(this.variableHeight){
|
||
|
domClass.add(this.domNode, "mblVariableHeight");
|
||
|
setTimeout(lang.hitch(this, "layoutVariableHeight"));
|
||
|
}
|
||
|
|
||
|
this.set("icon", this.icon); // _setIconAttr may be called twice but this is necessary for offline instantiation
|
||
|
if(!this.checked && this.checkClass.indexOf(',') !== -1){
|
||
|
this.set("checked", this.checked);
|
||
|
}
|
||
|
this.inherited(arguments);
|
||
|
},
|
||
|
|
||
|
resize: function(){
|
||
|
if(this.variableHeight){
|
||
|
this.layoutVariableHeight();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
onClick: function(e){
|
||
|
var a = e.currentTarget;
|
||
|
var li = a.parentNode;
|
||
|
if(domClass.contains(li, "mblItemSelected")){ return; } // already selected
|
||
|
if(this.anchorLabel){
|
||
|
for(var p = e.target; p.tagName !== this.tag.toUpperCase(); p = p.parentNode){
|
||
|
if(p.className == "mblListItemTextBox"){
|
||
|
domClass.add(p, "mblListItemTextBoxSelected");
|
||
|
setTimeout(function(){
|
||
|
domClass.remove(p, "mblListItemTextBoxSelected");
|
||
|
}, has("android") ? 300 : 1000);
|
||
|
this.onAnchorLabelClicked(e);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
var parent = this.getParent();
|
||
|
if(parent.select){
|
||
|
if(parent.select === "single"){
|
||
|
if(!this.checked){
|
||
|
this.set("checked", true);
|
||
|
}
|
||
|
}else if(parent.select === "multiple"){
|
||
|
this.set("checked", !this.checked);
|
||
|
}
|
||
|
}
|
||
|
this.select();
|
||
|
|
||
|
if (this.href && this.hrefTarget) {
|
||
|
common.openWindow(this.href, this.hrefTarget);
|
||
|
return;
|
||
|
}
|
||
|
var transOpts;
|
||
|
if(this.moveTo || this.href || this.url || this.scene){
|
||
|
transOpts = {moveTo: this.moveTo, href: this.href, url: this.url, scene: this.scene, transition: this.transition, transitionDir: this.transitionDir};
|
||
|
}else if(this.transitionOptions){
|
||
|
transOpts = this.transitionOptions;
|
||
|
}
|
||
|
|
||
|
if(transOpts){
|
||
|
this.setTransitionPos(e);
|
||
|
return new TransitionEvent(this.domNode,transOpts,e).dispatch();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
select: function(){
|
||
|
// summary:
|
||
|
// Makes this widget in the selected state.
|
||
|
var parent = this.getParent();
|
||
|
if(parent.stateful){
|
||
|
parent.deselectAll();
|
||
|
}else{
|
||
|
var _this = this;
|
||
|
setTimeout(function(){
|
||
|
_this.deselect();
|
||
|
}, has("android") ? 300 : 1000);
|
||
|
}
|
||
|
domClass.add(this.domNode, "mblItemSelected");
|
||
|
},
|
||
|
|
||
|
deselect: function(){
|
||
|
// summary:
|
||
|
// Makes this widget in the deselected state.
|
||
|
domClass.remove(this.domNode, "mblItemSelected");
|
||
|
},
|
||
|
|
||
|
onAnchorLabelClicked: function(e){
|
||
|
// summary:
|
||
|
// Stub function to connect to from your application.
|
||
|
},
|
||
|
|
||
|
layoutVariableHeight: function(){
|
||
|
var h = this.anchorNode.offsetHeight;
|
||
|
if(h === this.anchorNodeHeight){ return; }
|
||
|
this.anchorNodeHeight = h;
|
||
|
array.forEach([
|
||
|
this.rightTextNode,
|
||
|
this.rightIcon2Node,
|
||
|
this.rightIconNode,
|
||
|
this.iconNode
|
||
|
], function(n){
|
||
|
if(n){
|
||
|
var t = Math.round((h - n.offsetHeight) / 2);
|
||
|
n.style.marginTop = t + "px";
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
setArrow: function(){
|
||
|
// summary:
|
||
|
// Sets the arrow icon if necessary.
|
||
|
if(this.checked){ return; }
|
||
|
var c = "";
|
||
|
var parent = this.getParent();
|
||
|
if(this.moveTo || this.href || this.url || this.clickable){
|
||
|
if(!this.noArrow && !(parent && parent.stateful)){
|
||
|
c = this.arrowClass;
|
||
|
}
|
||
|
}
|
||
|
if(c){
|
||
|
this._setRightIconAttr(c);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_setIconAttr: function(icon){
|
||
|
if(!this.getParent()){ return; } // icon may be invalid because inheritParams is not called yet
|
||
|
this.icon = icon;
|
||
|
var a = this.anchorNode;
|
||
|
if(!this.iconNode){
|
||
|
if(icon){
|
||
|
var ref = this.rightIconNode || this.rightIcon2Node || this.rightTextNode || this.box;
|
||
|
this.iconNode = domConstruct.create("DIV", {className:"mblListItemIcon"}, ref, "before");
|
||
|
}
|
||
|
}else{
|
||
|
domConstruct.empty(this.iconNode);
|
||
|
}
|
||
|
if(icon && icon !== "none"){
|
||
|
common.createIcon(icon, this.iconPos, null, this.alt, this.iconNode);
|
||
|
if(this.iconPos){
|
||
|
domClass.add(this.iconNode.firstChild, "mblListItemSpriteIcon");
|
||
|
}
|
||
|
domClass.remove(a, "mblListItemAnchorNoIcon");
|
||
|
}else{
|
||
|
domClass.add(a, "mblListItemAnchorNoIcon");
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_setCheckedAttr: function(/*Boolean*/checked){
|
||
|
var parent = this.getParent();
|
||
|
if(parent && parent.select === "single" && checked){
|
||
|
array.forEach(parent.getChildren(), function(child){
|
||
|
child.set("checked", false);
|
||
|
});
|
||
|
}
|
||
|
this._setRightIconAttr(this.checkClass);
|
||
|
|
||
|
var icons = this.rightIconNode.childNodes;
|
||
|
if(icons.length === 1){
|
||
|
this.rightIconNode.style.display = checked ? "" : "none";
|
||
|
}else{
|
||
|
icons[0].style.display = checked ? "" : "none";
|
||
|
icons[1].style.display = !checked ? "" : "none";
|
||
|
}
|
||
|
|
||
|
domClass.toggle(this.domNode, "mblListItemChecked", checked);
|
||
|
if(parent && this.checked !== checked){
|
||
|
parent.onCheckStateChanged(this, checked);
|
||
|
}
|
||
|
this.checked = checked;
|
||
|
},
|
||
|
|
||
|
_setRightTextAttr: function(/*String*/text){
|
||
|
if(!this.rightTextNode){
|
||
|
this.rightTextNode = domConstruct.create("DIV", {className:"mblListItemRightText"}, this.box, "before");
|
||
|
}
|
||
|
this.rightText = text;
|
||
|
this.rightTextNode.innerHTML = this._cv ? this._cv(text) : text;
|
||
|
},
|
||
|
|
||
|
_setRightIconAttr: function(/*String*/icon){
|
||
|
if(!this.rightIconNode){
|
||
|
var ref = this.rightIcon2Node || this.rightTextNode || this.box;
|
||
|
this.rightIconNode = domConstruct.create("DIV", {className:"mblListItemRightIcon"}, ref, "before");
|
||
|
}else{
|
||
|
domConstruct.empty(this.rightIconNode);
|
||
|
}
|
||
|
this.rightIcon = icon;
|
||
|
var arr = (icon || "").split(/,/);
|
||
|
if(arr.length === 1){
|
||
|
common.createIcon(icon, null, null, this.rightIconTitle, this.rightIconNode);
|
||
|
}else{
|
||
|
common.createIcon(arr[0], null, null, this.rightIconTitle, this.rightIconNode);
|
||
|
common.createIcon(arr[1], null, null, this.rightIconTitle, this.rightIconNode);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_setRightIcon2Attr: function(/*String*/icon){
|
||
|
if(!this.rightIcon2Node){
|
||
|
var ref = this.rightTextNode || this.box;
|
||
|
this.rightIcon2Node = domConstruct.create("DIV", {className:"mblListItemRightIcon2"}, ref, "before");
|
||
|
}else{
|
||
|
domConstruct.empty(this.rightIcon2Node);
|
||
|
}
|
||
|
this.rightIcon2 = icon;
|
||
|
common.createIcon(icon, null, null, this.rightIcon2Title, this.rightIcon2Node);
|
||
|
},
|
||
|
|
||
|
_setLabelAttr: function(/*String*/text){
|
||
|
this.label = text;
|
||
|
this.labelNode.innerHTML = this._cv ? this._cv(text) : text;
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dijit/registry':function(){
|
||
|
define("dijit/registry", [
|
||
|
"dojo/_base/array", // array.forEach array.map
|
||
|
"dojo/_base/sniff", // has("ie")
|
||
|
"dojo/_base/unload", // unload.addOnWindowUnload
|
||
|
"dojo/_base/window", // win.body
|
||
|
"." // dijit._scopeName
|
||
|
], function(array, has, unload, win, dijit){
|
||
|
|
||
|
// module:
|
||
|
// dijit/registry
|
||
|
// summary:
|
||
|
// Registry of existing widget on page, plus some utility methods.
|
||
|
// Must be accessed through AMD api, ex:
|
||
|
// require(["dijit/registry"], function(registry){ registry.byId("foo"); })
|
||
|
|
||
|
var _widgetTypeCtr = {}, hash = {};
|
||
|
|
||
|
var registry = {
|
||
|
// summary:
|
||
|
// A set of widgets indexed by id
|
||
|
|
||
|
length: 0,
|
||
|
|
||
|
add: function(/*dijit._Widget*/ widget){
|
||
|
// summary:
|
||
|
// Add a widget to the registry. If a duplicate ID is detected, a error is thrown.
|
||
|
//
|
||
|
// widget: dijit._Widget
|
||
|
// Any dijit._Widget subclass.
|
||
|
if(hash[widget.id]){
|
||
|
throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
|
||
|
}
|
||
|
hash[widget.id] = widget;
|
||
|
this.length++;
|
||
|
},
|
||
|
|
||
|
remove: function(/*String*/ id){
|
||
|
// summary:
|
||
|
// Remove a widget from the registry. Does not destroy the widget; simply
|
||
|
// removes the reference.
|
||
|
if(hash[id]){
|
||
|
delete hash[id];
|
||
|
this.length--;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
byId: function(/*String|Widget*/ id){
|
||
|
// summary:
|
||
|
// Find a widget by it's id.
|
||
|
// If passed a widget then just returns the widget.
|
||
|
return typeof id == "string" ? hash[id] : id; // dijit._Widget
|
||
|
},
|
||
|
|
||
|
byNode: function(/*DOMNode*/ node){
|
||
|
// summary:
|
||
|
// Returns the widget corresponding to the given DOMNode
|
||
|
return hash[node.getAttribute("widgetId")]; // dijit._Widget
|
||
|
},
|
||
|
|
||
|
toArray: function(){
|
||
|
// summary:
|
||
|
// Convert registry into a true Array
|
||
|
//
|
||
|
// example:
|
||
|
// Work with the widget .domNodes in a real Array
|
||
|
// | array.map(dijit.registry.toArray(), function(w){ return w.domNode; });
|
||
|
|
||
|
var ar = [];
|
||
|
for(var id in hash){
|
||
|
ar.push(hash[id]);
|
||
|
}
|
||
|
return ar; // dijit._Widget[]
|
||
|
},
|
||
|
|
||
|
getUniqueId: function(/*String*/widgetType){
|
||
|
// summary:
|
||
|
// Generates a unique id for a given widgetType
|
||
|
|
||
|
var id;
|
||
|
do{
|
||
|
id = widgetType + "_" +
|
||
|
(widgetType in _widgetTypeCtr ?
|
||
|
++_widgetTypeCtr[widgetType] : _widgetTypeCtr[widgetType] = 0);
|
||
|
}while(hash[id]);
|
||
|
return dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String
|
||
|
},
|
||
|
|
||
|
findWidgets: function(/*DomNode*/ root){
|
||
|
// summary:
|
||
|
// Search subtree under root returning widgets found.
|
||
|
// Doesn't search for nested widgets (ie, widgets inside other widgets).
|
||
|
|
||
|
var outAry = [];
|
||
|
|
||
|
function getChildrenHelper(root){
|
||
|
for(var node = root.firstChild; node; node = node.nextSibling){
|
||
|
if(node.nodeType == 1){
|
||
|
var widgetId = node.getAttribute("widgetId");
|
||
|
if(widgetId){
|
||
|
var widget = hash[widgetId];
|
||
|
if(widget){ // may be null on page w/multiple dojo's loaded
|
||
|
outAry.push(widget);
|
||
|
}
|
||
|
}else{
|
||
|
getChildrenHelper(node);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
getChildrenHelper(root);
|
||
|
return outAry;
|
||
|
},
|
||
|
|
||
|
_destroyAll: function(){
|
||
|
// summary:
|
||
|
// Code to destroy all widgets and do other cleanup on page unload
|
||
|
|
||
|
// Clean up focus manager lingering references to widgets and nodes
|
||
|
dijit._curFocus = null;
|
||
|
dijit._prevFocus = null;
|
||
|
dijit._activeStack = [];
|
||
|
|
||
|
// Destroy all the widgets, top down
|
||
|
array.forEach(registry.findWidgets(win.body()), function(widget){
|
||
|
// Avoid double destroy of widgets like Menu that are attached to <body>
|
||
|
// even though they are logically children of other widgets.
|
||
|
if(!widget._destroyed){
|
||
|
if(widget.destroyRecursive){
|
||
|
widget.destroyRecursive();
|
||
|
}else if(widget.destroy){
|
||
|
widget.destroy();
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
getEnclosingWidget: function(/*DOMNode*/ node){
|
||
|
// summary:
|
||
|
// Returns the widget whose DOM tree contains the specified DOMNode, or null if
|
||
|
// the node is not contained within the DOM tree of any widget
|
||
|
while(node){
|
||
|
var id = node.getAttribute && node.getAttribute("widgetId");
|
||
|
if(id){
|
||
|
return hash[id];
|
||
|
}
|
||
|
node = node.parentNode;
|
||
|
}
|
||
|
return null;
|
||
|
},
|
||
|
|
||
|
// In case someone needs to access hash.
|
||
|
// Actually, this is accessed from WidgetSet back-compatibility code
|
||
|
_hash: hash
|
||
|
};
|
||
|
|
||
|
if(has("ie")){
|
||
|
// Only run _destroyAll() for IE because we think it's only necessary in that case,
|
||
|
// and because it causes problems on FF. See bug #3531 for details.
|
||
|
unload.addOnWindowUnload(function(){
|
||
|
registry._destroyAll();
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/*=====
|
||
|
dijit.registry = {
|
||
|
// summary:
|
||
|
// A list of widgets on a page.
|
||
|
};
|
||
|
=====*/
|
||
|
dijit.registry = registry;
|
||
|
|
||
|
return registry;
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/common':function(){
|
||
|
define([
|
||
|
"dojo/_base/kernel", // to test dojo.hash
|
||
|
"dojo/_base/array",
|
||
|
"dojo/_base/config",
|
||
|
"dojo/_base/connect",
|
||
|
"dojo/_base/lang",
|
||
|
"dojo/_base/window",
|
||
|
"dojo/dom-class",
|
||
|
"dojo/dom-construct",
|
||
|
"dojo/dom-style",
|
||
|
// "dojo/hash", // optionally prereq'ed
|
||
|
"dojo/ready",
|
||
|
"dijit/registry", // registry.toArray
|
||
|
"./sniff",
|
||
|
"./uacss"
|
||
|
], function(dojo, array, config, connect, lang, win, domClass, domConstruct, domStyle, ready, registry, has, uacss){
|
||
|
|
||
|
var dm = lang.getObject("dojox.mobile", true);
|
||
|
/*=====
|
||
|
var dm = dojox.mobile;
|
||
|
=====*/
|
||
|
|
||
|
// module:
|
||
|
// dojox/mobile/common
|
||
|
// summary:
|
||
|
// A common module for dojox.mobile.
|
||
|
// description:
|
||
|
// This module includes common utility functions that are used by
|
||
|
// dojox.mobile widgets. Also, it provides functions that are commonly
|
||
|
// necessary for mobile web applications, such as the hide address bar
|
||
|
// function.
|
||
|
|
||
|
dm.getScreenSize = function(){
|
||
|
// summary:
|
||
|
// Returns the dimensions of the browser window.
|
||
|
return {
|
||
|
h: win.global.innerHeight || win.doc.documentElement.clientHeight,
|
||
|
w: win.global.innerWidth || win.doc.documentElement.clientWidth
|
||
|
};
|
||
|
};
|
||
|
|
||
|
dm.updateOrient = function(){
|
||
|
// summary:
|
||
|
// Updates the orientation specific css classes, 'dj_portrait' and
|
||
|
// 'dj_landscape'.
|
||
|
var dim = dm.getScreenSize();
|
||
|
domClass.replace(win.doc.documentElement,
|
||
|
dim.h > dim.w ? "dj_portrait" : "dj_landscape",
|
||
|
dim.h > dim.w ? "dj_landscape" : "dj_portrait");
|
||
|
};
|
||
|
dm.updateOrient();
|
||
|
|
||
|
dm.tabletSize = 500;
|
||
|
dm.detectScreenSize = function(/*Boolean?*/force){
|
||
|
// summary:
|
||
|
// Detects the screen size and determines if the screen is like
|
||
|
// phone or like tablet. If the result is changed,
|
||
|
// it sets either of the following css class to <html>
|
||
|
// - 'dj_phone'
|
||
|
// - 'dj_tablet'
|
||
|
// and it publishes either of the following events.
|
||
|
// - '/dojox/mobile/screenSize/phone'
|
||
|
// - '/dojox/mobile/screenSize/tablet'
|
||
|
var dim = dm.getScreenSize();
|
||
|
var sz = Math.min(dim.w, dim.h);
|
||
|
var from, to;
|
||
|
if(sz >= dm.tabletSize && (force || (!this._sz || this._sz < dm.tabletSize))){
|
||
|
from = "phone";
|
||
|
to = "tablet";
|
||
|
}else if(sz < dm.tabletSize && (force || (!this._sz || this._sz >= dm.tabletSize))){
|
||
|
from = "tablet";
|
||
|
to = "phone";
|
||
|
}
|
||
|
if(to){
|
||
|
domClass.replace(win.doc.documentElement, "dj_"+to, "dj_"+from);
|
||
|
connect.publish("/dojox/mobile/screenSize/"+to, [dim]);
|
||
|
}
|
||
|
this._sz = sz;
|
||
|
};
|
||
|
dm.detectScreenSize();
|
||
|
|
||
|
dm.setupIcon = function(/*DomNode*/iconNode, /*String*/iconPos){
|
||
|
// summary:
|
||
|
// Sets up CSS sprite for a foreground image.
|
||
|
if(iconNode && iconPos){
|
||
|
var arr = array.map(iconPos.split(/[ ,]/),function(item){return item-0});
|
||
|
var t = arr[0]; // top
|
||
|
var r = arr[1] + arr[2]; // right
|
||
|
var b = arr[0] + arr[3]; // bottom
|
||
|
var l = arr[1]; // left
|
||
|
domStyle.set(iconNode, {
|
||
|
clip: "rect("+t+"px "+r+"px "+b+"px "+l+"px)",
|
||
|
top: (iconNode.parentNode ? domStyle.get(iconNode, "top") : 0) - t + "px",
|
||
|
left: -l + "px"
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// dojox.mobile.hideAddressBarWait: Number
|
||
|
// The time in milliseconds to wait before the fail-safe hiding address
|
||
|
// bar runs. The value must be larger than 800.
|
||
|
dm.hideAddressBarWait = typeof(config["mblHideAddressBarWait"]) === "number" ?
|
||
|
config["mblHideAddressBarWait"] : 1500;
|
||
|
|
||
|
dm.hide_1 = function(force){
|
||
|
// summary:
|
||
|
// Internal function to hide the address bar.
|
||
|
scrollTo(0, 1);
|
||
|
var h = dm.getScreenSize().h + "px";
|
||
|
if(has("android")){
|
||
|
if(force){
|
||
|
win.body().style.minHeight = h;
|
||
|
}
|
||
|
dm.resizeAll();
|
||
|
}else{
|
||
|
if(force || dm._h === h && h !== win.body().style.minHeight){
|
||
|
win.body().style.minHeight = h;
|
||
|
dm.resizeAll();
|
||
|
}
|
||
|
}
|
||
|
dm._h = h;
|
||
|
};
|
||
|
|
||
|
dm.hide_fs = function(){
|
||
|
// summary:
|
||
|
// Internal function to hide the address bar for fail-safe.
|
||
|
// description:
|
||
|
// Resets the height of the body, performs hiding the address
|
||
|
// bar, and calls resizeAll().
|
||
|
// This is for fail-safe, in case of failure to complete the
|
||
|
// address bar hiding in time.
|
||
|
var t = win.body().style.minHeight;
|
||
|
win.body().style.minHeight = (dm.getScreenSize().h * 2) + "px"; // to ensure enough height for scrollTo to work
|
||
|
scrollTo(0, 1);
|
||
|
setTimeout(function(){
|
||
|
dm.hide_1(1);
|
||
|
dm._hiding = false;
|
||
|
}, 1000);
|
||
|
};
|
||
|
dm.hideAddressBar = function(/*Event?*/evt){
|
||
|
// summary:
|
||
|
// Hides the address bar.
|
||
|
// description:
|
||
|
// Tries hiding of the address bar a couple of times to do it as
|
||
|
// quick as possible while ensuring resize is done after the hiding
|
||
|
// finishes.
|
||
|
if(dm.disableHideAddressBar || dm._hiding){ return; }
|
||
|
dm._hiding = true;
|
||
|
dm._h = 0;
|
||
|
win.body().style.minHeight = (dm.getScreenSize().h * 2) + "px"; // to ensure enough height for scrollTo to work
|
||
|
setTimeout(dm.hide_1, 0);
|
||
|
setTimeout(dm.hide_1, 200);
|
||
|
setTimeout(dm.hide_1, 800);
|
||
|
setTimeout(dm.hide_fs, dm.hideAddressBarWait);
|
||
|
};
|
||
|
|
||
|
dm.resizeAll = function(/*Event?*/evt, /*Widget?*/root){
|
||
|
// summary:
|
||
|
// Call the resize() method of all the top level resizable widgets.
|
||
|
// description:
|
||
|
// Find all widgets that do not have a parent or the parent does not
|
||
|
// have the resize() method, and call resize() for them.
|
||
|
// If a widget has a parent that has resize(), call of the widget's
|
||
|
// resize() is its parent's responsibility.
|
||
|
// evt:
|
||
|
// Native event object
|
||
|
// root:
|
||
|
// If specified, search the specified widget recursively for top level
|
||
|
// resizable widgets.
|
||
|
// root.resize() is always called regardless of whether root is a
|
||
|
// top level widget or not.
|
||
|
// If omitted, search the entire page.
|
||
|
if(dm.disableResizeAll){ return; }
|
||
|
connect.publish("/dojox/mobile/resizeAll", [evt, root]);
|
||
|
dm.updateOrient();
|
||
|
dm.detectScreenSize();
|
||
|
var isTopLevel = function(w){
|
||
|
var parent = w.getParent && w.getParent();
|
||
|
return !!((!parent || !parent.resize) && w.resize);
|
||
|
};
|
||
|
var resizeRecursively = function(w){
|
||
|
array.forEach(w.getChildren(), function(child){
|
||
|
if(isTopLevel(child)){ child.resize(); }
|
||
|
resizeRecursively(child);
|
||
|
});
|
||
|
};
|
||
|
if(root){
|
||
|
if(root.resize){ root.resize(); }
|
||
|
resizeRecursively(root);
|
||
|
}else{
|
||
|
array.forEach(array.filter(registry.toArray(), isTopLevel),
|
||
|
function(w){ w.resize(); });
|
||
|
}
|
||
|
};
|
||
|
|
||
|
dm.openWindow = function(url, target){
|
||
|
// summary:
|
||
|
// Opens a new browser window with the given url.
|
||
|
win.global.open(url, target || "_blank");
|
||
|
};
|
||
|
|
||
|
dm.createDomButton = function(/*DomNode*/refNode, /*Object?*/style, /*DomNode?*/toNode){
|
||
|
// summary:
|
||
|
// Creates a DOM button.
|
||
|
// description:
|
||
|
// DOM button is a simple graphical object that consists of one or
|
||
|
// more nested DIV elements with some CSS styling. It can be used
|
||
|
// in place of an icon image on ListItem, IconItem, and so on.
|
||
|
// The kind of DOM button to create is given as a class name of
|
||
|
// refNode. The number of DIVs to create is searched from the style
|
||
|
// sheets in the page. However, if the class name has a suffix that
|
||
|
// starts with an underscore, like mblDomButtonGoldStar_5, then the
|
||
|
// suffixed number is used instead. A class name for DOM button
|
||
|
// must starts with 'mblDomButton'.
|
||
|
// refNode:
|
||
|
// A node that has a DOM button class name.
|
||
|
// style:
|
||
|
// A hash object to set styles to the node.
|
||
|
// toNode:
|
||
|
// A root node to create a DOM button. If omitted, refNode is used.
|
||
|
|
||
|
if(!dm._domButtons){
|
||
|
if(has("webkit")){
|
||
|
var findDomButtons = function(sheet, dic){
|
||
|
// summary:
|
||
|
// Searches the style sheets for DOM buttons.
|
||
|
// description:
|
||
|
// Returns a key-value pair object whose keys are DOM
|
||
|
// button class names and values are the number of DOM
|
||
|
// elements they need.
|
||
|
var i, j;
|
||
|
if(!sheet){
|
||
|
var dic = {};
|
||
|
var ss = dojo.doc.styleSheets;
|
||
|
for (i = 0; i < ss.length; i++){
|
||
|
ss[i] && findDomButtons(ss[i], dic);
|
||
|
}
|
||
|
return dic;
|
||
|
}
|
||
|
var rules = sheet.cssRules || [];
|
||
|
for (i = 0; i < rules.length; i++){
|
||
|
var rule = rules[i];
|
||
|
if(rule.href && rule.styleSheet){
|
||
|
findDomButtons(rule.styleSheet, dic);
|
||
|
}else if(rule.selectorText){
|
||
|
var sels = rule.selectorText.split(/,/);
|
||
|
for (j = 0; j < sels.length; j++){
|
||
|
var sel = sels[j];
|
||
|
var n = sel.split(/>/).length - 1;
|
||
|
if(sel.match(/(mblDomButton\w+)/)){
|
||
|
var cls = RegExp.$1;
|
||
|
if(!dic[cls] || n > dic[cls]){
|
||
|
dic[cls] = n;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
dm._domButtons = findDomButtons();
|
||
|
}else{
|
||
|
dm._domButtons = {};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var s = refNode.className;
|
||
|
var node = toNode || refNode;
|
||
|
if(s.match(/(mblDomButton\w+)/) && s.indexOf("/") === -1){
|
||
|
var btnClass = RegExp.$1;
|
||
|
var nDiv = 4;
|
||
|
if(s.match(/(mblDomButton\w+_(\d+))/)){
|
||
|
nDiv = RegExp.$2 - 0;
|
||
|
}else if(dm._domButtons[btnClass] !== undefined){
|
||
|
nDiv = dm._domButtons[btnClass];
|
||
|
}
|
||
|
var props = null;
|
||
|
if(has("bb") && config["mblBBBoxShadowWorkaround"] !== false){
|
||
|
// Removes box-shadow because BlackBerry incorrectly renders it.
|
||
|
props = {style:"-webkit-box-shadow:none"};
|
||
|
}
|
||
|
for(var i = 0, p = node; i < nDiv; i++){
|
||
|
p = p.firstChild || domConstruct.create("DIV", props, p);
|
||
|
}
|
||
|
if(toNode){
|
||
|
setTimeout(function(){
|
||
|
domClass.remove(refNode, btnClass);
|
||
|
}, 0);
|
||
|
domClass.add(toNode, btnClass);
|
||
|
}
|
||
|
}else if(s.indexOf(".") !== -1){ // file name
|
||
|
domConstruct.create("IMG", {src:s}, node);
|
||
|
}else{
|
||
|
return null;
|
||
|
}
|
||
|
domClass.add(node, "mblDomButton");
|
||
|
if(config["mblAndroidWorkaround"] !== false && has("android") >= 2.2){
|
||
|
// Android workaround for the issue that domButtons' -webkit-transform styles sometimes invalidated
|
||
|
// by applying -webkit-transform:translated3d(x,y,z) style programmatically to non-ancestor elements,
|
||
|
// which results in breaking domButtons.
|
||
|
domStyle.set(node, "webkitTransform", "translate3d(0,0,0)");
|
||
|
}
|
||
|
!!style && domStyle.set(node, style);
|
||
|
return node;
|
||
|
};
|
||
|
|
||
|
dm.createIcon = function(/*String*/icon, /*String*/iconPos, /*DomNode*/node, /*String?*/title, /*DomNode?*/parent){
|
||
|
// summary:
|
||
|
// Creates or updates an icon node
|
||
|
// description:
|
||
|
// If node exists, updates the existing node. Otherwise, creates a new one.
|
||
|
// icon:
|
||
|
// Path for an image, or DOM button class name.
|
||
|
if(icon && icon.indexOf("mblDomButton") === 0){
|
||
|
// DOM button
|
||
|
if(node && node.className.match(/(mblDomButton\w+)/)){
|
||
|
domClass.remove(node, RegExp.$1);
|
||
|
}else{
|
||
|
node = domConstruct.create("DIV");
|
||
|
}
|
||
|
node.title = title;
|
||
|
domClass.add(node, icon);
|
||
|
dm.createDomButton(node);
|
||
|
}else if(icon && icon !== "none"){
|
||
|
// Image
|
||
|
if(!node || node.nodeName !== "IMG"){
|
||
|
node = domConstruct.create("IMG", {
|
||
|
alt: title
|
||
|
});
|
||
|
}
|
||
|
node.src = (icon || "").replace("${theme}", dm.currentTheme);
|
||
|
dm.setupIcon(node, iconPos);
|
||
|
if(parent && iconPos){
|
||
|
var arr = iconPos.split(/[ ,]/);
|
||
|
domStyle.set(parent, {
|
||
|
width: arr[2] + "px",
|
||
|
height: arr[3] + "px"
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
if(parent){
|
||
|
parent.appendChild(node);
|
||
|
}
|
||
|
return node;
|
||
|
};
|
||
|
|
||
|
// flag for iphone flicker workaround
|
||
|
dm._iw = config["mblIosWorkaround"] !== false && has("iphone");
|
||
|
if(dm._iw){
|
||
|
dm._iwBgCover = domConstruct.create("div"); // Cover to hide flicker in the background
|
||
|
}
|
||
|
|
||
|
if(config.parseOnLoad){
|
||
|
ready(90, function(){
|
||
|
// avoid use of query
|
||
|
/*
|
||
|
var list = query('[lazy=true] [dojoType]', null);
|
||
|
list.forEach(function(node, index, nodeList){
|
||
|
node.setAttribute("__dojoType", node.getAttribute("dojoType"));
|
||
|
node.removeAttribute("dojoType");
|
||
|
});
|
||
|
*/
|
||
|
|
||
|
var nodes = win.body().getElementsByTagName("*");
|
||
|
var i, len, s;
|
||
|
len = nodes.length;
|
||
|
for(i = 0; i < len; i++){
|
||
|
s = nodes[i].getAttribute("dojoType");
|
||
|
if(s){
|
||
|
if(nodes[i].parentNode.getAttribute("lazy") == "true"){
|
||
|
nodes[i].setAttribute("__dojoType", s);
|
||
|
nodes[i].removeAttribute("dojoType");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
ready(function(){
|
||
|
dm.detectScreenSize(true);
|
||
|
if(config["mblApplyPageStyles"] !== false){
|
||
|
domClass.add(win.doc.documentElement, "mobile");
|
||
|
}
|
||
|
if(has("chrome")){
|
||
|
// dojox.mobile does not load uacss (only _compat does), but we need dj_chrome.
|
||
|
domClass.add(win.doc.documentElement, "dj_chrome");
|
||
|
}
|
||
|
|
||
|
if(config["mblAndroidWorkaround"] !== false && has("android") >= 2.2){ // workaround for android screen flicker problem
|
||
|
if(config["mblAndroidWorkaroundButtonStyle"] !== false){
|
||
|
// workaround to avoid buttons disappear due to the side-effect of the webkitTransform workaroud below
|
||
|
domConstruct.create("style", {innerHTML:"BUTTON,INPUT[type='button'],INPUT[type='submit'],INPUT[type='reset'],INPUT[type='file']::-webkit-file-upload-button{-webkit-appearance:none;}"}, win.doc.head, "first");
|
||
|
}
|
||
|
if(has("android") < 3){ // for Android 2.2.x and 2.3.x
|
||
|
domStyle.set(win.doc.documentElement, "webkitTransform", "translate3d(0,0,0)");
|
||
|
// workaround for auto-scroll issue when focusing input fields
|
||
|
connect.connect(null, "onfocus", null, function(e){
|
||
|
domStyle.set(win.doc.documentElement, "webkitTransform", "");
|
||
|
});
|
||
|
connect.connect(null, "onblur", null, function(e){
|
||
|
domStyle.set(win.doc.documentElement, "webkitTransform", "translate3d(0,0,0)");
|
||
|
});
|
||
|
}else{ // for Android 3.x
|
||
|
if(config["mblAndroid3Workaround"] !== false){
|
||
|
domStyle.set(win.doc.documentElement, {
|
||
|
webkitBackfaceVisibility: "hidden",
|
||
|
webkitPerspective: 8000
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// You can disable hiding the address bar with the following djConfig.
|
||
|
// var djConfig = { mblHideAddressBar: false };
|
||
|
var f = dm.resizeAll;
|
||
|
if(config["mblHideAddressBar"] !== false &&
|
||
|
navigator.appVersion.indexOf("Mobile") != -1 ||
|
||
|
config["mblForceHideAddressBar"] === true){
|
||
|
dm.hideAddressBar();
|
||
|
if(config["mblAlwaysHideAddressBar"] === true){
|
||
|
f = dm.hideAddressBar;
|
||
|
}
|
||
|
}
|
||
|
connect.connect(null, (win.global.onorientationchange !== undefined && !has("android"))
|
||
|
? "onorientationchange" : "onresize", null, f);
|
||
|
|
||
|
// avoid use of query
|
||
|
/*
|
||
|
var list = query('[__dojoType]', null);
|
||
|
list.forEach(function(node, index, nodeList){
|
||
|
node.setAttribute("dojoType", node.getAttribute("__dojoType"));
|
||
|
node.removeAttribute("__dojoType");
|
||
|
});
|
||
|
*/
|
||
|
|
||
|
var nodes = win.body().getElementsByTagName("*");
|
||
|
var i, len = nodes.length, s;
|
||
|
for(i = 0; i < len; i++){
|
||
|
s = nodes[i].getAttribute("__dojoType");
|
||
|
if(s){
|
||
|
nodes[i].setAttribute("dojoType", s);
|
||
|
nodes[i].removeAttribute("__dojoType");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(dojo.hash){
|
||
|
// find widgets under root recursively
|
||
|
var findWidgets = function(root){
|
||
|
if(!root){ return []; }
|
||
|
var arr = registry.findWidgets(root);
|
||
|
var widgets = arr;
|
||
|
for(var i = 0; i < widgets.length; i++){
|
||
|
arr = arr.concat(findWidgets(widgets[i].containerNode));
|
||
|
}
|
||
|
return arr;
|
||
|
};
|
||
|
connect.subscribe("/dojo/hashchange", null, function(value){
|
||
|
var view = dm.currentView;
|
||
|
if(!view){ return; }
|
||
|
var params = dm._params;
|
||
|
if(!params){ // browser back/forward button was pressed
|
||
|
var moveTo = value ? value : dm._defaultView.id;
|
||
|
var widgets = findWidgets(view.domNode);
|
||
|
var dir = 1, transition = "slide";
|
||
|
for(i = 0; i < widgets.length; i++){
|
||
|
var w = widgets[i];
|
||
|
if("#"+moveTo == w.moveTo){
|
||
|
// found a widget that has the given moveTo
|
||
|
transition = w.transition;
|
||
|
dir = (w instanceof dm.Heading) ? -1 : 1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
params = [ moveTo, dir, transition ];
|
||
|
}
|
||
|
view.performTransition.apply(view, params);
|
||
|
dm._params = null;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
win.body().style.visibility = "visible";
|
||
|
});
|
||
|
|
||
|
// To search _parentNode first. TODO:1.8 reconsider this redefinition.
|
||
|
registry.getEnclosingWidget = function(node){
|
||
|
while(node){
|
||
|
var id = node.getAttribute && node.getAttribute("widgetId");
|
||
|
if(id){
|
||
|
return registry.byId(id);
|
||
|
}
|
||
|
node = node._parentNode || node.parentNode;
|
||
|
}
|
||
|
return null;
|
||
|
};
|
||
|
|
||
|
return dm;
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/uacss':function(){
|
||
|
define("dojox/mobile/uacss", [
|
||
|
"dojo/_base/kernel",
|
||
|
"dojo/_base/lang",
|
||
|
"dojo/_base/window",
|
||
|
"dojox/mobile/sniff"
|
||
|
], function(dojo, lang, win, has){
|
||
|
win.doc.documentElement.className += lang.trim([
|
||
|
has("bb") ? "dj_bb" : "",
|
||
|
has("android") ? "dj_android" : "",
|
||
|
has("iphone") ? "dj_iphone" : "",
|
||
|
has("ipod") ? "dj_ipod" : "",
|
||
|
has("ipad") ? "dj_ipad" : ""
|
||
|
].join(" ").replace(/ +/g," "));
|
||
|
return dojo;
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/RoundRectCategory':function(){
|
||
|
define([
|
||
|
"dojo/_base/declare",
|
||
|
"dojo/_base/window",
|
||
|
"dijit/_Contained",
|
||
|
"dijit/_WidgetBase"
|
||
|
], function(declare, win, Contained, WidgetBase){
|
||
|
|
||
|
/*=====
|
||
|
var Contained = dijit._Contained;
|
||
|
var WidgetBase = dijit._WidgetBase;
|
||
|
=====*/
|
||
|
|
||
|
// module:
|
||
|
// dojox/mobile/RoundRectCategory
|
||
|
// summary:
|
||
|
// A category header for a rounded rectangle list.
|
||
|
|
||
|
return declare("dojox.mobile.RoundRectCategory", [WidgetBase, Contained],{
|
||
|
// summary:
|
||
|
// A category header for a rounded rectangle list.
|
||
|
|
||
|
// label: String
|
||
|
// A label text for the widget.
|
||
|
label: "",
|
||
|
|
||
|
buildRendering: function(){
|
||
|
this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement("H2");
|
||
|
this.domNode.className = "mblRoundRectCategory";
|
||
|
if(!this.label){
|
||
|
this.label = this.domNode.innerHTML;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_setLabelAttr: function(/*String*/label){
|
||
|
this.label = label;
|
||
|
this.domNode.innerHTML = this._cv ? this._cv(label) : label;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/ProgressIndicator':function(){
|
||
|
define([
|
||
|
"dojo/_base/config",
|
||
|
"dojo/_base/declare",
|
||
|
"dojo/dom-construct",
|
||
|
"dojo/dom-style",
|
||
|
"dojo/has"
|
||
|
], function(config, declare, domConstruct, domStyle, has){
|
||
|
|
||
|
// module:
|
||
|
// dojox/mobile/ProgressIndicator
|
||
|
// summary:
|
||
|
// A progress indication widget.
|
||
|
|
||
|
var cls = declare("dojox.mobile.ProgressIndicator", null, {
|
||
|
// summary:
|
||
|
// A progress indication widget.
|
||
|
// description:
|
||
|
// ProgressIndicator is a round spinning graphical representation
|
||
|
// that indicates the current task is on-going.
|
||
|
|
||
|
// interval: Number
|
||
|
// The time interval in milliseconds for updating the spinning
|
||
|
// indicator.
|
||
|
interval: 100,
|
||
|
|
||
|
// colors: Array
|
||
|
// An array of indicator colors.
|
||
|
colors: [
|
||
|
"#C0C0C0", "#C0C0C0", "#C0C0C0", "#C0C0C0",
|
||
|
"#C0C0C0", "#C0C0C0", "#B8B9B8", "#AEAFAE",
|
||
|
"#A4A5A4", "#9A9A9A", "#8E8E8E", "#838383"
|
||
|
],
|
||
|
|
||
|
constructor: function(){
|
||
|
this._bars = [];
|
||
|
this.domNode = domConstruct.create("DIV");
|
||
|
this.domNode.className = "mblProgContainer";
|
||
|
if(config["mblAndroidWorkaround"] !== false && has("android") >= 2.2 && has("android") < 3){
|
||
|
// workaround to avoid the side effects of the fixes for android screen flicker problem
|
||
|
domStyle.set(this.domNode, "webkitTransform", "translate3d(0,0,0)");
|
||
|
}
|
||
|
this.spinnerNode = domConstruct.create("DIV", null, this.domNode);
|
||
|
for(var i = 0; i < this.colors.length; i++){
|
||
|
var div = domConstruct.create("DIV", {className:"mblProg mblProg"+i}, this.spinnerNode);
|
||
|
this._bars.push(div);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
start: function(){
|
||
|
// summary:
|
||
|
// Starts the ProgressIndicator spinning.
|
||
|
if(this.imageNode){
|
||
|
var img = this.imageNode;
|
||
|
var l = Math.round((this.domNode.offsetWidth - img.offsetWidth) / 2);
|
||
|
var t = Math.round((this.domNode.offsetHeight - img.offsetHeight) / 2);
|
||
|
img.style.margin = t+"px "+l+"px";
|
||
|
return;
|
||
|
}
|
||
|
var cntr = 0;
|
||
|
var _this = this;
|
||
|
var n = this.colors.length;
|
||
|
this.timer = setInterval(function(){
|
||
|
cntr--;
|
||
|
cntr = cntr < 0 ? n - 1 : cntr;
|
||
|
var c = _this.colors;
|
||
|
for(var i = 0; i < n; i++){
|
||
|
var idx = (cntr + i) % n;
|
||
|
_this._bars[i].style.backgroundColor = c[idx];
|
||
|
}
|
||
|
}, this.interval);
|
||
|
},
|
||
|
|
||
|
stop: function(){
|
||
|
// summary:
|
||
|
// Stops the ProgressIndicator spinning.
|
||
|
if(this.timer){
|
||
|
clearInterval(this.timer);
|
||
|
}
|
||
|
this.timer = null;
|
||
|
if(this.domNode.parentNode){
|
||
|
this.domNode.parentNode.removeChild(this.domNode);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
setImage: function(/*String*/file){
|
||
|
// summary:
|
||
|
// Sets an indicator icon image file (typically animated GIF).
|
||
|
// If null is specified, restores the default spinner.
|
||
|
if(file){
|
||
|
this.imageNode = domConstruct.create("IMG", {src:file}, this.domNode);
|
||
|
this.spinnerNode.style.display = "none";
|
||
|
}else{
|
||
|
if(this.imageNode){
|
||
|
this.domNode.removeChild(this.imageNode);
|
||
|
this.imageNode = null;
|
||
|
}
|
||
|
this.spinnerNode.style.display = "";
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
cls._instance = null;
|
||
|
cls.getInstance = function(){
|
||
|
if(!cls._instance){
|
||
|
cls._instance = new cls();
|
||
|
}
|
||
|
return cls._instance;
|
||
|
};
|
||
|
|
||
|
return cls;
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/EdgeToEdgeList':function(){
|
||
|
define([
|
||
|
"dojo/_base/declare",
|
||
|
"./RoundRectList"
|
||
|
], function(declare, RoundRectList){
|
||
|
|
||
|
/*=====
|
||
|
var RoundRectList = dojox.mobile.RoundRectList;
|
||
|
=====*/
|
||
|
|
||
|
// module:
|
||
|
// dojox/mobile/EdgeToEdgeCategory
|
||
|
// summary:
|
||
|
// An edge-to-edge layout list.
|
||
|
|
||
|
return declare("dojox.mobile.EdgeToEdgeList", RoundRectList, {
|
||
|
// summary:
|
||
|
// An edge-to-edge layout list.
|
||
|
// description:
|
||
|
// EdgeToEdgeList is an edge-to-edge layout list, which displays
|
||
|
// all items in equally sized rows. Each item must be
|
||
|
// dojox.mobile.ListItem.
|
||
|
|
||
|
buildRendering: function(){
|
||
|
this.inherited(arguments);
|
||
|
this.domNode.className = "mblEdgeToEdgeList";
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/EdgeToEdgeCategory':function(){
|
||
|
define([
|
||
|
"dojo/_base/declare",
|
||
|
"./RoundRectCategory"
|
||
|
], function(declare, RoundRectCategory){
|
||
|
|
||
|
/*=====
|
||
|
var RoundRectCategory = dojox.mobile.RoundRectCategory;
|
||
|
=====*/
|
||
|
|
||
|
// module:
|
||
|
// dojox/mobile/EdgeToEdgeCategory
|
||
|
// summary:
|
||
|
// A category header for an edge-to-edge list.
|
||
|
|
||
|
return declare("dojox.mobile.EdgeToEdgeCategory", RoundRectCategory, {
|
||
|
// summary:
|
||
|
// A category header for an edge-to-edge list.
|
||
|
buildRendering: function(){
|
||
|
this.inherited(arguments);
|
||
|
this.domNode.className = "mblEdgeToEdgeCategory";
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/ToolBarButton':function(){
|
||
|
define([
|
||
|
"dojo/_base/declare",
|
||
|
"dojo/_base/window",
|
||
|
"dojo/dom-class",
|
||
|
"dojo/dom-construct",
|
||
|
"dojo/dom-style",
|
||
|
"./common",
|
||
|
"./_ItemBase"
|
||
|
], function(declare, win, domClass, domConstruct, domStyle, common, ItemBase){
|
||
|
/*=====
|
||
|
var ItemBase = dojox.mobile._ItemBase;
|
||
|
=====*/
|
||
|
|
||
|
// module:
|
||
|
// dojox/mobile/ToolBarButton
|
||
|
// summary:
|
||
|
// A button widget that is placed in the Heading widget.
|
||
|
|
||
|
return declare("dojox.mobile.ToolBarButton", ItemBase, {
|
||
|
// summary:
|
||
|
// A button widget that is placed in the Heading widget.
|
||
|
// description:
|
||
|
// ToolBarButton is a button that is placed in the Heading
|
||
|
// widget. It is a subclass of dojox.mobile._ItemBase just like
|
||
|
// ListItem or IconItem. So, unlike Button, it has basically the
|
||
|
// same capability as ListItem or IconItem, such as icon support,
|
||
|
// transition, etc.
|
||
|
|
||
|
// selected: Boolean
|
||
|
// If true, the button is in the selected status.
|
||
|
selected: false,
|
||
|
|
||
|
// btnClass: String
|
||
|
// Deprecated.
|
||
|
btnClass: "",
|
||
|
|
||
|
/* internal properties */
|
||
|
_defaultColor: "mblColorDefault",
|
||
|
_selColor: "mblColorDefaultSel",
|
||
|
|
||
|
buildRendering: function(){
|
||
|
this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement("div");
|
||
|
this.inheritParams();
|
||
|
domClass.add(this.domNode, "mblToolBarButton mblArrowButtonText");
|
||
|
var color;
|
||
|
if(this.selected){
|
||
|
color = this._selColor;
|
||
|
}else if(this.domNode.className.indexOf("mblColor") == -1){
|
||
|
color = this._defaultColor;
|
||
|
}
|
||
|
domClass.add(this.domNode, color);
|
||
|
|
||
|
if(!this.label){
|
||
|
this.label = this.domNode.innerHTML;
|
||
|
}
|
||
|
|
||
|
if(this.icon && this.icon != "none"){
|
||
|
this.iconNode = domConstruct.create("div", {className:"mblToolBarButtonIcon"}, this.domNode);
|
||
|
common.createIcon(this.icon, this.iconPos, null, this.alt, this.iconNode);
|
||
|
if(this.iconPos){
|
||
|
domClass.add(this.iconNode.firstChild, "mblToolBarButtonSpriteIcon");
|
||
|
}
|
||
|
}else{
|
||
|
if(common.createDomButton(this.domNode)){
|
||
|
domClass.add(this.domNode, "mblToolBarButtonDomButton");
|
||
|
}else{
|
||
|
domClass.add(this.domNode, "mblToolBarButtonText");
|
||
|
}
|
||
|
}
|
||
|
this.connect(this.domNode, "onclick", "onClick");
|
||
|
},
|
||
|
|
||
|
select: function(){
|
||
|
// summary:
|
||
|
// Makes this widget in the selected state.
|
||
|
domClass.toggle(this.domNode, this._selColor, !arguments[0]);
|
||
|
this.selected = !arguments[0];
|
||
|
},
|
||
|
|
||
|
deselect: function(){
|
||
|
// summary:
|
||
|
// Makes this widget in the deselected state.
|
||
|
this.select(true);
|
||
|
},
|
||
|
|
||
|
onClick: function(e){
|
||
|
this.setTransitionPos(e);
|
||
|
this.defaultClickAction();
|
||
|
},
|
||
|
|
||
|
_setBtnClassAttr: function(/*String*/btnClass){
|
||
|
var node = this.domNode;
|
||
|
if(node.className.match(/(mblDomButton\w+)/)){
|
||
|
domClass.remove(node, RegExp.$1);
|
||
|
}
|
||
|
domClass.add(node, btnClass);
|
||
|
if(common.createDomButton(this.domNode)){
|
||
|
domClass.add(this.domNode, "mblToolBarButtonDomButton");
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_setLabelAttr: function(/*String*/text){
|
||
|
this.label = text;
|
||
|
this.domNode.innerHTML = this._cv ? this._cv(text) : text;
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/_ItemBase':function(){
|
||
|
define("dojox/mobile/_ItemBase", [
|
||
|
"dojo/_base/kernel",
|
||
|
"dojo/_base/config",
|
||
|
"dojo/_base/declare",
|
||
|
"dijit/registry", // registry.getEnclosingWidget
|
||
|
"dijit/_Contained",
|
||
|
"dijit/_Container",
|
||
|
"dijit/_WidgetBase",
|
||
|
"./TransitionEvent",
|
||
|
"./View"
|
||
|
], function(kernel, config, declare, registry, Contained, Container, WidgetBase, TransitionEvent, View){
|
||
|
|
||
|
/*=====
|
||
|
var Contained = dijit._Contained;
|
||
|
var Container = dijit._Container;
|
||
|
var WidgetBase = dijit._WidgetBase;
|
||
|
var TransitionEvent = dojox.mobile.TransitionEvent;
|
||
|
var View = dojox.mobile.View;
|
||
|
=====*/
|
||
|
|
||
|
// module:
|
||
|
// dojox/mobile/_ItemBase
|
||
|
// summary:
|
||
|
// A base class for item classes (e.g. ListItem, IconItem, etc.)
|
||
|
|
||
|
return declare("dojox.mobile._ItemBase", [WidgetBase, Container, Contained],{
|
||
|
// summary:
|
||
|
// A base class for item classes (e.g. ListItem, IconItem, etc.)
|
||
|
// description:
|
||
|
// _ItemBase is a base class for widgets that have capability to
|
||
|
// make a view transition when clicked.
|
||
|
|
||
|
// icon: String
|
||
|
// An icon image to display. The value can be either a path for an
|
||
|
// image file or a class name of a DOM button. If icon is not
|
||
|
// specified, the iconBase parameter of the parent widget is used.
|
||
|
icon: "",
|
||
|
|
||
|
// iconPos: String
|
||
|
// The position of an aggregated icon. IconPos is comma separated
|
||
|
// values like top,left,width,height (ex. "0,0,29,29"). If iconPos
|
||
|
// is not specified, the iconPos parameter of the parent widget is
|
||
|
// used.
|
||
|
iconPos: "", // top,left,width,height (ex. "0,0,29,29")
|
||
|
|
||
|
// alt: String
|
||
|
// An alt text for the icon image.
|
||
|
alt: "",
|
||
|
|
||
|
// href: String
|
||
|
// A URL of another web page to go to.
|
||
|
href: "",
|
||
|
|
||
|
// hrefTarget: String
|
||
|
// A target that specifies where to open a page specified by
|
||
|
// href. The value will be passed to the 2nd argument of
|
||
|
// window.open().
|
||
|
hrefTarget: "",
|
||
|
|
||
|
// moveTo: String
|
||
|
// The id of the transition destination view which resides in the
|
||
|
// current page.
|
||
|
//
|
||
|
// If the value has a hash sign ('#') before the id (e.g. #view1)
|
||
|
// and the dojo.hash module is loaded by the user application, the
|
||
|
// view transition updates the hash in the browser URL so that the
|
||
|
// user can bookmark the destination view. In this case, the user
|
||
|
// can also use the browser's back/forward button to navigate
|
||
|
// through the views in the browser history.
|
||
|
//
|
||
|
// If null, transitions to a blank view.
|
||
|
// If '#', returns immediately without transition.
|
||
|
moveTo: "",
|
||
|
|
||
|
// scene: String
|
||
|
// The name of a scene. Used from dojox.mobile.app.
|
||
|
scene: "",
|
||
|
|
||
|
// clickable: Boolean
|
||
|
// If true, this item becomes clickable even if a transition
|
||
|
// destination (moveTo, etc.) is not specified.
|
||
|
clickable: false,
|
||
|
|
||
|
// url: String
|
||
|
// A URL of an html fragment page or JSON data that represents a
|
||
|
// new view content. The view content is loaded with XHR and
|
||
|
// inserted in the current page. Then a view transition occurs to
|
||
|
// the newly created view. The view is cached so that subsequent
|
||
|
// requests would not load the content again.
|
||
|
url: "",
|
||
|
|
||
|
// urlTarget: String
|
||
|
// Node id under which a new view will be created according to the
|
||
|
// url parameter. If not specified, The new view will be created as
|
||
|
// a sibling of the current view.
|
||
|
urlTarget: "",
|
||
|
|
||
|
// transition: String
|
||
|
// A type of animated transition effect. You can choose from the
|
||
|
// standard transition types, "slide", "fade", "flip", or from the
|
||
|
// extended transition types, "cover", "coverv", "dissolve",
|
||
|
// "reveal", "revealv", "scaleIn", "scaleOut", "slidev",
|
||
|
// "swirl", "zoomIn", "zoomOut". If "none" is specified, transition
|
||
|
// occurs immediately without animation.
|
||
|
transition: "",
|
||
|
|
||
|
// transitionDir: Number
|
||
|
// The transition direction. If 1, transition forward. If -1,
|
||
|
// transition backward. For example, the slide transition slides
|
||
|
// the view from right to left when dir == 1, and from left to
|
||
|
// right when dir == -1.
|
||
|
transitionDir: 1,
|
||
|
|
||
|
// transitionOptions: Object
|
||
|
// A hash object that holds transition options.
|
||
|
transitionOptions: null,
|
||
|
|
||
|
// callback: Function|String
|
||
|
// A callback function that is called when the transition has been
|
||
|
// finished. A function reference, or name of a function in
|
||
|
// context.
|
||
|
callback: null,
|
||
|
|
||
|
// sync: Boolean
|
||
|
// If true, XHR for the view content specified with the url
|
||
|
// parameter is performed synchronously. If false, it is done
|
||
|
// asynchronously and the progress indicator is displayed while
|
||
|
// loading the content. This parameter is effective only when the
|
||
|
// url parameter is used.
|
||
|
sync: true,
|
||
|
|
||
|
// label: String
|
||
|
// A label of the item. If the label is not specified, innerHTML is
|
||
|
// used as a label.
|
||
|
label: "",
|
||
|
|
||
|
// toggle: Boolean
|
||
|
// If true, the item acts like a toggle button.
|
||
|
toggle: false,
|
||
|
|
||
|
// _duration: Number
|
||
|
// Duration of selection, milliseconds.
|
||
|
_duration: 800,
|
||
|
|
||
|
|
||
|
inheritParams: function(){
|
||
|
var parent = this.getParent();
|
||
|
if(parent){
|
||
|
if(!this.transition){ this.transition = parent.transition; }
|
||
|
if(this.icon && parent.iconBase &&
|
||
|
parent.iconBase.charAt(parent.iconBase.length - 1) === '/'){
|
||
|
this.icon = parent.iconBase + this.icon;
|
||
|
}
|
||
|
if(!this.icon){ this.icon = parent.iconBase; }
|
||
|
if(!this.iconPos){ this.iconPos = parent.iconPos; }
|
||
|
}
|
||
|
},
|
||
|
|
||
|
select: function(){
|
||
|
// summary:
|
||
|
// Makes this widget in the selected state.
|
||
|
// description:
|
||
|
// Subclass must implement.
|
||
|
},
|
||
|
|
||
|
deselect: function(){
|
||
|
// summary:
|
||
|
// Makes this widget in the deselected state.
|
||
|
// description:
|
||
|
// Subclass must implement.
|
||
|
},
|
||
|
|
||
|
defaultClickAction: function(e){
|
||
|
if(this.toggle){
|
||
|
if(this.selected){
|
||
|
this.deselect();
|
||
|
}else{
|
||
|
this.select();
|
||
|
}
|
||
|
}else if(!this.selected){
|
||
|
this.select();
|
||
|
if(!this.selectOne){
|
||
|
var _this = this;
|
||
|
setTimeout(function(){
|
||
|
_this.deselect();
|
||
|
}, this._duration);
|
||
|
}
|
||
|
var transOpts;
|
||
|
if(this.moveTo || this.href || this.url || this.scene){
|
||
|
transOpts = {moveTo: this.moveTo, href: this.href, url: this.url, scene: this.scene, transition: this.transition, transitionDir: this.transitionDir};
|
||
|
}else if(this.transitionOptions){
|
||
|
transOpts = this.transitionOptions;
|
||
|
}
|
||
|
if(transOpts){
|
||
|
return new TransitionEvent(this.domNode,transOpts,e).dispatch();
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
getParent: function(){
|
||
|
// summary:
|
||
|
// Gets the parent widget.
|
||
|
// description:
|
||
|
// Almost equivalent to _Contained#getParent, but this method
|
||
|
// does not cause a script error even if this widget has no
|
||
|
// parent yet.
|
||
|
var ref = this.srcNodeRef || this.domNode;
|
||
|
return ref && ref.parentNode ? registry.getEnclosingWidget(ref.parentNode) : null;
|
||
|
},
|
||
|
|
||
|
setTransitionPos: function(e){
|
||
|
// summary:
|
||
|
// Stores the clicked position for later use.
|
||
|
// description:
|
||
|
// Some of the transition animations (e.g. ScaleIn) needs the
|
||
|
// clicked position.
|
||
|
var w = this;
|
||
|
while(true){
|
||
|
w = w.getParent();
|
||
|
if(!w || w instanceof View){ break; }
|
||
|
}
|
||
|
if(w){
|
||
|
w.clickedPosX = e.clientX;
|
||
|
w.clickedPosY = e.clientY;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
transitionTo: function(moveTo, href, url, scene){
|
||
|
// summary:
|
||
|
// Performs a view transition.
|
||
|
// description:
|
||
|
// Given a transition destination, this method performs a view
|
||
|
// transition. This method is typically called when this item
|
||
|
// is clicked.
|
||
|
if(config.isDebug){
|
||
|
var alreadyCalledHash = arguments.callee._ach || (arguments.callee._ach = {}),
|
||
|
caller = (arguments.callee.caller || "unknown caller").toString();
|
||
|
if(!alreadyCalledHash[caller]){
|
||
|
kernel.deprecated(this.declaredClass + "::transitionTo() is deprecated." +
|
||
|
caller, "", "2.0");
|
||
|
alreadyCalledHash[caller] = true;
|
||
|
}
|
||
|
}
|
||
|
new TransitionEvent(this.domNode, {moveTo: moveTo, href: href, url: url, scene: scene,
|
||
|
transition: this.transition, transitionDir: this.transitionDir}).dispatch();
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dijit/_Contained':function(){
|
||
|
define("dijit/_Contained", [
|
||
|
"dojo/_base/declare", // declare
|
||
|
"./registry" // registry.getEnclosingWidget(), registry.byNode()
|
||
|
], function(declare, registry){
|
||
|
|
||
|
// module:
|
||
|
// dijit/_Contained
|
||
|
// summary:
|
||
|
// Mixin for widgets that are children of a container widget
|
||
|
|
||
|
return declare("dijit._Contained", null, {
|
||
|
// summary:
|
||
|
// Mixin for widgets that are children of a container widget
|
||
|
//
|
||
|
// example:
|
||
|
// | // make a basic custom widget that knows about it's parents
|
||
|
// | declare("my.customClass",[dijit._Widget,dijit._Contained],{});
|
||
|
|
||
|
_getSibling: function(/*String*/ which){
|
||
|
// summary:
|
||
|
// Returns next or previous sibling
|
||
|
// which:
|
||
|
// Either "next" or "previous"
|
||
|
// tags:
|
||
|
// private
|
||
|
var node = this.domNode;
|
||
|
do{
|
||
|
node = node[which+"Sibling"];
|
||
|
}while(node && node.nodeType != 1);
|
||
|
return node && registry.byNode(node); // dijit._Widget
|
||
|
},
|
||
|
|
||
|
getPreviousSibling: function(){
|
||
|
// summary:
|
||
|
// Returns null if this is the first child of the parent,
|
||
|
// otherwise returns the next element sibling to the "left".
|
||
|
|
||
|
return this._getSibling("previous"); // dijit._Widget
|
||
|
},
|
||
|
|
||
|
getNextSibling: function(){
|
||
|
// summary:
|
||
|
// Returns null if this is the last child of the parent,
|
||
|
// otherwise returns the next element sibling to the "right".
|
||
|
|
||
|
return this._getSibling("next"); // dijit._Widget
|
||
|
},
|
||
|
|
||
|
getIndexInParent: function(){
|
||
|
// summary:
|
||
|
// Returns the index of this widget within its container parent.
|
||
|
// It returns -1 if the parent does not exist, or if the parent
|
||
|
// is not a dijit._Container
|
||
|
|
||
|
var p = this.getParent();
|
||
|
if(!p || !p.getIndexOfChild){
|
||
|
return -1; // int
|
||
|
}
|
||
|
return p.getIndexOfChild(this); // int
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dojox/mobile/_base':function(){
|
||
|
define([
|
||
|
"./common",
|
||
|
"./View",
|
||
|
"./Heading",
|
||
|
"./RoundRect",
|
||
|
"./RoundRectCategory",
|
||
|
"./EdgeToEdgeCategory",
|
||
|
"./RoundRectList",
|
||
|
"./EdgeToEdgeList",
|
||
|
"./ListItem",
|
||
|
"./Switch",
|
||
|
"./ToolBarButton",
|
||
|
"./ProgressIndicator"
|
||
|
], function(common, View, Heading, RoundRect, RoundRectCategory, EdgeToEdgeCategory, RoundRectList, EdgeToEdgeList, ListItem, Switch, ToolBarButton, ProgressIndicator){
|
||
|
// module:
|
||
|
// dojox/mobile/_base
|
||
|
// summary:
|
||
|
// Includes the basic dojox.mobile modules
|
||
|
|
||
|
return common;
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dijit/main':function(){
|
||
|
define("dijit/main", [
|
||
|
"dojo/_base/kernel"
|
||
|
], function(dojo){
|
||
|
// module:
|
||
|
// dijit
|
||
|
// summary:
|
||
|
// The dijit package main module
|
||
|
|
||
|
return dojo.dijit;
|
||
|
});
|
||
|
|
||
|
},
|
||
|
'dijit/_Container':function(){
|
||
|
define("dijit/_Container", [
|
||
|
"dojo/_base/array", // array.forEach array.indexOf
|
||
|
"dojo/_base/declare", // declare
|
||
|
"dojo/dom-construct", // domConstruct.place
|
||
|
"./registry" // registry.byNode()
|
||
|
], function(array, declare, domConstruct, registry){
|
||
|
|
||
|
// module:
|
||
|
// dijit/_Container
|
||
|
// summary:
|
||
|
// Mixin for widgets that contain a set of widget children.
|
||
|
|
||
|
return declare("dijit._Container", null, {
|
||
|
// summary:
|
||
|
// Mixin for widgets that contain a set of widget children.
|
||
|
// description:
|
||
|
// Use this mixin for widgets that needs to know about and
|
||
|
// keep track of their widget children. Suitable for widgets like BorderContainer
|
||
|
// and TabContainer which contain (only) a set of child widgets.
|
||
|
//
|
||
|
// It's not suitable for widgets like ContentPane
|
||
|
// which contains mixed HTML (plain DOM nodes in addition to widgets),
|
||
|
// and where contained widgets are not necessarily directly below
|
||
|
// this.containerNode. In that case calls like addChild(node, position)
|
||
|
// wouldn't make sense.
|
||
|
|
||
|
buildRendering: function(){
|
||
|
this.inherited(arguments);
|
||
|
if(!this.containerNode){
|
||
|
// all widgets with descendants must set containerNode
|
||
|
this.containerNode = this.domNode;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
|
||
|
// summary:
|
||
|
// Makes the given widget a child of this widget.
|
||
|
// description:
|
||
|
// Inserts specified child widget's dom node as a child of this widget's
|
||
|
// container node, and possibly does other processing (such as layout).
|
||
|
|
||
|
var refNode = this.containerNode;
|
||
|
if(insertIndex && typeof insertIndex == "number"){
|
||
|
var children = this.getChildren();
|
||
|
if(children && children.length >= insertIndex){
|
||
|
refNode = children[insertIndex-1].domNode;
|
||
|
insertIndex = "after";
|
||
|
}
|
||
|
}
|
||
|
domConstruct.place(widget.domNode, refNode, insertIndex);
|
||
|
|
||
|
// If I've been started but the child widget hasn't been started,
|
||
|
// start it now. Make sure to do this after widget has been
|
||
|
// inserted into the DOM tree, so it can see that it's being controlled by me,
|
||
|
// so it doesn't try to size itself.
|
||
|
if(this._started && !widget._started){
|
||
|
widget.startup();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
removeChild: function(/*Widget|int*/ widget){
|
||
|
// summary:
|
||
|
// Removes the passed widget instance from this widget but does
|
||
|
// not destroy it. You can also pass in an integer indicating
|
||
|
// the index within the container to remove
|
||
|
|
||
|
if(typeof widget == "number"){
|
||
|
widget = this.getChildren()[widget];
|
||
|
}
|
||
|
|
||
|
if(widget){
|
||
|
var node = widget.domNode;
|
||
|
if(node && node.parentNode){
|
||
|
node.parentNode.removeChild(node); // detach but don't destroy
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
hasChildren: function(){
|
||
|
// summary:
|
||
|
// Returns true if widget has children, i.e. if this.containerNode contains something.
|
||
|
return this.getChildren().length > 0; // Boolean
|
||
|
},
|
||
|
|
||
|
_getSiblingOfChild: function(/*dijit._Widget*/ child, /*int*/ dir){
|
||
|
// summary:
|
||
|
// Get the next or previous widget sibling of child
|
||
|
// dir:
|
||
|
// if 1, get the next sibling
|
||
|
// if -1, get the previous sibling
|
||
|
// tags:
|
||
|
// private
|
||
|
var node = child.domNode,
|
||
|
which = (dir>0 ? "nextSibling" : "previousSibling");
|
||
|
do{
|
||
|
node = node[which];
|
||
|
}while(node && (node.nodeType != 1 || !registry.byNode(node)));
|
||
|
return node && registry.byNode(node); // dijit._Widget
|
||
|
},
|
||
|
|
||
|
getIndexOfChild: function(/*dijit._Widget*/ child){
|
||
|
// summary:
|
||
|
// Gets the index of the child in this container or -1 if not found
|
||
|
return array.indexOf(this.getChildren(), child); // int
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
}}});
|
||
|
|
||
|
require(["dojo/i18n"], function(i18n){
|
||
|
i18n._preloadLocalizations("dojox/nls/mobile", []);
|
||
|
});
|
||
|
define("dojox/mobile", [
|
||
|
".",
|
||
|
"dojo/_base/lang",
|
||
|
"dojox/mobile/_base"
|
||
|
], function(dojox, lang, base){
|
||
|
lang.getObject("mobile", true, dojox);
|
||
|
return dojox.mobile;
|
||
|
});
|