- removing usage of dojo for textfield widgets - they were basically useless and i'm working towards consistent presentation for valid/invalid states

- implementing preliminary validation feedback for submit errors meaning that for the most part, the client knows which elements are in an invalid state on submit and require fixes

next steps:
- add in xforms:alerts so we get better error messages when a control is not filled out/filled out with an invalid value
- fix up the error reporting in the ui so it looks more presentable
- add in support for custom xforms:alerts as metadata within the xsd so that we can have truly informative error messages.



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@4026 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Ariel Backenroth
2006-10-05 02:24:33 +00:00
parent 6da8f919df
commit 54ac87ef6b
5 changed files with 918 additions and 862 deletions

View File

@@ -538,19 +538,19 @@ public class SchemaFormBuilder
? this.submitMethod
: SchemaFormBuilder.SUBMIT_METHOD_POST));
//Element submitButton = (Element) formSection.appendChild(xForm.createElementNS(XFORMS_NS,SchemaFormBuilder.XFORMS_NS_PREFIX+"submit"));
Element submitButton =
final Element submitButton =
xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "submit");
Element submitControlWrapper = this.wrapper.createControlsWrapper(submitButton);
final Element submitControlWrapper = this.wrapper.createControlsWrapper(submitButton);
formContentWrapper.appendChild(submitControlWrapper);
submitButton.setAttributeNS(XFORMS_NS,
SchemaFormBuilder.XFORMS_NS_PREFIX + "submission",
submissionId);
this.setXFormsId(submitButton);
Element submitButtonCaption = (Element)
submitButton.appendChild(xForm.createElementNS(XFORMS_NS,
SchemaFormBuilder.XFORMS_NS_PREFIX + "label"));
final Element submitButtonCaption =
xForm.createElementNS(XFORMS_NS,
SchemaFormBuilder.XFORMS_NS_PREFIX + "label");
submitButton.appendChild(submitButtonCaption);
submitButtonCaption.appendChild(xForm.createTextNode("Submit"));
this.setXFormsId(submitButtonCaption);
return xForm;
@@ -2407,9 +2407,6 @@ public class SchemaFormBuilder
SchemaFormBuilder.XFORMS_NS_PREFIX + "label");
this.setXFormsId(triggerLabel);
trigger.appendChild(triggerLabel);
//triggerLabel_insert.setAttributeNS(SchemaFormBuilder.XLINK_NS,
// SchemaFormBuilder.XLINK_NS_PREFIX + "href",
// "images/add_new.gif");
triggerLabel.appendChild(xForm.createTextNode(label));

View File

@@ -132,6 +132,8 @@ public class XFormsBean
et.addEventListener(XFormsEventFactory.SUBMIT_DONE, el, true);
et.addEventListener(XFormsEventFactory.SUBMIT_ERROR, el, true);
et.addEventListener(XFormsEventFactory.REQUIRED, el, true);
et.addEventListener(XFormsEventFactory.OPTIONAL, el, true);
et.addEventListener(XFormsEventFactory.VALID, el, true);
et.addEventListener(XFormsEventFactory.INVALID, el, true);
et.addEventListener(XFormsEventFactory.OUT_OF_RANGE, el, true);
et.addEventListener(XFormsEventFactory.CHIBA_STATE_CHANGED, el, true);

View File

@@ -42,7 +42,7 @@
<xs:element name="optional_textfield" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="prefilled_textfield" type="xs:string" minOccurs="0" maxOccurs="1" default="i am the default value"/>
<xs:element name="integer" type="xs:integer"/>
<xs:element name="positiveInteger" type="xs:positiveInteger"/>
<xs:element name="positive_integer" type="xs:positiveInteger"/>
<xs:element name="double" type="xs:double"/>
<xs:element name="date" type="xs:date"/>
<xs:element name="radio" type="five_string_values"/>

View File

@@ -43,7 +43,7 @@ body
<xsl:template match="/components/integer">
<div style="line-height: 25px;"><span class="name">Integer:</span> <xsl:value-of select="/components/integer"/></div>
</xsl:template>
<xsl:template match="/components/positiveInteger">
<xsl:template match="/components/positive_integer">
<div style="line-height: 25px;"><span class="name">Positive Integer:</span> <xsl:value-of select="/components/positiveInteger"/></div>
</xsl:template>
<xsl:template match="/components/double">

