Index: Dev/trunk/src/client/qed-client/app/Notifications.js
===================================================================
--- Dev/trunk/src/client/qed-client/app/Notifications.js	(revision 491)
+++ Dev/trunk/src/client/qed-client/app/Notifications.js	(revision 492)
@@ -3,5 +3,5 @@
     return declare([Toaster],{
         positionDirection: "br-up",
-        duration: 3000
+        duration: 7000
     });
 });
Index: Dev/trunk/src/client/qed-client/app/Page.js
===================================================================
--- Dev/trunk/src/client/qed-client/app/Page.js	(revision 491)
+++ Dev/trunk/src/client/qed-client/app/Page.js	(revision 492)
@@ -16,5 +16,6 @@
         notify: lang.hitch(Content,'notify'),
         markDirty: lang.hitch(Content,'markDirty'),
-        markClean: lang.hitch(Content,'markClean')
+        markClean: lang.hitch(Content,'markClean'),
+        isDirty: lang.hitch(Content,'isDirty')
     });
     return Page;
Index: Dev/trunk/src/client/qed-client/css/variables.less
===================================================================
--- Dev/trunk/src/client/qed-client/css/variables.less	(revision 491)
+++ Dev/trunk/src/client/qed-client/css/variables.less	(revision 492)
@@ -6,4 +6,5 @@
 @headers: #999999;
 @text: #ffffff;
+@disabledtext: #777777;
 
 // Colours
Index: Dev/trunk/src/client/qed-client/css/widgets/BlockButton.less
===================================================================
--- Dev/trunk/src/client/qed-client/css/widgets/BlockButton.less	(revision 491)
+++ Dev/trunk/src/client/qed-client/css/widgets/BlockButton.less	(revision 492)
@@ -5,4 +5,9 @@
     height: @button_block_height;
     vertical-align: top;
