source: Dev/trunk/src/client/dojox/app/controllers/Load.js @ 529

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

Added Dojo 1.9.3 release.

  • Property svn:executable set to *
File size: 11.3 KB
Line 
1define(["require", "dojo/_base/lang", "dojo/_base/declare", "dojo/on", "dojo/Deferred", "dojo/when", "dojo/dom-style", "../Controller"],
2        function(require, lang, declare, on, Deferred, when, domStyle, Controller, View){
3        // module:
4        //              dojox/app/controllers/Load
5        // summary:
6        //              Bind "app-load" event on dojox/app application instance.
7        //              Load child view and sub children at one time.
8
9        return declare("dojox.app.controllers.Load", Controller, {
10
11
12                _waitingQueue:[],
13
14                constructor: function(app, events){
15                        // summary:
16                        //              bind "app-load" event on application instance.
17                        //
18                        // app:
19                        //              dojox/app application instance.
20                        // events:
21                        //              {event : handler}
22                        this.events = {
23                                "app-init": this.init,
24                                "app-load": this.load
25                        };
26                },
27
28                init: function(event){
29                        // when the load controller received "app-init", before the lifecycle really starts we create the root view
30                        // if any. This used to be done in main.js but must be done in Load to be able to create custom
31                        // views from the Load controller.
32                        //create and start child. return Deferred
33                        when(this.createView(event.parent, null, null, {
34                                        templateString: event.templateString,
35                                        controller: event.controller
36                        }, null, event.type), function(newView){
37                                when(newView.start(), event.callback);
38                        });
39                },
40
41                load: function(event){
42                        // summary:
43                        //              Response to dojox/app "loadArray" event.
44                        //
45                        // example:
46                        //              Use trigger() to trigger "loadArray" event, and this function will response the event. For example:
47                        //              |       this.trigger("app-load", {"parent":parent, "viewId":viewId, "viewArray":viewArray, "callback":function(){...}});
48                        //
49                        // event: Object
50                        //              LoadArray event parameter. It should be like this: {"parent":parent, "viewId":viewId, "viewArray":viewArray, "callback":function(){...}}
51                        // returns:
52                        //              A dojo/Deferred object.
53                        //              The return value cannot return directly.
54                        //              If the caller need to use the return value, pass callback function in event parameter and process return value in callback function.
55
56                        this.app.log("in app/controllers/Load event.viewId="+event.viewId+" event =", event);
57                        var views = event.viewId || "";
58                        var viewArray = [];
59                        // create an array from the diff views in event.viewId (they are separated by +)
60                        var parts = views.split('+');
61                        while(parts.length > 0){
62                                var viewId = parts.shift();
63                                viewArray.push(viewId);
64                        }
65
66                        var def;
67                        this.proceedLoadViewDef = new Deferred();
68                        if(viewArray && viewArray.length > 1){
69                                // loop thru the array calling loadView for each item in the array
70                                for(var i = 0; i < viewArray.length-1; i++){
71                                        var newEvent = lang.clone(event);
72                                        newEvent.callback = null;       // skip callback until after last view is loaded.
73                                        newEvent.viewId = viewArray[i];
74                                        this._waitingQueue.push(newEvent);
75                                }
76                                this.proceedLoadView(this._waitingQueue.shift());
77                                when(this.proceedLoadViewDef, lang.hitch(this, function(){
78                                        // for last view leave the callback to be notified
79                                        var newEvent = lang.clone(event);
80                                        newEvent.viewId = viewArray[i];
81                                        def = this.loadView(newEvent);
82                                        return def;
83                                }));
84                        }else{
85                                def = this.loadView(event);
86                                return def;
87                        }
88                },
89
90                proceedLoadView: function(loadEvt){
91                        // summary:
92                        //              Proceed load queue by FIFO by default.
93                        //              If load is in proceeding, add the next load to waiting queue.
94                        //
95                        // loadEvt: Object
96                        //              LoadArray event parameter. It should be like this: {"parent":parent, "viewId":viewId, "viewArray":viewArray, "callback":function(){...}}
97
98                        var def = this.loadView(loadEvt);
99                        when(def, lang.hitch(this, function(){
100                                                this.app.log("in app/controllers/Load proceedLoadView back from loadView for event", loadEvt);
101                                                var nextEvt = this._waitingQueue.shift();
102                                                if(nextEvt){
103                                                        this.app.log("in app/controllers/Load proceedLoadView back from loadView calling this.proceedLoadView(nextEvt) for ",nextEvt);
104                                                        this.proceedLoadView(nextEvt);
105                                                }else{
106                                                        this._waitingQueue = [];
107                                                        this.proceedLoadViewDef.resolve();
108                                                }
109                        }));
110                },
111
112                loadView: function(loadEvent){
113                        // summary:
114                        //              Response to dojox/app "app-load" event.
115                        //
116                        // example:
117                        //              Use trigger() to trigger "app-load" event, and this function will response the event. For example:
118                        //              |       this.trigger("app-load", {"parent":parent, "viewId":viewId, "callback":function(){...}});
119                        //
120                        // loadEvent: Object
121                        //              Load event parameter. It should be like this: {"parent":parent, "viewId":viewId, "callback":function(){...}}
122                        // returns:
123                        //              A dojo/Deferred object.
124                        //              The return value cannot return directly.
125                        //              If the caller need to use the return value, pass callback function in event parameter and process return value in callback function.
126
127                        var parent = loadEvent.parent || this.app;
128                        var viewId = loadEvent.viewId || "";
129                        var parts = viewId.split(',');
130                        var childId = parts.shift();
131                        var subIds = parts.join(",");
132                        var params = loadEvent.params || "";
133
134                        this._handleDefault = false;
135                        this._defaultHasPlus = false;
136                        var def = this.loadChild(parent, childId, subIds, params, loadEvent);
137                        // call Load event callback
138                        if(loadEvent.callback){
139                                when(def, lang.hitch(this, function(){
140                                        if(this._handleDefault  && !loadEvent.initLoad){
141                                                this.app.log("logTransitions:",""," emit app-transition this.childViews=["+this.childViews+"]");
142                                                this.app.emit("app-transition", {
143                                                        viewId: this.childViews,
144                                                        defaultView: true,
145                                                        forceTransitionNone: loadEvent.forceTransitionNone,
146                                                        opts: { params: params }
147                                                });
148                                        }
149                                        loadEvent.callback(this._handleDefault, this._defaultHasPlus);
150                                }))
151                        }
152                        return def;
153                },
154
155                createChild: function(parent, childId, subIds, params){
156                        // summary:
157                        //              Create a view instance if not already loaded by calling createView. This is typically a
158                        //              dojox/app/View.
159                        //
160                        // parent: Object
161                        //              parent of the view.
162                        // childId: String
163                        //              view id need to be loaded.
164                        // subIds: String
165                        //              sub views' id of this view.
166                        // returns:
167                        //              If view exist, return the view object.
168                        //              Otherwise, create the view and return a dojo.Deferred instance.
169
170                        var id = parent.id + '_' + childId;
171
172                        // check for possible default params if no params were provided
173                        if(!params && parent.views[childId] && parent.views[childId].defaultParams){
174                                params = parent.views[childId].defaultParams;
175                        }
176                        var view = parent.children[id];
177                        if(view){
178                                // set params to new value before returning
179                                if(params){
180                                        view.params = params;
181                                }
182                                this.app.log("in app/controllers/Load createChild view is already loaded so return the loaded view with the new parms ",view);
183                                return view;
184                        }
185                        var def = new Deferred();
186                        // create and start child. return Deferred
187                        when(this.createView(parent, id, childId, null, params, parent.views[childId].type), function(newView){
188                                parent.children[id] = newView;
189                                when(newView.start(), function(view){
190                                        def.resolve(view);
191                                });
192                        });
193                        return def;
194                },
195
196                createView: function(parent, id, name, mixin, params, type){
197                        // summary:
198                        //              Create a dojox/app/View instance. Can be overridden to create different type of views.
199                        // parent: Object
200                        //              parent of this view.
201                        // id: String
202                        //              view id.
203                        // name: String
204                        //              view name.
205                        // mixin: String
206                        //              additional property to be mixed into the view (templateString, controller...)
207                        // params: Object
208                        //              params of this view.
209                        // type: String
210                        //              the MID of the View. If not provided "dojox/app/View".
211                        // returns:
212                        //              A dojo/Deferred instance which will be resolved when the view will be instantiated.
213                        // tags:
214                        //              protected
215                        var def = new Deferred();
216                        var app = this.app;
217                        require([type?type:"../View"], function(View){
218                                var newView = new View(lang.mixin({
219                                        "app": app,
220                                        "id": id,
221                                        "name": name,
222                                        "parent": parent
223                                }, { "params": params }, mixin));
224                                def.resolve(newView);
225                        });
226                        return def;
227                },
228
229                loadChild: function(parent, childId, subIds, params, loadEvent){
230                        // summary:
231                        //              Load child and sub children views recursively.
232                        //
233                        // parent: Object
234                        //              parent of this view.
235                        // childId: String
236                        //              view id need to be loaded.
237                        // subIds: String
238                        //              sub views' id of this view.
239                        // params: Object
240                        //              params of this view.
241                        // loadEvent: Object
242                        //              the event passed for the load of this view.
243                        // returns:
244                        //              A dojo/Deferred instance which will be resolved when all views loaded.
245
246                        if(!parent){
247                                throw Error("No parent for Child '" + childId + "'.");
248                        }
249
250                        if(!childId){
251                                var parts = parent.defaultView ? parent.defaultView.split(",") : "default";
252                                if(parent.defaultView && !loadEvent.initLoad){ // in this case we need to call transfer to handle the defaultView calls to activate
253                                        var childViews = this._getViewNamesFromDefaults(parent);
254                                        this.app.log("logTransitions:","Load:loadChild","setting _handleDefault true for parent.defaultView childViews=["+childViews+"]");
255                                        this._handleDefault = true;
256                                        if(parent.defaultView.indexOf("+") >= 0){
257                                                this._defaultHasPlus = true;
258                                        }
259                                }else{
260                                        childId = parts.shift();
261                                        subIds = parts.join(',');
262                                }
263
264                        }
265
266                        var loadChildDeferred = new Deferred();
267                        var createPromise;
268                        try{
269                                createPromise = this.createChild(parent, childId, subIds, params);
270                        }catch(ex){
271                                console.warn("logTransitions:","","emit reject load exception for =["+childId+"]",ex);
272                                loadChildDeferred.reject("load child '"+childId+"' error.");
273                                return loadChildDeferred.promise;
274                        }
275                        when(createPromise, lang.hitch(this, function(child){
276                                // if no subIds and current view has default view, load the default view.
277                                if(!subIds && child.defaultView){ // in this case we need to call transfer to handle the defaultView activate
278                                        var childViews = this._getViewNamesFromDefaults(child);
279                                        this.app.log("logTransitions:","Load:loadChild"," setting _handleDefault = true child.defaultView childViews=["+childViews+"]");
280                                        this._handleDefault = true;
281                                        if(child.defaultView.indexOf("+") >= 0){
282                                                this._defaultHasPlus = true;
283                                        }
284                                        this.childViews = childViews;
285                                        loadChildDeferred.resolve();
286                                }
287
288                                var parts = subIds.split(',');
289                                childId = parts.shift();
290                                subIds = parts.join(',');
291                                if(childId){
292                                        var subLoadDeferred = this.loadChild(child, childId, subIds, params, loadEvent);
293                                        when(subLoadDeferred, function(){
294                                                loadChildDeferred.resolve();
295                                        },
296                                        function(){
297                                                loadChildDeferred.reject("load child '"+childId+"' error.");
298                                        });
299                                }else{
300                                        loadChildDeferred.resolve();
301                                }
302                        }),
303                        function(){
304                                console.warn("loadChildDeferred.REJECT() for ["+childId+"] subIds=["+subIds+"]");
305                                loadChildDeferred.reject("load child '"+childId+"' error.")
306                        });
307                        return loadChildDeferred.promise; // dojo/Deferred.promise
308                },
309
310                _getViewNamesFromDefaults: function(view){
311                        // summary:
312                        //              Build the full nested view name from the view and its defaultView(s)
313                        //
314                        // view: Object
315                        //              the view with defaultViews to process
316                        // returns:
317                        //              A string with the full nested view names
318                        var parent = view.parent;
319                        var parentNames = view.name;
320                        var viewNames = "";
321                        while(parent !== this.app){
322                                parentNames = parent.name+","+parentNames;
323                                parent = parent.parent;
324                        }
325                        var parts = view.defaultView.split('+');
326                        for(var item in parts){
327                                parts[item] = parentNames+","+parts[item];
328                        }
329                        viewNames = parts.join('+');
330                        return viewNames;
331                }
332        });
333});
Note: See TracBrowser for help on using the repository browser.