Index: Dev/trunk/src/client/qed-client/app/Content.js
===================================================================
--- Dev/trunk/src/client/qed-client/app/Content.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/app/Content.js	(revision 490)
@@ -8,4 +8,5 @@
         _container: null,
         _previousContent: null,
+        _dirty: false,
         startup: function() {
             if ( this._started ) { return; }
@@ -32,6 +33,6 @@
             }
             widget.region = 'center';
+            this._previousContent = widget;
             this._container.addChild(widget);
-            this._previousContent = widget;
         },
         notify: function(text,type) {
@@ -40,4 +41,13 @@
             }
             this._toaster.setContent(text,type || 'message');
+        },
+        markDirty: function() {
+            this._dirty = true;
+        },
+        markClean:function() {
+            this._dirty = false;
+        },
+        isDirty: function() {
+            return this._dirty;
         }
     });
Index: Dev/trunk/src/client/qed-client/app/Page.js
===================================================================
--- Dev/trunk/src/client/qed-client/app/Page.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/app/Page.js	(revision 490)
@@ -1,10 +1,24 @@
 define([
-    'dojo/_base/declare',
-    'dijit/_TemplatedMixin',
-    'dijit/_WidgetsInTemplateMixin',
-    'dijit/layout/BorderContainer'
-],function(declare,_TemplatedMixin,_WidgetsInTemplateMixin,BorderContainer){
-    return declare([BorderContainer,_TemplatedMixin,_WidgetsInTemplateMixin],{
-        templateString: '<div>Empty page.</div>'
+    "./Content",
+    "./Path",
+    "dijit/_TemplatedMixin",
+    "dijit/_WidgetsInTemplateMixin",
+    "dijit/layout/BorderContainer",
+    "dojo/_base/declare",
+    "dojo/_base/lang",
+    "dojo/hash"
+], function(Content, Path, _TemplatedMixin, _WidgetsInTemplateMixin, BorderContainer, declare, lang, hash) {
+    var Page = declare([BorderContainer,_TemplatedMixin,_WidgetsInTemplateMixin],{
+        templateString: '<div>Empty page.</div>',
+        die: function(msg) {
+            Content.set(new Page({templateString:'<div>Error: '+msg+'</div>'}));
+        },
+        notify: lang.hitch(Content,'notify'),
+        setURL: function(url,opts,addToHistory) {
+            hash(Path.format(url,opts),addToHistory !== true);
+        },
+        markDirty: lang.hitch(Content,'markDirty'),
+        markClean: lang.hitch(Content,'markClean')
     });
+    return Page;
 });
Index: Dev/trunk/src/client/qed-client/app/Router.js
===================================================================
--- Dev/trunk/src/client/qed-client/app/Router.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/app/Router.js	(revision 490)
@@ -1,10 +1,14 @@
 define([
-    'dojo/_base/declare',
-    'dojo/hash',
-    'dojo/topic',
-    './Content',
-    './Page',
-    './Path'
-],function(declare,hash,topic,Content,Page,Path){
+    "./Content",
+    "./Page",
+    "./Path",
+    "dojo/_base/declare",
+    "dojo/_base/event",
+    "dojo/_base/lang",
+    "dojo/_base/window",
+    "dojo/hash",
+    "dojo/on",
+    "dojo/topic"
+], function(Content, Page, Path, declare, event, lang, window, hash, on, topic) {
 
     var Router = declare(null,{
@@ -12,4 +16,5 @@
         _routes: null,
         _previousHash: null,
+        _beforePreviousHash: null,
 
         constructor: function() {
@@ -18,18 +23,15 @@
         startup: function() {
             if ( this._started ) { return; }
-            if ( !Content._started ) {
-                Content.startup();
-            }
+            Content.startup();
             this._started = true;
-
-            var self = this;
-
             if ( hash() === "" ) {
                 hash(Path.getDefault());
             }
-            this._handlePathChange(hash());
-			topic.subscribe("/dojo/hashchange", function(){
-                self._handlePathChange.apply(self,arguments);
-            });
+            this._handleHashChange(hash());
+            window.onbeforeunload = function() {
+                return Content.isDirty() && "Unsaved changes, leave anyway?";
+            };
+			topic.subscribe("/dojo/hashchange",
+                            lang.hitch(this,'_handleHashChange'));
         },
         register: function(route) {
@@ -68,6 +70,22 @@
             return callback;
         },
-        _handlePathChange: function(newHash) {
-            if ( this._previousHash === newHash ) { return; }
+        _handleHashChange: function(newHash) {
+            if ( this._previousHash === newHash ) {
+                return false;
+            }
+            if ( Content.isDirty() ) {
+                if ( !confirm("Unsaved changes, leave anyway?") ) {
+                    var probablyBack = this._beforePreviousHash === newHash;
+                    // if we think we go backwards, we re-add the history
+                    // entry, otherwise we reset the current one,
+                    // resulting in minor annoyance of double back
+                    // behaviour.
+                    hash(this._previousHash,!probablyBack);
+                    return false;
+                } else {
+                    Content.markClean();
+                }
+            }
+            this._beforePreviousHash = this._previousHash;
             this._previousHash = newHash;
             for (var i = this._routes.length-1; i >= 0; i--) {
@@ -78,7 +96,7 @@
                         route.callback(params);
                     } catch(err) {
-                        console.error("Page change failed with",err,err.toString());
+                        console.error("Page change failed with",err,err.stack,err.toString());
                     }
-                    return;
+                    return true;
                 }
             }
@@ -88,9 +106,9 @@
                 console.error("Default page failed.",err);
             }
+            return true;
         },
         go: function(path,args) {
             if ( !this._started ) { return; }
             var newHash = Path.format(path,args);
-            this._handlePathChange(newHash);
             hash(newHash);
         },
Index: Dev/trunk/src/client/qed-client/css/dijit/overrides.less
===================================================================
--- Dev/trunk/src/client/qed-client/css/dijit/overrides.less	(revision 489)
+++ Dev/trunk/src/client/qed-client/css/dijit/overrides.less	(revision 490)
@@ -122,2 +122,6 @@
     background-color: #333333;
 }
+
+.claro .dijitSelect {
+    color: #000000;
+}
Index: Dev/trunk/src/client/qed-client/model/classes/_Class.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/_Class.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/model/classes/_Class.js	(revision 490)
@@ -27,8 +27,11 @@
         },
         load: function(id) {
-            return this._store.get(id).then(lang.hitch(this,'_doDeserialize'));
+            return this._store.get(id)
+            .then(lang.hitch(this,'_doDeserialize'),
+                  lang.hitch(this,'_deserializeError'));
         },
         save: function(obj) {
-            return this._store.put(this._doSerialize(obj));
+            return this._store.put(this._doSerialize(obj))
+            .otherwise(lang.hitch(this,'_deserializeError'));
         },
         remove: function(objOrId,rev) {
@@ -40,8 +43,17 @@
                 rev = this.getRev(objOrId);
             }
-            return this._store.remove(id,{headers:{'If-Match':'"'+rev+'"'}});
+            return this._store.remove(id,{headers:{'If-Match':'"'+rev+'"'}})
+            .otherwise(lang.hitch(this,'_deserializeError'));
         },
         getRev: function(obj) {
             return obj._rev;
+        },
+        getName: function() {
+            return this._type;
+        },
+        getObjectPath: function(idOrObj) {
+            return '/'+this._collection+'/'+(typeof idOrObj === "string" ?
+                                             idOrObj :
+                                             this.getId(idOrObj));
         }
     });
