]> git.pond.sub.org Git - eow/blob - static/dojo-release-1.1.1/dojox/form/DropDownSelect.js
add Dojo 1.1.1
[eow] / static / dojo-release-1.1.1 / dojox / form / DropDownSelect.js
1 if(!dojo._hasResource["dojox.form.DropDownSelect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["dojox.form.DropDownSelect"] = true;
3 dojo.provide("dojox.form.DropDownSelect");
4
5 dojo.require("dijit.form.Button");
6 dojo.require("dijit.Menu");
7
8 dojo.require("dojo.data.ItemFileWriteStore");
9
10 dojo.declare("dojox.form.DropDownSelect", dijit.form.DropDownButton, {
11         // summary:
12         //              This is a "Styleable" select box - it is basically a DropDownButton which
13         //              can take as its input a <select>.
14
15         baseClass: "dojoxDropDownSelect",
16
17         /*=====
18         dojox.form.__SelectOption = function(){
19                 //      value: String
20                 //              The value of the option.  Setting to empty (or missing) will
21                 //              place a separator at that location
22                 //      label: String
23                 //              The label for our option.  It can contain html tags.
24                 this.value = value;
25                 this.label = label;
26         }
27         =====*/
28
29         // options: dojox.form.__SelectOption[]
30         //              our set of options
31         options: null,
32         
33         // emptyLabel: string
34         //              What to display in an "empty" dropdown
35         emptyLabel: "",
36         
37         // _isPopulated: boolean
38         //              Whether or not we have been populated
39         _isPopulated: false,
40
41         _addMenuItem: function(/* dojox.form.__SelectOption */ option){
42                 // summary:
43                 //              For the given option, add a menu item to our dropdown
44                 //              If the option doesn't have a value, then a separator is added 
45                 //              in that place.
46                 var menu = this.dropDown;
47
48                 if(!option.value){
49                         // We are a separator (no label set for it)
50                         menu.addChild(new dijit.MenuSeparator());
51                 }else{
52                         // Just a regular menu option
53                         var click = dojo.hitch(this, "setAttribute","value",option);
54                         var mi = new dijit.MenuItem({
55                                 id: this.id + "_item_" + option.value,
56                                 label: option.label,
57                                 onClick: click
58                         });
59                         menu.addChild(mi);
60
61                 }
62         },
63
64         _resetButtonState: function(){
65                 // summary: 
66                 //              Resets the menu and the length attribute of the button - and
67                 //              ensures that the label is appropriately set.
68                 var len = this.options.length;
69                 
70                 // reset the menu to make it "populatable on the next click
71                 var dropDown = this.dropDown;
72                 dojo.forEach(dropDown.getChildren(), function(child){
73                         child.destroyRecursive();
74                 });
75                 this._isPopulated = false;
76                 
77                 // Set our length attribute and our value
78                 this.setAttribute("readOnly", (len === 1));
79                 this.setAttribute("disabled", (len === 0));     
80                 this.setAttribute("value", this.value);
81         },
82         
83         _updateSelectedState: function(){
84                 // summary:
85                 //              Sets the "selected" class on the item for styling purposes
86                 var val = this.value;
87                 if(val){
88                         var testId = this.id + "_item_" + val;
89                         dojo.forEach(this.dropDown.getChildren(), function(child){
90                                 dojo[child.id === testId ? "addClass" : "removeClass"](child.domNode,
91                                                                                                                 this.baseClass + "SelectedOption");
92                         }, this);
93                 }
94         },
95         
96         addOption: function(/* dojox.form.__SelectOption or string, optional */ value, /* string? */ label){
97                 // summary:
98                 //              Adds an option to the end of the select.  If value is empty or 
99                 //              missing, a separator is created instead.
100                 
101                 this.options.push(value.value ? value : { value:value, label:label });
102         },
103         
104         removeOption: function(/* string, dojox.form.__SelectOption or number */ valueOrIdx){
105                 // summary:
106                 //              Removes the given option
107                 this.options = dojo.filter(this.options, function(node, idx){
108                         return !((typeof valueOrIdx === "number" && idx === valueOrIdx) ||
109                                         (typeof valueOrIdx === "string" && node.value === valueOrIdx) ||
110                                         (valueOrIdx.value && node.value === valueOrIdx.value));
111                 });
112         },
113         
114         setOptionLabel: function(/*string*/ value, /*string*/ label){
115                 dojo.forEach(this.options, function(node){
116                         if(node.value === value){
117                                 node.label = label;
118                         }
119                 });
120         },
121
122         destroy: function(){
123                 // summary:
124                 //              Clear out an outstanding hack handle
125                 if(this._labelHackHandle){
126                         clearTimeout(this._labelHackHandle);
127                 }
128                 this.inherited(arguments);
129         },
130         
131         setLabel: function(/* string */ content){
132                 // summary:
133                 //              Wraps our label in a div - that way, our rich text can work
134                 //              correctly.
135
136                 content = '<div class=" ' + this.baseClass + 'Label">' +
137                                         content +
138                                         '</div>';
139                 //              Because FF2 has a problem with layout, we need to delay this
140                 //              call for it.
141                 if(this._labelHackHandle){
142                         clearTimeout(this._labelHackHandle);
143                 }
144                 if(dojo.isFF === 2){
145                         this._labelHackHandle = setTimeout(dojo.hitch(this, function(){
146                                 this._labelHackHandle = null;
147                                 dijit.form.DropDownButton.prototype.setLabel.call(this, content);
148                         }), 0);
149                 }else{
150                         this.inherited(arguments);
151                 }
152         },
153
154         setAttribute: function(/*string*/ attr, /* anything */ value){
155                 // summary: sometime we get called to set our value - we need to 
156                 //                      make sure and route those requests through _setValue()
157                 //                      instead.
158                 if(attr === "value"){
159                         // If a string is passed, then we set our value from looking it up.
160                         if(typeof value === "string"){
161                                 value = dojo.filter(this.options, function(node){
162                                         return node.value === value;
163                                 })[0];
164                         }
165                         
166                         // If we don't have a value, try to show the first item
167                         if(!value){
168                                 value = this.options[0] || { value: "", label: "" };
169                         }
170                         this.value = value.value;
171                         if(this._started){
172                                 this.setLabel(value.label || this.emptyLabel || "&nbsp;");
173                         }
174                         this._handleOnChange(value.value);
175                         value = this.value;
176                 }else{
177                         this.inherited(arguments);
178                 }
179         },
180         
181         _fillContent: function(){
182                 // summary:  
183                 //              Loads our options and sets up our dropdown correctly.  We 
184                 //              don't want any content, so we don't call any inherit chain
185                 //              function.
186                 var opts = this.options;
187                 if(!opts){
188                         opts = this.options = this.srcNodeRef ? dojo.query(">", 
189                                                 this.srcNodeRef).map(function(node){
190                                                         if(node.getAttribute("type") === "separator"){
191                                                                 return { value: "", label: "" };
192                                                         }
193                                                         return { value: node.getAttribute("value"),
194                                                                                 label: String(node.innerHTML) };
195                                                 }, this) : [];
196                 }
197                 
198                 // Set the value to be the first, or the selected index
199                 if(opts.length && !this.value){
200                         var si = this.srcNodeRef.selectedIndex;
201                         this.value = opts[si != -1 ? si : 0].value;
202                 }
203                 
204                 // Create the dropDown widget
205                 this.dropDown = new dijit.Menu();
206         },
207
208         postCreate: function(){
209                 // summary: sets up our event handling that we need for functioning
210                 //                      as a select
211
212                 this.inherited(arguments);
213
214                 // Make our event connections for updating state
215                 var fx = function(){
216                         dojo[this._opened ? "addClass" : "removeClass"](this.focusNode,
217                                                                                                                 this.baseClass + "ButtonOpened");
218                 };
219                 this.connect(this, "_openDropDown", fx);
220                 this.connect(this, "_closeDropDown", fx);
221                 this.connect(this, "onChange", "_updateSelectedState");
222                 this.connect(this, "addOption", "_resetButtonState");
223                 this.connect(this, "removeOption", "_resetButtonState");
224                 this.connect(this, "setOptionLabel", "_resetButtonState");
225         },
226
227         startup: function(){
228                 // summary: 
229                 //              FF2 has layout problems if the reset call isn't done on a
230                 //              slight delay
231                 this.inherited(arguments);
232                 if(dojo.isFF === 2){
233                         setTimeout(dojo.hitch(this, this._resetButtonState), 0);
234                 }else{
235                         this._resetButtonState();
236                 }
237         },
238         
239         _populate: function(/* function */ callback){
240                 // summary: 
241                 //                      populates the menu (and does the callback, if passed)
242                 
243                 var dropDown = this.dropDown;
244                 
245                 // Add each menu item
246                 dojo.forEach(this.options, this._addMenuItem, this);
247                 
248                 // Update states
249                 this._updateSelectedState();
250                 dojo.addClass(this.dropDown.domNode, this.baseClass + "Menu");
251                 this._isPopulated = true;
252                 if(callback){ callback.call(this); }
253         },
254         
255         _toggleDropDown: function(){
256                 // summary: Overrides DropDownButton's toggle function to make sure 
257                 //                      that the values are correctly populated.
258                 var dropDown = this.dropDown;
259                 if(dropDown && !dropDown.isShowingNow && !this._isPopulated){
260                         this._populate(dojox.form.DropDownSelect.superclass._toggleDropDown);
261                 }else{
262                         this.inherited(arguments);
263                 }
264         }
265 });
266
267 }