diff options
Diffstat (limited to 'includes/js/dijit/form/Form.js')
-rw-r--r-- | includes/js/dijit/form/Form.js | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/includes/js/dijit/form/Form.js b/includes/js/dijit/form/Form.js new file mode 100644 index 0000000..4ad29f9 --- /dev/null +++ b/includes/js/dijit/form/Form.js @@ -0,0 +1,384 @@ +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 HTML form tag, for validation and serialization + // + // example: + // | <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}, ...]) + // + // + + reset: function(){ + dojo.forEach(this.getDescendants(), function(widget){ + if(widget.reset){ + widget.reset(); + } + }); + }, + + validate: function(){ + // summary: returns if the form is valid - same as isValid - but + // provides a few additional (ui-specific) features. + // 1 - it will highlight any sub-widgets that are not + // valid + // 2 - it will call focus() on the first invalid + // sub-widget + var didFocus = false; + return dojo.every(dojo.map(this.getDescendants(), function(widget){ + // Need to set this so that "required" widgets get their + // state set. + widget._hasBeenBlurred = true; + var valid = !widget.validate || widget.validate(); + if (!valid && !didFocus) { + // Set focus of the first non-valid widget + dijit.scrollIntoView(widget.containerNode||widget.domNode); + widget.focus(); + didFocus = true; + } + return valid; + }), "return item;"); + }, + + 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 setAttribute('checked') 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(typeof widgets[0].checked == 'boolean'){ + // for checkbox/radio, values is a list of which widgets should be checked + dojo.forEach(widgets, function(w, i){ + w.setValue(dojo.indexOf(values, w.value) != -1); + }); + }else if(widgets[0]._multiValue){ + // it takes an array (e.g. multi-select) + widgets[0].setValue(values); + }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 name = widget.name; + if(!name){ return; } + + // Single value widget (checkbox, radio, or plain <input> type widget + var value = (widget.getValue && !widget._getValueDeprecated) ? widget.getValue() : widget.value; + + // Store widget's value(s) as a scalar, except for checkboxes which are automatically arrays + if(typeof widget.checked == 'boolean'){ + if(/Radio/.test(widget.declaredClass)){ + // radio button + if(value !== false){ + 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(value !== false){ + 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; + }, + + // TODO: ComboBox might need time to process a recently input value. This should be async? + isValid: function(){ + // summary: 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], + { + // summary: + // Adds conveniences to regular HTML form + + // HTML <FORM> attributes + name: "", + action: "", + method: "", + encType: "", + "accept-charset": "", + accept: "", + target: "", + + templateString: "<form dojoAttachPoint='containerNode' dojoAttachEvent='onreset:_onReset,onsubmit:_onSubmit' name='${name}'></form>", + + attributeMap: dojo.mixin(dojo.clone(dijit._Widget.prototype.attributeMap), + {action: "", method: "", encType: "", "accept-charset": "", accept: "", target: ""}), + + execute: function(/*Object*/ formContents){ + // summary: + // Deprecated: use submit() + }, + + onExecute: function(){ + // summary: + // Deprecated: use onSubmit() + }, + + setAttribute: function(/*String*/ attr, /*anything*/ value){ + this.inherited(arguments); + switch(attr){ + case "encType": + if(dojo.isIE){ this.domNode.encoding = value; } + } + }, + + postCreate: function(){ + // IE tries to hide encType + if(dojo.isIE && this.srcNodeRef && this.srcNodeRef.attributes){ + var item = this.srcNodeRef.attributes.getNamedItem('encType'); + if(item && !item.specified && (typeof item.value == "string")){ + this.setAttribute('encType', item.value); + } + } + this.inherited(arguments); + }, + + onReset: function(/*Event?*/e){ + // summary: + // Callback when user resets the form. This method is intended + // to be over-ridden. When the `reset` method is called + // programmatically, the return value from `onReset` is used + // to compute whether or not resetting should proceed + return true; // Boolean + }, + + _onReset: function(e){ + // create fake event so we can know if preventDefault() is called + var faux = { + returnValue: true, // the IE way + preventDefault: function(){ // not IE + this.returnValue = false; + }, + stopPropagation: function(){}, currentTarget: e.currentTarget, target: e.target + }; + // if return value is not exactly false, and haven't called preventDefault(), then reset + if(!(this.onReset(faux) === false) && faux.returnValue){ + this.reset(); + } + dojo.stopEvent(e); + return false; + }, + + _onSubmit: function(e){ + var fp = dijit.form.Form.prototype; + // TODO: remove ths if statement beginning with 2.0 + if(this.execute != fp.execute || this.onExecute != fp.onExecute){ + dojo.deprecated("dijit.form.Form:execute()/onExecute() are deprecated. Use onSubmit() instead.", "", "2.0"); + this.onExecute(); + this.execute(this.getValues()); + } + if(this.onSubmit(e) === false){ // only exactly false stops submit + dojo.stopEvent(e); + } + }, + + onSubmit: function(/*Event?*/e){ + // summary: + // Callback when user submits the form. This method is + // intended to be over-ridden, but by default it checks and + // returns the validity of form elements. When the `submit` + // method is called programmatically, the return value from + // `onSubmit` is used to compute whether or not submission + // should proceed + + return this.isValid(); // Boolean + }, + + submit: function(){ + // summary: + // programmatically submit form if and only if the `onSubmit` returns true + if(!(this.onSubmit() === false)){ + this.containerNode.submit(); + } + } + } +); + +} |