]>
Commit | Line | Data |
---|---|---|
f0cfe83e AD |
1 | define("dijit/form/MultiSelect", [ |
2 | "dojo/_base/array", // array.indexOf, array.map | |
3 | "dojo/_base/declare", // declare | |
4 | "dojo/dom-geometry", // domGeometry.setMarginBox | |
5 | "dojo/query", // query | |
6 | "./_FormValueWidget" | |
7 | ], function(array, declare, domGeometry, query, _FormValueWidget){ | |
8 | ||
9 | // module: | |
10 | // dijit/form/MultiSelect | |
11 | ||
12 | return declare("dijit.form.MultiSelect", _FormValueWidget, { | |
13 | // summary: | |
14 | // Widget version of a `<select multiple=true>` element, | |
15 | // for selecting multiple options. | |
16 | ||
17 | // size: Number | |
18 | // Number of elements to display on a page | |
19 | // NOTE: may be removed in version 2.0, since elements may have variable height; | |
20 | // set the size via style="..." or CSS class names instead. | |
21 | size: 7, | |
22 | ||
23 | templateString: "<select multiple='true' ${!nameAttrSetting} data-dojo-attach-point='containerNode,focusNode' data-dojo-attach-event='onchange: _onChange'></select>", | |
24 | ||
25 | addSelected: function(/*dijit/form/MultiSelect*/ select){ | |
26 | // summary: | |
27 | // Move the selected nodes of a passed Select widget | |
28 | // instance to this Select widget. | |
29 | // | |
30 | // example: | |
31 | // | // move all the selected values from "bar" to "foo" | |
32 | // | dijit.byId("foo").addSelected(dijit.byId("bar")); | |
33 | ||
34 | select.getSelected().forEach(function(n){ | |
35 | if(this.restoreOriginalText){ | |
36 | n.text = this.enforceTextDirWithUcc(this.restoreOriginalText(n), n.text); | |
37 | } | |
38 | this.containerNode.appendChild(n); | |
39 | // scroll to bottom to see item | |
40 | // cannot use scrollIntoView since <option> tags don't support all attributes | |
41 | // does not work on IE due to a bug where <select> always shows scrollTop = 0 | |
42 | this.domNode.scrollTop = this.domNode.offsetHeight; // overshoot will be ignored | |
43 | // scrolling the source select is trickier esp. on safari who forgets to change the scrollbar size | |
44 | var oldscroll = select.domNode.scrollTop; | |
45 | select.domNode.scrollTop = 0; | |
46 | select.domNode.scrollTop = oldscroll; | |
47 | },this); | |
48 | this._set('value', this.get('value')); | |
49 | }, | |
50 | ||
51 | getSelected: function(){ | |
52 | // summary: | |
53 | // Access the NodeList of the selected options directly | |
54 | return query("option",this.containerNode).filter(function(n){ | |
55 | return n.selected; // Boolean | |
56 | }); // dojo/NodeList | |
57 | }, | |
58 | ||
59 | _getValueAttr: function(){ | |
60 | // summary: | |
61 | // Hook so get('value') works. | |
62 | // description: | |
63 | // Returns an array of the selected options' values. | |
64 | ||
65 | // Don't call getSelect.map() because it doesn't return a real array, | |
66 | // and that messes up dojo.toJson() calls like in the Form.html test | |
67 | return array.map(this.getSelected(), function(n){ | |
68 | return n.value; | |
69 | }); | |
70 | }, | |
71 | ||
72 | multiple: true, // for Form | |
73 | ||
74 | _setValueAttr: function(/*Array*/ values, /*Boolean?*/ priorityChange){ | |
75 | // summary: | |
76 | // Hook so set('value', values) works. | |
77 | // description: | |
78 | // Set the value(s) of this Select based on passed values | |
79 | query("option",this.containerNode).forEach(function(n){ | |
80 | n.selected = (array.indexOf(values,n.value) != -1); | |
81 | }); | |
82 | this.inherited(arguments); | |
83 | }, | |
84 | ||
85 | invertSelection: function(/*Boolean?*/ onChange){ | |
86 | // summary: | |
87 | // Invert the selection | |
88 | // onChange: Boolean | |
89 | // If false, onChange is not fired. | |
90 | var val = []; | |
91 | query("option",this.containerNode).forEach(function(n){ | |
92 | if(!n.selected){ val.push(n.value); } | |
93 | }); | |
94 | this._setValueAttr(val, !(onChange === false || onChange == null)); | |
95 | }, | |
96 | ||
97 | _onChange: function(/*Event*/){ | |
98 | this._handleOnChange(this.get('value'), true); | |
99 | }, | |
100 | ||
101 | // for layout widgets: | |
102 | resize: function(/*Object*/ size){ | |
103 | if(size){ | |
104 | domGeometry.setMarginBox(this.domNode, size); | |
105 | } | |
106 | }, | |
107 | ||
108 | postCreate: function(){ | |
109 | this._set('value', this.get('value')); | |
110 | this.inherited(arguments); | |
111 | }, | |
112 | ||
113 | _setTextDirAttr: function(textDir){ | |
114 | // to insure the code executed only when _BidiSupport loaded, and only | |
115 | // when there was a change in textDir | |
116 | if((this.textDir != textDir || !this._created) && this.enforceTextDirWithUcc){ | |
117 | this._set("textDir", textDir); | |
118 | ||
119 | query("option",this.containerNode).forEach(function(option){ | |
120 | // If the value wasn't defined explicitly, it the same object as | |
121 | // option.text. Since the option.text will be modified (by wrapping of UCC) | |
122 | // we want to save the original option.value for form submission. | |
123 | if(!this._created && option.value === option.text){ | |
124 | option.value = option.text; | |
125 | } | |
126 | // apply the bidi support | |
127 | option.text = this.enforceTextDirWithUcc(option, option.originalText || option.text); | |
128 | },this); | |
129 | } | |
130 | } | |
131 | ||
132 | }); | |
133 | ||
134 | }); |