Index: Dev/trunk/src/client/qed-client/model/classes/_View.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/_View.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/model/classes/_View.js	(revision 490)
@@ -1,8 +1,10 @@
 define([
     "../../store/JsonRest",
+    "dojo/Deferred",
     "dojo/_base/declare",
+    "dojo/_base/json",
     "dojo/_base/lang",
     "dojo/store/util/QueryResults"
-], function(JsonRest, declare, lang, queryResults) {
+], function(JsonRest, Deferred, declare, json, lang, queryResults) {
 
     var _View = declare([],{
@@ -18,4 +20,7 @@
             });
         },
+        _deserializeError: function(err) {
+            return new Deferred().reject(json.fromJson(err.responseText));
+        },
         _doDeserialize: function(obj) {
             obj = lang.clone(obj);
@@ -30,4 +35,7 @@
         getId: function(obj) {
             return obj._id;
+        },
+        getCollectionPath: function() {
+            return '/'+this._collection;
         }
     });
Index: Dev/trunk/src/client/qed-client/model/classes/responses.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/responses.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/model/classes/responses.js	(revision 490)
@@ -43,7 +43,6 @@
                 handleAs: 'json',
                 contentType: false
-            }).then(lang.hitch(this,'_doDeserialize'),function(err){
-                return new Deferred().reject(json.fromJson(err.responseText));
-            });
+            }).then(lang.hitch(this,'_doDeserialize'),
+                    lang.hitch(this,'_deserializeError'));
         },
         postWithSecret: function(response,secret) {
@@ -55,7 +54,6 @@
                 contentType: 'application/json',
                 rawBody: body
-            }).then(lang.hitch(this,'_doDeserialize'),function(err){
-                return new Deferred().reject(json.fromJson(err.responseText));
-            });
+            }).then(lang.hitch(this,'_doDeserialize'),
+                    lang.hitch(this,'_deserializeError'));
         },
         putWithSecret: function(response,secret) {
@@ -67,7 +65,6 @@
                 contentType: 'application/json',
                 rawBody: body
-            }).then(lang.hitch(this,'_doDeserialize'),function(err){
-                return new Deferred().reject(json.fromJson(err.responseText));
-            });
+            }).then(lang.hitch(this,'_doDeserialize'),
+                    lang.hitch(this,'_deserializeError'));
         },
         removeWithSecret: function(response,secret) {
@@ -85,5 +82,5 @@
                 contentType: 'application/json',
                 rawBody: body
-            });
+            }).otherwise(lang.hitch(this,'_deserializeError'));
         }
     });
Index: Dev/trunk/src/client/qed-client/model/classes/surveys.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/surveys.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/model/classes/surveys.js	(revision 490)
@@ -26,4 +26,9 @@
                 obj.publicationDate = stamp.toISOString(obj.publicationDate);
             }
+        },
+        getPreviewPath: function(idOrObj) {
+            return '/previewSurvey/'+(typeof idOrObj === "string"?
+                                      idOrObj :
+                                      this.getId(idOrObj));
         }
     });
