New file |
0,0 → 1,283 |
if(!dojo._hasResource["dijit.form.Form"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. |
dojo._hasResource["dijit.form.Form"] = true; |
dojo.provide("dijit.form.Form"); |
|
dojo.require("dijit._Widget"); |
dojo.require("dijit._Templated"); |
|
dojo.declare("dijit.form._FormMixin", null, |
{ |
/* |
summary: |
Widget corresponding to <form> tag, for validation and serialization |
|
usage: |
<form dojoType="dijit.form.Form" id="myForm"> |
Name: <input type="text" name="name" /> |
</form> |
myObj={name: "John Doe"}; |
dijit.byId('myForm').setValues(myObj); |
|
myObj=dijit.byId('myForm').getValues(); |
TODO: |
* Repeater |
* better handling for arrays. Often form elements have names with [] like |
* people[3].sex (for a list of people [{name: Bill, sex: M}, ...]) |
|
*/ |
|
// HTML <FORM> attributes |
|
action: "", |
method: "", |
enctype: "", |
name: "", |
"accept-charset": "", |
accept: "", |
target: "", |
|
attributeMap: dojo.mixin(dojo.clone(dijit._Widget.prototype.attributeMap), |
{action: "", method: "", enctype: "", "accept-charset": "", accept: "", target: ""}), |
|
// execute: Function |
// User defined function to do stuff when the user hits the submit button |
execute: function(/*Object*/ formContents){}, |
|
// onCancel: Function |
// Callback when user has canceled dialog, to notify container |
// (user shouldn't override) |
onCancel: function(){}, |
|
// onExecute: Function |
// Callback when user is about to execute dialog, to notify container |
// (user shouldn't override) |
onExecute: function(){}, |
|
templateString: "<form dojoAttachPoint='containerNode' dojoAttachEvent='onsubmit:_onSubmit' name='${name}' enctype='multipart/form-data'></form>", |
|
_onSubmit: function(/*event*/e) { |
// summary: callback when user hits submit button |
dojo.stopEvent(e); |
this.onExecute(); // notify container that we are about to execute |
this.execute(this.getValues()); |
}, |
|
submit: function() { |
// summary: programatically submit form |
this.containerNode.submit(); |
}, |
|
setValues: function(/*object*/obj) { |
// summary: fill in form values from a JSON structure |
|
// generate map from name --> [list of widgets with that name] |
var map = {}; |
dojo.forEach(this.getDescendants(), function(widget){ |
if(!widget.name){ return; } |
var entry = map[widget.name] || (map[widget.name] = [] ); |
entry.push(widget); |
}); |
|
// call setValue() or setChecked() for each widget, according to obj |
for(var name in map){ |
var widgets = map[name], // array of widgets w/this name |
values = dojo.getObject(name, false, obj); // list of values for those widgets |
if(!dojo.isArray(values)){ |
values = [ values ]; |
} |
if(widgets[0].setChecked){ |
// for checkbox/radio, values is a list of which widgets should be checked |
dojo.forEach(widgets, function(w, i){ |
w.setChecked(dojo.indexOf(values, w.value) != -1); |
}); |
}else{ |
// otherwise, values is a list of values to be assigned sequentially to each widget |
dojo.forEach(widgets, function(w, i){ |
w.setValue(values[i]); |
}); |
} |
} |
|
/*** |
* TODO: code for plain input boxes (this shouldn't run for inputs that are part of widgets |
|
dojo.forEach(this.containerNode.elements, function(element){ |
if (element.name == ''){return}; // like "continue" |
var namePath = element.name.split("."); |
var myObj=obj; |
var name=namePath[namePath.length-1]; |
for(var j=1,len2=namePath.length;j<len2;++j) { |
var p=namePath[j - 1]; |
// repeater support block |
var nameA=p.split("["); |
if (nameA.length > 1) { |
if(typeof(myObj[nameA[0]]) == "undefined") { |
myObj[nameA[0]]=[ ]; |
} // if |
|
nameIndex=parseInt(nameA[1]); |
if(typeof(myObj[nameA[0]][nameIndex]) == "undefined") { |
myObj[nameA[0]][nameIndex]={}; |
} |
myObj=myObj[nameA[0]][nameIndex]; |
continue; |
} // repeater support ends |
|
if(typeof(myObj[p]) == "undefined") { |
myObj=undefined; |
break; |
}; |
myObj=myObj[p]; |
} |
|
if (typeof(myObj) == "undefined") { |
return; // like "continue" |
} |
if (typeof(myObj[name]) == "undefined" && this.ignoreNullValues) { |
return; // like "continue" |
} |
|
// TODO: widget values (just call setValue() on the widget) |
|
switch(element.type) { |
case "checkbox": |
element.checked = (name in myObj) && |
dojo.some(myObj[name], function(val){ return val==element.value; }); |
break; |
case "radio": |
element.checked = (name in myObj) && myObj[name]==element.value; |
break; |
case "select-multiple": |
element.selectedIndex=-1; |
dojo.forEach(element.options, function(option){ |
option.selected = dojo.some(myObj[name], function(val){ return option.value == val; }); |
}); |
break; |
case "select-one": |
element.selectedIndex="0"; |
dojo.forEach(element.options, function(option){ |
option.selected = option.value == myObj[name]; |
}); |
break; |
case "hidden": |
case "text": |
case "textarea": |
case "password": |
element.value = myObj[name] || ""; |
break; |
} |
}); |
*/ |
}, |
|
getValues: function() { |
// summary: generate JSON structure from form values |
|
// get widget values |
var obj = {}; |
dojo.forEach(this.getDescendants(), function(widget){ |
var value = widget.getValue ? widget.getValue() : widget.value; |
var name = widget.name; |
if(!name){ return; } |
|
// Store widget's value(s) as a scalar, except for checkboxes which are automatically arrays |
if(widget.setChecked){ |
if(/Radio/.test(widget.declaredClass)){ |
// radio button |
if(widget.checked){ |
dojo.setObject(name, value, obj); |
} |
}else{ |
// checkbox/toggle button |
var ary=dojo.getObject(name, false, obj); |
if(!ary){ |
ary=[]; |
dojo.setObject(name, ary, obj); |
} |
if(widget.checked){ |
ary.push(value); |
} |
} |
}else{ |
// plain input |
dojo.setObject(name, value, obj); |
} |
}); |
|
/*** |
* code for plain input boxes (see also dojo.formToObject, can we use that instead of this code? |
* but it doesn't understand [] notation, presumably) |
var obj = { }; |
dojo.forEach(this.containerNode.elements, function(elm){ |
if (!elm.name) { |
return; // like "continue" |
} |
var namePath = elm.name.split("."); |
var myObj=obj; |
var name=namePath[namePath.length-1]; |
for(var j=1,len2=namePath.length;j<len2;++j) { |
var nameIndex = null; |
var p=namePath[j - 1]; |
var nameA=p.split("["); |
if (nameA.length > 1) { |
if(typeof(myObj[nameA[0]]) == "undefined") { |
myObj[nameA[0]]=[ ]; |
} // if |
nameIndex=parseInt(nameA[1]); |
if(typeof(myObj[nameA[0]][nameIndex]) == "undefined") { |
myObj[nameA[0]][nameIndex]={}; |
} |
} else if(typeof(myObj[nameA[0]]) == "undefined") { |
myObj[nameA[0]]={} |
} // if |
|
if (nameA.length == 1) { |
myObj=myObj[nameA[0]]; |
} else { |
myObj=myObj[nameA[0]][nameIndex]; |
} // if |
} // for |
|
if ((elm.type != "select-multiple" && elm.type != "checkbox" && elm.type != "radio") || (elm.type=="radio" && elm.checked)) { |
if(name == name.split("[")[0]) { |
myObj[name]=elm.value; |
} else { |
// can not set value when there is no name |
} |
} else if (elm.type == "checkbox" && elm.checked) { |
if(typeof(myObj[name]) == 'undefined') { |
myObj[name]=[ ]; |
} |
myObj[name].push(elm.value); |
} else if (elm.type == "select-multiple") { |
if(typeof(myObj[name]) == 'undefined') { |
myObj[name]=[ ]; |
} |
for (var jdx=0,len3=elm.options.length; jdx<len3; ++jdx) { |
if (elm.options[jdx].selected) { |
myObj[name].push(elm.options[jdx].value); |
} |
} |
} // if |
name=undefined; |
}); // forEach |
***/ |
return obj; |
}, |
|
isValid: function() { |
// TODO: ComboBox might need time to process a recently input value. This should be async? |
// make sure that every widget that has a validator function returns true |
return dojo.every(this.getDescendants(), function(widget){ |
return !widget.isValid || widget.isValid(); |
}); |
} |
}); |
|
dojo.declare( |
"dijit.form.Form", |
[dijit._Widget, dijit._Templated, dijit.form._FormMixin], |
null |
); |
|
} |