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