Index: Dev/trunk/src/client/qed-client/model/widgets/AccountListView.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/AccountListView.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/model/widgets/AccountListView.js	(revision 490)
@@ -23,5 +23,5 @@
                 actions: {
                     "Remove" : {
-                        callback: lang.hitch(this, 'removeItem', item),
+                        callback: lang.hitch(this, 'removeItem', item, true),
                         properties: {
                             blockButton: false,
Index: Dev/trunk/src/client/qed-client/model/widgets/CategoryListView.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/CategoryListView.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/model/widgets/CategoryListView.js	(revision 490)
@@ -25,5 +25,5 @@
                 actions: {
                     "Remove" : {
-                        callback: lang.hitch(this, 'removeItem', id),
+                        callback: lang.hitch(this, 'removeItem', id, true),
                         properties: {
                             blockButton: false,
Index: Dev/trunk/src/client/qed-client/model/widgets/QuestionEditorPreview.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/QuestionEditorPreview.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/model/widgets/QuestionEditorPreview.js	(revision 490)
@@ -24,5 +24,5 @@
             });
             this.own(previewItem.on('destroy',
-                                    lang.hitch(this,'removeItem',id)));
+                                    lang.hitch(this,'removeItem',id,true)));
             previewItem.startup();
             return previewItem;
Index: Dev/trunk/src/client/qed-client/model/widgets/QuestionListView.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/QuestionListView.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/model/widgets/QuestionListView.js	(revision 490)
@@ -23,5 +23,5 @@
                 actions: {
                     "Remove" : {
-                        callback: lang.hitch(this, 'removeItem', id),
+                        callback: lang.hitch(this, 'removeItem', id, true),
                         properties: {
                             blockButton: false,
Index: Dev/trunk/src/client/qed-client/model/widgets/SurveySummary.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/SurveySummary.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/model/widgets/SurveySummary.js	(revision 490)
@@ -1,3 +1,4 @@
 define([
+    "../classes/surveys",
     "dijit/_TemplatedMixin",
     "dijit/_WidgetBase",
@@ -5,5 +6,5 @@
     "dojo/dom-attr",
     "dojo/text!./templates/SurveySummary.html"
-], function(_TemplatedMixin, _WidgetBase, declare, domAttr, template) {
+], function(surveys, _TemplatedMixin, _WidgetBase, declare, domAttr, template) {
     return declare([_WidgetBase,_TemplatedMixin],{
         templateString: template,
@@ -17,5 +18,5 @@
         _setValueAttr: function(survey) {
             this.titleNode.innerHTML = survey.title || "";
-            domAttr.set(this.titleNode, "href", survey._id && ("#!/survey/"+survey._id));
+            domAttr.set(this.titleNode, "href", survey && surveys.getObjectPath(survey));
             this.descriptionNode.innerHTML = survey.description;
             this.questionsNode.innerHTML = survey.questions.length;
Index: Dev/trunk/src/client/qed-client/model/widgets/TabbedQuestionBrowser.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/TabbedQuestionBrowser.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/model/widgets/TabbedQuestionBrowser.js	(revision 490)
@@ -24,8 +24,4 @@
             this.inherited(arguments);
             this._dataMap = {};
-        },
-        postCreate: function() {
-            this.inherited(arguments);
-            this._query = '_design/questions/_view/'+this.include;
         },
         startup: function() {
Index: Dev/trunk/src/client/qed-client/model/widgets/questions/MultipleChoiceInputConfigWidget.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/questions/MultipleChoiceInputConfigWidget.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/model/widgets/questions/MultipleChoiceInputConfigWidget.js	(revision 490)
@@ -37,6 +37,6 @@
                 value: item,
                 onDestroy: lang.hitch(this,function(evt){
-                    this.itemsWidget.removeItem(id);
-                    event.stop(evt);
+                    this.itemsWidget.removeItem(id,true);
+                    if ( evt ) { event.stop(evt); }
                     return false;
                 })
@@ -61,6 +61,6 @@
         },
         onAddItem: function(evt) {
-            this.itemsWidget.appendItem({});
-            event.stop(evt);
+            this.itemsWidget.appendItem({},true);
+            if ( evt ) { event.stop(evt); }
             return false;
         }
Index: Dev/trunk/src/client/qed-client/model/widgets/questions/ScaleInputConfigWidget.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/questions/ScaleInputConfigWidget.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/model/widgets/questions/ScaleInputConfigWidget.js	(revision 490)
@@ -61,6 +61,6 @@
                 id: id,
                 onDestroy: lang.hitch(this,function(evt){
-                    this.itemsWidget.removeItem(id);
-                    event.stop(evt);
+                    this.itemsWidget.removeItem(id,true);
+                    if ( evt ) { event.stop(evt); }
                     return false;
                 })
@@ -75,6 +75,6 @@
         },
         onAddNewItem: function(e) {
-            this.itemsWidget.appendItem({});
-            event.stop(e);
+            this.itemsWidget.appendItem({},true);
+            if ( e ) { event.stop(e); }
             return false;
         },
Index: Dev/trunk/src/client/qed-client/pages/index.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/index.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/pages/index.js	(revision 490)
@@ -1,8 +1,10 @@
 define([
-    'dojo/_base/declare',
-    '../app/Router',
-    '../app/Page',
-    'dojo/text!./templates/index.html'
-],function(declare,Router,Page,template){
+    "../app/Page",
+    "../app/Router",
+    "../model/classes/questions",
+    "../model/classes/surveys",
+    "dojo/_base/declare",
+    "dojo/text!./templates/index.html"
+], function(Page, Router, questions, surveys, declare, template) {
     return declare([Page],{
         templateString: template,
@@ -11,11 +13,15 @@
             if ( this._started ) { return; }
             this.inherited(arguments);
-            this.btnContentCreate.on("click",function(){ Router.go("/sessions"); });
-            this.btnContentFacilitate.on("click",function(){ Router.go("/run"); });
-            this.btnSurveys.on("click",function(){ Router.go("/surveys"); });
-            this.btnQuestions.on("click",function(){ Router.go("/questions"); });
-            this.btnApplications.on("click",function(){ Router.go("/applications"); });
-            this.btnDashboards.on("click",function(){ Router.go("/dashboards"); });
-            this.btnResults.on("click",function(){ Router.go("/results"); });
+            //this.btnContentCreate.on("click",function(){ Router.go("/sessions"); });
+            //this.btnContentFacilitate.on("click",function(){ Router.go("/run"); });
+            this.btnSurveys.on("click",function(){
+                Router.go(surveys.getCollectionPath());
+            });
+            this.btnQuestions.on("click",function(){
+                Router.go(questions.getCollectionPath());
+            });
+            //this.btnApplications.on("click",function(){Router.go("/applications");});
+            //this.btnDashboards.on("click",function(){ Router.go("/dashboards"); });
+            //this.btnResults.on("click",function(){ Router.go("/results"); });
         }
     });
Index: Dev/trunk/src/client/qed-client/pages/question.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/question.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/pages/question.js	(revision 490)
@@ -1,78 +1,74 @@
 define([
-    "../app/Content",
-    "../app/Page",
     "../app/Router",
     "../model/classes/questions",
-    "../model/widgets/QuestionEditorPreview",
-    "../model/widgets/QuestionEditorToolkit",
-    "../widgets/_ComplexValueMixin",
+    "./_ObjectPage",
+    "dojo/Deferred",
     "dojo/_base/declare",
     "dojo/_base/event",
     "dojo/_base/lang",
-    "dojo/when",
+    "require",
     "dojo/text!./templates/question.html"
-], function(Content, Page, Router, questions, QuestionEditorPreview, QuestionEditorToolkit, _ComplexValueMixin, declare, event, lang, when, template) {
-    return declare([Page,_ComplexValueMixin], {
+], function(Router, questions, _ObjectPage, Deferred, declare, event, lang, require, template) {
+    return declare([_ObjectPage], {
+        contextRequire: require,
         templateString: template,
         _toolkit: null,
         _preview: null,
-        value: null,
-        
-        buildRendering: function() {
-            this.inherited(arguments);
-
-            this._toolkit = new QuestionEditorToolkit({
-            },this.QuestionEditorToolkitNode);
-            this._toolkit.on('submit',lang.hitch(this,"_onSave"));
-            this._toolkit.startup();
-
-            this._preview = new QuestionEditorPreview({ 
-                name: 'content',
-                delay: 5,
-                region: 'center'
-            });
-            this._preview.startup();
-            this.addChild(this._preview);
-        },
+        classStore: questions,
         startup: function() {
             if ( this._started ) { return; }
             this.inherited(arguments);
-            if ( !this.questionId ) {
-                throw new Error("Error: no reference to object set!");
+            this.propertiesForm.on('change',lang.hitch(this,'_handlePropertiesChange'));
+            this.contentList.on('change',lang.hitch(this,'_handleContentChange'));
+            this._load();
+        },
+        _refresh: function() {
+            this.titleNode.innerHTML = this.object.title || "";
+            this.propertiesForm.set('value',this.object);
+            this.contentList.set('value',this.object.content);
+        },
+        _handlePropertiesChange: function() {
+            if ( this.propertiesForm.validate() ) {
+                lang.mixin(this.object,this.propertiesForm.get('value'));
             }
-            if (this.questionId === "new") {
-                this.set('value', questions.create());
+            this.markDirty();
+        },
+        _handleContentChange: function() {
+            if ( this.contentList.validate() ) {
+                this.object.content = this.contentList.get('value');
+            }
+            this.markDirty();
+        },
+        _save: function() {
+            if ( this.propertiesForm.validate() && this.contentList.validate() ) {
+                lang.mixin(this.object,this.propertiesForm.get('value'));
+                this.object.content = this.contentList.get('value');
+                return this.inherited(arguments);
             } else {
-                when(questions.load(this.questionId))
-                .then(lang.hitch(this, function(value) {
-                    this.set('value', value);
-                }));
+                return new Deferred().reject();
             }
         },
-        _setValueAttr: function(value) {
-            this.value = value;
-            this.inherited(arguments);
-            this.titleNode.innerHTML = value.title || "";
-        },
-        _getValueAttr: function() {
-            var value = this.inherited(arguments);
-            lang.mixin(this.value, value);
-            return this.value;
-        },
         _onSave: function(evt) {
-            if ( this.validate() ) {
-                questions.save(this.get('value'))
-                .then(function() {
-                    Router.go('/questions');
-                },function(err){
-                    Content.notify(err,'error');
-                });
-            }
+            this._save();
             if ( evt ) { event.stop( evt ); }
             return false;
         },
-        _onDiscard: function() {
-            Router.go('/questions');
-            return true;
+        _onSaveAndClose: function(evt) {
+            this._save()
+            .then(function(){
+                Router.go(questions.getCollectionPath());
+            });
+            if ( evt ) { event.stop( evt ); }
+            return false;
+        },
+        _onDiscard: function(evt) {
+            this.markClean();
+            Router.go(questions.getCollectionPath());
+            if ( evt ) { event.stop( evt ); }
+            return false;
+        },
+        _ignore: function(evt) {
+            if ( evt ) { event.stop( evt ); }
+            return false;
         }
     });
Index: Dev/trunk/src/client/qed-client/pages/questions.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/questions.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/pages/questions.js	(revision 490)
@@ -1,4 +1,3 @@
 define([
-    "../app/Content",
     "../app/Page",
     "../app/Router",
@@ -10,5 +9,5 @@
     "dojo/_base/lang",
     "dojo/text!./templates/questions.html"
-], function(Content, Page, Router, questions, TabbedQuestionBrowser, Deferred, declare, event, lang, template) {
+], function(Page, Router, questions, TabbedQuestionBrowser, Deferred, declare, event, lang, template) {
     return declare([Page],{
         templateString: template,
@@ -41,25 +40,25 @@
         },
         onNewQuestion: function() {
-            Router.go("/question/new");
+            Router.go(questions.getObjectPath('new'));
         },
         onDeleteQuestion: function(question) {
             questions.remove(question)
-            .then(function(){
-                Content.notify("Question deleted.");
-            },function(err){
-                Content.notify(err,'error');
-            });
+            .then(lang.hitch(this,function(){
+                this.notify("Question deleted.");
+            }),lang.hitch(this,function(err){
+                this.notify(err.error,'error');
+            }));
         },
         onEditQuestion: function(question) {
-            Router.go("/question/"+question._id);
+            Router.go(questions.getObjectPath(question));
         },
         onPublishQuestion: function(question) {
             question.publicationDate = new Date();
             questions.save(question)
-            .then(function(){
-                Content.notify("Question published.");
-            },function(err){
-                Content.notify(err,'error');
-            });
+            .then(lang.hitch(this,function(){
+                this.notify("Question published.");
+            }),lang.hitch(this,function(err){
+                this.notify(err.error,'error');
+            }));
         }
     });
Index: Dev/trunk/src/client/qed-client/pages/response.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/response.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/pages/response.js	(revision 490)
@@ -1,6 +1,4 @@
 define([
-    "../app/Content",
     "../app/Page",
-    "../lib/async",
     "../model/classes/responses",
     "dojo/_base/declare",
@@ -13,5 +11,5 @@
     "require",
     "dojo/text!./templates/response.html"
-], function(Content, Page, async, responses, declare, event, json, lang, all, request, when, require, template) {
+], function(Page, responses, declare, event, json, lang, all, request, when, require, template) {
     return declare([Page],{
         contextRequire: require,
@@ -60,8 +58,8 @@
             .then(lang.hitch(this,function(response){
                 this.response = response;
-                Content.notify("Your response is saved.");
-            }), function(err){
-                Content.notify(err,'error');
-            });
+                this.notify("Your response is saved.");
+            }), lang.hitch(this,function(err){
+                this.notify(err.error,'error');
+            }));
         },
         _onSubmit: function(e) {
@@ -89,8 +87,8 @@
             .then(lang.hitch(this,function(res){
                 this._showInfo("<div>Your response has been deleted, no answers have been saved.</div>");
-                Content.notify("Your response is deleted.");
-            }), function(err){
-                Content.notify(err,'error');
-            });
+                this.notify("Your response is deleted.");
+            }), lang.hitch(this,function(err){
+                this.notify(err.error,'error');
+            }));
             if ( e ) { event.stop(e); }
             return false;
Index: Dev/trunk/src/client/qed-client/pages/survey.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/survey.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/pages/survey.js	(revision 490)
@@ -1,8 +1,8 @@
 define([
-    "../app/Page",
     "../app/Router",
     "../model/classes/surveys",
     "../model/widgets/QuestionListView",
     "../model/widgets/TabbedQuestionBrowser",
+    "./_ObjectPage",
     "dojo/_base/array",
     "dojo/_base/declare",
@@ -12,20 +12,16 @@
     "require",
     "dojo/text!./templates/survey.html"
-], function(Page, Router, surveys, QuestionListView, TabbedQuestionBrowser, array, declare, event, lang, when, require, template) {
-    return declare([Page],{
+], function(Router, surveys, QuestionListView, TabbedQuestionBrowser, _ObjectPage, array, declare, event, lang, when, require, template) {
+    return declare([_ObjectPage],{
         contextRequire: require,
         templateString: template,
-        survey: null,
+        classStore: surveys,
         questionList: null,
         startup: function() {
             if ( this._started ) { return; }
             this.inherited(arguments);
-            if ( this.surveyId ) {
-                this._setupQuestionBrowser();
-                this._setupListView();
-                this._loadSurvey();
-            } else {
-                throw "No valid uid or survey passed!";
-            }
+            this._setupQuestionBrowser();
+            this._setupListView();
+            this._load();
         },
         _setupQuestionBrowser: function() {
@@ -60,55 +56,55 @@
             this.questionList.startup();
         },
-        _loadSurvey: function() {
-            if ( this.surveyId === "new" ) {
-                this.survey = surveys.create();
-                this.refresh();
-            } else {
-                when(surveys.load(this.surveyId))
-                .then(lang.hitch(this,function(survey){
-                    this.survey = survey;
-                    this.questionList.set('value',
-                                          this.survey.questions);
-                    this.refresh();
-                }));
-            }
+        _refresh: function() {
+            this.titleNode.innerHTML = this.object.title || "(set title in properties)";
+            this.propertiesDialog.set('value',this.object);
+            this.questionList.set('value',
+                                  this.object.questions);
+        },
+        _save: function() {
+            this.object.questions = this.questionList.get('value');
+            return this.inherited(arguments);
         },
         _includeQuestion: function(question) {
             this.questionList.appendItem(question);
         },
-        refresh: function() {
-            this.titleNode.innerHTML = this.survey.title || "(set title in properties)";
-            this.propertiesDialog.set('value',this.survey);
-        },
         _onShowProperties: function(evt) {
             this.propertiesDialog.show();
+            if ( evt ) { event.stop(evt); }
+            return false;
         },
         _onPropertiesOk: function(evt) {
             this.propertiesDialog.hide();
-            lang.mixin(this.survey, this.propertiesDialog.get('value'));
-            this.refresh();
-            event.stop(evt);
+            lang.mixin(this.object, this.propertiesDialog.get('value'));
+            this.markDirty();
+            this._refresh();
+            if ( evt ) { event.stop(evt); }
             return false;
         },
         _onPropertiesCancel: function(evt) {
             this.propertiesDialog.hide();
-            this.propertiesDialog.reset('value',this.survey);
-            event.stop(evt);
+            this.propertiesDialog.set('value',this.object);
+            if ( evt ) { event.stop(evt); }
             return false;
         },
         _onSave: function(evt) {
-            this.survey.questions = this.questionList.get('value');
-            surveys.save(this.survey)
+            this._save();
+            if ( evt ) { event.stop(evt); }
+            return false;
+        },
+        _onSaveAndClose: function(evt) {
+            this._save()
             .then(function() { 
-                Router.go('/surveys');
+                Router.go(surveys.getCollectionPath());
             });
             event.stop(evt);
             return false;
         },
-        _onDiscard: function(evt) {
-            Router.go('/surveys');
+        _onDiscardAndClose: function(evt) {
+            this.markClean();
+            Router.go(surveys.getCollectionPath());
         },
         _onShowPreview: function() {
-            Router.go('/previewSurvey/'+this.survey._id,{
+            Router.go(surveys.getPreviewPath(this.object),{
                 preview: true
             });
Index: Dev/trunk/src/client/qed-client/pages/surveyRun.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/surveyRun.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/pages/surveyRun.js	(revision 490)
@@ -1,10 +1,13 @@
 define([
     "../app/Content",
-    "../app/Page",
+    "../app/Path",
     "../app/Router",
     "../lib/func",
     "../model/classes/responses",
     "../model/classes/surveyRuns",
+    "../model/classes/surveys",
     "../widgets/LineWithActionsWidget",
+    "./_ObjectPage",
+    "dojo/Deferred",
     "dojo/_base/array",
     "dojo/_base/declare",
@@ -14,35 +17,33 @@
     "require",
     "dojo/text!./templates/surveyRun.html"
-], function(Content, Page, Router, func, responses, surveyRuns, LineWithActionsWidget, array, declare, event, lang, when, require, template) {
-    return declare([Page],{
+], function(Content, Path, Router, func, responses, surveyRuns, surveys, LineWithActionsWidget, _ObjectPage, Deferred, array, declare, event, lang, when, require, template) {
+    return declare([_ObjectPage],{
         contextRequire: require,
         templateString: template,
-        surveyRun: null,
+        classStore: surveyRuns,
         startup: function() {
             if ( this._started ) { return; }
             this.inherited(arguments);
-            this.surveyRunWidget.on("blur",lang.hitch(this,'_onPropChange'));
-            if ( this.surveyRunId ) {
-                this._loadSurveyRun();
+            this.surveyRunWidget.on("change",lang.hitch(this,'_onPropChange'));
+            this._load();
+        },
+        _refresh: function() {
+            this.titleNode.innerHTML = this.object.title || "";
+            this.surveySummaryWidget.set('value',this.object.survey);
+            this.surveyRunWidget.set('value',this.object);
+            this._refreshURL();
+            this._loadResponses();
+        },
+        _refreshURL: function() {
+            if ( this.object.mode === "open" ) {
+                this.runURLNode.innerHTML =
+                    this._link(this._buildGeneralURL(this.object));
             } else {
-                throw "No valid uid or survey passed!";
+                this.runURLNode.innerHTML =
+                    "No general URL. Add individual respondents below.";
             }
         },
-        _loadSurveyRun: function() {
-            when(surveyRuns.load(this.surveyRunId))
-            .then(lang.hitch(this,function(surveyRun){
-                this.surveyRun = surveyRun;
-                this.refreshSurveyRun();
-                this._loadResponses();
-            }));
-        },
-        refreshSurveyRun: function() {
-            this.titleNode.innerHTML = this.surveyRun.title || "";
-            this.surveySummaryWidget.set('value',this.surveyRun.survey);
-            this.surveyRunWidget.set('value',this.surveyRun);
-            this._onPropChange();
-        },
         _loadResponses: function() {
-            responses.query({surveyRunId:surveyRuns.getId(this.surveyRun)})
+            responses.query({surveyRunId:surveyRuns.getId(this.object)})
             .then(lang.hitch(this,function(allResponses){
                 array.forEach(allResponses, function(response){
@@ -73,38 +74,43 @@
         },
         _onPropChange: function(e) {
-            var surveyRun = this.surveyRunWidget.get('value');
-            if ( surveyRun.mode === "open" ) {
-                this.runURLNode.innerHTML =
-                    this._link(this._buildGeneralURL(this.surveyRun));
-            } else {
-                this.runURLNode.innerHTML =
-                    "No general URL. Add individual respondents below.";
+            if ( this.surveyRunWidget.validate() ) {
+                lang.mixin(this.object,this.surveyRunWidget.get('value'));
+                this._refreshURL();
             }
+            this.markDirty();
         },
         _buildGeneralURL: function(surveyRun) {
-            return 'response.html#!/surveyRuns/'+surveyRuns.getId(surveyRun)+'!secret='+surveyRun.secret;
+            return 'response.html#'+Path.format(surveyRuns.getObjectPath(surveyRun),{secret:surveyRun.secret});
         },
         _buildResponseURL: function(response) {
-            return 'response.html#!/responses/'+responses.getId(response)+'!secret='+response.secret;
+            return 'response.html#'+Path.format(responses.getObjectPath(response),{secret:response.secret});
         },
         _link: function(url,label) {
             return '<a target="_blank" href="'+url+'">'+(label || url)+'</a>';
         },
+        _save: function() {
+            if ( this.surveyRunWidget.validate() ) {
+                lang.mixin(this.object,this.surveyRunWidget.get('value'));
+                return this.inherited(arguments);
+            } else {
+                return new Deferred.reject();
+            }
+        },
         _onSave: function(evt) {
-            if ( this.surveyRunWidget.validate() ) {
-                lang.mixin(this.surveyRun,this.surveyRunWidget.get('value'));
-
-                surveyRuns.save(this.surveyRun)
-                .then(function() { 
-                    Router.go('/surveys');
-                },function(err){
-                    Content.notify(err);
-                });
-            }
+            this._save();
+            if ( evt ) { event.stop(evt); }
+            return false;
+        },
+        _onSaveAndClose: function(evt) {
+            this._save()
+            .then(function() { 
+                Router.go(surveys.getCollectionPath());
+            });
             if ( evt ) { event.stop(evt); }
             return false;
         },
         _onDiscard: function(evt) {
-            Router.go('/surveys');
+            this.markClean();
+            Router.go(surveys.getCollectionPath());
             if ( evt ) { event.stop(evt); }
             return false;
Index: Dev/trunk/src/client/qed-client/pages/surveys.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/surveys.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/pages/surveys.js	(revision 490)
@@ -1,8 +1,7 @@
 define([
-    "../app/Content",
     "../app/Page",
     "../app/Router",
+    "../model/classes/surveyRuns",
     "../model/classes/surveys",
-    "../model/classes/surveyRuns",
     "../widgets/LineWithActionsWidget",
     "dojo/_base/array",
@@ -11,5 +10,5 @@
     "dojo/when",
     "dojo/text!./templates/surveys.html"
-], function(Content, Page, Router, surveys, surveyRuns, LineWithActionsWidget, array, declare, lang, when, template) {
+], function(Page, Router, surveyRuns, surveys, LineWithActionsWidget, array, declare, lang, when, template) {
     return declare([Page],{
         templateString: template,
@@ -20,5 +19,5 @@
         },
         _onNewSurvey: function(){
-            Router.go('/survey/new');
+            Router.go(surveys.getObjectPath('new'));
         },
         _onPublishSurvey:function(survey){
@@ -29,7 +28,7 @@
                 self.refreshDrafts();
                 self.refreshPublished();
-            },function(err){
-                Content.notify(err,'error');
-            });
+            },lang.hitch(this,function(err){
+                this.notify(err.error,'error');
+            }));
         },
         _onDeleteSurvey:function(survey){
@@ -38,13 +37,13 @@
             .then(function(){
                 self.refreshDrafts();
-            },function(err){
-                Content.notify(err,'error');
-            });
+            },lang.hitch(this,function(err){
+                this.notify(err.error,'error');
+            }));
         },
         _onEditSurvey:function(survey){
-            Router.go('/survey/'+survey._id);
+            Router.go(surveys.getObjectPath(survey));
         },
         _onPreviewSurvey:function(survey){
-            Router.go('/previewSurvey/'+survey._id);
+            Router.go(surveys.getPreviewPath(survey));
         },
         _onRunSurvey:function(survey){
@@ -54,10 +53,10 @@
             .then(lang.hitch(this,function(surveyRun){
                 this._onRunDetails(surveyRun);
-            }),function(err){
-                Content.notify(err);
-            });
+            }),lang.hitch(this,function(err){
+                this.notify(err.error,'error');
+            }));
         },
         _onRunDetails: function(surveyRun) {
-            Router.go('/surveyRun/'+surveyRun._id);
+            Router.go(surveyRuns.getObjectPath(surveyRun));
         },
         refresh: function() {
Index: Dev/trunk/src/client/qed-client/pages/templates/question.html
===================================================================
--- Dev/trunk/src/client/qed-client/pages/templates/question.html	(revision 489)
+++ Dev/trunk/src/client/qed-client/pages/templates/question.html	(revision 490)
@@ -1,3 +1,3 @@
-<form class="orange">
+<div class="orange">
     <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'top'">
         <h2>
@@ -6,12 +6,31 @@
         </h2>
     </div>
-    <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="region:'left', design:'headline'" style="width: 300px;">
-        <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'">
-            <div data-dojo-attach-point="QuestionEditorToolkitNode"></div>
+    <form data-dojo-type="dijit/form/Form"
+         data-dojo-props="region:'left'"
+         data-dojo-attach-point="propertiesForm"
+         data-dojo-attach-event="onSubmit:_ignore">
+        <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'" style="width: 300px;">
+            <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'">
+                <div data-dojo-type="../model/widgets/QuestionEditorToolkit"
+                     data-dojo-attach-point="QuestionEditorToolkitNode"></div>
+            </div>
+            <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'top'">
+                <button data-dojo-type="dijit/form/Button"
+                        data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconAccept'"
+                        data-dojo-attach-event="onClick:_onSave">
+                  Save</button>
+                <button data-dojo-type="dijit/form/Button"
+                        data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconAccept'"
+                        data-dojo-attach-event="onClick:_onSaveAndClose">
+                  Save &amp; Close</button>
+                <button data-dojo-type="dijit/form/Button"
+                        data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconCancel'"
+                        data-dojo-attach-event="onClick:_onDiscard">
+                  Discard &amp; Close</button>
+            </div>
         </div>
-        <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'top'">
-            <button data-dojo-type="dijit/form/Button" data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconCancel'" data-dojo-attach-event="onClick:_onDiscard">Discard</button>
-            <button data-dojo-type="dijit/form/Button" data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconAccept'" data-dojo-attach-event="onClick:_onSave">Save and exit</button>
-        </div>
-    </div>
-</form>
+    </form>
+    <div data-dojo-type="../model/widgets/QuestionEditorPreview"
+         data-dojo-attach-point="contentList"
+         data-dojo-props="name:'content',delay:5,region:'center'"></div>
+</div>
Index: Dev/trunk/src/client/qed-client/pages/templates/survey.html
===================================================================
--- Dev/trunk/src/client/qed-client/pages/templates/survey.html	(revision 489)
+++ Dev/trunk/src/client/qed-client/pages/templates/survey.html	(revision 490)
@@ -24,9 +24,13 @@
                     data-dojo-attach-event="onClick:_onSave"
                     data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconAccept'">
-                Save Changes</button>
+                Save</button>
             <button data-dojo-type="dijit/form/Button"
-                    data-dojo-attach-event="onClick:_onDiscard"
+                    data-dojo-attach-event="onClick:_onSaveAndClose"
+                    data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconAccept'">
+                Save &amp; Close</button>
+            <button data-dojo-type="dijit/form/Button"
+                    data-dojo-attach-event="onClick:_onDiscardAndClose"
                     data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconCancel'">
-                Discard changes</button>
+                Discard &amp; Close</button>
             <button data-dojo-type="dijit/form/Button"
                     data-dojo-attach-event="onClick:_onShowPreview"
Index: Dev/trunk/src/client/qed-client/pages/templates/surveyRun.html
===================================================================
--- Dev/trunk/src/client/qed-client/pages/templates/surveyRun.html	(revision 489)
+++ Dev/trunk/src/client/qed-client/pages/templates/surveyRun.html	(revision 490)
@@ -45,5 +45,5 @@
             <div>
                 <div class="qedLabel">Export results</div>
-                <a target="_blank" href="/api/surveyRuns/${surveyRunId}/responses.csv" class="qedField">To CSV</a>
+                <a target="_blank" href="/api/surveyRuns/${objectId}/responses.csv" class="qedField">To CSV</a>
             </div>
         </fieldset>
@@ -55,5 +55,9 @@
                 class="blue"
                 data-dojo-props="baseClass: 'rftBlockButton', iconClass: 'rftIcon rftIconSave'"
-                data-dojo-attach-event="onClick:_onSave">Save &amp; Close</button>
+                data-dojo-attach-event="onClick:_onSave">Save</button>
+        <button data-dojo-type="dijit/form/Button"
+                class="blue"
+                data-dojo-props="baseClass: 'rftBlockButton', iconClass: 'rftIcon rftIconSave'"
+                data-dojo-attach-event="onClick:_onSaveAndClose">Save &amp; Close</button>
         <button data-dojo-type="dijit/form/Button"
                 class="blue"
Index: Dev/trunk/src/client/qed-client/response.js
===================================================================
--- Dev/trunk/src/client/qed-client/response.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/response.js	(revision 490)
@@ -42,5 +42,5 @@
 
     function setContent(response) {
-        hash(Path.format("/responses/"+responses.getId(response),
+        hash(Path.format(responses.getObjectPath(response),
                          {secret:response.secret}));
         Content.set(new ResponsePage({
Index: Dev/trunk/src/client/qed-client/routes.js
===================================================================
--- Dev/trunk/src/client/qed-client/routes.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/routes.js	(revision 490)
@@ -1,3 +1,6 @@
 define([
+    "./model/classes/questions",
+    "./model/classes/surveyRuns",
+    "./model/classes/surveys",
     "./pages/index",
     "./pages/previewSurvey",
@@ -7,17 +10,17 @@
     "./pages/surveyRun",
     "./pages/surveys"
-], function(index, previewSurvey, question, questions, survey, surveyRun, surveys) {
+], function(questionsClass, surveyRunsClass, surveysClass, index, previewSurvey, question, questions, survey, surveyRun, surveys) {
 
     return [
         { path: "/", redirect: "/index" },
         { path: "/index", constructor: index },
-        { path: "/questions", constructor: questions },
-        { path: "/question/:questionId", constructor: question },
-        { path: "/surveys", constructor: surveys },
-        { path: "/survey/:surveyId", constructor: survey },
-        { path: "/surveyRun/:surveyRunId", constructor: surveyRun },
+        { path: questionsClass.getCollectionPath(), constructor: questions },
+        { path: questionsClass.getObjectPath(':objectId'), constructor: question },
+        { path: surveysClass.getCollectionPath(), constructor: surveys },
+        { path: surveysClass.getObjectPath(':objectId'), constructor: survey },
+        { path: surveyRunsClass.getObjectPath(':objectId'), constructor: surveyRun },
         //{ path: "/sessions", constructor: sessions },
         //{ path: "/session/:sessionId", constructor: session },
-        { path: "/previewSurvey/:surveyId", constructor: previewSurvey }
+        { path: surveysClass.getPreviewPath(':surveyId'), constructor: previewSurvey }
     ];
 
Index: Dev/trunk/src/client/qed-client/stddeps.js
===================================================================
--- Dev/trunk/src/client/qed-client/stddeps.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/stddeps.js	(revision 490)
@@ -28,4 +28,7 @@
     './app/Notifications',
 
+    './model/widgets/QuestionEditorPreview',
+    './model/widgets/QuestionEditorToolkit',
+    './model/widgets/AccountListView',
     './model/widgets/AccountListView',
     './model/widgets/SurveyRenderWidget',
Index: Dev/trunk/src/client/qed-client/widgets/LineWithActionsWidget.js
===================================================================
--- Dev/trunk/src/client/qed-client/widgets/LineWithActionsWidget.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/widgets/LineWithActionsWidget.js	(revision 490)
@@ -44,5 +44,5 @@
                             onClick: lang.hitch(this, function(action, e){
                                 if ( action.callback ) { action.callback(e); }
-                                event.stop(e);
+                                if ( e ) { event.stop(e); }
                                 return false;
                             }, this.actions[action])
@@ -58,5 +58,5 @@
                             onClick: lang.hitch(this, function(action, e){
                                 if ( action.callback ) { action.callback(e); }
-                                event.stop(e);
+                                if ( e ) { event.stop(e); }
                                 return false;
                             }, this.actions[action])
@@ -73,5 +73,5 @@
             var preventDefault = this.onClick(e) === false;
             if (preventDefault) {
-                event.stop(e);
+                if ( e ) { event.stop(e); }
             }
             return !preventDefault;
Index: Dev/trunk/src/client/qed-client/widgets/ListWidget.js
===================================================================
--- Dev/trunk/src/client/qed-client/widgets/ListWidget.js	(revision 489)
+++ Dev/trunk/src/client/qed-client/widgets/ListWidget.js	(revision 490)
@@ -8,6 +8,7 @@
     "dojo/dnd/Source",
     "dojo/dnd/common",
-    "dojo/dom-construct"
-], function(_Container, _WidgetBase, registry, array, declare, lang, Source, dnd, domConstruct) {
+    "dojo/dom-construct",
+    "dojo/on"
+], function(_Container, _WidgetBase, registry, array, declare, lang, Source, dnd, domConstruct, on) {
     return declare([_WidgetBase,_Container],{
         name: "",
@@ -49,4 +50,5 @@
             });
             this.source = new this.container(this.domNode,sourceParams);
+            this.source.on('Drop',lang.hitch(this,'_handleChange'));
         },
         creator: function(item, hint) {
@@ -66,4 +68,5 @@
                 }
             }
+            on(nodeOrWidget,'change',lang.hitch(this,'_handleChange'));
             var node = nodeOrWidget.domNode ? nodeOrWidget.domNode : nodeOrWidget;
             if ( hint !== "avatar" && node.id !== id ) {
@@ -79,5 +82,5 @@
         createListElement: null, /* function(id,item){},*/
         _getValueAttr: function() {
-            return array.map(this.source.getAllNodes(),function(node){
+            this.value = array.map(this.source.getAllNodes(),function(node){
                 var widget = registry.byNode(node);
                 if ( widget && "value" in widget ) {
@@ -87,4 +90,5 @@
                 }
             },this);
+            return this.value;
         },
         _setValueAttr: function(value) {
@@ -110,15 +114,18 @@
             }
         },
-        appendItems: function(items) {
+        appendItems: function(items,forceEvent) {
             this.source.insertNodes(false,items);
+            if ( forceEvent ) { this._handleChange(); }
         },
-        appendItem: function(item) {
+        appendItem: function(item,forceEvent) {
             this.source.insertNodes(false,[item]);
+            if ( forceEvent ) { this._handleChange(); }
         },
-        removeItem: function(key) {
+        removeItem: function(key,forceEvent) {
             array.forEach(array.filter(this.source.getAllNodes(), function(node){
                 return node.id === key;
             }), lang.hitch(this, "_destroyNodeOrWidget"));
             this.source.delItem(key);
+            if ( forceEvent ) { this._handleChange(); }
         },
         getChildren: function() {
@@ -127,8 +134,9 @@
             }),function(widget){ return widget !== null; });
         },
-        clear: function() {
+        clear: function(forceEvent) {
             array.forEach(this.source.getAllNodes(),
                           lang.hitch(this, "_destroyNodeOrWidget"));
             this.source.clearItems();
+            if ( forceEvent ) { this._handleChange(); }
         },
         _destroyNodeOrWidget: function(node) {
@@ -149,5 +157,10 @@
             this.source.destroy();
             this.inherited(arguments);
-        }
+        },
+        _handleChange: function() {
+            this.value = this._getValueAttr();
+            this.onChange(this.value);
+        },
+        onChange: function(value) {}
     });
 });
Index: Dev/trunk/src/server/app.js
===================================================================
--- Dev/trunk/src/server/app.js	(revision 489)
+++ Dev/trunk/src/server/app.js	(revision 490)
@@ -149,6 +149,5 @@
     function identity(obj) { return obj; }
     function handleUnknownResponse(status,error){
-        return new HTTPResult(500,{error: "Unexpected database response",
-                                   innerStatus: status, innerResponse: error});
+        return new HTTPResult(500,{error: error.reason});
     }
     function handleUnknownError(error){
@@ -393,5 +392,5 @@
             .handle({
                 200: function(others) {
-                    if ( others.length > 0 ) {
+                    if ( others.length > 0 && _.some(others,function(other){ return other._id !== id; })  ) {
                         return new HTTPResult(403,{error:"Other question with this code already exists."});
                     } else {
