Show ThinkcapInputWidget.java syntax highlighted
package org.integratedmodelling.thinkcap.widget;
import java.util.ArrayList;
import java.util.HashMap;
import org.integratedmodelling.thinkcap.PageSpecs;
import org.integratedmodelling.thinkcap.exceptions.ThinkcapWidgetException;
/**
* Use this one to create widgets that contain input fields. Offers easy definition, validation with ThinkLab
* literals, and easy styling, plus integration with all the rest.
*
* All those widgets put the validated input in one hidden form. Use the SubmitWidget to create the
* submit button for the whole page, and instances of ThinkcapWidgetResponse to parse the input back
* widget by widget.
*
* @author Ferdinando Villa
*
*/
public abstract class ThinkcapInputWidget implements IThinkcapWidget {
/*
* to use later for POD type validations - just the regexps. All the rest should go to
* Thinklab using a struts call to the server.
*/
static final String PODvalidators =
" isEmpty: function(s) {\r\n" +
" var regexpWhitespace = /^\\s+$/;\r\n" +
" return ((s == null) || (s.length == 0) || regexpWhitespace.test(s));\r\n" +
" },\r\n" +
" isAlpha: function(s) {\r\n" +
" var regexpAlphabetic = /^[a-zA-Z\\s]+$/; // Add \' and - ?\r\n" +
" return wFORMS.behaviors[\'validation\'].isEmpty(s) || regexpAlphabetic.test(s);\r\n" +
" },\r\n" +
" isAlphaNum: function(s) {\r\n" +
" var validChars = /^[\\w\\s]+$/;\r\n" +
" return wFORMS.behaviors[\'validation\'].isEmpty(s) || validChars.test(s);\r\n" +
" },\r\n" +
" isEmail: function(s) {\r\n" +
" var regexpEmail = /\\w{1,}[@][\\w\\-]{1,}([.]([\\w\\-]{1,})){1,3}$/;\r\n" +
" return wFORMS.behaviors[\'validation\'].isEmpty(s) || regexpEmail.test(s);\r\n" +
" },\r\n" +
" isInteger: function(s) {\r\n" +
" var regexp = /^[+]?\\d+$/;\r\n" +
" return wFORMS.behaviors[\'validation\'].isEmpty(s) || regexp.test(s);\r\n" +
" },\r\n" +
" isFloat: function(s) { \r\n" +
" return wFORMS.behaviors[\'validation\'].isEmpty(s) || !isNaN(parseFloat(s));\r\n" +
" },";
private class InputDesc {
public String type;
public String name;
public String internalName;
public String defCnt;
public String validatorSemanticType;
public String cssClass;
public Object[] options;
private String collectOptions(Object ... options) {
String ret = "";
if (options != null)
for (int i = 0; i < options.length; i++) {
ret +=
" " +
options[i] +
"=\"" +
options[++i] +
"\"";
}
return ret;
}
public InputDesc(String iname, String name, String type, Object[] options) {
this.type = type;
this.name = name;
this.internalName = iname;
this.options = options;
}
/*
* Generates the HTML for the field, adding all the event handlers requested, and
* if we're not having a widget-specific submit method, redirection of output to
* the page-level hidden form.
*/
public String generateField(PageSpecs pageSpecs, String formName, boolean redirecting) {
String ret = "<";
String script = "";
boolean validating = validatorSemanticType != null;
/*
* 1. generate field type, name, style and options
*/
if (type.equals("text")) {
ret += "input type=\"text\"";
} else if (type.equals("submit")) {
ret += "input type=\"submit\"";
} else if (type.equals("image")) {
ret += "input type=\"image\" src=\"" + name + "\"";
}
// TODO the rest
if (cssClass != null) {
ret += " class=\"" + cssClass + "\"";
}
ret += " name=\"" + internalName + "\"";
/*
* add options.
*/
ret += collectOptions(options);
/*
* 2. Redirection if any. If we're validating, inject validator in redirector, else
* just put out the validator.
*/
if (redirecting || validating) {
ret += " onchange=\"handle_" + internalName + "();\"";
script +=
"function handle_" + internalName + "() {\n" +
" var value = document." + formName + "." + internalName + ".value\n" +
(validating ? (" " + getValidatorCode(pageSpecs, validatorSemanticType)) : "" ) +
(redirecting ? " document." + PageSpecs.formName + internalName + "_proxy.value = value;" : "") +
"}\n";
}
// close off
ret += " />";
if (!script.equals("")) {
pageSpecs.addToScript("\n<script type=\"text/javascript\">\n" + script + "\n</script>\n");
}
return ret;
}
private String getValidatorCode(PageSpecs pageSpecs, String validatorSemanticType2) {
// TODO generate or load validation function; insert code with "value" as parameter
return "";
}
}
HashMap<String, InputDesc> fDescriptions = new HashMap<String, InputDesc>();
private String targetID = null;
private String targetURI = null;
private boolean redirected = true;
/**
* Check that the objects array contains the passed defaults; if not, add them and return the
* new array.
* @param objects
* @param defaults
* @return
*/
private static Object[] applyDefaults(Object[] objects, Object ... defaults) {
ArrayList<Object> newobjs = new ArrayList<Object>();
for (int i = 0; i < defaults.length; i++) {
Object dname = defaults[i];
Object dvalu = defaults[++i];
boolean found = false;
for (int j = 0; j < objects.length; j++) {
if (objects[j++].toString().equals(dname.toString())) {
found = true;
break;
}
}
if (!found) {
newobjs.add(dname);
newobjs.add(dvalu);
}
}
if (newobjs.size() > 0) {
/* FIXME there must be a faster way */
for (Object o : objects)
newobjs.add(o);
return newobjs.toArray();
}
return objects;
}
/**
* Decouple the widget from the page and give it its own autonomy.
*
* If this is called, the widget is supposed to have its own submit button and the ID is the name
* of an element where the results of submitting to the passed url are put. In this case, the widget
* is autonomous. Otherwise, sthe fields in this widget set matching ones in the global form, and the
* submit button works for all input widgets in the same page.
*
* @param receivingURL
* @param id the ID of an element in the page where we want to direct the results of
* submitting the form. Pass null if you want the submit action to create a new page that
* takes over the current one. Otherwise an AJAX call is generated to define the innerHTML
* of the element identified.
*/
public void setTarget(String receivingURL, String id) {
targetID = id;
targetURI = receivingURL;
redirected = false;
}
int fInd = 0;
private int getID() {
return fInd ++;
}
protected InputDesc getDescriptor(String name) {
return fDescriptions.get(name.substring(1,name.length() - 1));
}
public void validateFieldAs(String field, String semanticType) {
getDescriptor(field).validatorSemanticType = semanticType;
}
public String addInputField(String name, Object ... options) {
String wname = getName() + "_" + name ;
/* TODO check defaults */
options = applyDefaults(options, "size", 40, "length", 128);
InputDesc id = new InputDesc(wname, name, "text", options);
fDescriptions.put(wname, id);
return "@" + wname + "@";
}
public String addRadioButtonHorizontal(String name, Object ... options) {
String wname = getName() + "_" + name;
/* TODO check defaults */
InputDesc id = new InputDesc(wname, name, "radio", options);
fDescriptions.put(wname, id);
return "@" + wname + "@";
}
public String addRadioButtonVertical(String name, Object ... options) {
String wname = getName() + "_" + name;
/* TODO check defaults */
InputDesc id = new InputDesc(wname, name, "radio", options);
fDescriptions.put(wname, id);
return "@" + wname + "@";
}
public String addListbox(String name, Object ... options) {
String wname = getName() + "_" + name;
/* TODO check defaults */
InputDesc id = new InputDesc(wname, name, "select", options);
fDescriptions.put(wname, id);
return "@" + wname + "@";
}
public String addCheckbox(String name, Object ... options) {
String wname = getName() + "_" + name;
/* TODO check defaults */
InputDesc id = new InputDesc(wname, name, "checkbox", options);
fDescriptions.put(wname, id);
return "@" + wname + "@";
}
public String addButton(String name, Object ... options) {
String wname = getName() + "_" + name;
/* TODO check defaults */
InputDesc id = new InputDesc(wname, name, "INPUT", options);
fDescriptions.put(wname, id);
return "@" + wname + "@";
}
public String addImageSubmit(String image, Object ... options) {
String wname = getName() + "_" + getID();
/* TODO check defaults */
InputDesc id = new InputDesc(wname, image, "image", options);
fDescriptions.put(wname, id);
return "@" + wname + "@";
}
public String addSubmit(Object ... options) {
String wname = getName() + "_" + getID();
/* TODO check defaults */
InputDesc id = new InputDesc(wname, "submit", "submit", options);
fDescriptions.put(wname, id);
return "@" + wname + "@";
}
public String addFileUpload(String name, Object ... options) {
String wname = getName() + "_" + name;
/* TODO check defaults */
InputDesc id = new InputDesc(wname, name, "FILE", options);
fDescriptions.put(wname, id);
return "@" + wname + "@";
}
public String addPassword(String name, Object ... options) {
String wname = getName() + "_" + name;
/* TODO check defaults */
InputDesc id = new InputDesc(wname, name, "INPUT", options);
fDescriptions.put(wname, id);
return "@" + wname + "@";
}
public String addTextInput(String name, Object ... options) {
String wname = getName() + "_" + name;
/* TODO check defaults */
InputDesc id = new InputDesc(wname, name, "textarea", options);
fDescriptions.put(wname, id);
return "@" + wname + "@";
}
public String addDropDownList(String name, Object ... options) {
String wname = getName() + "_" + name;
/* TODO check defaults */
InputDesc id = new InputDesc(wname, name, "select", options);
fDescriptions.put(wname, id);
return "@" + wname + "@";
}
/* substitutes outputWidget, which becomes final here. */
public abstract String outputInputWidget(PageSpecs pagespecs);
/**
* This one is normally called to generate widgets that are used within other widgets.
* Calling any other function (e.g. outputWidget or outputInputWidget) will include
* the signatures of the sub-widgets, prompting analysis of the output as if the widgets
* were alone. No guarantee is made as of the order of analysis, so this is typically not
* desirable.
*
* This must not generate the outermost form. Whatever is generated by this one will be
* wrapped into a form by outputWidget().
*
* @param pageSpecs
* @return
* @throws ThinkcapWidgetException
*/
public final String generateWidget(PageSpecs pageSpecs) throws ThinkcapWidgetException {
String ret = "";
/* put all fields in page if we're redirecting before generating widget. We just
* need text for this one. */
if (redirected) {
for (InputDesc id : fDescriptions.values()) {
pageSpecs.addField(id.internalName + "_proxy");
}
}
/* Generate the actual widget. Use generateWidget so that the signature is only added
* for the outermost one.
* This should use the widget internal names where the widgets go.
*/
ret += outputInputWidget(pageSpecs);
/* generate and substitute all fields in widgets */
for (InputDesc id : fDescriptions.values()) {
String wid = "@" + id.internalName + "@";
String wwl = id.generateField(pageSpecs, getName() + "_form", redirected);
ret = ret.replaceAll(wid, wwl);
}
return ret;
}
public final String outputWidget(PageSpecs pageSpecs) throws ThinkcapWidgetException {
/* wrap the whole widget into a form and give it the
* target we wanted. Handle ajax as requested.
*/
/* TODO add ajax stuff if targetID is not null */
String ret =
"<form method=\"POST\" name=\"" +
getName() +
"_form\"";
if (!redirected)
ret +=
" action=\"" +
targetURI +
"\"";
ret += ">\n";
ret += generateWidget(pageSpecs);
/**
* add widget signature; make sure signatures of widgets used
* internally are not included.
*/
ret +=
"<input type=\"hidden\" name=\"widget_signature_" +
getName() +
"\" value=\"" +
getWidgetClass() +
"\"/>\n";
/*
* close off form
*/
ret += "\n</form>\n";
return ret;
}
}
See more files for this project here