123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- define("dojox/mobile/ViewController", [
- "dojo/_base/kernel",
- "dojo/_base/array",
- "dojo/_base/connect",
- "dojo/_base/declare",
- "dojo/_base/lang",
- "dojo/_base/window",
- "dojo/dom",
- "dojo/dom-class",
- "dojo/dom-construct",
- // "dojo/hash", // optionally prereq'ed
- "dojo/on",
- "dojo/ready",
- "dijit/registry", // registry.byId
- "./ProgressIndicator",
- "./TransitionEvent"
- ], function(dojo, array, connect, declare, lang, win, dom, domClass, domConstruct, on, ready, registry, ProgressIndicator, TransitionEvent){
- // module:
- // dojox/mobile/ViewController
- // summary:
- // A singleton class that controlls view transition.
- var dm = lang.getObject("dojox.mobile", true);
- var Controller = declare("dojox.mobile.ViewController", null, {
- // summary:
- // A singleton class that controlls view transition.
- // description:
- // This class listens to the "startTransition" events and performs
- // view transitions. If the transition destination is an external
- // view specified with the url parameter, retrieves the view
- // content and parses it to create a new target view.
- constructor: function(){
- this.viewMap={};
- this.currentView=null;
- this.defaultView=null;
- ready(lang.hitch(this, function(){
- on(win.body(), "startTransition", lang.hitch(this, "onStartTransition"));
- }));
- },
- findCurrentView: function(moveTo,src){
- // summary:
- // Searches for the currently showing view.
- if(moveTo){
- var w = registry.byId(moveTo);
- if(w && w.getShowingView){ return w.getShowingView(); }
- }
- if(dm.currentView){
- return dm.currentView; //TODO:1.8 may not return an expected result especially when views are nested
- }
- //TODO:1.8 probably never reaches here
- w = src;
- while(true){
- w = w.getParent();
- if(!w){ return null; }
- if(domClass.contains(w.domNode, "mblView")){ break; }
- }
- return w;
- },
- onStartTransition: function(evt){
- // summary:
- // A handler that performs view transition.
- evt.preventDefault();
- if(!evt.detail || (evt.detail && !evt.detail.moveTo && !evt.detail.href && !evt.detail.url && !evt.detail.scene)){ return; }
- var w = this.findCurrentView(evt.detail.moveTo, (evt.target && evt.target.id)?registry.byId(evt.target.id):registry.byId(evt.target)); // the current view widget
- if(!w || (evt.detail && evt.detail.moveTo && w === registry.byId(evt.detail.moveTo))){ return; }
- if(evt.detail.href){
- var t = registry.byId(evt.target.id).hrefTarget;
- if(t){
- dm.openWindow(evt.detail.href, t);
- }else{
- w.performTransition(null, evt.detail.transitionDir, evt.detail.transition, evt.target, function(){location.href = evt.detail.href;});
- }
- return;
- } else if(evt.detail.scene){
- connect.publish("/dojox/mobile/app/pushScene", [evt.detail.scene]);
- return;
- }
- var moveTo = evt.detail.moveTo;
- if(evt.detail.url){
- var id;
- if(dm._viewMap && dm._viewMap[evt.detail.url]){
- // external view has already been loaded
- id = dm._viewMap[evt.detail.url];
- }else{
- // get the specified external view and append it to the <body>
- var text = this._text;
- if(!text){
- if(registry.byId(evt.target.id).sync){
- // We do not add explicit dependency on dojo/_base/xhr to this module
- // to be able to create a build that does not contain dojo/_base/xhr.
- // User applications that do sync loading here need to explicitly
- // require dojo/_base/xhr up front.
- dojo.xhrGet({url:evt.detail.url, sync:true, load:function(result){
- text = lang.trim(result);
- }});
- }else{
- var s = "dojo/_base/xhr"; // assign to a variable so as not to be picked up by the build tool
- require([s], lang.hitch(this, function(xhr){
- var prog = ProgressIndicator.getInstance();
- win.body().appendChild(prog.domNode);
- prog.start();
- var obj = xhr.get({
- url: evt.detail.url,
- handleAs: "text"
- });
- obj.addCallback(lang.hitch(this, function(response, ioArgs){
- prog.stop();
- if(response){
- this._text = response;
- new TransitionEvent(evt.target, {
- transition: evt.detail.transition,
- transitionDir: evt.detail.transitionDir,
- moveTo: moveTo,
- href: evt.detail.href,
- url: evt.detail.url,
- scene: evt.detail.scene},
- evt.detail)
- .dispatch();
- }
- }));
- obj.addErrback(function(error){
- prog.stop();
- console.log("Failed to load "+evt.detail.url+"\n"+(error.description||error));
- });
- }));
- return;
- }
- }
- this._text = null;
- id = this._parse(text, registry.byId(evt.target.id).urlTarget);
- if(!dm._viewMap){
- dm._viewMap = [];
- }
- dm._viewMap[evt.detail.url] = id;
- }
- moveTo = id;
- w = this.findCurrentView(moveTo,registry.byId(evt.target.id)) || w; // the current view widget
- }
- var src = registry.getEnclosingWidget(evt.target);
- var context, method;
- if(src && src.callback){
- context = src;
- method = src.callback;
- }
- w.performTransition(moveTo, evt.detail.transitionDir, evt.detail.transition, context, method);
- },
- _parse: function(text, id){
- // summary:
- // Parses the given view content.
- // description:
- // If the content is html fragment, constructs dom tree with it
- // and runs the parser. If the content is json data, passes it
- // to _instantiate().
- var container, view, i, j, len;
- var currentView = this.findCurrentView();
- var target = registry.byId(id) && registry.byId(id).containerNode
- || dom.byId(id)
- || currentView && currentView.domNode.parentNode
- || win.body();
- // if a fixed bottom bar exists, a new view should be placed before it.
- var refNode = null;
- for(j = target.childNodes.length - 1; j >= 0; j--){
- var c = target.childNodes[j];
- if(c.nodeType === 1){
- if(c.getAttribute("fixed") === "bottom"){
- refNode = c;
- break;
- }
- }
- }
- if(text.charAt(0) === "<"){ // html markup
- container = domConstruct.create("DIV", {innerHTML: text});
- for(i = 0; i < container.childNodes.length; i++){
- var n = container.childNodes[i];
- if(n.nodeType === 1){
- view = n; // expecting <div dojoType="dojox.mobile.View">
- break;
- }
- }
- if(!view){
- console.log("dojox.mobile.ViewController#_parse: invalid view content");
- return;
- }
- view.style.visibility = "hidden";
- target.insertBefore(container, refNode);
- var ws = dojo.parser.parse(container);
- array.forEach(ws, function(w){
- if(w && !w._started && w.startup){
- w.startup();
- }
- });
- // allows multiple root nodes in the fragment,
- // but transition will be performed to the 1st view.
- for(i = 0, len = container.childNodes.length; i < len; i++){
- target.insertBefore(container.firstChild, refNode); // reparent
- }
- target.removeChild(container);
- registry.byNode(view)._visible = true;
- }else if(text.charAt(0) === "{"){ // json
- container = domConstruct.create("DIV");
- target.insertBefore(container, refNode);
- this._ws = [];
- view = this._instantiate(eval('('+text+')'), container);
- for(i = 0; i < this._ws.length; i++){
- var w = this._ws[i];
- w.startup && !w._started && (!w.getParent || !w.getParent()) && w.startup();
- }
- this._ws = null;
- }
- view.style.display = "none";
- view.style.visibility = "visible";
- return dojo.hash ? "#" + view.id : view.id;
- },
- _instantiate: function(/*Object*/obj, /*DomNode*/node, /*Widget*/parent){
- // summary:
- // Given the evaluated json data, does the same thing as what
- // the parser does.
- var widget;
- for(var key in obj){
- if(key.charAt(0) == "@"){ continue; }
- var cls = lang.getObject(key);
- if(!cls){ continue; }
- var params = {};
- var proto = cls.prototype;
- var objs = lang.isArray(obj[key]) ? obj[key] : [obj[key]];
- for(var i = 0; i < objs.length; i++){
- for(var prop in objs[i]){
- if(prop.charAt(0) == "@"){
- var val = objs[i][prop];
- prop = prop.substring(1);
- if(typeof proto[prop] == "string"){
- params[prop] = val;
- }else if(typeof proto[prop] == "number"){
- params[prop] = val - 0;
- }else if(typeof proto[prop] == "boolean"){
- params[prop] = (val != "false");
- }else if(typeof proto[prop] == "object"){
- params[prop] = eval("(" + val + ")");
- }
- }
- }
- widget = new cls(params, node);
- if(node){ // to call View's startup()
- widget._visible = true;
- this._ws.push(widget);
- }
- if(parent && parent.addChild){
- parent.addChild(widget);
- }
- this._instantiate(objs[i], null, widget);
- }
- }
- return widget && widget.domNode;
- }
- });
- new Controller(); // singleton
- return Controller;
- });
|