656 lines
22 KiB
JavaScript
656 lines
22 KiB
JavaScript
define("dojox/mobile/View", [
|
|
"dojo/_base/array",
|
|
"dojo/_base/config",
|
|
"dojo/_base/connect",
|
|
"dojo/_base/declare",
|
|
"dojo/_base/lang",
|
|
"dojo/_base/sniff",
|
|
"dojo/_base/window",
|
|
"dojo/_base/Deferred",
|
|
"dojo/dom",
|
|
"dojo/dom-class",
|
|
"dojo/dom-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"
|
|
], function(array, config, connect, declare, lang, has, win, Deferred, dom, domClass, domConstruct, domGeometry, domStyle, registry, Contained, Container, WidgetBase, ViewController, common, transitDeferred, viewRegistry){
|
|
|
|
// module:
|
|
// dojox/mobile/View
|
|
|
|
var dm = lang.getObject("dojox.mobile", true);
|
|
|
|
return declare("dojox.mobile.View", [WidgetBase, Container, Contained], {
|
|
// summary:
|
|
// A widget that represents a view that occupies the full screen
|
|
// description:
|
|
// View acts as a container for any HTML and/or widgets. An entire
|
|
// HTML page can have multiple View widgets and the user can
|
|
// navigate through the views back and forth without page
|
|
// transitions.
|
|
|
|
// selected: Boolean
|
|
// If true, the view is displayed at startup time.
|
|
selected: false,
|
|
|
|
// keepScrollPos: Boolean
|
|
// If true, the scroll position is kept when transition occurs between views.
|
|
keepScrollPos: true,
|
|
|
|
// tag: String
|
|
// A name of the HTML tag to create as domNode.
|
|
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(){
|
|
this.domNode = this.containerNode = this.srcNodeRef || domConstruct.create(this.tag);
|
|
|
|
this._animEndHandle = this.connect(this.domNode, "webkitAnimationEnd", "onAnimationEnd");
|
|
this._animStartHandle = this.connect(this.domNode, "webkitAnimationStart", "onAnimationStart");
|
|
if(!config['mblCSS3Transition']){
|
|
this._transEndHandle = this.connect(this.domNode, "webkitTransitionEnd", "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, "webkitTransformStyle", "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 != "visible"){ // this check is to avoid screen flickers
|
|
this.domNode.style.visibility = "visible";
|
|
}
|
|
|
|
// 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.containerNode.style.paddingTop = fromTop + "px";
|
|
}
|
|
|
|
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, "webkitTransformStyle", "preserve-3d");
|
|
domStyle.set(fromNode, "webkitTransformStyle", "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";
|
|
if(config["mblHideAddressBar"] !== false){
|
|
setTimeout(function(){ // iPhone needs setTimeout
|
|
win.global.scrollTo(0, (toTop || 1));
|
|
}, 0);
|
|
}
|
|
}
|
|
}else{
|
|
toNode.style.top = "0px";
|
|
}
|
|
toWidget.onBeforeTransitionIn.apply(toWidget, this._arguments);
|
|
connect.publish("/dojox/mobile/beforeTransitionIn", [toWidget].concat(lang._toArray(this._arguments)));
|
|
}
|
|
toNode.style.display = "none";
|
|
toNode.style.visibility = "visible";
|
|
|
|
common.fromView = this;
|
|
common.toView = toWidget;
|
|
|
|
this._doTransition(fromNode, toNode, detail.transition, detail.transitionDir);
|
|
},
|
|
|
|
_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);
|
|
this.invokeCallback();
|
|
}));
|
|
}));
|
|
}else{
|
|
if(transition.indexOf("cube") != -1){
|
|
if(has('ipad')){
|
|
domStyle.set(toNode.parentNode, {webkitPerspective:1600});
|
|
}else if(has('iphone')){
|
|
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
|
|
setTimeout(function(){
|
|
domClass.add(fromNode, s + " mblOut" + rev);
|
|
domClass.add(toNode, s + " mblIn" + rev);
|
|
domClass.remove(toNode, "mblAndroidWorkaround"); // remove offscreen style
|
|
setTimeout(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);
|
|
setTimeout(function(){
|
|
domClass.add(fromNode, "mblTransition");
|
|
domClass.add(toNode, "mblTransition");
|
|
}, 100);
|
|
}
|
|
// set transform origin
|
|
var fromOrigin = "50% 50%";
|
|
var toOrigin = "50% 50%";
|
|
var scrollTop, posX, posY;
|
|
if(transition.indexOf("swirl") != -1 || transition.indexOf("zoom") != -1){
|
|
if(this.keepScrollPos && !this.getParent()){
|
|
scrollTop = win.body().scrollTop || win.doc.documentElement.scrollTop || win.global.pageYOffset || 0;
|
|
}else{
|
|
scrollTop = -domGeometry.position(fromNode, true).y;
|
|
}
|
|
posY = win.global.innerHeight / 2 + scrollTop;
|
|
fromOrigin = "50% " + posY + "px";
|
|
toOrigin = "50% " + posY + "px";
|
|
}else if(transition.indexOf("scale") != -1){
|
|
var viewPos = domGeometry.position(fromNode, true);
|
|
posX = ((this.clickedPosX !== undefined) ? this.clickedPosX : win.global.innerWidth / 2) - viewPos.x;
|
|
if(this.keepScrollPos && !this.getParent()){
|
|
scrollTop = win.body().scrollTop || win.doc.documentElement.scrollTop || win.global.pageYOffset || 0;
|
|
}else{
|
|
scrollTop = -viewPos.y;
|
|
}
|
|
posY = ((this.clickedPosY !== undefined) ? this.clickedPosY : win.global.innerHeight / 2) + scrollTop;
|
|
fromOrigin = posX + "px " + posY + "px";
|
|
toOrigin = posX + "px " + posY + "px";
|
|
}
|
|
domStyle.set(fromNode, {webkitTransformOrigin:fromOrigin});
|
|
domStyle.set(toNode, {webkitTransformOrigin:toOrigin});
|
|
}
|
|
},
|
|
|
|
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.containerNode.style.paddingTop = "";
|
|
}
|
|
domStyle.set(this.domNode, {webkitTransformOrigin:""});
|
|
if(name.indexOf("Shrink") !== -1){
|
|
var li = e.target;
|
|
li.style.display = "none";
|
|
domClass.remove(li, "mblCloseContent");
|
|
|
|
// If 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('iphone')){
|
|
this.domNode.parentNode.style.webkitPerspective = "";
|
|
}
|
|
},
|
|
|
|
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 to avoid flicker in case of ScrollableView
|
|
setTimeout(lang.hitch(this, function(){
|
|
if(toWidget){ domStyle.set(this.toNode, "webkitTransformStyle", ""); }
|
|
domStyle.set(this.domNode, "webkitTransformStyle", "");
|
|
}), 0);
|
|
}
|
|
|
|
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";
|
|
}
|
|
});
|
|
});
|