Index: Dev/branches/rest-dojo-ui/client/index.html
===================================================================
--- Dev/branches/rest-dojo-ui/client/index.html	(revision 261)
+++ Dev/branches/rest-dojo-ui/client/index.html	(revision 263)
@@ -18,4 +18,7 @@
                 <span data-dojo-type="rft.ui.MenuBarLink" data-dojo-props="pageId:'surveys'">Surveys</span>
                 <span data-dojo-type="rft.ui.MenuBarLink" data-dojo-props="pageId:'results'">Results</span>
+                <span data-dojo-type="rft.ui.MenuBarLink" data-dojo-props="pageId:'test1'">Test 1</span>
+                <span data-dojo-type="rft.ui.MenuBarLink" data-dojo-props="pageId:'test2'">Test 2</span>
+                <span data-dojo-type="rft.ui.MenuBarLink" data-dojo-props="pageId:'test3'">Test 3</span>
             </div>
             <div id="userinfo" class="mainUserInfo">Login</div>
Index: Dev/branches/rest-dojo-ui/client/pages/index.html
===================================================================
--- Dev/branches/rest-dojo-ui/client/pages/index.html	(revision 263)
+++ Dev/branches/rest-dojo-ui/client/pages/index.html	(revision 263)
@@ -0,0 +1,3 @@
+<div>
+    <h1>Index pagina</h1>
+</div>
Index: Dev/branches/rest-dojo-ui/client/pages/session.html
===================================================================
--- Dev/branches/rest-dojo-ui/client/pages/session.html	(revision 261)
+++ Dev/branches/rest-dojo-ui/client/pages/session.html	(revision 263)
@@ -1,5 +1,6 @@
-<div data-dojo-type="rft.ui.Page">
-    <script type="dojo/method" data-dojo-event="init">
+<div>
+    <script type="dojo/method" data-dojo-event="onVisit">
         var that = this;
