Created
October 18, 2013 16:15
-
-
Save edchat/7043914 to your computer and use it in GitHub Desktop.
Custom dojox/app loader to always load the default child views for a view the first time the view is loaded. The name of the custom loader is CustomLoaderDefaults.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define(["require", "dojo/_base/lang", "dojo/_base/declare", "dojo/on", "dojo/Deferred", "dojo/when", "dojo/dom-style", "dojox/app/controllers/Load"], | |
function(require, lang, declare, on, Deferred, when, domStyle, Controller, View){ | |
// module: | |
// dojox/app/tests/nestedTestApp/controllers/CustomLoaderDefaults | |
// summary: | |
// A custom logger to handle always loading the defaultViews when a view is loaded for the first time. | |
// Bind "app-load" event on dojox/app application instance. | |
// Load child view and sub children at one time. | |
// | |
// | |
return declare(Controller, { | |
_waitingQueue:[], | |
constructor: function(app, events){ | |
// summary: | |
// bind "app-load" event on application instance. | |
// | |
// app: | |
// dojox/app application instance. | |
// events: | |
// {event : handler} | |
this.events = { | |
"app-init": this.init, | |
"app-load": this.load | |
}; | |
}, | |
init: function(event){ | |
// when the load controller received "app-init", before the lifecycle really starts we create the root view | |
// if any. This used to be done in main.js but must be done in Load to be able to create custom | |
// views from the Load controller. | |
//create and start child. return Deferred | |
when(this.createView(event.parent, null, null, { | |
templateString: event.templateString, | |
controller: event.controller | |
}, null, event.type), function(newView){ | |
when(newView.start(), event.callback); | |
}); | |
}, | |
load: function(event){ | |
// summary: | |
// Response to dojox/app "loadArray" event. | |
// | |
// example: | |
// Use trigger() to trigger "loadArray" event, and this function will response the event. For example: | |
// | this.trigger("app-load", {"parent":parent, "viewId":viewId, "viewArray":viewArray, "callback":function(){...}}); | |
// | |
// event: Object | |
// LoadArray event parameter. It should be like this: {"parent":parent, "viewId":viewId, "viewArray":viewArray, "callback":function(){...}} | |
// returns: | |
// A dojo/Deferred object. | |
// The return value cannot return directly. | |
// If the caller need to use the return value, pass callback function in event parameter and process return value in callback function. | |
this.app.log("in app/controllers/Load event.viewId="+event.viewId+" event =", event); | |
var views = event.viewId || ""; | |
var viewArray = []; | |
// create an array from the diff views in event.viewId (they are separated by +) | |
var parts = views.split('+'); | |
while(parts.length > 0){ | |
var viewId = parts.shift(); | |
viewArray.push(viewId); | |
} | |
var def; | |
this.proceedLoadViewDef = new Deferred(); | |
if(viewArray && viewArray.length > 1){ | |
// loop thru the array calling loadView for each item in the array | |
for(var i = 0; i < viewArray.length-1; i++){ | |
var newEvent = lang.clone(event); | |
newEvent.callback = null; // skip callback until after last view is loaded. | |
newEvent.viewId = viewArray[i]; | |
this._waitingQueue.push(newEvent); | |
} | |
this.proceedLoadView(this._waitingQueue.shift()); | |
when(this.proceedLoadViewDef, lang.hitch(this, function(){ | |
// for last view leave the callback to be notified | |
var newEvent = lang.clone(event); | |
newEvent.viewId = viewArray[i]; | |
def = this.loadView(newEvent); | |
return def; | |
})); | |
}else{ | |
def = this.loadView(event); | |
return def; | |
} | |
}, | |
proceedLoadView: function(loadEvt){ | |
// summary: | |
// Proceed load queue by FIFO by default. | |
// If load is in proceeding, add the next load to waiting queue. | |
// | |
// loadEvt: Object | |
// LoadArray event parameter. It should be like this: {"parent":parent, "viewId":viewId, "viewArray":viewArray, "callback":function(){...}} | |
var def = this.loadView(loadEvt); | |
when(def, lang.hitch(this, function(){ | |
this.app.log("in app/controllers/Load proceedLoadView back from loadView for event", loadEvt); | |
var nextEvt = this._waitingQueue.shift(); | |
if(nextEvt){ | |
this.app.log("in app/controllers/Load proceedLoadView back from loadView calling this.proceedLoadView(nextEvt) for ",nextEvt); | |
this.proceedLoadView(nextEvt); | |
}else{ | |
this._waitingQueue = []; | |
this.proceedLoadViewDef.resolve(); | |
} | |
})); | |
}, | |
loadView: function(loadEvent){ | |
// summary: | |
// Response to dojox/app "app-load" event. | |
// | |
// example: | |
// Use trigger() to trigger "app-load" event, and this function will response the event. For example: | |
// | this.trigger("app-load", {"parent":parent, "viewId":viewId, "callback":function(){...}}); | |
// | |
// loadEvent: Object | |
// Load event parameter. It should be like this: {"parent":parent, "viewId":viewId, "callback":function(){...}} | |
// returns: | |
// A dojo/Deferred object. | |
// The return value cannot return directly. | |
// If the caller need to use the return value, pass callback function in event parameter and process return value in callback function. | |
var parent = loadEvent.parent || this.app; | |
var viewId = loadEvent.viewId || ""; | |
var parts = viewId.split(','); | |
var childId = parts.shift(); | |
var subIds = parts.join(","); | |
var params = loadEvent.params || ""; | |
this._handleDefault = false; | |
this._defaultHasPlus = false; | |
var def = this.loadChild(parent, childId, subIds, params, loadEvent); | |
// call Load event callback | |
if(loadEvent.callback){ | |
when(def, lang.hitch(this, function(){ | |
if(this._handleDefault && !loadEvent.initLoad){ | |
this.app.log("logTransitions:",""," emit app-transition this.childViews=["+this.childViews+"]"); | |
this.app.emit("app-transition", { | |
viewId: this.childViews, | |
defaultView: true, | |
forceTransitionNone: loadEvent.forceTransitionNone, | |
opts: { params: params } | |
}); | |
} | |
loadEvent.callback(this._handleDefault, this._defaultHasPlus); | |
})) | |
} | |
return def; | |
}, | |
createChild: function(parent, childId, subIds, params){ | |
// summary: | |
// Create a view instance if not already loaded by calling createView. This is typically a | |
// dojox/app/View. | |
// | |
// parent: Object | |
// parent of the view. | |
// childId: String | |
// view id need to be loaded. | |
// subIds: String | |
// sub views' id of this view. | |
// returns: | |
// If view exist, return the view object. | |
// Otherwise, create the view and return a dojo.Deferred instance. | |
var id = parent.id + '_' + childId; | |
this.viewPreviouslyCreated = false; | |
// check for possible default params if no params were provided | |
if(!params && parent.views[childId] && parent.views[childId].defaultParams){ | |
params = parent.views[childId].defaultParams; | |
} | |
var view = parent.children[id]; | |
if(view){ | |
// set params to new value before returning | |
if(params){ | |
view.params = params; | |
} | |
this.app.log("in app/controllers/Load createChild view is already loaded so return the loaded view with the new parms ",view); | |
this.viewPreviouslyCreated = true; | |
return view; | |
} | |
var def = new Deferred(); | |
// create and start child. return Deferred | |
when(this.createView(parent, id, childId, null, params, parent.views[childId].type), function(newView){ | |
parent.children[id] = newView; | |
when(newView.start(), function(view){ | |
def.resolve(view); | |
}); | |
}); | |
return def; | |
}, | |
createView: function(parent, id, name, mixin, params, type){ | |
// summary: | |
// Create a dojox/app/View instance. Can be overridden to create different type of views. | |
// parent: Object | |
// parent of this view. | |
// id: String | |
// view id. | |
// name: String | |
// view name. | |
// mixin: String | |
// additional property to be mixed into the view (templateString, controller...) | |
// params: Object | |
// params of this view. | |
// type: String | |
// the MID of the View. If not provided "dojox/app/View". | |
// returns: | |
// A dojo/Deferred instance which will be resolved when the view will be instantiated. | |
// tags: | |
// protected | |
var def = new Deferred(); | |
var app = this.app; | |
require([type?type:"dojox/app/View"], function(View){ | |
var newView = new View(lang.mixin({ | |
"app": app, | |
"id": id, | |
"name": name, | |
"parent": parent | |
}, { "params": params }, mixin)); | |
def.resolve(newView); | |
}); | |
return def; | |
}, | |
loadChild: function(parent, childId, subIds, params, loadEvent){ | |
// summary: | |
// Load child and sub children views recursively. | |
// | |
// parent: Object | |
// parent of this view. | |
// childId: String | |
// view id need to be loaded. | |
// subIds: String | |
// sub views' id of this view. | |
// params: Object | |
// params of this view. | |
// loadEvent: Object | |
// the event passed for the load of this view. | |
// returns: | |
// A dojo/Deferred instance which will be resolved when all views loaded. | |
if(!parent){ | |
throw Error("No parent for Child '" + childId + "'."); | |
} | |
if(!childId){ | |
var parts = parent.defaultView ? parent.defaultView.split(",") : "default"; | |
if(parent.defaultView && !loadEvent.initLoad){ // in this case we need to call transfer to handle the defaultView calls to activate | |
var childViews = this._getViewNamesFromDefaults(parent); | |
this.app.log("logTransitions:","Load:loadChild","setting _handleDefault true for parent.defaultView childViews=["+childViews+"]"); | |
this._handleDefault = true; | |
if(parent.defaultView.indexOf("+") >= 0){ | |
this._defaultHasPlus = true; | |
} | |
}else{ | |
childId = parts.shift(); | |
subIds = parts.join(','); | |
} | |
} | |
var loadChildDeferred = new Deferred(); | |
var createPromise; | |
try{ | |
createPromise = this.createChild(parent, childId, subIds, params); | |
}catch(ex){ | |
console.warn("logTransitions:","","emit reject load exception for =["+childId+"]",ex); | |
loadChildDeferred.reject("load child '"+childId+"' error."); | |
return loadChildDeferred.promise; | |
} | |
when(createPromise, lang.hitch(this, function(child){ | |
// if no subIds and current view has default view, load the default view. | |
if(child.defaultView && (!subIds || !this.viewPreviouslyCreated)){ | |
var childViews = this._getViewNamesFromDefaults(child); | |
this.app.log("logTransitions:","Load:loadChild"," setting _handleDefault = true child.defaultView childViews=["+childViews+"]"); | |
this._handleDefault = true; | |
if(child.defaultView.indexOf("+") >= 0){ | |
this._defaultHasPlus = true; | |
} | |
this.childViews = childViews; | |
loadChildDeferred.resolve(); | |
} | |
var parts = subIds.split(','); | |
childId = parts.shift(); | |
subIds = parts.join(','); | |
if(childId){ | |
var subLoadDeferred = this.loadChild(child, childId, subIds, params, loadEvent); | |
when(subLoadDeferred, function(){ | |
loadChildDeferred.resolve(); | |
}, | |
function(){ | |
loadChildDeferred.reject("load child '"+childId+"' error."); | |
}); | |
}else{ | |
loadChildDeferred.resolve(); | |
} | |
}), | |
function(){ | |
console.warn("loadChildDeferred.REJECT() for ["+childId+"] subIds=["+subIds+"]"); | |
loadChildDeferred.reject("load child '"+childId+"' error.") | |
}); | |
return loadChildDeferred.promise; // dojo/Deferred.promise | |
}, | |
_getViewNamesFromDefaults: function(view){ | |
// summary: | |
// Build the full nested view name from the view and its defaultView(s) | |
// | |
// view: Object | |
// the view with defaultViews to process | |
// returns: | |
// A string with the full nested view names | |
var parent = view.parent; | |
var parentNames = view.name; | |
var viewNames = ""; | |
while(parent && parent !== this.app){ | |
parentNames = parent.name+","+parentNames; | |
parent = parent.parent; | |
} | |
var parts = view.defaultView.split('+'); | |
for(var item in parts){ | |
parts[item] = parentNames+","+parts[item]; | |
} | |
viewNames = parts.join('+'); | |
return viewNames; | |
} | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment