]> git.pond.sub.org Git - eow/blob - static/dojo-release-1.1.1/dijit/form/Form.js
add Dojo 1.1.1
[eow] / static / dojo-release-1.1.1 / dijit / form / Form.js
1 if(!dojo._hasResource["dijit.form.Form"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["dijit.form.Form"] = true;
3 dojo.provide("dijit.form.Form");
4
5 dojo.require("dijit._Widget");
6 dojo.require("dijit._Templated");
7
8 dojo.declare("dijit.form._FormMixin", null,
9         {
10         //
11         //      summary:
12         //              Widget corresponding to HTML form tag, for validation and serialization
13         //
14         //      example:
15         //      |       <form dojoType="dijit.form.Form" id="myForm">
16         //      |               Name: <input type="text" name="name" />
17         //      |       </form>
18         //      |       myObj = {name: "John Doe"};
19         //      |       dijit.byId('myForm').setValues(myObj);
20         //      |
21         //      |       myObj=dijit.byId('myForm').getValues();
22
23         //      TODO:
24         //      * Repeater
25         //      * better handling for arrays.  Often form elements have names with [] like
26         //      * people[3].sex (for a list of people [{name: Bill, sex: M}, ...])
27         //
28         //      
29
30                 reset: function(){
31                         dojo.forEach(this.getDescendants(), function(widget){
32                                 if(widget.reset){
33                                         widget.reset();
34                                 }
35                         });
36                 },
37
38                 validate: function(){
39                         // summary: returns if the form is valid - same as isValid - but
40                         //                      provides a few additional (ui-specific) features.
41                         //                      1 - it will highlight any sub-widgets that are not
42                         //                              valid
43                         //                      2 - it will call focus() on the first invalid 
44                         //                              sub-widget
45                         var didFocus = false;
46                         return dojo.every(dojo.map(this.getDescendants(), function(widget){
47                                 // Need to set this so that "required" widgets get their 
48                                 // state set.
49                                 widget._hasBeenBlurred = true;
50                                 var valid = !widget.validate || widget.validate();
51                                 if (!valid && !didFocus) {
52                                         // Set focus of the first non-valid widget
53                                         dijit.scrollIntoView(widget.containerNode||widget.domNode);
54                                         widget.focus();
55                                         didFocus = true;
56                                 }
57                                 return valid;
58                         }), "return item;");
59                 },
60                 
61                 setValues: function(/*object*/obj){
62                         // summary: fill in form values from a JSON structure
63
64                         // generate map from name --> [list of widgets with that name]
65                         var map = { };
66                         dojo.forEach(this.getDescendants(), function(widget){
67                                 if(!widget.name){ return; }
68                                 var entry = map[widget.name] || (map[widget.name] = [] );
69                                 entry.push(widget);
70                         });
71
72                         // call setValue() or setAttribute('checked') for each widget, according to obj
73                         for(var name in map){
74                                 var widgets = map[name],                                                // array of widgets w/this name
75                                         values = dojo.getObject(name, false, obj);      // list of values for those widgets
76                                 if(!dojo.isArray(values)){
77                                         values = [ values ];
78                                 }
79                                 if(typeof widgets[0].checked == 'boolean'){
80                                         // for checkbox/radio, values is a list of which widgets should be checked
81                                         dojo.forEach(widgets, function(w, i){
82                                                 w.setValue(dojo.indexOf(values, w.value) != -1);
83                                         });
84                                 }else if(widgets[0]._multiValue){
85                                         // it takes an array (e.g. multi-select)
86                                         widgets[0].setValue(values);
87                                 }else{
88                                         // otherwise, values is a list of values to be assigned sequentially to each widget
89                                         dojo.forEach(widgets, function(w, i){
90                                                 w.setValue(values[i]);
91                                         });                                     
92                                 }
93                         }
94
95                         /***
96                          *      TODO: code for plain input boxes (this shouldn't run for inputs that are part of widgets)
97
98                         dojo.forEach(this.containerNode.elements, function(element){
99                                 if (element.name == ''){return};        // like "continue"      
100                                 var namePath = element.name.split(".");
101                                 var myObj=obj;
102                                 var name=namePath[namePath.length-1];
103                                 for(var j=1,len2=namePath.length;j<len2;++j){
104                                         var p=namePath[j - 1];
105                                         // repeater support block
106                                         var nameA=p.split("[");
107                                         if (nameA.length > 1){
108                                                 if(typeof(myObj[nameA[0]]) == "undefined"){
109                                                         myObj[nameA[0]]=[ ];
110                                                 } // if
111
112                                                 nameIndex=parseInt(nameA[1]);
113                                                 if(typeof(myObj[nameA[0]][nameIndex]) == "undefined"){
114                                                         myObj[nameA[0]][nameIndex] = { };
115                                                 }
116                                                 myObj=myObj[nameA[0]][nameIndex];
117                                                 continue;
118                                         } // repeater support ends
119
120                                         if(typeof(myObj[p]) == "undefined"){
121                                                 myObj=undefined;
122                                                 break;
123                                         };
124                                         myObj=myObj[p];
125                                 }
126
127                                 if (typeof(myObj) == "undefined"){
128                                         return;         // like "continue"
129                                 }
130                                 if (typeof(myObj[name]) == "undefined" && this.ignoreNullValues){
131                                         return;         // like "continue"
132                                 }
133
134                                 // TODO: widget values (just call setValue() on the widget)
135
136                                 switch(element.type){
137                                         case "checkbox":
138                                                 element.checked = (name in myObj) &&
139                                                         dojo.some(myObj[name], function(val){ return val==element.value; });
140                                                 break;
141                                         case "radio":
142                                                 element.checked = (name in myObj) && myObj[name]==element.value;
143                                                 break;
144                                         case "select-multiple":
145                                                 element.selectedIndex=-1;
146                                                 dojo.forEach(element.options, function(option){
147                                                         option.selected = dojo.some(myObj[name], function(val){ return option.value == val; });
148                                                 });
149                                                 break;
150                                         case "select-one":
151                                                 element.selectedIndex="0";
152                                                 dojo.forEach(element.options, function(option){
153                                                         option.selected = option.value == myObj[name];
154                                                 });
155                                                 break;
156                                         case "hidden":
157                                         case "text":
158                                         case "textarea":
159                                         case "password":
160                                                 element.value = myObj[name] || "";
161                                                 break;
162                                 }
163                         });
164                         */
165                 },
166
167                 getValues: function(){
168                         // summary: generate JSON structure from form values
169
170                         // get widget values
171                         var obj = { };
172                         dojo.forEach(this.getDescendants(), function(widget){
173                                 var name = widget.name;
174                                 if(!name){ return; }
175
176                                 // Single value widget (checkbox, radio, or plain <input> type widget
177                                 var value = (widget.getValue && !widget._getValueDeprecated) ? widget.getValue() : widget.value;
178
179                                 // Store widget's value(s) as a scalar, except for checkboxes which are automatically arrays
180                                 if(typeof widget.checked == 'boolean'){
181                                         if(/Radio/.test(widget.declaredClass)){
182                                                 // radio button
183                                                 if(value !== false){
184                                                         dojo.setObject(name, value, obj);
185                                                 }
186                                         }else{
187                                                 // checkbox/toggle button
188                                                 var ary=dojo.getObject(name, false, obj);
189                                                 if(!ary){
190                                                         ary=[];
191                                                         dojo.setObject(name, ary, obj);
192                                                 }
193                                                 if(value !== false){
194                                                         ary.push(value);
195                                                 }
196                                         }
197                                 }else{
198                                         // plain input
199                                         dojo.setObject(name, value, obj);
200                                 }
201                         });
202
203                         /***
204                          * code for plain input boxes (see also dojo.formToObject, can we use that instead of this code?
205                          * but it doesn't understand [] notation, presumably)
206                         var obj = { };
207                         dojo.forEach(this.containerNode.elements, function(elm){
208                                 if (!elm.name)  {
209                                         return;         // like "continue"
210                                 }
211                                 var namePath = elm.name.split(".");
212                                 var myObj=obj;
213                                 var name=namePath[namePath.length-1];
214                                 for(var j=1,len2=namePath.length;j<len2;++j){
215                                         var nameIndex = null;
216                                         var p=namePath[j - 1];
217                                         var nameA=p.split("[");
218                                         if (nameA.length > 1){
219                                                 if(typeof(myObj[nameA[0]]) == "undefined"){
220                                                         myObj[nameA[0]]=[ ];
221                                                 } // if
222                                                 nameIndex=parseInt(nameA[1]);
223                                                 if(typeof(myObj[nameA[0]][nameIndex]) == "undefined"){
224                                                         myObj[nameA[0]][nameIndex] = { };
225                                                 }
226                                         } else if(typeof(myObj[nameA[0]]) == "undefined"){
227                                                 myObj[nameA[0]] = { }
228                                         } // if
229
230                                         if (nameA.length == 1){
231                                                 myObj=myObj[nameA[0]];
232                                         } else{
233                                                 myObj=myObj[nameA[0]][nameIndex];
234                                         } // if
235                                 } // for
236
237                                 if ((elm.type != "select-multiple" && elm.type != "checkbox" && elm.type != "radio") || (elm.type=="radio" && elm.checked)){
238                                         if(name == name.split("[")[0]){
239                                                 myObj[name]=elm.value;
240                                         } else{
241                                                 // can not set value when there is no name
242                                         }
243                                 } else if (elm.type == "checkbox" && elm.checked){
244                                         if(typeof(myObj[name]) == 'undefined'){
245                                                 myObj[name]=[ ];
246                                         }
247                                         myObj[name].push(elm.value);
248                                 } else if (elm.type == "select-multiple"){
249                                         if(typeof(myObj[name]) == 'undefined'){
250                                                 myObj[name]=[ ];
251                                         }
252                                         for (var jdx=0,len3=elm.options.length; jdx<len3; ++jdx){
253                                                 if (elm.options[jdx].selected){
254                                                         myObj[name].push(elm.options[jdx].value);
255                                                 }
256                                         }
257                                 } // if
258                                 name=undefined;
259                         }); // forEach
260                         ***/
261                         return obj;
262                 },
263
264                 // TODO: ComboBox might need time to process a recently input value.  This should be async?
265                 isValid: function(){
266                         // summary: make sure that every widget that has a validator function returns true
267                         return dojo.every(this.getDescendants(), function(widget){
268                                 return !widget.isValid || widget.isValid();
269                         });
270                 }
271         });
272
273 dojo.declare(
274         "dijit.form.Form",
275         [dijit._Widget, dijit._Templated, dijit.form._FormMixin],
276         {
277                 // summary:
278                 // Adds conveniences to regular HTML form
279
280                 // HTML <FORM> attributes
281                 name: "",
282                 action: "",
283                 method: "",
284                 encType: "",
285                 "accept-charset": "",
286                 accept: "",
287                 target: "",
288
289                 templateString: "<form dojoAttachPoint='containerNode' dojoAttachEvent='onreset:_onReset,onsubmit:_onSubmit' name='${name}'></form>",
290
291                 attributeMap: dojo.mixin(dojo.clone(dijit._Widget.prototype.attributeMap),
292                         {action: "", method: "", encType: "", "accept-charset": "", accept: "", target: ""}),
293
294                 execute: function(/*Object*/ formContents){
295                         //      summary:
296                         //              Deprecated: use submit()
297                 },
298
299                 onExecute: function(){
300                         // summary:
301                         //              Deprecated: use onSubmit()
302                 },
303
304                 setAttribute: function(/*String*/ attr, /*anything*/ value){
305                         this.inherited(arguments);
306                         switch(attr){
307                                 case "encType":
308                                         if(dojo.isIE){ this.domNode.encoding = value; }
309                         }
310                 },
311
312                 postCreate: function(){
313                         // IE tries to hide encType
314                         if(dojo.isIE && this.srcNodeRef && this.srcNodeRef.attributes){
315                                 var item = this.srcNodeRef.attributes.getNamedItem('encType');
316                                 if(item && !item.specified && (typeof item.value == "string")){
317                                         this.setAttribute('encType', item.value);
318                                 }
319                         }
320                         this.inherited(arguments);
321                 },
322
323                 onReset: function(/*Event?*/e){ 
324                         //      summary:
325                         //              Callback when user resets the form. This method is intended
326                         //              to be over-ridden. When the `reset` method is called
327                         //              programmatically, the return value from `onReset` is used
328                         //              to compute whether or not resetting should proceed
329                         return true; // Boolean
330                 },
331
332                 _onReset: function(e){
333                         // create fake event so we can know if preventDefault() is called
334                         var faux = {
335                                 returnValue: true, // the IE way
336                                 preventDefault: function(){  // not IE
337                                                         this.returnValue = false;
338                                                 },
339                                 stopPropagation: function(){}, currentTarget: e.currentTarget, target: e.target
340                         };
341                         // if return value is not exactly false, and haven't called preventDefault(), then reset
342                         if(!(this.onReset(faux) === false) && faux.returnValue){
343                                 this.reset();
344                         }
345                         dojo.stopEvent(e);
346                         return false;
347                 },
348
349                 _onSubmit: function(e){
350                         var fp = dijit.form.Form.prototype;
351                         // TODO: remove ths if statement beginning with 2.0
352                         if(this.execute != fp.execute || this.onExecute != fp.onExecute){
353                                 dojo.deprecated("dijit.form.Form:execute()/onExecute() are deprecated. Use onSubmit() instead.", "", "2.0");
354                                 this.onExecute();
355                                 this.execute(this.getValues());
356                         }
357                         if(this.onSubmit(e) === false){ // only exactly false stops submit
358                                 dojo.stopEvent(e);
359                         }
360                 },
361                 
362                 onSubmit: function(/*Event?*/e){ 
363                         //      summary:
364                         //              Callback when user submits the form. This method is
365                         //              intended to be over-ridden, but by default it checks and
366                         //              returns the validity of form elements. When the `submit`
367                         //              method is called programmatically, the return value from
368                         //              `onSubmit` is used to compute whether or not submission
369                         //              should proceed
370
371                         return this.isValid(); // Boolean
372                 },
373
374                 submit: function(){
375                         // summary:
376                         //              programmatically submit form if and only if the `onSubmit` returns true
377                         if(!(this.onSubmit() === false)){
378                                 this.containerNode.submit();
379                         }
380                 }
381         }
382 );
383
384 }