1 | define([ |
---|
2 | "dojo/_base/kernel", |
---|
3 | "dojo/_base/declare", |
---|
4 | "dojo/_base/array", |
---|
5 | "dojo/_base/event", |
---|
6 | "dojo/query", |
---|
7 | "dojo/dom-attr", |
---|
8 | "dojo/text!./resources/TriStateCheckBox.html", |
---|
9 | "dijit/form/ToggleButton" |
---|
10 | ], function(kernel, declare, array, event, query, domAttr, template, ToggleButton){ |
---|
11 | // module: |
---|
12 | // dojox/form/TriStateCheckBox |
---|
13 | // summary: |
---|
14 | // Checkbox with three states |
---|
15 | // |
---|
16 | |
---|
17 | /*===== |
---|
18 | ToggleButton = dijit.form.ToggleButton; |
---|
19 | =====*/ |
---|
20 | return declare("dojox.form.TriStateCheckBox", ToggleButton, |
---|
21 | { |
---|
22 | // summary: |
---|
23 | // Checkbox with three states |
---|
24 | |
---|
25 | templateString: template, |
---|
26 | |
---|
27 | baseClass: "dojoxTriStateCheckBox", |
---|
28 | |
---|
29 | // type: [private] String |
---|
30 | // type attribute on <input> node. |
---|
31 | // Overrides `dijit.form.Button.type`. Users should not change this value. |
---|
32 | type: "checkbox", |
---|
33 | |
---|
34 | /*===== |
---|
35 | // states: Array |
---|
36 | // States of TriStateCheckBox. |
---|
37 | // The value of This.checked should be one of these three states. |
---|
38 | states: [false, true, "mixed"], |
---|
39 | =====*/ |
---|
40 | |
---|
41 | /*===== |
---|
42 | // _stateLabels: Object |
---|
43 | // These characters are used to replace the image to show |
---|
44 | // current state of TriStateCheckBox in high contrast mode. |
---|
45 | _stateLabels: { |
---|
46 | "False": '', |
---|
47 | "True": '√', |
---|
48 | "Mixed": '≡' |
---|
49 | }, |
---|
50 | =====*/ |
---|
51 | |
---|
52 | /*===== |
---|
53 | // stateValues: Object |
---|
54 | // The values of the TriStateCheckBox in corresponding states. |
---|
55 | stateValues: { |
---|
56 | "False": "off", |
---|
57 | "True": "on", |
---|
58 | "Mixed": "mixed" |
---|
59 | }, |
---|
60 | =====*/ |
---|
61 | |
---|
62 | // _currentState: Integer |
---|
63 | // The current state of the TriStateCheckBox |
---|
64 | _currentState: 0, |
---|
65 | |
---|
66 | // _stateType: String |
---|
67 | // The current state type of the TriStateCheckBox |
---|
68 | // Could be "False", "True" or "Mixed" |
---|
69 | _stateType: "False", |
---|
70 | |
---|
71 | // readOnly: Boolean |
---|
72 | // Should this widget respond to user input? |
---|
73 | // In markup, this is specified as "readOnly". |
---|
74 | // Similar to disabled except readOnly form values are submitted. |
---|
75 | readOnly: false, |
---|
76 | |
---|
77 | constructor: function(){ |
---|
78 | // summary: |
---|
79 | // Runs on widget initialization to setup arrays etc. |
---|
80 | // tags: |
---|
81 | // private |
---|
82 | this.states = [false, true, "mixed"]; |
---|
83 | this._stateLabels = { |
---|
84 | "False": '', |
---|
85 | "True": '√', |
---|
86 | "Mixed": '≡' |
---|
87 | }; |
---|
88 | this.stateValues = { |
---|
89 | "False": "off", |
---|
90 | "True": "on", |
---|
91 | "Mixed": "mixed" |
---|
92 | }; |
---|
93 | }, |
---|
94 | |
---|
95 | // Override behavior from Button, since we don't have an iconNode |
---|
96 | _setIconClassAttr: null, |
---|
97 | |
---|
98 | _setCheckedAttr: function(/*String|Boolean*/ checked, /*Boolean?*/ priorityChange){ |
---|
99 | // summary: |
---|
100 | // Handler for checked = attribute to constructor, and also calls to |
---|
101 | // set('checked', val). |
---|
102 | // checked: |
---|
103 | // true, false or 'mixed' |
---|
104 | // description: |
---|
105 | // Controls the state of the TriStateCheckBox. Set this.checked, |
---|
106 | // this._currentState, value attribute of the <input type=checkbox> |
---|
107 | // according to the value of 'checked'. |
---|
108 | this._set("checked", checked); |
---|
109 | this._currentState = array.indexOf(this.states, checked); |
---|
110 | this._stateType = this._getStateType(checked); |
---|
111 | domAttr.set(this.focusNode || this.domNode, "checked", checked); |
---|
112 | domAttr.set(this.focusNode, "value", this.stateValues[this._stateType]); |
---|
113 | (this.focusNode || this.domNode).setAttribute("aria-checked", checked); |
---|
114 | this._handleOnChange(checked, priorityChange); |
---|
115 | }, |
---|
116 | |
---|
117 | setChecked: function(/*String|Boolean*/ checked){ |
---|
118 | // summary: |
---|
119 | // Deprecated. Use set('checked', true/false) instead. |
---|
120 | kernel.deprecated("setChecked("+checked+") is deprecated. Use set('checked',"+checked+") instead.", "", "2.0"); |
---|
121 | this.set('checked', checked); |
---|
122 | }, |
---|
123 | |
---|
124 | _setReadOnlyAttr: function(/*Boolean*/ value){ |
---|
125 | this._set("readOnly", value); |
---|
126 | domAttr.set(this.focusNode, "readOnly", value); |
---|
127 | this.focusNode.setAttribute("aria-readonly", value); |
---|
128 | }, |
---|
129 | |
---|
130 | _setValueAttr: function(/*String|Boolean*/ newValue, /*Boolean*/ priorityChange){ |
---|
131 | // summary: |
---|
132 | // Handler for value = attribute to constructor, and also calls to |
---|
133 | // set('value', val). |
---|
134 | // description: |
---|
135 | // During initialization, just saves as attribute to the <input type=checkbox>. |
---|
136 | // |
---|
137 | // After initialization, |
---|
138 | // when passed a boolean or the string 'mixed', controls the state of the |
---|
139 | // TriStateCheckBox. |
---|
140 | // If passed a string except 'mixed', changes the value attribute of the |
---|
141 | // TriStateCheckBox. Sets the state of the TriStateCheckBox to checked. |
---|
142 | if(typeof newValue == "string" && (array.indexOf(this.states, newValue) < 0)){ |
---|
143 | if(newValue == ""){ |
---|
144 | newValue = "on"; |
---|
145 | } |
---|
146 | this.stateValues["True"] = newValue; |
---|
147 | newValue = true; |
---|
148 | } |
---|
149 | if(this._created){ |
---|
150 | this._currentState = array.indexOf(this.states, newValue); |
---|
151 | this.set('checked', newValue, priorityChange); |
---|
152 | domAttr.set(this.focusNode, "value", this.stateValues[this._stateType]); |
---|
153 | } |
---|
154 | }, |
---|
155 | |
---|
156 | _setValuesAttr: function(/*Array*/ newValues){ |
---|
157 | // summary: |
---|
158 | // Handler for values = attribute to constructor, and also calls to |
---|
159 | // set('values', val). |
---|
160 | // newValues: |
---|
161 | // If the length of newValues is 1, it will replace the value of |
---|
162 | // the TriStateCheckBox in true state. Otherwise, the values of |
---|
163 | // the TriStateCheckBox in true state and 'mixed' state will be |
---|
164 | // replaced by the first two values in newValues. |
---|
165 | // description: |
---|
166 | // Change the value of the TriStateCheckBox in 'mixed' and true states. |
---|
167 | this.stateValues["True"] = newValues[0] ? newValues[0] : this.stateValues["True"]; |
---|
168 | this.stateValues["Mixed"] = newValues[1] ? newValues[1] : this.stateValues["False"]; |
---|
169 | }, |
---|
170 | |
---|
171 | _getValueAttr: function(){ |
---|
172 | // summary: |
---|
173 | // Hook so get('value') works. |
---|
174 | // description: |
---|
175 | // Returns value according to current state of the TriStateCheckBox. |
---|
176 | return this.stateValues[this._stateType]; |
---|
177 | }, |
---|
178 | |
---|
179 | startup: function(){ |
---|
180 | this.set("checked", this.params.checked || this.states[this._currentState]); |
---|
181 | domAttr.set(this.stateLabelNode, 'innerHTML', this._stateLabels[this._stateType]); |
---|
182 | this.inherited(arguments); |
---|
183 | }, |
---|
184 | |
---|
185 | _fillContent: function(/*DomNode*/ source){ |
---|
186 | // Override Button::_fillContent() since it doesn't make sense for CheckBox, |
---|
187 | // since CheckBox doesn't even have a container |
---|
188 | }, |
---|
189 | |
---|
190 | reset: function(){ |
---|
191 | this._hasBeenBlurred = false; |
---|
192 | this.stateValues = { |
---|
193 | "False" : "off", |
---|
194 | "True" : "on", |
---|
195 | "Mixed" : "mixed" |
---|
196 | }; |
---|
197 | this.set('checked', this.params.checked || this.states[0]); |
---|
198 | }, |
---|
199 | |
---|
200 | _onFocus: function(){ |
---|
201 | if(this.id){ |
---|
202 | query("label[for='"+this.id+"']").addClass("dijitFocusedLabel"); |
---|
203 | } |
---|
204 | this.inherited(arguments); |
---|
205 | }, |
---|
206 | |
---|
207 | _onBlur: function(){ |
---|
208 | if(this.id){ |
---|
209 | query("label[for='"+this.id+"']").removeClass("dijitFocusedLabel"); |
---|
210 | } |
---|
211 | this.inherited(arguments); |
---|
212 | }, |
---|
213 | |
---|
214 | _onClick: function(/*Event*/ e){ |
---|
215 | // summary: |
---|
216 | // Internal function to handle click actions - need to check |
---|
217 | // readOnly and disabled |
---|
218 | if(this.readOnly || this.disabled){ |
---|
219 | event.stop(e); |
---|
220 | return false; |
---|
221 | } |
---|
222 | if(this._currentState >= this.states.length - 1){ |
---|
223 | this._currentState = 0; |
---|
224 | }else{ |
---|
225 | this._currentState++; |
---|
226 | } |
---|
227 | this.set("checked", this.states[this._currentState]); |
---|
228 | domAttr.set(this.stateLabelNode, 'innerHTML', this._stateLabels[this._stateType]); |
---|
229 | return this.onClick(e); // user click actions |
---|
230 | }, |
---|
231 | |
---|
232 | _getStateType: function(/*String|Boolean*/ state){ |
---|
233 | // summary: |
---|
234 | // Internal function to return the type of a certain state |
---|
235 | // false: False |
---|
236 | // true: True |
---|
237 | // "mixed": Mixed |
---|
238 | return state ? (state == "mixed" ? "Mixed" : "True") : "False"; |
---|
239 | } |
---|
240 | } |
---|
241 | ); |
---|
242 | |
---|
243 | }); |
---|