source: Dev/trunk/src/client/qed-client/model/widgets/QuestionEditorPreviewItem.js

Last change on this file was 525, checked in by hendrikvanantwerpen, 11 years ago
  • Allow empty subcodes.
  • Use HTTPResult exclusively on server (no more q).
  • Set readonly & disabled on ourselves as well in _ComplexValueMixin
  • Split server into several modules.
  • Check codes on the variable level, not question level.
  • We can add modules in design documents now.
File size: 8.0 KB
Line 
1define([
2    "../../widgets/_ComplexValueWidget",
3    "./questions/Factory",
4    "dijit/_Container",
5    "dijit/_TemplatedMixin",
6    "dijit/_WidgetBase",
7    "dijit/_WidgetsInTemplateMixin",
8    "dojo/_base/array",
9    "dojo/_base/declare",
10    "dojo/_base/event",
11    "dojo/_base/fx",
12    "dojo/_base/lang",
13    "dojo/dom-class",
14    "dojo/dom-geometry",
15    "dojo/dom-style",
16    "dojo/on",
17    "dojo/text!./templates/QuestionEditorPreviewItem.html"
18], function(_ComplexValueWidget, QuestionWidgetFactory, _Container, _TemplatedMixin, _WidgetBase, _WidgetsInTemplateMixin, array, declare, event, fx, lang, domClass, domGeom, domStyle, on, template) {
19    return declare([_ComplexValueWidget], {
20        templateString: template,
21        baseClass: "qedQuestionEditorPreviewItem",
22        previousContentHeight: 200,
23        value: null,
24        innerWidget: null,
25        foldDuration: [250, 250],
26        animation: null,
27        _editing: null,
28        _factory: new QuestionWidgetFactory(),
29
30        startup: function() {
31            if ( this._started ){ return; }
32            this.inherited(arguments);
33            this.own(this.foldButton.on('click',
34                        lang.hitch(this, 'onToggleFold')));
35            this.own(this.removeButton.on('click',
36                        lang.hitch(this, '_handleDestroy')));
37            this.own(this.editButton.on('click',
38                        lang.hitch(this, 'onToggleEdit')));
39            this.showView();
40        },
41        _handleDestroy: function(evt) {
42            this.emit('destroy');
43            if ( evt ) { event.stop(evt); }
44            return false;
45        },
46        _getValueAttr: function() {
47            if ( this._editing === true ) {
48                return this.innerWidget.get('value');
49            }
50            return this.value;
51        },
52        _setValueAttr: function(value,priorityChange) {
53            this._setValueInternal(value,priorityChange);
54            if ( this._editing  === true ) {
55                this._showEditWidget();
56            } else {
57                this._showViewWidget();
58            }
59        },
60        _setReadOnlyAttr: function(readOnly) {
61            this._set('readOnly',readOnly);
62            this._setReadOnlyChildren(this.readOnly);
63            this._updateRemoveBtn();
64        },
65        _setDisabledAttr: function(disabled) {
66            this._set('disabled',disabled);
67            this._setDisabledChildren(this.disabled);
68            this._updateRemoveBtn();
69        },
70        _updateRemoveBtn: function() {
71            var node = this.removeButton.domNode;
72            if ( this.readOnly || this.disabled ) {
73                domClass.add(node, 'dijitHidden');
74            } else {
75                domClass.remove(node, 'dijitHidden');
76            }
77        },
78        _setDisabledChildren: function(disabled) {
79            array.forEach(this._getDescendantFormWidgets(),function(widget){
80                widget.set('disabled',disabled);
81            });
82        },
83        _setReadOnlyChildren: function(readOnly) {
84            array.forEach(this._getDescendantFormWidgets(),function(widget){
85                widget.set('readOnly',readOnly);
86            });
87        },
88        validate: function() {
89            return this._editing === false || this.innerWidget.validate();
90        },
91        focus: function() {
92            if ( this._editing === true ) {
93                this.innerWidget.focus();
94            }
95        },
96        showView: function() {
97            if ( this._editing === true ) {
98                if (!this.innerWidget.validate || this.innerWidget.validate() ) {
99                    this._setValueInternal(this.innerWidget.get('value'));
100                    this._showViewWidget();
101                }
102            }
103        },
104        showEdit: function() {
105            if ( this._editing === false ) {
106                this._showEditWidget();
107            }
108        },
109        onToggleEdit: function(evt) {
110            if ( this._editing === true ) {
111                this.showView();
112            } else {
113                this.showEdit();
114            }
115            if ( evt ) { event.stop(evt); }
116            return false;
117        },
118        _showViewWidget: function() {
119            // we pass an empty code, just in case the widget depends
120            // on it,but we don't know the actual code here.
121            var newWidget = this._factory.createViewWidget( lang.mixin({code:""},this.value) );
122            if ( newWidget ) {
123                this._destroyInnerWidget();
124                this.innerWidget = newWidget;
125                this.addChild(this.innerWidget);
126                this._setReadOnlyChildren(true);
127                this._setDisabledChildren(true);
128                this.titleNode.innerHTML = this.value.type+" [preview]";
129                domClass.replace(this.editButton.iconNode, "rftIconEdit", "rftIconAccept");
130                this.editButton.set("label", "Edit");
131                this._editing = false;
132            }
133        },
134        _showEditWidget: function() {
135            var newWidget = this._factory.createEditWidget( this.value );
136            if ( newWidget ) {
137                this._destroyInnerWidget();
138                this.innerWidget = newWidget;
139                this.addChild(this.innerWidget);
140                this._setReadOnlyChildren(this.readOnly);
141                this._setDisabledChildren(this.disabled);
142                this.titleNode.innerHTML = this.value.type+" [editing]";
143                domClass.replace(this.editButton.iconNode, "rftIconAccept", "rftIconEdit");
144                this.editButton.set("label", "Done");
145                this._editing = true;
146            }
147        },
148        _destroyInnerWidget: function() {
149            if ( this.innerWidget !== null ) {
150                if ( this._editing === true ) {
151                    // because the widget doesn't generate an event
152                    // unless it loses focus, we set the value here
153                    // just to be sure not to lose any user input
154                    this._setValueInternal(this.innerWidget.get('value'));
155                }
156                this.removeChild(this.innerWidget);
157                this.innerWidget.destroyRecursive();
158                this.innerWidget = null;
159            }
160        },
161        onToggleFold: function(evt) {
162            if (!this.animation) {
163                if (!domClass.contains(this.domNode, "fold")) {
164                    this.previousContentHeight = domGeom.getMarginBox(this.innerNode).h;
165                    this.animation = fx.animateProperty({
166                        node: this.innerNode,
167                        duration: this.foldDuration[0],
168                        properties: {
169                            height: 1
170                        },
171                        onEnd: lang.hitch(this, function(){
172                            domClass.add(this.domNode, "fold");
173                            this.animation = null;
174                        })
175                    }).play();
176                    domClass.replace(this.foldButton.iconNode, "rftIconHalfArrowDown", "rftIconHalfArrowUp");
177                } else {
178                    this.animation = fx.animateProperty({
179                        node: this.innerNode,
180                        duration: this.foldDuration[1],
181                        properties: {
182                            height: this.previousContentHeight
183                        },
184                        onEnd: lang.hitch(this, function(){
185                            domClass.remove(this.domNode, "fold");
186                            domStyle.set(this.innerNode, 'height', 'auto');
187                            this.animation = null;
188                        })
189                    }).play();
190                    domClass.replace(this.foldButton.iconNode, "rftIconHalfArrowUp", "rftIconHalfArrowDown");
191                }
192            }
193            if ( evt ) { event.stop(evt); }
194            return false;
195        }
196
197    });
198});
Note: See TracBrowser for help on using the repository browser.