Changeset 441 for Dev


Ignore:
Timestamp:
04/29/13 19:35:10 (12 years ago)
Author:
hendrikvanantwerpen
Message:

Big cleanup of the question content.

  • Replaced old list implementations with a new one that behaves like a form widget.
  • All question content is now in separate widgets, not in the factory itself.
  • Added form and widget validation for question editing.
Location:
Dev/trunk/client/qed
Files:
30 added
2 deleted
17 edited
6 moved

Legend:

Unmodified
Added
Removed
  • Dev/trunk/client/qed/css/forms.less

    r434 r441  
    3333        width: 150px;
    3434        display: inline-block;
     35        text-align: right;
     36        padding: 1px;
    3537    }
    3638
     
    3840        max-width: 350px;
    3941        display: inline-block;
     42        vertical-align: top;
     43        padding: 1px;
     44
     45        &.dijitTextArea {
     46            min-height: 5em;
     47        }
    4048    }
    4149
  • Dev/trunk/client/qed/css/model/widgets/QuestionEditor.less

    r439 r441  
    33        overflow: hidden;
    44    }
     5
     6    .surveyEditorPreview {
     7        overflow-y: auto;
     8    }
    59}
  • Dev/trunk/client/qed/css/qed.css

    r438 r441  
    991991  width: 150px;
    992992  display: inline-block;
    993 }
    994 /* line 37, /home/hendrik/gamelab/qed.svn/Dev/trunk/client/qed/css/forms.less */
    995 @media -sass-debug-info{filename{font-family:file\:\/\/\/home\/hendrik\/gamelab\/qed\.svn\/Dev\/trunk\/client\/qed\/css\/forms\.less}line{font-family:\0000337}}
     993  text-align: right;
     994  padding: 1px;
     995}
     996/* line 39, /home/hendrik/gamelab/qed.svn/Dev/trunk/client/qed/css/forms.less */
     997@media -sass-debug-info{filename{font-family:file\:\/\/\/home\/hendrik\/gamelab\/qed\.svn\/Dev\/trunk\/client\/qed\/css\/forms\.less}line{font-family:\0000339}}
    996998#rft.claro .qedField {
    997999  max-width: 350px;
    9981000  display: inline-block;
    999 }
    1000 /* line 42, /home/hendrik/gamelab/qed.svn/Dev/trunk/client/qed/css/forms.less */
    1001 @media -sass-debug-info{filename{font-family:file\:\/\/\/home\/hendrik\/gamelab\/qed\.svn\/Dev\/trunk\/client\/qed\/css\/forms\.less}line{font-family:\0000342}}
     1001  vertical-align: top;
     1002  padding: 1px;
     1003}
     1004/* line 45, /home/hendrik/gamelab/qed.svn/Dev/trunk/client/qed/css/forms.less */
     1005@media -sass-debug-info{filename{font-family:file\:\/\/\/home\/hendrik\/gamelab\/qed\.svn\/Dev\/trunk\/client\/qed\/css\/forms\.less}line{font-family:\0000345}}
     1006#rft.claro .qedField.dijitTextArea {
     1007  min-height: 5em;
     1008}
     1009/* line 50, /home/hendrik/gamelab/qed.svn/Dev/trunk/client/qed/css/forms.less */
     1010@media -sass-debug-info{filename{font-family:file\:\/\/\/home\/hendrik\/gamelab\/qed\.svn\/Dev\/trunk\/client\/qed\/css\/forms\.less}line{font-family:\0000350}}
    10021011#rft.claro .qedField.qedFill {
    10031012  width: 350px;
    10041013}
    1005 /* line 46, /home/hendrik/gamelab/qed.svn/Dev/trunk/client/qed/css/forms.less */
    1006 @media -sass-debug-info{filename{font-family:file\:\/\/\/home\/hendrik\/gamelab\/qed\.svn\/Dev\/trunk\/client\/qed\/css\/forms\.less}line{font-family:\0000346}}
     1014/* line 54, /home/hendrik/gamelab/qed.svn/Dev/trunk/client/qed/css/forms.less */
     1015@media -sass-debug-info{filename{font-family:file\:\/\/\/home\/hendrik\/gamelab\/qed\.svn\/Dev\/trunk\/client\/qed\/css\/forms\.less}line{font-family:\0000354}}
    10071016#rft.claro .qedFieldset {
    10081017  margin: 1em 0px;
     
    17431752  overflow: hidden;
    17441753}
     1754/* line 6, /home/hendrik/gamelab/qed.svn/Dev/trunk/client/qed/css/model/widgets/QuestionEditor.less */
     1755@media -sass-debug-info{filename{font-family:file\:\/\/\/home\/hendrik\/gamelab\/qed\.svn\/Dev\/trunk\/client\/qed\/css\/model\/widgets\/QuestionEditor\.less}line{font-family:\000036}}
     1756#rft.claro .surveyEditorPreview {
     1757  overflow-y: auto;
     1758}
    17451759/* line 5, /home/hendrik/gamelab/qed.svn/Dev/trunk/client/qed/css/pages/questions.less */
    17461760@media -sass-debug-info{filename{font-family:file\:\/\/\/home\/hendrik\/gamelab\/qed\.svn\/Dev\/trunk\/client\/qed\/css\/pages\/questions\.less}line{font-family:\000035}}
  • Dev/trunk/client/qed/model/widgets/AccountListView.js

    r417 r441  
    11define([
    2     'dojo/_base/declare',
    3     'dojo/_base/lang',
    4     'dojo/dom-construct',
    5     '../../widgets/LineWithActionsWidget',
    6     '../../widgets/list/OrderedList'
    7 ],function(
    8     declare,
    9     lang,
    10     domConstruct,
    11     LineWithActionsWidget,
    12     OrderedList
    13 ) {
    14     return declare([OrderedList],{
     2    "../../widgets/LineWithActionsWidget",
     3    "../../widgets/ListWidget",
     4    "dojo/_base/declare",
     5    "dojo/_base/lang",
     6    "dojo/dom-construct"
     7], function(LineWithActionsWidget, ListWidget, declare, lang, domConstruct) {
     8    return declare([ListWidget],{
    159        baseClass: 'rftAccountListView',
    1610        type: 'account',
    1711
    18         _createAvatarNode: function(item){
     12        createAvatar: function(id, item){
    1913            return domConstruct.create("div",{
    2014                'class': 'dragAvatar',
     
    2216            });
    2317        },
    24         _createListNode: function(item) {
     18        createListElement: function(id, item) {
    2519            var w = new LineWithActionsWidget({
     20                id: id,
    2621                title: item.title,
    2722                'class': "green",
     
    3732            });
    3833            w.startup();
    39             return w.domNode;
     34            return w;
    4035        }
    4136    });
  • Dev/trunk/client/qed/model/widgets/CategoryListView.js

    r426 r441  
    11define([
    2     'dojo/_base/declare',
    3     'dojo/_base/lang',
    4     'dojo/dom-construct',
    5     '../../widgets/LineWithActionsWidget',
    6     '../../widgets/list/List'
    7 ],function(declare, lang, domConstruct, LineWithActionsWidget, List) {
    8     return declare([List],{
     2    "../../widgets/LineWithActionsWidget",
     3    "../../widgets/ListWidget",
     4    "dojo/_base/declare",
     5    "dojo/_base/lang",
     6    "dojo/dom-construct"
     7], function(LineWithActionsWidget, ListWidget, declare, lang, domConstruct) {
     8    return declare([ListWidget],{
    99        baseClass: 'rftLineListView',
     10        type: 'category',
    1011
    11         _createAvatarNode: function(item) {
     12        createAvatar: function(id, item) {
    1213            var node = domConstruct.create("div",{
    1314                className: "dragAvatar",
     
    1718        },
    1819
    19         _createListNode: function(item) {
     20        createListElement: function(id, item) {
    2021            var w = new LineWithActionsWidget({
     22                id: id,
    2123                title: item,
    2224                'class': "orange",
    2325                actions: {
    2426                    "Remove" : {
    25                         callback: lang.hitch(this, function() {
    26                             this.removeItem(item, w);
    27                         }),
     27                        callback: lang.hitch(this, 'removeItem', id),
    2828                        properties: {
    2929                            blockButton: false,
     
    3434            });
    3535            w.startup();
    36             return w.domNode;
     36            return w;
    3737        }
    3838
  • Dev/trunk/client/qed/model/widgets/QuestionEditorPreview.js

    r436 r441  
    11define([
    2     'dojo/_base/array',
    3     'dojo/_base/declare',
    4     'dojo/_base/lang',
    5     'dojo/dom-construct',
    6     'dijit/registry',
    7     './QuestionEditorPreviewItem',
    8     '../../widgets/list/OrderedList'
    9 ], function(array, declare, lang, domConstruct, registry, QuestionEditorPreviewItem, OrderedList) {
    10     return declare([OrderedList], {
     2    "../../widgets/ListWidget",
     3    "./QuestionEditorPreviewItem",
     4    "dijit/registry",
     5    "dojo/_base/array",
     6    "dojo/_base/declare",
     7    "dojo/_base/lang",
     8    "dojo/dom-construct"
     9], function(ListWidget, QuestionEditorPreviewItem, registry, array, declare, lang, domConstruct) {
     10    return declare([ListWidget], {
    1111        baseClass: 'surveyEditorPreview',
    1212        type: 'questionContent',
    1313        withHandles: true,
    1414
    15         _createAvatarNode: function(item) {
    16             return domConstruct.create("span",{
    17                 innerHTML: item.type || "Dragging!!!"
     15        createAvatar: function(id, item) {
     16            return domConstruct.create("div",{
     17                innerHTML: item.type || "(unkown)"
    1818            });
    1919        },
    20         _createListNode: function(item) {
     20        createListElement: function(id, item) {
    2121            var previewItem = new QuestionEditorPreviewItem({
     22                id: id,
    2223                value: item
    2324            });
    24             this.own(previewItem.on('close',
    25                                     lang.hitch(this,'removeItem',item)));
     25            this.own(previewItem.on('destroy',
     26                                    lang.hitch(this,'removeItem',id)));
    2627            previewItem.startup();
    27             return previewItem.domNode;
    28         },
    29         getItems: function() {
    30             return array.map(
    31                 this.source.getAllNodes(),
    32                 function(node){
    33                     return registry.byNode(node).get('value');
    34                 },this);
     28            return previewItem;
    3529        }
    3630    });
  • Dev/trunk/client/qed/model/widgets/QuestionEditorPreviewItem.js

    r440 r441  
    11define([
    2     "./QuestionWidgetFactory",
     2    "./questions/Factory",
    33    "dijit/_Container",
    44    "dijit/_TemplatedMixin",
     
    66    "dijit/_WidgetsInTemplateMixin",
    77    "dojo/_base/declare",
     8    "dojo/_base/event",
    89    "dojo/_base/fx",
    910    "dojo/_base/lang",
     
    1314    "dojo/on",
    1415    "dojo/text!./templates/QuestionEditorPreviewItem.html"
    15 ], function(QuestionWidgetFactory, _Container, _TemplatedMixin, _WidgetBase, _WidgetsInTemplateMixin, declare, fx, lang, domClass, domGeom, domStyle, on, template) {
     16], function(QuestionWidgetFactory, _Container, _TemplatedMixin, _WidgetBase, _WidgetsInTemplateMixin, declare, event, fx, lang, domClass, domGeom, domStyle, on, template) {
    1617    return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, _Container], {
    1718        templateString: template,
     
    3132                        lang.hitch(this, 'onToggleFold')));
    3233            this.own(this.removeButton.on('click',
    33                         lang.hitch(this, 'onClose')));
     34                        lang.hitch(this, 'onDestroy')));
    3435            this.own(this.editButton.on('click',
    3536                        lang.hitch(this, 'onToggleEdit')));
    36             if (this.value) {
    37                 this._showEditWidget();
    38             } else {
    39                 throw "No data supplied to create an innerWidget!";
     37            this.showEdit();
     38        },
     39        onDestroy: function() {},
     40        _getValueAttr: function(value) {
     41            if ( this._editing ) {
     42                this.value = this.innerWidget.get('value');
    4043            }
    41         },
    42         onClose: function() {},
    43         _getValueAttr: function(value) {
    4444            return this.value;
    4545        },
    4646        _setValueAttr: function(value) {
    4747            this.value = value;
    48             this._destroyInnerWidget();
    4948            if ( this._editing ) {
    5049                this._showEditWidget();
     
    5352            }
    5453        },
    55         onToggleEdit: function() {
    56             if (this._editing) {
    57                 if ( this.innerWidget !== null ) {
    58                     if (!this.innerWidget.validate ||
    59                         this.innerWidget.validate() ) {
    60                         this.value = this.innerWidget.get('value');
    61                         this._showViewWidget();
    62                     }
    63                 } else {
     54        validate: function() {
     55            return !this._editing || this.innerWidget.validate();
     56        },
     57        showView: function() {
     58            if ( this._editing ) {
     59                if (!this.innerWidget.validate || this.innerWidget.validate() ) {
     60                    this.value = this.innerWidget.get('value');
    6461                    this._showViewWidget();
    6562                }
    66             } else {
     63            }
     64        },
     65        showEdit: function() {
     66            if (!this._editing) {
    6767                this._showEditWidget();
    6868            }
    6969        },
     70        onToggleEdit: function(evt) {
     71            if (this._editing) {
     72                this.showView();
     73            } else {
     74                this.showEdit();
     75            }
     76            evt && event.stop(evt);
     77            return false;
     78        },
    7079        _showViewWidget: function() {
    71             this._destroyInnerWidget();
    72             this.innerWidget = this._factory.createViewWidget( this.value );
    73             if ( this.innerWidget !== null ) {
     80            var newWidget = this._factory.createViewWidget( this.value );
     81            if ( newWidget !== null ) {
     82                this._destroyInnerWidget();
     83                this.innerWidget = newWidget;
    7484                this.innerWidget.placeAt(this.containerNode);
    7585                this.innerWidget.startup();
    7686                this.innerWidget.set('readOnly',true);
     87                this.titleNode.innerHTML = this.value.type+" [preview]";
     88                domClass.replace(this.editButton.iconNode, "rftIconEdit", "rftIconAccept");
     89                this.editButton.set("label", "Edit");
     90                this._editing = false;
    7791            }
    78             this.titleNode.innerHTML = this.value.type+" [preview]";
    79             domClass.replace(this.editButton.iconNode, "rftIconEdit", "rftIconAccept");
    80             this.editButton.set("label", "Edit");
    81             this._editing = false;
    8292        },
    8393        _showEditWidget: function() {
    84             this._destroyInnerWidget();
    85             this.innerWidget = this._factory.createEditWidget( this.value );
    86             if ( this.innerWidget !== null ) {
     94            var newWidget = this._factory.createEditWidget( this.value );
     95            if ( newWidget !== null ) {
     96                this._destroyInnerWidget();
     97                this.innerWidget = newWidget;
    8798                this.innerWidget.placeAt(this.containerNode);
    8899                this.innerWidget.startup();
     100                this.titleNode.innerHTML = this.value.type+" [editing]";
     101                domClass.replace(this.editButton.iconNode, "rftIconAccept", "rftIconEdit");
     102                this.editButton.set("label", "Done");
     103                this._editing = true;
    89104            }
    90             this.titleNode.innerHTML = this.value.type+" [editing]";
    91             domClass.replace(this.editButton.iconNode, "rftIconAccept", "rftIconEdit");
    92             this.editButton.set("label", "Done");
    93             this._editing = true;
    94105        },
    95106        _destroyInnerWidget: function() {
     
    98109            }
    99110        },
    100         onToggleFold: function() {
     111        onToggleFold: function(evt) {
    101112            if (!this.animation) {
    102113                if (!domClass.contains(this.domNode, "fold")) {
     
    130141                }
    131142            }
     143            evt && event.stop(evt);
     144            return false;
    132145        }
    133146
  • Dev/trunk/client/qed/model/widgets/QuestionEditorToolkit.js

    r428 r441  
    2525        _topicSelect: null,
    2626        _topicStore: null,
    27         _categories : null,
    2827
    2928        _contentItems: [
     
    3736            { type: "StringInput" },
    3837            { type: "TextInput" },
    39             { type: "IntegerInput" },
     38            { type: "NumberInput" },
    4039            { type: "ScaleInput" },
    4140            { type: "MultipleChoiceInput" }
     
    4948            "StringInput": "Text line",
    5049            "TextInput": "Free text",
    51             "IntegerInput": "Integer number",
     50            "NumberInput": "Number",
    5251            "ScaleInput": "Scale",
    5352            "MultipleChoiceInput": "Multiple choice"
     
    6160            "StringInput": "Text",
    6261            "TextInput": "Text",
    63             "IntegerInput": "Integer",
     62            "NumberInput": "Number",
    6463            "ScaleInput": "Scale",
    6564            "MultipleChoiceInput": "MultipleChoice"
     
    8786        },
    8887        _setValueAttr: function(question) {
    89             this.propertiesForm.set('value', question);
    90             this._categories = question.categories || [];
    9188            this._setupListView();
    9289            this._setupCategories();
    9390            this._setupTopic(question.topic);
     91            this.propertiesForm.set('value', question);
     92            this._list.set('value', question.categories);
    9493        },
    9594        _getValueAttr: function() {
    9695            var value = this.propertiesForm.get('value');
    97             value.categories = this._categories;
     96            value.categories = this._list.get('value');
    9897            return value;
    9998        },
     
    125124        },
    126125        _setupListView: function() {
    127             this._list = new CategoryListView( {
    128                 removeCallback: lang.hitch(this, this._removeCategory)
     126            this._list = new CategoryListView({
    129127            }).placeAt(this.listNode);
    130128            this._list.startup();               
    131             for (var category in this._categories) {
    132                 this._list.appendItem(this._categories[category]);
    133             }   
    134129        },
    135130        _setupCategories: function() {
     
    144139                searchAttr: "id"
    145140            }, this.categoriesBoxNode);
    146             this._supportingWidgets.push(this._categorySelect);
    147 
    148141        },
    149142        _setupTopic: function(topic) {
     
    159152                value: topic
    160153            }, this.topicBoxNode);
    161             this._supportingWidgets.push(this._topicSelect);
    162154        },
    163155        _addCategory: function(item) {
    164             this._categories.push(item);
    165156            this._list.appendItem(item);
    166         },
    167         _removeCategory: function(item) {
    168             this._categories.splice(this._categories.indexOf(item), 1);
    169157        }
    170158
  • Dev/trunk/client/qed/model/widgets/QuestionListView.js

    r426 r441  
    11define([
    2     'dojo/_base/declare',
    3     'dojo/_base/lang',
    4     'dojo/dom-construct',
    5     '../../widgets/LineWithActionsWidget',
    6     '../../widgets/list/OrderedList'
    7 ],function(
    8     declare,
    9     lang,
    10     domConstruct,
    11     LineWithActionsWidget,
    12     OrderedList
    13 ){
    14     return declare([OrderedList],{
     2    "../../widgets/LineWithActionsWidget",
     3    "../../widgets/ListWidget",
     4    "dojo/_base/declare",
     5    "dojo/_base/lang",
     6    "dojo/dom-construct"
     7], function(LineWithActionsWidget, ListWidget, declare, lang, domConstruct) {
     8    return declare([ListWidget],{
    159        baseClass: 'rftSurveyListView',
    1610        type: 'question',
    1711
    18         _createAvatarNode: function(item){
     12        createAvatar: function(id, item){
    1913            return domConstruct.create("div",{
    2014                'class': 'dragAvatar',
     
    2216            });
    2317        },
    24         _createListNode: function(item) {
     18        createListElement: function(id, item) {
    2519            var w = new LineWithActionsWidget({
     20                id: id,
    2621                title: item.title,
    2722                'class': "inheritBgColor",
    2823                actions: {
    2924                    "Remove" : {
    30                         callback: lang.hitch(this, 'removeItem', item),
     25                        callback: lang.hitch(this, 'removeItem', id),
    3126                        properties: {
    3227                            blockButton: false,
     
    4843            });
    4944            w.startup();
    50             return w.domNode;
     45            return w;
    5146        }
    5247    });
  • Dev/trunk/client/qed/model/widgets/SurveyWidget.js

    r433 r441  
    11define([
    22    "../classes/Survey",
    3     "../widgets/QuestionWidgetFactory",
     3    "./questions/Factory",
    44    "dijit/_Container",
    55    "dijit/_TemplatedMixin",
  • Dev/trunk/client/qed/model/widgets/questions/Factory.js

    r435 r441  
    11define([
    2     "../../widgets/list/OrderedList",
    3     "../../widgets/list/_EditableListMixin",
     2    "./HeaderConfigWidget",
     3    "./HeaderWidget",
     4    "./MultipleChoiceInputConfigWidget",
     5    "./MultipleChoiceInputWidget",
     6    "./NumberInputConfigWidget",
     7    "./NumberInputWidget",
    48    "./ScaleInputConfigWidget",
    59    "./ScaleInputWidget",
    6     "dijit/_Container",
    7     "dijit/_TemplatedMixin",
     10    "./StringInputConfigWidget",
     11    "./StringInputWidget",
     12    "./TextConfigWidget",
     13    "./TextInputConfigWidget",
     14    "./TextInputWidget",
     15    "./TextWidget",
    816    "dijit/_WidgetBase",
    9     "dijit/form/Button",
    10     "dijit/form/CheckBox",
    11     "dijit/form/Form",
    12     "dijit/form/NumberSpinner",
    13     "dijit/form/RadioButton",
    14     "dijit/form/TextBox",
    15     "dijit/form/Textarea",
    16     "dojo/_base/array",
    17     "dojo/_base/declare",
    18     "dojo/_base/lang",
    19     "dojo/dom-construct",
    20     "dojox/layout/TableContainer"
    21 ], function(OrderedList, _EditableListMixin, ScaleInputConfigWidget, ScaleInputWidget, _Container, _TemplatedMixin, _WidgetBase, Button, CheckBox, Form, NumberSpinner, RadioButton, TextBox, Textarea, array, declare, lang, domConstruct, TableContainer) {
     17    "dojo/_base/declare"
     18], function(HeaderConfigWidget, HeaderWidget, MultipleChoiceInputConfigWidget, MultipleChoiceInputWidget, NumberInputConfigWidget, NumberInputWidget, ScaleInputConfigWidget, ScaleInputWidget, StringInputConfigWidget, StringInputWidget, TextConfigWidget, TextInputConfigWidget, TextInputWidget, TextWidget, _WidgetBase, declare) {
    2219    var factory = declare(null, {
    2320        createViewWidget: function(/*Object*/options) {
     
    3128        createEditWidget: function(/*Object*/options) {
    3229            var fun = this['create'+options.type+'EditWidget'];
    33             var view = fun !== undefined ? fun() : null;
    34             if (view) {
    35                 view.set('value', options);
    36             }
     30            var view = fun !== undefined ? fun(options) : null;
    3731            return view;
    3832        },
    3933
    40         createHeaderViewWidget: function(options) {
    41             return new HeaderView({
    42                 options: options
     34        createHeaderViewWidget: function(config) {
     35            return new HeaderWidget(config);
     36        },
     37        createHeaderEditWidget: function(config) {
     38            return new HeaderConfigWidget({
     39                value: config
    4340            });
    4441        },
    45         createHeaderEditWidget: function() {
    46             return new HeaderEdit();
     42
     43        createTextViewWidget: function(config) {
     44            return new TextWidget(config);
    4745        },
    48 
    49         createTextViewWidget: function(options) {
    50             return new TextView({
    51                 options: options
     46        createTextEditWidget: function(config) {
     47            return new TextConfigWidget({
     48                value: config
    5249            });
    53         },
    54         createTextEditWidget: function() {
    55             return new TextEdit();
    5650        },
    5751
     
    6256        },
    6357
    64         createStringInputViewWidget: function(options) {
    65             return new StringInputView({
    66                 options: options
     58        createStringInputViewWidget: function(config) {
     59            return new StringInputWidget(config);
     60        },
     61        createStringInputEditWidget: function(config) {
     62            return new StringInputConfigWidget({
     63                value: config
    6764            });
    6865        },
    69         createStringInputEditWidget: function() {
    70             return new StringInputEdit();
     66
     67        createTextInputViewWidget: function(config) {
     68            return new TextInputWidget(config);
     69        },
     70        createTextInputEditWidget: function(config) {
     71            return new TextInputConfigWidget({
     72                value: config
     73            });
    7174        },
    7275
    73         createTextInputViewWidget: function(options) {
    74             return new TextInputView({
    75                 options: options
     76        createNumberInputViewWidget: function(config) {
     77            return new NumberInputWidget(config);
     78        },
     79        createNumberInputEditWidget: function(config) {
     80            return new NumberInputConfigWidget({
     81                value: config
    7682            });
    7783        },
    78         createTextInputEditWidget: function() {
    79             return new TextInputEdit();
     84
     85        createMultipleChoiceInputViewWidget: function(config) {
     86            return new MultipleChoiceInputWidget(config);
    8087        },
    81 
    82         createIntegerInputViewWidget: function(options) {
    83             return new IntegerInputView({
    84                 options: options
     88        createMultipleChoiceInputEditWidget: function(config) {
     89            return new MultipleChoiceInputConfigWidget({
     90                value: config
    8591            });
    86         },
    87         createIntegerInputEditWidget: function() {
    88             return new IntegerInputEdit();
    89         },
    90 
    91         createMultipleChoiceInputViewWidget: function(options) {
    92             return new MultipleChoiceInputView({
    93                 options: options
    94             });
    95         },
    96         createMultipleChoiceInputEditWidget: function() {
    97             return new MultipleChoiceInputEdit();
    9892        },
    9993
     
    108102    });
    109103
    110     var DefaultEdit = declare([Form,_Container],{
    111         type: null,
    112         addChild: function(widget) {
    113             domConstruct.create("label",{
    114                 innerHTML: widget.title || ''
    115             },this.containerNode,'last');
    116             this.inherited(arguments,[widget]);
    117         },
    118         _getValueAttr: function() {
    119             var val = this.inherited(arguments);
    120             val.type = this.type;
    121             return val;
    122         }
    123     });
    124 
    125     var HeaderView = declare([_WidgetBase], {
    126         postCreate: function() {
    127             this.domNode.innerHTML = "<h2>"+this.options.content+"</h2>";
    128         }
    129     });
    130 
    131     var HeaderEdit = declare([DefaultEdit], {
    132         type: 'Header',
    133         postCreate: function() {
    134             this.inherited(arguments);
    135             this.addChild(new TextBox({
    136                 title: 'Content',
    137                 name: 'content'
    138             }));
    139         }
    140     });
    141 
    142     var TextView = declare([_WidgetBase], {
    143         postCreate: function() {
    144             this.domNode.innerHTML = "<p>"+this.options.content+"</p>";
    145         }
    146     });
    147 
    148     var TextEdit = declare([DefaultEdit], {
    149         type: 'Text',
    150         postCreate: function() {
    151             this.inherited(arguments);
    152             this.addChild(new Textarea({
    153                 title: 'Content',
    154                 name: 'content'
    155             }));
    156         }
    157     });
    158 
    159104    var DividerView = declare([_WidgetBase], {
    160105        postCreate: function() {
     
    163108    });
    164109
    165     var DefaultInputEdit = declare([DefaultEdit],{
    166         postCreate: function() {
    167             this.inherited(arguments);
    168             this.addChild(new TextBox({
    169                 title: 'Text',
    170                 name: 'text'
    171             }));
    172         }
    173     });
    174 
    175     var StringInputView = declare([_WidgetBase, _Container],{
    176         _textBox: null,
    177         postCreate: function() {
    178             this._textBox = new TextBox({
    179                 name: this.options.code || ''
    180             });
    181             this.addChild(this._textBox);
    182             this._textBox.startup();
    183         },
    184         _setReadOnlyAttr: function(value) {
    185             this._textBox.set('readOnly', value);
    186         },
    187         _getCodeAttr: function() {
    188             return this.options.code;
    189         },
    190         _getValueAttr: function() {
    191             return this._textBox.get('value') || "";
    192         },
    193         _setValueAttr: function(value) {
    194             this._textBox.set('value',value || "");
    195         }
    196     });
    197 
    198     var StringInputEdit = declare([DefaultInputEdit],{
    199         type: 'StringInput'
    200     });
    201 
    202     var TextInputView = declare([_WidgetBase, _Container], {
    203         _textArea: null,
    204         postCreate: function() {
    205             this._textArea = new Textarea({
    206                 name: this.options.code
    207             });
    208             this._textArea.set('maxLength', this.options.maxLength || 1000);
    209             this._textArea.set('value', this.options.defaultValue || "");
    210             this.addChild(this._textArea);
    211             this._textArea.startup();
    212         },
    213         _getCodeAttr: function() {
    214             return this.options.code;
    215         },
    216         _getValueAttr: function() {
    217             return this._textArea.get('value');
    218         },
    219         _setReadOnlyAttr: function(value) {
    220             this._textArea.set('readOnly', value);
    221         }
    222     });
    223 
    224     var TextInputEdit = declare([DefaultInputEdit], {
    225         type: 'TextInput',
    226         postCreate: function() {
    227             this.inherited(arguments);
    228             this.addChild(new NumberSpinner({
    229                 name: 'maxLength',
    230                 title: "Maximum length",
    231                 constraints: {
    232                     min: 0
    233                 }
    234             }));
    235         }
    236     });
    237 
    238     var IntegerInputView = declare([_WidgetBase, _Container], {
    239         _numberInput: null,
    240         postCreate: function() {
    241             this._numberInput = new NumberSpinner({
    242                 name: this.options.code || '',
    243                 constraints: {
    244                     min: this.options.min,
    245                     max: this.options.max,
    246                     smallDelta: this.options.step
    247                 }
    248             });
    249             this.addChild(this._numberInput);
    250             this._numberInput.startup();
    251         },
    252         _getCodeAttr: function() {
    253             return this.options.code;
    254         },
    255         _getValueAttr: function() {
    256             return this._numberInput.get('value');
    257         },
    258         _setReadOnlyAttr: function(value) {
    259             this._numberInput.set('readOnly', value);
    260         }
    261     });
    262 
    263     var IntegerInputEdit = declare([DefaultInputEdit], {
    264         type: 'IntegerInput',
    265         postCreate: function() {
    266             this.inherited(arguments);
    267             this.addChild(new NumberSpinner({
    268                 title: "Minimum",
    269                 name: 'min'
    270             }));
    271             this.addChild(new NumberSpinner({
    272                 title: "Maximum",
    273                 name: 'max'
    274             }));
    275             this.addChild(new NumberSpinner({
    276                 title: "Step",
    277                 name: 'step'
    278             }));
    279         }
    280     });
    281 
    282     var MultipleChoiceInputView = declare([_WidgetBase, _Container], {
    283         postCreate: function() {
    284             var table = new TableContainer({ cols: 1, customClass: "labelsAndValues"} );
    285 
    286             var Ctor = this.options.multiple === true ? CheckBox : RadioButton;
    287             array.forEach(this.options.items || [], function(item){
    288                 table.addChild(new Ctor({
    289                     name: this.options.code || '',
    290                     title: item
    291                 }));
    292             },this);
    293 
    294             this.addChild(table);
    295             table.startup();
    296         },
    297         _getCodeAttr: function() {
    298             return this.options.code;
    299         },
    300         _getValueAttr: function() {
    301             var checked = array.filter(this.getChildren(),function(child){
    302                 return child.get('checked');
    303             });
    304             if ( this.options.multiple ) {
    305                 return array.map(checked,function(child){
    306                     return child.get('value');
    307                 });
    308             } else {
    309                 return checked.length > 0 ? checked[0].get('value') : null;
    310             }
    311         },
    312         _setReadOnlyAttr: function(value) {
    313             array.forEach(this.getChildren(),function(child){
    314                 child.set('readOnly', value);
    315             },this);
    316         }
    317     });
    318 
    319     var MCOptionItem = declare([_WidgetBase,_TemplatedMixin,_Container],{
    320         templateString: '<div><span class="dojoDndHandle">=</span></div>',
    321         _textBox: null,
    322         postCreate: function() {
    323             this._textBox = new TextBox({});
    324             this.addChild(this._textBox);
    325             this._textBox.startup();
    326 
    327             var del = new Button({
    328                 label: "X",
    329                 onClick: lang.hitch(this,'onDelete')
    330             });
    331             this.addChild(del);
    332             del.startup();
    333         },
    334         _getValueAttr: function() {
    335             return this._textBox.set('value');
    336         },
    337         _setValueAttr: function(value) {
    338             this._textBox.set('value',value);
    339         },
    340         onDelete: function(){}
    341     });
    342 
    343     var MCOptionList = declare([OrderedList,_EditableListMixin],{
    344         type: 'multipleChoiceOption',
    345         withHandles: true,
    346         _createAvatarNode: function(item){
    347             return domConstruct.create("div",{
    348                 'class': 'dragAvatar',
    349                 innerHTML: item
    350             });
    351         },
    352         _createListNode: function(item) {
    353             var w = new MCOptionItem();
    354             w.startup();
    355             w.set('value',item);
    356             w.on('delete',lang.hitch(this,'_onRemove',w,item));
    357             return w.domNode;
    358         },
    359         _onRemove: function(w,item) {
    360             w.destroyRecursive();
    361             if ( this.removeCallback ) { this.removeCallback(item); }
    362             this.source.sync();
    363         }
    364     });
    365 
    366     var MultipleChoiceInputEdit = declare([_WidgetBase, _Container], {
    367         _multipleInput: null,
    368         postCreate: function() {
    369             var table = new TableContainer({ cols: 1, customClass: "labelsAndValues"} );
    370 
    371             this._multipleInput = new CheckBox({
    372                 title: "Allow multiple"
    373             });
    374             table.addChild(this._multipleInput);
    375             this._multipleInput.startup();
    376 
    377             var add = new Button({
    378                 label: "Add",
    379                 onClick: lang.hitch(this,'_addOption',"")
    380             });
    381             table.addChild(add);
    382             add.startup();
    383 
    384             this._optionsList = new MCOptionList();
    385             table.addChild(this._optionsList);
    386             this._optionsList.startup();
    387 
    388             this.addChild(table);
    389             table.startup();
    390         },
    391 
    392         _addOption: function() {
    393             this._optionsList.appendItems([""]);
    394         },
    395 
    396         _setValueAttr: function(value) {
    397             this._multipleInput.set('checked', value.multiple);
    398             this._optionsList.deleteItems();
    399             this._optionsList.appendItems(value.items || []);
    400         },
    401         _getValueAttr: function() {
    402             return {
    403                 type: "MultipleChoiceInput",
    404                 multiple: this._multipleInput.get('checked'),
    405                 items: array.map(this._optionsList.getItems(),function(item){
    406                     return item.get('value');
    407                 },this)
    408             };
    409         }
    410     });
    411 
    412110    return factory;
    413111});
  • Dev/trunk/client/qed/model/widgets/questions/ScaleInputConfigWidget.js

    r435 r441  
    11define([
    2     "dijit/_Container",
    3     "dijit/_TemplatedMixin",
    4     "dijit/_WidgetBase",
    5     "dijit/_WidgetsInTemplateMixin",
     2    "../../../widgets/ListWidget",
     3    "../../../widgets/_ComplexValueWidget",
    64    "dijit/form/Button",
    75    "dijit/form/RadioButton",
    86    "dijit/form/TextBox",
    97    "dijit/form/ValidationTextBox",
    10     "dijit/form/_FormMixin",
    118    "dojo/_base/array",
    129    "dojo/_base/declare",
     
    2017    "dijit/form/NumberTextBox",
    2118    "dijit/form/TextBox"
    22 ], function(_Container, _TemplatedMixin, _WidgetBase, _WidgetsInTemplateMixin, Button, RadioButton, TextBox, ValidationTextBox, _FormMixin, array, declare, event, lang, domAttr, domConstruct, domStyle, rowTemplate, template) {
     19], function(ListWidget, _ComplexValueWidget, Button, RadioButton, TextBox, ValidationTextBox, array, declare, event, lang, domAttr, domConstruct, domStyle, rowTemplate, template) {
    2320
    24     var Row = declare([_WidgetBase,_TemplatedMixin,_WidgetsInTemplateMixin,_Container,_FormMixin],{
     21    var Row = declare([_ComplexValueWidget],{
    2522        templateString: rowTemplate,
    2623        hasNA: true,
     
    2926            this.inherited(arguments);
    3027        },
    31         onDestroy: function(e) {
    32             this.destroyRecursive();
    33             event.stop(e);
    34             return false;
    35         },
     28        onDestroy: function(evt) {},
    3629        _setHasNAAttr: function(value) {
    3730            if ( value === true ) {
     
    4336    });
    4437   
    45     return declare([_WidgetBase,_TemplatedMixin,_WidgetsInTemplateMixin,_Container,_FormMixin],{
     38    return declare([_ComplexValueWidget],{
    4639        templateString: template,
    4740        baseClass: "qedScaleWidget",
    48         value: null,
    4941        _hasNA: false,
    5042        constuctor: function() {
     
    5244            this.value = {};
    5345        },
    54         onAddItem: function(e) {
    55             this._addItem();
     46        buildRendering: function() {
     47            this.inherited(arguments);
     48            this.itemsWidget = new ListWidget({
     49                name: "items",
     50                type: "ScaleItem",
     51                delay: 5,
     52                skipForm: true,
     53                createListElement: lang.hitch(this, "_createRowWidget"),
     54                createAvatar: lang.hitch(this, "_createAvatar")
     55            }, this.itemsNode);
     56        },
     57        _createRowWidget: function(id, item) {
     58            var widget = new Row({
     59                value: item,
     60                hasNA: this._hasNA,
     61                id: id,
     62                onDestroy: lang.hitch(this,function(evt){
     63                    this.itemsWidget.removeItem(id);
     64                    event.stop(evt);
     65                    return false;
     66                })
     67            });
     68            widget.startup();
     69            return widget;
     70        },
     71        _createAvatar: function(id, item) {
     72            return domConstruct.create("div", {
     73                innerHTML: item.text || "(empty item)"
     74            });
     75        },
     76        onAddNewItem: function(e) {
     77            this.itemsWidget.appendItem({});
    5678            event.stop(e);
    5779            return false;
    5880        },
    59         _clearItems: function() {
    60             domConstruct.empty(this.itemsNode);
    61         },
    62         _addItem: function(value) {
    63             var item = new Row({
    64                 name: 'items',
    65                 value: value,
    66                 hasNA: this._hasNA
    67             });
    68             item.placeAt(this.itemsNode);
    69             return item;
    70         },
    71         _setValueAttr: function(value) {
    72             this.inherited(arguments);
    73             this._clearItems();
    74             array.forEach(value.items, function(value){
    75                 this._addItem(value);
    76             }, this);
    77         },
    7881        _getValueAttr: function(){
    7982            var value = this.inherited(arguments);
    80             if ( value.items && !lang.isArray(value.items) ) {
    81                 value.items = [value.items];
    82             }
    8383            value.type = 'ScaleInput';
    8484            return value;
     
    8989        },
    9090        _updateNA: function(value) {
    91             array.forEach(this.getChildren(), function(child) {
     91            array.forEach(this.itemsWidget.getChildren(), function(child) {
    9292                child.set('hasNA', this._hasNA);
    9393            }, this);
  • Dev/trunk/client/qed/model/widgets/questions/ScaleInputWidget.js

    r435 r441  
    11define([
    2     "dijit/_Container",
    3     "dijit/_TemplatedMixin",
    4     "dijit/_WidgetBase",
     2    "../../../widgets/_ComplexValueWidget",
    53    "dijit/form/RadioButton",
    6     "dijit/form/_FormMixin",
    74    "dojo/_base/array",
    85    "dojo/_base/declare",
     
    118    "dojo/dom-construct",
    129    "dojo/text!./templates/ScaleInputWidget.html"
    13 ], function(_Container, _TemplatedMixin, _WidgetBase, RadioButton, _FormMixin, array, declare, lang, domAttr, domConstruct, template) {
    14     return declare([_WidgetBase,_TemplatedMixin,_Container,_FormMixin],{
     10], function(_ComplexValueWidget, RadioButton, array, declare, lang, domAttr, domConstruct, template) {
     11    return declare([_ComplexValueWidget],{
    1512        templateString: template,
    1613        baseClass: "qedScaleWidget",
     
    4138                domConstruct.create("th", {
    4239                    innerHTML: i.toString()
    43                 }, this.minNode, "after");
     40                }, this.maxNode, "before");
    4441            }
    4542        },
     
    6966                    className: 'max'
    7067                }, tr);
    71                 if ( this.naLabel !== null ) {
     68                if ( this.naLabel !== null && this.naLabel !== "" ) {
    7269                    td = domConstruct.create("td", {}, tr);
    7370                    radio = new RadioButton({
  • Dev/trunk/client/qed/model/widgets/questions/templates/ScaleInputConfigWidget.html

    r435 r441  
    4141        <td class="item">
    4242          <button data-dojo-type="dijit/form/Button"
    43                   data-dojo-attach-event="onClick:onAddItem">Click to add item</button>
     43                  data-dojo-attach-event="onClick:onAddNewItem">Click to add item</button>
    4444        </td>
    4545      </tr>
  • Dev/trunk/client/qed/pages/question.js

    r426 r441  
    4242        _refresh: function () {
    4343            this.titleNode.innerHTML = Question.DisplayTitle.get(this.question);
    44             this._toolkit.set('value',this.question);
    45             this._preview.appendItems(Question.Content.get(this.question));
     44            this._toolkit.set('value', this.question);
     45            this._preview.set('value', Question.Content.get(this.question));
    4646        },
    4747        _onSave: function(evt) {
    48             lang.mixin(this.question, this._toolkit.get('value'));
    49             Question.Content.set(this.question, this._preview.getItems());
    50             store.put(this.question)
    51             .then(function() {
    52                 Router.go('/questions');
    53             },function(err){
    54                 Content.notify(err,'error');
    55             });
     48            if ( this._preview.validate() ) {
     49                lang.mixin(this.question, this._toolkit.get('value'));
     50                Question.Content.set(this.question, this._preview.get('value'));
     51                store.put(this.question)
     52                .then(function() {
     53                    Router.go('/questions');
     54                },function(err){
     55                    Content.notify(err,'error');
     56                });
     57            }
    5658            if ( evt ) { event.stop( evt ); }
    5759            return false;
     
    6870
    6971            this._preview = new QuestionEditorPreview({
    70             },this.QuestionEditorPreviewNode);
     72                name: 'content',
     73                delay: 5,
     74                region: 'center'
     75            });
    7176            this._preview.startup();
    72             this._supportingWidgets.push(this._toolkit, this._preview);
     77            this.addChild(this._preview);
    7378        }
    7479    });
  • Dev/trunk/client/qed/pages/session.js

    r420 r441  
    5151        onSave: function(evt) {
    5252            lang.mixin(this.session,this.propertiesForm.get('value'));
    53             this.session.accounts = array.map(this._accountList.getItems(),function(item){
    54                 return store.getIdentity(item);
     53            this.session.accounts = array.map(this._accountList.get('value'),
     54                                              function(item){
     55                                                  return store.getIdentity(item);
    5556            });
    5657            store.put(this.session)
     
    7172        },
    7273        _setupAccountList: function() {
    73             this._accountList = new AccountListView().placeAt(this.accountListNode);
     74            this._accountList = new AccountListView({
     75                value: this.session.accounts
     76            }).placeAt(this.accountListNode);
    7477            this._accountList.startup();
    75             for (var account in this.session.accounts) {
    76                 this._accountList.insertItem(this.session.accounts[account]);
    77             }
    7878        },
    7979        _setupAutoComplete: function() {
  • Dev/trunk/client/qed/pages/survey.js

    r426 r441  
    5555        _setupListView: function() {
    5656            this.questionList = new QuestionListView({
    57                 region: 'center'
     57                region: 'center',
     58                name: 'questions'
    5859            },this.surveyListViewNode);
    5960            this.questionList.startup();
     
    6768                .then(lang.hitch(this,function(survey){
    6869                    this.survey = survey;
    69                     array.forEach(Survey.Questions.get(this.survey),
    70                         lang.hitch(this.questionList,'appendItem'));
     70                    this.questionList.set('value',
     71                                          Survey.Questions.get(this.survey));
    7172                    this.refresh();
    7273                }));
     
    7475        },
    7576        _includeQuestion: function(question) {
    76             this.questionList.insertItem(question);
     77            this.questionList.appendItem(question);
    7778        },
    7879        refresh: function() {
     
    9798        },
    9899        _onSave: function(evt) {
    99             this.survey.questions = this.questionList.getItems();
     100            this.survey.questions = this.questionList.get('value');
    100101            store.put(this.survey)
    101102            .then(function() {
  • Dev/trunk/client/qed/pages/templates/question.html

    r417 r441  
    1515        </div>
    1616    </div>
    17     <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'">
    18         <div data-dojo-attach-point="QuestionEditorPreviewNode"></div>
    19     </div>
    2017</div>
  • Dev/trunk/client/qed/stddeps.js

    r420 r441  
    2828
    2929    'qed/model/widgets/AccountListView',
    30     'qed/model/widgets/QuestionWidget',
    3130    'qed/model/widgets/SurveyFieldset',
    3231    'qed/model/widgets/SurveyRunFieldset',
     
    4140    'qed/widgets/ObjectBox',
    4241    'qed/widgets/Selector',
    43     'qed/widgets/TitleGroup',
    44     'qed/widgets/list/List',
    45     'qed/widgets/list/OrderedList'
     42    'qed/widgets/TitleGroup'
    4643],function(){});
  • Dev/trunk/client/qed/store.js

    r420 r441  
    99   
    1010    var couchStore = new CouchStore({
    11         target: 'data/couch/',
     11        target: 'data/couch/' /*,
    1212        validate: function(object) {
    1313            var result = jsonSchema.validate(object,schema);
     
    1818                return false;
    1919            }
    20         }
     20        }*/
    2121    });
    2222    var memoryStore = new Memory({
  • Dev/trunk/client/qed/tests/test_ScaleWidget.html

    r435 r441  
    1414          'dojo/when',
    1515          'dojo/parser',
    16           'qed/model/widgets/ScaleInputConfigWidget',
    17           'qed/model/widgets/ScaleInputWidget',
     16          'qed/model/widgets/questions/ScaleInputConfigWidget',
     17          'qed/model/widgets/questions/ScaleInputWidget',
    1818          'dojo/domReady!'
    1919      ], function(registry,dom,when,parser,ScaleInputConfigWidget,ScaleInputWidget){
     
    7373      <div>
    7474        <div id="configWidget"
    75              data-dojo-type="qed/model/widgets/ScaleInputConfigWidget"></div>
     75             data-dojo-type="qed/model/widgets/questions/ScaleInputConfigWidget"></div>
    7676        <button id="defaultConfigButton"
    7777                data-dojo-type="dijit/form/Button">Set Example</button>
Note: See TracChangeset for help on using the changeset viewer.