+    color: @text;
+
+    &.dijitDisabled {
+        color: @disabledtext;
+    }
 
     .dijitButtonContents {
@@ -18,5 +23,4 @@
         padding: 0 @std_offset;
         border: none;
-        color: @text;
         font-size: @button_block_font_size;
 
Index: Dev/trunk/src/client/qed-client/css/widgets/InlineButton.less
===================================================================
--- Dev/trunk/src/client/qed-client/css/widgets/InlineButton.less	(revision 491)
+++ Dev/trunk/src/client/qed-client/css/widgets/InlineButton.less	(revision 492)
@@ -3,4 +3,9 @@
     height: @button_inline_height;
     width: @button_inline_height;
+    color: @text;
+
+    &.dijitDisabled {
+        color: @disabledtext;
+    }
 
     .dijitButtonNode {
Index: Dev/trunk/src/client/qed-client/css/widgets/LargeButton.less
===================================================================
--- Dev/trunk/src/client/qed-client/css/widgets/LargeButton.less	(revision 491)
+++ Dev/trunk/src/client/qed-client/css/widgets/LargeButton.less	(revision 492)
@@ -7,4 +7,5 @@
         height: @button_large_height;
         padding: 3px;
+        color: @text;
 
         &*, * {
@@ -15,4 +16,8 @@
         }
 
+        &.dijitDisabled {
+            color: @disabledtext;
+        }
+
         .dijitButtonNode {
 
@@ -21,5 +26,4 @@
             height: @button_large_height;
             background: transparent;
-            color: @headers;
             font-size: @button_large_font_size;
             .transition(0.3s);
Index: Dev/trunk/src/client/qed-client/model/classes/_Class.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/_Class.js	(revision 491)
+++ Dev/trunk/src/client/qed-client/model/classes/_Class.js	(revision 492)
@@ -2,6 +2,7 @@
     "./_View",
     "dojo/_base/declare",
-    "dojo/_base/lang"
-], function(_View, declare, lang) {
+    "dojo/_base/lang",
+    "dojo/date/stamp"
+], function(_View, declare, lang, stamp) {
 
     var _Class = declare([_View],{
@@ -56,4 +57,7 @@
                                              idOrObj :
                                              this.getId(idOrObj));
+        },
+        _formatDate: function(date) {
+            return stamp.toISOString(date,{zulu:true,milliseconds:false});
         }
     });
Index: Dev/trunk/src/client/qed-client/model/classes/_View.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/_View.js	(revision 491)
+++ Dev/trunk/src/client/qed-client/model/classes/_View.js	(revision 492)
@@ -5,6 +5,7 @@
     "dojo/_base/json",
     "dojo/_base/lang",
+    "dojo/date/stamp",
     "dojo/store/util/QueryResults"
-], function(JsonRest, Deferred, declare, json, lang, queryResults) {
+], function(JsonRest, Deferred, declare, json, lang, stamp, queryResults) {
 
     var _View = declare([],{
@@ -38,4 +39,7 @@
         getCollectionPath: function() {
             return '/'+this._collection;
+        },
+        _parseDate: function(str) {
+            return stamp.fromISOString(str);
         }
     });
Index: Dev/trunk/src/client/qed-client/model/classes/questions.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/questions.js	(revision 491)
+++ Dev/trunk/src/client/qed-client/model/classes/questions.js	(revision 492)
@@ -1,7 +1,6 @@
 define([
     "./_Class",
-    "dojo/_base/declare",
-    "dojo/date/stamp"
-], function(_Class, declare, stamp) {
+    "dojo/_base/declare"
+], function(_Class, declare) {
 
     var Questions = declare([_Class],{
@@ -20,10 +19,10 @@
         _deserialize: function(obj) {
             if (obj.publicationDate) {
-                obj.publicationDate = stamp.fromISOString(obj.publicationDate);
+                obj.publicationDate = this._parseDate(obj.publicationDate);
             }
         },
         _serialize: function(obj) {
             if (obj.publicationDate) {
-                obj.publicationDate = stamp.toISOString(obj.publicationDate);
+                obj.publicationDate = this._formatDate(obj.publicationDate);
             }
         }
Index: Dev/trunk/src/client/qed-client/model/classes/responses.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/responses.js	(revision 491)
+++ Dev/trunk/src/client/qed-client/model/classes/responses.js	(revision 492)
@@ -6,7 +6,6 @@
     "dojo/_base/json",
     "dojo/_base/lang",
-    "dojo/_base/xhr",
-    "dojo/date/stamp"
-], function(_Class, surveyRuns, Deferred, declare, json, lang, xhr, stamp) {
+    "dojo/_base/xhr"
+], function(_Class, surveyRuns, Deferred, declare, json, lang, xhr) {
 
     var Responses = declare([_Class],{
@@ -26,5 +25,5 @@
             }
             if (obj.publicationDate) {
-                obj.publicationDate = stamp.fromISOString(obj.publicationDate);
+                obj.publicationDate = this._parseDate(obj.publicationDate);
             }
         },
@@ -34,5 +33,5 @@
             }
             if (obj.publicationDate) {
-                obj.publicationDate = stamp.toISOString(obj.publicationDate);
+                obj.publicationDate = this._formatDate(obj.publicationDate);
             }
         },
Index: Dev/trunk/src/client/qed-client/model/classes/surveyRuns.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/surveyRuns.js	(revision 491)
+++ Dev/trunk/src/client/qed-client/model/classes/surveyRuns.js	(revision 492)
@@ -2,7 +2,6 @@
     "./_Class",
     "./surveys",
-    "dojo/_base/declare",
-    "dojo/date/stamp"
-], function(_Class, surveys, declare, stamp) {
+    "dojo/_base/declare"
+], function(_Class, surveys, declare) {
 
     var SurveyRuns = declare([_Class],{
@@ -21,8 +20,8 @@
         _deserialize: function(obj) {
             if (obj.endDate) {
-                obj.endDate = stamp.fromISOString(obj.endDate);
+                obj.endDate = this._parseDate(obj.endDate);
             }
             if (obj.startDate) {
-                obj.startDate = stamp.fromISOString(obj.startDate);
+                obj.startDate = this._parseDate(obj.startDate);
             }
             if (obj.survey) {
@@ -32,8 +31,8 @@
         _serialize: function(obj) {
             if (obj.endDate) {
-                obj.endDate = stamp.toISOString(obj.endDate);
+                obj.endDate = this._formatDate(obj.endDate);
             }
             if (obj.startDate) {
-                obj.startDate = stamp.toISOString(obj.startDate);
+                obj.startDate = this._formatDate(obj.startDate);
             }
             if (obj.survey) {
Index: Dev/trunk/src/client/qed-client/model/classes/surveys.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/surveys.js	(revision 491)
+++ Dev/trunk/src/client/qed-client/model/classes/surveys.js	(revision 492)
@@ -1,8 +1,9 @@
 define([
     "./_Class",
+    "./questions",
+    "dojo/_base/array",
     "dojo/_base/declare",
-    "dojo/date/stamp",
-    "dojo/store/JsonRest"
-], function(_Class, declare, stamp, JsonRest) {
+    "dojo/_base/lang"
+], function(_Class, questions, array, declare, lang) {
 
     var Surveys = declare([_Class],{
@@ -18,11 +19,15 @@
         },
         _deserialize: function(obj) {
+            obj.questions = array.map(obj.questions,
+                                      lang.hitch(questions,'_doDeserialize'));
             if (obj.publicationDate) {
-                obj.publicationDate = stamp.fromISOString(obj.publicationDate);
+                obj.publicationDate = this._parseDate(obj.publicationDate);
             }
         },
         _serialize: function(obj) {
+            obj.questions = array.map(obj.questions,
+                                      lang.hitch(questions,'_doSerialize'));
             if (obj.publicationDate) {
-                obj.publicationDate = stamp.toISOString(obj.publicationDate);
+                obj.publicationDate = this._formatDate(obj.publicationDate);
             }
         },
Index: Dev/trunk/src/client/qed-client/model/widgets/SurveyRunWidget.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/SurveyRunWidget.js	(revision 491)
+++ Dev/trunk/src/client/qed-client/model/widgets/SurveyRunWidget.js	(revision 492)
@@ -12,4 +12,11 @@
                 endDateBox.constraints.min  = value;
             });
+        },
+        _getValueAttr: function() {
+            var value = this.inherited(arguments);
+            if ( !value.startDate ) { delete value.startDate; }
+            if ( !value.endDate ) { delete value.endDate; }
+            value.respondentCanDeleteOwnResponse = value.respondentCanDeleteOwnResponse[0] === true;
+            return value;
         }
     });
Index: Dev/trunk/src/client/qed-client/model/widgets/questions/templates/TextInputWidget.html
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/questions/templates/TextInputWidget.html	(revision 491)
+++ Dev/trunk/src/client/qed-client/model/widgets/questions/templates/TextInputWidget.html	(revision 492)
@@ -1,4 +1,4 @@
 <form>
   <p>${text}</p>
-  <div class="qedField" data-dojo-attach-point="textArea" data-dojo-type="dijit/form/Textarea" name="text"></div>
+  <textarea class="qedField" data-dojo-attach-point="textArea" data-dojo-type="dijit/form/Textarea" name="text"></textarea>
 </form>
Index: Dev/trunk/src/client/qed-client/model/widgets/templates/QuestionWidget.html
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/templates/QuestionWidget.html	(revision 491)
+++ Dev/trunk/src/client/qed-client/model/widgets/templates/QuestionWidget.html	(revision 492)
@@ -7,5 +7,5 @@
             <input data-dojo-type="dijit/form/TextBox" name="title" type="text" class="loginInput" />
             <label for="question" class="loginLabel">Description</label>
-            <input data-dojo-type="dijit/form/Textarea" name="description" type="text" class="loginInput"/>
+            <textarea data-dojo-type="dijit/form/Textarea" name="description" type="text" class="loginInput"></textarea>
             <label for="category" class="loginLabel">Category</label>
             <input data-dojo-type="dijit/form/TextBox" name="category" type="text" class="loginInput" />
Index: Dev/trunk/src/client/qed-client/model/widgets/templates/SurveyRunWidget.html
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/templates/SurveyRunWidget.html	(revision 491)
+++ Dev/trunk/src/client/qed-client/model/widgets/templates/SurveyRunWidget.html	(revision 492)
@@ -3,15 +3,28 @@
     <div>
         <label for="mode" class="qedLabel">Description</label>
-        <textarea name="description" class="qedField" data-dojo-type="dijit/form/Textarea"></textarea>
+        <textarea name="description" class="qedField"
+                  data-dojo-type="dijit/form/Textarea"></textarea>
     </div>
 
     <div>
         <label for="startDate" class="qedLabel">Start date</label>
-        <input type="text" name="startDate" class="qedField" data-dojo-type="dijit/form/DateTextBox" data-dojo-attach-point="startDateBox" />
+        <input type="text" name="startDate" class="qedField"
+               data-dojo-type="dijit/form/DateTextBox"
+               data-dojo-attach-point="startDateBox" />
     </div>
 
     <div>
         <label for="endDate" class="qedLabel">End date</label>
-        <input type="text" name="endDate" class="qedField" data-dojo-type="dijit/form/DateTextBox" data-dojo-attach-point="endDateBox" />
+        <input type="text" name="endDate" class="qedField"
+               data-dojo-type="dijit/form/DateTextBox"
+               data-dojo-attach-point="endDateBox" />
+    </div>
+
+    <div>
+        <label for="endDate" class="qedLabel">Allow respondents to delete their unsubmitted response</label>
+        <input type="text" name="respondentCanDeleteOwnResponse"
+               class="qedField"
+               data-dojo-type="dijit/form/CheckBox"
+               data-dojo-props="'value':true" />
     </div>
 
Index: Dev/trunk/src/client/qed-client/model/widgets/templates/SurveyWidget.html
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/templates/SurveyWidget.html	(revision 491)
+++ Dev/trunk/src/client/qed-client/model/widgets/templates/SurveyWidget.html	(revision 492)
@@ -3,4 +3,4 @@
     <input data-dojo-type="dijit/form/TextBox" name="title"/><br/>
     <label for="description">Description</label>
-    <input data-dojo-type="dijit/form/Textarea" name="description"/><br/>
+    <textarea data-dojo-type="dijit/form/Textarea" name="description"></textarea><br/>
 </form>
Index: Dev/trunk/src/client/qed-client/pages/_ObjectPage.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/_ObjectPage.js	(revision 491)
+++ Dev/trunk/src/client/qed-client/pages/_ObjectPage.js	(revision 492)
@@ -11,5 +11,12 @@
         classStore: null,
         constructor: function() {
-            if ( !this.classStore ) { throw new Error("Subclasses must specify a classStore."); }
+            if ( !this.classStore ) {
+                throw new Error("Subclasses must specify a classStore.");
+            }
+        },
+        startup: function() {
+            if ( this._started ) { return; }
+            this.inherited(arguments);
+            this.markClean();
         },
         _load: function() {
Index: Dev/trunk/src/client/qed-client/pages/question.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/question.js	(revision 491)
+++ Dev/trunk/src/client/qed-client/pages/question.js	(revision 492)
@@ -29,19 +29,15 @@
         },
         _handlePropertiesChange: function() {
-            if ( this.propertiesForm.validate() ) {
-                lang.mixin(this.object,this.propertiesForm.get('value'));
-            }
+            lang.mixin(this.object,this.propertiesForm.get('value'));
             this.markDirty();
+            this._refresh();
         },
         _handleContentChange: function() {
-            if ( this.contentList.validate() ) {
-                this.object.content = this.contentList.get('value');
-            }
+            this.object.content = this.contentList.get('value');
             this.markDirty();
+            this._refresh();
         },
         _save: function() {
-            if ( this.propertiesForm.validate() && this.contentList.validate() ) {
-                lang.mixin(this.object,this.propertiesForm.get('value'));
-                this.object.content = this.contentList.get('value');
+            if ( this._isValid ) {
                 return this.inherited(arguments);
             } else {
@@ -68,4 +64,19 @@
             return false;
         },
+        markDirty: function() {
+            this._isValid = this.propertiesForm.validate() &&
+                            this.contentList.validate();
+            this.saveBtn.set('disabled',!this._isValid);
+            this.saveAndCloseBtn.set('disabled',!this._isValid);
+            this.discardBtn.set('label','Discard & Close');
+            this.inherited(arguments);
+        },
+        markClean: function() {
+            this._isValid = true;
+            this.saveBtn.set('disabled',true);
+            this.saveAndCloseBtn.set('disabled',true);
+            this.discardBtn.set('label','Close');
+            this.inherited(arguments);
+        },
         _ignore: function(evt) {
             if ( evt ) { event.stop( evt ); }
Index: Dev/trunk/src/client/qed-client/pages/response.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/response.js	(revision 491)
+++ Dev/trunk/src/client/qed-client/pages/response.js	(revision 492)
@@ -40,5 +40,7 @@
             this.submitButton.set('disabled',false);
             this.continueButton.set('disabled',false);
-            this.cancelButton.set('disabled',false);
+            var canDelete = (this.response &&
+                             this.response._surveyRun.respondentCanDeleteOwnResponse);
+            this.cancelButton.set('disabled',canDelete||false);
             this.surveyWidget.set('disabled', false);
         },
Index: Dev/trunk/src/client/qed-client/pages/survey.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/survey.js	(revision 491)
+++ Dev/trunk/src/client/qed-client/pages/survey.js	(revision 492)
@@ -23,4 +23,5 @@
             this._setupQuestionBrowser();
             this._setupListView();
+            this.questionList.on('change',lang.hitch(this,'_handleQuestionsChange'));
             this._load();
         },
@@ -58,14 +59,15 @@
         _refresh: function() {
             this.titleNode.innerHTML = this.object.title || "(set title in properties)";
-            this.propertiesDialog.set('value',{survey:this.object});
+            this.propertiesForm.set('value',{survey: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);
+        },
+        _handleQuestionsChange: function() {
+            this.object.questions = this.questionList.get('value');
+            this.markDirty();
+            this._refresh();
         },
         _onShowProperties: function(evt) {
@@ -76,5 +78,5 @@
         _onPropertiesOk: function(evt) {
             this.propertiesDialog.hide();
-            lang.mixin(this.object, this.propertiesDialog.get('value').survey);
+            lang.mixin(this.object, this.propertiesForm.get('value').survey);
             this.markDirty();
             this._refresh();
@@ -84,5 +86,5 @@
         _onPropertiesCancel: function(evt) {
             this.propertiesDialog.hide();
-            this.propertiesDialog.set('value',{survey:this.object});
+            this.propertiesForm.set('value',{survey:this.object});
             if ( evt ) { event.stop(evt); }
             return false;
@@ -109,4 +111,16 @@
                 preview: true
             });
+        },
+        markDirty: function() {
+            this.saveBtn.set('disabled',false);
+            this.saveAndCloseBtn.set('disabled',false);
+            this.discardBtn.set('label','Discard & Close');
+            this.inherited(arguments);
+        },
+        markClean: function() {
+            this.saveBtn.set('disabled',true);
+            this.saveAndCloseBtn.set('disabled',true);
+            this.discardBtn.set('label','Close');
+            this.inherited(arguments);
         }
     });
Index: Dev/trunk/src/client/qed-client/pages/surveyRun.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/surveyRun.js	(revision 491)
+++ Dev/trunk/src/client/qed-client/pages/surveyRun.js	(revision 492)
@@ -74,6 +74,5 @@
         },
         _onPropChange: function(e) {
-            if ( this.surveyRunWidget.validate() ) {
-                lang.mixin(this.object,this.surveyRunWidget.get('value'));
+            if ( this._updateObject() ) {
                 this._refreshURL();
             }
@@ -90,10 +89,16 @@
         },
         _save: function() {
-            if ( this.surveyRunWidget.validate() ) {
-                lang.mixin(this.object,this.surveyRunWidget.get('value'));
+            if ( this._updateObject() ) {
                 return this.inherited(arguments);
             } else {
                 return new Deferred.reject();
             }
+        },
+        _updateObject: function() {
+            var valid = this.surveyRunWidget.validate();
+            if ( valid ) {
+                lang.mixin(this.object,this.surveyRunWidget.get('value'));
+            }
+            return valid;
         },
         _onSave: function(evt) {
@@ -115,4 +120,16 @@
             if ( evt ) { event.stop(evt); }
             return false;
+        },
+        markDirty: function() {
+            this.saveBtn.set('disabled',false);
+            this.saveAndCloseBtn.set('disabled',false);
+            this.discardBtn.set('label','Discard & Close');
+            this.inherited(arguments);
+        },
+        markClean: function() {
+            this.saveBtn.set('disabled',true);
+            this.saveAndCloseBtn.set('disabled',true);
+            this.discardBtn.set('label','Close');
+            this.inherited(arguments);
         }
     });
Index: Dev/trunk/src/client/qed-client/pages/templates/question.html
===================================================================
--- Dev/trunk/src/client/qed-client/pages/templates/question.html	(revision 491)
+++ Dev/trunk/src/client/qed-client/pages/templates/question.html	(revision 492)
@@ -18,12 +18,15 @@
                 <button data-dojo-type="dijit/form/Button"
                         data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconAccept'"
+                        data-dojo-attach-point="saveBtn"
                         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-point="saveAndCloseBtn"
                         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-point="discardBtn"
                         data-dojo-attach-event="onClick:_onDiscard">
                   Discard &amp; Close</button>
Index: Dev/trunk/src/client/qed-client/pages/templates/survey.html
===================================================================
--- Dev/trunk/src/client/qed-client/pages/templates/survey.html	(revision 491)
+++ Dev/trunk/src/client/qed-client/pages/templates/survey.html	(revision 492)
@@ -23,12 +23,15 @@
             <button data-dojo-type="dijit/form/Button"
                     data-dojo-attach-event="onClick:_onSave"
+                    data-dojo-attach-point="saveBtn"
                     data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconAccept'">
                 Save</button>
             <button data-dojo-type="dijit/form/Button"
                     data-dojo-attach-event="onClick:_onSaveAndClose"
+                    data-dojo-attach-point="saveAndCloseBtn"
                     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-attach-point="discardBtn"
                     data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconCancel'">
                 Discard &amp; Close</button>
@@ -41,18 +44,21 @@
 
     <div data-dojo-type="dijit/Dialog"
-         title="Survey properties"
-         data-dojo-attach-point="propertiesDialog"
-         data-dojo-attach-event="onSubmit:_onPropertiesOk">
-        <fieldset class="qedFieldset">
-            <div data-dojo-type="../model/widgets/SurveyWidget" data-dojo-props="name:'survey'"></div>
-        </fieldset>
-        <button data-dojo-type="dijit/form/Button"
-                type="submit"
-                data-dojo-attach-event="onClick:_onPropertiesOk">
-            OK</button>
-        <button data-dojo-type="dijit/form/Button"
-                type="button"
-                data-dojo-attach-event="onClick:_onPropertiesCancel">
-            Cancel</button>
+         data-dojo-props="'title':'Survey properties'"
+         data-dojo-attach-point="propertiesDialog">
+        <form data-dojo-type="dijit/form/Form"
+              data-dojo-attach-point="propertiesForm"
+              data-dojo-attach-event="onSubmit:_onPropertiesOk">
+            <fieldset class="qedFieldset">
+                <div data-dojo-type="../model/widgets/SurveyWidget" data-dojo-props="name:'survey'"></div>
+            </fieldset>
+            <button data-dojo-type="dijit/form/Button"
+                    type="submit"
+                    data-dojo-attach-event="onClick:_onPropertiesOk">
+                OK</button>
+            <button data-dojo-type="dijit/form/Button"
+                    type="button"
+                    data-dojo-attach-event="onClick:_onPropertiesCancel">
+                Cancel</button>
+        </form>
     </div>
 
Index: Dev/trunk/src/client/qed-client/pages/templates/surveyRun.html
===================================================================
--- Dev/trunk/src/client/qed-client/pages/templates/surveyRun.html	(revision 491)
+++ Dev/trunk/src/client/qed-client/pages/templates/surveyRun.html	(revision 492)
@@ -55,12 +55,15 @@
                 class="blue"
                 data-dojo-props="baseClass: 'rftBlockButton', iconClass: 'rftIcon rftIconSave'"
+                data-dojo-attach-point="saveBtn"
                 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-point="saveAndCloseBtn"
                 data-dojo-attach-event="onClick:_onSaveAndClose">Save &amp; Close</button>
         <button data-dojo-type="dijit/form/Button"
                 class="blue"
                 data-dojo-props="baseClass: 'rftBlockButton', iconClass: 'rftIcon rftIconClose'"
+                data-dojo-attach-point="discardBtn"
                 data-dojo-attach-event="onClick:_onDiscard">Discard &amp; Close</button>
     </div>
Index: Dev/trunk/src/client/qed-client/ui/LoginDialogWrapper.coffee
===================================================================
--- Dev/trunk/src/client/qed-client/ui/LoginDialogWrapper.coffee	(revision 491)
+++ Dev/trunk/src/client/qed-client/ui/LoginDialogWrapper.coffee	(revision 492)
@@ -9,9 +9,11 @@
     "dojo/_base/lang",
     "dojo/on",
+    "dojo/when",
     "dojo/text!./templates/LoginDialogWrapper.html"
 ], (session, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin,
-    registry, declare, event, lang, _on, template) ->
+    registry, declare, event, lang, _on, _when, template) ->
     declare [_WidgetBase,_TemplatedMixin,_WidgetsInTemplateMixin],
         templateString: template
+        _fx: null
         startup: () ->
             if @_started then return
@@ -25,5 +27,7 @@
                               value.password
                 .then () =>
-                    @loginDialog.hide()
+                    @_fx = _when(@_fx)
+                    .then () =>
+                        @loginDialog.hide()
                 , () =>
                     alert "Login failed!"
@@ -31,7 +35,9 @@
             false
         onUserChange: (user) ->
-            if user
-                @loginDialog.hide()
-            else
-                @loginDialog.show()
+            @_fx = _when(@_fx)
+            .then () =>
+                if user
+                    @loginDialog.hide()
+                else
+                    @loginDialog.show()
             null
Index: Dev/trunk/src/client/qed-client/ui/templates/LoginDialogWrapper.html
===================================================================
--- Dev/trunk/src/client/qed-client/ui/templates/LoginDialogWrapper.html	(revision 491)
+++ Dev/trunk/src/client/qed-client/ui/templates/LoginDialogWrapper.html	(revision 492)
@@ -25,5 +25,5 @@
             <div data-dojo-type="dijit/form/Button"
                  type="submit"
-                 data-dojo-attach-event="onLogin">Login</div>
+                 data-dojo-attach-event="onClick:onLogin">Login</div>
         </form>
     </div>
Index: Dev/trunk/src/client/qed-client/widgets/_ComplexValueMixin.coffee
===================================================================
--- Dev/trunk/src/client/qed-client/widgets/_ComplexValueMixin.coffee	(revision 491)
+++ Dev/trunk/src/client/qed-client/widgets/_ComplexValueMixin.coffee	(revision 492)
@@ -2,8 +2,10 @@
     "dijit/_Container",
     "dijit/form/_FormMixin",
+    "dijit/registry",
     "dojo/_base/array",
     "dojo/_base/declare",
-    "dojo/_base/event"
-], (_Container, _FormMixin, array, declare, event) ->
+    "dojo/_base/event",
+    "dojo/on"
+], (_Container, _FormMixin, registry, array, declare, event, _on) ->
     declare [_Container,_FormMixin],
         name: ""
@@ -20,4 +22,5 @@
                         It is recommended to use <form> as the root
                         element in your template for", @declaredClass
+            @own ( _on @domNode, 'submit', (evt) => @_handleSubmit evt )
 
         _setDisabledAttr: (value) ->
@@ -35,15 +38,12 @@
             children[0].focus() if children.length > 0
 
-        onSubmit: (e) =>
-            # since this widget is used to create more complex
-            # widgets within other forms, the onSubmit must either be
-            # ignored or propagated, but not handled here.
-            event.stop e if e
+        _handleSubmit: (evt) ->
+            node = @domNode
+            until not node or ( widget and
+                                typeof widget._onSubmit is "function" )
+                node = node.parentNode
+                widget = registry.byNode node if node
+            widget._onSubmit(evt) if widget
+            # we always stop the event, since this is a widget after all
+            event.stop evt if evt
             false
-
-        _onSubmit: (e) =>
-            # since this widget is used to create more complex
-            # widgets within other forms, the onSubmit must either be
-            # ignored or propagated, but not handled here.
-            event.stop e if e
-            false
