SWF-844 - Dojo DateTextBox locale-specific formatting is not progressive
SWF-853 - Decorating a form submit button as a ajax submit with a validate-all submission constraint should be easier SWF-910 - Make the clientDateValidator JSF component more flexible
This commit is contained in:
@@ -15,6 +15,12 @@
|
||||
*/
|
||||
package org.springframework.faces.ui;
|
||||
|
||||
import javax.faces.component.ValueHolder;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.convert.DateTimeConverter;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Component that uses the Dojo implementation of Spring JavaScript to decorate a child input component with client-side
|
||||
* date validation behavior.
|
||||
@@ -26,12 +32,52 @@ public class DojoClientDateValidator extends DojoDecoration {
|
||||
|
||||
private static final String DOJO_COMPONENT_TYPE = "dijit.form.DateTextBox";
|
||||
|
||||
private static final String[] DOJO_ATTRS_INTERNAL = new String[] { "datePattern" };
|
||||
|
||||
private static final String[] DOJO_ATTRS;
|
||||
|
||||
private String datePattern = null;
|
||||
|
||||
static {
|
||||
DOJO_ATTRS = new String[DojoDecoration.DOJO_ATTRS.length + DOJO_ATTRS_INTERNAL.length];
|
||||
System.arraycopy(DojoDecoration.DOJO_ATTRS, 0, DOJO_ATTRS, 0, DojoDecoration.DOJO_ATTRS.length);
|
||||
System.arraycopy(DOJO_ATTRS_INTERNAL, 0, DOJO_ATTRS, DojoDecoration.DOJO_ATTRS.length,
|
||||
DOJO_ATTRS_INTERNAL.length);
|
||||
}
|
||||
|
||||
public String getDatePattern() {
|
||||
Assert.isTrue(getChildren().get(0) instanceof ValueHolder,
|
||||
"Date validation can only be applied to an ValueHolder");
|
||||
ValueHolder child = (ValueHolder) getChildren().get(0);
|
||||
if (child.getConverter() instanceof DateTimeConverter) {
|
||||
return ((DateTimeConverter) child.getConverter()).getPattern();
|
||||
}
|
||||
return datePattern;
|
||||
}
|
||||
|
||||
public void setDatePattern(String datePattern) {
|
||||
this.datePattern = datePattern;
|
||||
}
|
||||
|
||||
protected String[] getDojoAttributes() {
|
||||
return DojoDecoration.DOJO_ATTRS;
|
||||
return DOJO_ATTRS;
|
||||
}
|
||||
|
||||
public String getDojoComponentType() {
|
||||
return DOJO_COMPONENT_TYPE;
|
||||
}
|
||||
|
||||
public Object saveState(FacesContext context) {
|
||||
Object[] values = new Object[2];
|
||||
values[0] = super.saveState(context);
|
||||
values[1] = this.datePattern;
|
||||
return values;
|
||||
}
|
||||
|
||||
public void restoreState(FacesContext context, Object state) {
|
||||
Object values[] = (Object[]) state;
|
||||
super.restoreState(context, values[0]);
|
||||
this.datePattern = (String) values[1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,18 +16,14 @@
|
||||
package org.springframework.faces.ui;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.faces.FacesException;
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.component.ValueHolder;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.ResponseWriter;
|
||||
import javax.faces.convert.Converter;
|
||||
|
||||
import org.springframework.faces.ui.resource.ResourceHelper;
|
||||
import org.springframework.faces.webflow.JsfUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Generic renderer for components that use the Dojo implementation of Spring JavaScript to decorate a child component
|
||||
@@ -78,13 +74,8 @@ public class DojoDecorationRenderer extends BaseSpringJavascriptDecorationRender
|
||||
script.append(" widgetType : '" + ((DojoDecoration) component).getDojoComponentType() + "', ");
|
||||
script.append(" widgetAttrs : { ");
|
||||
|
||||
String nodeAttrs = getNodeAttributesAsString(context, advisedChild);
|
||||
String dojoAttrs = getDojoAttributesAsString(context, component);
|
||||
|
||||
script.append(nodeAttrs);
|
||||
if (StringUtils.hasText(dojoAttrs)) {
|
||||
script.append(", ");
|
||||
}
|
||||
script.append(dojoAttrs);
|
||||
|
||||
script.append(" }}));");
|
||||
@@ -94,50 +85,6 @@ public class DojoDecorationRenderer extends BaseSpringJavascriptDecorationRender
|
||||
ResourceHelper.endScriptBlock(context);
|
||||
}
|
||||
|
||||
protected String getNodeAttributesAsString(FacesContext context, UIComponent component) {
|
||||
|
||||
StringBuffer attrs = new StringBuffer();
|
||||
|
||||
attrs.append("name : '" + component.getClientId(context) + "'");
|
||||
|
||||
ValueHolder valueHolder = (ValueHolder) component;
|
||||
|
||||
if (valueHolder.getValue() != null) {
|
||||
attrs.append(", value : ");
|
||||
String strValue = "'" + getValueAsString(context, component) + "'";
|
||||
if (valueHolder.getValue() instanceof Date) {
|
||||
strValue = "dojo.date.locale.parse(" + strValue + ", {selector : 'date', datePattern : 'yyyy-MM-dd'})";
|
||||
}
|
||||
attrs.append(strValue);
|
||||
}
|
||||
|
||||
return attrs.toString();
|
||||
}
|
||||
|
||||
protected String getValueAsString(FacesContext context, UIComponent component) {
|
||||
|
||||
ValueHolder valueHolder = (ValueHolder) component;
|
||||
|
||||
if (valueHolder.getValue() instanceof String) {
|
||||
return valueHolder.getValue().toString();
|
||||
}
|
||||
|
||||
Converter converter;
|
||||
if (valueHolder.getConverter() != null) {
|
||||
converter = valueHolder.getConverter();
|
||||
} else {
|
||||
converter = context.getApplication().createConverter(valueHolder.getValue().getClass());
|
||||
}
|
||||
|
||||
if (converter == null) {
|
||||
throw new FacesException("A converter could not be found to convert the value of " + component
|
||||
+ " to a String.");
|
||||
}
|
||||
|
||||
return converter.getAsString(context, component, valueHolder.getValue());
|
||||
|
||||
}
|
||||
|
||||
protected String getDojoAttributesAsString(FacesContext context, UIComponent component) {
|
||||
|
||||
DojoDecoration advisor = (DojoDecoration) component;
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
package org.springframework.faces.ui;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.faces.FacesException;
|
||||
import javax.faces.component.UIInput;
|
||||
import javax.faces.convert.DateTimeConverter;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.faces.webflow.JSFMockHelper;
|
||||
|
||||
public class DojoDecorationRendererTests extends TestCase {
|
||||
|
||||
JSFMockHelper jsf = new JSFMockHelper();
|
||||
|
||||
public void setUp() throws Exception {
|
||||
jsf.setUp();
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
jsf.tearDown();
|
||||
}
|
||||
|
||||
public void testGetValueAsString() {
|
||||
UIInput childComponent = new UIInput();
|
||||
childComponent.setValue("foo");
|
||||
DojoDecorationRenderer renderer = new DojoDecorationRenderer();
|
||||
String convertedValue = renderer.getValueAsString(jsf.facesContext(), childComponent);
|
||||
assertEquals("foo", convertedValue);
|
||||
}
|
||||
|
||||
public void testGetValueAsString_LocalConverter() {
|
||||
UIInput childComponent = new UIInput();
|
||||
childComponent.setValue(new TestValue());
|
||||
childComponent.setConverter(new TestConverter());
|
||||
DojoDecorationRenderer renderer = new DojoDecorationRenderer();
|
||||
String convertedValue = renderer.getValueAsString(jsf.facesContext(), childComponent);
|
||||
assertEquals("foo", convertedValue);
|
||||
}
|
||||
|
||||
public void testGetValueAsString_NoConverter() {
|
||||
UIInput childComponent = new UIInput();
|
||||
childComponent.setValue(new TestValue());
|
||||
DojoDecorationRenderer renderer = new DojoDecorationRenderer();
|
||||
try {
|
||||
renderer.getValueAsString(jsf.facesContext(), childComponent);
|
||||
fail("getValueAsString should throw exception if no converter is found");
|
||||
} catch (FacesException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetValueAsString_GlobalConverter() throws Exception {
|
||||
UIInput childComponent = new UIInput();
|
||||
childComponent.setValue(new TestValue());
|
||||
jsf.facesContext().getApplication().addConverter(TestValue.class, TestConverter.class.getName());
|
||||
DojoDecorationRenderer renderer = new DojoDecorationRenderer();
|
||||
String convertedValue = renderer.getValueAsString(jsf.facesContext(), childComponent);
|
||||
assertEquals("foo", convertedValue);
|
||||
}
|
||||
|
||||
public void testGetNodeAttributesAsString() {
|
||||
String expectedAttributes = "name : 'foo', value : 'foo'";
|
||||
UIInput childComponent = new UIInput();
|
||||
childComponent.setId("foo");
|
||||
childComponent.setValue("foo");
|
||||
DojoDecorationRenderer renderer = new DojoDecorationRenderer();
|
||||
String nodeAttributes = renderer.getNodeAttributesAsString(jsf.facesContext(), childComponent);
|
||||
assertEquals(expectedAttributes, nodeAttributes);
|
||||
}
|
||||
|
||||
public void testGetNodeAttributesAsString_DateValue() {
|
||||
String expectedAttributes = "name : 'foo', value : dojo.date.locale.parse('Nov 21, 1977', "
|
||||
+ "{selector : 'date', datePattern : 'yyyy-MM-dd'})";
|
||||
UIInput childComponent = new UIInput();
|
||||
DateTimeConverter converter = new DateTimeConverter();
|
||||
converter.setLocale(Locale.US);
|
||||
childComponent.setConverter(converter);
|
||||
childComponent.setId("foo");
|
||||
Calendar cal = Calendar.getInstance(Locale.US);
|
||||
cal.set(1977, Calendar.NOVEMBER, 21, 12, 0);
|
||||
childComponent.setValue(cal.getTime());
|
||||
DojoDecorationRenderer renderer = new DojoDecorationRenderer();
|
||||
String nodeAttributes = renderer.getNodeAttributesAsString(jsf.facesContext(), childComponent);
|
||||
assertEquals(expectedAttributes, nodeAttributes);
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -41,6 +41,17 @@ dojo.declare("Spring.ElementDecoration", [Spring.AbstractElementDecoration, Spri
|
||||
console.error("Could not apply " + this.widgetType + " decoration. Element with id '" + this.elementId + "' not found in the DOM.");
|
||||
}
|
||||
else {
|
||||
var datePattern = this.widgetAttrs['datePattern'];
|
||||
if (datePattern && this.widgetType == 'dijit.form.DateTextBox') {
|
||||
if (!this.widgetAttrs['value']) {
|
||||
this.widgetAttrs['value'] = dojo.date.locale.parse(element.value, {selector : "date", datePattern : datePattern});
|
||||
}
|
||||
if (!this.widgetAttrs['serialize']) {
|
||||
this.widgetAttrs['serialize'] = function(d, options){
|
||||
return dojo.date.locale.format(d, {selector : "date", datePattern : datePattern});
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var copyField in this.copyFields) {
|
||||
copyField = this.copyFields[copyField];
|
||||
if (!this.widgetAttrs[copyField] && element[copyField] &&
|
||||
@@ -97,7 +108,8 @@ dojo.declare("Spring.ValidateAllDecoration", [Spring.AbstractValidateAllDecorati
|
||||
},
|
||||
|
||||
handleEvent : function(event, context){
|
||||
if (!Spring.validateAll()) {
|
||||
event.springValidateAll = Spring.validateAll();
|
||||
if (!event.springValidateAll) {
|
||||
dojo.stopEvent(event);
|
||||
} else if(dojo.isFunction(context.originalHandler)) {
|
||||
var result = context.originalHandler(event);
|
||||
@@ -130,7 +142,9 @@ dojo.declare("Spring.AjaxEventDecoration", [Spring.AbstractAjaxEventDecoration,
|
||||
if(this.formId == ""){
|
||||
Spring.remoting.getLinkedResource(this.sourceId, this.params, this.popup);
|
||||
} else {
|
||||
Spring.remoting.submitForm(this.sourceId, this.formId, this.params);
|
||||
if (event.springValidateAll){
|
||||
Spring.remoting.submitForm(this.sourceId, this.formId, this.params);
|
||||
}
|
||||
}
|
||||
dojo.stopEvent(event);
|
||||
}
|
||||
|
||||
@@ -50,9 +50,9 @@
|
||||
<h:outputLabel for="checkinDate">Check In Date:</h:outputLabel>
|
||||
</div>
|
||||
<div class="input">
|
||||
<sf:clientDateValidator required="true" >
|
||||
<sf:clientDateValidator required="true">
|
||||
<h:inputText id="checkinDate" value="#{booking.checkinDate}" required="true">
|
||||
<f:convertDateTime pattern="yyyy-MM-dd" timeZone="EST"/>
|
||||
<f:convertDateTime pattern="MM-dd-yyyy" timeZone="EST"/>
|
||||
</h:inputText>
|
||||
</sf:clientDateValidator>
|
||||
</div>
|
||||
@@ -64,7 +64,7 @@
|
||||
<div class="input">
|
||||
<sf:clientDateValidator required="true">
|
||||
<h:inputText id="checkoutDate" value="#{booking.checkoutDate}" required="true">
|
||||
<f:convertDateTime pattern="yyyy-MM-dd" timeZone="EST"/>
|
||||
<f:convertDateTime pattern="MM-dd-yyyy" timeZone="EST"/>
|
||||
</h:inputText>
|
||||
</sf:clientDateValidator>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,9 @@ public class ApplicationConversionService extends DefaultConversionService {
|
||||
@Override
|
||||
protected void addDefaultConverters() {
|
||||
super.addDefaultConverters();
|
||||
addConverter("shortDate", new StringToDate());
|
||||
StringToDate dateConverter = new StringToDate();
|
||||
dateConverter.setPattern("MM-dd-yyyy");
|
||||
addConverter("shortDate", dateConverter);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -40,7 +40,7 @@
|
||||
Spring.addDecoration(new Spring.ElementDecoration({
|
||||
elementId : "checkinDate",
|
||||
widgetType : "dijit.form.DateTextBox",
|
||||
widgetAttrs : { value : dojo.date.locale.parse(dojo.byId("checkinDate").value, {selector : "date", datePattern : "yyyy-MM-dd"}), required : true }}));
|
||||
widgetAttrs : { datePattern : "MM-dd-yyyy", required : true }}));
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
@@ -54,7 +54,7 @@
|
||||
Spring.addDecoration(new Spring.ElementDecoration({
|
||||
elementId : "checkoutDate",
|
||||
widgetType : "dijit.form.DateTextBox",
|
||||
widgetAttrs : { value : dojo.date.locale.parse(dojo.byId("checkoutDate").value, {selector : "date", datePattern : "yyyy-MM-dd"}), required : true }}));
|
||||
widgetAttrs : { datePattern : "MM-dd-yyyy", required : true }}));
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
@@ -170,10 +170,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttonGroup">
|
||||
<input type="submit" id="proceed" name="_eventId_proceed" value="Proceed"
|
||||
onclick="Spring.remoting.submitForm('proceed', 'booking', {fragments:'messages,bookingForm'}); return false;"/> 
|
||||
<input type="submit" id="proceed" name="_eventId_proceed" value="Proceed" /> 
|
||||
<script type="text/javascript">
|
||||
Spring.addDecoration(new Spring.ValidateAllDecoration({elementId:'proceed', event:'onclick'}));
|
||||
Spring.addDecoration(new Spring.AjaxEventDecoration({elementId:'proceed',event:'onclick',formId:'booking',params:{fragments:'messages,bookingForm'}}));
|
||||
</script>
|
||||
<input type="submit" name="_eventId_cancel" value="Cancel"/> 
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user