require({cache:{
'dojox/mobile':function(){
define([
".",
"dojo/_base/lang",
"dojox/mobile/_base"
], function(dojox, lang, base){
lang.getObject("mobile", true, dojox);
/*=====
return {
// summary:
// Deprecated. Should require dojox/mobile classes directly rather than trying to access them through
// this module.
};
=====*/
return dojox.mobile;
});
},
'dojox/main':function(){
define(["dojo/_base/kernel"], function(dojo) {
// module:
// dojox/main
/*=====
return {
// summary:
// The dojox package main module; dojox package is somewhat unusual in that the main module currently just provides an empty object.
// Apps should require modules from the dojox packages directly, rather than loading this module.
};
=====*/
return dojo.dojox;
});
},
'dojox/mobile/_base':function(){
define([
"./common",
"./View",
"./Heading",
"./RoundRect",
"./RoundRectCategory",
"./EdgeToEdgeCategory",
"./RoundRectList",
"./EdgeToEdgeList",
"./ListItem",
"./Container",
"./Pane",
"./Switch",
"./ToolBarButton",
"./ProgressIndicator"
], function(common, View, Heading, RoundRect, RoundRectCategory, EdgeToEdgeCategory, RoundRectList, EdgeToEdgeList, ListItem, Switch, ToolBarButton, ProgressIndicator){
// module:
// dojox/mobile/_base
/*=====
return {
// summary:
// Includes the basic dojox/mobile modules: common, View, Heading,
// RoundRect, RoundRectCategory, EdgeToEdgeCategory, RoundRectList,
// EdgeToEdgeList, ListItem, Container, Pane, Switch, ToolBarButton,
// and ProgressIndicator.
};
=====*/
return common;
});
},
'dojox/mobile/common':function(){
define([
"dojo/_base/array",
"dojo/_base/config",
"dojo/_base/connect",
"dojo/_base/lang",
"dojo/_base/window",
"dojo/_base/kernel",
"dojo/dom",
"dojo/dom-class",
"dojo/dom-construct",
"dojo/domReady",
"dojo/ready",
"dojo/touch",
"dijit/registry",
"./sniff",
"./uacss" // (no direct references)
], function(array, config, connect, lang, win, kernel, dom, domClass, domConstruct, domReady, ready, touch, registry, has){
// module:
// dojox/mobile/common
var dm = lang.getObject("dojox.mobile", true);
// tell dojo/touch to generate synthetic clicks immediately
// and regardless of preventDefault() calls on touch events
win.doc.dojoClick = true;
/// ... but let user disable this by removing dojoClick from the document
if(has("touch")){
// Do we need to send synthetic clicks when preventDefault() is called on touch events?
// This is normally true on anything except Android 4.1+ and IE10+, but users reported
// exceptions like Galaxy Note 2. So let's use a has("clicks-prevented") flag, and let
// applications override it through data-dojo-config="has:{'clicks-prevented':true}" if needed.
has.add("clicks-prevented", !(has("android") >= 4.1 || (has("ie") === 10) || (!has("ie") && has("trident") > 6)));
if(has("clicks-prevented")){
dm._sendClick = function(target, e){
// dojo/touch will send a click if dojoClick is set, so don't do it again.
for(var node = target; node; node = node.parentNode){
if(node.dojoClick){
return;
}
}
var ev = win.doc.createEvent("MouseEvents");
ev.initMouseEvent("click", true, true, win.global, 1, e.screenX, e.screenY, e.clientX, e.clientY);
target.dispatchEvent(ev);
};
}
}
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 ``:
//
// - '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();
// 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(){
// summary:
// Internal function to hide the address bar.
// tags:
// private
scrollTo(0, 1);
dm._hidingTimer = (dm._hidingTimer == 0) ? 200 : dm._hidingTimer * 2;
setTimeout(function(){ // wait for a while for "scrollTo" to finish
if(dm.isAddressBarHidden() || dm._hidingTimer > dm.hideAddressBarWait){
// Succeeded to hide address bar, or failed but timed out
dm.resizeAll();
dm._hiding = false;
}else{
// Failed to hide address bar, so retry after a while
setTimeout(dm.hide_1, dm._hidingTimer);
}
}, 50); //50ms is an experiential value
};
dm.hideAddressBar = function(/*Event?*/evt){
// summary:
// Hides the address bar.
// description:
// Tries to hide the address bar a couple of times. The purpose is to do
// it as quick as possible while ensuring the resize is done after the hiding
// finishes.
if(dm.disableHideAddressBar || dm._hiding){ return; }
dm._hiding = true;
dm._hidingTimer = has("ios") ? 200 : 0; // Need to wait longer in case of iPhone
var minH = screen.availHeight;
if(has('android')){
minH = outerHeight / devicePixelRatio;
// On some Android devices such as Galaxy SII, minH might be 0 at this time.
// In that case, retry again after a while. (200ms is an experiential value)
if(minH == 0){
dm._hiding = false;
setTimeout(function(){ dm.hideAddressBar(); }, 200);
}
// On some Android devices such as HTC EVO, "outerHeight/devicePixelRatio"
// is too short to hide address bar, so make it high enough
if(minH <= innerHeight){ minH = outerHeight; }
// On Android 2.2/2.3, hiding address bar fails when "overflow:hidden" style is
// applied to html/body element, so force "overflow:visible" style
if(has('android') < 3){
win.doc.documentElement.style.overflow = win.body().style.overflow = "visible";
}
}
if(win.body().offsetHeight < minH){ // to ensure enough height for scrollTo to work
win.body().style.minHeight = minH + "px";
dm._resetMinHeight = true;
}
setTimeout(dm.hide_1, dm._hidingTimer);
};
dm.isAddressBarHidden = function(){
return pageYOffset === 1;
};
dm.resizeAll = function(/*Event?*/evt, /*Widget?*/root){
// summary:
// Calls the resize() method of all the top level resizable widgets.
// description:
// Finds all widgets that do not have a parent or the parent does not
// have the resize() method, and calls resize() for them.
// If a widget has a parent that has resize(), calling widget's
// resize() is its parent's responsibility.
// evt:
// Native event object
// root:
// If specified, searches 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, searches the entire page.
if(dm.disableResizeAll){ return; }
connect.publish("/dojox/mobile/resizeAll", [evt, root]); // back compat
connect.publish("/dojox/mobile/beforeResizeAll", [evt, root]);
if(dm._resetMinHeight){
win.body().style.minHeight = dm.getScreenSize().h + "px";
}
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(); });
}
connect.publish("/dojox/mobile/afterResizeAll", [evt, root]);
};
dm.openWindow = function(url, target){
// summary:
// Opens a new browser window with the given URL.
win.global.open(url, target || "_blank");
};
dm._detectWindowsTheme = function(){
// summary:
// Detects if the "windows" theme is used,
// if it is used, set has("windows-theme") and
// add the .windows_theme class on the document.
// Avoid unwanted (un)zoom on some WP8 devices (at least Nokia Lumia 920)
if(navigator.userAgent.match(/IEMobile\/10\.0/)){
domConstruct.create("style",
{innerHTML: "@-ms-viewport {width: auto !important}"}, win.doc.head);
}
var setWindowsTheme = function(){
domClass.add(win.doc.documentElement, "windows_theme");
kernel.experimental("Dojo Mobile Windows theme", "Behavior and appearance of the Windows theme are experimental.");
};
// First see if the "windows-theme" feature has already been set explicitly
// in that case skip aut-detect
var windows = has("windows-theme");
if(windows !== undefined){
if(windows){
setWindowsTheme();
}
return;
}
// check css
var i, j;
var check = function(href){
// TODO: find a better regexp to match?
if(href && href.indexOf("/windows/") !== -1){
has.add("windows-theme", true);
setWindowsTheme();
return true;
}
return false;
};
// collect @import
var s = win.doc.styleSheets;
for(i = 0; i < s.length; i++){
if(s[i].href){ continue; }
var r = s[i].cssRules || s[i].imports;
if(!r){ continue; }
for(j = 0; j < r.length; j++){
if(check(r[j].href)){
return;
}
}
}
// collect
var elems = win.doc.getElementsByTagName("link");
for(i = 0; i < elems.length; i++){
if(check(elems[i].href)){
return;
}
}
};
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(win.global._no_dojo_dm){
// deviceTheme seems to be loaded from a script tag (= non-dojo usage)
var _dm = win.global._no_dojo_dm;
for(var i in _dm){
dm[i] = _dm[i];
}
dm.deviceTheme.setDm(dm);
}
// flag for Android transition animation flicker workaround
has.add('mblAndroidWorkaround',
config.mblAndroidWorkaround !== false && has('android') < 3, undefined, true);
has.add('mblAndroid3Workaround',
config.mblAndroid3Workaround !== false && has('android') >= 3, undefined, true);
dm._detectWindowsTheme();
dm.setSelectable = function(/*Node*/node, /*Boolean*/selectable){
var nodes, i;
node = dom.byId(node);
if (has("ie") <= 9){
// (IE < 10) Fall back to setting/removing the
// unselectable attribute on the element and all its children
// except the input element (see https://bugs.dojotoolkit.org/ticket/13846)
nodes = node.getElementsByTagName("*");
i = nodes.length;
if(selectable){
node.removeAttribute("unselectable");
while(i--){
nodes[i].removeAttribute("unselectable");
}
}else{
node.setAttribute("unselectable", "on");
while(i--){
if (nodes[i].tagName !== "INPUT"){
nodes[i].setAttribute("unselectable", "on");
}
}
}
}else{
domClass.toggle(node, "unselectable", !selectable);
}
};
var touchActionProp = has("pointer-events") ? "touchAction" : has("MSPointer") ? "msTouchAction" : null;
dm._setTouchAction = touchActionProp ? function(/*Node*/node, /*Boolean*/value){
node.style[touchActionProp] = value;
} : function(){};
// Set the background style using dojo/domReady, not dojo/ready, to ensure it is already
// set at widget initialization time. (#17418)
domReady(function(){
if(config.mblApplyPageStyles !== false){
domClass.add(win.body(), "mblBackground");
}
});
ready(function(){
dm.detectScreenSize(true);
if(config.mblAndroidWorkaroundButtonStyle !== false && has('android')){
// workaround for the form button disappearing issue on Android 2.2-4.0
domConstruct.create("style", {innerHTML:"BUTTON,INPUT[type='button'],INPUT[type='submit'],INPUT[type='reset'],INPUT[type='file']::-webkit-file-upload-button{-webkit-appearance:none;} audio::-webkit-media-controls-play-button,video::-webkit-media-controls-play-button{-webkit-appearance:media-play-button;} video::-webkit-media-controls-fullscreen-button{-webkit-appearance:media-fullscreen-button;}"}, win.doc.head, "first");
}
if(has('mblAndroidWorkaround')){
// add a css class to show view offscreen for android flicker workaround
domConstruct.create("style", {innerHTML:".mblView.mblAndroidWorkaround{position:absolute;top:-9999px !important;left:-9999px !important;}"}, win.doc.head, "last");
}
var f = dm.resizeAll;
// Address bar hiding
var isHidingPossible =
navigator.appVersion.indexOf("Mobile") != -1 && // only mobile browsers
// #17455: hiding Safari's address bar works in iOS < 7 but this is
// no longer possible since iOS 7. Hence, exclude iOS 7 and later:
!(has("ios") >= 7);
// You can disable the hiding of the address bar with the following dojoConfig:
// var dojoConfig = { mblHideAddressBar: false };
// If unspecified, the flag defaults to true.
if((config.mblHideAddressBar !== false && isHidingPossible) ||
config.mblForceHideAddressBar === true){
dm.hideAddressBar();
if(config.mblAlwaysHideAddressBar === true){
f = dm.hideAddressBar;
}
}
var ios6 = has("ios") >= 6; // Full-screen support for iOS6 or later
if((has('android') || ios6) && win.global.onorientationchange !== undefined){
var _f = f;
var curSize, curClientWidth, curClientHeight;
if(ios6){
curClientWidth = win.doc.documentElement.clientWidth;
curClientHeight = win.doc.documentElement.clientHeight;
}else{ // Android
// Call resize for the first resize event after orientationchange
// because the size information may not yet be up to date when the
// event orientationchange occurs.
f = function(evt){
var _conn = connect.connect(null, "onresize", null, function(e){
connect.disconnect(_conn);
_f(e);
});
};
curSize = dm.getScreenSize();
};
// Android: Watch for resize events when the virtual keyboard is shown/hidden.
// The heuristic to detect this is that the screen width does not change
// and the height changes by more than 100 pixels.
//
// iOS >= 6: Watch for resize events when entering or existing the new iOS6
// full-screen mode. The heuristic to detect this is that clientWidth does not
// change while the clientHeight does change.
connect.connect(null, "onresize", null, function(e){
if(ios6){
var newClientWidth = win.doc.documentElement.clientWidth,
newClientHeight = win.doc.documentElement.clientHeight;
if(newClientWidth == curClientWidth && newClientHeight != curClientHeight){
// full-screen mode has been entered/exited (iOS6)
_f(e);
}
curClientWidth = newClientWidth;
curClientHeight = newClientHeight;
}else{ // Android
var newSize = dm.getScreenSize();
if(newSize.w == curSize.w && Math.abs(newSize.h - curSize.h) >= 100){
// keyboard has been shown/hidden (Android)
_f(e);
}
curSize = newSize;
}
});
}
connect.connect(null, win.global.onorientationchange !== undefined
? "onorientationchange" : "onresize", null, f);
win.body().style.visibility = "visible";
});
// TODO: return functions declared above in this hash, rather than
// dojox.mobile.
/*=====
return {
// 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.
};
=====*/
return dm;
});
},
'dojo/touch':function(){
define(["./_base/kernel", "./aspect", "./dom", "./dom-class", "./_base/lang", "./on", "./has", "./mouse", "./domReady", "./_base/window"],
function(dojo, aspect, dom, domClass, lang, on, has, mouse, domReady, win){
// module:
// dojo/touch
var ios4 = has("ios") < 5;
// Detect if platform supports Pointer Events, and if so, the names of the events (pointerdown vs. MSPointerDown).
var hasPointer = has("pointer-events") || has("MSPointer"),
pointer = (function () {
var pointer = {};
for (var type in { down: 1, move: 1, up: 1, cancel: 1, over: 1, out: 1 }) {
pointer[type] = has("MSPointer") ?
"MSPointer" + type.charAt(0).toUpperCase() + type.slice(1) :
"pointer" + type;
}
return pointer;
})();
// Detect if platform supports the webkit touchstart/touchend/... events
var hasTouch = has("touch-events");
// Click generation variables
var clicksInited, clickTracker, useTarget = false, clickTarget, clickX, clickY, clickDx, clickDy, clickTime;
// Time of most recent touchstart, touchmove, or touchend event
var lastTouch;
function dualEvent(mouseType, touchType, pointerType){
// Returns synthetic event that listens for both the specified mouse event and specified touch event.
// But ignore fake mouse events that were generated due to the user touching the screen.
if(hasPointer && pointerType){
// IE10+: MSPointer* events are designed to handle both mouse and touch in a uniform way,
// so just use that regardless of hasTouch.
return function(node, listener){
return on(node, pointerType, listener);
};
}else if(hasTouch){
return function(node, listener){
var handle1 = on(node, touchType, function(evt){
listener.call(this, evt);
// On slow mobile browsers (see https://bugs.dojotoolkit.org/ticket/17634),
// a handler for a touch event may take >1s to run. That time shouldn't
// be included in the calculation for lastTouch.
lastTouch = (new Date()).getTime();
}),
handle2 = on(node, mouseType, function(evt){
if(!lastTouch || (new Date()).getTime() > lastTouch + 1000){
listener.call(this, evt);
}
});
return {
remove: function(){
handle1.remove();
handle2.remove();
}
};
};
}else{
// Avoid creating listeners for touch events on performance sensitive older browsers like IE6
return function(node, listener){
return on(node, mouseType, listener);
};
}
}
function marked(/*DOMNode*/ node){
// Search for node ancestor has been marked with the dojoClick property to indicate special processing.
// Returns marked ancestor.
do{
if(node.dojoClick !== undefined){ return node; }
}while(node = node.parentNode);
}
function doClicks(e, moveType, endType){
// summary:
// Setup touch listeners to generate synthetic clicks immediately (rather than waiting for the browser
// to generate clicks after the double-tap delay) and consistently (regardless of whether event.preventDefault()
// was called in an event listener. Synthetic clicks are generated only if a node or one of its ancestors has
// its dojoClick property set to truthy. If a node receives synthetic clicks because one of its ancestors has its
// dojoClick property set to truthy, you can disable synthetic clicks on this node by setting its own dojoClick property
// to falsy.
if(mouse.isRight(e)){
return; // avoid spurious dojoclick event on IE10+; right click is just for context menu
}
var markedNode = marked(e.target);
clickTracker = !e.target.disabled && markedNode && markedNode.dojoClick; // click threshold = true, number, x/y object, or "useTarget"
if(clickTracker){
useTarget = (clickTracker == "useTarget");
clickTarget = (useTarget?markedNode:e.target);
if(useTarget){
// We expect a click, so prevent any other
// default action on "touchpress"
e.preventDefault();
}
clickX = e.changedTouches ? e.changedTouches[0].pageX - win.global.pageXOffset : e.clientX;
clickY = e.changedTouches ? e.changedTouches[0].pageY - win.global.pageYOffset : e.clientY;
clickDx = (typeof clickTracker == "object" ? clickTracker.x : (typeof clickTracker == "number" ? clickTracker : 0)) || 4;
clickDy = (typeof clickTracker == "object" ? clickTracker.y : (typeof clickTracker == "number" ? clickTracker : 0)) || 4;
// add move/end handlers only the first time a node with dojoClick is seen,
// so we don't add too much overhead when dojoClick is never set.
if(!clicksInited){
clicksInited = true;
var updateClickTracker = function updateClickTracker(e){
if(useTarget){
clickTracker = dom.isDescendant(
win.doc.elementFromPoint(
(e.changedTouches ? e.changedTouches[0].pageX - win.global.pageXOffset : e.clientX),
(e.changedTouches ? e.changedTouches[0].pageY - win.global.pageYOffset : e.clientY)),
clickTarget);
}else{
clickTracker = clickTracker &&
(e.changedTouches ? e.changedTouches[0].target : e.target) == clickTarget &&
Math.abs((e.changedTouches ? e.changedTouches[0].pageX - win.global.pageXOffset : e.clientX) - clickX) <= clickDx &&
Math.abs((e.changedTouches ? e.changedTouches[0].pageY - win.global.pageYOffset : e.clientY) - clickY) <= clickDy;
}
};
win.doc.addEventListener(moveType, function(e){
if(mouse.isRight(e)){
return; // avoid spurious dojoclick event on IE10+; right click is just for context menu
}
updateClickTracker(e);
if(useTarget){
// prevent native scroll event and ensure touchend is
// fire after touch moves between press and release.
e.preventDefault();
}
}, true);
win.doc.addEventListener(endType, function(e){
if(mouse.isRight(e)){
return; // avoid spurious dojoclick event on IE10+; right click is just for context menu
}
updateClickTracker(e);
if(clickTracker){
clickTime = (new Date()).getTime();
var target = (useTarget?clickTarget:e.target);
if(target.tagName === "LABEL"){
// when clicking on a label, forward click to its associated input if any
target = dom.byId(target.getAttribute("for")) || target;
}
//some attributes can be on the Touch object, not on the Event:
//http://www.w3.org/TR/touch-events/#touch-interface
var src = (e.changedTouches) ? e.changedTouches[0] : e;
var createMouseEvent = function createMouseEvent(type){
//create the synthetic event.
//http://www.w3.org/TR/DOM-Level-3-Events/#widl-MouseEvent-initMouseEvent
var evt = document.createEvent("MouseEvents");
evt._dojo_click = true;
evt.initMouseEvent(type,
true, //bubbles
true, //cancelable
e.view,
e.detail,
src.screenX,
src.screenY,
src.clientX,
src.clientY,
e.ctrlKey,
e.altKey,
e.shiftKey,
e.metaKey,
0, //button
null //related target
);
return evt;
};
var mouseDownEvt = createMouseEvent("mousedown");
var mouseUpEvt = createMouseEvent("mouseup");
var clickEvt = createMouseEvent("click");
setTimeout(function(){
on.emit(target, "mousedown", mouseDownEvt);
on.emit(target, "mouseup", mouseUpEvt);
on.emit(target, "click", clickEvt);
// refresh clickTime in case app-defined click handler took a long time to run
clickTime = (new Date()).getTime();
}, 0);
}
}, true);
var stopNativeEvents = function stopNativeEvents(type){
win.doc.addEventListener(type, function(e){
// Stop native events when we emitted our own click event. Note that the native click may occur
// on a different node than the synthetic click event was generated on. For example,
// click on a menu item, causing the menu to disappear, and then (~300ms later) the browser
// sends a click event to the node that was *underneath* the menu. So stop all native events
// sent shortly after ours, similar to what is done in dualEvent.
// The INPUT.dijitOffScreen test is for offscreen inputs used in dijit/form/Button, on which
// we call click() explicitly, we don't want to stop this event.
var target = e.target;
if(clickTracker && !e._dojo_click &&
(new Date()).getTime() <= clickTime + 1000 &&
!(target.tagName == "INPUT" && domClass.contains(target, "dijitOffScreen"))){
e.stopPropagation();
e.stopImmediatePropagation && e.stopImmediatePropagation();
if(type == "click" &&
(target.tagName != "INPUT" ||
(target.type == "radio" &&
// #18352 Do not preventDefault for radios that are not dijit or
// dojox/mobile widgets.
// (The CSS class dijitCheckBoxInput holds for both checkboxes and radio buttons.)
(domClass.contains(target, "dijitCheckBoxInput") ||
domClass.contains(target, "mblRadioButton"))) ||
(target.type == "checkbox" &&
// #18352 Do not preventDefault for checkboxes that are not dijit or
// dojox/mobile widgets.
(domClass.contains(target, "dijitCheckBoxInput") ||
domClass.contains(target, "mblCheckBox")))) &&
target.tagName != "TEXTAREA" && target.tagName != "AUDIO" && target.tagName != "VIDEO"){
// preventDefault() breaks textual s on android, keyboard doesn't popup,
// but it is still needed for checkboxes and radio buttons, otherwise in some cases
// the checked state becomes inconsistent with the widget's state
e.preventDefault();
}
}
}, true);
};
stopNativeEvents("click");
// We also stop mousedown/up since these would be sent well after with our "fast" click (300ms),
// which can confuse some dijit widgets.
stopNativeEvents("mousedown");
stopNativeEvents("mouseup");
}
}
}
var hoveredNode;
if(has("touch")){
if(hasPointer){
// MSPointer (IE10+) already has support for over and out, so we just need to init click support
domReady(function(){
win.doc.addEventListener(pointer.down, function(evt){
doClicks(evt, pointer.move, pointer.up);
}, true);
});
}else{
domReady(function(){
// Keep track of currently hovered node
hoveredNode = win.body(); // currently hovered node
win.doc.addEventListener("touchstart", function(evt){
lastTouch = (new Date()).getTime();
// Precede touchstart event with touch.over event. DnD depends on this.
// Use addEventListener(cb, true) to run cb before any touchstart handlers on node run,
// and to ensure this code runs even if the listener on the node does event.stop().
var oldNode = hoveredNode;
hoveredNode = evt.target;
on.emit(oldNode, "dojotouchout", {
relatedTarget: hoveredNode,
bubbles: true
});
on.emit(hoveredNode, "dojotouchover", {
relatedTarget: oldNode,
bubbles: true
});
doClicks(evt, "touchmove", "touchend"); // init click generation
}, true);
function copyEventProps(evt){
// Make copy of event object and also set bubbles:true. Used when calling on.emit().
var props = lang.delegate(evt, {
bubbles: true
});
if(has("ios") >= 6){
// On iOS6 "touches" became a non-enumerable property, which
// is not hit by for...in. Ditto for the other properties below.
props.touches = evt.touches;
props.altKey = evt.altKey;
props.changedTouches = evt.changedTouches;
props.ctrlKey = evt.ctrlKey;
props.metaKey = evt.metaKey;
props.shiftKey = evt.shiftKey;
props.targetTouches = evt.targetTouches;
}
return props;
}
on(win.doc, "touchmove", function(evt){
lastTouch = (new Date()).getTime();
var newNode = win.doc.elementFromPoint(
evt.pageX - (ios4 ? 0 : win.global.pageXOffset), // iOS 4 expects page coords
evt.pageY - (ios4 ? 0 : win.global.pageYOffset)
);
if(newNode){
// Fire synthetic touchover and touchout events on nodes since the browser won't do it natively.
if(hoveredNode !== newNode){
// touch out on the old node
on.emit(hoveredNode, "dojotouchout", {
relatedTarget: newNode,
bubbles: true
});
// touchover on the new node
on.emit(newNode, "dojotouchover", {
relatedTarget: hoveredNode,
bubbles: true
});
hoveredNode = newNode;
}
// Unlike a listener on "touchmove", on(node, "dojotouchmove", listener) fires when the finger
// drags over the specified node, regardless of which node the touch started on.
if(!on.emit(newNode, "dojotouchmove", copyEventProps(evt))){
// emit returns false when synthetic event "dojotouchmove" is cancelled, so we prevent the
// default behavior of the underlying native event "touchmove".
evt.preventDefault();
}
}
});
// Fire a dojotouchend event on the node where the finger was before it was removed from the screen.
// This is different than the native touchend, which fires on the node where the drag started.
on(win.doc, "touchend", function(evt){
lastTouch = (new Date()).getTime();
var node = win.doc.elementFromPoint(
evt.pageX - (ios4 ? 0 : win.global.pageXOffset), // iOS 4 expects page coords
evt.pageY - (ios4 ? 0 : win.global.pageYOffset)
) || win.body(); // if out of the screen
on.emit(node, "dojotouchend", copyEventProps(evt));
});
});
}
}
//device neutral events - touch.press|move|release|cancel/over/out
var touch = {
press: dualEvent("mousedown", "touchstart", pointer.down),
move: dualEvent("mousemove", "dojotouchmove", pointer.move),
release: dualEvent("mouseup", "dojotouchend", pointer.up),
cancel: dualEvent(mouse.leave, "touchcancel", hasPointer ? pointer.cancel : null),
over: dualEvent("mouseover", "dojotouchover", pointer.over),
out: dualEvent("mouseout", "dojotouchout", pointer.out),
enter: mouse._eventHandler(dualEvent("mouseover","dojotouchover", pointer.over)),
leave: mouse._eventHandler(dualEvent("mouseout", "dojotouchout", pointer.out))
};
/*=====
touch = {
// summary:
// This module provides unified touch event handlers by exporting
// press, move, release and cancel which can also run well on desktop.
// Based on http://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html
// Also, if the dojoClick property is set to truthy on a DOM node, dojo/touch generates
// click events immediately for this node and its descendants (except for descendants that
// have a dojoClick property set to falsy), to avoid the delay before native browser click events,
// and regardless of whether evt.preventDefault() was called in a touch.press event listener.
//
// example:
// Used with dojo/on
// | define(["dojo/on", "dojo/touch"], function(on, touch){
// | on(node, touch.press, function(e){});
// | on(node, touch.move, function(e){});
// | on(node, touch.release, function(e){});
// | on(node, touch.cancel, function(e){});
// example:
// Used with touch.* directly
// | touch.press(node, function(e){});
// | touch.move(node, function(e){});
// | touch.release(node, function(e){});
// | touch.cancel(node, function(e){});
// example:
// Have dojo/touch generate clicks without delay, with a default move threshold of 4 pixels
// | node.dojoClick = true;
// example:
// Have dojo/touch generate clicks without delay, with a move threshold of 10 pixels horizontally and vertically
// | node.dojoClick = 10;
// example:
// Have dojo/touch generate clicks without delay, with a move threshold of 50 pixels horizontally and 10 pixels vertically
// | node.dojoClick = {x:50, y:5};
// example:
// Disable clicks without delay generated by dojo/touch on a node that has an ancestor with property dojoClick set to truthy
// | node.dojoClick = false;
press: function(node, listener){
// summary:
// Register a listener to 'touchstart'|'mousedown' for the given node
// node: Dom
// Target node to listen to
// listener: Function
// Callback function
// returns:
// A handle which will be used to remove the listener by handle.remove()
},
move: function(node, listener){
// summary:
// Register a listener that fires when the mouse cursor or a finger is dragged over the given node.
// node: Dom
// Target node to listen to
// listener: Function
// Callback function
// returns:
// A handle which will be used to remove the listener by handle.remove()
},
release: function(node, listener){
// summary:
// Register a listener to releasing the mouse button while the cursor is over the given node
// (i.e. "mouseup") or for removing the finger from the screen while touching the given node.
// node: Dom
// Target node to listen to
// listener: Function
// Callback function
// returns:
// A handle which will be used to remove the listener by handle.remove()
},
cancel: function(node, listener){
// summary:
// Register a listener to 'touchcancel'|'mouseleave' for the given node
// node: Dom
// Target node to listen to
// listener: Function
// Callback function
// returns:
// A handle which will be used to remove the listener by handle.remove()
},
over: function(node, listener){
// summary:
// Register a listener to 'mouseover' or touch equivalent for the given node
// node: Dom
// Target node to listen to
// listener: Function
// Callback function
// returns:
// A handle which will be used to remove the listener by handle.remove()
},
out: function(node, listener){
// summary:
// Register a listener to 'mouseout' or touch equivalent for the given node
// node: Dom
// Target node to listen to
// listener: Function
// Callback function
// returns:
// A handle which will be used to remove the listener by handle.remove()
},
enter: function(node, listener){
// summary:
// Register a listener to mouse.enter or touch equivalent for the given node
// node: Dom
// Target node to listen to
// listener: Function
// Callback function
// returns:
// A handle which will be used to remove the listener by handle.remove()
},
leave: function(node, listener){
// summary:
// Register a listener to mouse.leave or touch equivalent for the given node
// node: Dom
// Target node to listen to
// listener: Function
// Callback function
// returns:
// A handle which will be used to remove the listener by handle.remove()
}
};
=====*/
1 && (dojo.touch = touch);
return touch;
});
},
'dijit/registry':function(){
define([
"dojo/_base/array", // array.forEach array.map
"dojo/_base/window", // win.body
"./main" // dijit._scopeName
], function(array, win, dijit){
// module:
// dijit/registry
var _widgetTypeCtr = {}, hash = {};
var registry = {
// summary:
// Registry of existing widget on page, plus some utility methods.
// length: Number
// Number of registered widgets
length: 0,
add: function(widget){
// summary:
// Add a widget to the registry. If a duplicate ID is detected, a error is thrown.
// widget: dijit/_WidgetBase
// Any dijit/_WidgetBase 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/_WidgetBase
},
byNode: function(/*DOMNode*/ node){
// summary:
// Returns the widget corresponding to the given DOMNode
return hash[node.getAttribute("widgetId")]; // dijit/_WidgetBase
},
toArray: function(){
// summary:
// Convert registry into a true Array
//
// example:
// Work with the widget .domNodes in a real Array
// | array.map(registry.toArray(), function(w){ return w.domNode; });
var ar = [];
for(var id in hash){
ar.push(hash[id]);
}
return ar; // dijit/_WidgetBase[]
},
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(root, skipNode){
// summary:
// Search subtree under root returning widgets found.
// Doesn't search for nested widgets (ie, widgets inside other widgets).
// root: DOMNode
// Node to search under.
// skipNode: DOMNode
// If specified, don't search beneath this node (usually containerNode).
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 if(node !== skipNode){
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
// 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.nodeType == 1 && 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
};
dijit.registry = registry;
return registry;
});
},
'dijit/main':function(){
define([
"dojo/_base/kernel"
], function(dojo){
// module:
// dijit/main
/*=====
return {
// summary:
// The dijit package main module.
// Deprecated. Users should access individual modules (ex: dijit/registry) directly.
};
=====*/
return dojo.dijit;
});
},
'dojox/mobile/sniff':function(){
define([
"dojo/_base/kernel",
"dojo/sniff"
], function(kernel, has){
kernel.deprecated("dojox/mobile/sniff", "Use dojo/sniff instead", "2.0");
// TODO: remove this in 2.0
has.add("iphone", has("ios"));
/*=====
return {
// summary:
// Deprecated: use dojo/sniff instead.
// On iOS, dojox/mobile/sniff sets "iphone" to the same value as "ios"
// for compatibility with earlier versions, but this should be considered deprecated.
// In future versions, "iphone" will be set only when running on an iPhone (not iPad on iPod).
};
=====*/
return has;
});
},
'dojox/mobile/uacss':function(){
define([
"dojo/_base/kernel",
"dojo/_base/lang",
"dojo/_base/window",
"./sniff"
], function(dojo, lang, win, has){
var html = win.doc.documentElement;
html.className = lang.trim(html.className + " " + [
has('bb') ? "dj_bb" : "",
has('android') ? "dj_android" : "",
has("ios") ? "dj_ios" : "",
has("ios") >= 6 ? "dj_ios6" : "",
has("ios") ? "dj_iphone" : "", // TODO: remove for 2.0
has('ipod') ? "dj_ipod" : "",
has('ipad') ? "dj_ipad" : "",
has('ie') ? "dj_ie": ""
].join(" ").replace(/ +/g," "));
/*=====
return {
// summary:
// Requiring this module adds CSS classes to your document's ` tag:
//
// - "dj_android" when running on Android;
// - "dj_bb" when running on BlackBerry;
// - "dj_ios" when running on iOS (iPhone, iPad or iPod);
// - "dj_ios6" when running on iOS6+; this class is intended for the iphone theme to detect if it must use the iOS 6 variant of the theme. Currently applies on iOS 6 or later.
// - "dj_iphone" when running on iPhone, iPad or iPod (Note: will be changed in future versions to be set only on iPhone);
// - "dj_ipod" when running on iPod;
// - "dj_ipad" when running on iPad.
};
=====*/
return dojo;
});
},
'dojox/mobile/View':function(){
define([
"dojo/_base/array",
"dojo/_base/config",
"dojo/_base/connect",
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/sniff",
"dojo/_base/window",
"dojo/_base/Deferred",
"dojo/dom",
"dojo/dom-class",
"dojo/dom-construct",
"dojo/dom-geometry",
"dojo/dom-style",
"dijit/registry",
"dijit/_Contained",
"dijit/_Container",
"dijit/_WidgetBase",
"./ViewController", // to load ViewController for you (no direct references)
"./common",
"./transition",
"./viewRegistry",
"./_css3"
], function(array, config, connect, declare, lang, has, win, Deferred, dom, domClass, domConstruct, domGeometry, domStyle, registry, Contained, Container, WidgetBase, ViewController, common, transitDeferred, viewRegistry, css3){
// module:
// dojox/mobile/View
var dm = lang.getObject("dojox.mobile", true);
return declare("dojox.mobile.View", [WidgetBase, Container, Contained], {
// summary:
// A container widget for any HTML element and/or Dojo widgets
// description:
// View is a container widget for any HTML element and/or Dojo widgets.
// As a Dojo widget container it can itself contain View widgets
// forming a set of nested views. A Dojo Mobile application is usually
// made of multiple View widgets and the user can navigate through
// the views back and forth with animated transition effects.
//
// When using several sibling views (direct children of the same
// element), you can use the 'selected' attribute to define whether
// the view should be displayed when the application is launched.
// If no view has selected=true, the first sibling view is displayed
// at startup time.
// selected: Boolean
// If true, the view is displayed at startup time.
selected: false,
// keepScrollPos: Boolean
// If true, the scroll position is kept when transition occurs between views.
keepScrollPos: true,
// tag: String
// The name of the HTML tag to create as domNode. The default value is "div".
tag: "div",
/* internal properties */
baseClass: "mblView",
constructor: function(/*Object*/params, /*DomNode?*/node){
// summary:
// Creates a new instance of the class.
// params:
// Contains the parameters.
// node:
// The DOM node. If none is specified, it is automatically created.
if(node){
dom.byId(node).style.visibility = "hidden";
}
},
destroy: function(){
viewRegistry.remove(this.id);
this.inherited(arguments);
},
buildRendering: function(){
if(!this.templateString){
// Create root node if it wasn't created by _TemplatedMixin
this.domNode = this.containerNode = this.srcNodeRef || domConstruct.create(this.tag);
}
this._animEndHandle = this.connect(this.domNode, css3.name("animationEnd"), "onAnimationEnd");
this._animStartHandle = this.connect(this.domNode, css3.name("animationStart"), "onAnimationStart");
if(!config.mblCSS3Transition){
this._transEndHandle = this.connect(this.domNode, css3.name("transitionEnd"), "onAnimationEnd");
}
if(has('mblAndroid3Workaround')){
// workaround for the screen flicker issue on Android 3.x/4.0
// applying "-webkit-transform-style:preserve-3d" to domNode can avoid
// transition animation flicker
domStyle.set(this.domNode, css3.name("transformStyle"), "preserve-3d");
}
viewRegistry.add(this);
this.inherited(arguments);
},
startup: function(){
if(this._started){ return; }
// Determine which view among the siblings should be visible.
// Priority:
// 1. fragment id in the url (ex. #view1,view2)
// 2. this.selected
// 3. the first view
if(this._visible === undefined){
var views = this.getSiblingViews();
var ids = location.hash && location.hash.substring(1).split(/,/);
var fragView, selectedView, firstView;
array.forEach(views, function(v, i){
if(array.indexOf(ids, v.id) !== -1){ fragView = v; }
if(i == 0){ firstView = v; }
if(v.selected){ selectedView = v; }
v._visible = false;
}, this);
(fragView || selectedView || firstView)._visible = true;
}
if(this._visible){
// The 2nd arg is not to hide its sibling views so that they can be
// correctly initialized.
this.show(true, true);
// Defer firing events to let user connect to events just after creation
// TODO: revisit this for 2.0
this.defer(function(){
this.onStartView();
connect.publish("/dojox/mobile/startView", [this]);
});
}
if(this.domNode.style.visibility === "hidden"){ // this check is to avoid screen flickers
this.domNode.style.visibility = "inherit";
}
// Need to call inherited first - so that child widgets get started
// up correctly
this.inherited(arguments);
var parent = this.getParent();
if(!parent || !parent.resize){ // top level widget
this.resize();
}
if(!this._visible){
// hide() should be called last so that child widgets can be
// initialized while they are visible.
this.hide();
}
},
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.
},
_clearClasses: function(/*DomNode*/node){
// summary:
// Clean up the domNode classes that were added while making a transition.
// description:
// Remove all the "mbl" prefixed classes except mbl*View.
if(!node){ return; }
var classes = [];
array.forEach(lang.trim(node.className||"").split(/\s+/), function(c){
if(c.match(/^mbl\w*View$/) || c.indexOf("mbl") === -1){
classes.push(c);
}
}, this);
node.className = classes.join(' ');
},
_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")){
this._clearClasses(n);
}
}
this._clearClasses(toNode); // just in case toNode is a sibling of an ancestor.
// #16337
// Uninitialization may fail to clear _inProgress when multiple
// performTransition calls occur in a short duration of time.
var toWidget = registry.byNode(toNode);
if(toWidget){
toWidget._inProgress = false;
}
},
convertToId: function(moveTo){
if(typeof(moveTo) == "string"){
// removes a leading hash mark (#) and params if exists
// ex. "#bar&myParam=0003" -> "bar"
return moveTo.replace(/^#?([^&?]+).*/, "$1");
}
return moveTo;
},
_isBookmarkable: function(detail){
return detail.moveTo && (config.mblForceBookmarkable || detail.moveTo.charAt(0) === '#') && !detail.hashchange;
},
performTransition: function(/*String*/moveTo, /*Number*/transitionDir, /*String*/transition,
/*Object|null*/context, /*String|Function*/method /*...*/){
// 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.
// 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 transitionDir == 1,
// and from left to right when transitionDir == -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", "cube", and
// "swap". 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 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(this._inProgress){ return; } // transition is in progress
this._inProgress = true;
// normalize the arg
var detail, optArgs;
if(moveTo && typeof(moveTo) === "object"){
detail = moveTo;
optArgs = transitionDir; // array
}else{
detail = {
moveTo: moveTo,
transitionDir: transitionDir,
transition: transition,
context: context,
method: method
};
optArgs = [];
for(var i = 5; i < arguments.length; i++){
optArgs.push(arguments[i]);
}
}
// save the parameters
this._detail = detail;
this._optArgs = optArgs;
this._arguments = [
detail.moveTo,
detail.transitionDir,
detail.transition,
detail.context,
detail.method
];
if(detail.moveTo === "#"){ return; }
var toNode;
if(detail.moveTo){
toNode = this.convertToId(detail.moveTo);
}else{
if(!this._dummyNode){
this._dummyNode = win.doc.createElement("div");
win.body().appendChild(this._dummyNode);
}
toNode = this._dummyNode;
}
if(this.addTransitionInfo && typeof(detail.moveTo) == "string" && this._isBookmarkable(detail)){
this.addTransitionInfo(this.id, detail.moveTo, {transitionDir:detail.transitionDir, transition:detail.transition});
}
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: "+detail.moveTo); return; }
toNode.style.visibility = "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){
common.resizeAll(null, toWidget);
toWidget._resized = true;
}
if(detail.transition && detail.transition != "none"){
// Temporarily add padding to align with the fromNode while transition
toWidget._addTransitionPaddingTop(fromTop);
}
toWidget.load && toWidget.load(); // for ContentView
toWidget.movedFrom = fromNode.id;
}
if(has('mblAndroidWorkaround') && !config.mblCSS3Transition
&& detail.transition && detail.transition != "none"){
// workaround for the screen flicker issue on Android 2.2/2.3
// apply "-webkit-transform-style:preserve-3d" to both toNode and fromNode
// to make them 3d-transition-ready state just before transition animation
domStyle.set(toNode, css3.name("transformStyle"), "preserve-3d");
domStyle.set(fromNode, css3.name("transformStyle"), "preserve-3d");
// show toNode offscreen to avoid flicker when switching "display" and "visibility" styles
domClass.add(toNode, "mblAndroidWorkaround");
}
this.onBeforeTransitionOut.apply(this, this._arguments);
connect.publish("/dojox/mobile/beforeTransitionOut", [this].concat(lang._toArray(this._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 = (detail.transitionDir == 1) ? 0 : (toNode._scrollTop || 0);
toNode.style.top = "0px";
if(scrollTop > 1 || toTop !== 0){
fromNode.style.top = toTop - scrollTop + "px";
// address bar hiding does not work on iOS 7+.
if(!(has("ios") >= 7) && config.mblHideAddressBar !== false){
this.defer(function(){ // iPhone needs setTimeout (via defer)
win.global.scrollTo(0, (toTop || 1));
});
}
}
}else{
toNode.style.top = "0px";
}
toWidget.onBeforeTransitionIn.apply(toWidget, this._arguments);
connect.publish("/dojox/mobile/beforeTransitionIn", [toWidget].concat(lang._toArray(this._arguments)));
}
toNode.style.display = "none";
toNode.style.visibility = "inherit";
common.fromView = this;
common.toView = toWidget;
this._doTransition(fromNode, toNode, detail.transition, detail.transitionDir);
},
_addTransitionPaddingTop: function(/*String|Integer*/ value){
// add padding top to the view in order to get alignment during the transition
this.containerNode.style.paddingTop = value + "px";
},
_removeTransitionPaddingTop: function(){
// remove padding top from the view after the transition
this.containerNode.style.paddingTop = "";
},
_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, transitionDir){
var rev = (transitionDir == -1) ? " mblReverse" : "";
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: (transitionDir===-1)?true:false}),lang.hitch(this,function(){
domStyle.set(toNode, "position", toPosition);
// Reset the temporary padding on toNode
toNode.style.paddingTop = "";
this.invokeCallback();
}));
}));
}else{
if(transition.indexOf("cube") != -1){
if(has('ipad')){
domStyle.set(toNode.parentNode, {webkitPerspective:1600});
}else if(has("ios")){
domStyle.set(toNode.parentNode, {webkitPerspective:800});
}
}
var s = this._toCls(transition);
if(has('mblAndroidWorkaround')){
// workaround for the screen flicker issue on Android 2.2
// applying transition css classes just after setting toNode.style.display = ""
// causes flicker, so wait for a while using setTimeout (via defer)
var _this = this;
_this.defer(function(){
domClass.add(fromNode, s + " mblOut" + rev);
domClass.add(toNode, s + " mblIn" + rev);
domClass.remove(toNode, "mblAndroidWorkaround"); // remove offscreen style
_this.defer(function(){
domClass.add(fromNode, "mblTransition");
domClass.add(toNode, "mblTransition");
}, 30); // 30 = 100 - 70, to make total delay equal to 100ms
}, 70); // 70ms is experiential value
}else{
domClass.add(fromNode, s + " mblOut" + rev);
domClass.add(toNode, s + " mblIn" + rev);
this.defer(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, css3.add({}, {transformOrigin:fromOrigin}));
domStyle.set(toNode, css3.add({}, {transformOrigin:toOrigin}));
}
},
onAnimationStart: function(e){
// summary:
// A handler that is called when transition animation starts.
},
onAnimationEnd: function(e){
// summary:
// A handler that is called after transition animation ends.
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._detail.transition), "mblIn", "mblOut", "mblReverse"]);
}else{
// Reset the temporary padding
this._removeTransitionPaddingTop();
}
domStyle.set(this.domNode, css3.add({}, {transformOrigin:""}));
if(name.indexOf("Shrink") !== -1){
var li = e.target;
li.style.display = "none";
domClass.remove(li, "mblCloseContent");
// If target is placed inside scrollable, need to call onTouchEnd
// to adjust scroll position
var p = viewRegistry.getEnclosingScrollable(this.domNode);
p && p.onTouchEnd();
}
if(isOut){
this.invokeCallback();
}
this._clearClasses(this.domNode);
// clear the clicked position
this.clickedPosX = this.clickedPosY = undefined;
if(name.indexOf("Cube") !== -1 &&
name.indexOf("In") !== -1 && has("ios")){
this.domNode.parentNode.style[css3.name("perspective")] = "";
}
},
invokeCallback: function(){
// summary:
// A function to be called after performing a transition to
// call a specified callback.
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;
if(this.setFragIds && this._isBookmarkable(this._detail)){
this.setFragIds(toWidget); // setFragIds is defined in bookmarkable.js
}
}
if(has('mblAndroidWorkaround')){
// workaround for the screen flicker issue on Android 2.2/2.3
// remove "-webkit-transform-style" style after transition finished
// to avoid side effects such as input field auto-scrolling issue
// use setTimeout (via defer) to avoid flicker in case of ScrollableView
this.defer(function(){
if(toWidget){ domStyle.set(this.toNode, css3.name("transformStyle"), ""); }
domStyle.set(this.domNode, css3.name("transformStyle"), "");
});
}
var c = this._detail.context, m = this._detail.method;
if(c || m){
if(!m){
m = c;
c = null;
}
c = c || win.global;
if(typeof(m) == "string"){
c[m].apply(c, this._optArgs);
}else if(typeof(m) == "function"){
m.apply(c, this._optArgs);
}
}
this._detail = this._optArgs = this._arguments = undefined;
this._inProgress = false;
},
isVisible: function(/*Boolean?*/checkAncestors){
// summary:
// Return true if this view is visible
// checkAncestors:
// If true, in addition to its own visibility, also checks the
// ancestors visibility to see if the view is actually being
// shown or not.
var visible = function(node){
return domStyle.get(node, "display") !== "none";
};
if(checkAncestors){
for(var n = this.domNode; n.tagName !== "BODY"; n = n.parentNode){
if(!visible(n)){ return false; }
}
return true;
}else{
return visible(this.domNode);
}
},
getShowingView: function(){
// summary:
// Find the currently showing view from my sibling views.
// description:
// Note that depending on the ancestor views' visibility,
// the found view may not be actually shown.
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.style.display !== "none"){
return registry.byNode(n);
}
}
return null;
},
getSiblingViews: function(){
// summary:
// Returns an array of the sibling views.
if(!this.domNode.parentNode){ return [this]; }
return array.map(array.filter(this.domNode.parentNode.childNodes,
function(n){ return n.nodeType === 1 && domClass.contains(n, "mblView"); }),
function(n){ return registry.byNode(n); });
},
show: function(/*Boolean?*/noEvent, /*Boolean?*/doNotHideOthers){
// summary:
// Shows this view without a transition animation.
var out = this.getShowingView();
if(!noEvent){
if(out){
out.onBeforeTransitionOut(out.id);
connect.publish("/dojox/mobile/beforeTransitionOut", [out, out.id]);
}
this.onBeforeTransitionIn(this.id);
connect.publish("/dojox/mobile/beforeTransitionIn", [this, this.id]);
}
if(doNotHideOthers){
this.domNode.style.display = "";
}else{
array.forEach(this.getSiblingViews(), function(v){
v.domNode.style.display = (v === this) ? "" : "none";
}, this);
}
this.load && this.load(); // for ContentView
if(!noEvent){
if(out){
out.onAfterTransitionOut(out.id);
connect.publish("/dojox/mobile/afterTransitionOut", [out, out.id]);
}
this.onAfterTransitionIn(this.id);
connect.publish("/dojox/mobile/afterTransitionIn", [this, this.id]);
}
},
hide: function(){
// summary:
// Hides this view without a transition animation.
this.domNode.style.display = "none";
}
});
});
},
'dijit/_Contained':function(){
define([
"dojo/_base/declare", // declare
"./registry" // registry.getEnclosingWidget(), registry.byNode()
], function(declare, registry){
// module:
// dijit/_Contained
return declare("dijit._Contained", null, {
// summary:
// Mixin for widgets that are children of a container widget
// example:
// | // make a basic custom widget that knows about its parents
// | declare("my.customClass",[dijit._WidgetBase, dijit._Contained],{});
_getSibling: function(/*String*/ which){
// summary:
// Returns next or previous sibling
// which:
// Either "next" or "previous"
// tags:
// private
var p = this.getParent();
return (p && p._getSiblingOfChild && p._getSiblingOfChild(this, which == "previous" ? -1 : 1)) || null; // dijit/_WidgetBase
},
getPreviousSibling: function(){
// summary:
// Returns null if this is the first child of the parent,
// otherwise returns the next element sibling to the "left".
return this._getSibling("previous"); // dijit/_WidgetBase
},
getNextSibling: function(){
// summary:
// Returns null if this is the last child of the parent,
// otherwise returns the next element sibling to the "right".
return this._getSibling("next"); // dijit/_WidgetBase
},
getIndexInParent: function(){
// summary:
// Returns the index of this widget within its container parent.
// It returns -1 if the parent does not exist, or if the parent
// is not a dijit/_Container
var p = this.getParent();
if(!p || !p.getIndexOfChild){
return -1; // int
}
return p.getIndexOfChild(this); // int
}
});
});
},
'dijit/_Container':function(){
define([
"dojo/_base/array", // array.forEach array.indexOf
"dojo/_base/declare", // declare
"dojo/dom-construct", // domConstruct.place
"dojo/_base/kernel" // kernel.deprecated
], function(array, declare, domConstruct, kernel){
// module:
// dijit/_Container
return declare("dijit._Container", null, {
// summary:
// Mixin for widgets that contain HTML and/or a set of widget children.
buildRendering: function(){
this.inherited(arguments);
if(!this.containerNode){
// All widgets with descendants must set containerNode.
// NB: this code doesn't quite work right because for TabContainer it runs before
// _TemplatedMixin::buildRendering(), and thus
// sets this.containerNode to this.domNode, later to be overridden by the assignment in the template.
this.containerNode = this.domNode;
}
},
addChild: function(/*dijit/_WidgetBase*/ widget, /*int?*/ insertIndex){
// summary:
// Makes the given widget a child of this widget.
// description:
// Inserts specified child widget's dom node as a child of this widget's
// container node, and possibly does other processing (such as layout).
// I want to just call domConstruct.place(widget.domNode, this.containerNode, insertIndex), but the counting
// is thrown off by text nodes and comment nodes that show up when constructed by markup.
// In the future consider stripping those nodes on construction, either in the parser or this widget code.
var refNode = this.containerNode;
if(insertIndex > 0){
// Old-school way to get nth child; dojo.query would be easier but _Container was weened from dojo.query
// in #10087 to minimize download size. Not sure if that's still and issue with new smaller dojo/query.
refNode = refNode.firstChild;
while(insertIndex > 0){
if(refNode.nodeType == 1){ insertIndex--; }
refNode = refNode.nextSibling;
}
if(refNode){
insertIndex = "before";
}else{
// to support addChild(child, n-1) where there are n children (should add child at end)
refNode = this.containerNode;
insertIndex = "last";
}
}
domConstruct.place(widget.domNode, refNode, insertIndex);
// If I've been started but the child widget hasn't been started,
// start it now. Make sure to do this after widget has been
// inserted into the DOM tree, so it can see that it's being controlled by me,
// so it doesn't try to size itself.
if(this._started && !widget._started){
widget.startup();
}
},
removeChild: function(/*Widget|int*/ widget){
// summary:
// Removes the passed widget instance from this widget but does
// not destroy it. You can also pass in an integer indicating
// the index within the container to remove (ie, removeChild(5) removes the sixth widget).
if(typeof widget == "number"){
widget = this.getChildren()[widget];
}
if(widget){
var node = widget.domNode;
if(node && node.parentNode){
node.parentNode.removeChild(node); // detach but don't destroy
}
}
},
hasChildren: function(){
// summary:
// Returns true if widget has child widgets, i.e. if this.containerNode contains widgets.
return this.getChildren().length > 0; // Boolean
},
_getSiblingOfChild: function(/*dijit/_WidgetBase*/ child, /*int*/ dir){
// summary:
// Get the next or previous widget sibling of child
// dir:
// if 1, get the next sibling
// if -1, get the previous sibling
// tags:
// private
var children = this.getChildren(),
idx = array.indexOf(children, child); // int
return children[idx + dir];
},
getIndexOfChild: function(/*dijit/_WidgetBase*/ child){
// summary:
// Gets the index of the child in this container or -1 if not found
return array.indexOf(this.getChildren(), child); // int
}
});
});
},
'dijit/_WidgetBase':function(){
define([
"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.destroy domConstruct.place
"dojo/dom-geometry", // isBodyLtr
"dojo/dom-style", // domStyle.set, domStyle.get
"dojo/has",
"dojo/_base/kernel",
"dojo/_base/lang", // mixin(), isArray(), etc.
"dojo/on",
"dojo/ready",
"dojo/Stateful", // Stateful
"dojo/topic",
"dojo/_base/window", // win.body()
"./Destroyable",
"dojo/has!dojo-bidi?./_BidiMixin",
"./registry" // registry.getUniqueId(), registry.findWidgets()
], function(require, array, aspect, config, connect, declare,
dom, domAttr, domClass, domConstruct, domGeometry, domStyle, has, kernel,
lang, on, ready, Stateful, topic, win, Destroyable, _BidiMixin, registry){
// module:
// dijit/_WidgetBase
// Flag to make dijit load modules the app didn't explicitly request, for backwards compatibility
has.add("dijit-legacy-requires", !kernel.isAsync);
// Flag to enable support for textdir attribute
has.add("dojo-bidi", false);
// For back-compat, remove in 2.0.
if(has("dijit-legacy-requires")){
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);
};
}
function isEqual(a, b){
// summary:
// Function that determines whether two values are identical,
// taking into account that NaN is not normally equal to itself
// in JS.
return a === b || (/* a is NaN */ a !== a && /* b is NaN */ b !== b);
}
var _WidgetBase = declare("dijit._WidgetBase", [Stateful, Destroyable], {
// 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
//
// - Toggle DOM node CSS class
// | _setMyClassAttr: { node: "domNode", type: "toggleClass" }
// Toggles myClass on this.domNode by this.myClass
//
// 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
// class: String
// HTML class attribute
"class": "",
_setClassAttr: { node: "domNode", type: "class" },
// Override automatic assigning type --> focusNode, it causes exception on IE6-8.
// Instead, type must be specified as ${type} in the template, as part of the original DOM.
_setTypeAttr: null,
// 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. In this case it's
// interpreted as HTML.
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:
//
// |
// | here's a plain DOM node
// | and a widget
// | and another plain DOM node
// |
//
// containerNode would point to:
//
// | here's a plain DOM node
// | and a widget
// | and another plain DOM node
//
// 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,
// ownerDocument: [const] Document?
// The document this widget belongs to. If not specified to constructor, will default to
// srcNodeRef.ownerDocument, or if no sourceRef specified, then to the document global
ownerDocument: null,
_setOwnerDocumentAttr: function(val){
// this setter is merely to avoid automatically trying to set this.domNode.ownerDocument
this._set("ownerDocument", val);
},
/*=====
// _started: [readonly] 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 `` nodes in templates that really get their image via CSS background-image.
_blankGif: config.blankGif || require.toUrl("dojo/resources/blank.gif"),
// 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.
//
// This property is only effective when `has("dojo-bidi")` is defined to be true.
//
// Allowed values:
//
// 1. "" - default value; text is same direction as widget
// 2. "ltr"
// 3. "rtl"
// 4. "auto" - contextual the direction of a text defined by first strong letter.
textDir: "",
//////////// INITIALIZATION METHODS ///////////////////////////////////////
/*=====
constructor: function(params, srcNodeRef){
// summary:
// Create the widget.
// params: Object|null
// Hash of initialization parameters for widget, including scalar values (like title, duration etc.)
// and functions, typically callbacks like onClick.
// The hash can contain any of the widget's properties, excluding read-only properties.
// srcNodeRef: DOMNode|String?
// 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
},
=====*/
_introspect: function(){
// summary:
// Collect metadata about this widget (only once per class, not once per instance):
//
// - list of attributes with custom setters, storing in this.constructor._setterAttrs
// - generate this.constructor._onMap, mapping names like "mousedown" to functions like onMouseDown
var ctor = this.constructor;
if(!ctor._setterAttrs){
var proto = ctor.prototype,
attrs = ctor._setterAttrs = [], // attributes with custom setters
onMap = (ctor._onMap = {});
// Items in this.attributeMap are like custom setters. For back-compat, remove for 2.0.
for(var name in proto.attributeMap){
attrs.push(name);
}
// Loop over widget properties, collecting properties with custom setters and filling in ctor._onMap.
for(name in proto){
if(/^on/.test(name)){
onMap[name.substring(2).toLowerCase()] = name;
}
if(/^_set[A-Z](.*)Attr$/.test(name)){
name = name.charAt(4).toLowerCase() + name.substr(5, name.length - 9);
if(!proto.attributeMap || !(name in proto.attributeMap)){
attrs.push(name);
}
}
}
// Note: this isn't picking up info on properties like aria-label and role, that don't have custom setters
// but that set() maps to attributes on this.domNode or this.focusNode
}
},
postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){
// summary:
// Kicks off widget instantiation. See create() for details.
// tags:
// private
// Note that we skip calling this.inherited(), i.e. dojo/Stateful::postscript(), because 1.x widgets don't
// expect their custom setters to get called until after buildRendering(). Consider changing for 2.0.
this.create(params, srcNodeRef);
},
create: function(params, srcNodeRef){
// summary:
// Kick off the life-cycle of a widget
// 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.
// params: Object|null
// Hash of initialization parameters for widget, including scalar values (like title, duration etc.)
// and functions, typically callbacks like onClick.
// The hash can contain any of the widget's properties, excluding read-only properties.
// srcNodeRef: DOMNode|String?
// 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
// tags:
// private
// First time widget is instantiated, scan prototype to figure out info about custom setters etc.
this._introspect();
// store pointer to original DOM tree
this.srcNodeRef = dom.byId(srcNodeRef);
// No longer used, remove for 2.0.
this._connects = [];
this._supportingWidgets = [];
// this is here for back-compat, remove in 2.0 (but check NodeList-instantiate.html test)
if(this.srcNodeRef && this.srcNodeRef.id && (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, or it was specified as id: undefined.
// Do this before buildRendering() because it might expect the id to be there.
if(!this.id){
this.id = registry.getUniqueId(this.declaredClass.replace(/\./g, "_"));
if(this.params){
// if params contains {id: undefined}, prevent _applyAttributes() from processing it
delete this.params.id;
}
}
// The document and node this widget is associated with
this.ownerDocument = this.ownerDocument || (this.srcNodeRef ? this.srcNodeRef.ownerDocument : document);
this.ownerDocumentBody = win.body(this.ownerDocument);
registry.add(this);
this.buildRendering();
var deleteSrcNodeRef;
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);
deleteSrcNodeRef = true;
}
// 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.
// I think for back-compatibility it isn't deleting srcNodeRef until after postCreate() has run.
if(deleteSrcNodeRef){
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
// Call this.set() for each property that was either specified as parameter to constructor,
// or is in the list found above. For correlated properties like value and displayedValue, the one
// specified as a parameter should take precedence.
// Particularly important for new DateTextBox({displayedValue: ...}) since DateTextBox's default value is
// NaN and thus is not ignored like a default value of "".
// Step 1: Save the current values of the widget properties that were specified as parameters to the constructor.
// Generally this.foo == this.params.foo, except if postMixInProperties() changed the value of this.foo.
var params = {};
for(var key in this.params || {}){
params[key] = this._get(key);
}
// Step 2: Call set() for each property with a non-falsy value that wasn't passed as a parameter to the constructor
array.forEach(this.constructor._setterAttrs, function(key){
if(!(key in params)){
var val = this._get(key);
if(val){
this.set(key, val);
}
}
}, this);
// Step 3: Call set() for each property that was specified as parameter to constructor.
// Use params hash created above to ignore side effects from step #2 above.
for(key in params){
this.set(key, params[key]);
}
},
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 _TemplatedMixin
this.domNode = this.srcNodeRef || this.ownerDocument.createElement("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().
//
// Note that startup() may be called while the widget is still hidden, for example if the widget is
// inside a hidden dijit/Dialog or an unselected tab of a dijit/layout/TabContainer.
// For widgets that need to do layout, it's best to put that layout code inside resize(), and then
// extend dijit/layout/_LayoutWidget so that resize() is called when the widget is visible.
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._TemplatedMixin widgets.
this._beingDestroyed = true;
this.destroyDescendants(preserveDom);
this.destroy(preserveDom);
},
destroy: function(/*Boolean*/ preserveDom){
// summary:
// Destroy this widget, but not its descendants. Descendants means widgets inside of
// this.containerNode. Will also destroy any resources (including widgets) registered via this.own().
//
// This method will also destroy internal widgets such as those created from a template,
// assuming those widgets exist inside of this.domNode but outside of this.containerNode.
//
// For 2.0 it's planned that this method will also destroy descendant widgets, so apps should not
// depend on the current ability to destroy a widget without destroying its descendants. Generally
// they should use destroyRecursive() for widgets with children.
// preserveDom: Boolean
// If true, this method will leave the original DOM structure alone.
// Note: This will not yet work with _TemplatedMixin widgets
this._beingDestroyed = true;
this.uninitialize();
function destroy(w){
if(w.destroyRecursive){
w.destroyRecursive(preserveDom);
}else if(w.destroy){
w.destroy(preserveDom);
}
}
// Back-compat, remove for 2.0
array.forEach(this._connects, lang.hitch(this, "disconnect"));
array.forEach(this._supportingWidgets, destroy);
// Destroy supporting widgets, but not child widgets under this.containerNode (for 2.0, destroy child widgets
// here too). if() statement is to guard against exception if destroy() called multiple times (see #15815).
if(this.domNode){
array.forEach(registry.findWidgets(this.domNode, this.containerNode), 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:
// Deprecated. Override destroy() instead 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.
// attr:
// Name of member variable (ex: "focusNode" maps to this.focusNode) pointing
// to DOMNode inside the widget, or alternately pointing to a subwidget
// 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);
if(mapNode.tagName){
// Normal case, mapping to a DOMNode. Note that modern browsers will have a mapNode.set()
// method, but for consistency we still call domAttr
domAttr.set(mapNode, attrName, value);
}else{
// mapping to a sub-widget
mapNode.set(attrName, value);
}
break;
case "innerText":
// Deprecated, use "textContent" instead.
mapNode.innerHTML = "";
mapNode.appendChild(this.ownerDocument.createTextNode(value));
break;
case "textContent":
mapNode.textContent = value;
break;
case "innerHTML":
mapNode.innerHTML = value;
break;
case "class":
domClass.replace(mapNode, value, this[attr]);
break;
case "toggleClass":
domClass.toggle(mapNode, command.className || attr, value);
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._get(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/subwidget 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] && this[defaultNode].tagName,
attrsForTag = tag && (tagAttrs[tag] || (tagAttrs[tag] = getAttrs(this[defaultNode]))),
map = name in this.attributeMap ? this.attributeMap[name] :
names.s in this ? this[names.s] :
((attrsForTag && 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 property, and call handlers
// registered with watch() if the value has changed.
var oldValue = this[name];
this[name] = value;
if(this._created && !isEqual(oldValue, value)){
if(this._watchCallbacks){
this._watchCallbacks(name, oldValue, value);
}
this.emit("attrmodified-" + name, {
detail: {
prevValue: oldValue,
newValue: value
}
});
}
},
_get: function(/*String*/ name){
// summary:
// Helper function to get value for specified property stored by this._set(),
// i.e. for properties with custom setters. Used mainly by custom getters.
//
// For example, CheckBox._getValueAttr() calls this._get("value").
// future: return name in this.props ? this.props[name] : this[name];
return this[name];
},
emit: function(/*String*/ type, /*Object?*/ eventObj, /*Array?*/ callbackArgs){
// summary:
// Used by widgets to signal that a synthetic event occurred, ex:
// | myWidget.emit("attrmodified-selectedChildWidget", {}).
//
// Emits an event on this.domNode named type.toLowerCase(), based on eventObj.
// Also calls onType() method, if present, and returns value from that method.
// By default passes eventObj to callback, but will pass callbackArgs instead, if specified.
// Modifies eventObj by adding missing parameters (bubbles, cancelable, widget).
// tags:
// protected
// Specify fallback values for bubbles, cancelable in case they are not set in eventObj.
// Also set pointer to widget, although since we can't add a pointer to the widget for native events
// (see #14729), maybe we shouldn't do it here?
eventObj = eventObj || {};
if(eventObj.bubbles === undefined){
eventObj.bubbles = true;
}
if(eventObj.cancelable === undefined){
eventObj.cancelable = true;
}
if(!eventObj.detail){
eventObj.detail = {};
}
eventObj.detail.widget = this;
var ret, callback = this["on" + type];
if(callback){
ret = callback.apply(this, callbackArgs ? callbackArgs : [eventObj]);
}
// Emit event, but avoid spurious emit()'s as parent sets properties on child during startup/destroy
if(this._started && !this._beingDestroyed){
on.emit(this.domNode, type.toLowerCase(), eventObj);
}
return ret;
},
on: function(/*String|Function*/ type, /*Function*/ func){
// summary:
// Call specified function when event occurs, ex: myWidget.on("click", function(){ ... }).
// type:
// Name of event (ex: "click") or extension event like touch.press.
// 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))`.
// For backwards compatibility, if there's an onType() method in the widget then connect to that.
// Remove in 2.0.
var widgetMethod = this._onMap(type);
if(widgetMethod){
return aspect.after(this, widgetMethod, func, true);
}
// Otherwise, just listen for the event on this.domNode.
return this.own(on(this.domNode, type, func))[0];
},
_onMap: function(/*String|Function*/ type){
// summary:
// Maps on() type parameter (ex: "mousemove") to method name (ex: "onMouseMove").
// If type is a synthetic event like touch.press then returns undefined.
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[typeof type == "string" && 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 direct children of this widget, i.e. all widgets underneath this.containerNode whose parent
// is this widget. Note that it does not return all descendants, but rather just direct children.
// Analogous to [Node.childNodes](https://developer.mozilla.org/en-US/docs/DOM/Node.childNodes),
// except containing widgets rather than DOMNodes.
//
// The result intentionally excludes internally created widgets (a.k.a. supporting widgets)
// outside of this.containerNode.
//
// Note that the array returned is a simple array. Application code should not assume
// existence of methods like forEach().
return this.containerNode ? registry.findWidgets(this.containerNode) : []; // dijit/_WidgetBase[]
},
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:
// Deprecated, will be removed in 2.0, use this.own(on(...)) or this.own(aspect.after(...)) instead.
//
// Connects specified obj/event to specified method of this object
// and registers for disconnect() on widget destroy.
//
// 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 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
return this.own(connect.connect(obj, event, this, method))[0]; // handle
},
disconnect: function(handle){
// summary:
// Deprecated, will be removed in 2.0, use handle.remove() instead.
//
// Disconnects handle created by `connect`.
// tags:
// protected
handle.remove();
},
subscribe: function(t, method){
// summary:
// Deprecated, will be removed in 2.0, use this.own(topic.subscribe()) instead.
//
// Subscribes to the specified topic and calls the specified method
// of this object and registers for unsubscribe() on widget destroy.
//
// 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 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
return this.own(topic.subscribe(t, lang.hitch(this, method)))[0]; // handle
},
unsubscribe: function(/*Object*/ handle){
// summary:
// Deprecated, will be removed in 2.0, use handle.remove() instead.
//
// Unsubscribes handle created by this.subscribe.
// Also removes handle from this widget's list of subscriptions
// tags:
// protected
handle.remove();
},
isLeftToRight: function(){
// summary:
// Return this widget's explicit or implicit orientation (true for LTR, false for RTL)
// tags:
// protected
return this.dir ? (this.dir.toLowerCase() == "ltr") : domGeometry.isBodyLtr(this.ownerDocument); //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|DocumentFragment|dijit/_WidgetBase*/ reference, /*String|Int?*/ position){
// summary:
// Place this widget somewhere in the DOM based
// on standard domConstruct.place() conventions.
// 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:
// Widget, DOMNode, DocumentFragment, or id of widget or DOMNode
// position:
// If reference is a widget (or id of widget), and that widget has an ".addChild" method,
// it will be called passing this widget instance into that method, supplying the optional
// position index passed. In this case position (if specified) should be an integer.
//
// If reference is a DOMNode (or id matching a DOMNode but not a widget),
// the position argument can be a numeric index or a string
// "first", "last", "before", or "after", same as dojo/dom-construct::place().
// returns: dijit/_WidgetBase
// 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 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 Button({},"src").placeAt("wrapper");
// example:
// | // place a new button as the first element of some div
// | var button = new Button({ label:"click" }).placeAt("wrapper","first");
// example:
// | // create a contentpane and add it to a TabContainer
// | var tc = dijit.byId("myTabs");
// | new ContentPane({ href:"foo.html", title:"Wow!" }).placeAt(tc)
var refWidget = !reference.tagName && registry.byId(reference);
if(refWidget && refWidget.addChild && (!position || typeof position === "number")){
// Adding this to refWidget and can use refWidget.addChild() to handle everything.
refWidget.addChild(this, position);
}else{
// "reference" is a plain DOMNode, or we can't use refWidget.addChild(). Use domConstruct.place() and
// target refWidget.containerNode for nested placement (position==number, "first", "last", "only"), and
// refWidget.domNode otherwise ("after"/"before"/"replace"). (But not supported officially, see #14946.)
var ref = refWidget && ("domNode" in refWidget) ?
(refWidget.containerNode && !/after|before|replace/.test(position || "") ?
refWidget.containerNode : refWidget.domNode) : dom.byId(reference, this.ownerDocument);
domConstruct.place(this.domNode, ref, position);
// Start this iff it has a parent widget that's already started.
// TODO: for 2.0 maybe it should also start the widget when this.getParent() returns null??
if(!this._started && (this.getParent() || {})._started){
this.startup();
}
}
return this;
},
defer: function(fcn, delay){
// summary:
// Wrapper to setTimeout to avoid deferred functions executing
// after the originating widget has been destroyed.
// Returns an object handle with a remove method (that returns null) (replaces clearTimeout).
// fcn: Function
// Function reference.
// delay: Number?
// Delay, defaults to 0.
// tags:
// protected
var timer = setTimeout(lang.hitch(this,
function(){
if(!timer){
return;
}
timer = null;
if(!this._destroyed){
lang.hitch(this, fcn)();
}
}),
delay || 0
);
return {
remove: function(){
if(timer){
clearTimeout(timer);
timer = null;
}
return null; // so this works well: handle = handle.remove();
}
};
}
});
if(has("dojo-bidi")){
_WidgetBase.extend(_BidiMixin);
}
return _WidgetBase;
});
},
'dojo/Stateful':function(){
define(["./_base/declare", "./_base/lang", "./_base/array", "./when"], function(declare, lang, array, when){
// module:
// dojo/Stateful
return 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
//
// The class also provides the functionality to auto-magically manage getters
// and setters for object attributes/properties.
//
// Getters and Setters should follow the format of _xxxGetter or _xxxSetter where
// the xxx is a name of the attribute to handle. So an attribute of "foo"
// would have a custom getter of _fooGetter and a custom setter of _fooSetter.
//
// example:
// | require(["dojo/Stateful", function(Stateful) {
// | var obj = new Stateful();
// | obj.watch("foo", function(){
// | console.log("foo changed to " + this.get("foo"));
// | });
// | obj.set("foo","bar");
// | });
// _attrPairNames: Hash
// Used across all instances a hash to cache attribute names and their getter
// and setter names.
_attrPairNames: {},
_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]; }
return (apn[name] = {
s: "_" + name + "Setter",
g: "_" + name + "Getter"
});
},
postscript: function(/*Object?*/ params){
// Automatic setting of params during construction
if (params){ this.set(params); }
},
_get: function(name, names){
// summary:
// Private function that does a get based off a hash of names
// names:
// Hash of names of custom attributes
return typeof this[names.g] === "function" ? this[names.g]() : this[name];
},
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.
// example:
// | require(["dojo/Stateful", function(Stateful) {
// | var stateful = new Stateful({foo: 3});
// | stateful.get("foo") // returns 3
// | stateful.foo // returns 3
// | });
return this._get(name, this._getAttrNames(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.
// example:
// | require(["dojo/Stateful", function(Stateful) {
// | var stateful = new 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:
// | stateful.set({
// | foo: "Howdy",
// | bar: 3
// | });
// | });
// This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
// If an object is used, iterate through object
if(typeof name === "object"){
for(var x in name){
if(name.hasOwnProperty(x) && x !="_watchCallbacks"){
this.set(x, name[x]);
}
}
return this;
}
var names = this._getAttrNames(name),
oldValue = this._get(name, names),
setter = this[names.s],
result;
if(typeof setter === "function"){
// use the explicit setter
result = setter.apply(this, Array.prototype.slice.call(arguments, 1));
}else{
// no setter so set attribute directly
this[name] = value;
}
if(this._watchCallbacks){
var self = this;
// If setter returned a promise, wait for it to complete, otherwise call watches immediately
when(result, function(){
self._watchCallbacks(name, oldValue, value);
});
}
return this; // dojo/Stateful
},
_changeAttrValue: function(name, value){
// summary:
// Internal helper for directly changing an attribute value.
//
// name: String
// The property to set.
// value: Mixed
// The value to set in the property.
//
// description:
// Directly change the value of an attribute on an object, bypassing any
// accessor setter. Also handles the calling of watch and emitting events.
// It is designed to be used by descendant class when there are two values
// of attributes that are linked, but calling .set() is not appropriate.
var oldValue = this.get(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++){
propertyCallbacks[i].call(self, name, oldValue, value);
}
}
};
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);
// TODO: Remove unwatch in 2.0
var handle = {};
handle.unwatch = handle.remove = function(){
var index = array.indexOf(propertyCallbacks, callback);
if(index > -1){
propertyCallbacks.splice(index, 1);
}
};
return handle; //Object
}
});
});
},
'dijit/Destroyable':function(){
define([
"dojo/_base/array", // array.forEach array.map
"dojo/aspect",
"dojo/_base/declare"
], function(array, aspect, declare){
// module:
// dijit/Destroyable
return declare("dijit.Destroyable", null, {
// summary:
// Mixin to track handles and release them when instance is destroyed.
// description:
// Call this.own(...) on list of handles (returned from dojo/aspect, dojo/on,
// dojo/Stateful::watch, or any class (including widgets) with a destroyRecursive() or destroy() method.
// Then call destroy() later to destroy this instance and release the resources.
destroy: function(/*Boolean*/ preserveDom){
// summary:
// Destroy this class, releasing any resources registered via own().
this._destroyed = true;
},
own: function(){
// summary:
// Track specified handles and remove/destroy them when this instance is destroyed, unless they were
// already removed/destroyed manually.
// tags:
// protected
// returns:
// The array of specified handles, so you can do for example:
// | var handle = this.own(on(...))[0];
var cleanupMethods = [
"destroyRecursive",
"destroy",
"remove"
];
array.forEach(arguments, function(handle){
// When this.destroy() is called, destroy handle. Since I'm using aspect.before(),
// the handle will be destroyed before a subclass's destroy() method starts running, before it calls
// this.inherited() or even if it doesn't call this.inherited() at all. If that's an issue, make an
// onDestroy() method and connect to that instead.
var destroyMethodName;
var odh = aspect.before(this, "destroy", function (preserveDom){
handle[destroyMethodName](preserveDom);
});
// Callback for when handle is manually destroyed.
var hdhs = [];
function onManualDestroy(){
odh.remove();
array.forEach(hdhs, function(hdh){
hdh.remove();
});
}
// Setup listeners for manual destroy of handle.
// Also computes destroyMethodName, used in listener above.
if(handle.then){
// Special path for Promises. Detect when Promise is resolved, rejected, or
// canceled (nb: cancelling a Promise causes it to be rejected).
destroyMethodName = "cancel";
handle.then(onManualDestroy, onManualDestroy);
}else{
// Path for other handles. Just use AOP to detect when handle is manually destroyed.
array.forEach(cleanupMethods, function(cleanupMethod){
if(typeof handle[cleanupMethod] === "function"){
if(!destroyMethodName){
// Use first matching method name in above listener (prefer destroyRecursive() to destroy())
destroyMethodName = cleanupMethod;
}
hdhs.push(aspect.after(handle, cleanupMethod, onManualDestroy, true));
}
});
}
}, this);
return arguments; // handle
}
});
});
},
'dojox/mobile/ViewController':function(){
define([
"dojo/_base/kernel",
"dojo/_base/array",
"dojo/_base/connect",
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/_base/window",
"dojo/_base/Deferred",
"dojo/dom",
"dojo/dom-class",
"dojo/dom-construct",
"dojo/on",
"dojo/ready",
"dijit/registry",
"./ProgressIndicator",
"./TransitionEvent",
"./viewRegistry"
], function(dojo, array, connect, declare, lang, win, Deferred, dom, domClass, domConstruct, on, ready, registry, ProgressIndicator, TransitionEvent, viewRegistry){
// module:
// dojox/mobile/ViewController
var Controller = declare("dojox.mobile.ViewController", null, {
// summary:
// A singleton class that controls view transition.
// description:
// This class listens to the "startTransition" events and performs
// view transitions. If the transition destination is an external
// view specified with the url parameter, the view content is
// retrieved and parsed to create a new target view.
// dataHandlerClass: Object
// The data handler class used to load external views,
// by default "dojox/mobile/dh/DataHandler"
// (see the Data Handlers page in the reference documentation).
dataHandlerClass: "dojox/mobile/dh/DataHandler",
// dataSourceClass: Object
// The data source class used to load external views,
// by default "dojox/mobile/dh/UrlDataSource"
// (see the Data Handlers page in the reference documentation).
dataSourceClass: "dojox/mobile/dh/UrlDataSource",
// fileTypeMapClass: Object
// The file type map class used to load external views,
// by default "dojox/mobile/dh/SuffixFileTypeMap"
// (see the Data Handlers page in the reference documentation).
fileTypeMapClass: "dojox/mobile/dh/SuffixFileTypeMap",
constructor: function(){
// summary:
// Creates a new instance of the class.
// tags:
// private
this.viewMap = {};
ready(lang.hitch(this, function(){
on(win.body(), "startTransition", lang.hitch(this, "onStartTransition"));
}));
},
findTransitionViews: function(/*String*/moveTo){
// summary:
// Parses the moveTo argument and determines a starting view and a destination view.
// returns: Array
// An array containing the currently showing view, the destination view
// and the transition parameters, or an empty array if the moveTo argument
// could not be parsed.
if(!moveTo){ return []; }
// removes a leading hash mark (#) and params if exists
// ex. "#bar&myParam=0003" -> "bar"
moveTo.match(/^#?([^&?]+)(.*)/);
var params = RegExp.$2;
var view = registry.byId(RegExp.$1);
if(!view){ return []; }
for(var v = view.getParent(); v; v = v.getParent()){ // search for the topmost invisible parent node
if(v.isVisible && !v.isVisible()){
var sv = view.getShowingView();
if(sv && sv.id !== view.id){
view.show();
}
view = v;
}
}
return [view.getShowingView(), view, params]; // fromView, toView, params
},
openExternalView: function(/*Object*/ transOpts, /*DomNode*/ target){
// summary:
// Loads an external view and performs a transition to it.
// returns: dojo/_base/Deferred
// Deferred object that resolves when the external view is
// ready and a transition starts. Note that it resolves before
// the transition is complete.
// description:
// This method loads external view content through the
// dojox/mobile data handlers, creates a new View instance with
// the loaded content, and performs a view transition to the
// new view. The external view content can be specified with
// the url property of transOpts. The new view is created under
// a DOM node specified by target.
//
// example:
// This example loads view1.html, creates a new view under
// ``, and performs a transition to the new view with the
// slide animation.
//
// | var vc = ViewController.getInstance();
// | vc.openExternalView({
// | url: "view1.html",
// | transition: "slide"
// | }, win.body());
//
//
// example:
// If you want to perform a view transition without animation,
// you can give transition:"none" to transOpts.
//
// | var vc = ViewController.getInstance();
// | vc.openExternalView({
// | url: "view1.html",
// | transition: "none"
// | }, win.body());
//
// example:
// If you want to dynamically create an external view, but do
// not want to perform a view transition to it, you can give noTransition:true to transOpts.
// This may be useful when you want to preload external views before the user starts using them.
//
// | var vc = ViewController.getInstance();
// | vc.openExternalView({
// | url: "view1.html",
// | noTransition: true
// | }, win.body());
//
// example:
// To do something when the external view is ready:
//
// | var vc = ViewController.getInstance();
// | Deferred.when(vc.openExternalView({...}, win.body()), function(){
// | doSomething();
// | });
var d = new Deferred();
var id = this.viewMap[transOpts.url];
if(id){
transOpts.moveTo = id;
if(transOpts.noTransition){
registry.byId(id).hide();
}else{
new TransitionEvent(win.body(), transOpts).dispatch();
}
d.resolve(true);
return d;
}
// if a fixed bottom bar exists, a new view should be placed before it.
var refNode = null;
for(var i = target.childNodes.length - 1; i >= 0; i--){
var c = target.childNodes[i];
if(c.nodeType === 1){
var fixed = c.getAttribute("fixed") // TODO: Remove the non-HTML5-compliant attribute in 2.0
|| c.getAttribute("data-mobile-fixed")
|| (registry.byNode(c) && registry.byNode(c).fixed);
if(fixed === "bottom"){
refNode = c;
break;
}
}
}
var dh = transOpts.dataHandlerClass || this.dataHandlerClass;
var ds = transOpts.dataSourceClass || this.dataSourceClass;
var ft = transOpts.fileTypeMapClass || this.fileTypeMapClass;
require([dh, ds, ft], lang.hitch(this, function(DataHandler, DataSource, FileTypeMap){
var handler = new DataHandler(new DataSource(transOpts.data || transOpts.url), target, refNode);
var contentType = transOpts.contentType || FileTypeMap.getContentType(transOpts.url) || "html";
handler.processData(contentType, lang.hitch(this, function(id){
if(id){
this.viewMap[transOpts.url] = transOpts.moveTo = id;
if(transOpts.noTransition){
registry.byId(id).hide();
}else{
new TransitionEvent(win.body(), transOpts).dispatch();
}
d.resolve(true);
}else{
d.reject("Failed to load "+transOpts.url);
}
}));
}));
return d;
},
onStartTransition: function(evt){
// summary:
// A handler that performs view transition.
evt.preventDefault();
if(!evt.detail){ return; }
var detail = evt.detail;
if(!detail.moveTo && !detail.href && !detail.url && !detail.scene){ return; }
if(detail.url && !detail.moveTo){
var urlTarget = detail.urlTarget;
var w = registry.byId(urlTarget);
var target = w && w.containerNode || dom.byId(urlTarget);
if(!target){
w = viewRegistry.getEnclosingView(evt.target);
target = w && w.domNode.parentNode || win.body();
}
var src = registry.getEnclosingWidget(evt.target);
if(src && src.callback){
detail.context = src;
detail.method = src.callback;
}
this.openExternalView(detail, target);
return;
}else if(detail.href){
if(detail.hrefTarget && detail.hrefTarget != "_self"){
win.global.open(detail.href, detail.hrefTarget);
}else{
var view; // find top level visible view
for(var v = viewRegistry.getEnclosingView(evt.target); v; v = viewRegistry.getParentView(v)){
view = v;
}
if(view){
view.performTransition(null, detail.transitionDir, detail.transition, evt.target, function(){location.href = detail.href;});
}
}
return;
}else if(detail.scene){
connect.publish("/dojox/mobile/app/pushScene", [detail.scene]);
return;
}
var arr = this.findTransitionViews(detail.moveTo),
fromView = arr[0],
toView = arr[1],
params = arr[2];
if(!location.hash && !detail.hashchange){
viewRegistry.initialView = fromView;
}
if(detail.moveTo && toView){
detail.moveTo = (detail.moveTo.charAt(0) === '#' ? '#' + toView.id : toView.id) + params;
}
if(!fromView || (detail.moveTo && fromView === registry.byId(detail.moveTo.replace(/^#?([^&?]+).*/, "$1")))){ return; }
src = registry.getEnclosingWidget(evt.target);
if(src && src.callback){
detail.context = src;
detail.method = src.callback;
}
fromView.performTransition(detail);
}
});
Controller._instance = new Controller(); // singleton
Controller.getInstance = function(){
return Controller._instance;
};
return Controller;
});
},
'dojox/mobile/ProgressIndicator':function(){
define([
"dojo/_base/config",
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/dom-class",
"dojo/dom-construct",
"dojo/dom-geometry",
"dojo/dom-style",
"dojo/has",
"dijit/_Contained",
"dijit/_WidgetBase",
"./_css3",
"dojo/has!dojo-bidi?dojox/mobile/bidi/ProgressIndicator"
], function(config, declare, lang, domClass, domConstruct, domGeometry, domStyle, has, Contained, WidgetBase, css3, BidiProgressIndicator){
// module:
// dojox/mobile/ProgressIndicator
var cls = declare("dojox.mobile.ProgressIndicator", [WidgetBase, Contained], {
// summary:
// A progress indication widget.
// description:
// ProgressIndicator is a round spinning graphical representation
// that indicates the current task is ongoing.
// interval: Number
// The time interval in milliseconds for updating the spinning
// indicator.
interval: 100,
// size: [const] Number
// The size of the indicator in pixels.
// Note that changing the value of the property after the widget
// creation has no effect.
size: 40,
// removeOnStop: Boolean
// If true, this widget is removed from the parent node
// when stop() is called.
removeOnStop: true,
// startSpinning: Boolean
// If true, calls start() to run the indicator at startup.
startSpinning: false,
// center: Boolean
// If true, the indicator is displayed as center aligned.
center: true,
// colors: String[]
// An array of indicator colors. 12 colors have to be given.
// If colors are not specified, CSS styles
// (mblProg0Color - mblProg11Color) are used.
colors: null,
/* internal properties */
// baseClass: String
// The name of the CSS class of this widget.
baseClass: "mblProgressIndicator",
constructor: function(){
// summary:
// Creates a new instance of the class.
this.colors = [];
this._bars = [];
},
buildRendering: function(){
this.inherited(arguments);
if(this.center){
domClass.add(this.domNode, "mblProgressIndicatorCenter");
}
this.containerNode = domConstruct.create("div", {className:"mblProgContainer"}, this.domNode);
this.spinnerNode = domConstruct.create("div", null, this.containerNode);
for(var i = 0; i < 12; i++){
var div = domConstruct.create("div", {className:"mblProg mblProg"+i}, this.spinnerNode);
this._bars.push(div);
}
this.scale(this.size);
if(this.startSpinning){
this.start();
}
},
scale: function(/*Number*/size){
// summary:
// Changes the size of the indicator.
// size:
// The size of the indicator in pixels.
var scale = size / 40;
domStyle.set(this.containerNode, css3.add({}, {
transform: "scale(" + scale + ")",
transformOrigin: "0 0"
}));
domGeometry.setMarginBox(this.domNode, {w:size, h:size});
domGeometry.setMarginBox(this.containerNode, {w:size / scale, h:size / scale});
},
start: function(){
// summary:
// Starts the spinning of the ProgressIndicator.
if(this.imageNode){
var img = this.imageNode;
var l = Math.round((this.containerNode.offsetWidth - img.offsetWidth) / 2);
var t = Math.round((this.containerNode.offsetHeight - img.offsetHeight) / 2);
img.style.margin = t+"px "+l+"px";
return;
}
var cntr = 0;
var _this = this;
var n = 12;
this.timer = setInterval(function(){
cntr--;
cntr = cntr < 0 ? n - 1 : cntr;
var c = _this.colors;
for(var i = 0; i < n; i++){
var idx = (cntr + i) % n;
if(c[idx]){
_this._bars[i].style.backgroundColor = c[idx];
}else{
domClass.replace(_this._bars[i],
"mblProg" + idx + "Color",
"mblProg" + (idx === n - 1 ? 0 : idx + 1) + "Color");
}
}
}, this.interval);
},
stop: function(){
// summary:
// Stops the spinning of the ProgressIndicator.
if(this.timer){
clearInterval(this.timer);
}
this.timer = null;
if(this.removeOnStop && this.domNode && this.domNode.parentNode){
this.domNode.parentNode.removeChild(this.domNode);
}
},
setImage: function(/*String*/file){
// summary:
// Sets an indicator icon image file (typically animated GIF).
// If null is specified, restores the default spinner.
if(file){
this.imageNode = domConstruct.create("img", {src:file}, this.containerNode);
this.spinnerNode.style.display = "none";
}else{
if(this.imageNode){
this.containerNode.removeChild(this.imageNode);
this.imageNode = null;
}
this.spinnerNode.style.display = "";
}
},
destroy: function(){
this.inherited(arguments);
if(this === cls._instance){
cls._instance = null;
}
}
});
cls = has("dojo-bidi") ? declare("dojox.mobile.ProgressIndicator", [cls, BidiProgressIndicator]) : cls;
cls._instance = null;
cls.getInstance = function(props){
if(!cls._instance){
cls._instance = new cls(props);
}
return cls._instance;
};
return cls;
});
},
'dojox/mobile/_css3':function(){
define([
"dojo/_base/window",
"dojo/_base/array",
"dojo/has"
], function(win, arr, has){
// caches for capitalized names and hypen names
var cnames = [], hnames = [];
// element style used for feature testing
var style = win.doc.createElement("div").style;
// We just test webkit prefix for now since our themes only have standard and webkit
// (see dojox/mobile/themes/common/css3.less)
// More prefixes can be added if/when we add them to css3.less.
var prefixes = ["webkit"];
// Does the browser support CSS3 animations?
has.add("css3-animations", function(global, document, element){
var style = element.style;
return (style["animation"] !== undefined && style["transition"] !== undefined) ||
arr.some(prefixes, function(p){
return style[p+"Animation"] !== undefined && style[p+"Transition"] !== undefined;
});
});
// Indicates whether style 'transition' returns empty string instead of
// undefined, although TransitionEvent is not supported.
// Reported on Android 4.1.x on some devices: https://bugs.dojotoolkit.org/ticket/17164
has.add("t17164", function(global, document, element){
return (element.style["transition"] !== undefined) && !('TransitionEvent' in window);
});
var css3 = {
// summary:
// This module provide some cross-browser support for CSS3 properties.
name: function(/*String*/p, /*Boolean?*/hyphen){
// summary:
// Returns the name of a CSS3 property with the correct prefix depending on the browser.
// p:
// The (non-prefixed) property name. The property name is assumed to be consistent with
// the hyphen argument, for example "transition-property" if hyphen is true, or "transitionProperty"
// if hyphen is false. If the browser supports the non-prefixed property, the property name will be
// returned unchanged.
// hyphen:
// Optional, true if hyphen notation should be used (for example "transition-property" or "-webkit-transition-property"),
// false for camel-case notation (for example "transitionProperty" or "webkitTransitionProperty").
var n = (hyphen?hnames:cnames)[p];
if(!n){
if(/End|Start/.test(p)){
// event names: no good way to feature-detect, so we
// assume they have the same prefix as the corresponding style property
var idx = p.length - (p.match(/End/) ? 3 : 5);
var s = p.substr(0, idx);
var pp = this.name(s);
if(pp == s){
// no prefix, standard event names are all lowercase
n = p.toLowerCase();
}else{
// prefix, e.g. webkitTransitionEnd (camel case)
n = pp + p.substr(idx);
}
}else if(p == "keyframes"){
// special case for keyframes, we also rely on consistency between 'animation' and 'keyframes'
var pk = this.name("animation", hyphen);
if(pk == "animation"){
n = p;
}else if(hyphen){
n = pk.replace(/animation/, "keyframes");
}else{
n = pk.replace(/Animation/, "Keyframes");
}
}else{
// convert name to camel-case for feature test
var cn = hyphen ? p.replace(/-(.)/g, function(match, p1){
return p1.toUpperCase();
}) : p;
if(style[cn] !== undefined && !has('t17164')){
// standard non-prefixed property is supported
n = p;
}else{
// try prefixed versions
cn = cn.charAt(0).toUpperCase() + cn.slice(1);
arr.some(prefixes, function(prefix){
if(style[prefix+cn] !== undefined){
if(hyphen){
n = "-" + prefix + "-" + p;
}else{
n = prefix + cn;
}
}
});
}
}
if(!n){
// The property is not supported, just return it unchanged, it will be ignored.
n = p;
}
(hyphen?hnames:cnames)[p] = n;
}
return n;
},
add: function(/*Object*/styles, /*Object*/css3Styles){
// summary:
// Prefixes all property names in "css3Styles" and adds the prefixed properties in "styles".
// Used as a convenience when an object is passed to domStyle.set to set multiple styles.
// example:
// domStyle.set(bar, css3.add({
// opacity: 0.6,
// position: "absolute",
// backgroundColor: "#606060"
// }, {
// borderRadius: "2px",
// transformOrigin: "0 0"
// }));
// returns:
// The "styles" argument where the CSS3 styles have been added.
for(var p in css3Styles){
if(css3Styles.hasOwnProperty(p)){
styles[css3.name(p)] = css3Styles[p];
}
}
return styles;
}
};
return css3;
});
},
'dojox/mobile/TransitionEvent':function(){
define(["dojo/_base/declare", "dojo/on"], function(declare, on){
return declare("dojox.mobile.TransitionEvent", null, {
// summary:
// A class used to trigger view transitions.
constructor: function(/*DomNode*/target, /*Object*/transitionOptions, /*Event?*/triggerEvent){
// summary:
// Creates a transition event.
// target:
// The DOM node that initiates the transition (for example a ListItem).
// transitionOptions:
// Contains the transition options.
// triggerEvent:
// The event that triggered the transition (for example a touch event on a ListItem).
this.transitionOptions = transitionOptions;
this.target = target;
this.triggerEvent = triggerEvent||null;
},
dispatch: function(){
// summary:
// Dispatches this transition event. Emits a "startTransition" event on the target.
var opts = {bubbles:true, cancelable:true, detail: this.transitionOptions, triggerEvent: this.triggerEvent};
var evt = on.emit(this.target,"startTransition", opts);
}
});
});
},
'dojox/mobile/viewRegistry':function(){
define([
"dojo/_base/array",
"dojo/dom-class",
"dijit/registry"
], function(array, domClass, registry){
// module:
// dojox/mobile/viewRegistry
var viewRegistry = {
// summary:
// A registry of existing views.
// length: Number
// The number of registered views.
length: 0,
// hash: [private] Object
// The object used to register views.
hash: {},
// initialView: [private] dojox/mobile/View
// The initial view.
initialView: null,
add: function(/*dojox/mobile/View*/ view){
// summary:
// Adds a view to the registry.
this.hash[view.id] = view;
this.length++;
},
remove: function(/*String*/ id){
// summary:
// Removes a view from the registry.
if(this.hash[id]){
delete this.hash[id];
this.length--;
}
},
getViews: function(){
// summary:
// Gets all registered views.
// returns: Array
var arr = [];
for(var i in this.hash){
arr.push(this.hash[i]);
}
return arr;
},
getParentView: function(/*dojox/mobile/View*/ view){
// summary:
// Gets the parent view of the specified view.
// returns: dojox/mobile/View
for(var v = view.getParent(); v; v = v.getParent()){
if(domClass.contains(v.domNode, "mblView")){ return v; }
}
return null;
},
getChildViews: function(/*dojox/mobile/View*/ parent){
// summary:
// Gets the children views of the specified view.
// returns: Array
return array.filter(this.getViews(), function(v){ return this.getParentView(v) === parent; }, this);
},
getEnclosingView: function(/*DomNode*/ node){
// summary:
// Gets the view containing the specified DOM node.
// returns: dojox/mobile/View
for(var n = node; n && n.tagName !== "BODY"; n = n.parentNode){
if(n.nodeType === 1 && domClass.contains(n, "mblView")){
return registry.byNode(n);
}
}
return null;
},
getEnclosingScrollable: function(/*DomNode*/ node){
// summary:
// Gets the dojox/mobile/scrollable object containing the specified DOM node.
// returns: dojox/mobile/scrollable
for(var w = registry.getEnclosingWidget(node); w; w = w.getParent()){
if(w.scrollableParams && w._v){ return w; }
}
return null;
}
};
return viewRegistry;
});
},
'dojox/mobile/transition':function(){
define([
"dojo/_base/Deferred",
"dojo/_base/config"
], function(Deferred, config){
/*=====
return {
// summary:
// This is the wrapper module which loads
// dojox/css3/transit conditionally. If mblCSS3Transition
// is set to 'dojox/css3/transit', it will be loaded as
// the module to conduct view transitions, otherwise this module returns null.
};
=====*/
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;
});
},
'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",
"dojo/dom-attr",
"dijit/registry",
"./common",
"dijit/_Contained",
"dijit/_Container",
"dijit/_WidgetBase",
"./ProgressIndicator",
"./ToolBarButton",
"./View",
"dojo/has",
"dojo/has!dojo-bidi?dojox/mobile/bidi/Heading"
], function(array, connect, declare, lang, win, domClass, domConstruct, domStyle, domAttr, registry, common, Contained, Container, WidgetBase, ProgressIndicator, ToolBarButton, View, has, BidiHeading){
// module:
// dojox/mobile/Heading
var dm = lang.getObject("dojox.mobile", true);
var Heading = declare(has("dojo-bidi") ? "dojox.mobile.NonBidiHeading" : "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 of the navigation control.
// If the value has a hash sign ('#') before the id (e.g. #view1)
// and the dojox/mobile/bookmarkable 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", "cube", and "swap". 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: "",
// tag: String
// A name of HTML tag to create as domNode.
tag: "h1",
// busy: Boolean
// If true, a progress indicator spins on this widget.
busy: false,
// progStyle: String
// A css class name to add to the progress indicator.
progStyle: "mblProgWhite",
/* internal properties */
// baseClass: String
// The name of the CSS class of this widget.
baseClass: "mblHeading",
buildRendering: function(){
if(!this.templateString){ // true if this widget is not templated
// Create root node if it wasn't created by _TemplatedMixin
this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement(this.tag);
}
this.inherited(arguments);
if(!this.templateString){ // true if this widget is not templated
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);
}
if(this.labelDivNode){
domAttr.set(this.labelDivNode, "role", "heading"); //a11y
domAttr.set(this.labelDivNode, "aria-level", "1");
}
common.setSelectable(this.domNode, false);
},
startup: function(){
if(this._started){ return; }
var parent = this.getParent && this.getParent();
if(!parent || !parent.resize){ // top level widget
var _this = this;
_this.defer(function(){ // necessary to render correctly
_this.resize();
});
}
this.inherited(arguments);
},
resize: function(){
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 && domStyle.get(c, "display") !== "none"){
if(!rightBtn && domStyle.get(c, "float") === "right"){
rightBtn = c;
}
if(!leftBtn && domStyle.get(c, "float") === "left"){
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){
// tags:
// private
this._set("back", back);
if(!this.backButton){
this.backButton = new ToolBarButton({
arrow: "left",
label: back,
moveTo: this.moveTo,
back: !this.moveTo && !this.href, // use browser history unless moveTo or href
href: this.href,
transition: this.transition,
transitionDir: -1,
dir: this.isLeftToRight() ? "ltr" : "rtl"
});
this.backButton.placeAt(this.domNode, "first");
}else{
this.backButton.set("label", back);
}
this.resize();
},
_setMoveToAttr: function(/*String*/moveTo){
// tags:
// private
this._set("moveTo", moveTo);
if(this.backButton){
this.backButton.set("moveTo", moveTo);
this.backButton.set("back", !moveTo && !this.href);
}
},
_setHrefAttr: function(/*String*/href){
// tags:
// private
this._set("href", href);
if(this.backButton){
this.backButton.set("href", href);
this.backButton.set("back", !this.moveTo && !href);
}
},
_setTransitionAttr: function(/*String*/transition){
// tags:
// private
this._set("transition", transition);
if(this.backButton){
this.backButton.set("transition", transition);
}
},
_setLabelAttr: function(/*String*/label){
// tags:
// private
this._set("label", label);
this.labelNode.innerHTML = this.labelDivNode.innerHTML = this._cv ? this._cv(label) : label;
delete this.labelNodeLen;
},
_setBusyAttr: function(/*Boolean*/busy){
// tags:
// private
var prog = this._prog;
if(busy){
if(!prog){
prog = this._prog = new ProgressIndicator({size:30, center:false});
domClass.add(prog.domNode, this.progStyle);
}
domConstruct.place(prog.domNode, this.domNode, "first");
prog.start();
}else if(prog){
prog.stop();
}
this._set("busy", busy);
}
});
return has("dojo-bidi") ? declare("dojox.mobile.Heading", [Heading, BidiHeading]) : Heading;
});
},
'dojox/mobile/ToolBarButton':function(){
define([
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/_base/window",
"dojo/dom-class",
"dojo/dom-construct",
"dojo/dom-style",
"dojo/dom-attr",
"./sniff",
"./_ItemBase",
"dojo/has!dojo-bidi?dojox/mobile/bidi/ToolBarButton"
], function(declare, lang, win, domClass, domConstruct, domStyle, domAttr, has, ItemBase, BidiToolBarButton){
// module:
// dojox/mobile/ToolBarButton
var ToolBarButton = declare(has("dojo-bidi") ? "dojox.mobile.NonBidiToolBarButton" : "dojox.mobile.ToolBarButton", ItemBase, {
// summary:
// A button widget which is placed in the Heading widget.
// description:
// ToolBarButton is a button which is typically placed in the
// Heading widget. It is a subclass of dojox/mobile/_ItemBase just
// like ListItem or IconItem. So, unlike Button, it has basically
// the same capability as ListItem or IconItem, such as icon
// support, transition, etc.
// selected: Boolean
// If true, the button is in the selected state.
selected: false,
// arrow: [const] String
// Specifies "right" or "left" to be an arrow button.
// Note that changing the value of the property after the widget
// creation has no effect.
arrow: "",
// light: [const] Boolean
// If true, this widget produces only a single `` node when it
// has only an icon or only a label, and has no arrow. In that
// case, you cannot have both icon and label, or arrow even if you
// try to set them.
// Note that changing the value of the property after the widget
// creation has no effect.
light: true,
// defaultColor: String
// CSS class for the default color.
// Note: If this button has an arrow (typically back buttons on iOS),
// the class selector used for it is the value of defaultColor + "45".
// For example, by default the arrow selector is "mblColorDefault45".
defaultColor: "mblColorDefault",
// selColor: String
// CSS class for the selected color.
// Note: If this button has an arrow (typically back buttons on iOS),
// the class selector used for it is the value of selColor + "45".
// For example, by default the selected arrow selector is "mblColorDefaultSel45".
selColor: "mblColorDefaultSel",
/* internal properties */
baseClass: "mblToolBarButton",
_selStartMethod: "touch",
_selEndMethod: "touch",
buildRendering: function(){
if(!this.label && this.srcNodeRef){
this.label = this.srcNodeRef.innerHTML;
}
this.label = lang.trim(this.label);
this.domNode = (this.srcNodeRef && this.srcNodeRef.tagName === "SPAN") ?
this.srcNodeRef : domConstruct.create("span");
domAttr.set(this.domNode, "role", "button");
this.inherited(arguments);
if(this.light && !this.arrow && (!this.icon || !this.label)){
this.labelNode = this.tableNode = this.bodyNode = this.iconParentNode = this.domNode;
domClass.add(this.domNode, this.defaultColor + " mblToolBarButtonBody" +
(this.icon ? " mblToolBarButtonLightIcon" : " mblToolBarButtonLightText"));
return;
}
this.domNode.innerHTML = "";
if(this.arrow === "left" || this.arrow === "right"){
this.arrowNode = domConstruct.create("span", {
className: "mblToolBarButtonArrow mblToolBarButton" +
(this.arrow === "left" ? "Left" : "Right") + "Arrow " +
(has("ie") < 10 ? "" : (this.defaultColor + " " + this.defaultColor + "45"))
}, this.domNode);
domClass.add(this.domNode, "mblToolBarButtonHas" +
(this.arrow === "left" ? "Left" : "Right") + "Arrow");
}
this.bodyNode = domConstruct.create("span", {className:"mblToolBarButtonBody"}, this.domNode);
this.tableNode = domConstruct.create("table", {cellPadding:"0",cellSpacing:"0",border:"0",role:"presentation"}, this.bodyNode);
if(!this.label && this.arrow){
// The class mblToolBarButtonText is needed for arrow shape too.
// If the button has a label, the class is set by _setLabelAttr. If no label, do it here.
this.tableNode.className = "mblToolBarButtonText";
}
var row = this.tableNode.insertRow(-1);
this.iconParentNode = row.insertCell(-1);
this.labelNode = row.insertCell(-1);
this.iconParentNode.className = "mblToolBarButtonIcon";
this.labelNode.className = "mblToolBarButtonLabel";
if(this.icon && this.icon !== "none" && this.label){
domClass.add(this.domNode, "mblToolBarButtonHasIcon");
domClass.add(this.bodyNode, "mblToolBarButtonLabeledIcon");
}
domClass.add(this.bodyNode, this.defaultColor);
},
startup: function(){
if(this._started){ return; }
this.connect(this.domNode, "onkeydown", "_onClick"); // for desktop browsers
this.inherited(arguments);
if(!this._isOnLine){
this._isOnLine = true;
// retry applying the attribute for which the custom setter delays the actual
// work until _isOnLine is true.
this.set("icon", this._pendingIcon !== undefined ? this._pendingIcon : this.icon);
// Not needed anymore (this code executes only once per life cycle):
delete this._pendingIcon;
}
},
_onClick: function(e){
// summary:
// Internal handler for click events.
// tags:
// private
if(e && e.type === "keydown" && e.keyCode !== 13){ return; }
if(this.onClick(e) === false){ return; } // user's click action
this.defaultClickAction(e);
},
onClick: function(/*Event*/ /*===== e =====*/){
// summary:
// User defined function to handle clicks
// tags:
// callback
},
_setLabelAttr: function(/*String*/text){
// summary:
// Sets the button label text.
this.inherited(arguments);
domClass.toggle(this.tableNode, "mblToolBarButtonText", text || this.arrow); // also needed if only arrow
},
_setSelectedAttr: function(/*Boolean*/selected){
// summary:
// Makes this widget in the selected or unselected state.
var replace = function(node, a, b){
domClass.replace(node, a + " " + a + "45", b + " " + b + "45");
};
this.inherited(arguments);
if(selected){
domClass.replace(this.bodyNode, this.selColor, this.defaultColor);
if(!(has("ie") < 10) && this.arrowNode){
replace(this.arrowNode, this.selColor, this.defaultColor);
}
}else{
domClass.replace(this.bodyNode, this.defaultColor, this.selColor);
if(!(has("ie") < 10) && this.arrowNode){
replace(this.arrowNode, this.defaultColor, this.selColor);
}
}
domClass.toggle(this.domNode, "mblToolBarButtonSelected", selected);
domClass.toggle(this.bodyNode, "mblToolBarButtonBodySelected", selected);
}
});
return has("dojo-bidi") ? declare("dojox.mobile.ToolBarButton", [ToolBarButton, BidiToolBarButton]) : ToolBarButton;
});
},
'dojox/mobile/_ItemBase':function(){
define([
"dojo/_base/array",
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/_base/window",
"dojo/dom-class",
"dojo/touch",
"dijit/registry",
"dijit/_Contained",
"dijit/_Container",
"dijit/_WidgetBase",
"./TransitionEvent",
"./iconUtils",
"./sniff",
"./viewRegistry",
"dojo/has!dojo-bidi?dojox/mobile/bidi/_ItemBase"
], function(array, declare, lang, win, domClass, touch, registry, Contained, Container,
WidgetBase, TransitionEvent, iconUtils, has, viewRegistry, BidiItemBase){
// module:
// dojox/mobile/_ItemBase
var _ItemBase = declare(has("dojo-bidi") ? "dojox.mobile._NonBidiItemBase" : "dojox.mobile._ItemBase", [WidgetBase, Container, Contained], {
// summary:
// A base class for item classes (e.g. ListItem, IconItem, etc.).
// description:
// _ItemBase is a base class for widgets that have capability to
// make a view transition when clicked.
// icon: String
// An icon image to display. The value can be either a path for an
// image file or a class name of a DOM button. If icon is not
// specified, the iconBase parameter of the parent widget is used.
icon: "",
// iconPos: String
// The position of an aggregated icon. IconPos is comma separated
// values like top,left,width,height (ex. "0,0,29,29"). If iconPos
// is not specified, the iconPos parameter of the parent widget is
// used.
iconPos: "", // top,left,width,height (ex. "0,0,29,29")
// alt: String
// An alternate text for the icon image.
alt: "",
// href: String
// A URL of another web page to go to.
href: "",
// hrefTarget: String
// A target that specifies where to open a page specified by
// href. The value will be passed to the 2nd argument of
// window.open().
hrefTarget: "",
// moveTo: String
// The id of the transition destination view which resides in the
// current page.
//
// If the value has a hash sign ('#') before the id (e.g. #view1)
// and the dojo/hash module is loaded by the user application, the
// view transition updates the hash in the browser URL so that the
// user can bookmark the destination view. In this case, the user
// can also use the browser's back/forward button to navigate
// through the views in the browser history.
//
// If null, transitions to a blank view.
// If '#', returns immediately without transition.
moveTo: "",
// scene: String
// The name of a scene. Used from dojox/mobile/app.
scene: "",
// clickable: Boolean
// If true, this item becomes clickable even if a transition
// destination (moveTo, etc.) is not specified.
clickable: false,
// url: String
// A URL of an html fragment page or JSON data that represents a
// new view content. The view content is loaded with XHR and
// inserted in the current page. Then a view transition occurs to
// the newly created view. The view is cached so that subsequent
// requests would not load the content again.
url: "",
// urlTarget: String
// Node id under which a new view will be created according to the
// url parameter. If not specified, The new view will be created as
// a sibling of the current view.
urlTarget: "",
// back: Boolean
// If true, history.back() is called when clicked.
back: false,
// transition: String
// A type of animated transition effect. You can choose from the
// standard transition types, "slide", "fade", "flip", or from the
// extended transition types, "cover", "coverv", "dissolve",
// "reveal", "revealv", "scaleIn", "scaleOut", "slidev",
// "swirl", "zoomIn", "zoomOut", "cube", and "swap". If "none" is
// specified, transition occurs immediately without animation.
transition: "",
// transitionDir: Number
// The transition direction. If 1, transition forward. If -1,
// transition backward. For example, the slide transition slides
// the view from right to left when dir == 1, and from left to
// right when dir == -1.
transitionDir: 1,
// transitionOptions: Object
// A hash object that holds transition options.
transitionOptions: null,
// callback: Function|String
// A callback function that is called when the transition has been
// finished. A function reference, or name of a function in
// context.
callback: null,
// label: String
// A label of the item. If the label is not specified, innerHTML is
// used as a label.
label: "",
// toggle: Boolean
// If true, the item acts like a toggle button.
toggle: false,
// selected: Boolean
// If true, the item is highlighted to indicate it is selected.
selected: false,
// tabIndex: String
// Tabindex setting for the item so users can hit the tab key to
// focus on it.
tabIndex: "0",
// _setTabIndexAttr: [private] String
// Sets tabIndex to domNode.
_setTabIndexAttr: "",
/* internal properties */
// paramsToInherit: String
// Comma separated parameters to inherit from the parent.
paramsToInherit: "transition,icon",
// _selStartMethod: String
// Specifies how the item enters the selected state.
//
// - "touch": Use touch events to enter the selected state.
// - "none": Do not change the selected state.
_selStartMethod: "none", // touch or none
// _selEndMethod: String
// Specifies how the item leaves the selected state.
//
// - "touch": Use touch events to leave the selected state.
// - "timer": Use setTimeout to leave the selected state.
// - "none": Do not change the selected state.
_selEndMethod: "none", // touch, timer, or none
// _delayedSelection: Boolean
// If true, selection is delayed 100ms and canceled if dragged in
// order to avoid selection when flick operation is performed.
_delayedSelection: false,
// _duration: Number
// Duration of selection, milliseconds.
_duration: 800,
// _handleClick: Boolean
// If true, this widget listens to touch events.
_handleClick: true,
buildRendering: function(){
this.inherited(arguments);
this._isOnLine = this.inheritParams();
},
startup: function(){
if(this._started){ return; }
if(!this._isOnLine){
this.inheritParams();
}
this._updateHandles();
this.inherited(arguments);
},
inheritParams: function(){
// summary:
// Copies from the parent the values of parameters specified
// by the property paramsToInherit.
var parent = this.getParent();
if(parent){
array.forEach(this.paramsToInherit.split(/,/), function(p){
if(p.match(/icon/i)){
var base = p + "Base", pos = p + "Pos";
if(this[p] && parent[base] &&
parent[base].charAt(parent[base].length - 1) === '/'){
this[p] = parent[base] + this[p];
}
if(!this[p]){ this[p] = parent[base]; }
if(!this[pos]){ this[pos] = parent[pos]; }
}
if(!this[p]){ this[p] = parent[p]; }
}, this);
}
return !!parent;
},
_updateHandles: function(){
// tags:
// private
if(this._handleClick && this._selStartMethod === "touch"){
if(!this._onTouchStartHandle){
this._onTouchStartHandle = this.connect(this.domNode, touch.press, "_onTouchStart");
}
}else{
if(this._onTouchStartHandle){
this.disconnect(this._onTouchStartHandle);
this._onTouchStartHandle = null;
}
}
},
getTransOpts: function(){
// summary:
// Copies from the parent and returns the values of parameters
// specified by the property paramsToInherit.
var opts = this.transitionOptions || {};
array.forEach(["moveTo", "href", "hrefTarget", "url", "target",
"urlTarget", "scene", "transition", "transitionDir"], function(p){
opts[p] = opts[p] || this[p];
}, this);
return opts; // Object
},
userClickAction: function(/*Event*/ /*===== e =====*/){
// summary:
// User-defined click action.
},
defaultClickAction: function(/*Event*/e){
// summary:
// The default action of this item.
this.handleSelection(e);
if(this.userClickAction(e) === false){ return; } // user's click action
this.makeTransition(e);
},
handleSelection: function(/*Event*/e){
// summary:
// Handles this items selection state.
// Before transitioning, we want the visual effect of selecting the item.
// To ensure this effect happens even if _delayedSelection is true:
if(this._delayedSelection){
this.set("selected", true);
} // the item will be deselected after transition.
if(this._onTouchEndHandle){
this.disconnect(this._onTouchEndHandle);
this._onTouchEndHandle = null;
}
var p = this.getParent();
if(this.toggle){
this.set("selected", !this._currentSel);
}else if(p && p.selectOne){
this.set("selected", true);
}else{
if(this._selEndMethod === "touch"){
this.set("selected", false);
}else if(this._selEndMethod === "timer"){
this.defer(function(){
this.set("selected", false);
}, this._duration);
}
}
},
makeTransition: function(/*Event*/e){
// summary:
// Makes a transition.
if(this.back && history){
history.back();
return;
}
if (this.href && this.hrefTarget && this.hrefTarget != "_self") {
win.global.open(this.href, this.hrefTarget || "_blank");
this._onNewWindowOpened(e);
return;
}
var opts = this.getTransOpts();
var doTransition =
!!(opts.moveTo || opts.href || opts.url || opts.target || opts.scene);
if(this._prepareForTransition(e, doTransition ? opts : null) === false){ return; }
if(doTransition){
this.setTransitionPos(e);
new TransitionEvent(this.domNode, opts, e).dispatch();
}
},
_onNewWindowOpened: function(/*Event*/ /*===== e =====*/){
// summary:
// Subclasses may want to implement it.
},
_prepareForTransition: function(/*Event*/e, /*Object*/transOpts){
// summary:
// Subclasses may want to implement it.
},
_onTouchStart: function(e){
// tags:
// private
if(this.getParent().isEditing || this.onTouchStart(e) === false){ return; } // user's touchStart action
var enclosingScrollable = viewRegistry.getEnclosingScrollable(this.domNode);
if(enclosingScrollable &&
domClass.contains(enclosingScrollable.containerNode, "mblScrollableScrollTo2")){
// #17165: do not select the item during scroll animation
return;
}
if(!this._onTouchEndHandle && this._selStartMethod === "touch"){
// Connect to the entire window. Otherwise, fail to receive
// events if operation is performed outside this widget.
// Expose both connect handlers in case the user has interest.
this._onTouchMoveHandle = this.connect(win.body(), touch.move, "_onTouchMove");
this._onTouchEndHandle = this.connect(win.body(), touch.release, "_onTouchEnd");
}
this.touchStartX = e.touches ? e.touches[0].pageX : e.clientX;
this.touchStartY = e.touches ? e.touches[0].pageY : e.clientY;
this._currentSel = this.selected;
if(this._delayedSelection){
// so as not to make selection when the user flicks on ScrollableView
this._selTimer = this.defer(function(){
this.set("selected", true);
}, 100);
}else{
this.set("selected", true);
}
},
onTouchStart: function(/*Event*/ /*===== e =====*/){
// summary:
// User-defined function to handle touchStart events.
// tags:
// callback
},
_onTouchMove: function(e){
// tags:
// private
var x = e.touches ? e.touches[0].pageX : e.clientX;
var y = e.touches ? e.touches[0].pageY : e.clientY;
if(Math.abs(x - this.touchStartX) >= 4 ||
Math.abs(y - this.touchStartY) >= 4){ // dojox/mobile/scrollable.threshold
this.cancel();
var p = this.getParent();
if(p && p.selectOne){
this._prevSel && this._prevSel.set("selected", true);
}else{
this.set("selected", false);
}
}
},
_disconnect: function(){
// tags:
// private
this.disconnect(this._onTouchMoveHandle);
this.disconnect(this._onTouchEndHandle);
this._onTouchMoveHandle = this._onTouchEndHandle = null;
},
cancel: function(){
// summary:
// Cancels an ongoing selection (if any).
if(this._selTimer){
this._selTimer.remove();
this._selTimer = null;
}
this._disconnect();
},
_onTouchEnd: function(e){
// tags:
// private
if(!this._selTimer && this._delayedSelection){ return; }
this.cancel();
this._onClick(e);
},
setTransitionPos: function(e){
// summary:
// Stores the clicked position for later use.
// description:
// Some of the transition animations (e.g. ScaleIn) need the
// clicked position.
var w = this;
while(true){
w = w.getParent();
if(!w || domClass.contains(w.domNode, "mblView")){ break; }
}
if(w){
w.clickedPosX = e.clientX;
w.clickedPosY = e.clientY;
}
},
transitionTo: function(/*String|Object*/moveTo, /*String*/href, /*String*/url, /*String*/scene){
// summary:
// Performs a view transition.
// description:
// Given a transition destination, this method performs a view
// transition. This method is typically called when this item
// is clicked.
var opts = (moveTo && typeof(moveTo) === "object") ? moveTo :
{moveTo: moveTo, href: href, url: url, scene: scene,
transition: this.transition, transitionDir: this.transitionDir};
new TransitionEvent(this.domNode, opts).dispatch();
},
_setIconAttr: function(icon){
// tags:
// private
if(!this._isOnLine){
// record the value to be able to reapply it (see the code in the startup method)
this._pendingIcon = icon;
return;
} // icon may be invalid because inheritParams is not called yet
this._set("icon", icon);
this.iconNode = iconUtils.setIcon(icon, this.iconPos, this.iconNode, this.alt, this.iconParentNode, this.refNode, this.position);
},
_setLabelAttr: function(/*String*/text){
// tags:
// private
this._set("label", text);
this.labelNode.innerHTML = this._cv ? this._cv(text) : text;
},
_setSelectedAttr: function(/*Boolean*/selected){
// summary:
// Makes this widget in the selected or unselected state.
// description:
// Subclass should override.
// tags:
// private
if(selected){
var p = this.getParent();
if(p && p.selectOne){
// deselect the currently selected item
var arr = array.filter(p.getChildren(), function(w){
return w.selected;
});
array.forEach(arr, function(c){
this._prevSel = c;
c.set("selected", false);
}, this);
}
}
this._set("selected", selected);
}
});
return has("dojo-bidi") ? declare("dojox.mobile._ItemBase", [_ItemBase, BidiItemBase]) : _ItemBase;
});
},
'dojox/mobile/iconUtils':function(){
define([
"dojo/_base/array",
"dojo/_base/config",
"dojo/_base/connect",
"dojo/_base/event",
"dojo/_base/lang",
"dojo/_base/window",
"dojo/dom-class",
"dojo/dom-construct",
"dojo/dom-style",
"./sniff"
], function(array, config, connect, event, lang, win, domClass, domConstruct, domStyle, has){
var dm = lang.getObject("dojox.mobile", true);
// module:
// dojox/mobile/iconUtils
var IconUtils = function(){
// summary:
// Utilities to create an icon (image, CSS sprite image, or DOM Button).
this.setupSpriteIcon = 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, {
position: "absolute",
clip: "rect("+t+"px "+r+"px "+b+"px "+l+"px)",
top: (iconNode.parentNode ? domStyle.get(iconNode, "top") : 0) - t + "px",
left: -l + "px"
});
domClass.add(iconNode, "mblSpriteIcon");
}
};
this.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(!this._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 = win.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;
}
}
}
}
}
return dic;
};
this._domButtons = findDomButtons();
}else{
this._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(this._domButtons[btnClass] !== undefined){
nDiv = this._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");
!!style && domStyle.set(node, style);
return node;
};
this.createIcon = function(/*String*/icon, /*String?*/iconPos, /*DomNode?*/node, /*String?*/title, /*DomNode?*/parent, /*DomNode?*/refNode, /*String?*/pos){
// 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.
title = title || "";
if(icon && icon.indexOf("mblDomButton") === 0){
// DOM button
if(!node){
node = domConstruct.create("div", null, refNode || parent, pos);
}else{
if(node.className.match(/(mblDomButton\w+)/)){
domClass.remove(node, RegExp.$1);
}
}
node.title = title;
domClass.add(node, icon);
this.createDomButton(node);
}else if(icon && icon !== "none"){
// Image
if(!node || node.nodeName !== "IMG"){
node = domConstruct.create("img", {
alt: title
}, refNode || parent, pos);
}
node.src = (icon || "").replace("${theme}", dm.currentTheme);
this.setupSpriteIcon(node, iconPos);
if(iconPos && parent){
var arr = iconPos.split(/[ ,]/);
domStyle.set(parent, {
position: "relative",
width: arr[2] + "px",
height: arr[3] + "px"
});
domClass.add(parent, "mblSpriteIconParent");
}
connect.connect(node, "ondragstart", event, "stop");
}
return node;
};
this.iconWrapper = false;
this.setIcon = function(/*String*/icon, /*String*/iconPos, /*DomNode*/iconNode, /*String?*/alt, /*DomNode*/parent, /*DomNode?*/refNode, /*String?*/pos){
// summary:
// A setter function to set an icon.
// description:
// This function is intended to be used by icon setters (e.g. _setIconAttr)
// icon:
// An icon path or a DOM button class name.
// iconPos:
// The position of an aggregated icon. IconPos is comma separated
// values like top,left,width,height (ex. "0,0,29,29").
// iconNode:
// An icon node.
// alt:
// An alt text for the icon image.
// parent:
// Parent node of the icon.
// refNode:
// A node reference to place the icon.
// pos:
// The position of the icon relative to refNode.
if(!parent || !icon && !iconNode){ return null; }
if(icon && icon !== "none"){ // create or update an icon
if(!this.iconWrapper && icon.indexOf("mblDomButton") !== 0 && !iconPos){ // image
if(iconNode && iconNode.tagName === "DIV"){
domConstruct.destroy(iconNode);
iconNode = null;
}
iconNode = this.createIcon(icon, null, iconNode, alt, parent, refNode, pos);
domClass.add(iconNode, "mblImageIcon");
}else{ // sprite or DOM button
if(iconNode && iconNode.tagName === "IMG"){
domConstruct.destroy(iconNode);
iconNode = null;
}
iconNode && domConstruct.empty(iconNode);
if(!iconNode){
iconNode = domConstruct.create("div", null, refNode || parent, pos);
}
this.createIcon(icon, iconPos, null, null, iconNode);
if(alt){
iconNode.title = alt;
}
}
domClass.remove(parent, "mblNoIcon");
return iconNode;
}else{ // clear the icon
domConstruct.destroy(iconNode);
domClass.add(parent, "mblNoIcon");
return null;
}
};
};
// Return singleton. (TODO: can we replace IconUtils class and singleton w/a simple hash of functions?)
return new IconUtils();
});
},
'dojox/mobile/RoundRect':function(){
define([
"dojo/_base/declare",
"dojo/dom-class",
"./Container"
], function(declare, domClass, Container){
// module:
// dojox/mobile/RoundRect
return declare("dojox.mobile.RoundRect", Container, {
// 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: [const] Boolean
// If true, adds a shadow effect to the container element by adding
// the CSS class "mblShadow" to widget's domNode. The default value
// is false. Note that changing the value of the property after
// the widget creation has no effect.
shadow: false,
/* internal properties */
// baseClass: String
// The name of the CSS class of this widget.
baseClass: "mblRoundRect",
buildRendering: function(){
this.inherited(arguments);
if(this.shadow){
domClass.add(this.domNode, "mblShadow");
}
}
});
});
},
'dojox/mobile/Container':function(){
define([
"dojo/_base/declare",
"dijit/_Container",
"./Pane"
], function(declare, Container, Pane){
// module:
// dojox/mobile/Container
return declare("dojox.mobile.Container", [Pane, Container], {
// summary:
// A simple container-type widget.
// description:
// Container is a simple general-purpose container widget.
// It is a widget, but can be regarded as a simple `
` element.
// baseClass: String
// The name of the CSS class of this widget.
baseClass: "mblContainer"
});
});
},
'dojox/mobile/Pane':function(){
define([
"dojo/_base/array",
"dojo/_base/declare",
"dijit/_Contained",
"dijit/_WidgetBase"
], function(array, declare, Contained, WidgetBase){
// module:
// dojox/mobile/Pane
return declare("dojox.mobile.Pane", [WidgetBase, Contained], {
// summary:
// A simple pane widget.
// description:
// Pane is a simple general-purpose pane widget.
// It is a widget, but can be regarded as a simple `
` element.
// baseClass: String
// The name of the CSS class of this widget.
baseClass: "mblPane",
buildRendering: function(){
this.inherited(arguments);
if(!this.containerNode){
// set containerNode so that getChildren() works
this.containerNode = this.domNode;
}
},
resize: function(){
// summary:
// Calls resize() of each child widget.
array.forEach(this.getChildren(), function(child){
if(child.resize){ child.resize(); }
});
}
});
});
},
'dojox/mobile/RoundRectCategory':function(){
define([
"dojo/_base/declare",
"dojo/_base/window",
"dojo/dom-construct",
"dijit/_Contained",
"dijit/_WidgetBase",
"dojo/has",
"dojo/has!dojo-bidi?dojox/mobile/bidi/RoundRectCategory"
], function(declare, win, domConstruct, Contained, WidgetBase, has, BidiRoundRectCategory){
// module:
// dojox/mobile/RoundRectCategory
var RoundRectCategory = declare(has("dojo-bidi") ? "dojox.mobile.NonBidiRoundRectCategory" : "dojox.mobile.RoundRectCategory", [WidgetBase, Contained], {
// summary:
// A category header for a rounded rectangle list.
// label: String
// A label of the category. If the label is not specified,
// innerHTML is used as a label.
label: "",
// tag: String
// A name of html tag to create as domNode.
tag: "h2",
/* internal properties */
// baseClass: String
// The name of the CSS class of this widget.
baseClass: "mblRoundRectCategory",
buildRendering: function(){
var domNode = this.domNode = this.containerNode = this.srcNodeRef || domConstruct.create(this.tag);
this.inherited(arguments);
if(!this.label && domNode.childNodes.length === 1 && domNode.firstChild.nodeType === 3){
// if it has only one text node, regard it as a label
this.label = domNode.firstChild.nodeValue;
}
},
_setLabelAttr: function(/*String*/label){
// summary:
// Sets the category header text.
// tags:
// private
this.label = label;
this.domNode.innerHTML = this._cv ? this._cv(label) : label;
}
});
return has("dojo-bidi") ? declare("dojox.mobile.RoundRectCategory", [RoundRectCategory, BidiRoundRectCategory]) : RoundRectCategory;
});
},
'dojox/mobile/EdgeToEdgeCategory':function(){
define([
"dojo/_base/declare",
"./RoundRectCategory"
], function(declare, RoundRectCategory){
// module:
// dojox/mobile/EdgeToEdgeCategory
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";
if(this.type && this.type == "long"){
this.domNode.className += " mblEdgeToEdgeCategoryLong";
}
}
});
});
},
'dojox/mobile/RoundRectList':function(){
define([
"dojo/_base/array",
"dojo/_base/declare",
"dojo/_base/event",
"dojo/_base/lang",
"dojo/_base/window",
"dojo/dom-construct",
"dojo/dom-attr",
"dijit/_Contained",
"dijit/_Container",
"dijit/_WidgetBase"
], function(array, declare, event, lang, win, domConstruct, domAttr, Contained, Container, WidgetBase){
// module:
// dojox/mobile/RoundRectList
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 a 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.
// If "", the check mark is not shown.
select: "",
// stateful: Boolean
// If true, the last selected item remains highlighted.
stateful: false,
// syncWithViews: [const] Boolean
// If true, this widget listens to view transition events to be
// synchronized with view's visibility.
// Note that changing the value of the property after the widget
// creation has no effect.
syncWithViews: false,
// editable: [const] Boolean
// If true, the list can be reordered.
// Note that changing the value of the property after the widget
// creation has no effect.
editable: false,
// tag: String
// A name of html tag to create as domNode.
tag: "ul",
/* internal properties */
// editableMixinClass: String
// The name of the mixin class.
editableMixinClass: "dojox/mobile/_EditableListMixin",
// baseClass: String
// The name of the CSS class of this widget.
baseClass: "mblRoundRectList",
// filterBoxClass: String
// The name of the CSS class added to the DOM node inside which is placed the
// dojox/mobile/SearchBox created when mixing dojox/mobile/FilteredListMixin.
// The default value is "mblFilteredRoundRectListSearchBox".
filterBoxClass: "mblFilteredRoundRectListSearchBox",
buildRendering: function(){
this.domNode = this.srcNodeRef || domConstruct.create(this.tag);
if(this.select){
domAttr.set(this.domNode, "role", "listbox");
if(this.select === "multiple"){
domAttr.set(this.domNode, "aria-multiselectable", "true");
}
}
this.inherited(arguments);
},
postCreate: function(){
if(this.editable){
require([this.editableMixinClass], lang.hitch(this, function(module){
declare.safeMixin(this, new module());
}));
}
this.connect(this.domNode, "onselectstart", event.stop);
if(this.syncWithViews){ // see also TabBar#postCreate
var f = function(view, moveTo, dir, transition, context, method){
var child = array.filter(this.getChildren(), function(w){
return w.moveTo === "#" + view.id || w.moveTo === view.id; })[0];
if(child){ child.set("selected", true); }
};
this.subscribe("/dojox/mobile/afterTransitionIn", f);
this.subscribe("/dojox/mobile/startView", f);
}
},
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){
// tags:
// private
this._set("stateful", stateful);
this.selectOne = stateful;
array.forEach(this.getChildren(), function(child){
child.setArrow && child.setArrow();
});
},
deselectItem: function(/*dojox/mobile/ListItem*/item){
// summary:
// Deselects the given item.
item.set("selected", false);
},
deselectAll: function(){
// summary:
// Deselects all the items.
array.forEach(this.getChildren(), function(child){
child.set("selected", false);
});
},
selectItem: function(/*ListItem*/item){
// summary:
// Selects the given item.
item.set("selected", true);
}
});
});
},
'dojox/mobile/EdgeToEdgeList':function(){
define([
"dojo/_base/declare",
"./RoundRectList"
], function(declare, RoundRectList){
// module:
// dojox/mobile/EdgeToEdgeCategory
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 a
// dojox/mobile/ListItem.
// filterBoxClass: String
// The name of the CSS class added to the DOM node inside which is placed the
// dojox/mobile/SearchBox created when mixing dojox/mobile/FilteredListMixin.
// The default value is "mblFilteredEdgeToEdgeListSearchBox".
filterBoxClass: "mblFilteredEdgeToEdgeListSearchBox",
buildRendering: function(){
this.inherited(arguments);
this.domNode.className = "mblEdgeToEdgeList";
}
});
});
},
'dojox/mobile/ListItem':function(){
define([
"dojo/_base/array",
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/dom-class",
"dojo/dom-construct",
"dojo/dom-style",
"dojo/dom-attr",
"dijit/registry",
"dijit/_WidgetBase",
"./iconUtils",
"./_ItemBase",
"./ProgressIndicator",
"dojo/has",
"dojo/has!dojo-bidi?dojox/mobile/bidi/ListItem"
], function(array, declare, lang, domClass, domConstruct, domStyle, domAttr, registry, WidgetBase, iconUtils, ItemBase, ProgressIndicator, has, BidiListItem){
// module:
// dojox/mobile/ListItem
var ListItem = declare(has("dojo-bidi") ? "dojox.mobile.NonBidiListItem" : "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.
//
// A child DOM node (or widget) can have the layout attribute,
// whose value is "left", "right", or "center". Such nodes will be
// aligned as specified.
// example:
// |
// |
Left Node
// |
Right Node
// |
Center Node
// |
//
// Similarly, a child widget can have the preventTouch
// attribute, whose value is a boolean (or data-mobile-prevent-touch
// for children which are not widgets), such that touching such
// child doesn't trigger the item action.
//
// Note that even if you specify variableHeight="true" for the list
// and place a tall object inside the layout node as in the example
// below, the layout node does not expand as you may expect,
// because layout node is aligned using float:left, float:right, or
// position:absolute.
// example:
// |
// |
// |
// 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: "",
// deleteIcon: String
// A delete icon to display at the left of the item. The value can
// be either a path for an image file or a class name of a DOM
// button.
deleteIcon: "",
// 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,
// 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: "",
// 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: "",
// uncheckClass: String
// An icon to display as an uncheck mark. The value can be either a
// path for an image file or a class name of a DOM button.
uncheckClass: "",
// variableHeight: Boolean
// If true, the height of the item varies according to its content.
variableHeight: false,
// rightIconTitle: String
// An alt text for the right icon.
rightIconTitle: "",
// rightIcon2Title: String
// An alt text for the right icon2.
rightIcon2Title: "",
// header: Boolean
// If true, this item is rendered as a category header.
header: false,
// tag: String
// A name of html tag to create as domNode.
tag: "li",
// busy: Boolean
// If true, a progress indicator spins.
busy: false,
// progStyle: String
// A css class name to add to the progress indicator.
progStyle: "",
// layoutOnResize: Boolean
// If true, a call to resize() will force computation of variable height items layout. You should not need this as in most
// cases ListItem height doesn't change on container resize. Depending on number and complexity
// of items in a view, setting to true may have a high impact on performance.
layoutOnResize: false,
/* internal properties */
// The following properties are overrides of those in _ItemBase.
paramsToInherit: "variableHeight,transition,deleteIcon,icon,rightIcon,rightIcon2,uncheckIcon,arrowClass,checkClass,uncheckClass,deleteIconTitle,deleteIconRole",
baseClass: "mblListItem",
_selStartMethod: "touch",
_selEndMethod: "timer",
_delayedSelection: true,
_selClass: "mblListItemSelected",
buildRendering: function(){
this._templated = !!this.templateString; // true if this widget is templated
if(!this._templated){
// Create root node if it wasn't created by _TemplatedMixin
this.domNode = this.containerNode = this.srcNodeRef || domConstruct.create(this.tag);
}
this.inherited(arguments);
if(this.selected){
domClass.add(this.domNode, this._selClass);
}
if(this.header){
domClass.replace(this.domNode, "mblEdgeToEdgeCategory", this.baseClass);
}
if(!this._templated){
this.labelNode =
domConstruct.create("div", {className:"mblListItemLabel"});
var ref = this.srcNodeRef;
if(ref && ref.childNodes.length === 1 && ref.firstChild.nodeType === 3){
// if ref has only one text node, regard it as a label
this.labelNode.appendChild(ref.firstChild);
}
this.domNode.appendChild(this.labelNode);
}
this._layoutChildren = [];
},
startup: function(){
if(this._started){ return; }
var parent = this.getParent();
var opts = this.getTransOpts();
// When using a template, labelNode may be created via an attach point.
// The attach points are not yet set when ListItem.buildRendering()
// executes, hence the need to use them in startup().
if((!this._templated || this.labelNode) && this.anchorLabel){
this.labelNode.style.display = "inline"; // to narrow the text region
this.labelNode.style.cursor = "pointer";
this.connect(this.labelNode, "onclick", "_onClick");
this.onTouchStart = function(e){
return (e.target !== this.labelNode);
};
}
this.inherited(arguments);
if(domClass.contains(this.domNode, "mblVariableHeight")){
this.variableHeight = true;
}
if(this.variableHeight){
domClass.add(this.domNode, "mblVariableHeight");
this.defer("layoutVariableHeight");
}
if(!this._isOnLine){
this._isOnLine = true;
this.set({
// retry applying the attributes for which the custom setter delays the actual
// work until _isOnLine is true
icon: this._pending_icon !== undefined ? this._pending_icon : this.icon,
deleteIcon: this._pending_deleteIcon !== undefined ? this._pending_deleteIcon : this.deleteIcon,
rightIcon: this._pending_rightIcon !== undefined ? this._pending_rightIcon : this.rightIcon,
rightIcon2: this._pending_rightIcon2 !== undefined ? this._pending_rightIcon2 : this.rightIcon2,
uncheckIcon: this._pending_uncheckIcon !== undefined ? this._pending_uncheckIcon : this.uncheckIcon
});
// Not needed anymore (this code executes only once per life cycle):
delete this._pending_icon;
delete this._pending_deleteIcon;
delete this._pending_rightIcon;
delete this._pending_rightIcon2;
delete this._pending_uncheckIcon;
}
if(parent && parent.select){
// retry applying the attributes for which the custom setter delays the actual
// work until _isOnLine is true.
this.set("checked", this._pendingChecked !== undefined ? this._pendingChecked : this.checked);
domAttr.set(this.domNode, "role", "option");
if(this._pendingChecked || this.checked){
domAttr.set(this.domNode, "aria-selected", "true");
}
// Not needed anymore (this code executes only once per life cycle):
delete this._pendingChecked;
}
this.setArrow();
this.layoutChildren();
},
_updateHandles: function(){
// tags:
// private
var parent = this.getParent();
var opts = this.getTransOpts();
if(opts.moveTo || opts.href || opts.url || this.clickable || (parent && parent.select)){
if(!this._keydownHandle){
this._keydownHandle = this.connect(this.domNode, "onkeydown", "_onClick"); // for desktop browsers
}
this._handleClick = true;
}else{
if(this._keydownHandle){
this.disconnect(this._keydownHandle);
this._keydownHandle = null;
}
this._handleClick = false;
}
this.inherited(arguments);
},
layoutChildren: function(){
var centerNode;
array.forEach(this.domNode.childNodes, function(n){
if(n.nodeType !== 1){ return; }
var layout = n.getAttribute("layout") || // TODO: Remove the non-HTML5-compliant attribute in 2.0
n.getAttribute("data-mobile-layout") ||
(registry.byNode(n) || {}).layout;
if(layout){
domClass.add(n, "mblListItemLayout" +
layout.charAt(0).toUpperCase() + layout.substring(1));
this._layoutChildren.push(n);
if(layout === "center"){ centerNode = n; }
}
}, this);
if(centerNode){
this.domNode.insertBefore(centerNode, this.domNode.firstChild);
}
},
resize: function(){
if(this.layoutOnResize && this.variableHeight){
this.layoutVariableHeight();
}
// labelNode may not exist only when using a template (if not created by an attach point)
if(!this._templated || this.labelNode){
// If labelNode is empty, shrink it so as not to prevent user clicks.
this.labelNode.style.display = this.labelNode.firstChild ? "block" : "inline";
}
},
_onTouchStart: function(e){
// tags:
// private
if(e.target.getAttribute("preventTouch") || // TODO: Remove the non-HTML5-compliant attribute in 2.0
e.target.getAttribute("data-mobile-prevent-touch") ||
(registry.getEnclosingWidget(e.target) || {}).preventTouch){
return;
}
this.inherited(arguments);
},
_onClick: function(e){
// summary:
// Internal handler for click events.
// tags:
// private
if(this.getParent().isEditing || e && e.type === "keydown" && e.keyCode !== 13){ return; }
if(this.onClick(e) === false){ return; } // user's click action
var n = this.labelNode;
// labelNode may not exist only when using a template
if((this._templated || n) && this.anchorLabel && e.currentTarget === n){
domClass.add(n, "mblListItemLabelSelected");
this.defer(function(){
domClass.remove(n, "mblListItemLabelSelected");
}, this._duration);
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.defaultClickAction(e);
},
onClick: function(/*Event*/ /*===== e =====*/){
// summary:
// User-defined function to handle clicks.
// tags:
// callback
},
onAnchorLabelClicked: function(e){
// summary:
// Stub function to connect to from your application.
},
layoutVariableHeight: function(){
// summary:
// Lays out the current item with variable height.
var h = this.domNode.offsetHeight;
if(h === this.domNodeHeight){ return; }
this.domNodeHeight = h;
array.forEach(this._layoutChildren.concat([
this.rightTextNode,
this.rightIcon2Node,
this.rightIconNode,
this.uncheckIconNode,
this.iconNode,
this.deleteIconNode,
this.knobIconNode
]), function(n){
if(n){
var domNode = this.domNode;
var f = function(){
var t = Math.round((domNode.offsetHeight - n.offsetHeight) / 2) -
domStyle.get(domNode, "paddingTop");
n.style.marginTop = t + "px";
};
if(n.offsetHeight === 0 && n.tagName === "IMG"){
n.onload = f;
}else{
f();
}
}
}, this);
},
setArrow: function(){
// summary:
// Sets the arrow icon if necessary.
if(this.checked){ return; }
var c = "";
var parent = this.getParent();
var opts = this.getTransOpts();
if(opts.moveTo || opts.href || opts.url || this.clickable){
if(!this.noArrow && !(parent && parent.selectOne)){
c = this.arrowClass || "mblDomButtonArrow";
domAttr.set(this.domNode, "role", "button");
}
}
if(c){
this._setRightIconAttr(c);
}
},
_findRef: function(/*String*/type){
// summary:
// Find an appropriate position to insert a new child node.
// tags:
// private
var i, node, list = ["deleteIcon", "icon", "rightIcon", "uncheckIcon", "rightIcon2", "rightText"];
for(i = array.indexOf(list, type) + 1; i < list.length; i++){
node = this[list[i] + "Node"];
if(node){ return node; }
}
for(i = list.length - 1; i >= 0; i--){
node = this[list[i] + "Node"];
if(node){ return node.nextSibling; }
}
return this.domNode.firstChild;
},
_setIcon: function(/*String*/icon, /*String*/type){
// tags:
// private
if(!this._isOnLine){
// record the value to be able to reapply it (see the code in the startup method)
this["_pending_" + type] = icon;
return;
} // icon may be invalid because inheritParams is not called yet
this._set(type, icon);
this[type + "Node"] = iconUtils.setIcon(icon, this[type + "Pos"],
this[type + "Node"], this[type + "Title"] || this.alt, this.domNode, this._findRef(type), "before");
if(this[type + "Node"]){
var cap = type.charAt(0).toUpperCase() + type.substring(1);
domClass.add(this[type + "Node"], "mblListItem" + cap);
}
var role = this[type + "Role"];
if(role){
this[type + "Node"].setAttribute("role", role);
}
},
_setDeleteIconAttr: function(/*String*/icon){
// tags:
// private
this._setIcon(icon, "deleteIcon");
},
_setIconAttr: function(icon){
// tags:
// private
this._setIcon(icon, "icon");
},
_setRightTextAttr: function(/*String*/text){
// tags:
// private
if(!this._templated && !this.rightTextNode){
// When using a template, let the template create the element.
this.rightTextNode = domConstruct.create("div", {className:"mblListItemRightText"}, this.labelNode, "before");
}
this.rightText = text;
this.rightTextNode.innerHTML = this._cv ? this._cv(text) : text;
},
_setRightIconAttr: function(/*String*/icon){
// tags:
// private
this._setIcon(icon, "rightIcon");
},
_setUncheckIconAttr: function(/*String*/icon){
// tags:
// private
this._setIcon(icon, "uncheckIcon");
},
_setRightIcon2Attr: function(/*String*/icon){
// tags:
// private
this._setIcon(icon, "rightIcon2");
},
_setCheckedAttr: function(/*Boolean*/checked){
// tags:
// private
if(!this._isOnLine){
// record the value to be able to reapply it (see the code in the startup method)
this._pendingChecked = checked;
return;
} // icon may be invalid because inheritParams is not called yet
var parent = this.getParent();
if(parent && parent.select === "single" && checked){
array.forEach(parent.getChildren(), function(child){
child !== this && child.checked && child.set("checked", false) && domAttr.set(child.domNode, "aria-selected", "false");
}, this);
}
this._setRightIconAttr(this.checkClass || "mblDomButtonCheck");
this._setUncheckIconAttr(this.uncheckClass);
domClass.toggle(this.domNode, "mblListItemChecked", checked);
domClass.toggle(this.domNode, "mblListItemUnchecked", !checked);
domClass.toggle(this.domNode, "mblListItemHasUncheck", !!this.uncheckIconNode);
this.rightIconNode.style.position = (this.uncheckIconNode && !checked) ? "absolute" : "";
if(parent && this.checked !== checked){
parent.onCheckStateChanged(this, checked);
}
this._set("checked", checked);
domAttr.set(this.domNode, "aria-selected", checked ? "true" : "false");
},
_setBusyAttr: function(/*Boolean*/busy){
// tags:
// private
var prog = this._prog;
if(busy){
if(!this._progNode){
this._progNode = domConstruct.create("div", {className:"mblListItemIcon"});
prog = this._prog = new ProgressIndicator({size:25, center:false, removeOnStop:false});
domClass.add(prog.domNode, this.progStyle);
this._progNode.appendChild(prog.domNode);
}
if(this.iconNode){
this.domNode.replaceChild(this._progNode, this.iconNode);
}else{
domConstruct.place(this._progNode, this._findRef("icon"), "before");
}
prog.start();
}else if(this._progNode){
if(this.iconNode){
this.domNode.replaceChild(this.iconNode, this._progNode);
}else{
this.domNode.removeChild(this._progNode);
}
prog.stop();
}
this._set("busy", busy);
},
_setSelectedAttr: function(/*Boolean*/selected){
// summary:
// Makes this widget in the selected or unselected state.
// tags:
// private
this.inherited(arguments);
domClass.toggle(this.domNode, this._selClass, selected);
},
_setClickableAttr: function(/*Boolean*/clickable){
// tags:
// private
this._set("clickable", clickable);
this._updateHandles();
},
_setMoveToAttr: function(/*String*/moveTo){
// tags:
// private
this._set("moveTo", moveTo);
this._updateHandles();
},
_setHrefAttr: function(/*String*/href){
// tags:
// private
this._set("href", href);
this._updateHandles();
},
_setUrlAttr: function(/*String*/url){
// tags:
// private
this._set("url", url);
this._updateHandles();
}
});
ListItem.ChildWidgetProperties = {
// summary:
// These properties can be specified for the children of a dojox/mobile/ListItem.
// layout: String
// Specifies the position of the ListItem child ("left", "center" or "right").
layout: "",
// preventTouch: Boolean
// Disables touch events on the ListItem child.
preventTouch: false
};
// Since any widget can be specified as a ListItem child, mix ChildWidgetProperties
// into the base widget class. (This is a hack, but it's effective.)
// This is for the benefit of the parser. Remove for 2.0. Also, hide from doc viewer.
lang.extend(WidgetBase, /*===== {} || =====*/ ListItem.ChildWidgetProperties);
return has("dojo-bidi") ? declare("dojox.mobile.ListItem", [ListItem, BidiListItem]) : ListItem;
});
},
'dojox/mobile/Switch':function(){
define([
"dojo/_base/array",
"dojo/_base/connect",
"dojo/_base/declare",
"dojo/_base/event",
"dojo/_base/window",
"dojo/dom-class",
"dojo/dom-construct",
"dojo/dom-style",
"dojo/dom-attr",
"dojo/touch",
"dijit/_Contained",
"dijit/_WidgetBase",
"./sniff",
"./_maskUtils",
"./common",
"dojo/has!dojo-bidi?dojox/mobile/bidi/Switch"
], function(array, connect, declare, event, win, domClass, domConstruct, domStyle, domAttr, touch, Contained, WidgetBase, has, maskUtils, dm, BidiSwitch){
// module:
// dojox/mobile/Switch
var Switch = declare(has("dojo-bidi") ? "dojox.mobile.NonBidiSwitch" : "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",
// shape: String
// The shape of the switch.
// "mblSwDefaultShape", "mblSwSquareShape", "mblSwRoundShape1",
// "mblSwRoundShape2", "mblSwArcShape1" or "mblSwArcShape2".
// The default value is "mblSwDefaultShape".
shape: "mblSwDefaultShape",
// tabIndex: String
// Tabindex setting for this widget so users can hit the tab key to
// focus on it.
tabIndex: "0",
_setTabIndexAttr: "", // sets tabIndex to domNode
/* internal properties */
baseClass: "mblSwitch",
// role: [private] String
// The accessibility role.
role: "", // a11y
buildRendering: function(){
if(!this.templateString){ // true if this widget is not templated
this.domNode = (this.srcNodeRef && this.srcNodeRef.tagName === "SPAN") ?
this.srcNodeRef : domConstruct.create("span");
}
// prevent browser scrolling on IE10 (evt.preventDefault() is not enough)
dm._setTouchAction(this.domNode, "none");
this.inherited(arguments);
if(!this.templateString){ // true if this widget is not templated
var c = (this.srcNodeRef && this.srcNodeRef.className) || this.className || this["class"];
if((c = c.match(/mblSw.*Shape\d*/))){ this.shape = c; }
domClass.add(this.domNode, this.shape);
var nameAttr = this.name ? " name=\"" + this.name + "\"" : "";
this.domNode.innerHTML =
'
'
+ '
'
+ ''
+ '
'
+ '
'
+ ''
+ '
'
+ ''
+ '
'
+ '
';
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];
}
domAttr.set(this.domNode, "role", "checkbox"); //a11y
domAttr.set(this.domNode, "aria-checked", (this.value === "on") ? "true" : "false"); //a11y
this.switchNode = this.domNode;
if(has("windows-theme")) {
var rootNode = domConstruct.create("div", {className: "mblSwitchContainer"});
this.labelNode = domConstruct.create("label", {"class": "mblSwitchLabel", "for": this.id}, rootNode);
rootNode.appendChild(this.domNode.cloneNode(true));
this.domNode = rootNode;
this.focusNode = rootNode.childNodes[1];
this.labelNode.innerHTML = (this.value=="off") ? this.rightLabel : this.leftLabel;
this.switchNode = this.domNode.childNodes[1];
var inner = this.inner = this.domNode.childNodes[1].firstChild;
this.left = inner.childNodes[0];
this.right = inner.childNodes[1];
this.knob = inner.childNodes[2];
this.input = inner.childNodes[3];
}
},
postCreate: function(){
this.connect(this.switchNode, "onclick", "_onClick");
this.connect(this.switchNode, "onkeydown", "_onClick"); // for desktop browsers
this._startHandle = this.connect(this.switchNode, touch.press, "onTouchStart");
this._initialValue = this.value; // for reset()
},
startup: function(){
var started = this._started;
this.inherited(arguments);
if(!started){
this.resize();
}
},
resize: function(){
if(has("windows-theme")){
// Override the custom CSS width (if any) to avoid misplacement.
// Per design, the windows theme does not allow resizing the controls.
// The label of the switch is placed next to the switch, and a custom
// width would only have the effect to increase the distance between the
// label and the switch, which is undesired. Hence, on windows theme,
// ensure the width of root DOM node is 100%.
domStyle.set(this.domNode, "width", "100%");
}else{
var value = domStyle.get(this.domNode,"width");
var outWidth = value + "px";
var innWidth = (value - domStyle.get(this.knob,"width")) + "px";
domStyle.set(this.left, "width", outWidth);
domStyle.set(this.right,this.isLeftToRight()?{width: outWidth, left: innWidth}:{width: outWidth});
domStyle.set(this.left.firstChild, "width", innWidth);
domStyle.set(this.right.firstChild, "width", innWidth);
domStyle.set(this.knob, "left", innWidth);
if(this.value == "off"){
domStyle.set(this.inner, "left", this.isLeftToRight()?("-" + innWidth):0);
}
this._hasMaskImage = false;
this._createMaskImage();
}
},
_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.switchNode, "mblSwitchAnimation");
}
domClass.remove(this.switchNode, on ? "mblSwitchOff" : "mblSwitchOn");
domClass.add(this.switchNode, on ? "mblSwitchOn" : "mblSwitchOff");
domAttr.set(this.switchNode, "aria-checked", on ? "true" : "false"); //a11y
if(!on && !has("windows-theme")){
this.inner.style.left = (this.isLeftToRight()?(-(domStyle.get(this.domNode,"width") - domStyle.get(this.knob,"width"))):0) + "px";
}
var _this = this;
_this.defer(function(){
_this.left.style.display = on ? "" : "none";
_this.right.style.display = !on ? "" : "none";
domClass.remove(_this.switchNode, "mblSwitchAnimation");
}, anim ? 300 : 0);
},
_createMaskImage: function(){
if(this._timer){
this._timer.remove();
delete this._timer;
}
if(this._hasMaskImage){ return; }
var w = domStyle.get(this.domNode,"width"), h = domStyle.get(this.domNode,"height");
this._width = (w - domStyle.get(this.knob,"width"));
this._hasMaskImage = true;
if(!(has("mask-image"))){ return; }
var rDef = domStyle.get(this.left, "borderTopLeftRadius");
if(!rDef || rDef == "0px"){ return; }
var rDefs = rDef.split(" ");
var rx = parseFloat(rDefs[0]), ry = (rDefs.length == 1) ? rx : parseFloat(rDefs[1]);
if(rx && ry){
maskUtils.createRoundMask(this.switchNode, 0, 0, 0, 0, w, h, rx, ry, 1);
}
},
_onClick: function(e){
// summary:
// Internal handler for click events.
// tags:
// private
if(e && e.type === "keydown" && e.keyCode !== 13){ return; }
if(this.onClick(e) === false){ return; } // user's click action
if(this._moved){ return; }
this._set("value", this.input.value = (this.value == "on") ? "off" : "on");
this._changeState(this.value, true);
this.onStateChanged(this.value);
},
onClick: function(/*Event*/ /*===== e =====*/){
// summary:
// User defined function to handle clicks
// tags:
// callback
},
onTouchStart: function(/*Event*/e){
// summary:
// Internal function to handle touchStart events.
this._moved = false;
this.innerStartX = this.inner.offsetLeft;
if(!this._conn){
this._conn = [
this.connect(this.inner, touch.move, "onTouchMove"),
this.connect(win.doc, touch.release, "onTouchEnd")
];
/* While moving the slider knob sometimes IE fires MSPointerCancel event. That prevents firing
MSPointerUp event (http://msdn.microsoft.com/ru-ru/library/ie/hh846776%28v=vs.85%29.aspx) so the
knob can be stuck in the middle of the switch. As a fix we handle MSPointerCancel event with the
same lintener as for MSPointerUp event.
*/
if(has("windows-theme")){
this._conn.push(this.connect(win.doc, "MSPointerCancel", "onTouchEnd"));
}
}
this.touchStartX = e.touches ? e.touches[0].pageX : e.clientX;
this.left.style.display = "";
this.right.style.display = "";
event.stop(e);
this._createMaskImage();
},
onTouchMove: function(/*Event*/e){
// summary:
// Internal function to handle touchMove events.
e.preventDefault();
var dx;
if(e.targetTouches){
if(e.targetTouches.length != 1){ return; }
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(/*Event*/e){
// summary:
// Internal function to handle touchEnd events.
array.forEach(this._conn, connect.disconnect);
this._conn = null;
if(this.innerStartX == this.inner.offsetLeft){
// need to send a synthetic click?
if(has("touch") && has("clicks-prevented")){
dm._sendClick(this.inner, e);
}
return;
}
var newState = (this.inner.offsetLeft < -(this._width/2)) ? "off" : "on";
newState = this._newState(newState);
this._changeState(newState, true);
if(newState != this.value){
this._set("value", this.input.value = newState);
this.onStateChanged(newState);
}
},
_newState: function(newState){
return newState;
},
onStateChanged: function(/*String*/newState){
// summary:
// Stub function to connect to from your application.
// description:
// Called when the state has been changed.
if (this.labelNode) {
this.labelNode.innerHTML = newState=='off' ? this.rightLabel : this.leftLabel;
}
},
_setValueAttr: function(/*String*/value){
this._changeState(value, false);
if(this.value != value){
this._set("value", this.input.value = value);
this.onStateChanged(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);
}
});
return has("dojo-bidi") ? declare("dojox.mobile.Switch", [Switch, BidiSwitch]) : Switch;
});
},
'dojox/mobile/_maskUtils':function(){
define([
"dojo/_base/window",
"dojo/dom-style",
"./sniff"
], function(win, domStyle, has){
has.add("mask-image-css", function(global, doc, elt){
return typeof doc.getCSSCanvasContext === "function" && typeof elt.style.webkitMaskImage !== "undefined";
});
// Indicates whether image mask is available (either via css mask image or svg)
has.add("mask-image", function(){
return has("mask-image-css") || has("svg");
});
var cache = {};
return {
// summary:
// Utility methods to clip rounded corners of various elements (Switch, ScrollablePane, scrollbars in scrollable widgets).
// Uses -webkit-mask-image on webkit, or SVG on other browsers.
createRoundMask: function(/*DomNode*/node, x, y, r, b, w, h, rx, ry, e){
// summary:
// Creates and sets a mask for the specified node.
var tw = x + w + r;
var th = y + h + b;
if(has("mask-image-css")){ // use -webkit-mask-image
var id = ("DojoMobileMask" + x + y + w + h + rx + ry).replace(/\./g, "_");
if (!cache[id]) {
cache[id] = 1;
var ctx = win.doc.getCSSCanvasContext("2d", id, tw, th);
ctx.beginPath();
if (rx == ry) {
// round arc
if(rx == 2 && w == 5){
// optimized case for vertical scrollbar
ctx.fillStyle = "rgba(0,0,0,0.5)";
ctx.fillRect(1, 0, 3, 2);
ctx.fillRect(0, 1, 5, 1);
ctx.fillRect(0, h - 2, 5, 1);
ctx.fillRect(1, h - 1, 3, 2);
ctx.fillStyle = "rgb(0,0,0)";
ctx.fillRect(0, 2, 5, h - 4);
}else if(rx == 2 && h == 5){
// optimized case for horizontal scrollbar
ctx.fillStyle = "rgba(0,0,0,0.5)";
ctx.fillRect(0, 1, 2, 3);
ctx.fillRect(1, 0, 1, 5);
ctx.fillRect(w - 2, 0, 1, 5);
ctx.fillRect(w - 1, 1, 2, 3);
ctx.fillStyle = "rgb(0,0,0)";
ctx.fillRect(2, 0, w - 4, 5);
}else{
// general case
ctx.fillStyle = "#000000";
ctx.moveTo(x+rx, y);
ctx.arcTo(x, y, x, y+rx, rx);
ctx.lineTo(x, y+h - rx);
ctx.arcTo(x, y+h, x+rx, y+h, rx);
ctx.lineTo(x+w - rx, y+h);
ctx.arcTo(x+w, y+h, x+w, y+rx, rx);
ctx.lineTo(x+w, y+rx);
ctx.arcTo(x+w, y, x+w - rx, y, rx);
}
} else {
// elliptical arc
var pi = Math.PI;
ctx.scale(1, ry / rx);
ctx.moveTo(x+rx, y);
ctx.arc(x+rx, y+rx, rx, 1.5 * pi, 0.5 * pi, true);
ctx.lineTo(x+w - rx, y+2 * rx);
ctx.arc(x+w - rx, y+rx, rx, 0.5 * pi, 1.5 * pi, true);
}
ctx.closePath();
ctx.fill();
}
node.style.webkitMaskImage = "-webkit-canvas(" + id + ")";
}else if(has("svg")){ // add an SVG image to clip the corners.
if(node._svgMask){
node.removeChild(node._svgMask);
}
var bg = null;
for(var p = node.parentNode; p; p = p.parentNode){
bg = domStyle.getComputedStyle(p).backgroundColor;
if(bg && bg != "transparent" && !bg.match(/rgba\(.*,\s*0\s*\)/)){
break;
}
}
var svgNS = "http://www.w3.org/2000/svg";
var svg = win.doc.createElementNS(svgNS, "svg");
svg.setAttribute("width", tw);
svg.setAttribute("height", th);
svg.style.position = "absolute";
svg.style.pointerEvents = "none";
svg.style.opacity = "1";
svg.style.zIndex = "2147483647"; // max int
var path = win.doc.createElementNS(svgNS, "path");
e = e || 0;
rx += e;
ry += e;
// TODO: optimized cases for scrollbars as in webkit case?
var d = " M" + (x + rx - e) + "," + (y - e) + " a" + rx + "," + ry + " 0 0,0 " + (-rx) + "," + ry + " v" + (-ry) + " h" + rx + " Z" +
" M" + (x - e) + "," + (y + h - ry + e) + " a" + rx + "," + ry + " 0 0,0 " + rx + "," + ry + " h" + (-rx) + " v" + (-ry) + " z" +
" M" + (x + w - rx + e) + "," + (y + h + e) + " a" + rx + "," + ry + " 0 0,0 " + rx + "," + (-ry) + " v" + ry + " h" + (-rx) + " z" +
" M" + (x + w + e) + "," + (y + ry - e) + " a" + rx + "," + ry + " 0 0,0 " + (-rx) + "," + (-ry) + " h" + rx + " v" + ry + " z";
if(y > 0){
d += " M0,0 h" + tw + " v" + y + " h" + (-tw) + " z";
}
if(b > 0){
d += " M0," + (y + h) + " h" + tw + " v" + b + " h" + (-tw) + " z";
}
path.setAttribute("d", d);
path.setAttribute("fill", bg);
path.setAttribute("stroke", bg);
path.style.opacity = "1";
svg.appendChild(path);
node._svgMask = svg;
node.appendChild(svg);
}
}
};
});
},
'dojox/mobile/parser':function(){
define([
"dojo/_base/kernel",
"dojo/_base/array",
"dojo/_base/config",
"dojo/_base/lang",
"dojo/_base/window",
"dojo/ready"
], function(dojo, array, config, lang, win, ready){
// module:
// dojox/mobile/parser
var dm = lang.getObject("dojox.mobile", true);
var Parser = function(){
// summary:
// A lightweight parser.
// description:
// dojox/mobile/parser is an extremely small subset of dojo/parser.
// It has no additional features over dojo/parser, so there is no
// benefit in terms of features by using dojox/mobile/parser instead
// of dojo/parser. However, if dojox/mobile/parser's capabilities are
// enough for your application, using it could reduce the total code size.
var _ctorMap = {};
var getCtor = function(type, mixins){
if(typeof(mixins) === "string"){
var t = type + ":" + mixins.replace(/ /g, "");
return _ctorMap[t] ||
(_ctorMap[t] = getCtor(type).createSubclass(array.map(mixins.split(/, */), getCtor)));
}
return _ctorMap[type] || (_ctorMap[type] = lang.getObject(type) || require(type));
};
var _eval = function(js){ return eval(js); };
this.instantiate = function(/* DomNode[] */nodes, /* Object? */mixin, /* Object? */options){
// summary:
// Function for instantiating a list of widget nodes.
// nodes:
// The list of DomNodes to walk and instantiate widgets on.
mixin = mixin || {};
options = options || {};
var i, ws = [];
if(nodes){
for(i = 0; i < nodes.length; i++){
var n = nodes[i],
type = n._type,
ctor = getCtor(type, n.getAttribute("data-dojo-mixins")),
proto = ctor.prototype,
params = {}, prop, v, t;
lang.mixin(params, _eval.call(options.propsThis, '({'+(n.getAttribute("data-dojo-props")||"")+'})'));
lang.mixin(params, options.defaults);
lang.mixin(params, mixin);
for(prop in proto){
v = n.getAttributeNode(prop);
v = v && v.nodeValue;
t = typeof proto[prop];
if(!v && (t !== "boolean" || v !== "")){ continue; }
if(lang.isArray(proto[prop])){
params[prop] = v.split(/\s*,\s*/);
}else if(t === "string"){
params[prop] = v;
}else if(t === "number"){
params[prop] = v - 0;
}else if(t === "boolean"){
params[prop] = (v !== "false");
}else if(t === "object"){
params[prop] = eval("(" + v + ")");
}else if(t === "function"){
params[prop] = lang.getObject(v, false) || new Function(v);
n.removeAttribute(prop);
}
}
params["class"] = n.className;
if(!params.style){ params.style = n.style.cssText; }
v = n.getAttribute("data-dojo-attach-point");
if(v){ params.dojoAttachPoint = v; }
v = n.getAttribute("data-dojo-attach-event");
if(v){ params.dojoAttachEvent = v; }
var instance = new ctor(params, n);
ws.push(instance);
var jsId = n.getAttribute("jsId") || n.getAttribute("data-dojo-id");
if(jsId){
lang.setObject(jsId, instance);
}
}
for(i = 0; i < ws.length; i++){
var w = ws[i];
!options.noStart && w.startup && !w._started && w.startup();
}
}
return ws;
};
this.parse = function(/* DomNode */ rootNode, /* Object? */ options){
// summary:
// Function to handle parsing for widgets in the current document.
// It is not as powerful as the full parser, but it will handle basic
// use cases fine.
// rootNode:
// The root node in the document to parse from
if(!rootNode){
rootNode = win.body();
}else if(!options && rootNode.rootNode){
// Case where 'rootNode' is really a params object.
options = rootNode;
rootNode = rootNode.rootNode;
}
var nodes = rootNode.getElementsByTagName("*");
var i, j, list = [];
for(i = 0; i < nodes.length; i++){
var n = nodes[i],
type = (n._type = n.getAttribute("dojoType") || n.getAttribute("data-dojo-type"));
if(type){
if(n._skip){
n._skip = "";
continue;
}
if(getCtor(type).prototype.stopParser && !(options && options.template)){
var arr = n.getElementsByTagName("*");
for(j = 0; j < arr.length; j++){
arr[j]._skip = "1";
}
}
list.push(n);
}
}
var mixin = options && options.template ? {template: true} : null;
return this.instantiate(list, mixin, options);
};
};
// Singleton. (TODO: replace parser class and singleton w/a simple hash of functions)
var parser = new Parser();
if(config.parseOnLoad){
ready(100, function(){
// Now that all the modules are loaded, check if the app loaded dojo/parser too.
// If it did, let dojo/parser handle the parseOnLoad flag instead of me.
try{
if(!require("dojo/parser")){
// IE6 takes this path when dojo/parser unavailable, rather than catch() block below,
// due to http://support.microsoft.com/kb/944397
parser.parse();
}
}catch(e){
// Other browsers (and later versions of IE) take this path when dojo/parser unavailable
parser.parse();
}
});
}
dm.parser = parser; // for backward compatibility
dojo.parser = dojo.parser || parser; // in case user application calls dojo.parser
return parser;
});
},
'dojox/mobile/compat':function(){
define([
"dojo/_base/lang",
"dojo/sniff"
], function(lang, has){
// module:
// dojox/mobile/compat
var dm = lang.getObject("dojox.mobile", true);
// TODO: Use feature detection instead, but this would require a major rewrite of _compat
// to detect each feature and plug the corresponding compat code if needed.
// Currently the compat code is a workaround for too many different things to be able to
// decide based on feature detection. So for now we just disable _compat on the mobile browsers
// that are known to support enough CSS3: all webkit-based browsers, IE10 (Windows [Phone] 8) and IE11+.
if(!(has("webkit") || has("ie") === 10) || (!has("ie") && has("trident") > 6)){
var s = "dojox/mobile/_compat"; // assign to a variable so as not to be picked up by the build tool
require([s]);
}
/*=====
return {
// summary:
// CSS3 compatibility module.
// description:
// This module provides to dojox/mobile support for some of the CSS3 features
// in non-CSS3 browsers, such as IE or Firefox.
// If you require this module, when running in a non-CSS3 browser it directly
// replaces some of the methods of dojox/mobile classes, without any subclassing.
// This way, HTML pages remain the same regardless of whether this compatibility
// module is used or not.
//
// Example of usage:
// | require([
// | "dojox/mobile",
// | "dojox/mobile/compat",
// | ...
// | ], function(...){
// | ...
// | });
//
// This module also loads compatibility CSS files, which have a -compat.css
// suffix. You can use either the `` tag or `@import` to load theme
// CSS files. Then, this module searches for the loaded CSS files and loads
// compatibility CSS files. For example, if you load dojox/mobile/themes/iphone/iphone.css
// in a page, this module automatically loads dojox/mobile/themes/iphone/iphone-compat.css.
// If you explicitly load iphone-compat.css with `` or `@import`,
// this module will not load again the already loaded file.
//
// Note that, by default, compatibility CSS files are only loaded for CSS files located
// in a directory containing a "mobile/themes" path. For that, a matching is done using
// the default pattern "/\/mobile\/themes\/.*\.css$/". If a custom theme is not located
// in a directory containing this path, the data-dojo-config needs to specify a custom
// pattern using the "mblLoadCompatPattern" configuration parameter, for instance:
// | data-dojo-config="mblLoadCompatPattern: /\/mycustomtheme\/.*\.css$/"
};
=====*/
return dm;
});
},
'dojox/mobile/deviceTheme':function(){
(typeof define === "undefined" ? function(deps, def) { def(); } : define)([
"dojo/_base/config",
"dojo/_base/lang",
"dojo/_base/window",
"require"
], function(config, lang, win, require){
// module:
// dojox/mobile/deviceTheme
var dm = lang && lang.getObject("dojox.mobile", true) || {};
var DeviceTheme = function(){
// summary:
// Automatic theme loader.
// description:
// This module detects the user agent of the browser and loads the
// appropriate theme files. It can be enabled by simply including
// the dojox/mobile/deviceTheme script in your application as follows:
//
// |
// |
//
// Using the script tag as above is the recommended way to load the
// deviceTheme. Trying to load it using the AMD loader can lead to styles
// being applied too late, because the loading of the theme files would
// be performed asynchronously by the browser, so you could not assume
// that the loading has been completed when your widgets are initialized.
// However, loading deviceTheme using the script tag has the drawback that
// deviceTheme.js cannot be included in a build.
//
// You can also pass an additional query parameter string:
// theme={theme id} to force a specific theme through the browser
// URL input. The available theme ids are Android, Holodark (theme introduced in Android 3.0),
// BlackBerry, Custom, iPhone, and iPad. The theme names are case-sensitive. If the given
// id does not match, the iOS7 theme is used.
//
// | http://your.server.com/yourapp.html // automatic detection
// | http://your.server.com/yourapp.html?theme=Android // forces Android theme
// | http://your.server.com/yourapp.html?theme=Holodark // forces Holodark theme
// | http://your.server.com/yourapp.html?theme=BlackBerry // forces Blackberry theme
// | http://your.server.com/yourapp.html?theme=Custom // forces Custom theme
// | http://your.server.com/yourapp.html?theme=iPhone // forces iPhone theme
// | http://your.server.com/yourapp.html?theme=iPad // forces iPad theme
// | http://your.server.com/yourapp.html?theme=ios7 // forces iOS 7 theme
//
// To simulate a particular device from the application code, the user agent
// can be forced by setting dojoConfig.mblUserAgent as follows:
//
// |
// |
//
// By default, an all-in-one theme file (e.g. themes/ios7/ios7.css) is
// loaded. The all-in-one theme files contain style sheets for all the
// dojox/mobile widgets regardless of whether they are used in your
// application or not.
//
// If you want to choose what theme files to load, you can specify them
// via dojoConfig or data-dojo-config as shown in the following example:
//
// |
// |
//
// In the case of this example, if iphone is detected, for example, the
// following files will be loaded:
//
// | dojox/mobile/themes/ios7/base.css
// | dojox/mobile/themes/ios7/Button.css
//
// If you want to load style sheets for your own custom widgets, you can
// specify a package name along with a theme file name in an array.
//
// | ['base',['com.acme','MyWidget']]
//
// In this case, the following files will be loaded.
//
// | dojox/mobile/themes/ios7/base.css
// | com/acme/themes/ios7/MyWidget.css
//
// If you specify '@theme' as a theme file name, it will be replaced with
// the theme folder name (e.g. 'ios7'). For example,
//
// | ['@theme',['com.acme','MyWidget']]
//
// will load the following files:
//
// | dojox/mobile/themes/ios7/ios7.css
// | com/acme/themes/ios7/MyWidget.css
if(!win){
win = window;
win.doc = document;
win._no_dojo_dm = dm;
}
config = config || win.mblConfig || {};
var scripts = win.doc.getElementsByTagName("script");
for(var i = 0; i < scripts.length; i++){
var n = scripts[i];
var src = n.getAttribute("src") || "";
if(src.match(/\/deviceTheme\.js/i)){
config.baseUrl = src.replace("deviceTheme\.js", "../../dojo/");
var conf = (n.getAttribute("data-dojo-config") || n.getAttribute("djConfig"));
if(conf){
var obj = eval("({ " + conf + " })");
for(var key in obj){
config[key] = obj[key];
}
}
break;
}else if(src.match(/\/dojo\.js/i)){
config.baseUrl = src.replace("dojo\.js", "");
break;
}
}
this.loadCssFile = function(/*String*/file){
// summary:
// Loads the given CSS file programmatically.
var link = win.doc.createElement("link");
link.href = file;
link.type = "text/css";
link.rel = "stylesheet";
var head = win.doc.getElementsByTagName('head')[0];
head.insertBefore(link, head.firstChild);
dm.loadedCssFiles.push(link);
};
this.toUrl = function(/*String*/path){
// summary:
// A wrapper for require.toUrl to support non-dojo usage.
return require ? require.toUrl(path) : config.baseUrl + "../" + path;
};
this.setDm = function(/*Object*/_dm){
// summary:
// Replaces the dojox/mobile object.
// description:
// When this module is loaded from a script tag, dm is a plain
// local object defined at the beginning of this module.
// common.js will replace the local dm object with the
// real dojox/mobile object through this method.
dm = _dm;
};
this.themeMap = config.themeMap || [
// summary:
// A map of user-agents to theme files.
// description:
// The first array element is a regexp pattern that matches the
// userAgent string.
//
// The second array element is a theme folder name.
//
// The third array element is an array of css file paths to load.
//
// The matching is performed in the array order, and stops after the
// first match.
[
"Holodark",
"holodark",
[]
],
[
"Android [3-9]",
"holodark",
[]
],
[
"Android",
"android",
[]
],
[
"BlackBerry",
"blackberry",
[]
],
[
"BB10",
"blackberry",
[]
],
[
"ios7",
"ios7",
[]
],
[
"iPhone;.*OS ([7-9]|1[0-9])_",
"ios7",
[]
],
[
"iPad;.*OS ([7-9]|1[0-9])_",
"ios7",
[]
],
[
"iPhone",
"iphone",
[]
],
[
"iPad",
"iphone",
[this.toUrl("dojox/mobile/themes/iphone/ipad.css")]
],
[
"WindowsPhone",
"windows",
[]
],
[
"Windows Phone",
"windows",
[]
],
[
"Trident",
"ios7",
[]
],
[
"Custom",
"custom",
[]
],
[
".*",
"ios7",
[]
]
];
dm.loadedCssFiles = [];
this.loadDeviceTheme = function(/*String?*/userAgent){
// summary:
// Loads a device-specific theme according to the user-agent
// string.
// description:
// This function is automatically called when this module is
// evaluated.
var t = config.mblThemeFiles || dm.themeFiles || ["@theme"];
var i, j;
var m = this.themeMap;
var ua = userAgent || config.mblUserAgent || (location.search.match(/theme=(\w+)/) ? RegExp.$1 : navigator.userAgent);
for(i = 0; i < m.length; i++){
if(ua.match(new RegExp(m[i][0]))){
var theme = m[i][1];
if(theme == "windows" && config.mblDisableWindowsTheme){
continue;
}
var cls = win.doc.documentElement.className;
cls = cls.replace(new RegExp(" *" + dm.currentTheme + "_theme"), "") + " " + theme + "_theme";
win.doc.documentElement.className = cls;
dm.currentTheme = theme;
var files = [].concat(m[i][2]);
for(j = 0; j < t.length; j++){
var isArray = (t[j] instanceof Array || typeof t[j] == "array");
var path;
if(!isArray && t[j].indexOf('/') !== -1){
path = t[j];
}else{
var pkg = isArray ? (t[j][0]||"").replace(/\./g, '/') : "dojox/mobile";
var name = (isArray ? t[j][1] : t[j]).replace(/\./g, '/');
var f = "themes/" + theme + "/" +
(name === "@theme" ? theme : name) + ".css";
path = pkg + "/" + f;
}
files.unshift(this.toUrl(path));
}
//remove old css files
for(var k = 0; k < dm.loadedCssFiles.length; k++){
var n = dm.loadedCssFiles[k];
n.parentNode.removeChild(n);
}
dm.loadedCssFiles = [];
for(j = 0; j < files.length; j++){
// dojox.mobile mirroring support
var cssFilePath = files[j].toString();
if(config["dojo-bidi"] == true && cssFilePath.indexOf("_rtl") == -1){
var rtlCssList = "android.css blackberry.css custom.css iphone.css holodark.css base.css Carousel.css ComboBox.css IconContainer.css IconMenu.css ListItem.css RoundRectCategory.css SpinWheel.css Switch.css TabBar.css ToggleButton.css ToolBarButton.css ProgressIndicator.css Accordion.css GridLayout.css FormLayout.css";
var cssName = cssFilePath.substr(cssFilePath.lastIndexOf('/') + 1);
if(rtlCssList.indexOf(cssName) != -1){
this.loadCssFile(cssFilePath.replace(".css","_rtl.css"));
}
}
this.loadCssFile(files[j].toString());
}
if(userAgent && dm.loadCompatCssFiles){
dm.loadCompatCssFiles();
}
break;
}
}
};
};
// Singleton. (TODO: can we replace DeviceTheme class and singleton w/a simple hash of functions?)
var deviceTheme = new DeviceTheme();
deviceTheme.loadDeviceTheme();
window.deviceTheme = dm.deviceTheme = deviceTheme;
return deviceTheme;
});
},
'dojox/dgauges/components/default/CircularLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../utils",
"../../CircularGauge",
"../../LinearScaler",
"../../CircularScale",
"../../CircularValueIndicator",
"../../TextIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, utils, CircularGauge, LinearScaler, CircularScale, CircularValueIndicator, TextIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.default.CircularLinearGauge", [CircularGauge, DefaultPropertiesMixin], {
// summary:
// A circular gauge widget.
// _radius: Number
_radius: 100,
// borderColor: Object|Array|int
// The border color. Default is "#C9DFF2".
borderColor: "#C9DFF2",
// fillColor: Object|Array|int
// The background color. Default is "#FCFCFF".
fillColor: "#FCFCFF",
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#F01E28".
indicatorColor: "#F01E28",
constructor: function(){
// Base colors
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
// Draw background
this.addElement("background", lang.hitch(this, this.drawBackground));
// Scaler
var scaler = new LinearScaler();
// Scale
var scale = new CircularScale();
scale.set("scaler", scaler);
this.addElement("scale", scale);
// Value indicator
var indicator = new CircularValueIndicator();
scale.addIndicator("indicator", indicator);
// Gauge Foreground (needle cap)
this.addElement("foreground", lang.hitch(this, this.drawForeground));
// Indicator Text
var indicatorText = new TextIndicator();
indicatorText.set("indicator", indicator);
indicatorText.set("x", 100);
indicatorText.set("y", 150);
this.addElement("indicatorText", indicatorText);
utils.genericCircularGauge(scale, indicator, this._radius, this._radius, 0.65 * this._radius, 130, 50, null, null, "outside");
},
drawBackground: function(g){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// tags:
// protected
var r = this._radius;
var w = 2 * r;
var h = w;
var entries = utils.createGradient([0, utils.brightness(this.borderColor, 70), 1, utils.brightness(this.borderColor, -40)]);
g.createEllipse({
cx: r,
cy: r,
rx: r,
ry: r
}).setFill(lang.mixin({
type: "linear",
x1: w,
y1: 0,
x2: 0,
y2: h
}, entries)).setStroke({
color: "#A5A5A5",
width: 0.2
});
entries = utils.createGradient([0, utils.brightness(this.borderColor, 70), 1, utils.brightness(this.borderColor, -50)]);
g.createEllipse({
cx: r,
cy: r,
rx: r * 0.99,
ry: r * 0.99
}).setFill(lang.mixin({
type: "linear",
x1: 0,
y1: 0,
x2: w,
y2: h
}, entries));
entries = utils.createGradient([0, utils.brightness(this.borderColor, 60), 1, utils.brightness(this.borderColor, -40)]);
g.createEllipse({
cx: r,
cy: r,
rx: r * 0.92,
ry: r * 0.92
}).setFill(lang.mixin({
type: "linear",
x1: 0,
y1: 0,
x2: w,
y2: h
}, entries));
entries = utils.createGradient([0, utils.brightness(this.borderColor, 70), 1, utils.brightness(this.borderColor, -40)]);
g.createEllipse({
cx: r,
cy: r,
rx: r * 0.9,
ry: r * 0.9
}).setFill(lang.mixin({
type: "linear",
x1: w,
y1: 0,
x2: 0,
y2: h
}, entries));
entries = utils.createGradient([0, [255, 255, 255, 220], 0.8, utils.brightness(this.fillColor, -5), 1, utils.brightness(this.fillColor, -30)]);
g.createEllipse({
cx: r,
cy: r,
rx: r * 0.9,
ry: r * 0.9
}).setFill(lang.mixin({
type: "radial",
cx: r,
cy: r,
r: r
}, entries)).setStroke({
color: utils.brightness(this.fillColor, -40),
width: 0.4
});
},
drawForeground: function(g){
// summary:
// Draws the foreground shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the foreground.
// tags:
// protected
var r = 0.07 * this._radius;
var entries = utils.createGradient([0, this.borderColor, 1, utils.brightness(this.borderColor, -20)]);
g.createEllipse({
cx: this._radius,
cy: this._radius,
rx: r,
ry: r
}).setFill(lang.mixin({
type: "radial",
cx: 0.96 * this._radius,
cy: 0.96 * this._radius,
r: r
}, entries)).setStroke({
color: utils.brightness(this.fillColor, -50),
width: 0.4
});
}
});
});
},
'dojox/dgauges/components/utils':function(){
define(["dojo/_base/lang", "dojo/_base/Color"], function(lang, Color){
// module:
// dojox/dgauges/components/utils
// summary:
// Gauge utilities.
// tags:
// public
var utils = {};
lang.mixin(utils, {
brightness: function(col, b){
// summary:
// Adjusts the brightness of a color.
// col: Number
// The base color
// b: Number
// A positive or negative value to adjust the brightness
// returns: Number
// The modified color
var res = lang.mixin(null, col);
res.r = Math.max(Math.min(res.r + b, 255), 0);
res.g = Math.max(Math.min(res.g + b, 255), 0);
res.b = Math.max(Math.min(res.b + b, 255), 0);
return res;
},
createGradient: function(entries){
// summary:
// Creates a gradient object
// entries: Array
// An array of numbers representing colors
// returns: Number
// The modified color
var res = {
colors: []
};
var obj;
for(var i = 0; i < entries.length; i++){
if(i % 2 == 0){
obj = {
offset: entries[i]
};
} else {
obj.color = entries[i];
res.colors.push(obj);
}
}
return res;
},
_setter: function(obj, attributes, values){
for(var i = 0; i < attributes.length; i++){
obj[attributes[i]] = values[i];
}
},
genericCircularGauge: function(scale, indicator, originX, originY, radius, startAngle, endAngle, orientation, font, labelPosition, tickShapeFunc){
// summary:
// A helper method for configuring a circular gauge.
// scale: CircularScale
// A circular scale
// indicator: IndicatorBase
// A circular indicator
// originX: Number
// The x-coordinate of the center of the scale (in pixels)
// originY: Number
// The y-coordinate of the center of the scale (in pixels)
// radius: Number
// The radius of the scale (in pixels)
// startAngle: Number
// The start angle of the scale (in degrees)
// endAngle: Number
// The end angle of the scale (in degrees)
// orientation: String?
// The orientation of the scale, can be "clockwise" or "cclockwise"
// font: Object?
// The font used for the gauge
// labelPosition: String?
// The position of the labels regarding
// tickShapeFunc: Object?
// A drawing function for the ticks
// returns: Number
// The modified color
var attributes = ["originX", "originY", "radius", "startAngle", "endAngle", "orientation", "font", "labelPosition", "tickShapeFunc"];
if(!orientation){
orientation = "clockwise";
}
if(!font){
font = {
family: "Helvetica",
style: "normal",
size: "10pt",
color: "#555555"
};
}
if(!labelPosition){
labelPosition = "inside";
}
if(!tickShapeFunc){
tickShapeFunc = function(group, scale, tick){
var stroke = scale.tickStroke;
var majorStroke;
var minorStroke;
if(stroke){
majorStroke = {color:stroke.color ? stroke.color : "#000000", width:stroke.width ? stroke.width : 0.5};
var col = new Color(stroke.color).toRgb();
minorStroke = {color:stroke.color ? utils.brightness({r:col[0], g:col[1], b:col[2]},51) : "#000000", width:stroke.width ? stroke.width * 0.6 : 0.3};
}
return group.createLine({
x1: tick.isMinor ? 2 : 0,
y1: 0,
x2: tick.isMinor ? 8 : 10,
y2: 0
}).setStroke(tick.isMinor ? minorStroke : majorStroke);
};
}
this._setter(scale, attributes, [originX, originY, radius, startAngle, endAngle, orientation, font, labelPosition, tickShapeFunc]);
indicator.set("interactionArea", "gauge");
// Needle shape
indicator.set("indicatorShapeFunc", function(group, indicator){
return group.createPolyline([0, -5, indicator.scale.radius - 6, 0, 0, 5, 0, -5]).setStroke({
color: "#333333",
width: 0.25
}).setFill(scale._gauge.indicatorColor);
});
}
});
return utils;
});
},
'dojox/dgauges/CircularGauge':function(){
define(["dojo/_base/declare", "dojo/dom-geometry", "dojox/gfx", "./GaugeBase"], function(declare, domGeom, gfx, GaugeBase){
return declare("dojox.dgauges.CircularGauge", GaugeBase, {
// summary:
// The base class for circular gauges.
// You can create custom circular or semi-circular gauges by extending this class.
// See dojox.dgauges.components.default.CircularLinearGauge.js for an example of circular gauge.
_transformProperties: null,
refreshRendering: function(){
if(this._widgetBox.w <= 0 || this._widgetBox.h <= 0){
return;
}
for(var key in this._elementsIndex){
this._elementsRenderers[key] = this._elementsIndex[key].refreshRendering();
}
// Maximize the drawing area and center the gauge
var bb = this._computeBoundingBox(this._gfxGroup);
var naturalRatio = (bb.x + bb.width) / (bb.y + bb.height);
var widgetWidth = this._widgetBox.w;
var widgetHeight = this._widgetBox.h;
var widgetRatio = this._widgetBox.w / this._widgetBox.h;
var xpos = 0;
var ypos = 0;
var h = 0;
var w = 0;
if(naturalRatio > widgetRatio){
w = widgetWidth;
h = w / naturalRatio;
ypos = (widgetHeight - h) / 2;
}else{
h = widgetHeight;
w = h * naturalRatio;
xpos = (widgetWidth - w) / 2;
}
var scaleFactor = Math.max(w / (bb.x + bb.width), h / (bb.y + bb.height));
this._transformProperties = {scale:scaleFactor, tx:xpos, ty:ypos};
this._gfxGroup.setTransform([gfx.matrix.scale(scaleFactor), gfx.matrix.translate(xpos / scaleFactor, ypos / scaleFactor)]);
},
_gaugeToPage: function(px, py){
// summary:
// Internal method.
// tags:
// private
if(this._transformProperties){
var np = domGeom.position(this.domNode, true);
return {x: np.x + px * this._transformProperties.scale + this._transformProperties.tx, y: np.y + py * this._transformProperties.scale + this._transformProperties.ty};
}else{
return null;
}
}
});
});
},
'dojox/gfx':function(){
define(["dojo/_base/lang", "./gfx/_base", "./gfx/renderer!"],
function(lang, gfxBase, renderer){
// module:
// dojox/gfx
// summary:
// This the root of the Dojo Graphics package
gfxBase.switchTo(renderer);
return gfxBase;
});
},
'dojox/gfx/_base':function(){
define(["dojo/_base/kernel", "dojo/_base/lang", "dojo/_base/Color", "dojo/_base/sniff", "dojo/_base/window",
"dojo/_base/array","dojo/dom", "dojo/dom-construct","dojo/dom-geometry"],
function(kernel, lang, Color, has, win, arr, dom, domConstruct, domGeom){
// module:
// dojox/gfx
// summary:
// This module contains common core Graphics API used by different graphics renderers.
var g = lang.getObject("dojox.gfx", true),
b = g._base = {};
// candidates for dojox.style (work on VML and SVG nodes)
g._hasClass = function(/*DomNode*/node, /*String*/classStr){
// summary:
// Returns whether or not the specified classes are a portion of the
// class list currently applied to the node.
// return (new RegExp('(^|\\s+)'+classStr+'(\\s+|$)')).test(node.className) // Boolean
var cls = node.getAttribute("className");
return cls && (" " + cls + " ").indexOf(" " + classStr + " ") >= 0; // Boolean
};
g._addClass = function(/*DomNode*/node, /*String*/classStr){
// summary:
// Adds the specified classes to the end of the class list on the
// passed node.
var cls = node.getAttribute("className") || "";
if(!cls || (" " + cls + " ").indexOf(" " + classStr + " ") < 0){
node.setAttribute("className", cls + (cls ? " " : "") + classStr);
}
};
g._removeClass = function(/*DomNode*/node, /*String*/classStr){
// summary:
// Removes classes from node.
var cls = node.getAttribute("className");
if(cls){
node.setAttribute(
"className",
cls.replace(new RegExp('(^|\\s+)' + classStr + '(\\s+|$)'), "$1$2")
);
}
};
// candidate for dojox.html.metrics (dynamic font resize handler is not implemented here)
// derived from Morris John's emResized measurer
b._getFontMeasurements = function(){
// summary:
// Returns an object that has pixel equivilents of standard font
// size values.
var heights = {
'1em': 0, '1ex': 0, '100%': 0, '12pt': 0, '16px': 0, 'xx-small': 0,
'x-small': 0, 'small': 0, 'medium': 0, 'large': 0, 'x-large': 0,
'xx-large': 0
};
var p, oldStyle;
if(has("ie")){
// We do a font-size fix if and only if one isn't applied already.
// NOTE: If someone set the fontSize on the HTML Element, this will kill it.
oldStyle = win.doc.documentElement.style.fontSize || "";
if(!oldStyle){
win.doc.documentElement.style.fontSize="100%";
}
}
// set up the measuring node.
var div = domConstruct.create("div", {style: {
position: "absolute",
left: "0",
top: "-100px",
width: "30px",
height: "1000em",
borderWidth: "0",
margin: "0",
padding: "0",
outline: "none",
lineHeight: "1",
overflow: "hidden"
}}, win.body());
// do the measurements.
for(p in heights){
div.style.fontSize = p;
heights[p] = Math.round(div.offsetHeight * 12/16) * 16/12 / 1000;
}
if(has("ie")){
// Restore the font to its old style.
win.doc.documentElement.style.fontSize = oldStyle;
}
win.body().removeChild(div);
return heights; //object
};
var fontMeasurements = null;
b._getCachedFontMeasurements = function(recalculate){
if(recalculate || !fontMeasurements){
fontMeasurements = b._getFontMeasurements();
}
return fontMeasurements;
};
// candidate for dojox.html.metrics
var measuringNode = null, empty = {};
b._getTextBox = function( /*String*/ text,
/*Object*/ style,
/*String?*/ className){
var m, s, al = arguments.length;
var i, box;
if(!measuringNode){
measuringNode = domConstruct.create("div", {style: {
position: "absolute",
top: "-10000px",
left: "0",
visibility: "hidden"
}}, win.body());
}
m = measuringNode;
// reset styles
m.className = "";
s = m.style;
s.borderWidth = "0";
s.margin = "0";
s.padding = "0";
s.outline = "0";
// set new style
if(al > 1 && style){
for(i in style){
if(i in empty){ continue; }
s[i] = style[i];
}
}
// set classes
if(al > 2 && className){
m.className = className;
}
// take a measure
m.innerHTML = text;
if(m.getBoundingClientRect){
var bcr = m.getBoundingClientRect();
box = {l: bcr.left, t: bcr.top, w: bcr.width || (bcr.right - bcr.left), h: bcr.height || (bcr.bottom - bcr.top)};
}else{
box = domGeom.getMarginBox(m);
}
m.innerHTML = "";
return box;
};
b._computeTextLocation = function(/*g.defaultTextShape*/textShape, /*Number*/width, /*Number*/height, /*Boolean*/fixHeight) {
var loc = {}, align = textShape.align;
switch (align) {
case 'end':
loc.x = textShape.x - width;
break;
case 'middle':
loc.x = textShape.x - width / 2;
break;
default:
loc.x = textShape.x;
break;
}
var c = fixHeight ? 0.75 : 1;
loc.y = textShape.y - height*c; // **rough** approximation of the ascent...
return loc;
};
b._computeTextBoundingBox = function(/*shape.Text*/s){
// summary:
// Compute the bbox of the given shape.Text instance. Note that this method returns an
// approximation of the bbox, and should be used when the underlying renderer cannot provide precise metrics.
if(!g._base._isRendered(s)){
return {x:0, y:0, width:0, height:0};
}
var loc, textShape = s.getShape(),
font = s.getFont() || g.defaultFont,
w = s.getTextWidth(),
h = g.normalizedLength(font.size);
loc = b._computeTextLocation(textShape, w, h, true);
return {
x: loc.x,
y: loc.y,
width: w,
height: h
};
};
b._isRendered = function(/*Shape*/s){
var p = s.parent;
while(p && p.getParent){
p = p.parent;
}
return p !== null;
};
// candidate for dojo.dom
var uniqueId = 0;
b._getUniqueId = function(){
// summary:
// returns a unique string for use with any DOM element
var id;
do{
id = kernel._scopeName + "xUnique" + (++uniqueId);
}while(dom.byId(id));
return id;
};
// IE10
var touchActionProp = has("pointer-events") ? "touchAction" : has("MSPointer") ? "msTouchAction" : null;
b._fixMsTouchAction = touchActionProp ? function(/*dojox/gfx/shape.Surface*/surface){
surface.rawNode.style[touchActionProp] = "none";
} : function() {};
/*=====
g.Stroke = {
// summary:
// A stroke defines stylistic properties that are used when drawing a path.
// color: String
// The color of the stroke, default value 'black'.
color: "black",
// style: String
// The style of the stroke, one of 'solid', ... . Default value 'solid'.
style: "solid",
// width: Number
// The width of a stroke, default value 1.
width: 1,
// cap: String
// The endcap style of the path. One of 'butt', 'round', ... . Default value 'butt'.
cap: "butt",
// join: Number
// The join style to use when combining path segments. Default value 4.
join: 4
};
g.Fill = {
// summary:
// Defines how to fill a shape. Four types of fills can be used: solid, linear gradient, radial gradient and pattern.
// See dojox/gfx.LinearGradient, dojox/gfx.RadialGradient and dojox/gfx.Pattern respectively for more information about the properties supported by each type.
// type: String?
// The type of fill. One of 'linear', 'radial', 'pattern' or undefined. If not specified, a solid fill is assumed.
type:"",
// color: String|dojo/Color?
// The color of a solid fill type.
color:null,
};
g.LinearGradient = {
// summary:
// An object defining the default stylistic properties used for Linear Gradient fills.
// Linear gradients are drawn along a virtual line, which results in appearance of a rotated pattern in a given direction/orientation.
// type: String
// Specifies this object is a Linear Gradient, value 'linear'
type: "linear",
// x1: Number
// The X coordinate of the start of the virtual line along which the gradient is drawn, default value 0.
x1: 0,
// y1: Number
// The Y coordinate of the start of the virtual line along which the gradient is drawn, default value 0.
y1: 0,
// x2: Number
// The X coordinate of the end of the virtual line along which the gradient is drawn, default value 100.
x2: 100,
// y2: Number
// The Y coordinate of the end of the virtual line along which the gradient is drawn, default value 100.
y2: 100,
// colors: Array
// An array of colors at given offsets (from the start of the line). The start of the line is
// defined at offest 0 with the end of the line at offset 1.
// Default value, [{ offset: 0, color: 'black'},{offset: 1, color: 'white'}], is a gradient from black to white.
colors: []
};
g.RadialGradient = {
// summary:
// Specifies the properties for RadialGradients using in fills patterns.
// type: String
// Specifies this is a RadialGradient, value 'radial'
type: "radial",
// cx: Number
// The X coordinate of the center of the radial gradient, default value 0.
cx: 0,
// cy: Number
// The Y coordinate of the center of the radial gradient, default value 0.
cy: 0,
// r: Number
// The radius to the end of the radial gradient, default value 100.
r: 100,
// colors: Array
// An array of colors at given offsets (from the center of the radial gradient).
// The center is defined at offest 0 with the outer edge of the gradient at offset 1.
// Default value, [{ offset: 0, color: 'black'},{offset: 1, color: 'white'}], is a gradient from black to white.
colors: []
};
g.Pattern = {
// summary:
// An object specifying the default properties for a Pattern using in fill operations.
// type: String
// Specifies this object is a Pattern, value 'pattern'.
type: "pattern",
// x: Number
// The X coordinate of the position of the pattern, default value is 0.
x: 0,
// y: Number
// The Y coordinate of the position of the pattern, default value is 0.
y: 0,
// width: Number
// The width of the pattern image, default value is 0.
width: 0,
// height: Number
// The height of the pattern image, default value is 0.
height: 0,
// src: String
// A url specifying the image to use for the pattern.
src: ""
};
g.Text = {
// summary:
// A keyword argument object defining both the text to be rendered in a VectorText shape,
// and specifying position, alignment, and fitting.
// text: String
// The text to be rendered.
// x: Number?
// The left coordinate for the text's bounding box.
// y: Number?
// The top coordinate for the text's bounding box.
// width: Number?
// The width of the text's bounding box.
// height: Number?
// The height of the text's bounding box.
// align: String?
// The alignment of the text, as defined in SVG. Can be "start", "end" or "middle".
// fitting: Number?
// How the text is to be fitted to the bounding box. Can be 0 (no fitting), 1 (fitting based on
// passed width of the bounding box and the size of the font), or 2 (fit text to the bounding box,
// and ignore any size parameters).
// leading: Number?
// The leading to be used between lines in the text.
// decoration: String?
// Any text decoration to be used.
};
g.Font = {
// summary:
// An object specifying the properties for a Font used in text operations.
// type: String
// Specifies this object is a Font, value 'font'.
type: "font",
// style: String
// The font style, one of 'normal', 'bold', default value 'normal'.
style: "normal",
// variant: String
// The font variant, one of 'normal', ... , default value 'normal'.
variant: "normal",
// weight: String
// The font weight, one of 'normal', ..., default value 'normal'.
weight: "normal",
// size: String
// The font size (including units), default value '10pt'.
size: "10pt",
// family: String
// The font family, one of 'serif', 'sanserif', ..., default value 'serif'.
family: "serif"
};
=====*/
lang.mixin(g, {
// summary:
// defines constants, prototypes, and utility functions for the core Graphics API
// default shapes, which are used to fill in missing parameters
defaultPath: {
// summary:
// Defines the default Path prototype object.
// type: String
// Specifies this object is a Path, default value 'path'.
type: "path",
// path: String
// The path commands. See W32C SVG 1.0 specification.
// Defaults to empty string value.
path: ""
},
defaultPolyline: {
// summary:
// Defines the default PolyLine prototype.
// type: String
// Specifies this object is a PolyLine, default value 'polyline'.
type: "polyline",
// points: Array
// An array of point objects [{x:0,y:0},...] defining the default polyline's line segments. Value is an empty array [].
points: []
},
defaultRect: {
// summary:
// Defines the default Rect prototype.
// type: String
// Specifies this default object is a type of Rect. Value is 'rect'
type: "rect",
// x: Number
// The X coordinate of the default rectangles position, value 0.
x: 0,
// y: Number
// The Y coordinate of the default rectangle's position, value 0.
y: 0,
// width: Number
// The width of the default rectangle, value 100.
width: 100,
// height: Number
// The height of the default rectangle, value 100.
height: 100,
// r: Number
// The corner radius for the default rectangle, value 0.
r: 0
},
defaultEllipse: {
// summary:
// Defines the default Ellipse prototype.
// type: String
// Specifies that this object is a type of Ellipse, value is 'ellipse'
type: "ellipse",
// cx: Number
// The X coordinate of the center of the ellipse, default value 0.
cx: 0,
// cy: Number
// The Y coordinate of the center of the ellipse, default value 0.
cy: 0,
// rx: Number
// The radius of the ellipse in the X direction, default value 200.
rx: 200,
// ry: Number
// The radius of the ellipse in the Y direction, default value 200.
ry: 100
},
defaultCircle: {
// summary:
// An object defining the default Circle prototype.
// type: String
// Specifies this object is a circle, value 'circle'
type: "circle",
// cx: Number
// The X coordinate of the center of the circle, default value 0.
cx: 0,
// cy: Number
// The Y coordinate of the center of the circle, default value 0.
cy: 0,
// r: Number
// The radius, default value 100.
r: 100
},
defaultLine: {
// summary:
// An object defining the default Line prototype.
// type: String
// Specifies this is a Line, value 'line'
type: "line",
// x1: Number
// The X coordinate of the start of the line, default value 0.
x1: 0,
// y1: Number
// The Y coordinate of the start of the line, default value 0.
y1: 0,
// x2: Number
// The X coordinate of the end of the line, default value 100.
x2: 100,
// y2: Number
// The Y coordinate of the end of the line, default value 100.
y2: 100
},
defaultImage: {
// summary:
// Defines the default Image prototype.
// type: String
// Specifies this object is an image, value 'image'.
type: "image",
// x: Number
// The X coordinate of the image's position, default value 0.
x: 0,
// y: Number
// The Y coordinate of the image's position, default value 0.
y: 0,
// width: Number
// The width of the image, default value 0.
width: 0,
// height: Number
// The height of the image, default value 0.
height: 0,
// src: String
// The src url of the image, defaults to empty string.
src: ""
},
defaultText: {
// summary:
// Defines the default Text prototype.
// type: String
// Specifies this is a Text shape, value 'text'.
type: "text",
// x: Number
// The X coordinate of the text position, default value 0.
x: 0,
// y: Number
// The Y coordinate of the text position, default value 0.
y: 0,
// text: String
// The text to be displayed, default value empty string.
text: "",
// align: String
// The horizontal text alignment, one of 'start', 'end', 'center'. Default value 'start'.
align: "start",
// decoration: String
// The text decoration , one of 'none', ... . Default value 'none'.
decoration: "none",
// rotated: Boolean
// Whether the text is rotated, boolean default value false.
rotated: false,
// kerning: Boolean
// Whether kerning is used on the text, boolean default value true.
kerning: true
},
defaultTextPath: {
// summary:
// Defines the default TextPath prototype.
// type: String
// Specifies this is a TextPath, value 'textpath'.
type: "textpath",
// text: String
// The text to be displayed, default value empty string.
text: "",
// align: String
// The horizontal text alignment, one of 'start', 'end', 'center'. Default value 'start'.
align: "start",
// decoration: String
// The text decoration , one of 'none', ... . Default value 'none'.
decoration: "none",
// rotated: Boolean
// Whether the text is rotated, boolean default value false.
rotated: false,
// kerning: Boolean
// Whether kerning is used on the text, boolean default value true.
kerning: true
},
// default stylistic attributes
defaultStroke: {
// summary:
// A stroke defines stylistic properties that are used when drawing a path.
// This object defines the default Stroke prototype.
// type: String
// Specifies this object is a type of Stroke, value 'stroke'.
type: "stroke",
// color: String
// The color of the stroke, default value 'black'.
color: "black",
// style: String
// The style of the stroke, one of 'solid', ... . Default value 'solid'.
style: "solid",
// width: Number
// The width of a stroke, default value 1.
width: 1,
// cap: String
// The endcap style of the path. One of 'butt', 'round', ... . Default value 'butt'.
cap: "butt",
// join: Number
// The join style to use when combining path segments. Default value 4.
join: 4
},
defaultLinearGradient: {
// summary:
// An object defining the default stylistic properties used for Linear Gradient fills.
// Linear gradients are drawn along a virtual line, which results in appearance of a rotated pattern in a given direction/orientation.
// type: String
// Specifies this object is a Linear Gradient, value 'linear'
type: "linear",
// x1: Number
// The X coordinate of the start of the virtual line along which the gradient is drawn, default value 0.
x1: 0,
// y1: Number
// The Y coordinate of the start of the virtual line along which the gradient is drawn, default value 0.
y1: 0,
// x2: Number
// The X coordinate of the end of the virtual line along which the gradient is drawn, default value 100.
x2: 100,
// y2: Number
// The Y coordinate of the end of the virtual line along which the gradient is drawn, default value 100.
y2: 100,
// colors: Array
// An array of colors at given offsets (from the start of the line). The start of the line is
// defined at offest 0 with the end of the line at offset 1.
// Default value, [{ offset: 0, color: 'black'},{offset: 1, color: 'white'}], is a gradient from black to white.
colors: [
{ offset: 0, color: "black" }, { offset: 1, color: "white" }
]
},
defaultRadialGradient: {
// summary:
// An object specifying the default properties for RadialGradients using in fills patterns.
// type: String
// Specifies this is a RadialGradient, value 'radial'
type: "radial",
// cx: Number
// The X coordinate of the center of the radial gradient, default value 0.
cx: 0,
// cy: Number
// The Y coordinate of the center of the radial gradient, default value 0.
cy: 0,
// r: Number
// The radius to the end of the radial gradient, default value 100.
r: 100,
// colors: Array
// An array of colors at given offsets (from the center of the radial gradient).
// The center is defined at offest 0 with the outer edge of the gradient at offset 1.
// Default value, [{ offset: 0, color: 'black'},{offset: 1, color: 'white'}], is a gradient from black to white.
colors: [
{ offset: 0, color: "black" }, { offset: 1, color: "white" }
]
},
defaultPattern: {
// summary:
// An object specifying the default properties for a Pattern using in fill operations.
// type: String
// Specifies this object is a Pattern, value 'pattern'.
type: "pattern",
// x: Number
// The X coordinate of the position of the pattern, default value is 0.
x: 0,
// y: Number
// The Y coordinate of the position of the pattern, default value is 0.
y: 0,
// width: Number
// The width of the pattern image, default value is 0.
width: 0,
// height: Number
// The height of the pattern image, default value is 0.
height: 0,
// src: String
// A url specifying the image to use for the pattern.
src: ""
},
defaultFont: {
// summary:
// An object specifying the default properties for a Font used in text operations.
// type: String
// Specifies this object is a Font, value 'font'.
type: "font",
// style: String
// The font style, one of 'normal', 'bold', default value 'normal'.
style: "normal",
// variant: String
// The font variant, one of 'normal', ... , default value 'normal'.
variant: "normal",
// weight: String
// The font weight, one of 'normal', ..., default value 'normal'.
weight: "normal",
// size: String
// The font size (including units), default value '10pt'.
size: "10pt",
// family: String
// The font family, one of 'serif', 'sanserif', ..., default value 'serif'.
family: "serif"
},
getDefault: (function(){
// summary:
// Returns a function used to access default memoized prototype objects (see them defined above).
var typeCtorCache = {};
// a memoized delegate()
return function(/*String*/ type){
var t = typeCtorCache[type];
if(t){
return new t();
}
t = typeCtorCache[type] = function () {};
t.prototype = g[ "default" + type ];
return new t();
}
})(),
normalizeColor: function(/*dojo/Color|Array|string|Object*/ color){
// summary:
// converts any legal color representation to normalized
// dojo/Color object
// color:
// A color representation.
return (color instanceof Color) ? color : new Color(color); // dojo/Color
},
normalizeParameters: function(existed, update){
// summary:
// updates an existing object with properties from an 'update'
// object
// existed: Object
// the target object to be updated
// update: Object
// the 'update' object, whose properties will be used to update
// the existed object
var x;
if(update){
var empty = {};
for(x in existed){
if(x in update && !(x in empty)){
existed[x] = update[x];
}
}
}
return existed; // Object
},
makeParameters: function(defaults, update){
// summary:
// copies the original object, and all copied properties from the
// 'update' object
// defaults: Object
// the object to be cloned before updating
// update: Object
// the object, which properties are to be cloned during updating
// returns: Object
// new object with new and default properties
var i = null;
if(!update){
// return dojo.clone(defaults);
return lang.delegate(defaults);
}
var result = {};
for(i in defaults){
if(!(i in result)){
result[i] = lang.clone((i in update) ? update[i] : defaults[i]);
}
}
return result; // Object
},
formatNumber: function(x, addSpace){
// summary:
// converts a number to a string using a fixed notation
// x: Number
// number to be converted
// addSpace: Boolean
// whether to add a space before a positive number
// returns: String
// the formatted value
var val = x.toString();
if(val.indexOf("e") >= 0){
val = x.toFixed(4);
}else{
var point = val.indexOf(".");
if(point >= 0 && val.length - point > 5){
val = x.toFixed(4);
}
}
if(x < 0){
return val; // String
}
return addSpace ? " " + val : val; // String
},
// font operations
makeFontString: function(font){
// summary:
// converts a font object to a CSS font string
// font: Object
// font object (see dojox/gfx.defaultFont)
return font.style + " " + font.variant + " " + font.weight + " " + font.size + " " + font.family; // Object
},
splitFontString: function(str){
// summary:
// converts a CSS font string to a font object
// description:
// Converts a CSS font string to a gfx font object. The CSS font
// string components should follow the W3C specified order
// (see http://www.w3.org/TR/CSS2/fonts.html#font-shorthand):
// style, variant, weight, size, optional line height (will be
// ignored), and family. Note that the Font.size attribute is limited to numeric CSS length.
// str: String
// a CSS font string.
// returns: Object
// object in dojox/gfx.defaultFont format
var font = g.getDefault("Font");
var t = str.split(/\s+/);
do{
if(t.length < 5){ break; }
font.style = t[0];
font.variant = t[1];
font.weight = t[2];
var i = t[3].indexOf("/");
font.size = i < 0 ? t[3] : t[3].substring(0, i);
var j = 4;
if(i < 0){
if(t[4] == "/"){
j = 6;
}else if(t[4].charAt(0) == "/"){
j = 5;
}
}
if(j < t.length){
font.family = t.slice(j).join(" ");
}
}while(false);
return font; // Object
},
// length operations
// cm_in_pt: Number
// points per centimeter (constant)
cm_in_pt: 72 / 2.54,
// mm_in_pt: Number
// points per millimeter (constant)
mm_in_pt: 7.2 / 2.54,
px_in_pt: function(){
// summary:
// returns the current number of pixels per point.
return g._base._getCachedFontMeasurements()["12pt"] / 12; // Number
},
pt2px: function(len){
// summary:
// converts points to pixels
// len: Number
// a value in points
return len * g.px_in_pt(); // Number
},
px2pt: function(len){
// summary:
// converts pixels to points
// len: Number
// a value in pixels
return len / g.px_in_pt(); // Number
},
normalizedLength: function(len) {
// summary:
// converts any length value to pixels
// len: String
// a length, e.g., '12pc'
// returns: Number
// pixels
if(len.length === 0){ return 0; }
if(len.length > 2){
var px_in_pt = g.px_in_pt();
var val = parseFloat(len);
switch(len.slice(-2)){
case "px": return val;
case "pt": return val * px_in_pt;
case "in": return val * 72 * px_in_pt;
case "pc": return val * 12 * px_in_pt;
case "mm": return val * g.mm_in_pt * px_in_pt;
case "cm": return val * g.cm_in_pt * px_in_pt;
}
}
return parseFloat(len); // Number
},
// pathVmlRegExp: RegExp
// a constant regular expression used to split a SVG/VML path into primitive components
// tags:
// private
pathVmlRegExp: /([A-Za-z]+)|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,
// pathVmlRegExp: RegExp
// a constant regular expression used to split a SVG/VML path into primitive components
// tags:
// private
pathSvgRegExp: /([A-DF-Za-df-z])|([-+]?\d*[.]?\d+(?:[eE][-+]?\d+)?)/g,
equalSources: function(a, b){
// summary:
// compares event sources, returns true if they are equal
// a: Object
// first event source
// b: Object
// event source to compare against a
// returns: Boolean
// true, if objects are truthy and the same
return a && b && a === b;
},
switchTo: function(/*String|Object*/ renderer){
// summary:
// switch the graphics implementation to the specified renderer.
// renderer:
// Either the string name of a renderer (eg. 'canvas', 'svg, ...) or the renderer
// object to switch to.
var ns = typeof renderer == "string" ? g[renderer] : renderer;
if(ns){
// If more options are added, update the docblock at the end of shape.js!
arr.forEach(["Group", "Rect", "Ellipse", "Circle", "Line",
"Polyline", "Image", "Text", "Path", "TextPath",
"Surface", "createSurface", "fixTarget"], function(name){
g[name] = ns[name];
});
if(typeof renderer == "string"){
g.renderer = renderer;
}else{
arr.some(["svg","vml","canvas","canvasWithEvents","silverlight"], function(r){
return (g.renderer = g[r] && g[r].Surface === g.Surface ? r : null);
});
}
}
}
});
/*=====
g.createSurface = function(parentNode, width, height){
// summary:
// creates a surface
// parentNode: Node
// a parent node
// width: String|Number
// width of surface, e.g., "100px" or 100
// height: String|Number
// height of surface, e.g., "100px" or 100
// returns: dojox/gfx.Surface
// newly created surface
};
g.fixTarget = function(){
// tags:
// private
};
=====*/
return g; // defaults object api
});
},
'dojox/gfx/renderer':function(){
define(["./_base","dojo/_base/lang", "dojo/_base/sniff", "dojo/_base/window", "dojo/_base/config"],
function(g, lang, has, win, config){
//>> noBuildResolver
var currentRenderer = null;
has.add("vml", function(global, document, element){
element.innerHTML = "";
var supported = ("adj" in element.firstChild);
element.innerHTML = "";
return supported;
});
return {
// summary:
// This module is an AMD loader plugin that loads the appropriate graphics renderer
// implementation based on detected environment and current configuration settings.
load: function(id, require, load){
// tags:
// private
if(currentRenderer && id != "force"){
load(currentRenderer);
return;
}
var renderer = config.forceGfxRenderer,
renderers = !renderer && (lang.isString(config.gfxRenderer) ?
config.gfxRenderer : "svg,vml,canvas,silverlight").split(","),
silverlightObject, silverlightFlag;
while(!renderer && renderers.length){
switch(renderers.shift()){
case "svg":
// the next test is from https://github.com/phiggins42/has.js
if("SVGAngle" in win.global){
renderer = "svg";
}
break;
case "vml":
if(has("vml")){
renderer = "vml";
}
break;
case "silverlight":
try{
if(has("ie")){
silverlightObject = new ActiveXObject("AgControl.AgControl");
if(silverlightObject && silverlightObject.IsVersionSupported("1.0")){
silverlightFlag = true;
}
}else{
if(navigator.plugins["Silverlight Plug-In"]){
silverlightFlag = true;
}
}
}catch(e){
silverlightFlag = false;
}finally{
silverlightObject = null;
}
if(silverlightFlag){
renderer = "silverlight";
}
break;
case "canvas":
if(win.global.CanvasRenderingContext2D){
renderer = "canvas";
}
break;
}
}
if (renderer === 'canvas' && config.canvasEvents !== false) {
renderer = "canvasWithEvents";
}
if(config.isDebug){
console.log("gfx renderer = " + renderer);
}
function loadRenderer(){
require(["dojox/gfx/" + renderer], function(module){
g.renderer = renderer;
// memorize the renderer module
currentRenderer = module;
// now load it
load(module);
});
}
if(renderer == "svg" && typeof window.svgweb != "undefined"){
window.svgweb.addOnLoad(loadRenderer);
}else{
loadRenderer();
}
}
};
});
},
'dojox/dgauges/GaugeBase':function(){
define(["dojo/_base/lang", "dojo/_base/declare", "dojo/dom-geometry", "dijit/registry", "dijit/_WidgetBase", "dojo/_base/html",
"dojo/_base/event", "dojox/gfx", "dojox/widget/_Invalidating","./ScaleBase", "dojox/gfx/matrix"],
function(lang, // lang.extend
declare, domGeom, WidgetRegistry, _WidgetBase, html, event, gfx, _Invalidating, ScaleBase, matrix){
return declare("dojox.dgauges.GaugeBase", [_WidgetBase, _Invalidating], {
// summary:
// This class is the base class for the circular and
// rectangular (horizontal and vertical) gauge components.
// A gauge is a composition of elements added to the gauge using the addElement method.
// Elements are drawn from back to front in the same order they are added (using addElement).
// An elements can be:
//
// - A GFX drawing functions typically used for defining the style of the gauge.
// - A scale: CircularScale or RectangularScale depending on the type of gauge.
// - A text, using the TextIndicator
// Note: Indicator classes (value indicators, range indicators) are sub-elements of scales
// To create a custom gauge, subclass CircularGauge or RectangularGauge and
// configure its elements in the constructor.
// Ready to use, predefined gauges are available in dojox/dgauges/components/
// They are good examples of gauges built on top of the framework.
_elements: null,
_scales: null,
_elementsIndex: null,
_elementsRenderers: null,
_gfxGroup: null,
_mouseShield: null,
_widgetBox: null,
_node: null,
// value: Number
// This property acts as a top-level wrapper for the value of the first indicator added to
// its scale with the name "indicator", i.e. myScale.addIndicator("indicator", myIndicator).
// This property must be manipulated with get("value") and set("value", xxx).
value: 0,
_mainIndicator: null,
_getValueAttr: function(){
// summary:
// Internal method.
// tags:
// private
if(this._mainIndicator){
return this._mainIndicator.get("value");
}else{
this._setMainIndicator();
if(this._mainIndicator){
return this._mainIndicator.get("value");
}
}
return this.value;
},
_setValueAttr: function(value){
// summary:
// Internal method.
// tags:
// private
this._set("value", value);
if(this._mainIndicator){
this._mainIndicator.set("value", value);
}else{
this._setMainIndicator();
if(this._mainIndicator){
this._mainIndicator.set("value", value);
}
}
},
_setMainIndicator: function(){
// summary:
// Internal method.
// tags:
// private
var indicator;
for(var i=0; i 0){
var matrix = m.normalize(arg[0]);
// combine matrices
for(var i = 1; i < arg.length; ++i){
var l = matrix, r = m.normalize(arg[i]);
matrix = new m.Matrix2D();
matrix.xx = l.xx * r.xx + l.xy * r.yx;
matrix.xy = l.xx * r.xy + l.xy * r.yy;
matrix.yx = l.yx * r.xx + l.yy * r.yx;
matrix.yy = l.yx * r.xy + l.yy * r.yy;
matrix.dx = l.xx * r.dx + l.xy * r.dy + l.dx;
matrix.dy = l.yx * r.dx + l.yy * r.dy + l.dy;
}
lang.mixin(this, matrix);
}
}else{
lang.mixin(this, arg);
}
}
};
// the default (identity) matrix, which is used to fill in missing values
lang.extend(m.Matrix2D, {xx: 1, xy: 0, yx: 0, yy: 1, dx: 0, dy: 0});
lang.mixin(m, {
// summary:
// class constants, and methods of dojox/gfx/matrix
// matrix constants
// identity: dojox/gfx/matrix.Matrix2D
// an identity matrix constant: identity * (x, y) == (x, y)
identity: new m.Matrix2D(),
// flipX: dojox/gfx/matrix.Matrix2D
// a matrix, which reflects points at x = 0 line: flipX * (x, y) == (-x, y)
flipX: new m.Matrix2D({xx: -1}),
// flipY: dojox/gfx/matrix.Matrix2D
// a matrix, which reflects points at y = 0 line: flipY * (x, y) == (x, -y)
flipY: new m.Matrix2D({yy: -1}),
// flipXY: dojox/gfx/matrix.Matrix2D
// a matrix, which reflects points at the origin of coordinates: flipXY * (x, y) == (-x, -y)
flipXY: new m.Matrix2D({xx: -1, yy: -1}),
// matrix creators
translate: function(a, b){
// summary:
// forms a translation matrix
// description:
// The resulting matrix is used to translate (move) points by specified offsets.
// a: Number|dojox/gfx.Point
// an x coordinate value, or a point-like object, which specifies offsets for both dimensions
// b: Number?
// a y coordinate value
// returns: dojox/gfx/matrix.Matrix2D
if(arguments.length > 1){
return new m.Matrix2D({dx: a, dy: b}); // dojox/gfx/matrix.Matrix2D
}
// branch
return new m.Matrix2D({dx: a.x, dy: a.y}); // dojox/gfx/matrix.Matrix2D
},
scale: function(a, b){
// summary:
// forms a scaling matrix
// description:
// The resulting matrix is used to scale (magnify) points by specified offsets.
// a: Number|dojox/gfx.Point
// a scaling factor used for the x coordinate, or
// a uniform scaling factor used for the both coordinates, or
// a point-like object, which specifies scale factors for both dimensions
// b: Number?
// a scaling factor used for the y coordinate
// returns: dojox/gfx/matrix.Matrix2D
if(arguments.length > 1){
return new m.Matrix2D({xx: a, yy: b}); // dojox/gfx/matrix.Matrix2D
}
if(typeof a == "number"){
return new m.Matrix2D({xx: a, yy: a}); // dojox/gfx/matrix.Matrix2D
}
return new m.Matrix2D({xx: a.x, yy: a.y}); // dojox/gfx/matrix.Matrix2D
},
rotate: function(angle){
// summary:
// forms a rotating matrix
// description:
// The resulting matrix is used to rotate points
// around the origin of coordinates (0, 0) by specified angle.
// angle: Number
// an angle of rotation in radians (>0 for CW)
// returns: dojox/gfx/matrix.Matrix2D
var c = Math.cos(angle);
var s = Math.sin(angle);
return new m.Matrix2D({xx: c, xy: -s, yx: s, yy: c}); // dojox/gfx/matrix.Matrix2D
},
rotateg: function(degree){
// summary:
// forms a rotating matrix
// description:
// The resulting matrix is used to rotate points
// around the origin of coordinates (0, 0) by specified degree.
// See dojox/gfx/matrix.rotate() for comparison.
// degree: Number
// an angle of rotation in degrees (>0 for CW)
// returns: dojox/gfx/matrix.Matrix2D
return m.rotate(m._degToRad(degree)); // dojox/gfx/matrix.Matrix2D
},
skewX: function(angle) {
// summary:
// forms an x skewing matrix
// description:
// The resulting matrix is used to skew points in the x dimension
// around the origin of coordinates (0, 0) by specified angle.
// angle: Number
// a skewing angle in radians
// returns: dojox/gfx/matrix.Matrix2D
return new m.Matrix2D({xy: Math.tan(angle)}); // dojox/gfx/matrix.Matrix2D
},
skewXg: function(degree){
// summary:
// forms an x skewing matrix
// description:
// The resulting matrix is used to skew points in the x dimension
// around the origin of coordinates (0, 0) by specified degree.
// See dojox/gfx/matrix.skewX() for comparison.
// degree: Number
// a skewing angle in degrees
// returns: dojox/gfx/matrix.Matrix2D
return m.skewX(m._degToRad(degree)); // dojox/gfx/matrix.Matrix2D
},
skewY: function(angle){
// summary:
// forms a y skewing matrix
// description:
// The resulting matrix is used to skew points in the y dimension
// around the origin of coordinates (0, 0) by specified angle.
// angle: Number
// a skewing angle in radians
// returns: dojox/gfx/matrix.Matrix2D
return new m.Matrix2D({yx: Math.tan(angle)}); // dojox/gfx/matrix.Matrix2D
},
skewYg: function(degree){
// summary:
// forms a y skewing matrix
// description:
// The resulting matrix is used to skew points in the y dimension
// around the origin of coordinates (0, 0) by specified degree.
// See dojox/gfx/matrix.skewY() for comparison.
// degree: Number
// a skewing angle in degrees
// returns: dojox/gfx/matrix.Matrix2D
return m.skewY(m._degToRad(degree)); // dojox/gfx/matrix.Matrix2D
},
reflect: function(a, b){
// summary:
// forms a reflection matrix
// description:
// The resulting matrix is used to reflect points around a vector,
// which goes through the origin.
// a: dojox/gfx.Point|Number
// a point-like object, which specifies a vector of reflection, or an X value
// b: Number?
// a Y value
// returns: dojox/gfx/matrix.Matrix2D
if(arguments.length == 1){
b = a.y;
a = a.x;
}
// make a unit vector
var a2 = a * a, b2 = b * b, n2 = a2 + b2, xy = 2 * a * b / n2;
return new m.Matrix2D({xx: 2 * a2 / n2 - 1, xy: xy, yx: xy, yy: 2 * b2 / n2 - 1}); // dojox/gfx/matrix.Matrix2D
},
project: function(a, b){
// summary:
// forms an orthogonal projection matrix
// description:
// The resulting matrix is used to project points orthogonally on a vector,
// which goes through the origin.
// a: dojox/gfx.Point|Number
// a point-like object, which specifies a vector of projection, or
// an x coordinate value
// b: Number?
// a y coordinate value
// returns: dojox/gfx/matrix.Matrix2D
if(arguments.length == 1){
b = a.y;
a = a.x;
}
// make a unit vector
var a2 = a * a, b2 = b * b, n2 = a2 + b2, xy = a * b / n2;
return new m.Matrix2D({xx: a2 / n2, xy: xy, yx: xy, yy: b2 / n2}); // dojox/gfx/matrix.Matrix2D
},
// ensure matrix 2D conformance
normalize: function(matrix){
// summary:
// converts an object to a matrix, if necessary
// description:
// Converts any 2D matrix-like object or an array of
// such objects to a valid dojox/gfx/matrix.Matrix2D object.
// matrix: Object
// an object, which is converted to a matrix, if necessary
// returns: dojox/gfx/matrix.Matrix2D
return (matrix instanceof m.Matrix2D) ? matrix : new m.Matrix2D(matrix); // dojox/gfx/matrix.Matrix2D
},
// common operations
isIdentity: function(matrix){
// summary:
// returns whether the specified matrix is the identity.
// matrix: dojox/gfx/matrix.Matrix2D
// a 2D matrix object to be tested
// returns: Boolean
return matrix.xx == 1 && matrix.xy == 0 && matrix.yx == 0 && matrix.yy == 1 && matrix.dx == 0 && matrix.dy == 0; // Boolean
},
clone: function(matrix){
// summary:
// creates a copy of a 2D matrix
// matrix: dojox/gfx/matrix.Matrix2D
// a 2D matrix-like object to be cloned
// returns: dojox/gfx/matrix.Matrix2D
var obj = new m.Matrix2D();
for(var i in matrix){
if(typeof(matrix[i]) == "number" && typeof(obj[i]) == "number" && obj[i] != matrix[i]) obj[i] = matrix[i];
}
return obj; // dojox/gfx/matrix.Matrix2D
},
invert: function(matrix){
// summary:
// inverts a 2D matrix
// matrix: dojox/gfx/matrix.Matrix2D
// a 2D matrix-like object to be inverted
// returns: dojox/gfx/matrix.Matrix2D
var M = m.normalize(matrix),
D = M.xx * M.yy - M.xy * M.yx;
M = new m.Matrix2D({
xx: M.yy/D, xy: -M.xy/D,
yx: -M.yx/D, yy: M.xx/D,
dx: (M.xy * M.dy - M.yy * M.dx) / D,
dy: (M.yx * M.dx - M.xx * M.dy) / D
});
return M; // dojox/gfx/matrix.Matrix2D
},
_multiplyPoint: function(matrix, x, y){
// summary:
// applies a matrix to a point
// matrix: dojox/gfx/matrix.Matrix2D
// a 2D matrix object to be applied
// x: Number
// an x coordinate of a point
// y: Number
// a y coordinate of a point
// returns: dojox/gfx.Point
return {x: matrix.xx * x + matrix.xy * y + matrix.dx, y: matrix.yx * x + matrix.yy * y + matrix.dy}; // dojox/gfx.Point
},
multiplyPoint: function(matrix, /* Number||Point */ a, /* Number? */ b){
// summary:
// applies a matrix to a point
// matrix: dojox/gfx/matrix.Matrix2D
// a 2D matrix object to be applied
// a: Number|dojox/gfx.Point
// an x coordinate of a point, or a point
// b: Number?
// a y coordinate of a point
// returns: dojox/gfx.Point
var M = m.normalize(matrix);
if(typeof a == "number" && typeof b == "number"){
return m._multiplyPoint(M, a, b); // dojox/gfx.Point
}
return m._multiplyPoint(M, a.x, a.y); // dojox/gfx.Point
},
multiplyRectangle: function(matrix, /*Rectangle*/ rect){
// summary:
// Applies a matrix to a rectangle.
// description:
// The method applies the transformation on all corners of the
// rectangle and returns the smallest rectangle enclosing the 4 transformed
// points.
// matrix: dojox/gfx/matrix.Matrix2D
// a 2D matrix object to be applied.
// rect: Rectangle
// the rectangle to transform.
// returns: dojox/gfx.Rectangle
var M = m.normalize(matrix);
rect = rect || {x:0, y:0, width:0, height:0};
if(m.isIdentity(M))
return {x: rect.x, y: rect.y, width: rect.width, height: rect.height}; // dojo/gfx.Rectangle
var p0 = m.multiplyPoint(M, rect.x, rect.y),
p1 = m.multiplyPoint(M, rect.x, rect.y + rect.height),
p2 = m.multiplyPoint(M, rect.x + rect.width, rect.y),
p3 = m.multiplyPoint(M, rect.x + rect.width, rect.y + rect.height),
minx = Math.min(p0.x, p1.x, p2.x, p3.x),
miny = Math.min(p0.y, p1.y, p2.y, p3.y),
maxx = Math.max(p0.x, p1.x, p2.x, p3.x),
maxy = Math.max(p0.y, p1.y, p2.y, p3.y);
return{ // dojo/gfx.Rectangle
x: minx,
y: miny,
width: maxx - minx,
height: maxy - miny
};
},
multiply: function(matrix){
// summary:
// combines matrices by multiplying them sequentially in the given order
// matrix: dojox/gfx/matrix.Matrix2D
// a 2D matrix-like object,
// all subsequent arguments are matrix-like objects too
var M = m.normalize(matrix);
// combine matrices
for(var i = 1; i < arguments.length; ++i){
var l = M, r = m.normalize(arguments[i]);
M = new m.Matrix2D();
M.xx = l.xx * r.xx + l.xy * r.yx;
M.xy = l.xx * r.xy + l.xy * r.yy;
M.yx = l.yx * r.xx + l.yy * r.yx;
M.yy = l.yx * r.xy + l.yy * r.yy;
M.dx = l.xx * r.dx + l.xy * r.dy + l.dx;
M.dy = l.yx * r.dx + l.yy * r.dy + l.dy;
}
return M; // dojox/gfx/matrix.Matrix2D
},
// high level operations
_sandwich: function(matrix, x, y){
// summary:
// applies a matrix at a central point
// matrix: dojox/gfx/matrix.Matrix2D
// a 2D matrix-like object, which is applied at a central point
// x: Number
// an x component of the central point
// y: Number
// a y component of the central point
return m.multiply(m.translate(x, y), matrix, m.translate(-x, -y)); // dojox/gfx/matrix.Matrix2D
},
scaleAt: function(a, b, c, d){
// summary:
// scales a picture using a specified point as a center of scaling
// description:
// Compare with dojox/gfx/matrix.scale().
// a: Number
// a scaling factor used for the x coordinate, or a uniform scaling factor used for both coordinates
// b: Number?
// a scaling factor used for the y coordinate
// c: Number|Point
// an x component of a central point, or a central point
// d: Number
// a y component of a central point
// returns: dojox/gfx/matrix.Matrix2D
switch(arguments.length){
case 4:
// a and b are scale factor components, c and d are components of a point
return m._sandwich(m.scale(a, b), c, d); // dojox/gfx/matrix.Matrix2D
case 3:
if(typeof c == "number"){
return m._sandwich(m.scale(a), b, c); // dojox/gfx/matrix.Matrix2D
}
return m._sandwich(m.scale(a, b), c.x, c.y); // dojox/gfx/matrix.Matrix2D
}
return m._sandwich(m.scale(a), b.x, b.y); // dojox/gfx/matrix.Matrix2D
},
rotateAt: function(angle, a, b){
// summary:
// rotates a picture using a specified point as a center of rotation
// description:
// Compare with dojox/gfx/matrix.rotate().
// angle: Number
// an angle of rotation in radians (>0 for CW)
// a: Number|dojox/gfx.Point
// an x component of a central point, or a central point
// b: Number?
// a y component of a central point
// returns: dojox/gfx/matrix.Matrix2D
if(arguments.length > 2){
return m._sandwich(m.rotate(angle), a, b); // dojox/gfx/matrix.Matrix2D
}
return m._sandwich(m.rotate(angle), a.x, a.y); // dojox/gfx/matrix.Matrix2D
},
rotategAt: function(degree, a, b){
// summary:
// rotates a picture using a specified point as a center of rotation
// description:
// Compare with dojox/gfx/matrix.rotateg().
// degree: Number
// an angle of rotation in degrees (>0 for CW)
// a: Number|dojox/gfx.Point
// an x component of a central point, or a central point
// b: Number?
// a y component of a central point
// returns: dojox/gfx/matrix.Matrix2D
if(arguments.length > 2){
return m._sandwich(m.rotateg(degree), a, b); // dojox/gfx/matrix.Matrix2D
}
return m._sandwich(m.rotateg(degree), a.x, a.y); // dojox/gfx/matrix.Matrix2D
},
skewXAt: function(angle, a, b){
// summary:
// skews a picture along the x axis using a specified point as a center of skewing
// description:
// Compare with dojox/gfx/matrix.skewX().
// angle: Number
// a skewing angle in radians
// a: Number|dojox/gfx.Point
// an x component of a central point, or a central point
// b: Number?
// a y component of a central point
// returns: dojox/gfx/matrix.Matrix2D
if(arguments.length > 2){
return m._sandwich(m.skewX(angle), a, b); // dojox/gfx/matrix.Matrix2D
}
return m._sandwich(m.skewX(angle), a.x, a.y); // dojox/gfx/matrix.Matrix2D
},
skewXgAt: function(degree, a, b){
// summary:
// skews a picture along the x axis using a specified point as a center of skewing
// description:
// Compare with dojox/gfx/matrix.skewXg().
// degree: Number
// a skewing angle in degrees
// a: Number|dojox/gfx.Point
// an x component of a central point, or a central point
// b: Number?
// a y component of a central point
// returns: dojox/gfx/matrix.Matrix2D
if(arguments.length > 2){
return m._sandwich(m.skewXg(degree), a, b); // dojox/gfx/matrix.Matrix2D
}
return m._sandwich(m.skewXg(degree), a.x, a.y); // dojox/gfx/matrix.Matrix2D
},
skewYAt: function(angle, a, b){
// summary:
// skews a picture along the y axis using a specified point as a center of skewing
// description:
// Compare with dojox/gfx/matrix.skewY().
// angle: Number
// a skewing angle in radians
// a: Number|dojox/gfx.Point
// an x component of a central point, or a central point
// b: Number?
// a y component of a central point
// returns: dojox/gfx/matrix.Matrix2D
if(arguments.length > 2){
return m._sandwich(m.skewY(angle), a, b); // dojox/gfx/matrix.Matrix2D
}
return m._sandwich(m.skewY(angle), a.x, a.y); // dojox/gfx/matrix.Matrix2D
},
skewYgAt: function(/* Number */ degree, /* Number||Point */ a, /* Number? */ b){
// summary:
// skews a picture along the y axis using a specified point as a center of skewing
// description:
// Compare with dojox/gfx/matrix.skewYg().
// degree: Number
// a skewing angle in degrees
// a: Number|dojox/gfx.Point
// an x component of a central point, or a central point
// b: Number?
// a y component of a central point
// returns: dojox/gfx/matrix.Matrix2D
if(arguments.length > 2){
return m._sandwich(m.skewYg(degree), a, b); // dojox/gfx/matrix.Matrix2D
}
return m._sandwich(m.skewYg(degree), a.x, a.y); // dojox/gfx/matrix.Matrix2D
}
//TODO: rect-to-rect mapping, scale-to-fit (isotropic and anisotropic versions)
});
// propagate Matrix2D up
g.Matrix2D = m.Matrix2D;
return m;
});
},
'dojox/dgauges/LinearScaler':function(){
define(["dojo/_base/lang", "dojo/_base/declare", "dojo/Stateful"], function(lang, declare, Stateful){
return declare("dojox.dgauges.LinearScaler", Stateful, {
// summary:
// The linear scaler. This scaler creates major and minor ticks regularly between
// a minimum and a maximum.
// Scalers are responsible for tick generation and various data-transform operations.
// minimum: Number
// The minimum value of the scaler. Default is 0.
minimum: 0,
// maximum: Number
// The maximum value of the scaler. Default is 100.
maximum: 100,
// snapInterval:
// Specifies the increment value to be used as snap values on this scale
// during user interaction.
// Default is 1.
snapInterval: 1,
// majorTickInterval: Number
// The interval between two major ticks.
majorTickInterval: NaN,
// minorTickInterval: Number
// The interval between two minor ticks.
minorTickInterval: NaN,
// minorTicksEnabled: Boolean
// If false, minor ticks are not generated. Default is true.
minorTicksEnabled: true,
// majorTicks:
// The array of generated major ticks. You should not set this
// property when using the scaler.
majorTicks: null,
// minorTicks:
// The array of generated minor ticks. You should not set this
// property when using the scaler.
minorTicks: null,
_computedMajorTickInterval: NaN,
_computedMinorTickInterval: NaN,
constructor: function(){
this.watchedProperties = ["minimum", "maximum", "majorTickInterval", "minorTickInterval", "snapInterval", "minorTicksEnabled"];
},
_buildMinorTickItems: function(){
// summary:
// Internal method.
// tags:
// private
var mt = this.majorTicks;
var minorTickCache = [];
if(this.maximum > this.minimum){
var majorTickCount = Math.floor((this.maximum - this.minimum) / this.getComputedMajorTickInterval()) + 1;
var minorTickCount = Math.floor(this.getComputedMajorTickInterval() / this.getComputedMinorTickInterval());
var data;
for(var i = 0; i < majorTickCount - 1; i++){
for(var j = 1; j < minorTickCount; j++){
data = {scaler: this};
data.isMinor = true;
data.value = mt[i].value + j * this.getComputedMinorTickInterval();
data.position = (Number(data.value) - this.minimum) / (this.maximum - this.minimum);
minorTickCache.push(data);
}
}
}
return minorTickCache;
},
_buildMajorTickItems: function(){
// summary:
// Internal method.
// tags:
// private
var majorTickCache = [];
if(this.maximum > this.minimum){
var majorTickCount = Math.floor((this.maximum - this.minimum) / this.getComputedMajorTickInterval()) + 1;
var data;
for(var i = 0; i < majorTickCount; i++){
data = {scaler: this};
data.isMinor = false;
data.value = this.minimum + i * this.getComputedMajorTickInterval();
data.position = (Number(data.value) - this.minimum) / (this.maximum - this.minimum);
majorTickCache.push(data);
}
}
return majorTickCache;
},
getComputedMajorTickInterval: function(){
// summary:
// The computed or user defined major tick interval.
// returns: Number
// The major tick interval used for ticks generation.
if(!isNaN(this.majorTickInterval)){
return this.majorTickInterval;
}
if(isNaN(this._computedMajorTickInterval)){
this._computedMajorTickInterval = (this.maximum - this.minimum) / 10;
}
return this._computedMajorTickInterval;
},
getComputedMinorTickInterval: function(){
// summary:
// The computed or user defined minor tick interval.
// returns: Number
// The minor tick interval used for ticks generation.
if(!isNaN(this.minorTickInterval)){
return this.minorTickInterval;
}
if(isNaN(this._computedMinorTickInterval)){
this._computedMinorTickInterval = this.getComputedMajorTickInterval() / 5;
}
return this._computedMinorTickInterval;
},
computeTicks: function(){
// summary:
// Creates or re-creates the ticks for this scaler.
// returns: Array
// An array containing all ticks (major then minor ticks).
this.majorTicks = this._buildMajorTickItems();
this.minorTicks = this.minorTicksEnabled ? this._buildMinorTickItems() : [];
return this.majorTicks.concat(this.minorTicks);
},
positionForValue: function(value){
// summary:
// Transforms a value into a relative position between 0 and 1.
// value: Number
// A value to transform.
// returns: Number
// The position between 0 and 1.
var position;
if(value == null || isNaN(value) || value <= this.minimum){
position = 0;
}
if(value >= this.maximum){
position = 1;
}
if(isNaN(position)){
position = (value - this.minimum) / (this.maximum - this.minimum);
}
return position;
},
valueForPosition: function(position){
// summary:
// Transforms a relative position (between 0 and 1) into a value.
// position: Number
// A relative position to transform.
// returns: Number
// The transformed value between minimum and maximum.
var range = Math.abs(this.minimum - this.maximum);
var value = this.minimum + range * position;
if(!isNaN(this.snapInterval) && this.snapInterval > 0){
value = Math.round((value - this.minimum) / this.snapInterval) * this.snapInterval + this.minimum;
}
return value;
}
});
});
},
'dojox/dgauges/CircularScale':function(){
define(["dojo/_base/declare", "dojox/gfx", "./ScaleBase", "./_circularUtils"], function(declare, gfx, ScaleBase, _circularUtils){
return declare("dojox.dgauges.CircularScale", ScaleBase, {
// summary:
// The circular scale. A scaler must be set to use this class.
// originX: Number
// The origin x-coordinate of the scale in pixels.
originX: 50,
// originY: Number
// The origin y-coordinate of the scale in pixels.
originY: 50,
// radius: Number
// The outer radius in pixels of the scale.
radius: 50,
// startAngle: Number
// The start angle of the scale in degrees.
startAngle: 0,
// endAngle: Number
// The end angle of the scale in degrees.
endAngle: 180,
// orientation: String
// The orientation of the scale. Can be "clockwise" or "cclockwise".
// The default value is "clockwise".
orientation: "clockwise",
constructor: function(){
this.labelPosition = "inside";
this.addInvalidatingProperties(["originX", "originY", "radius", "startAngle", "endAngle", "orientation"]);
},
_getOrientationNum: function(){
// summary:
// Internal method.
// tags:
// private
return this.orientation == "cclockwise" ? -1 : 1;
},
positionForValue: function(/* Number */value){
// summary:
// Transforms a value into an angle using the associated scaler.
// returns: Number
// An angle in degrees.
var totalAngle = _circularUtils.computeTotalAngle(this.startAngle, this.endAngle, this.orientation);
var relativePos = this.scaler.positionForValue(value);
return _circularUtils.modAngle(this.startAngle + this._getOrientationNum() * totalAngle * relativePos, 360);
},
_positionForTickItem: function(tickItem){
// summary:
// Internal method.
// tags:
// private
var totalAngle = _circularUtils.computeTotalAngle(this.startAngle, this.endAngle, this.orientation);
return _circularUtils.modAngle(this.startAngle + this._getOrientationNum() * totalAngle * tickItem.position, 360);
},
valueForPosition: function(/* Number */angle){
// summary:
// Transforms an angle in degrees into a value using the associated scaler.
// returns: Number
// The value represented by angle.
if(!this.positionInRange(angle)){
var min1 = _circularUtils.modAngle(this.startAngle - angle, 360);
var min2 = 360 - min1;
var max1 = _circularUtils.modAngle(this.endAngle - angle, 360);
var max2 = 360 - max1;
var pos;
if(Math.min(min1, min2) < Math.min(max1, max2)){
pos = 0;
}else{
pos = 1;
}
}else{
var relativeAngle = _circularUtils.modAngle(this._getOrientationNum() * (angle - this.startAngle), 360);
var totalAngle = _circularUtils.computeTotalAngle(this.startAngle, this.endAngle, this.orientation);
pos = relativeAngle / totalAngle;
}
return this.scaler.valueForPosition(pos);
},
positionInRange: function(/* Number */value){
// summary:
// Returns true if the value parameter is between the accepted scale positions.
// returns: Boolean
// True if the value parameter is between the accepted scale positions.
if(this.startAngle == this.endAngle){
return true;
}
value = _circularUtils.modAngle(value, 360);
if(this._getOrientationNum() == 1){
if(this.startAngle < this.endAngle){
return value >= this.startAngle && value <= this.endAngle;
}else{
return !(value > this.endAngle && value < this.startAngle);
}
}else{
if(this.startAngle < this.endAngle){
return !(value > this.startAngle && value < this.endAngle);
}else{
return value >= this.endAngle && value <= this.startAngle;
}
}
},
_distance: function(x1, y1, x2, y2){
// summary:
// Internal method.
// tags:
// private
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
},
_layoutLabel: function(label, txt, ox, oy, lrad, angle, labelPlacement){
// summary:
// Internal method.
// tags:
// private
var font = this._getFont();
var box = gfx._base._getTextBox(txt, {
font: gfx.makeFontString(gfx.makeParameters(gfx.defaultFont, font))
});
var tw = box.w;
var fz = font.size;
var th = gfx.normalizedLength(fz);
var tfx = ox + Math.cos(angle) * lrad - tw / 2;
var tfy = oy - Math.sin(angle) * lrad - th / 2;
var side;
var intersections = [];
// Intersection with top segment
side = tfx;
var ipx = side;
var ipy = -Math.tan(angle) * side + oy + Math.tan(angle) * ox;
// Verify if intersection is on segment
if(ipy >= tfy && ipy <= tfy + th){
intersections.push({
x: ipx,
y: ipy
});
}
// Intersection with bottom segment
side = tfx + tw;
ipx = side;
ipy = -Math.tan(angle) * side + oy + Math.tan(angle) * ox;
// Verify if intersection is on segment
if(ipy >= tfy && ipy <= tfy + th){
intersections.push({
x: ipx,
y: ipy
});
}
// Intersection with left segment
side = tfy;
ipx = -1 / Math.tan(angle) * side + ox + 1 / Math.tan(angle) * oy;
ipy = side;
// Verify if intersection is on segment
if(ipx >= tfx && ipx <= tfx + tw){
intersections.push({
x: ipx,
y: ipy
});
}
// Intersection with right segment
side = tfy + th;
ipx = -1 / Math.tan(angle) * side + ox + 1 / Math.tan(angle) * oy;
ipy = side;
// Verify if intersection is on segment
if(ipx >= tfx && ipx <= tfx + tw){
intersections.push({
x: ipx,
y: ipy
});
}
var dif;
if(labelPlacement == "inside"){
for(var it = 0; it < intersections.length; it++){
var ip = intersections[it];
dif = this._distance(ip.x, ip.y, ox, oy) - lrad;
if(dif >= 0){
// Place reference intersection point on reference circle
tfx = ox + Math.cos(angle) * (lrad - dif) - tw / 2;
tfy = oy - Math.sin(angle) * (lrad - dif) - th / 2;
break;
}
}
}else{// "outside" placement
for(it = 0; it < intersections.length; it++){
ip = intersections[it];
dif = this._distance(ip.x, ip.y, ox, oy) - lrad;
if(dif <= 0){
// Place reference intersection point on reference circle
tfx = ox + Math.cos(angle) * (lrad - dif) - tw / 2;
tfy = oy - Math.sin(angle) * (lrad - dif) - th / 2;
break;
}
}
}
if(label){
label.setTransform([{
dx: tfx + tw / 2,
dy: tfy + th
}]);
}
},
refreshRendering: function(){
this.inherited(arguments);
if(!this._gfxGroup || !this.scaler){
return;
}
// Normalize angles
this.startAngle = _circularUtils.modAngle(this.startAngle, 360);
this.endAngle = _circularUtils.modAngle(this.endAngle, 360);
this._ticksGroup.clear();
var renderer;
var label;
var labelText;
// Layout ticks
var allTicks = this.scaler.computeTicks();
var tickBB;
for(var i = 0; i < allTicks.length; i++){
var tickItem = allTicks[i];
renderer = this.tickShapeFunc(this._ticksGroup, this, tickItem);
tickBB = this._gauge._computeBoundingBox(renderer);
var a;
if(tickItem.position){
a = this._positionForTickItem(tickItem);
}else{
a = this.positionForValue(tickItem.value);
}
if(renderer){
renderer.setTransform([{
dx: this.originX,
dy: this.originY
}, gfx.matrix.rotateg(a), {
dx: this.radius - tickBB.width - 2 * tickBB.x,
dy: 0
}]);
}
labelText = this.tickLabelFunc(tickItem);
if(labelText){
label = this._ticksGroup.createText({
x: 0,
y: 0,
text: labelText,
align: "middle"
}).setFont(this._getFont()).setFill(this._getFont().color ? this._getFont().color : "black");
var rad = this.radius;
if(this.labelPosition == "inside"){
rad -= (tickBB.width + this.labelGap);
}else{
rad += this.labelGap;
}
this._layoutLabel(label, labelText, this.originX, this.originY, rad, _circularUtils.toRadians(360 - a), this.labelPosition);
}
}
for(var key in this._indicatorsIndex){
this._indicatorsRenderers[key] = this._indicatorsIndex[key].invalidateRendering();
}
}
});
});
},
'dojox/dgauges/_circularUtils':function(){
define(function(){
// module:
// dojox/dgauges/components/_circularUtils
// summary:
// Internal circular utilities.
// tags:
// private
return {
computeTotalAngle: function(start, end, orientation){
// summary:
// Internal method.
// tags:
// private
if(start == end){
return 360;
}else{
return this.computeAngle(start, end, orientation, 360);
}
},
modAngle: function(angle, base){
// summary:
// Internal method.
// tags:
// private
if(base == undefined){
base = 6.28318530718;
}
if(angle >= base){
do {
angle -= base;
}
while (angle >= base);
}else{
while (angle < 0){
angle += base;
}
}
return angle;
},
computeAngle: function(startAngle, endAngle, orientation, base){
// summary:
// Internal method.
// tags:
// private
if(base == undefined){
base = 6.28318530718;
}
var totalAngle;
if(endAngle == startAngle){
return base;
}
if(orientation == "clockwise"){
if(endAngle < startAngle){
totalAngle = base - (startAngle - endAngle);
}else{
totalAngle = endAngle - startAngle;
}
}
else{
if(endAngle < startAngle){
totalAngle = startAngle - endAngle;
}else{
totalAngle = base - (endAngle - startAngle);
}
}
return this.modAngle(totalAngle, base);
},
toRadians: function(deg){
// summary:
// Internal method.
// tags:
// private
return deg * Math.PI / 180;
},
toDegrees: function(rad){
// summary:
// Internal method.
// tags:
// private
return rad * 180 / Math.PI;
}
}
});
},
'dojox/dgauges/CircularValueIndicator':function(){
define(["dojo/_base/declare", "dojox/gfx", "./ScaleIndicatorBase", "dojo/_base/event"], function(declare, gfx, ScaleIndicatorBase, eventUtil){
return declare("dojox.dgauges.CircularValueIndicator", ScaleIndicatorBase, {
// summary:
// The circular value indicator, typically used for creating needles.
indicatorShapeFunc: function(group, indicator){
// summary:
// Draws the indicator. The rotation center is at (0, 0).
// group: dojox/gfx/Group
// A GFX group for drawing.
// indicator: dojox/dgauges/IndicatorBase
// A reference to this indicator.
// returns: dojox/gfx/shape.Shape
// A GFX shape retrievable using the getIndicatorRenderer method of the associated scale.
return group.createLine({
x1: 0,
y1: 0,
x2: 40,
y2: 0
}).setStroke({
color: "black",
width: 1
});
},
refreshRendering: function(){
this.inherited(arguments);
if(this._gfxGroup === null || this.scale === null){
return;
}else{
var v = isNaN(this._transitionValue) ? this.value : this._transitionValue;
var angle = this.scale.positionForValue(v);
this._gfxGroup.setTransform([{
dx: this.scale.originX,
dy: this.scale.originY
}, gfx.matrix.rotateg(angle)]);
}
},
_onMouseDown: function(event){
// summary:
// Internal method.
// tags:
// private
this.inherited(arguments);
var origin = this.scale._gauge._gaugeToPage(this.scale.originX, this.scale.originY);
var angle = ((Math.atan2(event.pageY - origin.y, event.pageX - origin.x)) * 180) / (Math.PI);
this.set("value", this.scale.valueForPosition(angle));
// prevent the browser from selecting text
eventUtil.stop(event);
},
_onMouseMove: function(event){
// summary:
// Internal method.
// tags:
// private
this.inherited(arguments);
var origin = this.scale._gauge._gaugeToPage(this.scale.originX, this.scale.originY);
var angle = ((Math.atan2(event.pageY - origin.y, event.pageX - origin.x)) * 180) / (Math.PI);
this.set("value", this.scale.valueForPosition(angle));
}
});
});
},
'dojox/dgauges/ScaleIndicatorBase':function(){
define(["dojo/_base/lang", "dojo/_base/declare", "dojo/_base/window", "dojo/on", "dojo/touch", "dojo/_base/fx", "dojox/gfx", "dojox/widget/_Invalidating", "./IndicatorBase"],
function(lang, declare, win, on, touch, fx, gfx, _Invalidating, IndicatorBase){
return declare("dojox.dgauges.ScaleIndicatorBase", IndicatorBase, {
// summary:
// The base class for indicators that rely on a scale for their rendering.
// Typically, value indicators and range indicators are subclasses of ScaleIndicatorBase.
// summary:
// The scale associated with this indicator.
scale: null,
// summary:
// The value of the indicator. Default is 0.
value: 0,
// interactionArea: String
// How to interact with the indicator using mouse or touch interactions.
// Can be "indicator", "gauge", "area" or "none". The default value is "gauge".
// If set to "indicator", the indicator shape reacts to mouse and touch events.
// If set to "gauge", the whole gauge reacts to mouse and touch events.
// If set to "area", the whole bounding box of the widget reacts to mouse and touch events.
// If "none", interactions are disabled.
interactionArea: "gauge",
// interactionMode: String
// Deprecated. Can be "mouse" or "touch".
interactionMode: "mouse",
// animationDuration: Number
// The duration of the value change animation in milliseconds. Default is 0.
// The animation occurs on both user interactions and programmatic value changes.
// Set this property to 0 to disable animation.
animationDuration: 0,
// animationEaser: Object
// The easer function of the value change animation. Default is fx._defaultEasing.
animationEaser: null,
_indicatorShapeFuncFlag: true,
_interactionAreaFlag: true,
_downListeners: null,
_cursorListeners: null,
_moveAndUpListeners: null,
_transitionValue: NaN,
_preventAnimation: false,
_animation: null,
constructor: function(){
// watches changed happening on the "value" property
this.watch("value", lang.hitch(this, function(){
this.valueChanged(this);
}));
this.watch("value", lang.hitch(this, this._startAnimation));
this.watch("interactionArea", lang.hitch(this, function(){
this._interactionAreaFlag = true;
}));
this.watch("interactionMode", lang.hitch(this, function(){
this._interactionAreaFlag = true;
}));
this.watch("indicatorShapeFunc", lang.hitch(this, function(){
this._indicatorShapeFuncFlag = true;
}));
this.addInvalidatingProperties(["scale", "value", "indicatorShapeFunc", "interactionArea", "interactionMode"]);
this._downListeners = [];
this._moveAndUpListeners = [];
this._cursorListeners = [];
},
_startAnimation: function(prop, oldValue, newValue){
// summary:
// Internal method.
// tags:
// private
if(this.animationDuration === 0){
return;
}
if(this._animation && (this._preventAnimation || oldValue == newValue)){
this._animation.stop();
return;
}
this._animation = new fx.Animation({curve: [oldValue, newValue],
duration: this.animationDuration,
easing: this.animationEaser ? this.animationEaser : fx._defaultEasing,
onAnimate: lang.hitch(this, this._updateAnimation),
onEnd: lang.hitch(this, this._endAnimation),
onStop: lang.hitch(this, this._endAnimation)});
this._animation.play();
},
_updateAnimation: function(v){
// summary:
// Internal method.
// tags:
// private
this._transitionValue = v;
this.invalidateRendering();
},
_endAnimation: function(){
// summary:
// Internal method.
// tags:
// private
this._transitionValue = NaN;
this.invalidateRendering();
},
refreshRendering: function(){
if(this._gfxGroup === null || this.scale === null){
return;
}else{
if(this._indicatorShapeFuncFlag && lang.isFunction(this.indicatorShapeFunc)){
this._gfxGroup.clear();
this.indicatorShapeFunc(this._gfxGroup, this);
this._indicatorShapeFuncFlag = false;
}
if(this._interactionAreaFlag){
this._interactionAreaFlag = this._connectDownListeners();
}
}
},
valueChanged: function(indicator){
// summary:
// Invoked when the value of the indicator changes.
// User can connect an listener on this function:
// | theIndicator.on("valueChanged", lang.hitch(this, function(){
// | //do something
// | }));
on.emit(this, "valueChanged", {
target: this,
bubbles: true,
cancelable: true
});
},
_disconnectDownListeners: function(){
// summary:
// Internal method.
// tags:
// private
for(var i = 0; i < this._downListeners.length; i++){
this._downListeners[i].remove();
}
this._downListeners = [];
},
_disconnectMoveAndUpListeners: function(){
// summary:
// Internal method.
// tags:
// private
for(var i = 0; i < this._moveAndUpListeners.length; i++){
this._moveAndUpListeners[i].remove();
}
this._moveAndUpListeners = [];
},
_disconnectListeners: function(){
// summary:
// Internal method.
// tags:
// private
this._disconnectDownListeners();
this._disconnectMoveAndUpListeners();
this._disconnectCursorListeners();
},
_connectCursorListeners: function(target){
// summary:
// Internal method.
// tags:
// private
var listener = target.on(touch.over , lang.hitch(this, function(){
this.scale._gauge._setCursor("pointer");
}));
this._cursorListeners.push(listener);
listener = target.on(touch.out, lang.hitch(this, function(event){
this.scale._gauge._setCursor("");
}
));
this._cursorListeners.push(listener);
},
_disconnectCursorListeners: function(){
// summary:
// Internal method.
// tags:
// private
for(var i = 0; i < this._cursorListeners.length; i++){
this._cursorListeners[i].remove();
}
this._cursorListeners = [];
},
_connectDownListeners: function(){
// summary:
// Internal method.
// tags:
// private
this._disconnectDownListeners();
this._disconnectCursorListeners();
var listener = null;
if(this.interactionMode == "mouse" || this.interactionMode == "touch"){
if(this.interactionArea == "indicator"){
listener = this._gfxGroup.on(touch.press, lang.hitch(this, this._onMouseDown));
this._downListeners.push(listener);
this._connectCursorListeners(this._gfxGroup);
}else if(this.interactionArea == "gauge"){
if(!this.scale || !this.scale._gauge || !this.scale._gauge._gfxGroup){
return true;
}
listener = this.scale._gauge._gfxGroup.on(touch.press, lang.hitch(this, this._onMouseDown));
this._downListeners.push(listener);
listener = this._gfxGroup.on(touch.press, lang.hitch(this, this._onMouseDown));
this._downListeners.push(listener);
this._connectCursorListeners(this.scale._gauge._gfxGroup);
}else if(this.interactionArea == "area"){
if(!this.scale || !this.scale._gauge || !this.scale._gauge._baseGroup){
return true;
}
listener = this.scale._gauge._baseGroup.on(touch.press, lang.hitch(this, this._onMouseDown));
this._downListeners.push(listener);
listener = this._gfxGroup.on(touch.press, lang.hitch(this, this._onMouseDown));
this._downListeners.push(listener);
this._connectCursorListeners(this.scale._gauge._baseGroup);
}
}
return false;
},
_connectMoveAndUpListeners: function(){
// summary:
// Internal method.
// tags:
// private
var listener = null;
listener = on(win.doc, touch.move, lang.hitch(this, this._onMouseMove));
this._moveAndUpListeners.push(listener);
listener = on(win.doc, touch.release, lang.hitch(this, this._onMouseUp));
this._moveAndUpListeners.push(listener);
},
_onMouseDown: function(event){
// summary:
// Internal method.
// tags:
// private
this._connectMoveAndUpListeners();
this._startEditing();
},
_onMouseMove: function(event){
// summary:
// Internal method.
// tags:
// private
this._preventAnimation = true;
if(this._animation){
this._animation.stop();
}
},
_onMouseUp: function(event){
// summary:
// Internal method.
// tags:
// private
this._disconnectMoveAndUpListeners();
this._preventAnimation = false;
this._endEditing();
},
_startEditing: function(){
// summary:
// Internal method.
// tags:
// private
if(!this.scale || !this.scale._gauge){
return;
}else{
this.scale._gauge.onStartEditing({
indicator: this
});
}
},
_endEditing: function(){
// summary:
// Internal method.
// tags:
// private
if(!this.scale || !this.scale._gauge){
return;
}else{
this.scale._gauge.onEndEditing({
indicator: this
});
}
}
});
});
},
'dojox/dgauges/IndicatorBase':function(){
define(["dojo/_base/declare", "dojox/widget/_Invalidating"], function(declare, _Invalidating){
return declare("dojox.dgauges.IndicatorBase", _Invalidating, {
// summary:
// The base class for indicators. Basically, an indicator is used to render a value.
// value: Number
// The value of this indicator.
value: null
});
});
},
'dojox/dgauges/TextIndicator':function(){
define(["dojo/_base/lang", "dojo/_base/declare", "dojo/_base/sniff", "dojo/_base/array", "dojo/on", "dojox/gfx", "./IndicatorBase"],
function(lang, declare, has, array, on, gfx, IndicatorBase){
return declare("dojox.dgauges.TextIndicator", IndicatorBase, {
// summary:
// This type of indicator is used to render text.
// To render an arbitrary text, set the value property.
// To render the value of a value indicator or a range indicator, set the indicator property.
// Setting the indicator property takes precedence on setting the value property.
// When the indicator property is set, the text is automatically updated on value changes.
// font: Object
// Font used by this element.
font: null,
// x: Number
// The text anchor x-position. Default is 0.
x: 0,
// y: Number
// The text anchor y-position. Default is 0.
y: 0,
// align: String
// An alignment of a text in regards to the anchor position:
//
// - "start": A text's baseline starts at the anchor.
// This is the default value of the align attribute.
// - "middle": A text's baseline is centered on the anchor point.
// - "end": A text's baseline ends at the anchor point.
align: "middle",
// color: Object
// The color of the text.
color: "black",
// indicator: dojox/dgauges/IndicatorBase
// If this property is set, the value of the indicator is automatically
// rendered by this text element.
indicator: null,
// labelFunc: Object
// If set, this method allows to format the value of this text indicator.
// A label function takes the text to render as argument and returns a String.
labelFunc: null,
constructor: function(){
this.addInvalidatingProperties(["indicator"]);
var resetProps = ["x", "y", "font", "align", "color", "labelFunc"];
array.forEach(resetProps, lang.hitch(this, function(entry){
this.watch(entry, this._resetText);
}));
this.watch("indicator", lang.hitch(this, this._indicatorChanged));
},
postscript: function(mixin){
// summary:
// Internal method
// tags:
// private
this.inherited(arguments);
if(mixin && mixin.indicator){
this._indicatorChanged("indicator", null, mixin.indicator);
}
},
_resetText: function(){
// summary:
// Internal method.
// tags:
// private
this._textCreated = false;
this.invalidateRendering();
},
_valueWatcher: null,
_indicatorChanged: function(name, oldValue, newValue){
// summary:
// Internal method.
// tags:
// private
if(this._valueWatcher){
this._valueWatcher.unwatch();
}
this._valueWatcher = newValue.watch("value", lang.hitch(this, this.refreshRendering));
},
_getFont: function(){
// summary:
// Internal method.
// tags:
// private
var font = this.font;
if(!font && this._gauge){
font = this._gauge.font;
}
if(!font){
font = gfx.defaultFont;
}
return font;
},
_textCreated: false,
_textInstance: null,
_createText: function(group, font, color, text, x, y, align){
// summary:
// Internal method.
// tags:
// private
var gfxText = group.createText({
x: x,
y: y,
text: text,
align: align
}).setFont(font).setFill(color);
return gfxText;
},
refreshRendering: function(){
if(this._gfxGroup == null){
return;
}
var text;
if(this.indicator){
text = this.indicator.value;
}else{
text = this.value;
}
if(this.labelFunc){
text = this.labelFunc(text);
}
var iOsVersion = has("iphone");
// Workaround for a bug on iOS version < 5.0: Recreate the text every times
if(!this._textCreated || (iOsVersion != undefined && iOsVersion < 5)){
this._gfxGroup.clear();
var font = this._getFont();
this._textInstance = this._createText(this._gfxGroup, font, font.color ? font.color : this.color, "", this.x, this.y, this.align);
this._textCreated = true;
}
this._textInstance.setShape({
text: text
});
return this._textInstance;
}
})
});
},
'dojox/dgauges/components/DefaultPropertiesMixin':function(){
define(["dojo/_base/declare", "dojo/_base/Color"], function(declare, Color){
return declare("dojox.dgauges.components.DefaultPropertiesMixin", null, {
// summary:
// This class defines default properties of predefined gauges.
// minimum: Number
// The minimum value of the scaler. Default is 0.
minimum: 0,
// maximum: Number
// The maximum value of the scaler. Default is 100.
maximum: 100,
// snapInterval:
// Specifies the increment value to be used as snap values on this scale
// during user interaction.
// Default is 1.
snapInterval: 1,
// majorTickInterval: Number
// The interval between two major ticks.
majorTickInterval: NaN,
// minorTickInterval: Number
// The interval between two minor ticks.
minorTickInterval: NaN,
// minorTicksEnabled: Boolean
// If false, minor ticks are not generated. Default is true.
minorTicksEnabled: true,
// summary:
// The value of the indicator. Default is 0.
value: 0,
// interactionArea: String
// How to interact with the indicator using mouse or touch interactions.
// Can be "indicator", "gauge" or "none". The default value is "gauge".
// If set to "indicator", the indicator shape reacts to mouse and touch events.
// If set to "gauge", the whole gauge reacts to mouse and touch events.
// If "none", interactions are disabled.
interactionArea: "gauge",
// interactionMode: String
// Can be "mouse" or "touch".
interactionMode: "mouse",
// animationDuration: Number
// The duration of the value change animation in milliseconds. Default is 0.
// The animation occurs on both user interactions and programmatic value changes.
// Set this property to 0 to disable animation.
animationDuration: 0,
_setMinimumAttr: function(v){
this.getElement("scale").scaler.set("minimum", v);
},
_setMaximumAttr: function(v){
this.getElement("scale").scaler.set("maximum", v);
},
_setSnapIntervalAttr: function(v){
this.getElement("scale").scaler.set("snapInterval", v);
},
_setMajorTickIntervalAttr: function(v){
this.getElement("scale").scaler.set("majorTickInterval", v);
},
_setMinorTickIntervalAttr: function(v){
this.getElement("scale").scaler.set("minorTickInterval", v);
},
_setMinorTicksEnabledAttr: function(v){
this.getElement("scale").scaler.set("minorTicksEnabled", v);
},
_setInteractionAreaAttr: function(v){
this.getElement("scale").getIndicator("indicator").set("interactionArea", v);
},
_setInteractionModeAttr: function(v){
this.getElement("scale").getIndicator("indicator").set("interactionMode", v);
},
_setAnimationDurationAttr: function(v){
this.getElement("scale").getIndicator("indicator").set("animationDuration", v);
},
_setBorderColorAttr: function(v){
this.borderColor = new Color(v);
this.invalidateRendering();
},
_setFillColorAttr: function(v){
this.fillColor = new Color(v);
this.invalidateRendering();
},
_setIndicatorColorAttr: function(v){
this.indicatorColor = new Color(v);
this.invalidateRendering();
}
});
});
},
'dojox/dgauges/components/default/SemiCircularLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../utils",
"../../CircularGauge",
"../../LinearScaler",
"../../CircularScale",
"../../CircularValueIndicator",
"../../TextIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, utils, CircularGauge, LinearScaler, CircularScale, CircularValueIndicator, TextIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.default.SemiCircularLinearGauge", [CircularGauge, DefaultPropertiesMixin], {
// summary:
// A semi circular gauge widget.
_radius: 88,
_width: 200,
_height: 123,
// borderColor: Object|Array|int
// The border color. Default is "#C9DFF2".
borderColor: "#C9DFF2",
// fillColor: Object|Array|int
// The background color. Default is "#FCFCFF".
fillColor: "#FCFCFF",
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#F01E28".
indicatorColor: "#F01E28",
constructor: function(){
// Base colors
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
// Draw background
this.addElement("background", lang.hitch(this, this.drawBackground));
// Scaler
var scaler = new LinearScaler();
// Scale
var scale = new CircularScale();
scale.set("scaler", scaler);
this.addElement("scale", scale);
// Value indicator
var indicator = new CircularValueIndicator();
scale.addIndicator("indicator", indicator);
// Gauge Foreground (needle cap)
this.addElement("foreground", lang.hitch(this, this.drawForeground));
// Indicator Text Border
this.addElement("indicatorTextBorder", lang.hitch(this, this.drawTextBorder), "leading");
// Indicator Text
var indicatorText = new TextIndicator();
indicatorText.set("indicator", indicator);
indicatorText.set("x", 100);
indicatorText.set("y", 115);
this.addElement("indicatorText", indicatorText);
utils.genericCircularGauge(scale, indicator, this._width / 2, 0.76 * this._height, this._radius, 166, 14, null, null, "inside");
},
drawBackground: function(g){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// tags:
// protected
var w = this._width;
var h = this._height;
var gap = 0;
var cr = 3;
var entries = utils.createGradient([0, utils.brightness(this.borderColor, -20), 0.1, utils.brightness(this.borderColor, -40)]);
g.createRect({
x: 0,
y: 0,
width: w,
height: h,
r: cr
}).setFill(lang.mixin({
type: "linear",
x1: 0,
y1: 0,
x2: w,
y2: h
}, entries)).setStroke({
color: "#A5A5A5",
width: 0.2
});
entries = utils.createGradient([0, utils.brightness(this.borderColor, 70), 1, utils.brightness(this.borderColor, -50)]);
gap = 4;
cr = 2
g.createRect({
x: gap,
y: gap,
width: w - 2 * gap,
height: h - 2 * gap,
r: cr
}).setFill(lang.mixin({
type: "linear",
x1: 0,
y1: 0,
x2: w,
y2: h
}, entries));
gap = 6;
cr = 1
entries = utils.createGradient([0, utils.brightness(this.borderColor, 60), 1, utils.brightness(this.borderColor, -40)]);
g.createRect({
x: gap,
y: gap,
width: w - 2 * gap,
height: h - 2 * gap,
r: cr
}).setFill(lang.mixin({
type: "linear",
x1: 0,
y1: 0,
x2: w,
y2: h
}, entries));
gap = 7;
cr = 0
entries = utils.createGradient([0, utils.brightness(this.borderColor, 70), 1, utils.brightness(this.borderColor, -40)]);
g.createRect({
x: gap,
y: gap,
width: w - 2 * gap,
height: h - 2 * gap,
r: cr
}).setFill(lang.mixin({
type: "linear",
x1: w,
y1: 0,
x2: 0,
y2: h
}, entries));
gap = 5;
cr = 0
entries = utils.createGradient([0, [255, 255, 255, 220], 0.8, utils.brightness(this.fillColor, -5), 1, utils.brightness(this.fillColor, -30)]);
g.createRect({
x: gap,
y: gap,
width: w - 2 * gap,
height: h - 2 * gap,
r: cr
}).setFill(lang.mixin({
type: "radial",
cx: w/2,
cy: h/2,
r: h
}, entries)).setStroke({
color: utils.brightness(this.fillColor, -40),
width: 0.4
});
},
drawForeground: function(g){
// summary:
// Draws the foreground shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the foreground.
// tags:
// protected
var r = 0.07 * this._radius;
var entries = utils.createGradient([0, this.borderColor, 1, utils.brightness(this.borderColor, -20)]);
g.createEllipse({
cx: this._width / 2,
cy: 0.76 * this._height,
rx: r,
ry: r
}).setFill(lang.mixin({
type: "radial",
cx: this._width / 2 - 5,
cy: this._height * 0.76 - 5,
r: r
}, entries)).setStroke({
color: utils.brightness(this.fillColor, -50),
width: 0.4
});
},
drawTextBorder: function(g){
// summary:
// Internal method.
// tags:
// private
return g.createRect({
x: this._width / 2 - 12,
y: this._height - 20,
width: 24,
height: 14
}).setStroke({
color: utils.brightness(this.fillColor, -20),
width: 0.3
});
}
});
});
},
'dojox/dgauges/components/default/VerticalLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../utils",
"../../RectangularGauge",
"../../LinearScaler",
"../../RectangularScale",
"../../RectangularValueIndicator",
"../../RectangularRangeIndicator",
"../../TextIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, utils, RectangularGauge, LinearScaler, RectangularScale, RectangularValueIndicator, RectangularRangeIndicator, TextIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.default.VerticalLinearGauge", [RectangularGauge, DefaultPropertiesMixin], {
// summary:
// A vertical gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#C9DFF2".
borderColor: "#C9DFF2",
// fillColor: Object|Array|int
// The background color. Default is "#FCFCFF".
fillColor: "#FCFCFF",
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#F01E28".
indicatorColor: "#F01E28",
constructor: function(){
this.orientation = "vertical";
// Base colors
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
// Draw background
this.addElement("background", lang.hitch(this, this.drawBackground));
// Scaler
var scaler = new LinearScaler();
// Scale
var scale = new RectangularScale();
scale.set("scaler", scaler);
scale.set("labelPosition", "leading");
scale.set("paddingBottom", 20);
scale.set("paddingLeft", 25);
this.addElement("scale", scale);
// Value indicator
var indicator = new RectangularValueIndicator();
indicator.indicatorShapeFunc = lang.hitch(this, function(group){
var indic = group.createPolyline([0, 0, 10, 0, 0, 10, -10, 0, 0, 0]).setStroke({
color: "blue",
width: 0.25
}).setFill(this.indicatorColor);
return indic;
});
indicator.set("paddingLeft", 45);
indicator.set("interactionArea", "gauge");
scale.addIndicator("indicator", indicator);
// Indicator Text Border
this.addElement("indicatorTextBorder", lang.hitch(this, this.drawTextBorder), "leading");
// Indicator Text
var indicatorText = new TextIndicator();
indicatorText.set("indicator", indicator);
indicatorText.set("x", 22.5);
indicatorText.set("y", 30);
this.addElement("indicatorText", indicatorText);
},
drawBackground: function(g, w, h){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// w: Number
// The width of the gauge.
// h: Number
// The height of the gauge.
// tags:
// protected
w = 49;
var gap = 0;
var cr = 3;
var entries = utils.createGradient([0, utils.brightness(this.borderColor, -20), 0.1, utils.brightness(this.borderColor, -40)]);
g.createRect({
x: 0,
y: 0,
width: w,
height: h,
r: cr
}).setFill(lang.mixin({
type: "linear",
x1: 0,
y1: 0,
x2: w,
y2: h
}, entries)).setStroke({
color: "#A5A5A5",
width: 0.2
});
entries = utils.createGradient([0, utils.brightness(this.borderColor, 70), 1, utils.brightness(this.borderColor, -50)]);
gap = 4;
cr = 2
g.createRect({
x: gap,
y: gap,
width: w - 2 * gap,
height: h - 2 * gap,
r: cr
}).setFill(lang.mixin({
type: "linear",
x1: 0,
y1: 0,
x2: w,
y2: h
}, entries));
gap = 6;
cr = 1
entries = utils.createGradient([0, utils.brightness(this.borderColor, 60), 1, utils.brightness(this.borderColor, -40)]);
g.createRect({
x: gap,
y: gap,
width: w - 2 * gap,
height: h - 2 * gap,
r: cr
}).setFill(lang.mixin({
type: "linear",
x1: 0,
y1: 0,
x2: w,
y2: h
}, entries));
gap = 7;
cr = 0
entries = utils.createGradient([0, utils.brightness(this.borderColor, 70), 1, utils.brightness(this.borderColor, -40)]);
g.createRect({
x: gap,
y: gap,
width: w - 2 * gap,
height: h - 2 * gap,
r: cr
}).setFill(lang.mixin({
type: "linear",
x1: w,
y1: 0,
x2: 0,
y2: h
}, entries));
gap = 5;
cr = 0
entries = utils.createGradient([0, [255, 255, 255, 220], 0.8, utils.brightness(this.fillColor, -5), 1, utils.brightness(this.fillColor, -30)]);
g.createRect({
x: gap,
y: gap,
width: w - 2 * gap,
height: h - 2 * gap,
r: cr
}).setFill(lang.mixin({
type: "radial",
cx: 0,
cy: h / 2,
r: h
}, entries)).setStroke({
color: utils.brightness(this.fillColor, -40),
width: 0.4
});
},
drawTextBorder: function(g){
// summary:
// Internal method.
// tags:
// private
return g.createRect({
x: 5,
y: 5,
width: 40,
height: 40
}).setStroke({
color: "#CECECE",
width: 1
});
}
});
});
},
'dojox/dgauges/RectangularGauge':function(){
define(["dojo/_base/declare", "./GaugeBase", "dojox/gfx/matrix"], function(declare, GaugeBase, matrix){
return declare("dojox.dgauges.RectangularGauge", GaugeBase, {
// summary:
// The base class for rectangular gauges.
// You can create custom horizontal or vertical gauges by extending this class.
// See dojox/dgauges/components/default/HorinzontalLinearGauge.js for an example of rectangular gauge.
// orientation: "horizontal"|"vertical"
// The orientation of the gauge. Default is "horizontal".
orientation: "horizontal",
// leading, middle and trailing graphical parts
_middleParts: null,
_leadingParts: null,
_trailingParts: null,
_baseParts: null,
_classParts: null,
_layoutInfos: {},
constructor: function(){
this.orientation = "horizontal";
this._middleParts = [];
this._leadingParts = [];
this._trailingParts = [];
this._baseParts = [];
this._classParts = [];
this._layoutInfos = {
leading: {
x: 0,
y: 0,
w: 0,
h: 0
},
middle: {
x: 0,
y: 0,
w: 0,
h: 0
},
trailing: {
x: 0,
y: 0,
w: 0,
h: 0
}
};
this.addInvalidatingProperties(["orientation"]);
},
addElement: function(name, element, location){
// summary:
// Adds a element to the gauge.
// name: String
// The name of the element to be added.
// element: Object
// This parameter can be:
// - A function which takes on argument of type GFX Group and return null or a
// GFX element retrievable using the getElementRenderer() method.
// - A Scale instance, i.e. CircularScale or RectangularScale.
// - A TextIndicator instance.
// location: String
// The area to place the element. Valid values are "leading"|"middle"|"trailing". Leading and trailing areas are fixed size. The
// middle area use the remaining size. If not specified, the element's refreshRendering
// is called with the whole gauge size as argument.
this.inherited(arguments);
var obj = this._elements[this._elements.length - 1];
if(location == "middle"){
this._middleParts.push(obj);
}else if(location == "leading"){
this._leadingParts.push(obj);
}else if(location == "trailing"){
this._trailingParts.push(obj);
}else{
if(obj._isGFX){
this._baseParts.push(obj);
}else{
this._classParts.push(obj);
}
}
},
removeElement: function(name){
// summary:
// Remove the element defined by name from the gauge.
// name: String
// The name of the element as defined using addElement.
// returns: Object
// A reference to the removed element.
var obj = this.getElement(name);
if(obj){
if(this._middleParts && this._middleParts.indexOf(obj) >= 0){
this._middleParts.splice(this._middleParts.indexOf(obj), 1);
}else if(this._leadingParts && this._leadingParts.indexOf(obj) >= 0){
this._leadingParts.splice(this._leadingParts.indexOf(obj), 1);
}else if(this._trailingParts && this._trailingParts.indexOf(obj) >= 0){
this._trailingParts.splice(this._trailingParts.indexOf(obj), 1);
}else if(this._baseParts && this._baseParts.indexOf(obj) >= 0){
this._baseParts.splice(this._baseParts.indexOf(obj), 1);
}else if(this._classParts && this._classParts.indexOf(obj) >= 0){
this._classParts.splice(this._classParts.indexOf(obj), 1);
}
}
this.inherited(arguments);
},
_computeArrayBoundingBox: function(elements){
// summary:
// Internal method.
// tags:
// private
if(elements.length == 0){
return {x: 0, y: 0, w: 0, h: 0};
}
var bbox = null;
var minX, minY, maxX, maxY;
minX = minY = +Infinity;
maxX = maxY = -Infinity;
for(var i = 0; i < elements.length; i++){
bbox = this._computeBoundingBox(elements[i]._gfxGroup);
if(minX > bbox.x){
minX = bbox.x;
}
if(minY > bbox.y){
minY = bbox.y;
}
if(maxX < bbox.x + bbox.width){
maxX = bbox.x + bbox.width;
}
if(maxY < bbox.y + bbox.height){
maxY = bbox.y + bbox.height;
}
}
return {x: minX, y:minY, w: maxX-minX, h: maxY-minY};
},
refreshRendering: function(){
if(this._widgetBox.w <= 0 || this._widgetBox.h <= 0){
return;
}
var i;
if(this._baseParts){
for(i = 0; i < this._baseParts.length; i++){
this._baseParts[i].width = this._widgetBox.w;
this._baseParts[i].height = this._widgetBox.h;
this._elementsRenderers[this._baseParts[i]._name] = this._baseParts[i].refreshRendering();
}
}
if(this._leadingParts){
for(i = 0; i < this._leadingParts.length; i++){
this._elementsRenderers[this._leadingParts[i]._name] = this._leadingParts[i].refreshRendering();
}
}
if(this._trailingParts){
for(i = 0; i < this._trailingParts.length; i++){
this._elementsRenderers[this._trailingParts[i]._name] = this._trailingParts[i].refreshRendering();
}
}
var leadingBoundingBox = this._computeArrayBoundingBox(this._leadingParts);
var trailingBoundingBox = this._computeArrayBoundingBox(this._trailingParts);
var middleBoundingBox = {};
if(this.orientation == "horizontal"){
middleBoundingBox.x = leadingBoundingBox.x + leadingBoundingBox.w;
middleBoundingBox.y = 0;
middleBoundingBox.w = this._widgetBox.w - leadingBoundingBox.w - trailingBoundingBox.w;
middleBoundingBox.h = this._widgetBox.h;
}else{
middleBoundingBox.x = 0;
middleBoundingBox.y = leadingBoundingBox.y + leadingBoundingBox.h;
middleBoundingBox.w = this._widgetBox.w;
middleBoundingBox.h = this._widgetBox.h - leadingBoundingBox.h - trailingBoundingBox.h;
}
this._layoutInfos = {
leading: leadingBoundingBox,
middle: middleBoundingBox,
trailing: trailingBoundingBox
};
// translates middle part
for(i = 0; i < this._middleParts.length; i++){
this._middleParts[i]._gfxGroup.setTransform([matrix.translate(middleBoundingBox.x, middleBoundingBox.y)]);
}
// translates trailing part
if(this._trailingParts){
for(i = 0; i < this._trailingParts.length; i++){
this._trailingParts[i]._gfxGroup.setTransform(matrix.translate(this._widgetBox.w - trailingBoundingBox.w, 0));
}
}
// Render remaining elements (scales, ...)
for(i = 0; i < this._classParts.length; i++){
this._elementsRenderers[this._classParts[i]._name] = this._classParts[i].refreshRendering();
}
}
})
});
},
'dojox/dgauges/RectangularScale':function(){
define(["dojo/_base/declare", "dojox/gfx", "./ScaleBase"], function(declare, gfx, ScaleBase){
return declare("dojox.dgauges.RectangularScale", ScaleBase, {
// summary:
// The rectangular scale. A scaler must be set to use this class.
// paddingLeft: Number
// The left padding.
paddingLeft: 15,
// paddingTop: Number
// The top padding.
paddingTop: 12,
// paddingRight: Number
// The right padding.
paddingRight: 15,
// paddingBottom: Number
// The bottom padding.
paddingBottom: 0,
_contentBox: null,
constructor: function(){
this.labelPosition = "leading";
this.addInvalidatingProperties(["paddingTop", "paddingLeft", "paddingRight", "paddingBottom"]);
},
positionForValue: function(value){
// summary:
// Transforms a value into a position using the associated scaler.
// value:
// The value to transform.
// returns: Number
// A position in pixels.
var relativePos = 0;
var position;
var spos = 0;
var length = 0;
if(this._contentBox){
if(this._gauge.orientation == "horizontal"){
spos = this._contentBox.x;
length = this._contentBox.w;
}else{
spos = this._contentBox.y;
length = this._contentBox.h;
}
}
relativePos = this.scaler.positionForValue(value);
position = spos + (relativePos * length);
return position;
},
valueForPosition: function(pos){
// summary:
// Transforms a position in pixels into a value using the associated scaler.
// pos:
// The position to transform.
// returns: Number
// The value represented by pos.
var value = this.scaler.minimum;
var position = NaN;
var spos = 0;
var epos = 0;
if(this._gauge.orientation == "horizontal"){
position = pos.x;
spos = this._contentBox.x;
epos = this._contentBox.x + this._contentBox.w;
}else{
position = pos.y;
spos = this._contentBox.y;
epos = this._contentBox.y + this._contentBox.h;
}
if(position <= spos){
value = this.scaler.minimum;
}else if(position >= epos){
value = this.scaler.maximum;
}else {
value = this.scaler.valueForPosition((position - spos)/(epos - spos));
}
return value;
},
refreshRendering: function(){
this.inherited(arguments);
if(!this._gfxGroup || !this.scaler)
return;
this._ticksGroup.clear();
// variables for ticks rendering
var middleBox = this._gauge._layoutInfos.middle;
this._contentBox = {};
this._contentBox.x = middleBox.x + this.paddingLeft;
this._contentBox.y = middleBox.y + this.paddingTop;
this._contentBox.w = middleBox.w - (this.paddingLeft + this.paddingRight);
this._contentBox.h = middleBox.h - (this.paddingBottom + this.paddingTop);
var renderer;
// variables for tick labels
var labelText;
var font = this._getFont();
// Layout ticks
var allTicks = this.scaler.computeTicks();
for(var i = 0; i < allTicks.length; i++){
var tickItem = allTicks[i];
renderer = this.tickShapeFunc(this._ticksGroup, this, tickItem);
if(renderer){
var a = this.positionForValue(tickItem.value);
var tickSize = this._gauge._computeBoundingBox(renderer).width;
var x1 = 0, y1 = 0, angle = 0;
if(this._gauge.orientation == "horizontal"){
x1 = a;
y1 = this._contentBox.y;
angle = 90;
}else{
x1 = this._contentBox.x;
y1 = a;
}
renderer.setTransform([{
dx: x1,
dy: y1
}, gfx.matrix.rotateg(angle)]);
}
labelText = this.tickLabelFunc(tickItem);
if(labelText){
var tbox = gfx._base._getTextBox(labelText, {
font: gfx.makeFontString(gfx.makeParameters(gfx.defaultFont, font))
});
var tw = tbox.w;
var th = tbox.h;
var al = "start";
var xt = x1;
var yt = y1;
if(this._gauge.orientation == "horizontal"){
xt = x1;
if(this.labelPosition == "trailing"){
yt = y1 + tickSize + this.labelGap + th;
}else{
yt = y1 - this.labelGap;
}
al = "middle";
}else{
if(this.labelPosition == "trailing"){
xt = x1 + tickSize + this.labelGap;
}else{
xt = x1 - this.labelGap - tw;
}
yt = y1 + th / 2;
}
var t = this._ticksGroup.createText({
x: xt,
y: yt,
text: labelText,
align: al
});
t.setFill(font.color ? font.color : "black");
t.setFont(font);
}
}
for(var key in this._indicatorsIndex){
this._indicatorsRenderers[key] = this._indicatorsIndex[key].invalidateRendering();
}
}
})
});
},
'dojox/dgauges/RectangularValueIndicator':function(){
define(["dojo/_base/declare", "./ScaleIndicatorBase", "dojox/gfx", "dojo/_base/event", "dojo/dom-geometry"],
function(declare, ScaleIndicatorBase, gfx, eventUtil, domGeom){
return declare("dojox.dgauges.RectangularValueIndicator", ScaleIndicatorBase, {
// summary:
// The rectangular value indicator, typically used for creating markers or thumbs.
// paddingLeft: Number
// The left padding.
paddingLeft: 0,
// paddingTop: Number
// The top padding.
paddingTop: 0,
// paddingRight: Number
// The right padding.
paddingRight: 0,
// paddingBottom: Number
// The bottom padding.
paddingBottom: 0,
constructor: function(){
this.addInvalidatingProperties(["paddingTop", "paddingLeft", "paddingRight", "paddingBottom"]);
},
indicatorShapeFunc: function(group, indicator){
// summary:
// Draws the indicator.
// group: dojox/gfx/Group
// A GFX group for drawing. The indicator is always centered horizontally and is
// automatically rotated if the scale is vertical.
// indicator: dojox/dgauges/IndicatorBase
// A reference to this indicator.
// returns: dojox/gfx/shape.Shape
// A GFX shape retrievable using the getIndicatorRenderer method of the associated scale.
return group.createPolyline([0, 0, 10, 0, 0, 10, -10, 0, 0, 0]).setStroke({
color: "black",
width: 1
});
},
refreshRendering: function(){
this.inherited(arguments);
// get position corresponding to the value
var v = isNaN(this._transitionValue) ? this.value : this._transitionValue;
var pos = this.scale.positionForValue(v);
// computes offsets to move the indicator
var dx = 0, dy = 0;
var angle = 0;
if(this.scale._gauge.orientation == "horizontal"){
dx = pos;
dy = this.paddingTop;
}else{
dx = this.paddingLeft;
dy = pos;
angle = 90;
}
// translate the indicator
this._gfxGroup.setTransform([{
dx: dx,
dy: dy
}, gfx.matrix.rotateg(angle)]);
},
_onMouseDown: function(event){
// summary:
// Internal method.
// tags:
// private
this.inherited(arguments);
var np = domGeom.position(this.scale._gauge.domNode, true);
this.set("value", this.scale.valueForPosition({x: event.pageX - np.x, y: event.pageY - np.y}));
// prevent the browser from selecting text
eventUtil.stop(event);
},
_onMouseMove: function(event){
// summary:
// Internal method.
// tags:
// private
this.inherited(arguments);
var np = domGeom.position(this.scale._gauge.domNode, true);
this.set("value", this.scale.valueForPosition({x: event.pageX - np.x, y: event.pageY - np.y}));
}
})
});
},
'dojox/dgauges/RectangularRangeIndicator':function(){
define(["dojo/_base/declare", "dojox/gfx", "./ScaleIndicatorBase", "dojo/_base/event", "dojo/dom-geometry"],
function(declare, gfx, ScaleIndicatorBase, eventUtil, domGeom){
return declare("dojox.dgauges.RectangularRangeIndicator", ScaleIndicatorBase, {
// summary:
// A RectangularRangeIndicator is used to represent a range of values on a scale.
// For adding this kind of indicator instance to the gauge, use the addIndicator
// method of RectangularScale.
// start: Number
// The start value of the range. Default is 0.
start: 0,
// startThickness: Number
// The thickness in pixels of the shape at the position defined by the start property.
// Default is 10.
startThickness: 10,
// endThickness: Number
// The thickness in pixels of the shape at the position defined by the value property.
// Default is 10.
endThickness: 10,
// fill: Object
// A fill object that will be passed to the setFill method of GFX.
fill: null,
// stroke: Object
// A stroke object that will be passed to the setStroke method of GFX.
stroke: null,
// paddingLeft: Number
// The left padding. Not used for horizontal gauges.
paddingLeft: 10,
// paddingTop: Number
// The top padding. Not used for vertical gauges.
paddingTop: 10,
// paddingRight: Number
// The right padding. Not used for horizontal gauges.
paddingRight: 10,
// paddingBottom: Number
// The bottom padding. Not used for vertical gauges.
paddingBottom: 10,
constructor: function(){
this.fill = [255, 120, 0];
this.stroke = {
color: "black",
width: .2
};
this.interactionMode = "none";
this.addInvalidatingProperties(["start", "startThickness", "endThickness", "fill", "stroke"]);
},
_defaultHorizontalShapeFunc: function(indicator, group, scale, startX, startY, endPosition, startThickness, endThickness, fill, stroke){
// summary:
// Internal method.
// tags:
// private
var gp = [startX, startY, endPosition, startY, endPosition, startY + endThickness, startX, startY + startThickness, startX, startY]
if(fill && fill.colors){
// Configure gradient
fill.x1 = startX;
fill.y1 = startY;
fill.x2 = endPosition;
fill.y2 = startY;
}
return group.createPolyline(gp).setFill(fill).setStroke(stroke);
},
_defaultVerticalShapeFunc: function(indicator, group, scale, startX, startY, endPosition, startThickness, endThickness, fill, stroke){
// summary:
// Internal method.
// tags:
// private
var gp = [startX, startY, startX, endPosition, startX + endThickness, endPosition, startX + startThickness, startY, startX, startY]
if(fill && fill.colors){
// Configure gradient
fill.x1 = startX;
fill.y1 = startY;
fill.x2 = startX;
fill.y2 = endPosition;
}
return group.createPolyline(gp).setFill(fill).setStroke(stroke);
},
_shapeFunc: function(indicator, group, scale, startX, startY, endPosition, startThickness, endThickness, fill, stroke){
// summary:
// Internal method.
// tags:
// private
if(this.scale._gauge.orientation == "horizontal"){
this._defaultHorizontalShapeFunc(indicator, group, scale, startX, startY, endPosition, startThickness, endThickness, fill, stroke);
}else{
this._defaultVerticalShapeFunc(indicator, group, scale, startX, startY, endPosition, startThickness, endThickness, fill, stroke);
}
},
refreshRendering: function(){
this.inherited(arguments);
if(this._gfxGroup == null || this.scale == null){
return;
}
// gets position corresponding to the values
var spos = this.scale.positionForValue(this.start);
var v = isNaN(this._transitionValue) ? this.value : this._transitionValue;
var pos = this.scale.positionForValue(v);
this._gfxGroup.clear();
var startX;
var startY;
var endPosition;
if(this.scale._gauge.orientation == "horizontal"){
startX = spos;
startY = this.paddingTop;
endPosition = pos;
}else{
startX = this.paddingLeft;
startY = spos;
endPosition = pos;
}
this._shapeFunc(this, this._gfxGroup, this.scale, startX, startY, endPosition, this.startThickness, this.endThickness, this.fill, this.stroke);
},
_onMouseDown: function(event){
// summary:
// Internal method.
// tags:
// private
this.inherited(arguments);
var np = domGeom.position(this.scale._gauge.domNode, true);
this.set("value", this.scale.valueForPosition({x: event.pageX - np.x, y: event.pageY - np.y}));
// prevent the browser from selecting text
eventUtil.stop(event);
},
_onMouseMove: function(event){
// summary:
// Internal method.
// tags:
// private
this.inherited(arguments);
var np = domGeom.position(this.scale._gauge.domNode, true);
this.set("value", this.scale.valueForPosition({x: event.pageX - np.x, y: event.pageY - np.y}));
}
})
});
},
'dojox/dgauges/components/default/HorizontalLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../utils",
"../../RectangularGauge",
"../../LinearScaler",
"../../RectangularScale",
"../../RectangularValueIndicator",
"../../TextIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, utils, RectangularGauge, LinearScaler, RectangularScale, RectangularValueIndicator, TextIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.default.HorizontalLinearGauge", [RectangularGauge, DefaultPropertiesMixin], {
// summary:
// A horizontal gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#C9DFF2".
borderColor: "#C9DFF2",
// fillColor: Object|Array|int
// The background color. Default is "#FCFCFF".
fillColor: "#FCFCFF",
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#F01E28".
indicatorColor: "#F01E28",
constructor: function(){
// Base colors
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
// Draw background
this.addElement("background", lang.hitch(this, this.drawBackground));
// Scaler
var scaler = new LinearScaler();
// Scale
var scale = new RectangularScale();
scale.set("scaler", scaler);
scale.set("labelPosition", "trailing");
scale.set("paddingTop", 15);
scale.set("paddingRight", 23);
this.addElement("scale", scale);
// Value indicator
var indicator = new RectangularValueIndicator();
indicator.indicatorShapeFunc = lang.hitch(this, function(group){
var indic = group.createPolyline([0, 0, 10, 0, 0, 10, -10, 0, 0, 0]).setStroke({
color: "blue",
width: 0.25
}).setFill(this.indicatorColor);
return indic;
});
indicator.set("paddingTop", 5);
indicator.set("interactionArea", "gauge");
scale.addIndicator("indicator", indicator);
// Indicator Text Border
this.addElement("indicatorTextBorder", lang.hitch(this, this.drawTextBorder), "leading");
// Indicator Text
var indicatorText = new TextIndicator();
indicatorText.set("indicator", indicator);
indicatorText.set("x", 32.5);
indicatorText.set("y", 30);
this.addElement("indicatorText", indicatorText);
},
drawBackground: function(g, w, h){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// w: Number
// The width of the gauge.
// h: Number
// The height of the gauge.
// tags:
// protected
h = 49;
var gap = 0;
var cr = 3;
var entries = utils.createGradient([0, utils.brightness(this.borderColor, -20), 0.1, utils.brightness(this.borderColor, -40)]);
g.createRect({
x: 0,
y: 0,
width: w,
height: h,
r: cr
}).setFill(lang.mixin({
type: "linear",
x1: 0,
y1: 0,
x2: w,
y2: h
}, entries)).setStroke({
color: "#A5A5A5",
width: 0.2
});
entries = utils.createGradient([0, utils.brightness(this.borderColor, 70), 1, utils.brightness(this.borderColor, -50)]);
gap = 4;
cr = 2
g.createRect({
x: gap,
y: gap,
width: w - 2 * gap,
height: h - 2 * gap,
r: cr
}).setFill(lang.mixin({
type: "linear",
x1: 0,
y1: 0,
x2: w,
y2: h
}, entries));
gap = 6;
cr = 1
entries = utils.createGradient([0, utils.brightness(this.borderColor, 60), 1, utils.brightness(this.borderColor, -40)]);
g.createRect({
x: gap,
y: gap,
width: w - 2 * gap,
height: h - 2 * gap,
r: cr
}).setFill(lang.mixin({
type: "linear",
x1: 0,
y1: 0,
x2: w,
y2: h
}, entries));
gap = 7;
cr = 0
entries = utils.createGradient([0, utils.brightness(this.borderColor, 70), 1, utils.brightness(this.borderColor, -40)]);
g.createRect({
x: gap,
y: gap,
width: w - 2 * gap,
height: h - 2 * gap,
r: cr
}).setFill(lang.mixin({
type: "linear",
x1: w,
y1: 0,
x2: 0,
y2: h
}, entries));
gap = 5;
cr = 0
entries = utils.createGradient([0, [255, 255, 255, 220], 0.8, utils.brightness(this.fillColor, -5), 1, utils.brightness(this.fillColor, -30)]);
g.createRect({
x: gap,
y: gap,
width: w - 2 * gap,
height: h - 2 * gap,
r: cr
}).setFill(lang.mixin({
type: "radial",
cx: w / 2,
cy: 0,
r: w
}, entries)).setStroke({
color: utils.brightness(this.fillColor, -40),
width: 0.4
});
},
drawTextBorder: function(g){
// summary:
// Internal method.
// tags:
// private
return g.createRect({
x: 5,
y: 5,
width: 60,
height: 39
}).setStroke({
color: "#CECECE",
width: 1
});
}
});
});
},
'dojox/dgauges/components/black/CircularLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../../CircularGauge",
"../../LinearScaler",
"../../CircularScale",
"../../CircularValueIndicator",
"../../CircularRangeIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, CircularGauge, LinearScaler, CircularScale, CircularValueIndicator, CircularRangeIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.black.CircularLinearGauge", [CircularGauge, DefaultPropertiesMixin], {
// summary:
// A circular gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#000000".
borderColor: "#000000",
// fillColor: Object|Array|int
// The background color. Default is "#000000".
fillColor: "#000000",
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#A4A4A4".
indicatorColor: "#A4A4A4",
constructor: function(){
// Base colors
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
var scaler = new LinearScaler();
this.addElement("background", lang.hitch(this, this.drawBackground));
var scale = new CircularScale();
scale.set("scaler", scaler);
scale.set("radius", 149.82183);
scale.set("originX", 186.9446);
scale.set("originY", 184.74838);
scale.set("startAngle", 130.16044);
scale.set("endAngle", 50.25444);
scale.set("orientation", "clockwise");
scale.set("labelGap", 8);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "14pt",
color: "#CECECE"
});
scale.set("tickShapeFunc", function(group, scale, tick){
return group.createCircle({
r: tick.isMinor ? 2 : 4
}).setFill("#CECECE");
});
this.addElement("scale", scale);
var indicator = new CircularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group, indicator){
return group.createPolyline([0, -12, indicator.scale.radius - 2, 0, 0, 12, 0, -12]).setStroke({
color: [70, 70, 70],
width: 1
}).setFill(this.indicatorColor);
}));
scale.addIndicator("indicator", indicator);
this.addElement("foreground", lang.hitch(this, this.drawForeground));
},
drawBackground: function(g){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// tags:
// protected
g.createPath({
path: "M372.9962 186.58 C373.0312 289.5712 289.57 373.0888 186.5787 373.1237 C83.5887 373.16 0.07 289.6975 0.035 186.7062 L0.035 186.58 C-0 83.5888 83.4625 0.0712 186.4524 0.0362 C289.4425 -0 372.9611 83.4625 372.9962 186.4525 L372.9962 186.58 Z"
}).setFill(this.borderColor);
g.createPath({
path: "M358.7902 186.5795 C358.8253 281.7258 281.7202 358.8808 186.574 358.9145 C91.4277 358.9471 14.2715 281.842 14.239 186.6957 L14.239 186.5795 C14.2077 91.4332 91.3127 14.2782 186.4565 14.2445 C281.6027 14.2132 358.759 91.317 358.7902 186.4633 L358.7902 186.5795 Z"
}).setFill({
type: "linear",
x1: 14.23897,
y1: 358.91452,
x2: 14.23897,
y2: 221.04652,
colors: [
{offset: 0, color: [100,100,100]},
{offset: 1, color: this.fillColor}
]
});
g.createPath({
path: "M358.749 182.9033 C356.8202 89.4033 280.4165 14.2132 186.4615 14.2445 C92.5465 14.277 16.2165 89.4533 14.289 182.9008 C66.884 197.0646 127.4052 168.8146 188.7977 168.8146 C250.209 168.8146 306.3027 197.0708 358.749 182.9033"
}).setFill({
type: "linear",
x1: 14.28899,
y1: 186.87839,
x2: 14.28899,
y2: 14.24451,
colors: [
{offset: 0, color: this.fillColor},
{offset: 1, color: [200,200,200]}
]
});
g.createPath({
path: "M358.7457 182.9033 C356.817 89.4033 280.4132 14.2133 186.4582 14.2445 C92.5432 14.277 16.2132 89.4533 14.2857 182.9008 C66.8807 197.0646 127.402 168.8146 188.7945 168.8146 C250.2057 168.8146 306.2995 197.0708 358.7457 182.9033"
}).setFill([255,255,255,0.12157]);
},
drawForeground: function(g){
// summary:
// Draws the foreground shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the foreground.
// tags:
// protected
var g1 = g.createGroup();
g1.createPath({
path: "M214.9859 185.33 C214.9909 201.0537 202.2496 213.8037 186.5259 213.81 C170.7996 213.815 158.0496 201.0725 158.0446 185.35 L158.0446 185.33 C158.0384 169.6062 170.7821 156.8562 186.5071 156.85 C202.2296 156.845 214.9809 169.5875 214.9859 185.3113 L214.9859 185.33 Z"
}).setFill(this.borderColor);
g1.createPath({
path: "M211.4015 185.3295 C211.4052 199.0745 200.2689 210.2183 186.524 210.2232 C172.7802 210.2282 161.6352 199.0908 161.6302 185.347 L161.6302 185.3295 C161.6252 171.5858 172.7628 160.4408 186.5065 160.4358 C200.2515 160.4308 211.3965 171.5695 211.4015 185.3133 L211.4015 185.3295 Z"
}).setFill({
type: "linear",
x1: 161.63024,
y1: 210.22326,
x2: 161.63024,
y2: 185.32952,
colors: [
{offset: 0, color: [100,100,100]},
{offset: 1, color: this.fillColor}
]
});
g1.createPath({
path: "M211.3952 184.7995 C211.1165 171.2933 200.0802 160.4308 186.5077 160.4358 C172.9415 160.4408 161.9152 171.2995 161.6377 184.7995 C169.234 186.8446 177.9752 182.7645 186.8465 182.7645 C195.7165 182.7645 203.819 186.8458 211.3952 184.7995"
}).setFill({
type: "linear",
x1: 161.63772,
y1: 185.37364,
x2: 161.63772,
y2: 160.43577,
colors: [
{offset: 0, color: this.fillColor},
{offset: 1, color: [150,150,150]}
]
});
g1.createPath({
path: "M211.3946 184.799 C211.1158 171.2928 200.0796 160.4315 186.5084 160.4365 C172.9409 160.4415 161.9159 171.3003 161.6371 184.799 C169.2334 186.844 177.9759 182.764 186.8458 182.764 C195.7158 182.764 203.8184 186.8465 211.3946 184.799"
}).setFill([255,255,255,0.12157]);
}
});
}
);
},
'dojox/dgauges/CircularRangeIndicator':function(){
define(["dojo/_base/declare", "./ScaleIndicatorBase", "./_circularUtils", "dojo/_base/event"],
function(declare, ScaleIndicatorBase, _circularUtils, eventUtil){
return declare("dojox.dgauges.CircularRangeIndicator", ScaleIndicatorBase, {
// summary:
// A CircularRangeIndicator is used to represent a range of values on a scale.
// Use the addIndicator method of CircularScale to use it.
// It is represented as a donut slice.
// start: Number
// The start value of the range indicator.
start: 0,
// radius: Number
// The outer radius in pixels of the range indicator.
radius: NaN,
// startThickness: Number
// The start thickness of the donut slice in pixels.
startThickness: 6,
// endThickness: Number
// The end thickness of the donut slice in pixels.
endThickness: 6,
// fill: Object
// A fill object that will be passed to the setFill method of GFX.
fill: null,
// stroke: Object
// A stroke object that will be passed to the setStroke method of GFX.
stroke: null,
constructor: function(){
this.indicatorShapeFunc = null;
this.fill = [255, 120, 0];
this.stroke = {
color: "black",
width: .2
};
this.interactionMode = "none";
this.addInvalidatingProperties(["start", "radius", "startThickness", "endThickness", "fill", "stroke"]);
},
_interpolateColor: function(from, dest, n){
// summary:
// Internal method.
// tags:
// private
var fr = (from >> 16) & 0xff;
var fg = (from >> 8) & 0xff;
var fb = from & 0xff;
var tr = (dest >> 16) & 0xff;
var tg = (dest >> 8) & 0xff;
var tb = dest & 0xff;
var r = ((1 - n) * fr + n * tr) & 0xff;
var g = ((1 - n) * fg + n * tg) & 0xff;
var b = ((1 - n) * fb + n * tb) & 0xff;
return r << 16 | g << 8 | b;
},
_colorsInterpolation: function(colors, ratios, len){
// summary:
// Internal method.
// tags:
// private
var ret = [];
var ilen = 0;
for(var i = 0; i < colors.length - 1; i++){
ilen = (ratios[i + 1] - ratios[i]) * len;
ilen = Math.round(ilen);
ret = ret.concat(_colorInterpolation(colors[i], colors[i + 1], ilen));
}
return ret;
},
_alphasInterpolation: function(alphas, positions, len){
// summary:
// Internal method.
// tags:
// private
var ret = [];
var ilen = 0;
for(var i = 0; i < alphas.length - 1; i++){
ilen = (positions[i + 1] - positions[i]) * len;
ilen = Math.round(ilen);
ret = ret.concat(_alphaInterpolation(alphas[i], alphas[i + 1], ilen));
}
return ret;
},
_alphaInterpolation: function(c1, c2, len){
// summary:
// Internal method.
// tags:
// private
var step = (c2 - c1) / (len - 1);
var ret = [];
for(var i = 0; i < len; i++){
ret.push(c1 + i * step);
}
return ret;
},
_colorInterpolation: function(c1, c2, len){
// summary:
// Internal method.
// tags:
// private
var ret = [];
for (var i = 0; i < len; i++){
ret.push(_interpolateColor(c1, c2, i / (len - 1)));
}
return ret;
},
_getEntriesFor: function(entries, attr){
// summary:
// Internal method.
// tags:
// private
var ret = [];
var e;
var val;
for(var i = 0; i < entries.length; i++){
e = entries[i];
if(e[attr] == null || isNaN(e[attr])) {
val = i / (entries.length - 1);
}
else{
val = e[attr];
}
ret.push(val);
}
return ret;
},
_drawColorTrack: function(g, ox, oy, radius, orientation, startAngleRadians, endAngleRadians, sWeight, eWeight, fill, stroke, clippingAngleRadians){
// summary:
// Internal method.
// tags:
// private
var angleStep = 0.05;
var totalAngle;
totalAngle = 6.28318530718 - _circularUtils.computeAngle(startAngleRadians, endAngleRadians, orientation);
if(!isNaN(clippingAngleRadians)){
var deltaAngle = _circularUtils.computeAngle(startAngleRadians, clippingAngleRadians, orientation);
eWeight *= deltaAngle / totalAngle;
totalAngle = deltaAngle;
}
var iterCount = Math.max(2, Math.floor(totalAngle / angleStep));
angleStep = totalAngle / iterCount;
var innerRadius;
var outerRadius;
var outerStep = 0;
var innerStep = 0;
var px;
var py;
innerRadius = -sWeight;
outerRadius = 0;
innerStep = (sWeight - eWeight) / iterCount;
var angle;
var i;
if(orientation == "clockwise"){
angleStep = -angleStep;
}
var gp = [];
px = ox + Math.cos(startAngleRadians) * (radius + innerRadius);
py = oy - Math.sin(startAngleRadians) * (radius + innerRadius);
gp.push(px, py);
for(i = 0; i < iterCount; i++){
angle = startAngleRadians + i * angleStep;
px = ox + Math.cos(angle + angleStep) * (radius + innerRadius + i * innerStep);
py = oy - Math.sin(angle + angleStep) * (radius + innerRadius + i * innerStep);
gp.push(px, py);
}
if(isNaN(angle)){
angle = startAngleRadians;
}
px = ox + Math.cos(angle + angleStep) * (radius + outerRadius + (iterCount - 1) * outerStep);
py = oy - Math.sin(angle + angleStep) * (radius + outerRadius + (iterCount - 1) * outerStep);
gp.push(px, py);
for(i = iterCount - 1; i >= 0; i--){
angle = startAngleRadians + i * angleStep;
px = ox + Math.cos(angle + angleStep) * (radius + outerRadius + i * outerStep);
py = oy - Math.sin(angle + angleStep) * (radius + outerRadius + i * outerStep);
gp.push(px, py);
}
px = ox + Math.cos(startAngleRadians) * (radius + outerRadius);
py = oy - Math.sin(startAngleRadians) * (radius + outerRadius);
gp.push(px, py);
px = ox + Math.cos(startAngleRadians) * (radius + innerRadius);
py = oy - Math.sin(startAngleRadians) * (radius + innerRadius);
gp.push(px, py);
g.createPolyline(gp).setFill(fill).setStroke(stroke);
},
refreshRendering: function(){
this.inherited(arguments);
var g = this._gfxGroup;
g.clear();
var ox = this.scale.originX;
var oy = this.scale.originY;
var radius = isNaN(this.radius) ? this.scale.radius : this.radius;
var orientation = this.scale.orientation;
var startAngleRadians = _circularUtils.toRadians(360 - this.scale.positionForValue(this.start));
var v = isNaN(this._transitionValue) ? this.value : this._transitionValue;
var endAngleRadians = _circularUtils.toRadians(360 - this.scale.positionForValue(v));
var sWeight = this.startThickness;
var eWeight = this.endThickness;
var clippingAngleRadians = NaN;
this._drawColorTrack(g, ox, oy, radius, orientation, startAngleRadians, endAngleRadians, sWeight, eWeight, this.fill, this.stroke, clippingAngleRadians);
},
_onMouseDown: function(event){
// summary:
// Internal method.
// tags:
// private
this.inherited(arguments);
var origin = this.scale._gauge._gaugeToPage(this.scale.originX, this.scale.originY);
var angle = ((Math.atan2(event.pageY - origin.y, event.pageX - origin.x)) * 180) / (Math.PI);
this.set("value", this.scale.valueForPosition(angle));
// prevent the browser from selecting text
eventUtil.stop(event);
},
_onMouseMove: function(event){
// summary:
// Internal method.
// tags:
// private
this.inherited(arguments);
var origin = this.scale._gauge._gaugeToPage(this.scale.originX, this.scale.originY);
var angle = ((Math.atan2(event.pageY - origin.y, event.pageX - origin.x)) * 180) / (Math.PI);
this.set("value", this.scale.valueForPosition(angle));
}
});
});
},
'dojox/dgauges/components/black/SemiCircularLinearGauge':function(){
define(["dojo/_base/lang", "dojo/_base/declare", "dojo/_base/Color",
"../../CircularGauge",
"../../LinearScaler",
"../../CircularScale",
"../../CircularValueIndicator",
"../../CircularRangeIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, CircularGauge, LinearScaler, CircularScale, CircularValueIndicator, CircularRangeIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.black.SemiCircularLinearGauge", [CircularGauge, DefaultPropertiesMixin], {
// summary:
// A semi circular gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#000000".
borderColor: "#000000",
// fillColor: Object|Array|int
// The background color. Default is "#000000".
fillColor: "#000000",
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#A4A4A4".
indicatorColor: "#A4A4A4",
constructor: function(){
// Base colors
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
var scaler = new LinearScaler();
this.addElement("background", lang.hitch(this, this.drawBackground));
var scale = new CircularScale();
scale.set("scaler", scaler);
scale.set("originX", 186.46999);
scale.set("originY", 184.74814);
scale.set("radius", 149.82183);
scale.set("startAngle", -180);
scale.set("endAngle", 0);
scale.set("orientation", "clockwise");
scale.set("labelGap", 8);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "14pt",
color: "#CECECE"
});
scale.set("tickShapeFunc", function(group, scale, tick){
return group.createCircle({
r: tick.isMinor ? 2 : 4
}).setFill("#CECECE");
});
this.addElement("scale", scale);
var indicator = new CircularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group, indicator){
return group.createPolyline([0, -12, indicator.scale.radius - 2, 0, 0, 12, 0, -12]).setStroke({
color: [70, 70, 70],
width: 1
}).setFill(this.indicatorColor);
}));
scale.addIndicator("indicator", indicator);
this.addElement("foreground", lang.hitch(this, this.drawForeground));
},
drawBackground: function(g){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// tags:
// protected
g.createPath({
path: "M372.8838 205.5688 C372.9125 204.4538 372.93 194.135 372.94 185.6062 C372.4475 83.0063 289.1138 -0 186.4063 0.035 C83.7 0.0713 0.4225 83.1325 0 185.7325 C0.01 194.2175 0.0275 204.4638 0.0563 205.5763 C0.235 212.3488 5.7763 217.7462 12.5525 217.7462 L360.3888 217.7462 C367.1663 217.7462 372.71 212.3438 372.8838 205.5688"
}).setFill(this.borderColor);
g.createPath({
path: "M358.6738 203.9965 C358.7188 202.3627 358.7463 188.224 358.745 186.579 L358.745 186.4627 C358.7138 91.3165 281.5575 14.2127 186.4113 14.244 C91.2675 14.2777 14.1625 91.4327 14.1938 186.579 C14.1938 186.6177 14.2213 202.4015 14.2663 203.9965 L358.6738 203.9965 Z"
}).setFill({
type: "linear",
x1: 14.19376,
y1: 260.92225,
x2: 14.19376,
y2: 156.55837,
colors: [{
offset: 0,
color: [100, 100, 100]
}, {
offset: 1,
color: this.fillColor
}]
});
g.createPath({
path: "M358.7038 182.9027 C356.775 89.4027 280.3713 14.2127 186.4163 14.244 C92.5013 14.2765 16.1713 89.4527 14.2438 182.9002 C66.8388 197.064 127.36 168.814 188.7525 168.814 C250.1638 168.814 306.2575 197.0703 358.7038 182.9027"
}).setFill({
type: "linear",
x1: 14.24378,
y1: 186.87786,
x2: 14.24378,
y2: 14.24398,
colors: [{
offset: 0,
color: this.fillColor
}, {
offset: 1,
color: [200, 200, 200]
}]
});
g.createPath({
path: "M358.953 183.1553 C357.0243 89.6553 280.6205 14.4653 186.6655 14.4966 C92.7505 14.5291 16.4205 89.7053 14.493 183.1528 C67.088 197.3166 127.6093 169.0666 189.0018 169.0666 C250.413 169.0666 306.5068 197.3228 358.953 183.1553"
}).setFill([255, 255, 255, 0.12157]);
},
drawForeground: function(g){
// summary:
// Draws the foreground shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the foreground.
// tags:
// protected
var g1 = g.createGroup();
g1.createPath({
path: "M214.9406 185.3295 C214.9456 201.0533 202.2044 213.8033 186.4806 213.8095 C170.7544 213.8145 158.0044 201.072 157.9994 185.3495 L157.9994 185.3295 C157.9931 169.6057 170.7369 156.8557 186.4619 156.8495 C202.1844 156.8445 214.9356 169.587 214.9406 185.3108 L214.9406 185.3295 Z"
}).setFill(this.borderColor);
g1.createPath({
path: "M211.3563 185.329 C211.36 199.074 200.2238 210.2177 186.4787 210.2228 C172.735 210.2277 161.59 199.0902 161.585 185.3465 L161.585 185.329 C161.58 171.5852 172.7175 160.4402 186.4613 160.4352 C200.2063 160.4303 211.3513 171.569 211.3563 185.3128 L211.3563 185.329 Z"
}).setFill({
type: "linear",
x1: 161.58503,
y1: 210.22273,
x2: 161.58503,
y2: 185.32899,
colors: [{
offset: 0,
color: [100, 100, 100]
}, {
offset: 1,
color: this.fillColor
}]
});
g1.createPath({
path: "M211.35 184.799 C211.0713 171.2928 200.035 160.4303 186.4625 160.4352 C172.8963 160.4402 161.87 171.299 161.5925 184.799 C169.1888 186.844 177.93 182.764 186.8013 182.764 C195.6712 182.764 203.7738 186.8452 211.35 184.799"
}).setFill({
type: "linear",
x1: 161.59251,
y1: 185.37311,
x2: 161.59251,
y2: 160.43524,
colors: [{
offset: 0,
color: this.fillColor
}, {
offset: 1,
color: [150, 150, 150]
}]
});
g1.createPath({
path: "M211.3494 184.7985 C211.0706 171.2923 200.0344 160.431 186.4632 160.436 C172.8956 160.441 161.8707 171.2997 161.5919 184.7985 C169.1881 186.8435 177.9306 182.7635 186.8006 182.7635 C195.6706 182.7635 203.7731 186.846 211.3494 184.7985"
}).setFill([255, 255, 255, 0.12157]);
}
});
});
},
'dojox/dgauges/components/black/VerticalLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../../RectangularGauge",
"../../LinearScaler",
"../../RectangularScale",
"../../RectangularValueIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, RectangularGauge, LinearScaler, RectangularScale, RectangularValueIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.black.VerticalLinearGauge", [RectangularGauge, DefaultPropertiesMixin], {
// summary:
// A vertical gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#000000".
borderColor: "#000000",
// fillColor: Object|Array|int
// The background color. Default is "#000000".
fillColor: "#000000",
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#A4A4A4".
indicatorColor: "#A4A4A4",
constructor: function(){
this.orientation = "vertical";
// Base colors
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
this.addElement("background", lang.hitch(this, this.drawBackground));
// Scaler
var scaler = new LinearScaler();
// Scale
var scale = new RectangularScale();
scale.set("scaler", scaler);
scale.set("labelPosition", "trailing");
scale.set("paddingTop", 30);
scale.set("paddingBottom", 30);
scale.set("paddingLeft", 15);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "7pt",
color: "#CECECE"
});
scale.set("tickShapeFunc", function(group, scale, tick){
return group.createCircle({
r: tick.isMinor ? 0.5 : 3
}).setFill("#CECECE");
});
this.addElement("scale", scale);
var indicator = new RectangularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("paddingLeft", 18);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group){
return group.createPolyline([0, 0, -10, -20, 10, -20, 0, 0]).setFill(this.indicatorColor).setStroke({
color: [69,69,69],
width: 1,
style: "Solid",
cap: "butt",
join: 20.0
});
}));
scale.addIndicator("indicator", indicator);
},
drawBackground: function(g, w, h){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// w: Number
// The width of the gauge.
// h: Number
// The height of the gauge.
// tags:
// protected
g.createRect({
x: 0,
y: 0,
width: 50,
height: h,
r: 15
}).setFill(this.borderColor);
g.createRect({
x: 4,
y: 4,
width: 42,
height: h - 8,
r: 12
}).setFill({
type: "linear",
x1: 5,
y1: 0,
x2: 20,
y2: 0,
colors: [
{offset: 0, color: [100,100,100]},
{offset: 1, color: this.fillColor}
]
});
g.createPath().moveTo(25, 4).hLineTo(36).smoothCurveTo(46, 4, 46, 18).vLineTo(h - 20).smoothCurveTo(46, h - 4, 36, h - 4).closePath().setFill({
type: "linear",
x1: 70,
y1: 0,
x2: 25,
y2: 0,
colors: [
{offset: 0, color: [150,150,150]},
{offset: 1, color: this.fillColor}
]
});
g.createPath().moveTo(25, 4).hLineTo(36).smoothCurveTo(46, 4, 46, 18).vLineTo(h - 20).smoothCurveTo(46, h - 4, 36, h - 4).closePath().setFill([255,255,255,0.05]);
}
});
}
);
},
'dojox/dgauges/components/black/HorizontalLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../../RectangularGauge",
"../../LinearScaler",
"../../RectangularScale",
"../../RectangularValueIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, RectangularGauge, LinearScaler, RectangularScale, RectangularValueIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.black.HorizontalLinearGauge", [RectangularGauge, DefaultPropertiesMixin], {
// summary:
// A horizontal gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#000000".
borderColor: "#000000",
// fillColor: Object|Array|int
// The background color. Default is "#000000".
fillColor: "#000000",
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#A4A4A4".
indicatorColor: "#A4A4A4",
constructor: function(){
// Base colors
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
this.addElement("background", lang.hitch(this, this.drawBackground));
// Scaler
var scaler = new LinearScaler();
// Scale
var scale = new RectangularScale();
scale.set("scaler", scaler);
scale.set("labelPosition", "leading");
scale.set("paddingLeft", 30);
scale.set("paddingRight", 30);
scale.set("paddingTop", 34);
scale.set("labelGap", 8);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "7pt",
color: "#CECECE"
});
scale.set("tickShapeFunc", function(group, scale, tick){
return group.createCircle({
r: tick.isMinor ? 0.5 : 3
}).setFill("#CECECE");
});
this.addElement("scale", scale);
var indicator = new RectangularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("paddingTop", 30);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group, indicator){
return group.createPolyline([0, 0, -10, -20, 10, -20, 0, 0]).setFill(this.indicatorColor).setStroke({
color: [70, 70, 70],
width: 1,
style: "Solid",
cap: "butt",
join: 20.0
});
}));
scale.addIndicator("indicator", indicator);
},
drawBackground: function(g, w, h){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// w: Number
// The width of the gauge.
// h: Number
// The height of the gauge.
// tags:
// protected
g.createRect({
x: 0,
y: 0,
width: w,
height: 50,
r: 15
}).setFill(this.borderColor);
g.createRect({
x: 4,
y: 4,
width: w - 8,
height: 42,
r: 12
}).setFill({
type: "linear",
x1: 0,
y1: 50,
x2: 0,
y2: 30,
colors: [
{offset: 0, color: [100,100,100]},
{offset: 1, color: this.fillColor}
]
});
g.createPath().moveTo(4, 25).vLineTo(14).smoothCurveTo(4, 4, 18, 4).hLineTo(w - 16).smoothCurveTo(w - 4, 4, w - 4, 16).closePath().setFill({
type: "linear",
x1: 0,
y1: 0,
x2: 0,
y2: 20,
colors: [
{offset: 0, color: [150,150,150]},
{offset: 1, color: this.fillColor}
]
});
g.createPath().moveTo(4, 25).vLineTo(14).smoothCurveTo(4, 4, 18, 4).hLineTo(w - 16).smoothCurveTo(w - 4, 4, w - 4, 16).closePath().setFill([255,255,255,0.05]);
}
});
}
);
},
'dojox/dgauges/components/green/CircularLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../utils",
"../../CircularGauge",
"../../LinearScaler",
"../../CircularScale",
"../../CircularValueIndicator",
"../../CircularRangeIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, utils, CircularGauge, LinearScaler, CircularScale, CircularValueIndicator, CircularRangeIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.green.CircularLinearGauge", [CircularGauge, DefaultPropertiesMixin], {
// summary:
// A circular gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#323232".
borderColor: [50,50,50],
// fillColor: Object|Array|int
// The fill color. Default is "#6DB713".
fillColor: [109,183,19],
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#000000".
indicatorColor: [0,0,0],
constructor: function(){
var scaler = new LinearScaler();
this.addElement("background", lang.hitch(this, this.drawBackground));
var scale = new CircularScale();
scale.set("scaler", scaler);
scale.set("originX", 132);
scale.set("originY", 133.5);
scale.set("radius", 100);
scale.set("startAngle", 120);
scale.set("endAngle", 60);
scale.set("orientation", "clockwise");
scale.set("labelGap", 6);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "8pt"
});
this.addElement("scale", scale);
var indicator = new CircularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group, indicator){
var l = indicator.scale.radius - 2;
group.createPath().moveTo(-20, 0).lineTo(-20, -5).lineTo(l, 0).lineTo(-20, 5).closePath().setFill(this.indicatorColor);
return group;
}));
scale.addIndicator("indicator", indicator);
this.addElement("foreground", lang.hitch(this, this.drawForeground));
},
drawBackground: function(g){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// tags:
// protected
var lighterFillColor = utils.brightness(new Color(this.fillColor), 100);
g.createEllipse({
cx: 132.2528,
cy: 133.617,
rx: 132.2528,
ry: 131.9046
}).setFill(this.borderColor);
g.createPath({
path: "M260.5056 133.617 C260.5188 179.3085 236.0769 221.5348 196.39 244.3844 C156.703 267.234 107.8027 267.234 68.1158 244.3844 C28.4287 221.5348 3.9866 179.3085 4 133.617 C3.9866 87.9255 28.4287 45.6992 68.1158 22.8496 C107.8027 0 156.703 0 196.39 22.8496 C236.0769 45.6992 260.5188 87.9255 260.5056 133.617 Z"
}).setFill({
type: "linear",
x1: 4.00002,
y1: 5.71243,
x2: 183.55392,
y2: 261.52156,
colors: [
{offset: 0, color: [226,226,221]},
{offset: 0.5, color: [239,239,236]},
{offset: 1, color: "white"}
]
});
g.createPath({
path: "M132.2358 5.7124 C61.4417 5.7124 4 63.0164 4 133.617 C4 204.2176 61.4417 261.5216 132.2358 261.5216 C203.0297 261.5216 260.5056 204.2176 260.5056 133.617 C260.5056 63.0164 203.0297 5.7124 132.2358 5.7124 ZM132.2358 29.5811 C189.165 29.5811 235.3862 76.19 235.3862 133.617 C235.3862 191.0441 189.165 237.653 132.2358 237.653 C75.3064 237.653 29.1195 191.0441 29.1195 133.617 C29.1195 76.19 75.3064 29.5811 132.2358 29.5811 Z"
}).setFill({
type: "linear",
x1: 4.00003,
y1: 5.71235,
x2: 4.00003,
y2: 261.52154,
colors: [
{offset: 0, color: lighterFillColor},
{offset: 0.25, color: this.fillColor},
{offset: 0.5, color: this.fillColor},
{offset: 0.75, color: this.fillColor},
{offset: 1, color: lighterFillColor}
]
});
g.createPath({
path: "M-389.2685 91.1524 C-389.2685 194.5704 -473.1053 278.4072 -576.5233 278.4072 C-679.9412 278.4072 -763.778 194.5704 -763.778 91.1524 C-763.778 -12.2655 -679.9412 -96.1024 -576.5233 -96.1024 C-473.1053 -96.1024 -389.2685 -12.2655 -389.2685 91.1524 Z"
}).setTransform({
xx: 0.1,
xy: 0.46404,
yx: -0.46637,
yy: 0.1005,
dx: 147.5,
dy: -144.5
}).setStroke({
color: "white",
width: 3.04506,
style: "Solid",
cap: "butt",
join: 4.0
});
},
drawForeground: function(g){
// summary:
// Draws the foreground shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the foreground.
// tags:
// protected
var g1 = g.createGroup();
g1.createEllipse({
cx: 132,
cy: 133.5,
rx: 18,
ry: 18
}).setFill(this.fillColor);
g1.createEllipse({
cx: 132,
cy: 133.5,
rx: 17,
ry: 17
}).setFill({
type: "linear",
x1: 116.09304,
y1: 118.09373,
x2: 116.09304,
y2: 149.2857,
colors: [
{offset: 0, color: [255,255,246]},
{offset: 0.17857, color: [252,251,236]},
{offset: 0.25755, color: [250,247,230]},
{offset: 0.77747, color: [246,243,224]},
{offset: 1, color: [227,209,184]}
]
});
g.createPath({
path: "M235.494 63.7584 C235.494 87.4242 189.2719 51.6605 132.3194 51.6605 C75.367 51.6605 29.1447 87.4242 29.1447 63.7584 C29.1447 40.0927 75.367 2.531 132.3194 2.531 C189.2719 2.531 235.494 40.0927 235.494 63.7584 Z"
}).setFill([255,255,255,0.19608]);
}
});
}
);
},
'dojox/dgauges/components/green/SemiCircularLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../utils",
"../../CircularGauge",
"../../LinearScaler",
"../../CircularScale",
"../../CircularValueIndicator",
"../../CircularRangeIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, utils, CircularGauge, LinearScaler, CircularScale, CircularValueIndicator, CircularRangeIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.green.SemiCircularLinearGauge", [CircularGauge, DefaultPropertiesMixin], {
// summary:
// A semi circular gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#323232".
borderColor: [50,50,50],
// fillColor: Object|Array|int
// The fill color. Default is "#6DB713".
fillColor: [109,183,19],
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#000000".
indicatorColor: [0,0,0],
constructor: function(){
var scaler = new LinearScaler({
majorTickInterval: 25,
minorTickInterval: 5
});
this.addElement("background", lang.hitch(this, this.drawBackground));
var scale = new CircularScale();
scale.set("scaler", scaler);
scale.set("originX", 131);
scale.set("originY", 149.5);
scale.set("radius", 108.66756);
scale.set("startAngle", -136);
scale.set("endAngle", -43);
scale.set("orientation", "clockwise");
scale.set("labelGap", 2);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "10pt"
});
this.addElement("scale", scale);
var indicator = new CircularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group, indicator){
var l = indicator.scale.radius - 2;
group.createPath().moveTo(-20, 0).lineTo(-20, -5).lineTo(l, 0).lineTo(-20, 5).closePath().setFill(this.indicatorColor);
return group;
}));
scale.addIndicator("indicator", indicator);
this.addElement("foreground", lang.hitch(this, this.drawForeground));
},
drawBackground: function(g){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// tags:
// protected
var lighterFillColor = utils.brightness(new Color(this.fillColor), 100);
g.createPath({
path: "M260.7431 100.826 C260.7431 172.7911 202.3367 200.1975 130.3716 200.1975 C58.4065 200.1975 -0 172.7911 -0 100.826 C-0 28.8609 58.4065 0.4545 130.3716 0.4545 C202.3367 0.4545 260.7431 28.8609 260.7431 100.826 Z"
}).setFill(this.borderColor);
g.createPath({
path: "M258.2581 100.819 C258.2581 171.0137 200.9626 197.7459 130.3662 197.7459 C59.7698 197.7459 2.4742 171.0137 2.4742 100.819 C2.4742 30.6244 59.7698 2.9168 130.3662 2.9168 C200.9626 2.9168 258.2581 30.6244 258.2581 100.819 Z"
}).setFill({
type: "linear",
x1: 2.47421,
y1: 2.91677,
x2: 181.52295,
y2: 197.74595,
colors: [
{offset: 0, color: [226,226,221]},
{offset: 0.5, color: [239,239,236]},
{offset: 1, color: "white"}
]
});
g.createPath({
path: "M130.3762 2.9168 C59.9006 2.9168 2.4742 30.3335 2.4742 100.8214 C2.4742 171.3093 59.9006 197.7459 130.3762 197.7459 C200.8516 197.7459 258.2581 171.3093 258.2581 100.8214 C258.2581 30.3335 200.8516 2.9168 130.3762 2.9168 ZM130.3762 25.2846 C188.7428 25.2846 235.8942 42.4445 235.8942 100.8214 C235.8942 159.1984 188.7428 175.3581 130.3762 175.3581 C72.0095 175.3581 24.858 159.1984 24.858 100.8214 C24.858 42.4445 72.0095 25.2846 130.3762 25.2846 Z"
}).setFill({
type: "linear",
x1: 2.47417,
y1: 2.91681,
x2: 2.47417,
y2: 197.74593,
colors: [
{offset: 0, color: lighterFillColor},
{offset: 0.25, color: this.fillColor},
{offset: 0.5, color: this.fillColor},
{offset: 0.75, color: this.fillColor},
{offset: 1, color: lighterFillColor}
]
});
g.createPath({
path: "M128.9903 34.9775 C177.3318 33.7519 217.6275 49.1301 218.936 97.6431 C220.2445 146.1562 182.0729 160.5238 133.7314 161.7494 C85.39 162.975 45.0943 150.5968 43.7858 102.0838 C42.4772 53.5708 80.6489 36.2031 128.9903 34.9775 Z"
}).setStroke({
color: "white",
width: 1.42712,
style: "Solid",
cap: "butt",
join: 4.0
});
},
drawForeground: function(g){
// summary:
// Draws the foreground shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the foreground.
// tags:
// protected
var g1 = g.createGroup();
g1.createEllipse({
cx: 131,
cy: 149.5,
rx: 18,
ry: 18
}).setFill(this.fillColor);
g1.createEllipse({
cx: 131,
cy: 149.5,
rx: 17,
ry: 17
}).setFill({
type: "linear",
x1: 114.63479,
y1: 133.63361,
x2: 114.63479,
y2: 164.82557,
colors: [
{offset: 0, color: [255,255,246]},
{offset: 0.17857, color: [252,251,236]},
{offset: 0.25755, color: [250,247,230]},
{offset: 0.77747, color: [246,243,224]},
{offset: 1, color: [227,209,184]}
]
});
g.createPath({
path: "M244.8093 59.9472 C244.8093 82.7317 193.7605 47.2998 130.8612 47.2998 C67.9619 47.2998 16.9132 81.7317 16.9132 58.9472 C16.9132 36.1628 67.9619 0 130.8612 0 C193.7605 0 244.8093 37.1628 244.8093 59.9472 Z"
}).setFill([255,255,255,0.19608]);
}
});
}
);
},
'dojox/dgauges/components/green/VerticalLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../utils",
"../../RectangularGauge",
"../../LinearScaler",
"../../RectangularScale",
"../../RectangularValueIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, utils, RectangularGauge, LinearScaler, RectangularScale, RectangularValueIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.green.VerticalLinearGauge", [RectangularGauge, DefaultPropertiesMixin], {
// summary:
// A vertical gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#323232".
borderColor: [50,50,50],
// fillColor: Object|Array|int
// The background color. Default is "#6DB713".
fillColor: [109,183,19],
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#000000".
indicatorColor: [0,0,0],
constructor: function(){
this.orientation = "vertical";
// Base colors
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
this.addElement("background", lang.hitch(this, this.drawBackground));
// Scaler
var scaler = new LinearScaler();
// Scale
var scale = new RectangularScale();
scale.set("scaler", scaler);
scale.set("labelPosition", "trailing");
scale.set("paddingTop", 30);
scale.set("paddingBottom", 30);
scale.set("paddingLeft", 15);
scale.set("labelGap", 2);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "7pt"
});
this.addElement("scale", scale);
var indicator = new RectangularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("paddingLeft", 18);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group){
return group.createPolyline([0, 0, -10, -20, 10, -20, 0, 0]).setFill(this.indicatorColor);
}));
scale.addIndicator("indicator", indicator);
},
drawBackground: function(g, w, h){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// w: Number
// The width of the gauge.
// h: Number
// The height of the gauge.
// tags:
// protected
var lighterFillColor = utils.brightness(new Color(this.fillColor), 100);
g.createRect({
x: 0,
y: 0,
width: 50,
height: h,
r: 10
}).setFill(this.borderColor);
g.createRect({
x: 3,
y: 3,
width: 44,
height: h - 6,
r: 7
}).setFill({
type: "linear",
x1: 6,
y1: 0,
x2: 38,
y2: 0,
colors: [
{offset: 0, color: lighterFillColor},
{offset: 1, color: this.fillColor}
]
});
g.createRect({
x: 6,
y: 6,
width: 38,
height: h - 12,
r: 6
}).setFill({
type: "linear",
x1: 7,
y1: 0,
x2: 36,
y2: 0,
colors: [
{offset: 0, color: [226,226,221]},
{offset: 0.5, color: [239,239,236]},
{offset: 1, color: "white"}
]
});
}
});
}
);
},
'dojox/dgauges/components/green/HorizontalLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../utils",
"../../RectangularGauge",
"../../LinearScaler",
"../../RectangularScale",
"../../RectangularValueIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, utils, RectangularGauge, LinearScaler, RectangularScale, RectangularValueIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.green.HorizontalLinearGauge", [RectangularGauge, DefaultPropertiesMixin], {
// summary:
// A horizontal gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#323232".
borderColor: [50,50,50],
// fillColor: Object|Array|int
// The background color. Default is "#6DB713".
fillColor: [109,183,19],
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#000000".
indicatorColor: [0,0,0],
constructor: function(){
// Base colors
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
this.addElement("background", lang.hitch(this, this.drawBackground));
// Scaler
var scaler = new LinearScaler();
// Scale
var scale = new RectangularScale();
scale.set("scaler", scaler);
scale.set("labelPosition", "leading");
scale.set("paddingLeft", 30);
scale.set("paddingRight", 30);
scale.set("paddingTop", 28);
scale.set("labelGap", 2);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "7pt"
});
this.addElement("scale", scale);
var indicator = new RectangularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("paddingTop", 32);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group, indicator){
return group.createPolyline([0, 0, -10, -20, 10, -20, 0, 0]).setFill(this.indicatorColor);
}));
scale.addIndicator("indicator", indicator);
},
drawBackground: function(g, w, h){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// w: Number
// The width of the gauge.
// h: Number
// The height of the gauge.
// tags:
// protected
var lighterFillColor = utils.brightness(new Color(this.fillColor), 100);
g.createRect({
x: 0,
y: 0,
width: w,
height: 50,
r: 10
}).setFill(this.borderColor);
g.createRect({
x: 3,
y: 3,
width: w - 6,
height: 44,
r: 7
}).setFill({
type: "linear",
x1: 0,
y1: 2,
x2: 0,
y2: 30,
colors: [
{offset: 0, color: lighterFillColor},
{offset: 1, color: this.fillColor}
]
});
g.createRect({
x: 6,
y: 6,
width: w - 12,
height: 38,
r: 5
}).setFill({
type: "linear",
x1: 0,
y1: 6,
x2: 0,
y2: 38,
colors: [
{offset: 0, color: [226,226,221]},
{offset: 0.5, color: [239,239,236]},
{offset: 1, color: "white"}
]
});
}
});
}
);
},
'dojox/dgauges/components/grey/CircularLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../utils",
"../../CircularGauge",
"../../LinearScaler",
"../../CircularScale",
"../../CircularValueIndicator",
"../../CircularRangeIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, utils, CircularGauge, LinearScaler, CircularScale, CircularValueIndicator, CircularRangeIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.grey.CircularLinearGauge", [CircularGauge, DefaultPropertiesMixin], {
// summary:
// A circular gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#9498A1".
borderColor: [148,152,161],
// fillColor: Object|Array|int
// The background color. Default is "#9498A1".
fillColor: [148,152,161],
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#3F3F3F".
indicatorColor: [63,63,63],
constructor: function(args, node){
var scaler = new LinearScaler();
this.addElement("background", lang.hitch(this, this.drawBackground));
var scale = new CircularScale();
scale.set("scaler", scaler);
scale.set("originX", 73.4);
scale.set("originY", 74.10297);
scale.set("radius", 61.44239);
scale.set("startAngle", 130.16044);
scale.set("endAngle", 50.25444);
scale.set("orientation", "clockwise");
scale.set("labelGap", 2);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "8pt"
});
this.addElement("scale", scale);
var indicator = new CircularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group, indicator){
var l = indicator.scale.radius - 2;
group.createPath().moveTo(0, 0).lineTo(0, -5).lineTo(l, 0).lineTo(0, 0).closePath().setFill(this.indicatorColor);
var lighterColor = utils.brightness(new Color(this.indicatorColor), 70);
group.createPath().moveTo(0, 0).lineTo(0, 5).lineTo(l, 0).lineTo(0, 0).closePath().setFill(lighterColor);
return group;
}));
scale.addIndicator("indicator", indicator);
this.addElement("foreground", lang.hitch(this, this.drawForeground));
},
drawBackground: function(g){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// tags:
// protected
g.createEllipse({
cx: 73.5,
cy: 73.75,
rx: 73.5,
ry: 73.75
}).setFill(this.borderColor);
g.createEllipse({
cx: 73.5,
cy: 73.75,
rx: 71.5,
ry: 71.75
}).setFill({
type: "linear",
x1: 2,
y1: 2,
x2: 2,
y2: 174.2,
colors: [
{offset: 0, color: this.fillColor},
{offset: 1, color: "white"}
]
});
g.createPath({
path: "M71.7134 2.3627 C35.3338 3.0547 6.0025 32.818 6.0025 69.3621 C6.0025 69.7225 5.9968 70.0836 6.0025 70.4427 C26.4442 78.2239 50.1913 82.6622 75.4956 82.6622 C98.7484 82.6622 120.6538 78.8779 139.918 72.2299 C139.9587 71.2717 140.0011 70.3303 140.0011 69.3621 C140.0011 32.3847 109.9791 2.3627 73.0018 2.3627 C72.5685 2.3627 72.1447 2.3545 71.7133 2.3627 Z"
}).setFill({
type: "linear",
x1: 6,
y1: 2.3591,
x2: 6,
y2: 150,
colors: [
{offset: 0, color: "white"},
{offset: 1, color: this.fillColor}
]
});
},
drawForeground: function(g){
// summary:
// Draws the foreground shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the foreground.
// tags:
// protected
g.createEllipse({
cx: 73.3,
cy: 73.8,
rx: 9.25,
ry: 9.25
}).setFill({
type: "radial",
cx: 73.30003,
cy: 70.10003,
r: 18.5,
colors: [
{offset: 0, color: [149,149,149]},
{offset: 0.5, color: "black"},
{offset: 1, color: "black"}
]
}).setStroke({
color: "black",
width: 0.1,
style: "Solid",
cap: "butt",
join: 4.0
});
}
});
}
);
},
'dojox/dgauges/components/grey/SemiCircularLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../utils",
"../../CircularGauge",
"../../LinearScaler",
"../../CircularScale",
"../../CircularValueIndicator",
"../../CircularRangeIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, utils, CircularGauge, LinearScaler, CircularScale, CircularValueIndicator, CircularRangeIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.grey.SemiCircularLinearGauge", [CircularGauge, DefaultPropertiesMixin], {
// summary:
// A semi circular gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#9498A1".
borderColor: [148,152,161],
// fillColor: Object|Array|int
// The background color. Default is "#9498A1".
fillColor: [148,152,161],
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#3F3F3F".
indicatorColor: [63,63,63],
constructor: function(args, node){
var scaler = new LinearScaler({
majorTickInterval: 25,
minorTickInterval: 5
});
this.addElement("background", lang.hitch(this, this.drawBackground));
var scale = new CircularScale();
scale.set("scaler", scaler);
scale.set("originX", 118.80925);
scale.set("originY", 172.98112);
scale.set("radius", 160.62904);
scale.set("startAngle", -127.30061);
scale.set("endAngle", -53);
scale.set("orientation", "clockwise");
scale.set("labelGap", 2);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "8pt"
});
this.addElement("scale", scale);
var indicator = new CircularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group, indicator){
var l = indicator.scale.radius - 2;
group.createPath().moveTo(0, 0).lineTo(0, -5).lineTo(l, 0).lineTo(0, 0).closePath().setFill(this.indicatorColor);
var lighterColor = utils.brightness(new Color(this.indicatorColor), 70);
group.createPath().moveTo(0, 0).lineTo(0, 5).lineTo(l, 0).lineTo(0, 0).closePath().setFill(lighterColor);
return group;
}));
scale.addIndicator("indicator", indicator);
this.addElement("foreground", lang.hitch(this, this.drawForeground));
},
drawBackground: function(g){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// tags:
// protected
g.createPath({
path: "M116.4449 0.014 C82.013 -0 48.0666 7.3389 14.6499 22.4862 C6.1025 25.6372 0 33.8658 0 43.5028 C0 49.8823 2.677 55.6345 6.9637 59.713 L99.9834 180.9853 C99.9859 180.9893 99.9914 180.9917 99.9939 180.9957 C103.9488 187.329 110.9778 191.5406 118.9895 191.5406 C126.8965 191.5406 133.8563 187.4321 137.8385 181.2366 C137.8426 181.2301 137.8448 181.222 137.849 181.2157 L231.3295 59.4197 C235.4368 55.3611 237.9789 49.7288 237.9789 43.5028 C237.9789 33.7053 231.6713 25.3703 222.8998 22.3395 C186.9226 7.6322 151.4291 0.0282 116.4449 0.014 Z"
}).setFill(this.borderColor);
g.createPath({
path: "M116.224 1.014 C82.301 1.0002 48.8563 8.2306 15.9334 23.1541 C7.5123 26.2585 1.5 34.3655 1.5 43.8601 C1.5 50.1453 4.1374 55.8125 8.3608 59.8307 L100.0058 179.3108 C100.0083 179.3148 100.0137 179.3171 100.0162 179.3211 C103.9126 185.5608 110.8377 189.7102 118.731 189.7102 C126.5212 189.7102 133.3781 185.6624 137.3015 179.5584 C137.3055 179.552 137.3077 179.5441 137.3118 179.5378 L229.4108 59.5418 C233.4574 55.5432 235.962 49.9941 235.962 43.8601 C235.962 34.2074 229.7476 25.9956 221.1057 23.0096 C185.6602 8.5196 150.6912 1.028 116.224 1.014 Z"
}).setFill({
type: "linear",
x1: 1.5,
y1: 1.01397,
x2: 1.5,
y2: 227.44943,
colors: [
{offset: 0, color: this.fillColor},
{offset: 1, color: "white"}
]
});
g.createPath({
path: "M117.848 3.0148 C83.3161 3.3066 42.2685 15.8301 16.4018 27.4452 C5.957 32.4174 9.5019 48.0401 18.3827 57.3539 C46.55 86.8947 80.5357 90.0379 118.4979 90.0379 C118.5432 90.0379 118.5868 90.0379 118.6321 90.0379 C118.7622 90.0379 118.8943 90.038 119.0241 90.0379 C119.0686 90.0379 119.1137 90.0379 119.1582 90.0379 C153.5091 90.0379 191.1062 86.8947 219.2735 57.3539 C228.1543 48.0401 231.6992 32.4174 221.2543 27.4452 C195.2041 15.7477 153.7583 3.1333 119.0757 3.0148 C119.0485 3.0148 119.0203 3.0148 118.9932 3.0148 C118.8843 3.0145 118.7717 3.0148 118.663 3.0148 C118.6351 3.0149 118.6084 3.0147 118.5805 3.0148 C118.3362 3.0156 118.093 3.0127 117.848 3.0148 Z"
}).setFill({
type: "linear",
x1: 10.0001,
y1: 3.01406,
x2: 10.0001,
y2: 150,
colors: [
{offset: 0, color: "white"},
{offset: 1, color: this.fillColor}
]
});
},
drawForeground: function(g){
// summary:
// Draws the foreground shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the foreground.
// tags:
// protected
g.createEllipse({
cx: 118.80001,
cy: 172.81399,
rx: 9.25,
ry: 9.25
}).setFill({
type: "radial",
cx: 118.80003,
cy: 169.11402,
r: 18.5,
colors: [
{offset: 0, color: [149,149,149]},
{offset: 0.5, color: "black"},
{offset: 1, color: "black"}
]
}).setStroke({
color: "black",
width: 0.1,
style: "Solid",
cap: "butt",
join: 4.0
});
}
});
}
);
},
'dojox/dgauges/components/grey/VerticalLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../../RectangularGauge",
"../../LinearScaler",
"../../RectangularScale",
"../../RectangularValueIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, RectangularGauge, LinearScaler, RectangularScale, RectangularValueIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.grey.VerticalLinearGauge", [RectangularGauge, DefaultPropertiesMixin], {
// summary:
// A vertical gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#9498A1".
borderColor: [148,152,161],
// fillColor: Object|Array|int
// The background color. Default is "#9498A1".
fillColor: [148,152,161],
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#3F3F3F".
indicatorColor: [63,63,63],
constructor: function(){
this.orientation = "vertical";
// Base colors
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
this.addElement("background", lang.hitch(this, this.drawBackground));
// Scaler
var scaler = new LinearScaler();
// Scale
var scale = new RectangularScale();
scale.set("scaler", scaler);
scale.set("labelPosition", "trailing");
scale.set("paddingTop", 30);
scale.set("paddingBottom", 30);
scale.set("paddingLeft", 15);
scale.set("labelGap", 4);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "7pt"
});
this.addElement("scale", scale);
var indicator = new RectangularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("paddingLeft", 22);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group){
group.createPath().moveTo(0, 0).lineTo(-10, -20).lineTo(10, -20).lineTo(0, 0).closePath().setFill(this.indicatorColor);
return group;
}));
scale.addIndicator("indicator", indicator);
},
drawBackground: function(g, w, h){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// w: Number
// The width of the gauge.
// h: Number
// The height of the gauge.
// tags:
// protected
g.createRect({
x: 0,
y: 0,
width: 50,
height: h,
r: 13.5
}).setFill(this.borderColor);
g.createRect({
x: 2,
y: 2,
width: 46,
height: h - 4,
r: 11.5
}).setFill({
type: "linear",
x1: -2,
y1: 0,
x2: 60,
y2: 0,
colors: [
{offset: 0, color: "white"},
{offset: 1, color: this.fillColor}
]
});
g.createPath().moveTo(25, 2).hLineTo(38).smoothCurveTo(48, 2, 48, 18).vLineTo(h - 16).smoothCurveTo(48, h - 2, 38, h - 2).closePath().setFill({
type: "linear",
x1: -10,
y1: 0,
x2: 60,
y2: 0,
colors: [
{offset: 0, color: this.fillColor},
{offset: 1, color: "white"}
]
});
}
});
}
);
},
'dojox/dgauges/components/grey/HorizontalLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../../RectangularGauge",
"../../LinearScaler",
"../../RectangularScale",
"../../RectangularValueIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, RectangularGauge, LinearScaler, RectangularScale, RectangularValueIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.grey.HorizontalLinearGauge", [RectangularGauge, DefaultPropertiesMixin], {
// summary:
// A horizontal gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#9498A1".
borderColor: [148,152,161],
// fillColor: Object|Array|int
// The background color. Default is "#9498A1".
fillColor: [148,152,161],
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#3F3F3F".
indicatorColor: [63,63,63],
constructor: function(){
// Base colors
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
this.addElement("background", lang.hitch(this, this.drawBackground));
// Scaler
var scaler = new LinearScaler();
// Scale
var scale = new RectangularScale();
scale.set("scaler", scaler);
scale.set("labelPosition", "leading");
scale.set("paddingLeft", 30);
scale.set("paddingRight", 30);
scale.set("paddingTop", 28);
scale.set("labelGap", 8);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "7pt"
});
this.addElement("scale", scale);
var indicator = new RectangularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("paddingTop", 32);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group, indicator){
return group.createPolyline([0, 0, -10, -20, 10, -20, 0, 0]).setFill(this.indicatorColor).setStroke({
color: [70, 70, 70],
width: 1,
style: "Solid",
cap: "butt",
join: 20.0
});
}));
scale.addIndicator("indicator", indicator);
},
drawBackground: function(g, w, h){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// w: Number
// The width of the gauge.
// h: Number
// The height of the gauge.
// tags:
// protected
g.createRect({
x: 0,
y: 0,
width: w,
height: 50,
r: 13.5
}).setFill(this.borderColor);
g.createRect({
x: 2,
y: 2,
width: w - 4,
height: 46,
r: 11.5
}).setFill({
type: "linear",
x1: 0,
y1: -2,
x2: 0,
y2: 60,
colors: [
{offset: 0, color: this.fillColor},
{offset: 1, color: "white"}
]
});
g.createPath().moveTo(2, 25).vLineTo(12).smoothCurveTo(2, 2, 16, 2).hLineTo(w - 12).smoothCurveTo(w - 2, 2, w - 2, 16).closePath().setFill({
type: "linear",
x1: 0,
y1: -5,
x2: 0,
y2: 40,
colors: [
{offset: 0, color: "white"},
{offset: 1, color: this.fillColor}
]
});
}
});
}
);
},
'dojox/dgauges/components/classic/CircularLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../../CircularGauge",
"../../LinearScaler",
"../../CircularScale",
"../../CircularValueIndicator",
"../../CircularRangeIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, CircularGauge, LinearScaler, CircularScale, CircularValueIndicator, CircularRangeIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.classic.CircularLinearGauge", [CircularGauge, DefaultPropertiesMixin], {
// summary:
// A circular gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#797E86".
borderColor: [121,126,134],
// fillColor: Object|Array|int
// The background color. Default is "#9498A1".
fillColor: [148,152,161],
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#FFFFFF".
indicatorColor: "#FFFFFF",
constructor: function(){
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
var scaler = new LinearScaler();
this.addElement("background", lang.hitch(this, this.drawBackground));
var scale = new CircularScale();
scale.set("scaler", scaler);
scale.set("originX", 81.94991);
scale.set("originY", 87.99015);
scale.set("radius", 66.34219);
scale.set("startAngle", 115.9);
scale.set("endAngle", 61.6);
scale.set("orientation", "clockwise");
scale.set("labelGap", 2);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "6pt"
});
this.addElement("scale", scale);
var indicator = new CircularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group, indicator){
var l = indicator.scale.radius - 2;
return group.createPath().moveTo(0, 0).smoothCurveTo(l / 2, -10, l, 0).lineTo(l, 0).smoothCurveTo(l / 2, 10, 0, 0).closePath().setStroke({
color: this.borderColor,
width: 1,
join: 10
}).setFill({
type: "linear",
x1: 0,
y1: 0,
x2: l,
y2: 0,
colors: [
{offset: 0, color: [208,208,208]},
{offset: 1, color: this.indicatorColor}
]
});
}));
scale.addIndicator("indicator", indicator);
this.addElement("foreground", lang.hitch(this, this.drawForeground));
},
drawBackground: function(g){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// tags:
// protected
g.createPath({
path: "M81.9213 6.4012 C36.7458 6.4012 0 43.1469 0 88.3225 C0 133.498 36.7458 170.2438 81.9213 170.2438 C127.0968 170.2438 163.8426 133.498 163.8425 88.3225 C163.8425 43.147 127.0968 6.4012 81.9213 6.4012 ZM81.9213 14.6771 C122.6195 14.6771 155.5666 47.6241 155.5666 88.3225 C155.5667 129.0207 122.6195 161.9678 81.9213 161.9678 C41.223 161.9678 8.2759 129.0207 8.2759 88.3225 C8.2759 47.6242 41.223 14.6771 81.9213 14.6771 Z"
}).setFill(this.borderColor);
g.createPath({
path: "M131.7007 23.859 C123.1609 16.836 112.7669 11.9131 100.5479 9.0902 C61.2014 0 20.5795 20.6702 9.8522 55.1976 C9.3592 56.9339 12.7501 58.0358 13.6957 55.5238 C24.6274 24.4073 64.5764 6.1932 100.6316 14.523 C118.2575 18.5951 131.7906 27.3347 141.2184 40.7415 C143.0075 43.6629 146.9334 42.1265 145.2492 39.0652 C141.4153 33.222 136.9106 28.1434 131.7007 23.859 Z"
}).setFill({
type: "linear",
x1: 9.8035,
y1: 6.94738,
x2: 9.8035,
y2: 31.97231,
colors: [
{offset: 0, color: [235,235,235]},
{offset: 1, color: this.borderColor}
]
});
g.createPath({
path: "M128.7453 148.5681 C120.6736 155.591 110.8493 160.5139 99.3 163.3368 C62.1102 172.427 23.715 151.7568 13.5757 117.2294 C13.1097 115.4931 16.3147 114.3912 17.2085 116.9032 C27.541 148.0197 65.3002 166.2338 99.3792 157.904 C116.0389 153.8319 128.8303 145.0923 137.7413 131.6855 C139.4323 128.7641 143.143 130.3005 141.5511 133.3618 C137.9274 139.205 133.6696 144.2836 128.7453 148.5681 Z"
}).setFill({
type: "linear",
x1: 13.52963,
y1: 165.47966,
x2: 13.52963,
y2: 140.45474,
colors: [
{offset: 0, color: [235,235,235]},
{offset: 1, color: this.borderColor}
]
});
g.createPath({
path: "M155.481 88.3136 C155.481 129.2951 122.5479 162.5169 81.9228 162.5169 C41.2978 162.5169 8.3647 129.2951 8.3647 88.3136 C8.3647 47.3323 41.2978 14.1102 81.9228 14.1102 C122.5479 14.1102 155.481 47.3323 155.481 88.3136 Z"
}).setFill({
type: "linear",
x1: 8.3647,
y1: 14.11022,
x2: 155.48103,
y2: 162.51695,
colors: [
{offset: 0, color: "white"},
{offset: 1, color: this.fillColor}
]
});
g.createPath({
path: "M81.9229 13.2351 C40.8398 13.2351 7.4925 46.8859 7.4925 88.3295 C7.4925 129.7729 40.8398 163.3921 81.9229 163.3921 C123.006 163.3921 156.3532 129.7729 156.3532 88.3295 C156.3532 46.8859 123.006 13.2351 81.9229 13.2351 ZM81.9229 14.7211 C122.1911 14.7211 154.8672 47.708 154.8672 88.3295 C154.8672 128.951 122.1911 161.906 81.9229 161.906 C41.6546 161.906 8.9786 128.951 8.9786 88.3295 C8.9786 47.708 41.6546 14.7211 81.9229 14.7211 Z"
}).setFill({
type: "linear",
x1: 7.4925,
y1: 13.23515,
x2: 7.4925,
y2: 163.39214,
colors: [
{offset: 0, color: "white"},
{offset: 1, color: [148,152,161]}
]
});
},
drawForeground: function(g){
// summary:
// Draws the foreground shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the foreground.
// tags:
// protected
g.createEllipse({
cx: 81.85091,
cy: 87.72405,
rx: 9.25,
ry: 9.25
}).setFill({
type: "radial",
cx: 81.85093,
cy: 84.02408,
r: 18.5,
colors: [
{offset: 0, color: [149,149,149]},
{offset: 0.5, color: "black"},
{offset: 1, color: "black"}
]
}).setStroke({
color: "black",
width: 0.1,
style: "Solid",
cap: "butt",
join: 4.0
});
}
});
}
);
},
'dojox/dgauges/components/classic/SemiCircularLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../../CircularGauge",
"../../LinearScaler",
"../../CircularScale",
"../../CircularValueIndicator",
"../../CircularRangeIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, CircularGauge, LinearScaler, CircularScale, CircularValueIndicator, CircularRangeIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.classic.SemiCircularLinearGauge", [CircularGauge, DefaultPropertiesMixin], {
// summary:
// A semi circular gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#797E86".
borderColor: [121,126,134],
// fillColor: Object|Array|int
// The background color. Default is "#9498A1".
fillColor: [148,152,161],
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#FFFFFF".
indicatorColor: "#FFFFFF",
constructor: function(){
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
var scaler = new LinearScaler();
this.addElement("background", lang.hitch(this, this.drawBackground));
var scale = new CircularScale();
scale.set("scaler", scaler);
scale.set("originX", 82.5469);
scale.set("originY", 86.56135);
scale.set("radius", 68.2182);
scale.set("startAngle", -179.9);
scale.set("endAngle", -0.1);
scale.set("orientation", "clockwise");
scale.set("labelGap", 2);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "6pt"
});
this.addElement("scale", scale);
var indicator = new CircularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group, indicator){
var l = indicator.scale.radius - 2;
return group.createPath().moveTo(0, 0).smoothCurveTo(l / 2, -10, l, 0).lineTo(l, 0).smoothCurveTo(l / 2, 10, 0, 0).closePath().setStroke({
color: this.borderColor,
width: 1,
join: 10
}).setFill({
type: "linear",
x1: 0,
y1: 0,
x2: l,
y2: 0,
colors: [
{offset: 0, color: [208,208,208]},
{offset: 1, color: this.indicatorColor}
]
});
}));
scale.addIndicator("indicator", indicator);
this.addElement("foreground", lang.hitch(this, this.drawForeground));
},
drawBackground: function(g){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// tags:
// protected
g.createPath({
path: "M82.4061 4.2361 C36.9308 4.2361 0 41.1357 0 86.6111 C0 92.8402 0.719 98.9014 2.0311 104.7361 L162.75 104.7361 C164.0621 98.9014 164.7812 92.8402 164.7812 86.6111 C164.7812 41.1357 127.8816 4.2361 82.4061 4.2361 Z"
}).setFill([121,126,134,1]);
g.createPath({
path: "M132.1809 21.8379 C109.1471 3.3761 75.6533 -0 48.8591 11.9106 C31.1385 19.6122 16.0526 34.4656 10.3325 53.1765 C13.128 58.4642 15.6567 49.646 16.9008 47.1352 C27.4881 26.5761 49.7822 14.215 72.1729 11.227 C95.4142 8.1002 121.0126 14.95 136.9788 32.7778 C139.4356 34.8999 143.5455 43.9915 146.1132 38.1149 C142.8197 31.7999 137.5776 26.4561 132.1809 21.8379 Z"
}).setFill({
type: "linear",
x1: 10.3325,
y1: 4.93862,
x2: 10.3325,
y2: 29.8873,
colors: [
{offset: 0, color: [235,235,235]},
{offset: 1, color: this.borderColor}
]
});
g.createPath({
path: "M82.2469 11.4202 C54.147 11.0778 26.9953 28.2183 14.7503 53.4303 C7.835 67.2286 5.3186 83.1515 7.5166 98.4202 C57.3367 98.4202 107.1569 98.4202 156.9772 98.4202 C161.2359 70.7787 148.7651 41.4452 125.8445 25.4041 C113.2386 16.3396 97.7752 11.3718 82.2469 11.4202 Z"
}).setFill({
type: "linear",
x1: 6.74398,
y1: 11.41516,
x2: 6.74398,
y2: 98.4202,
colors: [
{offset: 0, color: "white"},
{offset: 1, color: this.fillColor}
]
});
g.createPath({
path: "M82.2469 12.4202 C53.2167 12.031 25.1734 30.4906 13.8879 57.2103 C8.3968 69.7668 6.5444 83.863 8.5064 97.4202 C57.6668 97.4202 106.827 97.4202 155.9873 97.4202 C160.2416 70.0807 147.542 41.1134 124.6241 25.6326 C112.2794 17.0413 97.2852 12.377 82.2469 12.4202 L82.2469 12.4202 Z"
}).setFill({
type: "linear",
x1: 7.74645,
y1: 12.41416,
x2: 156.8018,
y2: 97.4202,
colors: [
{offset: 0, color: "white"},
{offset: 1, color: this.fillColor}
]
});
},
drawForeground: function(g){
// summary:
// Draws the foreground shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the foreground.
// tags:
// protected
g.createEllipse({
cx: 82.2187,
cy: 86.0486,
rx: 9.25,
ry: 9.25
}).setFill({
type: "radial",
cx: 82.21872,
cy: 82.34862,
r: 18.5,
colors: [
{offset: 0, color: [149,149,149]},
{offset: 0.5, color: "black"},
{offset: 1, color: "black"}
]
}).setStroke({
color: "black",
width: 0.1,
style: "Solid",
cap: "butt",
join: 4.0
});
}
});
}
);
},
'dojox/dgauges/components/classic/VerticalLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../../RectangularGauge",
"../../LinearScaler",
"../../RectangularScale",
"../../RectangularValueIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, RectangularGauge, LinearScaler, RectangularScale, RectangularValueIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.classic.VerticalLinearGauge", [RectangularGauge, DefaultPropertiesMixin], {
// summary:
// A vertical gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#797E86".
borderColor: [121,126,134],
// fillColor: Object|Array|int
// The background color. Default is "#9498A1".
fillColor: [148,152,161],
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#FFFFFF".
indicatorColor: "#FFFFFF",
constructor: function(){
this.orientation = "vertical";
// Base colors
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
this.addElement("background", lang.hitch(this, this.drawBackground));
// Scaler
var scaler = new LinearScaler();
// Scale
var scale = new RectangularScale();
scale.set("scaler", scaler);
scale.set("labelPosition", "trailing");
scale.set("paddingTop", 30);
scale.set("paddingBottom", 30);
scale.set("paddingLeft", 17);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "7pt"
});
scale.set("tickShapeFunc", function(group, scale, tick){
return group.createCircle({
r: tick.isMinor ? 0.5 : 2
}).setFill("black");
});
this.addElement("scale", scale);
var indicator = new RectangularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("paddingLeft", 18);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group){
return group.createPolyline([0, 0, -10, -20, 10, -20, 0, 0]).setFill(this.indicatorColor).setStroke({
color: [121,126,134],
width: 1,
style: "Solid",
cap: "butt",
join: 20.0
});
}));
scale.addIndicator("indicator", indicator);
},
drawBackground: function(g, w, h){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// w: Number
// The width of the gauge.
// h: Number
// The height of the gauge.
// tags:
// protected
g.createRect({
x: 0,
y: 0,
width: 50,
height: h,
r: 8
}).setFill(this.borderColor);
g.createRect({
x: 2,
y: 2,
width: 46,
height: h / 2,
r: 6
}).setFill({
type: "linear",
x1: 0,
y1: 2,
x2: 0,
y2: h / 2,
colors: [
{offset: 0, color: [235,235,235]},
{offset: 1, color: this.borderColor}
]
});
g.createRect({
x: 6,
y: 6,
width: 38,
height: h - 12,
r: 5
}).setFill({
type: "linear",
x1: 6,
y1: 0,
x2: 38,
y2: 0,
colors: [
{offset: 0, color: this.fillColor},
{offset: 1, color: [220,220,220]}
]
});
g.createRect({
x: 7,
y: 7,
width: 36,
height: h - 14,
r: 3
}).setFill({
type: "linear",
x1: 7,
y1: 0,
x2: 36,
y2: 0,
colors: [
{offset: 0, color: [220,220,220]},
{offset: 1, color: this.fillColor}
]
});
}
});
}
);
},
'dojox/dgauges/components/classic/HorizontalLinearGauge':function(){
define([
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/Color",
"../../RectangularGauge",
"../../LinearScaler",
"../../RectangularScale",
"../../RectangularValueIndicator",
"../DefaultPropertiesMixin"
],
function(lang, declare, Color, RectangularGauge, LinearScaler, RectangularScale, RectangularValueIndicator, DefaultPropertiesMixin){
return declare("dojox.dgauges.components.classic.HorizontalLinearGauge", [RectangularGauge, DefaultPropertiesMixin], {
// summary:
// A horizontal gauge widget.
// borderColor: Object|Array|int
// The border color. Default is "#797E86".
borderColor: [121,126,134],
// fillColor: Object|Array|int
// The background color. Default is "#9498A1".
fillColor: [148,152,161],
// indicatorColor: Object|Array|int
// The indicator fill color. Default is "#FFFFFF".
indicatorColor: "#FFFFFF",
constructor: function(){
// Base colors
this.borderColor = new Color(this.borderColor);
this.fillColor = new Color(this.fillColor);
this.indicatorColor = new Color(this.indicatorColor);
this.addElement("background", lang.hitch(this, this.drawBackground));
// Scaler
var scaler = new LinearScaler();
// Scale
var scale = new RectangularScale();
scale.set("scaler", scaler);
scale.set("labelPosition", "leading");
scale.set("paddingLeft", 30);
scale.set("paddingRight", 30);
scale.set("paddingTop", 32);
scale.set("labelGap", 8);
scale.set("font", {
family: "Helvetica",
weight: "bold",
size: "7pt"
});
scale.set("tickShapeFunc", function(group, scale, tick){
return group.createCircle({
r: tick.isMinor ? 0.5 : 2
}).setFill("black");
});
this.addElement("scale", scale);
var indicator = new RectangularValueIndicator();
indicator.set("interactionArea", "gauge");
indicator.set("value", scaler.minimum);
indicator.set("paddingTop", 30);
indicator.set("indicatorShapeFunc", lang.hitch(this, function(group, indicator){
return group.createPolyline([0, 0, -10, -20, 10, -20, 0, 0]).setFill(this.indicatorColor).setStroke({
color: [121,126,134],
width: 1,
style: "Solid",
cap: "butt",
join: 20.0
});
}));
scale.addIndicator("indicator", indicator);
},
drawBackground: function(g, w, h){
// summary:
// Draws the background shape of the gauge.
// g: dojox/gfx/Group
// The group used to draw the background.
// w: Number
// The width of the gauge.
// h: Number
// The height of the gauge.
// tags:
// protected
g.createRect({
x: 0,
y: 0,
width: w,
height: 50,
r: 8
}).setFill(this.borderColor);
g.createRect({
x: 2,
y: 2,
width: w - 4,
height: 32,
r: 6
}).setFill({
type: "linear",
x1: 0,
y1: 2,
x2: 0,
y2: 15,
colors: [
{offset: 0, color: [235,235,235]},
{offset: 1, color: this.borderColor}
]
});
g.createRect({
x: 6,
y: 6,
width: w - 12,
height: 38,
r: 5
}).setFill({
type: "linear",
x1: 0,
y1: 6,
x2: 0,
y2: 38,
colors: [
{offset: 0, color: [220,220,220]},
{offset: 1, color: this.fillColor}
]
});
g.createRect({
x: 7,
y: 7,
width: w - 14,
height: 36,
r: 3
}).setFill({
type: "linear",
x1: 0,
y1: 7,
x2: 0,
y2: 36,
colors: [
{offset: 0, color: this.fillColor},
{offset: 1, color: [220,220,220]}
]
});
}
});
}
);
}}});
require(["dojox/mobile", "dojox/mobile/parser", "dojox/mobile/compat", "dojox/mobile/deviceTheme",
"dojox/dgauges/components/default/CircularLinearGauge",
"dojox/dgauges/components/default/SemiCircularLinearGauge",
"dojox/dgauges/components/default/VerticalLinearGauge",
"dojox/dgauges/components/default/HorizontalLinearGauge",
"dojox/dgauges/components/black/CircularLinearGauge",
"dojox/dgauges/components/black/SemiCircularLinearGauge",
"dojox/dgauges/components/black/VerticalLinearGauge",
"dojox/dgauges/components/black/HorizontalLinearGauge",
"dojox/dgauges/components/green/CircularLinearGauge",
"dojox/dgauges/components/green/SemiCircularLinearGauge",
"dojox/dgauges/components/green/VerticalLinearGauge",
"dojox/dgauges/components/green/HorizontalLinearGauge",
"dojox/dgauges/components/grey/CircularLinearGauge",
"dojox/dgauges/components/grey/SemiCircularLinearGauge",
"dojox/dgauges/components/grey/VerticalLinearGauge",
"dojox/dgauges/components/grey/HorizontalLinearGauge",
"dojox/dgauges/components/classic/CircularLinearGauge",
"dojox/dgauges/components/classic/SemiCircularLinearGauge",
"dojox/dgauges/components/classic/VerticalLinearGauge",
"dojox/dgauges/components/classic/HorizontalLinearGauge"]);