+        debugger;
         require(['dojo/_base/json','dojo/dom','dojo/store/JsonRest','dojo/domReady!'],
             function(json,dom,JsonRest){
Index: Dev/branches/rest-dojo-ui/client/pages/sessions.html
===================================================================
--- Dev/branches/rest-dojo-ui/client/pages/sessions.html	(revision 261)
+++ Dev/branches/rest-dojo-ui/client/pages/sessions.html	(revision 263)
@@ -1,21 +1,36 @@
-<div data-dojo-type="rft.ui.Page">
-    <script type="dojo/method" data-dojo-event="init">
+<div>
+    <script type="rft/method" data-rft-method="onVisit">
         var that = this;
-        require(['dojo/store/JsonRest','dojox/grid/DataGrid',
-            Â Â Â Â 'dojo/data/ObjectStore','dojo/domReady!'],
-        function(JsonRest,DataGrid,ObjectStore){
+        require(['dojo/_base/lang','dojo/_base/event','dojo/store/JsonRest','dojox/grid/DataGrid',
+        Â Â Â Â 'dojo/data/ObjectStore','rft/content','dojo/domReady!'],
+        function(lang,event,JsonRest,DataGrid,ObjectStore,content){
             var store = new JsonRest({
                 target:"../server/api.php/data/Session/",
                 idProperty: 'uid'
             });
-        Â Â Â Â var grid = new DataGrid({
-        Â Â Â Â Â Â Â Â store: ObjectStore({objectStore: store}),
-                autoWidth: true,
-                autoHeight: true,
-        Â Â Â Â Â Â Â Â structure: [
-            Â Â Â Â Â Â Â Â Â Â Â Â {name:"Title", field:"title", width: "200px"}
-        Â Â Â Â Â Â Â Â ]
-        Â Â Â Â }, that.page_sessions_grid);
-        Â Â Â Â grid.startup();
+
+            that.grid.setStore(ObjectStore({objectStore: store}));
+        
+            that.grid.on('rowclick',lang.hitch(that,function(evt){
+                var obj = evt.grid.getItem(evt.rowIndex);
+                this.form.set('value', obj);
+            }));
+
+            that.grid.on('rowdblclick',lang.hitch(that,function(evt){
+                var obj = evt.grid.getItem(evt.rowIndex);
+                content.goTo('/session',{uid:obj.uid});
+            }));
+
+            var submitHandler = lang.hitch(that,function(evt){
+                var newObj = this.form.get('value');
+                debugger;
+                // mixin newObj in obj.
+                // store.put(newObj);
+                event.stop(evt);
+                return false;
+            });
+            that.btnSave.on('click',submitHandler);
+            that.form.on('submit',submitHandler);
+        
         });
     </script>
@@ -23,5 +38,19 @@
         <div class="largeTitle">Sessions</div>
         <div class="content">
-            <div data-rft-attach-point="page_sessions_grid"></div>
+            <div data-dojo-type="dojox.grid.DataGrid" data-dojo-props="autoWidth:true,autoHeight:true,structure:[{name:'Title',field:'title'}]" data-dojo-attach-point="grid"></div>
+        </div>
+
+    </div>
+
+    <div class="largeFrame" style="width: 400px;">
+        <div class="largeTitle">Details</div>
+        <div>
+            <form data-dojo-type="dijit.form.Form" data-dojo-attach-point="form">
+                <fieldset>
+                    <label for="title" class="loginLabel">Title</label>
+                    <input data-dojo-type="dijit.form.TextBox" name="title" type="text" class="loginInput" />
+                </fieldset>
+                <button type="submit" data-dojo-type="dijit.form.Button" data-dojo-attach-point="btnSave">Save</button>
+            </form>
         </div>
     </div>
Index: Dev/branches/rest-dojo-ui/client/pages/test1.html
===================================================================
--- Dev/branches/rest-dojo-ui/client/pages/test1.html	(revision 263)
+++ Dev/branches/rest-dojo-ui/client/pages/test1.html	(revision 263)
@@ -0,0 +1,18 @@
+<div data-rft-mixin="rft/ui/TestPageController">
+    <h1>External _PageController test</h1>
+    <div data-dojo-type="dijit.layout.TabContainer" data-dojo-props="doLayout: false">
+        <div data-dojo-type="dijit.layout.ContentPane" title="Sessions">
+            <div data-dojo-type="dojox.grid.DataGrid" data-dojo-props="autoWidth:true,autoHeight:true,structure:[{name:'Title',field:'title'}]" data-dojo-attach-point="grid"></div>
+        </div>
+        <div data-dojo-type="dijit.layout.ContentPane" title="Details">
+            <form data-dojo-type="dijit.form.Form" data-dojo-attach-point="form">
+                <fieldset>
+                    <label for="title" class="loginLabel">Title</label>
+                    <input data-dojo-type="dijit.form.TextBox" name="title" type="text" class="loginInput" />
+                </fieldset>
+                <button type="submit" data-dojo-type="dijit.form.Button" data-dojo-attach-point="btnSave">Save</button>
+            </form>
+            <div data-dojo-attach-point="errors"></div>
+        </div>
+    </div>
+</div>
Index: Dev/branches/rest-dojo-ui/client/pages/test2.html
===================================================================
--- Dev/branches/rest-dojo-ui/client/pages/test2.html	(revision 263)
+++ Dev/branches/rest-dojo-ui/client/pages/test2.html	(revision 263)
@@ -0,0 +1,18 @@
+<div>
+    <h1>No rft.ui._Page features used</h1>
+    <div data-dojo-type="dijit.layout.TabContainer" data-dojo-props="doLayout: false" style="border: 1px solid black" id="tabber">
+        <div data-dojo-type="dijit.layout.ContentPane" title="Sessions">
+            <div data-dojo-type="dojox.grid.DataGrid" data-dojo-props="store:dojo.data.ObjectStore({objectStore: new dojo.store.JsonRest({target:'../server/api.php/data/Session/',idProperty: 'uid'})}),autoWidth:true,autoHeight:true,structure:[{name:'Title',field:'title'}]"></div>
+        </div>
+        <div data-dojo-type="dijit.layout.ContentPane" title="Details">
+            <form data-dojo-type="dijit.form.Form">
+                <fieldset>
+                    <label for="title" class="loginLabel">Title</label>
+                    <input data-dojo-type="dijit.form.TextBox" name="title" type="text" class="loginInput" />
+                </fieldset>
+                <button type="submit" data-dojo-type="dijit.form.Button">Save</button>
+            </form>
+            <div></div>
+        </div>
+    </div>
+</div>
Index: Dev/branches/rest-dojo-ui/client/pages/test3.html
===================================================================
--- Dev/branches/rest-dojo-ui/client/pages/test3.html	(revision 263)
+++ Dev/branches/rest-dojo-ui/client/pages/test3.html	(revision 263)
@@ -0,0 +1,92 @@
+<div>
+    <script type="rft/method" data-rft-method="onVisit">
+        var that = this;
+        require(['dojo/_base/declare','dojo/_base/lang','dojo/_base/event','rft/content',
+            'dojo/store/JsonRest','dojo/data/ObjectStore','rft/ui/_PageController','dijit/registry'],
+        function(declare,lang,event,content,JsonRest,ObjectStore,_PageController,registry){
+            (lang.hitch(that,function(){
+                this._store = new JsonRest({
+                    target:"../server/api.php/data/Session/",
+                    idProperty: 'uid'
+                });
+
+                function setEnabledRecursive(node,value) {
+                    registry.findWidgets(node).forEach(function(w){
+                        w.set('disabled',!value);
+                        setEnabledRecursive(w.domNode,value);
+                    });
+                };
+
+                setEnabledRecursive(this.form.domNode,false);
+                
+                var refreshGrid = lang.hitch(this,function(){
+                    this.grid.setStore(ObjectStore({
+                        objectStore: this._store
+                    }),'');
+                });
+                refreshGrid();
+                
+                var getSelectedItem = lang.hitch(this,function(evt){
+                    var items = this.grid.selection.getSelected();
+                    if (items.length)
+                        return items[0];
+                    return null;
+                });
+                
+                this.grid.on('rowclick',lang.hitch(this,function(evt){
+                    var obj = getSelectedItem();
+                    if ( obj) {
+                        this.form.set('value', obj);
+                        setEnabledRecursive(this.form.domNode, true);
+                    } else {
+                        setEnabledRecursive(this.form.domNode, false);
+                        this.form.reset();
+                    }
+                }));
+
+                this.grid.on('rowdblclick',lang.hitch(this,function(evt){
+                    var obj = getSelectedItem();
+                    content.goTo('/session',{
+                        uid:obj.uid
+                    });
+                }));
+
+                var submitHandler = lang.hitch(this,function(evt){
+                    this.errors.innerHTML = '';
+                    var newObj = this.form.get('value');
+                    var obj = getSelectedItem();
+                    obj = lang.mixin(obj,newObj);
+                    //this._store.put(newObj,{id:obj.uid})
+                    this._store.put(obj,{
+                        overwrite:true
+                    })
+                    .then(lang.hitch(this,function(){
+                        refreshGrid();
+                    }),lang.hitch(this,function(e){
+                        this.errors.innerHTML = e.toString();
+                    }));
+                    event.stop(evt);
+                    return false;
+                });
+                
+                this.form.on('submit',submitHandler);
+            }))();
+        });
+    </script>
+    <h1>Embedded scripts</h1>
+    <div data-dojo-type="dijit.layout.TabContainer" data-dojo-props="doLayout: false">
+        <div data-dojo-type="dijit.layout.ContentPane" title="Sessions">
+            <div data-dojo-type="dojox.grid.DataGrid" data-dojo-props="autoWidth:true,autoHeight:true,structure:[{name:'Title',field:'title'}]" data-dojo-attach-point="grid"></div>
+        </div>
+        <div data-dojo-type="dijit.layout.ContentPane" title="Details">
+            <form data-dojo-type="dijit.form.Form" data-dojo-attach-point="form">
+                <fieldset>
+                    <label for="title" class="loginLabel">Title</label>
+                    <input data-dojo-type="dijit.form.TextBox" name="title" type="text" class="loginInput" />
+                </fieldset>
+                <button type="submit" data-dojo-type="dijit.form.Button" data-dojo-attach-point="btnSave">Save</button>
+            </form>
+            <div data-dojo-attach-point="errors"></div>
+        </div>
+    </div>
+</div>
Index: Dev/branches/rest-dojo-ui/client/rft/content.js
===================================================================
--- Dev/branches/rest-dojo-ui/client/rft/content.js	(revision 261)
+++ Dev/branches/rest-dojo-ui/client/rft/content.js	(revision 263)
@@ -1,13 +1,14 @@
-define(['dojo/_base/declare','dojo/_base/connect','dojo/_base/xhr','dojo/dom-construct',
-    'dojo/dom-attr','dojo/_base/lang','dojo/_base/Deferred','dojo/hash',
-    'dojo/io-query','dojo/_base/json','dijit','rft/util'],
-    function(declare,connect,xhr,domConstruct,attr,lang,Deferred,hash,uriQuery,json,dijit,util){
+define(['dojo/_base/declare','dojo/_base/connect','dojo/_base/xhr',
+    'dojo/_base/lang','dojo/_base/Deferred','dojo/hash',
+    'dojo/io-query','dijit','rft/util','rft/ui/_Page'],
+    function(declare,connect,xhr,lang,Deferred,hash,uriQuery,dijit,util,_Page){
         return new (function() {
             var self = this;
-            var current = "";
+            var currentHash = "";
+            var currentPage = null;
             
             var HRI = declare(null,{
                 constructor: function() {
-                    this._path = '/';
+                    this._path = this._fixPath('/');
                     this._args = {};
                     if ( arguments.length == 1 ) {
@@ -54,35 +55,54 @@
             function _goTo(hri,replace) {
                 var contentPane = dijit.byId('content');
-                var d = new Deferred();
+                var dfd = new Deferred();
                 var newHash = hri.hash();
-                if ( current == newHash ) {
-                    d.resolve();
-                    return d.promise;
+                
+                // if already there, return
+                if ( currentHash === newHash ) {
+                    dfd.resolve();
+                    return dfd.promise;
                 }
-                current = newHash;
+                
+                // check if we can leave current page
+                if ( currentPage ) {
+                    if ( currentPage.onLeave() === false ) {
+                        dfd.reject();
+                        return dfd.promise;
+                    }
+                }
+                
+                // update hash
+                currentHash = newHash;
                 hash(newHash,replace);
+                
+                // load html
+                var pageUrl = 'pages'+hri.path()+'.html';
                 xhr.get({
-                    url: 'pages'+hri.path()+'.html',
+                    url: pageUrl,
                     failOk: true
                 })
+                
+                // initialize page or create error message
                 .then(function(html){
-                    var root = domConstruct.toDom(html)
-                    var props = json.toJson(hri.args());
-                    props = props.slice(1,props.length-2);
-                    if ( props )
-                        attr.set(root,'data-rft-props',props);
-                    contentPane.set('content',root);
-                    d.resolve();
+                    currentPage = new _Page({
+                        templateString: html,
+                        pageQuery: hri.args()
+                    });
+                    contentPane.set('content',currentPage);
+                    dfd.resolve();
                 },function(){
-                    contentPane.set('content',"Page "+hri.path()+" not found.");
-                    d.reject();
+                    currentPage = new _Page({
+                        templateString: "<div>Page "+hri.path()+" not found.</div>"
+                    });
+                    contentPane.set('content',currentPage);
+                    dfd.reject();
                 });
-                return d.promise;
+                return dfd.promise;
             }
 
             self.initial = function(path,args) {
-                if ( current ) {
+                if ( currentHash ) {
                     var dfd = new Deferred();
-                    dfd.resolved();
+                    dfd.resolve();
                     return dfd.promise;
                 }
Index: Dev/branches/rest-dojo-ui/client/rft/run.js
===================================================================
--- Dev/branches/rest-dojo-ui/client/rft/run.js	(revision 261)
+++ Dev/branches/rest-dojo-ui/client/rft/run.js	(revision 263)
@@ -1,14 +1,25 @@
+require([
+    'dijit/form/Form',
+    'dojo/store/JsonRest',
+    'dojo/data/ObjectStore',
+    'dojox/grid/DataGrid',
+    'dijit/layout/ContentPane',
+    'dijit/layout/TabContainer',
+    'dijit/MenuBar',
+    'dijit/MenuBarItem',
+    'rft/ui/MenuBarLink',
+]);
+
 require(['dojo/_base/window','dojo/parser', 'rft/ui/LoginDialog', 
     'dojo/dom', 'dojo/_base/connect', 'rft/auth', 'rft/content',
-    'dojo/domReady!', 'dijit/layout/ContentPane', 'dijit/MenuBar',
-    'dijit/MenuBarItem', 'rft/ui/MenuBarLink', 'rft/ui/Page'],
+    'dojo/domReady!', ],
     function(win,parser,LoginDialog,dom,connect,auth,content) {
         parser.parse();
 
-        var login = new LoginDialog().placeAt(document.body);
+        var login = new LoginDialog().placeAt(win.body());
         login.startup();
 
         auth.restore()
-        .then(function(user){
+        .then(function(){
             content.initial();
         },function(){
Index: Dev/branches/rest-dojo-ui/client/rft/ui/LoginDialog.html
===================================================================
--- Dev/branches/rest-dojo-ui/client/rft/ui/LoginDialog.html	(revision 261)
+++ Dev/branches/rest-dojo-ui/client/rft/ui/LoginDialog.html	(revision 263)
@@ -14,7 +14,7 @@
                 <input data-dojo-type="dijit.form.TextBox" name="password" type="password" class="loginInput" />
             </fieldset>
+            <button type="submit" data-dojo-type="dijit.form.Button" data-dojo-attach-event="onClick:onLogin">Login</button>
+            <button type="button" data-dojo-type="dijit.form.Button" data-dojo-attach-event="onClick:onCancel">Cancel</button>
         </form>
-        <button type="button" data-dojo-type="dijit.form.Button" data-dojo-attach-event="onClick:onLogin">Login</button>
-        <button type="button" data-dojo-type="dijit.form.Button" data-dojo-attach-event="onClick:onCancel">Cancel</button>
         <div data-dojo-attach-point="loginErrors"></div>
     </div>
Index: Dev/branches/rest-dojo-ui/client/rft/ui/LoginDialog.js
===================================================================
--- Dev/branches/rest-dojo-ui/client/rft/ui/LoginDialog.js	(revision 261)
+++ Dev/branches/rest-dojo-ui/client/rft/ui/LoginDialog.js	(revision 263)
@@ -1,6 +1,6 @@
-define(['dojo/_base/declare','dojo/_base/lang','dijit/Dialog','dijit/_WidgetsInTemplateMixin',
-    '../auth', 'dojo/text!./LoginDialog.html','../content',
-    'dijit/form/Form','dijit/form/Button','dijit/form/TextBox'],
-    function (declare, lang, Dialog, _WidgetsInTemplateMixin, auth, template, content) {
+define(['dojo/_base/declare','dojo/_base/lang','dojo/_base/event','dijit/Dialog',
+    'dijit/_WidgetsInTemplateMixin','../auth', 'dojo/text!./LoginDialog.html',
+    '../content','dijit/form/Form','dijit/form/Button','dijit/form/TextBox'],
+    function (declare, lang, event, Dialog, _WidgetsInTemplateMixin, auth, template, content) {
         return declare([Dialog,_WidgetsInTemplateMixin], {
             templateString: template,
@@ -8,4 +8,8 @@
             title: "Login",
             baseClass: "rftLoginDialog",
+            startup: function() {
+                this.inherited(arguments);
+                this.loginForm.on('submit',lang.hitch(this,'onLogin'));
+            },
             show: function() {
                 this.loginErrors.innerHTML = '';
@@ -13,15 +17,15 @@
                 this.inherited(arguments);
             },
-            onLogin: function() {
+            onLogin: function(evt) {
                 this.loginErrors.innerHTML = '';
                 var data = this.loginForm.get('value');
-                var hide = lang.hitch(this,"hide");
                 auth.login(data.username,data.password)
-                .then(function() {
-                    hide();
+                .then(lang.hitch(this,function() {
+                    this.hide();
                     content.initial();
-                },function() {
+                }),lang.hitch(this,function() {
                     this.loginErrors.innerHTML = 'Login failed.';
-                })
+                }));
+                event.stop(evt);
                 return false;
             }
Index: Dev/branches/rest-dojo-ui/client/rft/ui/Page.js
===================================================================
--- Dev/branches/rest-dojo-ui/client/rft/ui/Page.js	(revision 261)
+++ 	(revision )
@@ -1,23 +1,0 @@
-define(['dojo/_base/declare','dojo/query','dojo/_base/json','dojo/dom-attr','dojo/_base/lang','dijit/registry','dijit/_WidgetBase','dijit/_Container'],
-    function(declare,query,json,attr,lang,registry,_WidgetBase,_Container){
-        return declare('rft.ui.Page',[_WidgetBase,_Container],{
-            postCreate: function() {
-                this.inherited(arguments);
-                this.args = {};
-                var props = attr.get(this.domNode,'data-rft-props');
-                if ( props ) {
-                    props = json.fromJson.call(this,'{'+props+'}');
-                    lang.mixin(this.args,props);
-                }
-            },
-            startup: function() {
-                this.inherited(arguments);
-                query('[data-rft-attach-point]').forEach(lang.hitch(this,function(node){
-                    var name = attr.get(node,'data-rft-attach-point');
-                    this[name] = registry.byNode(node) || node;
-                }));
-                this.init();
-            },
-            init: function(){}
-        });
-    });
Index: Dev/branches/rest-dojo-ui/client/rft/ui/TestPageController.js
===================================================================
--- Dev/branches/rest-dojo-ui/client/rft/ui/TestPageController.js	(revision 263)
+++ Dev/branches/rest-dojo-ui/client/rft/ui/TestPageController.js	(revision 263)
@@ -0,0 +1,73 @@
+define(['dojo/_base/declare','dojo/_base/lang','dojo/_base/event','rft/content',
+    'dojo/store/JsonRest','dojo/data/ObjectStore','rft/ui/_PageController','dijit/registry'],
+    function(declare,lang,event,content,JsonRest,ObjectStore,_PageController,registry) {
+        return declare([_PageController],{
+            onVisit: function() {
+                this._store = new JsonRest({
+                    target:"../server/api.php/data/Session/",
+                    idProperty: 'uid'
+                });
+
+                function setEnabledRecursive(node,value) {
+                    registry.findWidgets(node).forEach(function(w){
+                        w.set('disabled',!value);
+                        setEnabledRecursive(w.domNode,value);
+                    });
+                };
+
+                setEnabledRecursive(this.form.domNode,false);
+
+                var refreshGrid = lang.hitch(this,function(){
+                    this.grid.setStore(ObjectStore({
+                        objectStore: this._store
+                    }),'');
+                });
+                refreshGrid();
+                
+                var getSelectedItem = lang.hitch(this,function(evt){
+                    var items = this.grid.selection.getSelected();
+                    if (items.length)
+                        return items[0];
+                    return null;
+                });
+                
+                this.grid.on('rowclick',lang.hitch(this,function(evt){
+                    var obj = getSelectedItem();
+                    if ( obj) {
+                        this.form.set('value', obj);
+                        setEnabledRecursive(this.form.domNode, true);
+                    } else {
+                        setEnabledRecursive(this.form.domNode, false);
+                        this.form.reset();
+                    }
+                }));
+
+                this.grid.on('rowdblclick',lang.hitch(this,function(evt){
+                    var obj = getSelectedItem();
+                    content.goTo('/session',{
+                        uid:obj.uid
+                    });
+                }));
+
+                var submitHandler = lang.hitch(this,function(evt){
+                    this.errors.innerHTML = '';
+                    var newObj = this.form.get('value');
+                    var obj = getSelectedItem();
+                    obj = lang.mixin(obj,newObj);
+                    //this._store.put(newObj,{id:obj.uid})
+                    this._store.put(obj,{
+                        overwrite:true
+                    })
+                    .then(lang.hitch(this,function(){
+                        refreshGrid();
+                    }),lang.hitch(this,function(e){
+                        this.errors.innerHTML = e.toString();
+                    }));
+                    event.stop(evt);
+                    return false;
+                });
+                
+                this.form.on('submit',submitHandler);
+            }
+        });
+    });
Index: Dev/branches/rest-dojo-ui/client/rft/ui/_Page.js
===================================================================
--- Dev/branches/rest-dojo-ui/client/rft/ui/_Page.js	(revision 263)
+++ Dev/branches/rest-dojo-ui/client/rft/ui/_Page.js	(revision 263)
@@ -0,0 +1,44 @@
+define(['dojo/_base/declare','dojo/_base/lang','dojo/_base/array','dojo/parser','dojo/query','dojo/_base/Deferred',
+    'dijit/_WidgetBase','dijit/_TemplatedMixin','dijit/_WidgetsInTemplateMixin','rft/ui/_PageController'],
+    function(declare,lang,array,parser,query,Deferred,_WidgetBase,_TemplatedMixin,_WidgetsInTemplateMixin,_PageController){
+        return declare('rft.ui._Page',[_WidgetBase,_TemplatedMixin,_WidgetsInTemplateMixin,_PageController],{
+            _controllerLoaded: false,
+            _hasStarted: false,
+            _triggeredOnVisit: false,
+            pageController: null, /* class derived from rft.ui._PageController, mixed in at creation */
+            buildRendering: function() {
+                this.inherited(arguments);
+                var dfd = new Deferred();
+                var mixinType = this.domNode.getAttribute("data-rft-mixin");
+                if ( mixinType ) {
+                    require([mixinType],lang.hitch(this,function(SomePageController){
+                        declare.safeMixin(this,new SomePageController());
+                        dfd.resolve();
+                    }));
+                } else {
+                    dfd.resolve();
+                }
+                dfd.then(lang.hitch(this,function(){
+                    var methods = query('> script[type^="rft/method"]',this.domNode).orphan();
+                    array.forEach(methods,lang.hitch(this,function(s){
+                        var method = s.getAttribute("data-rft-method");
+                        var func = parser._functionFromScript(s);
+                        this[method] = func;
+                    }));
+                    this._controllerLoaded = true;
+                    this._triggerOnVisit();
+                }));
+            },
+            startup: function() {
+                this.inherited(arguments);
+                this._hasStarted = true;
+                this._triggerOnVisit();
+            },
+            _triggerOnVisit: function() {
+                if ( this._controllerLoaded && this._hasStarted && !this._triggeredOnVisit ) {
+                    this._triggeredOnVisit = false;
+                    this.onVisit();
+                }
+            }
+        });
+    });
Index: Dev/branches/rest-dojo-ui/client/rft/ui/_PageController.js
===================================================================
--- Dev/branches/rest-dojo-ui/client/rft/ui/_PageController.js	(revision 263)
+++ Dev/branches/rest-dojo-ui/client/rft/ui/_PageController.js	(revision 263)
@@ -0,0 +1,10 @@
+define(['dojo/_base/declare'],
+    function(declare) {
+        return declare('rft.ui._PageController',null,{
+            /** Event fired after startup of all widegts is complete */
+            onVisit: function(){},
+            /** Event fired before leaving the page. Return false to prevent */
+            onLeave: function(){}
+        });
+    });
+
Index: Dev/branches/rest-dojo-ui/server/api.php
===================================================================
--- Dev/branches/rest-dojo-ui/server/api.php	(revision 261)
+++ Dev/branches/rest-dojo-ui/server/api.php	(revision 263)
@@ -12,5 +12,5 @@
 use Tonic\Resource as Resource;
 
-function set_session_cookie($response,$user) {
+function set_session_cookie($response, $user) {
     $response->addHeader('Set-Cookie', 'rft_uid=' . $user->uid . '; Max-Age: 3600; Path=' . $response->request->baseUri);
 }
@@ -31,4 +31,10 @@
 }
 
+function add_default_headers($response) {
+    $response->addHeader('Content-Type', 'application/json');
+    $response->addHeader('Cache-Control', 'no-cache, must-revalidate');
+    $response->addHeader('Expires', 'Sat, 26 Jul 1997 05:00:00 GMT');
+}
+
 /**
  *  @uri /login
@@ -41,6 +47,6 @@
         $user = null;
         $data = null;
-        if ( !empty($request->data) ) {
-            $data = json_decode($request->data,true);
+        if (!empty($request->data)) {
+            $data = json_decode($request->data, true);
         }
         if (!empty($data)) {
@@ -49,4 +55,5 @@
                 throw new ResponseException("Incorrect username and password", Response::UNAUTHORIZED);
             }
+            set_session_cookie($response, $user);
         } else {
             $user = restore_session($response);
@@ -140,5 +147,5 @@
         $objects = $info['type']::get(array('uid' => $info['uid']));
         if (empty($objects)) {
-            throw new ReponseException("Object not found", Response::NOTFOUND);
+            throw new ResponseException("Object not found", Response::NOTFOUND);
         }
 
@@ -195,4 +202,5 @@
     $request->baseUri = $baseUri;
 }
+
 try {
     $resource = $request->loadResource();
@@ -200,8 +208,11 @@
 } catch (ResponseException $e) {
     $response = $e->response($request);
-}
-$response->addHeader('Content-Type', 'application/json');
-$response->addHeader('Cache-Control', 'no-cache, must-revalidate');
-$response->addHeader('Expires', 'Sat, 26 Jul 1997 05:00:00 GMT');
+    $response->body = json_encode(array('errorMsg' => $response->body));
+} catch (Exception $e) {
+    $response = new Response($request);
+    $response->code = Response::INTERNALSERVERERROR;
+    $response->body = json_encode(array('errorMsg' => "Unhandled exception: " . $e));
+}
+add_default_headers($response);
 $response->output();
 ?>
Index: Dev/branches/rest-dojo-ui/server/classes/models/Answer.php
===================================================================
--- Dev/branches/rest-dojo-ui/server/classes/models/Answer.php	(revision 261)
+++ Dev/branches/rest-dojo-ui/server/classes/models/Answer.php	(revision 263)
@@ -112,5 +112,5 @@
 		//TODO: Decide how to fix invalid references graciously.
 		if(!$this->evaluate()) 
-			return false;
+			throw new Exception('Evaluation failed.');
 
 		//Ensure the required folder exists.
Index: Dev/branches/rest-dojo-ui/server/classes/models/AnswerSet.php
===================================================================
--- Dev/branches/rest-dojo-ui/server/classes/models/AnswerSet.php	(revision 261)
+++ Dev/branches/rest-dojo-ui/server/classes/models/AnswerSet.php	(revision 263)
@@ -84,6 +84,7 @@
 		//TODO: Decide how to fix invalid references graciously.
 		if(!$this->evaluate()) 
-			return false;
-		//Ensure the required folder exists.
+			throw new Exception('Evaluation failed.');
+
+        //Ensure the required folder exists.
 		if(!is_dir('data/results/'))
 			mkdir('data/results/');
Index: Dev/branches/rest-dojo-ui/server/classes/models/ApplicationInstance.php
===================================================================
--- Dev/branches/rest-dojo-ui/server/classes/models/ApplicationInstance.php	(revision 261)
+++ Dev/branches/rest-dojo-ui/server/classes/models/ApplicationInstance.php	(revision 263)
@@ -76,5 +76,5 @@
 		//Do note save if there are invalid references in this object.
 		if(!$this->evaluate())
-			return false;
+			throw new Exception('Evaluation failed.');
 
 		//Ensure the required folder exists.
Index: Dev/branches/rest-dojo-ui/server/classes/models/ResultSet.php
===================================================================
--- Dev/branches/rest-dojo-ui/server/classes/models/ResultSet.php	(revision 261)
+++ Dev/branches/rest-dojo-ui/server/classes/models/ResultSet.php	(revision 263)
@@ -72,6 +72,7 @@
 		//TODO: Decide how to fix invalid references graciously.
 		if(!$this->evaluate()) 
-			return false;
-		//Ensure the required folder exists.
+			throw new Exception('Evaluation failed.');
+
+        //Ensure the required folder exists.
 		if(!is_dir('data/results/'))
 			mkdir('data/results/');
Index: Dev/branches/rest-dojo-ui/server/classes/models/Session.php
===================================================================
--- Dev/branches/rest-dojo-ui/server/classes/models/Session.php	(revision 261)
+++ Dev/branches/rest-dojo-ui/server/classes/models/Session.php	(revision 263)
@@ -82,5 +82,5 @@
 		//TODO: Decide how to fix invalid references graciously.
 		if(!$this->evaluate())
-			return false;
+			throw new Exception('Evaluation failed.');
 
 		//Ensure the required folder exists.
Index: Dev/branches/rest-dojo-ui/server/classes/models/SessionInstance.php
===================================================================
--- Dev/branches/rest-dojo-ui/server/classes/models/SessionInstance.php	(revision 261)
+++ Dev/branches/rest-dojo-ui/server/classes/models/SessionInstance.php	(revision 263)
@@ -95,5 +95,5 @@
 		//TODO: Decide how to fix invalid references graciously.
 		if(!$this->evaluate()) 
-			return false;
+			throw new Exception('Evaluation failed.');
 
 		//Ensure the required folder exists.
Index: Dev/branches/rest-dojo-ui/server/classes/models/Survey.php
===================================================================
--- Dev/branches/rest-dojo-ui/server/classes/models/Survey.php	(revision 261)
+++ Dev/branches/rest-dojo-ui/server/classes/models/Survey.php	(revision 263)
@@ -65,5 +65,5 @@
 		//TODO: Decide how to fix invalid references graciously.
 		if(!$this->evaluate()) 
-			return false;
+			throw new Exception('Evaluation failed.');
 
 		if(!is_dir('data/surveys/'))
Index: Dev/branches/rest-dojo-ui/server/data/sessions/sessions.rdf
===================================================================
--- Dev/branches/rest-dojo-ui/server/data/sessions/sessions.rdf	(revision 261)
+++ Dev/branches/rest-dojo-ui/server/data/sessions/sessions.rdf	(revision 263)
@@ -12,5 +12,5 @@
    <ns1:uid>8eda00ead3b9770a54678c63110e5572</ns1:uid>
    <ns1:title><![CDATA[]]></ns1:title>
-   <ns1:creator>525f949e2cce1ebc964f89fba2826ab9</ns1:creator>
+   <ns1:creator>49a9d2d8643b66e5fa0e8f6b7b51a9f3</ns1:creator>
    <ns1:creationdate>1328711521</ns1:creationdate>
 </rdf:Description>
@@ -20,5 +20,5 @@
    <ns1:uid>d8b94990fbc59320c4cc0a409a4368a5</ns1:uid>
    <ns1:title><![CDATA[]]></ns1:title>
-   <ns1:creator>525f949e2cce1ebc964f89fba2826ab9</ns1:creator>
+   <ns1:creator>49a9d2d8643b66e5fa0e8f6b7b51a9f3</ns1:creator>
    <ns1:creationdate>1328714755</ns1:creationdate>
 </rdf:Description>
@@ -28,5 +28,5 @@
    <ns1:uid>d40c12ae47d52a97b1d0d009890bc1bc</ns1:uid>
    <ns1:title>My session (for real)</ns1:title>
-   <ns1:creator>525f949e2cce1ebc964f89fba2826ab9</ns1:creator>
+   <ns1:creator>49a9d2d8643b66e5fa0e8f6b7b51a9f3</ns1:creator>
    <ns1:creationdate>1328714890</ns1:creationdate>
 </rdf:Description>
@@ -36,5 +36,5 @@
    <ns1:uid>c765e10335f7f6bc1670eb8ebf83f08c</ns1:uid>
    <ns1:title>Name...</ns1:title>
-   <ns1:creator>525f949e2cce1ebc964f89fba2826ab9</ns1:creator>
+   <ns1:creator>49a9d2d8643b66e5fa0e8f6b7b51a9f3</ns1:creator>
    <ns1:creationdate>1328715256</ns1:creationdate>
 </rdf:Description>
Index: Dev/branches/rest-dojo-ui/server/data/users/users.rdf
===================================================================
--- Dev/branches/rest-dojo-ui/server/data/users/users.rdf	(revision 261)
+++ Dev/branches/rest-dojo-ui/server/data/users/users.rdf	(revision 263)
@@ -15,129 +15,3 @@
 </rdf:Description>
 
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/150fe83c17857e833a921ddf50caf882">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>150fe83c17857e833a921ddf50caf882</ns1:uid>
-   <ns1:email><![CDATA[]]></ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/63ef7c9bbfaaa46d6517f227cde4d1eb">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>63ef7c9bbfaaa46d6517f227cde4d1eb</ns1:uid>
-   <ns1:email><![CDATA[]]></ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/5fa5ca4f64bfbf843313ca1ce08630e5">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>5fa5ca4f64bfbf843313ca1ce08630e5</ns1:uid>
-   <ns1:email>noot</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/f9978056e4df42aad84a7003a4eb770e">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>f9978056e4df42aad84a7003a4eb770e</ns1:uid>
-   <ns1:email>noot</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/0bfe935a03efd12363d0321b485ad6ce">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>0bfe935a03efd12363d0321b485ad6ce</ns1:uid>
-   <ns1:email>noot</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/1f9d2dc28329bd7ae2e426676bf3a6f3">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>1f9d2dc28329bd7ae2e426676bf3a6f3</ns1:uid>
-   <ns1:email>noot</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/20be613d2b8590d7565e47b1c712b548">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>20be613d2b8590d7565e47b1c712b548</ns1:uid>
-   <ns1:email>noot</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/2578f4174ea728ed9a0b4cc0d91c661a">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>2578f4174ea728ed9a0b4cc0d91c661a</ns1:uid>
-   <ns1:email>wim</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/fd135ec93f7566a7a9cad338a219f13f">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>fd135ec93f7566a7a9cad338a219f13f</ns1:uid>
-   <ns1:email>mies</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/5df5871a812dedab6cdc4ce8a3bd6113">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>5df5871a812dedab6cdc4ce8a3bd6113</ns1:uid>
-   <ns1:email>mies</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/6f2563b665865a2a885491f0599e0462">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>6f2563b665865a2a885491f0599e0462</ns1:uid>
-   <ns1:email>wim</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/905628f99785ee2a7f15bbd76ed8f2b8">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>905628f99785ee2a7f15bbd76ed8f2b8</ns1:uid>
-   <ns1:email>teun</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/4d89d76fea260fd7794a25a4156eb7d5">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>4d89d76fea260fd7794a25a4156eb7d5</ns1:uid>
-   <ns1:email>teun</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/1a33469e005d3dde1bcdabbed2011a17">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>1a33469e005d3dde1bcdabbed2011a17</ns1:uid>
-   <ns1:email>teun</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/f29a3d47f398ac48188fa7b3180c8aa6">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>f29a3d47f398ac48188fa7b3180c8aa6</ns1:uid>
-   <ns1:email>teun</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/f58b9e3942d793cf7ada3cf36cd3a4de">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>f58b9e3942d793cf7ada3cf36cd3a4de</ns1:uid>
-   <ns1:email>teun</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/f2dbe7ca68844c186ec1a348330640b5">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>f2dbe7ca68844c186ec1a348330640b5</ns1:uid>
-   <ns1:email>vuur</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
-<rdf:Description rdf:about="http://tbm.tudelft.nl/researchtool/resources/user/0cc6b4db5454824c15b02c7c27c944c1">
-   <ns1:resource_type rdf:resource="http://tbm.tudelft.nl/researchtool/resources/user"/>
-   <ns1:uid>0cc6b4db5454824c15b02c7c27c944c1</ns1:uid>
-   <ns1:email>vuur</ns1:email>
-   <ns1:password>noot</ns1:password>
-</rdf:Description>
-
 </rdf:RDF>
