source: Dev/trunk/src/client/qed-client/widgets/_ComplexValueMixin.js @ 513

Last change on this file since 513 was 513, checked in by hendrikvanantwerpen, 11 years ago
  • Another shot at getting change events right for _ComplexValueMixin. Our previous approach made it impossible to detect if a change was cause during startup. Now we work purely with widget 'change' events. Children are connected during postCreate, addChild. If you add children otherwise you need to call connectChildsChanges yourself. Also to make sure events are generated, use _setValueInternal if you really need to set the value attribute yourself.
  • Removed unused widget.
File size: 5.4 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', array.indexOf(values, w._get('value')) !== -1, priorityChange);
67                        });
68                    } else if (widgets[0].multiple) {
69                        widgets[0].set('value', values, priorityChange);
70                    } else {
71                        array.forEach(widgets, function(w, i){
72                            w.set('value', values[i], priorityChange);
73                        });
74                    }
75                                }
76                        }
77           
78            if ( priorityChange !== null ) {
79                this._handleOnChange(this.value);
80            }
81                },
82        // use _setValueInternal instead of 'this.value = ?' or
83        // 'this._set('value',?)' so proper events will be generated.
84        _setValueInternal: function(value,priorityChange) {
85            this._set('value',value);
86            if ( priorityChange !== null ){
87                this._handleOnChange(this.value);
88            }
89        },
90        _setDisabledAttr: function(disabled) {
91            this.inherited(arguments);
92            array.forEach(
93                this._getDescendantFormWidgets(),
94                function(child) {
95                    child.set('disabled', disabled);
96                },this);
97        },
98        _setReadOnlyAttr: function(readOnly) {
99            this.inherited(arguments);
100            array.forEach(
101                this._getDescendantFormWidgets(),
102                function(child) {
103                    child.set('readOnly', readOnly);
104                },this);
105        },
106
107        focus: function() {
108            /*var children = this._getDescendantFormWidgets();
109            if ( children.length > 0 ) {
110                children[0].focus();
111            }*/
112        },
113        addChild: function(child) {
114            this.inherited(arguments);
115            this.connectChildsChanges(child);
116        },
117
118        _handleSubmit: function(evt) {
119            if ( this._started ) {
120                var node = this.domNode;
121                var widget;
122                while ( node ) {
123                    node = node.parentNode;
124                    widget = registry.byNode(node);
125                    if ( widget &&
126                         typeof widget._onSubmit === "function" ) {
127                        widget._onSubmit(evt);
128                        break;
129                    }
130                }
131            }
132            if (evt) { event.stop(evt); }
133            return false;
134        },
135        _handleChildChange: function() {
136            this._setValueInternal(this.get('value'));
137            return false;
138        },
139        _handleOnChange: function(value) {
140            if ( this._onChangeActive &&
141                 !(this.readOnly || this.disabled) ) {
142                if ( this._onChangeHandle ) {
143                    this._onChangeHandle.remove();
144                }
145                this._onChangeHandle = this.defer(function(){
146                    this._onChangeHandle = null;
147                    this.onChange(value);
148                });
149            }
150        },
151        onChange: function() {}
152    });
153});
Note: See TracBrowser for help on using the repository browser.