source: Dev/trunk/src/client/qed-client/widgets/_ComplexValueMixin.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: 5.6 KB
Line 
1define([
2    "dijit/_Container",
3    "dijit/form/_FormMixin",
4    "dijit/registry",
5    "dojo/_base/array",
6    "dojo/_base/declare",
7    "dojo/_base/event",
8    "dojo/_base/lang",
9    "dojo/on"
10], function(_Container, _FormMixin, registry, array, declare, event, lang, on) {
11    return declare([_Container, _FormMixin], {
12        name: "",
13        value: null,
14        disabled: false,
15        readOnly: false,
16        _onChangeActive: false,
17        _onChangeHandle: null,
18        constructor: function() {
19            this._listenerMap = {};
20        },
21        buildRendering: function() {
22            // capture child events
23            this.inherited(arguments);
24            if ( this.domNode.tagName.toLowerCase() !== "form" ) {
25                console.warn("Not scoping a _ComplexValueMixin in a form element can cause name clashes. E.g. radio buttons might stop working correctly. It is recommended to use <form> as the root element in your template for", this.declaredClass);
26            }
27            this.own(on(this.domNode,'submit',
28                        lang.hitch(this,'_handleSubmit')));
29        },
30        create: function() {
31            this.inherited(arguments);
32            this._onChangeActive = true;
33        },
34        postCreate: function() {
35            array.forEach(this._getDescendantFormWidgets(),
36                          this.connectChildsChanges,
37                          this);
38        },
39        connectChildsChanges: function(child) {
40            this.own(child.on('change',
41                              lang.hitch(this,'_handleChildChange')));
42        },
43        // Yuk, _setValueAttr is taken directly from _FromMixin only
44        // to add the priorityChange parameter
45                _setValueAttr: function(obj, priorityChange) {
46            this._setValueInternal(obj, priorityChange);
47
48                        var map = { };
49                        array.forEach(this._getDescendantFormWidgets(), function(widget){
50                                if(!widget.name){ return; }
51                                var entry = map[widget.name] || (map[widget.name] = [] );
52                                entry.push(widget);
53                        });
54
55                        for(var name in map){
56                                if (map.hasOwnProperty(name)) {
57                    var widgets = map[name],
58                        values = lang.getObject(name, false, obj);
59
60                    if (values === undefined) {
61                        continue;
62                    }
63                    values = [].concat(values);
64                    if (typeof widgets[0].checked === 'boolean') {
65                        array.forEach(widgets, function(w){
66                            w.set('value',
67                                  array.indexOf(values,w._get('value'))!==-1,
68                                  priorityChange);
69                        });
70                    } else if (widgets[0].multiple) {
71                        widgets[0].set('value', values, priorityChange);
72                    } else {
73                        array.forEach(widgets, function(w, i){
74                            w.set('value', values[i], priorityChange);
75                        });
76                    }
77                                }
78                        }
79           
80            if ( priorityChange !== null ) {
81                this._handleOnChange(this.value);
82            }
83                },
84        // use _setValueInternal instead of 'this.value = ?' or
85        // 'this._set('value',?)' so proper events will be generated.
86        _setValueInternal: function(value,priorityChange) {
87            this._set('value',value);
88            if ( priorityChange !== null ){
89                this._handleOnChange(this.value);
90            }
91        },
92        _setDisabledAttr: function(disabled) {
93            this.inherited(arguments);
94            this._set('disabled',disabled);
95            array.forEach(
96                this._getDescendantFormWidgets(),
97                function(child) {
98                    child.set('disabled', disabled);
99                },this);
100        },
101        _setReadOnlyAttr: function(readOnly) {
102            this.inherited(arguments);
103            this._set('readOnly',readOnly);
104            array.forEach(
105                this._getDescendantFormWidgets(),
106                function(child) {
107                    child.set('readOnly', readOnly);
108                },this);
109        },
110
111        focus: function() {
112            /*var children = this._getDescendantFormWidgets();
113            if ( children.length > 0 ) {
114                children[0].focus();
115            }*/
116        },
117        addChild: function(child) {
118            this.inherited(arguments);
119            this.connectChildsChanges(child);
120        },
121
122        _handleSubmit: function(evt) {
123            if ( this._started ) {
124                var node = this.domNode;
125                var widget;
126                while ( node ) {
127                    node = node.parentNode;
128                    widget = registry.byNode(node);
129                    if ( widget &&
130                         typeof widget._onSubmit === "function" ) {
131                        widget._onSubmit(evt);
132                        break;
133                    }
134                }
135            }
136            if (evt) { event.stop(evt); }
137            return false;
138        },
139        _handleChildChange: function() {
140            this._setValueInternal(this.get('value'));
141            return false;
142        },
143        _handleOnChange: function(value) {
144            if ( this._onChangeActive &&
145                 !(this.readOnly || this.disabled) ) {
146                if ( this._onChangeHandle ) {
147                    this._onChangeHandle.remove();
148                }
149                this._onChangeHandle = this.defer(function(){
150                    this._onChangeHandle = null;
151                    this.onChange(value);
152                });
153            }
154        },
155        onChange: function() {}
156    });
157});
Note: See TracBrowser for help on using the repository browser.