source: Dev/trunk/src/client/dojox/mobile/View.js @ 529

Last change on this file since 529 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 23.6 KB
Line 
1define([
2        "dojo/_base/array",
3        "dojo/_base/config",
4        "dojo/_base/connect",
5        "dojo/_base/declare",
6        "dojo/_base/lang",
7        "dojo/sniff",
8        "dojo/_base/window",
9        "dojo/_base/Deferred",
10        "dojo/dom",
11        "dojo/dom-class",
12        "dojo/dom-construct",
13        "dojo/dom-geometry",
14        "dojo/dom-style",
15        "dijit/registry",
16        "dijit/_Contained",
17        "dijit/_Container",
18        "dijit/_WidgetBase",
19        "./ViewController", // to load ViewController for you (no direct references)
20        "./common",
21        "./transition",
22        "./viewRegistry",
23        "./_css3"
24], function(array, config, connect, declare, lang, has, win, Deferred, dom, domClass, domConstruct, domGeometry, domStyle, registry, Contained, Container, WidgetBase, ViewController, common, transitDeferred, viewRegistry, css3){
25
26        // module:
27        //              dojox/mobile/View
28
29        var dm = lang.getObject("dojox.mobile", true);
30
31        return declare("dojox.mobile.View", [WidgetBase, Container, Contained], {
32                // summary:
33                //              A widget that represents a view that occupies the full screen
34                // description:
35                //              View is a container widget for any HTML element and/or Dojo widgets.
36                //              As a Dojo widget container it can itself contain View widgets
37                //              forming a set of nested views. A Dojo Mobile application is usually
38                //              made of multiple View widgets and the user can navigate through
39                //              the views back and forth with animated transition effects.
40                //             
41                //              When using several sibling views (direct children of the same
42                //              element), you can use the 'selected' attribute to define whether
43                //              the view should be displayed when the application is launched.
44                //              If no view has selected=true, the first sibling view is displayed
45                //              at startup time.
46
47                // selected: Boolean
48                //              If true, the view is displayed at startup time.
49                selected: false,
50
51                // keepScrollPos: Boolean
52                //              If true, the scroll position is kept when transition occurs between views.
53                keepScrollPos: true,
54
55                // tag: String
56                //              The name of the HTML tag to create as domNode. The default value is "div".
57                tag: "div",
58
59                /* internal properties */
60                baseClass: "mblView",
61
62                constructor: function(/*Object*/params, /*DomNode?*/node){
63                        // summary:
64                        //              Creates a new instance of the class.
65                        // params:
66                        //              Contains the parameters.
67                        // node:
68                        //              The DOM node. If none is specified, it is automatically created.
69                        if(node){
70                                dom.byId(node).style.visibility = "hidden";
71                        }
72                },
73
74                destroy: function(){
75                        viewRegistry.remove(this.id);
76                        this.inherited(arguments);
77                },
78
79                buildRendering: function(){
80                        if(!this.templateString){
81                                // Create root node if it wasn't created by _TemplatedMixin
82                                this.domNode = this.containerNode = this.srcNodeRef || domConstruct.create(this.tag);
83                        }
84
85                        this._animEndHandle = this.connect(this.domNode, css3.name("animationEnd"), "onAnimationEnd");
86                        this._animStartHandle = this.connect(this.domNode, css3.name("animationStart"), "onAnimationStart");
87                        if(!config['mblCSS3Transition']){
88                                this._transEndHandle = this.connect(this.domNode, css3.name("transitionEnd"), "onAnimationEnd");
89                        }
90                        if(has('mblAndroid3Workaround')){
91                                // workaround for the screen flicker issue on Android 3.x/4.0
92                                // applying "-webkit-transform-style:preserve-3d" to domNode can avoid
93                                // transition animation flicker
94                                domStyle.set(this.domNode, css3.name("transformStyle"), "preserve-3d");
95                        }
96
97                        viewRegistry.add(this);
98                        this.inherited(arguments);
99                },
100
101                startup: function(){
102                        if(this._started){ return; }
103
104                        // Determine which view among the siblings should be visible.
105                        // Priority:
106                        //       1. fragment id in the url (ex. #view1,view2)
107                        //       2. this.selected
108                        //       3. the first view
109                        if(this._visible === undefined){
110                                var views = this.getSiblingViews();
111                                var ids = location.hash && location.hash.substring(1).split(/,/);
112                                var fragView, selectedView, firstView;
113                                array.forEach(views, function(v, i){
114                                        if(array.indexOf(ids, v.id) !== -1){ fragView = v; }
115                                        if(i == 0){ firstView = v; }
116                                        if(v.selected){ selectedView = v; }
117                                        v._visible = false;
118                                }, this);
119                                (fragView || selectedView || firstView)._visible = true;
120                        }
121                        if(this._visible){
122                                // The 2nd arg is not to hide its sibling views so that they can be
123                                // correctly initialized.
124                                this.show(true, true);
125
126                                // Defer firing events to let user connect to events just after creation
127                                // TODO: revisit this for 2.0
128                                this.defer(function(){
129                                        this.onStartView();
130                                        connect.publish("/dojox/mobile/startView", [this]);
131                                });
132                        }
133
134                        if(this.domNode.style.visibility === "hidden"){ // this check is to avoid screen flickers
135                                this.domNode.style.visibility = "inherit";
136                        }
137
138                        // Need to call inherited first - so that child widgets get started
139                        // up correctly
140                        this.inherited(arguments);
141
142                        var parent = this.getParent();
143                        if(!parent || !parent.resize){ // top level widget
144                                this.resize();
145                        }
146
147                        if(!this._visible){
148                                // hide() should be called last so that child widgets can be
149                                // initialized while they are visible.
150                                this.hide();
151                        }
152                },
153
154                resize: function(){
155                        // summary:
156                        //              Calls resize() of each child widget.
157                        array.forEach(this.getChildren(), function(child){
158                                if(child.resize){ child.resize(); }
159                        });
160                },
161
162                onStartView: function(){
163                        // summary:
164                        //              Stub function to connect to from your application.
165                        // description:
166                        //              Called only when this view is shown at startup time.
167                },
168
169                onBeforeTransitionIn: function(moveTo, dir, transition, context, method){
170                        // summary:
171                        //              Stub function to connect to from your application.
172                        // description:
173                        //              Called before the arriving transition occurs.
174                },
175
176                onAfterTransitionIn: function(moveTo, dir, transition, context, method){
177                        // summary:
178                        //              Stub function to connect to from your application.
179                        // description:
180                        //              Called after the arriving transition occurs.
181                },
182
183                onBeforeTransitionOut: function(moveTo, dir, transition, context, method){
184                        // summary:
185                        //              Stub function to connect to from your application.
186                        // description:
187                        //              Called before the leaving transition occurs.
188                },
189
190                onAfterTransitionOut: function(moveTo, dir, transition, context, method){
191                        // summary:
192                        //              Stub function to connect to from your application.
193                        // description:
194                        //              Called after the leaving transition occurs.
195                },
196
197                _clearClasses: function(/*DomNode*/node){
198                        // summary:
199                        //              Clean up the domNode classes that were added while making a transition.
200                        // description:
201                        //              Remove all the "mbl" prefixed classes except mbl*View.
202                        if(!node){ return; }
203                        var classes = [];
204                        array.forEach(lang.trim(node.className||"").split(/\s+/), function(c){
205                                if(c.match(/^mbl\w*View$/) || c.indexOf("mbl") === -1){
206                                        classes.push(c);
207                                }
208                        }, this);
209                        node.className = classes.join(' ');
210                },
211
212                _fixViewState: function(/*DomNode*/toNode){
213                        // summary:
214                        //              Sanity check for view transition states.
215                        // description:
216                        //              Sometimes uninitialization of Views fails after making view transition,
217                        //              and that results in failure of subsequent view transitions.
218                        //              This function does the uninitialization for all the sibling views.
219                        var nodes = this.domNode.parentNode.childNodes;
220                        for(var i = 0; i < nodes.length; i++){
221                                var n = nodes[i];
222                                if(n.nodeType === 1 && domClass.contains(n, "mblView")){
223                                        this._clearClasses(n);
224                                }
225                        }
226                        this._clearClasses(toNode); // just in case toNode is a sibling of an ancestor.
227                       
228                        // #16337
229                        // Uninitialization may fail to clear _inProgress when multiple
230                        // performTransition calls occur in a short duration of time.
231                        var toWidget = registry.byNode(toNode);
232                        if(toWidget){
233                                toWidget._inProgress = false;
234                        }
235                },
236
237                convertToId: function(moveTo){
238                        if(typeof(moveTo) == "string"){
239                                // removes a leading hash mark (#) and params if exists
240                                // ex. "#bar&myParam=0003" -> "bar"
241                                return moveTo.replace(/^#?([^&?]+).*/, "$1");
242                        }
243                        return moveTo;
244                },
245
246                _isBookmarkable: function(detail){
247                        return detail.moveTo && (config['mblForceBookmarkable'] || detail.moveTo.charAt(0) === '#') && !detail.hashchange;
248                },
249
250                performTransition: function(/*String*/moveTo, /*Number*/transitionDir, /*String*/transition,
251                                                                        /*Object|null*/context, /*String|Function*/method /*...*/){
252                        // summary:
253                        //              Function to perform the various types of view transitions, such as fade, slide, and flip.
254                        // moveTo: String
255                        //              The id of the transition destination view which resides in
256                        //              the current page.
257                        //              If the value has a hash sign ('#') before the id
258                        //              (e.g. #view1) and the dojo/hash module is loaded by the user
259                        //              application, the view transition updates the hash in the
260                        //              browser URL so that the user can bookmark the destination
261                        //              view. In this case, the user can also use the browser's
262                        //              back/forward button to navigate through the views in the
263                        //              browser history.
264                        //              If null, transitions to a blank view.
265                        //              If '#', returns immediately without transition.
266                        // transitionDir: Number
267                        //              The transition direction. If 1, transition forward. If -1, transition backward.
268                        //              For example, the slide transition slides the view from right to left when transitionDir == 1,
269                        //              and from left to right when transitionDir == -1.
270                        // transition: String
271                        //              A type of animated transition effect. You can choose from
272                        //              the standard transition types, "slide", "fade", "flip", or
273                        //              from the extended transition types, "cover", "coverv",
274                        //              "dissolve", "reveal", "revealv", "scaleIn", "scaleOut",
275                        //              "slidev", "swirl", "zoomIn", "zoomOut", "cube", and
276                        //              "swap". If "none" is specified, transition occurs
277                        //              immediately without animation.
278                        // context: Object
279                        //              The object that the callback function will receive as "this".
280                        // method: String|Function
281                        //              A callback function that is called when the transition has finished.
282                        //              A function reference, or name of a function in context.
283                        // tags:
284                        //              public
285                        //
286                        // example:
287                        //              Transition backward to a view whose id is "foo" with the slide animation.
288                        //      |       performTransition("foo", -1, "slide");
289                        //
290                        // example:
291                        //              Transition forward to a blank view, and then open another page.
292                        //      |       performTransition(null, 1, "slide", null, function(){location.href = href;});
293
294                        if(this._inProgress){ return; } // transition is in progress
295                        this._inProgress = true;
296                       
297                        // normalize the arg
298                        var detail, optArgs;
299                        if(moveTo && typeof(moveTo) === "object"){
300                                detail = moveTo;
301                                optArgs = transitionDir; // array
302                        }else{
303                                detail = {
304                                        moveTo: moveTo,
305                                        transitionDir: transitionDir,
306                                        transition: transition,
307                                        context: context,
308                                        method: method
309                                };
310                                optArgs = [];
311                                for(var i = 5; i < arguments.length; i++){
312                                        optArgs.push(arguments[i]);
313                                }
314                        }
315
316                        // save the parameters
317                        this._detail = detail;
318                        this._optArgs = optArgs;
319                        this._arguments = [
320                                detail.moveTo,
321                                detail.transitionDir,
322                                detail.transition,
323                                detail.context,
324                                detail.method
325                        ];
326
327                        if(detail.moveTo === "#"){ return; }
328                        var toNode;
329                        if(detail.moveTo){
330                                toNode = this.convertToId(detail.moveTo);
331                        }else{
332                                if(!this._dummyNode){
333                                        this._dummyNode = win.doc.createElement("div");
334                                        win.body().appendChild(this._dummyNode);
335                                }
336                                toNode = this._dummyNode;
337                        }
338
339                        if(this.addTransitionInfo && typeof(detail.moveTo) == "string" && this._isBookmarkable(detail)){
340                                this.addTransitionInfo(this.id, detail.moveTo, {transitionDir:detail.transitionDir, transition:detail.transition});
341                        }
342
343                        var fromNode = this.domNode;
344                        var fromTop = fromNode.offsetTop;
345                        toNode = this.toNode = dom.byId(toNode);
346                        if(!toNode){ console.log("dojox/mobile/View.performTransition: destination view not found: "+detail.moveTo); return; }
347                        toNode.style.visibility = "hidden";
348                        toNode.style.display = "";
349                        this._fixViewState(toNode);
350                        var toWidget = registry.byNode(toNode);
351                        if(toWidget){
352                                // Now that the target view became visible, it's time to run resize()
353                                if(config["mblAlwaysResizeOnTransition"] || !toWidget._resized){
354                                        common.resizeAll(null, toWidget);
355                                        toWidget._resized = true;
356                                }
357
358                                if(detail.transition && detail.transition != "none"){
359                                        // Temporarily add padding to align with the fromNode while transition
360                                        toWidget._addTransitionPaddingTop(fromTop);
361                                }
362
363                                toWidget.load && toWidget.load(); // for ContentView
364
365                                toWidget.movedFrom = fromNode.id;
366                        }
367                        if(has('mblAndroidWorkaround') && !config['mblCSS3Transition']
368                                        && detail.transition && detail.transition != "none"){
369                                // workaround for the screen flicker issue on Android 2.2/2.3
370                                // apply "-webkit-transform-style:preserve-3d" to both toNode and fromNode
371                                // to make them 3d-transition-ready state just before transition animation
372                                domStyle.set(toNode, css3.name("transformStyle"), "preserve-3d");
373                                domStyle.set(fromNode, css3.name("transformStyle"), "preserve-3d");
374                                // show toNode offscreen to avoid flicker when switching "display" and "visibility" styles
375                                domClass.add(toNode, "mblAndroidWorkaround");
376                        }
377
378                        this.onBeforeTransitionOut.apply(this, this._arguments);
379                        connect.publish("/dojox/mobile/beforeTransitionOut", [this].concat(lang._toArray(this._arguments)));
380                        if(toWidget){
381                                // perform view transition keeping the scroll position
382                                if(this.keepScrollPos && !this.getParent()){
383                                        var scrollTop = win.body().scrollTop || win.doc.documentElement.scrollTop || win.global.pageYOffset || 0;
384                                        fromNode._scrollTop = scrollTop;
385                                        var toTop = (detail.transitionDir == 1) ? 0 : (toNode._scrollTop || 0);
386                                        toNode.style.top = "0px";
387                                        if(scrollTop > 1 || toTop !== 0){
388                                                fromNode.style.top = toTop - scrollTop + "px";
389                                                // address bar hiding does not work on iOS 7+.
390                                                if(!(has("ios") >= 7) && config["mblHideAddressBar"] !== false){
391                                                        this.defer(function(){ // iPhone needs setTimeout (via defer)
392                                                                win.global.scrollTo(0, (toTop || 1));
393                                                        });
394                                                }
395                                        }
396                                }else{
397                                        toNode.style.top = "0px";
398                                }
399                                toWidget.onBeforeTransitionIn.apply(toWidget, this._arguments);
400                                connect.publish("/dojox/mobile/beforeTransitionIn", [toWidget].concat(lang._toArray(this._arguments)));
401                        }
402                        toNode.style.display = "none";
403                        toNode.style.visibility = "inherit";
404
405                        common.fromView = this;
406                        common.toView = toWidget;
407
408                        this._doTransition(fromNode, toNode, detail.transition, detail.transitionDir);
409                },
410
411                _addTransitionPaddingTop: function(/*String|Integer*/ value){
412                        // add padding top to the view in order to get alignment during the transition
413                        this.containerNode.style.paddingTop = value + "px";
414                },
415
416                _removeTransitionPaddingTop: function(){
417                        // remove padding top from the view after the transition
418                        this.containerNode.style.paddingTop = "";
419                },
420
421                _toCls: function(s){
422                        // convert from transition name to corresponding class name
423                        // ex. "slide" -> "mblSlide"
424                        return "mbl"+s.charAt(0).toUpperCase() + s.substring(1);
425                },
426
427                _doTransition: function(fromNode, toNode, transition, transitionDir){
428                        var rev = (transitionDir == -1) ? " mblReverse" : "";
429                        toNode.style.display = "";
430                        if(!transition || transition == "none"){
431                                this.domNode.style.display = "none";
432                                this.invokeCallback();
433                        }else if(config['mblCSS3Transition']){
434                                //get dojox/css3/transit first
435                                Deferred.when(transitDeferred, lang.hitch(this, function(transit){
436                                        //follow the style of .mblView.mblIn in View.css
437                                        //need to set the toNode to absolute position
438                                        var toPosition = domStyle.get(toNode, "position");
439                                        domStyle.set(toNode, "position", "absolute");
440                                        Deferred.when(transit(fromNode, toNode, {transition: transition, reverse: (transitionDir===-1)?true:false}),lang.hitch(this,function(){
441                                                domStyle.set(toNode, "position", toPosition);
442                                                // Reset the temporary padding on toNode
443                                                toNode.style.paddingTop = "";
444                                                this.invokeCallback();
445                                        }));
446                                }));
447                        }else{
448                                if(transition.indexOf("cube") != -1){
449                                        if(has('ipad')){
450                                                domStyle.set(toNode.parentNode, {webkitPerspective:1600});
451                                        }else if(has("ios")){
452                                                domStyle.set(toNode.parentNode, {webkitPerspective:800});
453                                        }
454                                }
455                                var s = this._toCls(transition);
456                                if(has('mblAndroidWorkaround')){
457                                        // workaround for the screen flicker issue on Android 2.2
458                                        // applying transition css classes just after setting toNode.style.display = ""
459                                        // causes flicker, so wait for a while using setTimeout (via defer)
460                                        var _this = this;
461                                        _this.defer(function(){
462                                                domClass.add(fromNode, s + " mblOut" + rev);
463                                                domClass.add(toNode, s + " mblIn" + rev);
464                                                domClass.remove(toNode, "mblAndroidWorkaround"); // remove offscreen style
465                                                _this.defer(function(){
466                                                        domClass.add(fromNode, "mblTransition");
467                                                        domClass.add(toNode, "mblTransition");
468                                                }, 30); // 30 = 100 - 70, to make total delay equal to 100ms
469                                        }, 70); // 70ms is experiential value
470                                }else{
471                                        domClass.add(fromNode, s + " mblOut" + rev);
472                                        domClass.add(toNode, s + " mblIn" + rev);
473                                        this.defer(function(){
474                                                domClass.add(fromNode, "mblTransition");
475                                                domClass.add(toNode, "mblTransition");
476                                        }, 100);
477                                }
478                                // set transform origin
479                                var fromOrigin = "50% 50%";
480                                var toOrigin = "50% 50%";
481                                var scrollTop, posX, posY;
482                                if(transition.indexOf("swirl") != -1 || transition.indexOf("zoom") != -1){
483                                        if(this.keepScrollPos && !this.getParent()){
484                                                scrollTop = win.body().scrollTop || win.doc.documentElement.scrollTop || win.global.pageYOffset || 0;
485                                        }else{
486                                                scrollTop = -domGeometry.position(fromNode, true).y;
487                                        }
488                                        posY = win.global.innerHeight / 2 + scrollTop;
489                                        fromOrigin = "50% " + posY + "px";
490                                        toOrigin = "50% " + posY + "px";
491                                }else if(transition.indexOf("scale") != -1){
492                                        var viewPos = domGeometry.position(fromNode, true);
493                                        posX = ((this.clickedPosX !== undefined) ? this.clickedPosX : win.global.innerWidth / 2) - viewPos.x;
494                                        if(this.keepScrollPos && !this.getParent()){
495                                                scrollTop = win.body().scrollTop || win.doc.documentElement.scrollTop || win.global.pageYOffset || 0;
496                                        }else{
497                                                scrollTop = -viewPos.y;
498                                        }
499                                        posY = ((this.clickedPosY !== undefined) ? this.clickedPosY : win.global.innerHeight / 2) + scrollTop;
500                                        fromOrigin = posX + "px " + posY + "px";
501                                        toOrigin = posX + "px " + posY + "px";
502                                }
503                                domStyle.set(fromNode, css3.add({}, {transformOrigin:fromOrigin}));
504                                domStyle.set(toNode, css3.add({}, {transformOrigin:toOrigin}));
505                        }
506                },
507
508                onAnimationStart: function(e){
509                        // summary:
510                        //              A handler that is called when transition animation starts.
511                },
512
513                onAnimationEnd: function(e){
514                        // summary:
515                        //              A handler that is called after transition animation ends.
516                        var name = e.animationName || e.target.className;
517                        if(name.indexOf("Out") === -1 &&
518                                name.indexOf("In") === -1 &&
519                                name.indexOf("Shrink") === -1){ return; }
520                        var isOut = false;
521                        if(domClass.contains(this.domNode, "mblOut")){
522                                isOut = true;
523                                this.domNode.style.display = "none";
524                                domClass.remove(this.domNode, [this._toCls(this._detail.transition), "mblIn", "mblOut", "mblReverse"]);
525                        }else{
526                                // Reset the temporary padding
527                                this._removeTransitionPaddingTop();
528                        }
529                        domStyle.set(this.domNode, css3.add({}, {transformOrigin:""}));
530                        if(name.indexOf("Shrink") !== -1){
531                                var li = e.target;
532                                li.style.display = "none";
533                                domClass.remove(li, "mblCloseContent");
534
535                                // If target is placed inside scrollable, need to call onTouchEnd
536                                // to adjust scroll position
537                                var p = viewRegistry.getEnclosingScrollable(this.domNode);
538                                p && p.onTouchEnd();
539                        }
540                        if(isOut){
541                                this.invokeCallback();
542                        }
543                        this._clearClasses(this.domNode);
544
545                        // clear the clicked position
546                        this.clickedPosX = this.clickedPosY = undefined;
547
548                        if(name.indexOf("Cube") !== -1 &&
549                                name.indexOf("In") !== -1 && has("ios")){
550                                this.domNode.parentNode.style[css3.name("perspective")] = "";
551                        }
552                },
553
554                invokeCallback: function(){
555                        // summary:
556                        //              A function to be called after performing a transition to
557                        //              call a specified callback.
558                        this.onAfterTransitionOut.apply(this, this._arguments);
559                        connect.publish("/dojox/mobile/afterTransitionOut", [this].concat(this._arguments));
560                        var toWidget = registry.byNode(this.toNode);
561                        if(toWidget){
562                                toWidget.onAfterTransitionIn.apply(toWidget, this._arguments);
563                                connect.publish("/dojox/mobile/afterTransitionIn", [toWidget].concat(this._arguments));
564                                toWidget.movedFrom = undefined;
565                                if(this.setFragIds && this._isBookmarkable(this._detail)){
566                                        this.setFragIds(toWidget); // setFragIds is defined in bookmarkable.js
567                                }
568                        }
569                        if(has('mblAndroidWorkaround')){
570                                // workaround for the screen flicker issue on Android 2.2/2.3
571                                // remove "-webkit-transform-style" style after transition finished
572                                // to avoid side effects such as input field auto-scrolling issue
573                                // use setTimeout (via defer) to avoid flicker in case of ScrollableView
574                                this.defer(function(){
575                                        if(toWidget){ domStyle.set(this.toNode, css3.name("transformStyle"), ""); }
576                                        domStyle.set(this.domNode, css3.name("transformStyle"), "");
577                                });
578                        }
579
580                        var c = this._detail.context, m = this._detail.method;
581                        if(c || m){
582                                if(!m){
583                                        m = c;
584                                        c = null;
585                                }
586                                c = c || win.global;
587                                if(typeof(m) == "string"){
588                                        c[m].apply(c, this._optArgs);
589                                }else if(typeof(m) == "function"){
590                                        m.apply(c, this._optArgs);
591                                }
592                        }
593                        this._detail = this._optArgs = this._arguments = undefined;
594                        this._inProgress = false;
595                },
596
597                isVisible: function(/*Boolean?*/checkAncestors){
598                        // summary:
599                        //              Return true if this view is visible
600                        // checkAncestors:
601                        //              If true, in addition to its own visibility, also checks the
602                        //              ancestors visibility to see if the view is actually being
603                        //              shown or not.
604                        var visible = function(node){
605                                return domStyle.get(node, "display") !== "none";
606                        };
607                        if(checkAncestors){
608                                for(var n = this.domNode; n.tagName !== "BODY"; n = n.parentNode){
609                                        if(!visible(n)){ return false; }
610                                }
611                                return true;
612                        }else{
613                                return visible(this.domNode);
614                        }
615                },
616
617                getShowingView: function(){
618                        // summary:
619                        //              Find the currently showing view from my sibling views.
620                        // description:
621                        //              Note that depending on the ancestor views' visibility,
622                        //              the found view may not be actually shown.
623                        var nodes = this.domNode.parentNode.childNodes;
624                        for(var i = 0; i < nodes.length; i++){
625                                var n = nodes[i];
626                                if(n.nodeType === 1 && domClass.contains(n, "mblView") && n.style.display !== "none"){
627                                        return registry.byNode(n);
628                                }
629                        }
630                        return null;
631                },
632
633                getSiblingViews: function(){
634                        // summary:
635                        //              Returns an array of the sibling views.
636                        if(!this.domNode.parentNode){ return [this]; }
637                        return array.map(array.filter(this.domNode.parentNode.childNodes,
638                                function(n){ return n.nodeType === 1 && domClass.contains(n, "mblView"); }),
639                                function(n){ return registry.byNode(n); });
640                },
641
642                show: function(/*Boolean?*/noEvent, /*Boolean?*/doNotHideOthers){
643                        // summary:
644                        //              Shows this view without a transition animation.
645                        var out = this.getShowingView();
646                        if(!noEvent){
647                                if(out){
648                                        out.onBeforeTransitionOut(out.id);
649                                        connect.publish("/dojox/mobile/beforeTransitionOut", [out, out.id]);
650                                }
651                                this.onBeforeTransitionIn(this.id);
652                                connect.publish("/dojox/mobile/beforeTransitionIn", [this, this.id]);
653                        }
654
655                        if(doNotHideOthers){
656                                this.domNode.style.display = "";
657                        }else{
658                                array.forEach(this.getSiblingViews(), function(v){
659                                        v.domNode.style.display = (v === this) ? "" : "none";
660                                }, this);
661                        }
662                        this.load && this.load(); // for ContentView
663
664                        if(!noEvent){
665                                if(out){
666                                        out.onAfterTransitionOut(out.id);
667                                        connect.publish("/dojox/mobile/afterTransitionOut", [out, out.id]);
668                                }
669                                this.onAfterTransitionIn(this.id);
670                                connect.publish("/dojox/mobile/afterTransitionIn", [this, this.id]);
671                        }
672                },
673
674                hide: function(){
675                        // summary:
676                        //              Hides this view without a transition animation.
677                        this.domNode.style.display = "none";
678                }
679        });
680});
Note: See TracBrowser for help on using the repository browser.