View File

@@ -35,6 +35,8 @@ dojo.declare("alfresco.xforms.Widget",
this.node = node;
this.node.widget = this;
this.id = this.node.getAttribute("id");
this.modified = false;
this.valid = true;
},
parent: null,
domContainer: null,
@@ -42,6 +44,32 @@ dojo.declare("alfresco.xforms.Widget",
{
return this.xform.getBinding(this.node);
},
setModified: function(b)
{
this.modified = b;
this._updateDisplay();
},
setValid: function(b)
{
this.valid = b;
this._updateDisplay();
},
setRequired: function(b)
{
this.required = b;
this._updateDisplay();
},
isValidForSubmit: function()
{
var result = true;
if (!this.valid)
result = false;
else if (!this.modified &&
this.isRequired() &&
this.getInitialValue() == null)
result = false;
return result;
},
getDepth: function()
{
var result = 1;
@@ -78,7 +106,9 @@ dojo.declare("alfresco.xforms.Widget",
nsResolver,
XPathResult.STRING_TYPE,
null);
return result.stringValue;
return (result.stringValue != null && result.stringValue.length > 0
? result.stringValue
: null);
},
_getLabelNode: function()
{
@@ -96,44 +126,11 @@ dojo.declare("alfresco.xforms.Widget",
{
var node = this._getLabelNode();
return node ? dojo.dom.textContent(node) : "";
}
});
dojo.declare("alfresco.xforms.NumericStepper",
alfresco.xforms.Widget,
{
initializer: function(xform, node, stepper_type)
{
this.inherited("initializer", [ xform, node ]);
this.stepper_type = stepper_type;
},
render: function(attach_point)
_updateDisplay: function()
{
var nodeRef = document.createElement("div");
attach_point.appendChild(nodeRef);
var initial_value = this.getInitialValue() || "";
var w = dojo.widget.createWidget((this.stepper_type == "double"
? "AdjustableRealNumberTextBox"
: "AdjustableIntegerTextBox"),
{
widgetId: this.id + "-widget",
required: this.isRequired(),
value: initial_value
},
nodeRef);
w.widget = this;
this.widget = w;
dojo.event.connect(w, "adjustValue", this, this._widget_changeHandler);
dojo.event.connect(w, "onkeyup", this, this._widget_changeHandler);
},
getValue: function()
{
return this.widget.getValue();
},
_widget_changeHandler: function(event)
{
this.xform.setXFormsValue(this.id, this.getValue());
// this.domContainer.style.backgroundColor =
// (!this.valid ? "yellow" : this.modified ? "lightgreen" : "white");
}
});
@@ -146,22 +143,16 @@ dojo.declare("alfresco.xforms.DatePicker",
},
render: function(attach_point)
{
var initial_value = this.getInitialValue();
var initial_value = this.getInitialValue() || "";
var dateTextBoxDiv = document.createElement("div");
attach_point.appendChild(dateTextBoxDiv);
this.dateTextBox = dojo.widget.createWidget("DateTextBox",
{
widgetId: this.id + "-widget",
required: this.isRequired(),
format: "YYYY-MM-DD",
value: initial_value
},
dateTextBoxDiv);
dojo.event.connect(this.dateTextBox,
"onfocus",
this,
this._dateTextBox_focusHandler);
this.domNode = document.createElement("div");
attach_point.appendChild(this.domNode);
this.widget = document.createElement("input");
this.widget.setAttribute("id", this.id + "-widget");
this.widget.setAttribute("type", "text");
this.widget.setAttribute("value", initial_value);
this.domNode.appendChild(this.widget);
dojo.event.connect(this.widget, "onfocus", this, this._dateTextBox_focusHandler);
var datePickerDiv = document.createElement("div");
attach_point.appendChild(datePickerDiv);
@@ -169,36 +160,36 @@ dojo.declare("alfresco.xforms.DatePicker",
var dp_initial_value = (initial_value
? initial_value
: dojo.widget.DatePicker.util.toRfcDate(new Date()));
this.dateTextBox.picker = dojo.widget.createWidget("DatePicker",
this.widget.picker = dojo.widget.createWidget("DatePicker",
{
isHidden: true,
storedDate: dp_initial_value
},
datePickerDiv);
this.dateTextBox.picker.hide();
dojo.event.connect(this.dateTextBox.picker,
this.widget.picker.hide();
dojo.event.connect(this.widget.picker,
"onSetDate",
this,
this._datePicker_setDateHandler);
},
getValue: function()
{
return this.dateTextBox.getValue();
return this.widget.value;
},
_dateTextBox_focusHandler: function(event)
{
this.dateTextBox.hide();
this.dateTextBox.picker.show();
dojo.style.hide(this.widget);
this.widget.picker.show();
this.domContainer.style.height =
this.dateTextBox.picker.domNode.offsetHeight + "px";
this.widget.picker.domNode.offsetHeight + "px";
},
_datePicker_setDateHandler: function(event)
{
this.dateTextBox.picker.hide();
this.dateTextBox.show();
this.widget.picker.hide();
dojo.style.show(this.widget);
this.domContainer.style.height =
this.dateTextBox.domNode.offsetHeight + "px";
this.dateTextBox.setValue(dojo.widget.DatePicker.util.toRfcDate(this.dateTextBox.picker.date));
Math.max(this.widget.offsetHeight, 20) + "px";
this.widget.value = dojo.widget.DatePicker.util.toRfcDate(this.widget.picker.date);
this.xform.setXFormsValue(this.id, this.getValue());
}
});
@@ -210,26 +201,43 @@ dojo.declare("alfresco.xforms.TextField",
{
this.inherited("initializer", [ xform, node ]);
},
isValidForSubmit: function()
{
var result = this.inherited("isValidForSubmit", []);
if (!result)
return false;
if (this.isRequired() && this.getValue() == null)
return false;
return true;
},
render: function(attach_point)
{
var nodeRef = document.createElement("div");
attach_point.appendChild(nodeRef);
var initial_value = this.getInitialValue() || "";
this.domNode = document.createElement("div");
this.domNode.setAttribute("id", this.id + "-domNode");
attach_point.appendChild(this.domNode);
var w = dojo.widget.createWidget("ValidationTextBox",
{
widgetId: this.id + "-widget",
required: this.isRequired(),
value: initial_value
},
nodeRef);
w.widget = this;
this.widget = w;
dojo.event.connect(w, "onkeyup", this, this._widget_keyUpHandler);
this.widget = document.createElement("input");
this.widget.setAttribute("type", "text");
this.widget.setAttribute("id", this.id + "-widget");
this.widget.setAttribute("value", initial_value);
this.domNode.appendChild(this.widget);
// this.widget = dojo.widget.createWidget("ValidationTextBox",
// {
// widgetId: this.id + "-widget",
// required: this.isRequired(),
// value: initial_value
// },
// this.domNode);
dojo.event.connect(this.widget, "onkeyup", this, this._widget_keyUpHandler);
},
getValue: function()
{
return this.widget.getValue();
var result = this.widget.value;
if (result != null && result.length == 0)
result = null;
return result;
},
_widget_keyUpHandler: function(event)
{
@@ -335,6 +343,7 @@ dojo.declare("alfresco.xforms.Select",
}
else
{
initial_value = initial_value ? initial_value.split(' ') : [];
var list = document.createElement("select");
list.setAttribute("id", this.id + "-widget");
list.setAttribute("multiple", true);
@@ -344,7 +353,7 @@ dojo.declare("alfresco.xforms.Select",
var option = document.createElement("option");
option.appendChild(document.createTextNode(values[i].label));
option.setAttribute("value", values[i].value);
if (values[i].value == initial_value)
if (initial_value.indexOf(values[i].value) != -1)
option.setAttribute("selected", "true");
list.appendChild(option);
}
@@ -468,6 +477,18 @@ dojo.declare("alfresco.xforms.Group",
this.children = [];
},
children: null,
getWidgetsInvalidForSubmit: function()
{
var result = [];
for (var i = 0; i < this.children.length; i++)
{
if (this.children[i] instanceof alfresco.xforms.Group)
result = result.concat(this.children[i].getWidgetsInvalidForSubmit());
else if (!this.children[i].isValidForSubmit())
result.push(this.children[i]);
}
return result;
},
getChildAt: function(index)
{
return index < this.children.length ? this.children[index] : null;
@@ -546,7 +567,7 @@ dojo.declare("alfresco.xforms.Group",
child.domContainer.style.lineHeight = child.domContainer.style.height;
}
contentDiv.style.top = "-" + contentDiv.offsetTop + "px";
contentDiv.widget = child;
this._updateDisplay();
return child.domContainer;
@@ -587,6 +608,10 @@ dojo.declare("alfresco.xforms.Group",
},
_updateDisplay: function()
{
for (var i = 0; i < this.children.length; i++)
{
this.children[i]._updateDisplay();
}
}
});
@@ -645,6 +670,7 @@ dojo.declare("alfresco.xforms.Repeat",
},
_updateDisplay: function()
{
this.inherited("_updateDisplay", []);
for (var i = 0; i < this.children.length; i++)
{
this.children[i].domContainer.style.backgroundColor =
@@ -888,9 +914,9 @@ dojo.declare("alfresco.xforms.XFormsEvent",
},
getTarget: function()
{
var targetDomNode = document.getElementById(this.targetId + "-domNode");
var targetDomNode = document.getElementById(this.targetId + "-content");
if (!targetDomNode)
throw new Error("unable to find node " + this.targetId + "-domNode");
throw new Error("unable to find node " + this.targetId + "-content");
return targetDomNode.widget;
}
});
@@ -925,9 +951,10 @@ dojo.declare("alfresco.xforms.XForm",
var alfUI = document.getElementById("alf-ui");
alfUI.style.width = "100%";
var root = new alfresco.xforms.Group(this, alfUI);
root.render(alfUI);
this.loadWidgets(this.getBody(), root);
this.rootWidget = new alfresco.xforms.Group(this, alfUI);
this.rootWidget.render(alfUI);
this.loadWidgets(this.getBody(), this.rootWidget);
this.rootWidget._updateDisplay();
},
createWidget: function(node)
{
@@ -960,7 +987,6 @@ dojo.declare("alfresco.xforms.XForm",
case "unsignedLong":
case "unsignedShort":
case "positiveInteger":
return new alfresco.xforms.NumericStepper(this, node, type);
case "string":
default:
return new alfresco.xforms.TextField(this, node);
@@ -1077,6 +1103,7 @@ dojo.declare("alfresco.xforms.XForm",
},
setXFormsValue: function(id, value)
{
value = value == null ? "" : value;
dojo.debug("setting value " + id + " = " + value);
var req = create_ajax_request(this,
"setXFormsValue",
@@ -1105,6 +1132,13 @@ dojo.declare("alfresco.xforms.XForm",
xfe.getTarget().handleIndexChanged(index);
break;
}
case "chiba-state-changed":
{
var valid = xfe.properties["valid"] == "true";
xfe.getTarget().setValid(valid);
xfe.getTarget().setModified(true);
break;
}
case "chiba-prototype-cloned":
{
var prototypeId = xfe.properties["prototypeId"];
@@ -1152,8 +1186,30 @@ dojo.declare("alfresco.xforms.XForm",
document.submitWidget.currentButton = null;
}
break;
case "xforms-valid":
xfe.getTarget().setValid(true);
xfe.getTarget().setModified(true);
break;
case "xforms-invalid":
xfe.getTarget().setValid(false);
xfe.getTarget().setModified(true);
break;
case "xforms-required":
xfe.getTarget().setRequired(true);
break;
case "xforms-optional":
xfe.getTarget().setRequired(false);
break;
case "xforms-submit-error":
_show_error("Please provide values for all required fields.");
var invalid = this.rootWidget.getWidgetsInvalidForSubmit();
var msg = "Please provide values for all required fields.";
msg += "<br/><ul>";
for (var j = 0; j < invalid.length; j++)
{
msg += "<li>" + invalid[j].getLabel() + "</li>";
}
msg += "</ul>";
_show_error(msg);
break;
default:
{
@@ -1174,6 +1230,7 @@ function addSubmitHandlerToButton(b)
{
dojo.debug("not done, resubmitting");
tinyMCE.triggerSave();
_hide_errors();
document.submitWidget.currentButton = this;
document.submitWidget.widget.buttonClick();
return false;
@@ -1247,7 +1304,7 @@ function _show_error(msg)
dojo.dom.prependChild(errorDiv, alfUI);
}
if (errorDiv.style.display == "block")
errorDiv.innerHTML = errorDiv.innerHTML + "<br/>" + e.message;
errorDiv.innerHTML = errorDiv.innerHTML + "<br/>" + msg;
else
{
errorDiv.innerHTML = msg;