From a55dd335d284bdcc981191b03c23fe85ef253faa Mon Sep 17 00:00:00 2001 From: Erik Brakkee Date: Tue, 7 Sep 2010 20:04:51 +0000 Subject: [PATCH] added the capability to add an optional configuration object to the ready function. This allows the implementation of plugins that require configuration. One example is a tooltip plugin that requires the tooltip text and possibly other options to configure the tooltip. --- wicket/components/pom.xml | 5 + .../wicket/behavior/PreselectionBehavior.java | 4 +- .../wicket/jquery/AbstractJQueryBehavior.java | 98 ++++++++++++++++--- .../jquery/AbstractJQueryBehaviorTest.java | 79 +++++++++++++-- 4 files changed, 163 insertions(+), 23 deletions(-) diff --git a/wicket/components/pom.xml b/wicket/components/pom.xml index 19d008f0..9d2c6247 100644 --- a/wicket/components/pom.xml +++ b/wicket/components/pom.xml @@ -26,6 +26,11 @@ wamblee-support-general 0.6-SNAPSHOT + + net.sf.flexjson + flexjson + 2.0 + org.wamblee wamblee-support-inject diff --git a/wicket/components/src/main/java/org/wamblee/wicket/behavior/PreselectionBehavior.java b/wicket/components/src/main/java/org/wamblee/wicket/behavior/PreselectionBehavior.java index 047b1eeb..3331238b 100644 --- a/wicket/components/src/main/java/org/wamblee/wicket/behavior/PreselectionBehavior.java +++ b/wicket/components/src/main/java/org/wamblee/wicket/behavior/PreselectionBehavior.java @@ -37,13 +37,15 @@ import org.wamblee.wicket.jquery.AbstractJQueryBehavior; */ public class PreselectionBehavior extends AbstractJQueryBehavior { + private static final String READY_FUNCTION = "org.wamblee.preselectionSetup"; + static final String PRESELECT_SCRIPT = "wamblee-preselect.js"; private static HeaderContributor PRESELECTION_BEHAVIOR = JavascriptPackageResource .getHeaderContribution(PreselectionBehavior.class, PRESELECT_SCRIPT); public PreselectionBehavior() { - super("preselectionSetup", new NamespaceBehavior(), PRESELECTION_BEHAVIOR); + super(READY_FUNCTION, new NamespaceBehavior(), PRESELECTION_BEHAVIOR); } } diff --git a/wicket/components/src/main/java/org/wamblee/wicket/jquery/AbstractJQueryBehavior.java b/wicket/components/src/main/java/org/wamblee/wicket/jquery/AbstractJQueryBehavior.java index b1d27134..d49110dd 100644 --- a/wicket/components/src/main/java/org/wamblee/wicket/jquery/AbstractJQueryBehavior.java +++ b/wicket/components/src/main/java/org/wamblee/wicket/jquery/AbstractJQueryBehavior.java @@ -23,19 +23,33 @@ import org.apache.wicket.behavior.IBehavior; import org.apache.wicket.markup.html.IHeaderResponse; import org.wamblee.wicket.behavior.CompositeBehavior; +import flexjson.JSONSerializer; + /** * Abstract JQuery hehavior class that makes it easy to write jQuery behaviors: * * + * The ready function will be invoked as part of a ready handler and will invoke + * a function with two arguments. The first is the id of the component and the second + * is a configuration object. + *

+ * The second parameter is obtained through a call to {@link #getConfigurationJavascript()}. + * + * * @author Erik Brakkee * + * */ -public class AbstractJQueryBehavior extends CompositeBehavior { +public class AbstractJQueryBehavior extends CompositeBehavior { + + private static final String DEFAULT_NAMESPACE = "org.wamblee"; + private static JSONSerializer DEFAULT_JSON_SERIALIZER = new JSONSerializer(); private Component component; private String function; @@ -44,8 +58,8 @@ public class AbstractJQueryBehavior extends CompositeBehavior { * Constructs the behavior. * * @param aFunction - * Function to be invoked from the ready handler. This function is invoked with a - * CSS selector that identifies the component. + * Function to be invoked from the ready handler. This function + * is invoked with a CSS selector that identifies the component. * @param aBehaviors * Behaviors to add in addition to the basic JQuery stuff. */ @@ -84,34 +98,92 @@ public class AbstractJQueryBehavior extends CompositeBehavior { @Override public void renderHead(IHeaderResponse aResponse) { super.renderHead(aResponse); - String jsString = createReadyFunction(function, component); + String jsString = createReadyFunction(); aResponse.renderJavascript(jsString, null); } /** * Creates a jQuery ready handler that invokes a given javascript function - * with the id of a component. + * with the id of a component and with a second parameter of parameters to + * pass additional information to the function. * * @param aFunction - * Javascript function to invoke. + * Javascript function to invoke, the name of this function must + * include the namespace as it is called from a global scope. * @param aComponent * Component to invoke the id for. * @return */ - public static String createReadyFunction(String aFunction, - Component aComponent) { - if (!aComponent.getOutputMarkupId()) { + String createReadyFunction() { + if (!component.getOutputMarkupId()) { throw new IllegalStateException( "The component " + - aComponent + + component + " does not have its markup id set so this ready handler will not have any effect"); } StringBuffer js = new StringBuffer(); js.append("jQuery(function(){"); - js.append("org.wamblee." + aFunction + "(\"#" + - aComponent.getMarkupId() + "\");"); + js.append(function + "("); + js.append("\"#" + component.getMarkupId() + "\""); + String config = getConfigurationJavascript(); + if (config != null) { + js.append(","); + js.append(config); + } + js.append(");"); js.append("});"); String jsString = js.toString(); return jsString; } + + /** + * Returns a javascript object that is passed as second argument to the + * ready function. This method uses {@link #getConfigurationObject()} to + * obtain the configuration object to use which is then serialized to + * javascript using {@link JSONSerializer}. Subclasses can override the + * default JSONSerializer by implementing {@link #getCustomSerializer()}. + *

+ * Subclasses should override this method to perform custom serialization. + * + * @return Configuration object in javascript. + */ + protected String getConfigurationJavascript() { + Object config = getConfigurationObject(); + return getActualSerializer().serialize(config); + } + + /** + * Gets the actual serializer to use. It uses {@link #getCustomSerializer()} + * to check if there is a custom serializer available. + * + * @return Serializer. + */ + private JSONSerializer getActualSerializer() { + JSONSerializer serializer = getCustomSerializer(); + if (serializer != null) { + return serializer; + } + return DEFAULT_JSON_SERIALIZER; + } + + /** + * Returns the serializer to use. Implementations can override this method + * to perform custom initialization of the serializer knowing the type of + * configuration object to use. + * + * @return Custom serializer to use. + */ + protected JSONSerializer getCustomSerializer() { + return null; + } + + /** + * Gets the configuration object to use. This is transformed to JSON using + * the serializer. + * + * @return Configuration object. + */ + protected ConfigType getConfigurationObject() { + return null; + } } diff --git a/wicket/components/src/test/java/org/wamblee/wicket/jquery/AbstractJQueryBehaviorTest.java b/wicket/components/src/test/java/org/wamblee/wicket/jquery/AbstractJQueryBehaviorTest.java index 92fcf16e..e6c001fc 100644 --- a/wicket/components/src/test/java/org/wamblee/wicket/jquery/AbstractJQueryBehaviorTest.java +++ b/wicket/components/src/test/java/org/wamblee/wicket/jquery/AbstractJQueryBehaviorTest.java @@ -25,6 +25,8 @@ import org.junit.Before; import org.junit.Test; import org.wamblee.wicket.MyPage; +import flexjson.JSONSerializer; + import static junit.framework.TestCase.*; public class AbstractJQueryBehaviorTest { @@ -39,9 +41,9 @@ public class AbstractJQueryBehaviorTest { public void tearDown() { wicket.destroy(); } - + @Test - public void testVerifyBasicFunc() { + public void testVerifyBasicFunc() { MyPage page = new MyPage(); page.getLabel().add(new AbstractJQueryBehavior("initfunc")); wicket.startPage(page); @@ -52,19 +54,78 @@ public class AbstractJQueryBehaviorTest { assertTrue(doc.contains("jquery-noconflict")); assertTrue(doc.contains("initfunc")); } - + @Test - public void testCreateReadyJavascript() { + public void testCreateReadyJavascript() { Component component = new Label("label"); component.setOutputMarkupId(true); - String readyHandler = AbstractJQueryBehavior.createReadyFunction("myfunc", component); - assertEquals("jQuery(function(){org.wamblee.myfunc(\"#" + component.getMarkupId() + "\");});", readyHandler); + AbstractJQueryBehavior behavior = new AbstractJQueryBehavior("myfunc"); + behavior.bind(component); + String readyHandler = behavior.createReadyFunction(); + assertEquals("jQuery(function(){myfunc(\"#" + component.getMarkupId() + + "\",null);});", readyHandler); + } + + @Test + public void testCreateReadyJavaScriptWithCustomConfigJavascript() { + Component component = new Label("label"); + component.setOutputMarkupId(false); + AbstractJQueryBehavior behavior = new AbstractJQueryBehavior("myfunc") { + @Override + protected String getConfigurationJavascript() { + return "bla"; + } + }; + behavior.bind(component); + String readyHandler = behavior.createReadyFunction(); + assertEquals("jQuery(function(){myfunc(\"#" + component.getMarkupId() + + "\",bla);});", readyHandler); + } + + public static final class X { + private int x = 10; + public int getX() { + return x; + } + } + + @Test + public void testCreateReadyJavaScriptWithConfig() { + Component component = new Label("label"); + component.setOutputMarkupId(false); + AbstractJQueryBehavior behavior = new AbstractJQueryBehavior("myfunc") { + @Override + protected Object getConfigurationObject() { + return new X(); + } + }; + behavior.bind(component); + String readyHandler = behavior.createReadyFunction(); + String config = new JSONSerializer().serialize(new X()); + assertEquals("jQuery(function(){myfunc(\"#" + component.getMarkupId() + + "\"," + config + ");});", readyHandler); } - @Test(expected = IllegalStateException.class) - public void testCreateReadyJavascriptNoMarkupId() { + @Test + public void testCreateReadyJavaScriptWithConfigWithCustomSerializer() { Component component = new Label("label"); - String readyHandler = AbstractJQueryBehavior.createReadyFunction("myfunc", component); + component.setOutputMarkupId(false); + AbstractJQueryBehavior behavior = new AbstractJQueryBehavior("myfunc") { + @Override + protected Object getConfigurationObject() { + return new X(); + } + @Override + protected JSONSerializer getCustomSerializer() { + return new JSONSerializer().exclude("x"); + } + }; + behavior.bind(component); + String readyHandler = behavior.createReadyFunction(); + String config = new JSONSerializer().exclude("x").serialize(new X()); + assertEquals("jQuery(function(){myfunc(\"#" + component.getMarkupId() + + "\"," + config + ");});", readyHandler); } + } -- 2.31.1