source: Dev/trunk/src/client/dojox/app/controllers/Transition.js

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

Added Dojo 1.9.3 release.

  • Property svn:executable set to *
File size: 30.5 KB
Line 
1define(["require", "dojo/_base/lang", "dojo/_base/declare", "dojo/has", "dojo/on", "dojo/Deferred", "dojo/when",
2        "dojo/dom-style", "../Controller", "../utils/constraints"],
3        function(require, lang, declare, has, on, Deferred, when, domStyle, Controller, constraints){
4
5        var transit;
6        var MODULE = "app/controllers/Transition";
7        var LOGKEY = "logTransitions:";
8
9        // module:
10        //              dojox/app/controllers/Transition
11        //              Bind "app-transition" event on dojox/app application instance.
12        //              Do transition from one view to another view.
13        return declare("dojox.app.controllers.Transition", Controller, {
14
15                proceeding: false,
16
17                waitingQueue:[],
18
19                constructor: function(app, events){
20                        // summary:
21                        //              bind "app-transition" event on application instance.
22                        //
23                        // app:
24                        //              dojox/app application instance.
25                        // events:
26                        //              {event : handler}
27                        this.events = {
28                                "app-transition": this.transition,
29                                "app-domNode": this.onDomNodeChange
30                        };
31                        require([this.app.transit || "dojox/css3/transit"], function(t){
32                                transit = t;
33                        });
34                        if(this.app.domNode){
35                                this.onDomNodeChange({oldNode: null, newNode: this.app.domNode});
36                        }
37                },
38
39                transition: function(event){
40                        // summary:
41                        //              Response to dojox/app "app-transition" event.
42                        //
43                        // example:
44                        //              Use emit to trigger "app-transition" event, and this function will response to the event. For example:
45                        //              |       this.app.emit("app-transition", {"viewId": viewId, "opts": opts});
46                        //
47                        // event: Object
48                        //              "app-transition" event parameter. It should be like: {"viewId": viewId, "opts": opts}
49                        var F = MODULE+":transition";
50                        this.app.log(LOGKEY,F,"New Transition event.viewId=["+event.viewId+"]");
51                        this.app.log(F,"event.viewId=["+event.viewId+"]","event.opts=",event.opts);
52
53                        var viewsId = event.viewId || "";
54                        this.proceedingSaved = this.proceeding;
55                        var parts = viewsId.split('+');
56                        var removePartsTest = viewsId.split('-');
57                        var viewId, newEvent;
58                        if(parts.length > 0 || removePartsTest.length > 0){
59                                while(parts.length > 1){       
60                                        viewId = parts.shift();
61                                        newEvent = lang.clone(event);
62                                        if(viewId.indexOf("-") >= 0){ // there is a remove
63                                                var removeParts = viewId.split('-');
64                                                if(removeParts.length > 0){
65                                                        viewId = removeParts.shift();
66                                                        if(viewId){
67                                                                newEvent._removeView = false;
68                                                                newEvent.viewId = viewId;
69                                                                this.proceeding = true;
70                                                                this.proceedTransition(newEvent);
71                                                                newEvent = lang.clone(event);
72                                                        }
73                                                        viewId = removeParts.shift();
74                                                        if(viewId){
75                                                                newEvent._removeView = true;
76                                                                newEvent.viewId = viewId;
77                                                                this.proceeding = true;
78                                                                this.proceedTransition(newEvent);
79                                                        }
80                                                }
81                                        }else{
82                                                newEvent._removeView = false;
83                                                newEvent.viewId = viewId;
84                                                this.proceeding = true;
85                                                this.proceedTransition(newEvent);
86                                        }
87                                }
88                                viewId = parts.shift();
89                                var removeParts = viewId.split('-');
90                                if(removeParts.length > 0){
91                                        viewId = removeParts.shift();
92                                }
93                                if(viewId.length > 0){ // check viewId.length > 0 to skip this section for a transition with only -viewId
94                                        this.proceeding = this.proceedingSaved;
95                                        event.viewId = viewId;
96                                        event._doResize = true; // at the end of the last transition call resize
97                                        event._removeView = false;
98                                        this.proceedTransition(event);
99                                }
100                                if(removeParts.length > 0){
101                                        while(removeParts.length > 0){
102                                                var remViewId = removeParts.shift();
103                                                newEvent = lang.clone(event);
104                                                newEvent.viewId = remViewId;
105                                                newEvent._removeView = true;
106                                                newEvent._doResize = true; // at the end of the last transition call resize
107                                                this.proceedTransition(newEvent);
108                                        }
109                                }
110                        }else{
111                                event._doResize = true; // at the end of the last transition call resize
112                                event._removeView = false;
113                                this.proceedTransition(event);
114                        }
115                },
116
117                onDomNodeChange: function(evt){
118                        if(evt.oldNode != null){
119                                this.unbind(evt.oldNode, "startTransition");
120                        }
121                        this.bind(evt.newNode, "startTransition", lang.hitch(this, this.onStartTransition));
122                },
123
124                onStartTransition: function(evt){
125                        // summary:
126                        //              Response to dojox/app "startTransition" event.
127                        //
128                        // example:
129                        //              Use "dojox/mobile/TransitionEvent" to trigger "startTransition" event, and this function will response the event. For example:
130                        //              |       var transOpts = {
131                        //              |               title:"List",
132                        //              |               target:"items,list",
133                        //              |               url: "#items,list",
134                        //              |               data: {}
135                        //              |       };
136                        //              |       new TransitionEvent(domNode, transOpts, e).dispatch();
137                        //
138                        // evt: Object
139                        //              transition options parameter
140
141                        // prevent event from bubbling to window and being
142                        // processed by dojox/mobile/ViewController
143                        if(evt.preventDefault){
144                                evt.preventDefault();
145                        }
146                        evt.cancelBubble = true;
147                        if(evt.stopPropagation){
148                                evt.stopPropagation();
149                        }
150
151                        var target = evt.detail.target;
152                        var regex = /#(.+)/;
153                        if(!target && regex.test(evt.detail.href)){
154                                target = evt.detail.href.match(regex)[1];
155                        }
156
157                        // transition to the target view
158                        this.transition({ "viewId":target, opts: lang.mixin({}, evt.detail), data: evt.detail.data });
159                },
160
161                _addTransitionEventToWaitingQueue: function(transitionEvt){
162                        if(transitionEvt.defaultView && this.waitingQueue.length > 0){ // need to test for defaultView to position this view correctly
163                                var addedEvt = false;
164                                for(var i = 0; i < this.waitingQueue.length; i++){
165                                        var evt = this.waitingQueue[i];
166                                        if(!evt.defaultView){
167                                                this.waitingQueue.splice(i,0,transitionEvt); // insert before first non defaultView
168                                                addedEvt = true;
169                                                break;
170                                        }
171                                }
172                                if(!addedEvt){
173                                        this.waitingQueue.push(transitionEvt);
174                                }
175                        }else{
176                                this.waitingQueue.push(transitionEvt);
177                        }
178                },
179                proceedTransition: function(transitionEvt){
180                        // summary:
181                        //              Proceed transition queue by FIFO by default.
182                        //              If transition is in proceeding, add the next transition to waiting queue.
183                        //
184                        // transitionEvt: Object
185                        //              "app-transition" event parameter. It should be like: {"viewId":viewId, "opts":opts}
186                        var F = MODULE+":proceedTransition";
187
188                        if(this.proceeding){
189                                this._addTransitionEventToWaitingQueue(transitionEvt);
190                                this.app.log(F+" added this event to waitingQueue", transitionEvt);
191                                this.processingQueue = false;
192                                return;
193                        }
194                        // If there are events waiting, needed to have the last in be the last processed, so add it to waitingQueue
195                        // process the events in order.
196                        this.app.log(F+" this.waitingQueue.length ="+ this.waitingQueue.length+ " this.processingQueue="+this.processingQueue);
197                        if(this.waitingQueue.length > 0 && !this.processingQueue){
198                                this.processingQueue = true;
199                                this._addTransitionEventToWaitingQueue(transitionEvt);
200                                this.app.log(F+" added this event to waitingQueue passed proceeding", transitionEvt);
201                                transitionEvt = this.waitingQueue.shift();
202                                this.app.log(F+" shifted waitingQueue to process", transitionEvt);
203                        }
204                       
205                        this.proceeding = true;
206
207                        this.app.log(F+" calling trigger load", transitionEvt);
208                        if(!transitionEvt.opts){
209                                transitionEvt.opts = {};
210                        }
211                        var params = transitionEvt.params || transitionEvt.opts.params;
212                        this.app.emit("app-load", {
213                                "viewId": transitionEvt.viewId,
214                                "params": params,
215                                "forceTransitionNone": transitionEvt.forceTransitionNone,
216                                "callback": lang.hitch(this, function(needToHandleDefaultView, defaultHasPlus){
217                                        if(needToHandleDefaultView){ // do not process this view if needToHandleDefaultView true
218                                                this.proceeding = false;
219                                                this.processingQueue = true;
220                                                // use pop instead of shift here to get the last event for the defaultView when the default does not have a +
221                                                // use shift when it has a + or the defaults will be out of order but it can move the default to be after other views if we are processing views with a +
222                                                var nextEvt = (defaultHasPlus) ? this.waitingQueue.shift() : this.waitingQueue.pop();
223                                                if(nextEvt){
224                                                        this.proceedTransition(nextEvt);
225                                                }
226                                        }else{
227                                                var transitionDef = this._doTransition(transitionEvt.viewId, transitionEvt.opts, params, transitionEvt.opts.data, this.app, transitionEvt._removeView, transitionEvt._doResize, transitionEvt.forceTransitionNone);
228                                                when(transitionDef, lang.hitch(this, function(){
229                                                        this.proceeding = false;
230                                                        this.processingQueue = true;
231                                                        var nextEvt = this.waitingQueue.shift();
232                                                        if(nextEvt){
233                                                                this.proceedTransition(nextEvt);
234                                                        }
235                                                }));
236                                        }
237                                })
238                        });
239                },
240
241                _getTransition: function(nextView, parent, transitionTo, opts, forceTransitionNone){
242                        // summary:
243                        //              Get view's transition type from the config for the view or from the parent view recursively.
244                        //              If not available use the transition option otherwise get view default transition type in the
245                        //              config from parent view.
246                        //
247                        // parent: Object
248                        //              view's parent
249                        // transitionTo: Object
250                        //              view to transition to
251                        //      opts: Object
252                        //              transition options
253                        // forceTransitionNone: boolean
254                        //              true if the transition type should be forced to none, used for the initial defaultView
255                        //
256                        // returns:
257                        //              transition type like "slide", "fade", "flip" or "none".
258                        if(forceTransitionNone){
259                                return "none";
260                        }
261                        var parentView = parent;
262                        var transition = null;
263                        if(nextView){
264                                transition = nextView.transition;
265                        }
266                        if(!transition && parentView.views[transitionTo]){
267                                transition = parentView.views[transitionTo].transition;
268                        }
269                        if(!transition){
270                                transition = parentView.transition;
271                        }
272                        var defaultTransition = (nextView && nextView.defaultTransition) ?  nextView.defaultTransition : parentView.defaultTransition;
273                        while(!transition && parentView.parent){
274                                parentView = parentView.parent;
275                                transition = parentView.transition;
276                                if(!defaultTransition){
277                                        defaultTransition = parentView.defaultTransition;
278                                }
279                        }
280                        return transition || opts.transition || defaultTransition || "none";
281                },
282
283
284                _getParamsForView: function(view, params){
285                        // summary:
286                        //              Get view's params only include view specific params if they are for this view.
287                        //
288                        // view: String
289                        //              the view's name
290                        // params: Object
291                        //              the params
292                        //
293                        // returns:
294                        //              params Object for this view
295                        var viewParams = {};
296                        for(var item in params){
297                                var value = params[item];
298                                if(lang.isObject(value)){       // view specific params
299                                        if(item == view){               // it is for this view
300                                                // need to add these params for the view
301                                                viewParams = lang.mixin(viewParams, value);
302                                        }
303                                }else{  // these params are for all views, so add them
304                                        if(item && value != null){
305                                                viewParams[item] = params[item];
306                                        }
307                                }
308                        }
309                        return viewParams;
310                },
311
312                _doTransition: function(transitionTo, opts, params, data, parent, removeView, doResize, forceTransitionNone, nested){
313                        // summary:
314                        //              Transitions from the currently visible view to the defined view.
315                        //              It should determine what would be the best transition unless
316                        //              an override in opts tells it to use a specific transitioning methodology
317                        //              the transitionTo is a string in the form of [view1,view2].
318                        //
319                        // transitionTo: Object
320                        //              transition to view id. It looks like #tabView,tab1
321                        // opts: Object
322                        //              transition options
323                        // params: Object
324                        //              params
325                        // data: Object
326                        //              data object that will be passed on activate & de-activate methods of the view
327                        // parent: Object
328                        //              view's parent
329                        // removeView: Boolean
330                        //              remove the view instead of transition to it
331                        // doResize: Boolean
332                        //              emit a resize event
333                        // forceTransitionNone: Boolean
334                        //              force the transition type to be none, used for the initial default view
335                        // nested: Boolean
336                        //              whether the method is called from the transitioning of a parent view
337                        //
338                        // returns:
339                        //              transit dojo/promise/all object.
340                        var F = MODULE+":_doTransition";
341
342                        if(!parent){
343                                throw Error("view parent not found in transition.");
344                        }
345
346                        this.app.log(F+" transitionTo=[",transitionTo,"], removeView=[",removeView,"] parent.name=[",parent.name,"], opts=",opts);
347
348                        var parts, toId, subIds, next;
349                        if(transitionTo){
350                                parts = transitionTo.split(",");
351                        }else{
352                                // If parent.defaultView is like "main,main", we also need to split it and set the value to toId and subIds.
353                                // Or cannot get the next view by "parent.children[parent.id + '_' + toId]"
354                                parts = parent.defaultView.split(",");
355                        }
356                        toId = parts.shift();
357                        subIds = parts.join(',');
358
359                        // next is loaded and ready for transition
360                        next = parent.children[parent.id + '_' + toId];
361                        if(!next){
362                                if(removeView){
363                                        this.app.log(F+" called with removeView true, but that view is not available to remove");
364                                        return; // trying to remove a view which is not showing
365                                }
366                                throw Error("child view must be loaded before transition.");
367                        }
368                        // if no subIds and next has default view,
369                        // set the subIds to the default view and transition to default view.
370                        if(!subIds && next.defaultView){
371                                subIds = next.defaultView;
372                        }
373
374                        var nextSubViewArray = [next || parent];
375                        if(subIds){
376                                nextSubViewArray = this._getNextSubViewArray(subIds, next, parent);
377                        }
378
379                        var current = constraints.getSelectedChild(parent, next.constraint);
380                        var currentSubViewArray = this._getCurrentSubViewArray(parent, nextSubViewArray, removeView);
381
382                        var currentSubNames = this._getCurrentSubViewNamesArray(currentSubViewArray);
383
384                        // set params on next view.
385                        next.params = this._getParamsForView(next.name, params);
386
387                        if(removeView){
388                                if(next !== current){ // nothing to remove
389                                        this.app.log(F+" called with removeView true, but that view is not available to remove");
390                                        return; // trying to remove a view which is not showing
391                                }       
392                                this.app.log(LOGKEY,F,"Transition Remove current From=["+currentSubNames+"]");
393                                // if next == current we will set next to null and remove the view with out a replacement
394                                next = null;
395                        }
396
397                        // get the list of nextSubNames, this is next.name followed by the subIds
398                        var nextSubNames = "";
399                        if(next){
400                                nextSubNames = next.name;
401                                if(subIds){
402                                        nextSubNames = nextSubNames+","+subIds;
403                                }
404                        }
405
406                        if(nextSubNames == currentSubNames && next == current){ // new test to see if current matches next
407                                this.app.log(LOGKEY,F,"Transition current and next DO MATCH From=["+currentSubNames+"] TO=["+nextSubNames+"]");
408                                this._handleMatchingViews(nextSubViewArray, next, current, parent, data, removeView, doResize, subIds, currentSubNames, toId, forceTransitionNone, opts);
409
410                        }else{
411                                this.app.log(LOGKEY,F,"Transition current and next DO NOT MATCH From=["+currentSubNames+"] TO=["+nextSubNames+"]");
412                                //When clicking fast, history module will cache the transition request que
413                                //and prevent the transition conflicts.
414                                //Originally when we conduct transition, selectedChild will not be the
415                                //view we want to start transition. For example, during transition 1 -> 2
416                                //if user click button to transition to 3 and then transition to 1. After
417                                //1->2 completes, it will perform transition 2 -> 3 and 2 -> 1 because
418                                //selectedChild is always point to 2 during 1 -> 2 transition and transition
419                                //will record 2->3 and 2->1 right after the button is clicked.
420
421                                //assume next is already loaded so that this.set(...) will not return
422                                //a promise object. this.set(...) will handles the this.selectedChild,
423                                //activate or deactivate views and refresh layout.
424
425                                //necessary, to avoid a flash when the layout sets display before resize
426                                if(!removeView && next){
427                                        var nextLastSubChild = this.nextLastSubChildMatch || next;
428                                        var startHiding = false; // only hide views which will transition in
429                                        for(var i = nextSubViewArray.length-1; i >= 0; i--){
430                                                var v = nextSubViewArray[i];
431                                                if(startHiding || v.id == nextLastSubChild.id){
432                                                        startHiding = true;
433                                                        if(!v._needsResize && v.domNode){
434                                                                this.app.log(LOGKEY,F," setting domStyle visibility hidden for v.id=["+v.id+"], display=["+v.domNode.style.display+"], visibility=["+v.domNode.style.visibility+"]");
435                                                                this._setViewVisible(v, false);
436                                                        }
437                                                }
438                                        }
439                                }
440
441                                if(current && current._active){
442                                        this._handleBeforeDeactivateCalls(currentSubViewArray, this.nextLastSubChildMatch || next, current, data, subIds);
443                                }
444                                if(next){
445                                        this.app.log(F+" calling _handleBeforeActivateCalls next name=[",next.name,"], parent.name=[",next.parent.name,"]");
446                                        this._handleBeforeActivateCalls(nextSubViewArray, this.currentLastSubChildMatch || current, data, subIds);
447                                }
448                                if(!removeView){
449                                        var nextLastSubChild = this.nextLastSubChildMatch || next;
450                                        var trans = this._getTransition(nextLastSubChild, parent, toId, opts, forceTransitionNone)
451                                        this.app.log(F+" calling _handleLayoutAndResizeCalls trans="+trans);
452                                        this._handleLayoutAndResizeCalls(nextSubViewArray, removeView, doResize, subIds, forceTransitionNone, trans);
453                                }else{
454                                        // for removeView need to set visible before transition do it here
455                                        for(var i = 0; i < nextSubViewArray.length; i++){
456                                                var v = nextSubViewArray[i];
457                                                this.app.log(LOGKEY,F,"setting visibility visible for v.id=["+v.id+"]");
458                                                if(v.domNode){
459                                                        this.app.log(LOGKEY,F,"  setting domStyle for removeView visibility visible for v.id=["+v.id+"], display=["+v.domNode.style.display+"]");
460                                                        this._setViewVisible(v, true);
461                                                }
462                                        }
463                                }
464                                var result = true;
465
466                                // this.currentLastSubChildMatch holds the view to transition from
467                                if(transit && (!nested || this.currentLastSubChildMatch != null) && this.currentLastSubChildMatch !== next){
468                                        // css3 transit has the check for IE so it will not try to do it on ie, so we do not need to check it here.
469                                        // We skip in we are transitioning to a nested view from a parent view and that nested view
470                                        // did not have any current
471                                        result = this._handleTransit(next, parent, this.currentLastSubChildMatch, opts, toId, removeView, forceTransitionNone, doResize);
472                                }
473                                when(result, lang.hitch(this, function(){
474                                        if(next){
475                                                this.app.log(F+" back from transit for next ="+next.name);
476                                        }
477                                        if(removeView){
478                                                var nextLastSubChild = this.nextLastSubChildMatch || next;
479                                                var trans = this._getTransition(nextLastSubChild, parent, toId, opts, forceTransitionNone)
480                                                this._handleLayoutAndResizeCalls(nextSubViewArray, removeView, doResize, subIds, forceTransitionNone, trans);
481                                        }
482
483                                        // Add call to handleAfterDeactivate and handleAfterActivate here!
484                                        this._handleAfterDeactivateCalls(currentSubViewArray, this.nextLastSubChildMatch || next, current, data, subIds);
485                                        this._handleAfterActivateCalls(nextSubViewArray, removeView, this.currentLastSubChildMatch || current, data, subIds);
486                                }));
487                                return result; // dojo/promise/all
488                        }
489                },
490
491                _handleMatchingViews: function(subs, next, current, parent, data, removeView, doResize, subIds, currentSubNames, toId, forceTransitionNone, opts){
492                        // summary:
493                        //              Called when the current views and the next views match
494                        var F = MODULE+":_handleMatchingViews";
495
496                        this._handleBeforeDeactivateCalls(subs, this.nextLastSubChildMatch || next, current, data, subIds);
497                        // this is the order that things were being done before on a reload of the same views, so I left it
498                        // calling _handleAfterDeactivateCalls here instead of after _handleLayoutAndResizeCalls
499                        this._handleAfterDeactivateCalls(subs, this.nextLastSubChildMatch || next, current, data, subIds);
500                        this._handleBeforeActivateCalls(subs, this.currentLastSubChildMatch || current, data, subIds);
501                        var nextLastSubChild = this.nextLastSubChildMatch || next;
502                        var trans = this._getTransition(nextLastSubChild, parent, toId, opts, forceTransitionNone)
503                        this._handleLayoutAndResizeCalls(subs, removeView, doResize, subIds, trans);
504                        this._handleAfterActivateCalls(subs, removeView, this.currentLastSubChildMatch || current, data, subIds);
505                },
506
507                _handleBeforeDeactivateCalls: function(subs, next, current, /*parent,*/ data, /*removeView, doResize,*/ subIds/*, currentSubNames*/){
508                        // summary:
509                        //              Call beforeDeactivate for each of the current views which are about to be deactivated
510                        var F = MODULE+":_handleBeforeDeactivateCalls";
511                        if(current._active){
512                                //now we need to loop backwards thru subs calling beforeDeactivate
513                                for(var i = subs.length-1; i >= 0; i--){
514                                        var v = subs[i];
515                                        if(v && v.beforeDeactivate && v._active){
516                                                this.app.log(LOGKEY,F,"beforeDeactivate for v.id="+v.id);
517                                                v.beforeDeactivate(next, data);
518                                        }
519                                }
520                        }
521                },
522
523                _handleAfterDeactivateCalls: function(subs, next, current, data, subIds){
524                        // summary:
525                        //              Call afterDeactivate for each of the current views which have been deactivated
526                        var F = MODULE+":_handleAfterDeactivateCalls";
527                        if(current && current._active){
528                                //now we need to loop forwards thru subs calling afterDeactivate
529                                for(var i = 0; i < subs.length; i++){
530                                        var v = subs[i];
531                                        if(v && v.beforeDeactivate && v._active){
532                                                this.app.log(LOGKEY,F,"afterDeactivate for v.id="+v.id);
533                                                v.afterDeactivate(next, data);
534                                                v._active = false;
535                                        }
536                                }
537
538                        }
539                },
540
541                _handleBeforeActivateCalls: function(subs, current, data, subIds){
542                        // summary:
543                        //              Call beforeActivate for each of the next views about to be activated
544                        var F = MODULE+":_handleBeforeActivateCalls";
545                        //now we need to loop backwards thru subs calling beforeActivate (ok since next matches current)
546                        for(var i = subs.length-1; i >= 0; i--){
547                                var v = subs[i];
548                                this.app.log(LOGKEY,F,"beforeActivate for v.id="+v.id);
549                                v.beforeActivate(current, data);
550                        }
551                },
552
553                _handleLayoutAndResizeCalls: function(subs, removeView, doResize, subIds, forceTransitionNone, transition){
554                        // summary:
555                        //              fire app-layoutView for each of the next views about to be activated, and fire app-resize if doResize is true
556                        var F = MODULE+":_handleLayoutAndResizeCalls";
557                        var remove = removeView;
558                        for(var i = 0; i < subs.length; i++){
559                                var v = subs[i];
560                                this.app.log(LOGKEY,F,"emit layoutView v.id=["+v.id+"] removeView=["+remove+"]");
561                                // it seems like we should be able to minimize calls to resize by passing doResize: false and only doing resize on the app-resize emit
562                                this.app.emit("app-layoutView", {"parent": v.parent, "view": v, "removeView": remove, "doResize": false, "transition": transition, "currentLastSubChildMatch": this.currentLastSubChildMatch});
563                                remove = false;
564                        }
565                        if(doResize){
566                                this.app.log(LOGKEY,F,"emit doResize called");
567                                this.app.emit("app-resize"); // after last layoutView fire app-resize
568                                if(transition == "none"){
569                                        this._showSelectedChildren(this.app); // Need to set visible too before transition do it now.
570                                }
571                        }
572
573                },
574
575                _showSelectedChildren: function(w){
576                        var F = MODULE+":_showSelectedChildren";
577                        this.app.log(LOGKEY,F," setting domStyle visibility visible for w.id=["+w.id+"], display=["+w.domNode.style.display+"], visibility=["+w.domNode.style.visibility+"]");
578                        this._setViewVisible(w, true);
579                        w._needsResize = false;
580                        for(var hash in w.selectedChildren){    // need this to handle all selectedChildren
581                                if(w.selectedChildren[hash] && w.selectedChildren[hash].domNode){
582                                        this.app.log(LOGKEY,F," calling _showSelectedChildren for w.selectedChildren[hash].id="+w.selectedChildren[hash].id);
583                                        this._showSelectedChildren(w.selectedChildren[hash]);
584                                }
585                        }
586                },
587
588                _setViewVisible: function(v, visible){
589                        if(visible){
590                                domStyle.set(v.domNode, "visibility", "visible");
591                        }else{
592                                domStyle.set(v.domNode, "visibility", "hidden");
593                        }
594                },
595
596
597                _handleAfterActivateCalls: function(subs, removeView, current, data, subIds){
598                        // summary:
599                        //              Call afterActivate for each of the next views which have been activated
600                        var F = MODULE+":_handleAfterActivateCalls";
601                        //now we need to loop backwards thru subs calling beforeActivate (ok since next matches current)
602                        var startInt = 0;
603                        if(removeView && subs.length > 1){
604                                startInt = 1;
605                        }
606                        for(var i = startInt; i < subs.length; i++){
607                                var v = subs[i];
608                                if(v.afterActivate){
609                                        this.app.log(LOGKEY,F,"afterActivate for v.id="+v.id);
610                                        v.afterActivate(current, data);
611                                        v._active = true;
612                                }
613                        }
614                },
615
616                _getNextSubViewArray: function(subIds, next, parent){
617                        // summary:
618                        //              Get next sub view array, this array will hold the views which are about to be transitioned to
619                        //
620                        // subIds: String
621                        //              the subids, the views are separated with a comma
622                        // next: Object
623                        //              the next view to be transitioned to.
624                        // parent: Object
625                        //              the parent view used in place of next if next is not set.
626                        //
627                        // returns:
628                        //              Array of views which will be transitioned to during this transition
629                        var F = MODULE+":_getNextSubViewArray";
630                        var parts = [];
631                        var p = next || parent;
632                        if(subIds){
633                                parts = subIds.split(",");
634                        }
635                        var nextSubViewArray = [p];
636                        //now we need to loop forwards thru subIds calling beforeActivate
637                        for(var i = 0; i < parts.length; i++){
638                                toId = parts[i];
639                                var v = p.children[p.id + '_' + toId];
640                                if(v){
641                                        nextSubViewArray.push(v);
642                                        p = v;
643                                }
644                        }
645                        nextSubViewArray.reverse();
646                        return nextSubViewArray;
647                },
648
649                _getCurrentSubViewArray: function(parent, nextSubViewArray, removeView){
650                        // summary:
651                        //              Get current sub view array which will be replaced by the views in the nextSubViewArray
652                        //
653                        // parent: String
654                        //              the parent view whose selected children will be replaced
655                        // nextSubViewArray: Array
656                        //              the array of views which are to be transitioned to.
657                        //
658                        // returns:
659                        //              Array of views which will be deactivated during this transition
660                        var F = MODULE+":_getCurrentSubViewArray";
661                        var currentSubViewArray = [];
662                        var constraint, type, hash;
663                        var p = parent;
664                        this.currentLastSubChildMatch = null;
665                        this.nextLastSubChildMatch = null;
666
667                        for(var i = nextSubViewArray.length-1; i >= 0; i--){
668                                constraint = nextSubViewArray[i].constraint;
669                                type = typeof(constraint);
670                                hash = (type == "string" || type == "number") ? constraint : constraint.__hash;
671                                // if there is a selected child for this constraint, and the child matches this view, push it.
672                                if(p && p.selectedChildren && p.selectedChildren[hash]){
673                                        if(p.selectedChildren[hash] == nextSubViewArray[i]){
674                                                this.currentLastSubChildMatch = p.selectedChildren[hash];
675                                                this.nextLastSubChildMatch = nextSubViewArray[i];
676                                                currentSubViewArray.push(this.currentLastSubChildMatch);
677                                                p = this.currentLastSubChildMatch;
678                                        }else{
679                                                this.currentLastSubChildMatch = p.selectedChildren[hash];
680                                                currentSubViewArray.push(this.currentLastSubChildMatch);
681                                                this.nextLastSubChildMatch = nextSubViewArray[i]; // setting this means the transition will be done to the child instead of the parent
682                                                // since the constraint was set, but it did not match, need to deactivate all selected children of this.currentLastSubChildMatch
683                                                if(!removeView){
684                                                        var selChildren = constraints.getAllSelectedChildren(this.currentLastSubChildMatch);
685                                                        currentSubViewArray = currentSubViewArray.concat(selChildren);
686                                                }
687                                                break;
688                                        }
689                                }else{ // the else is for the constraint not matching which means no more to deactivate.
690                                        this.currentLastSubChildMatch = null; // there was no view selected for this constraint
691                                        this.nextLastSubChildMatch = nextSubViewArray[i]; // set this to the next view for transition to an empty constraint
692                                        break;
693                                }
694
695                        }
696                        // Here since they had the constraint but it was not the same I need to deactivate all children of p
697                        if(removeView){
698                                var selChildren = constraints.getAllSelectedChildren(p);
699                                currentSubViewArray = currentSubViewArray.concat(selChildren);
700                        }
701
702                        return currentSubViewArray;
703                },
704
705                _getCurrentSubViewNamesArray: function(currentSubViewArray){
706                        // summary:
707                        //              Get current sub view names array, the names of the views which will be transitioned from
708                        //
709                        // currentSubViewArray: Array
710                        //              the array of views which are to be transitioned from.
711                        //
712                        // returns:
713                        //              Array of views which will be deactivated during this transition
714                        var F = MODULE+":_getCurrentSubViewNamesArray";
715                        var currentSubViewNamesArray = [];
716                        for(var i = 0; i < currentSubViewArray.length; i++){
717                                currentSubViewNamesArray.push(currentSubViewArray[i].name);
718                        }
719                        return currentSubViewNamesArray;
720                },
721
722                _handleTransit: function(next, parent, currentLastSubChild, opts, toId, removeView, forceTransitionNone, resizeDone){
723                        // summary:
724                        //              Setup the options and call transit to do the transition
725                        //
726                        // next: Object
727                        //              the next view, the view which will be transitioned to
728                        // parent: Object
729                        //              the parent view which is used to get the transition type to be used
730                        // currentLastSubChild: Object
731                        //              the current view which is being transitioned away from
732                        // opts: Object
733                        //              the options used for the transition
734                        // toId: String
735                        //              the id of the view being transitioned to
736                        // removeView: boolean
737                        //              true if the view is being removed
738                        // forceTransitionNone: boolean
739                        //              true if the transition type should be forced to none, used for the initial defaultView
740                        // resizeDone: boolean
741                        //              true if resize was called before this transition
742                        //
743                        // returns:
744                        //              the promise returned by the call to transit
745                        var F = MODULE+":_handleTransit";
746
747                        var nextLastSubChild = this.nextLastSubChildMatch || next;
748
749                        var mergedOpts = lang.mixin({}, opts); // handle reverse from mergedOpts or transitionDir
750                        mergedOpts = lang.mixin({}, mergedOpts, {
751                                reverse: (mergedOpts.reverse || mergedOpts.transitionDir === -1)?true:false,
752                                // if transition is set for the view (or parent) in the config use it, otherwise use it from the event or defaultTransition from the config
753                                transition: this._getTransition(nextLastSubChild, parent, toId, mergedOpts, forceTransitionNone)
754                        });
755
756                        if(removeView){
757                                nextLastSubChild = null;
758                        }
759                        if(currentLastSubChild){
760                                this.app.log(LOGKEY,F,"transit FROM currentLastSubChild.id=["+currentLastSubChild.id+"]");
761                        }
762                        if(nextLastSubChild){
763                                if(mergedOpts.transition !== "none"){
764                                        if(!resizeDone && nextLastSubChild._needsResize){ // need to resize if not done yet or things will not be positioned correctly
765                                                this.app.log(LOGKEY,F,"emit doResize called from _handleTransit");
766                                                this.app.emit("app-resize"); // after last layoutView fire app-resize
767                                        }
768                                        this.app.log(LOGKEY,F,"  calling _showSelectedChildren for w3.id=["+nextLastSubChild.id+"], display=["+nextLastSubChild.domNode.style.display+"], visibility=["+nextLastSubChild.domNode.style.visibility+"]");
769                                        this._showSelectedChildren(this.app); // Need to set visible too before transition do it now.
770                                }
771                                this.app.log(LOGKEY,F,"transit TO nextLastSubChild.id=["+nextLastSubChild.id+"] transition=["+mergedOpts.transition+"]");
772                        }else{
773                                this._showSelectedChildren(this.app); // Need to set visible too before transition do it now.
774                        }
775                        return transit(currentLastSubChild && currentLastSubChild.domNode, nextLastSubChild && nextLastSubChild.domNode, mergedOpts);
776                }
777
778        });
779});
Note: See TracBrowser for help on using the repository browser.