added the capability to add an optional configuration
authorerik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Tue, 7 Sep 2010 20:04:51 +0000 (20:04 +0000)
committererik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Tue, 7 Sep 2010 20:04:51 +0000 (20:04 +0000)
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
wicket/components/src/main/java/org/wamblee/wicket/behavior/PreselectionBehavior.java
wicket/components/src/main/java/org/wamblee/wicket/jquery/AbstractJQueryBehavior.java
wicket/components/src/test/java/org/wamblee/wicket/jquery/AbstractJQueryBehaviorTest.java

index 19d008f093e4abc9b63580d2e08318236b07d4c7..9d2c624723e8144a4437cafac56e1191bee2d9ea 100644 (file)
       <artifactId>wamblee-support-general</artifactId>
       <version>0.6-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>net.sf.flexjson</groupId>
+      <artifactId>flexjson</artifactId>
+      <version>2.0</version>
+    </dependency>
     <dependency>
       <groupId>org.wamblee</groupId>
       <artifactId>wamblee-support-inject</artifactId>
index 047b1eebd98510cfc1d3a9d6df9c8d9eee455ac2..3331238b0b6d0f3a3cc30e27405dcfe04f4c9aa0 100644 (file)
@@ -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);
     }
 
 }
index b1d271346ffe605579333ed8cf7f72bd84cceecc..d49110dd3d14e929162d149d2e3ba950abea3b22 100644 (file)
@@ -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:
  * <ul>
  * <li>Creating a ready function which will be invoked for the component</li>
  * <li>Checking that the component is not a page</li>
  * <li>Ensuring tha the markup id of the component is output</li>
- * <li>Creating a call to an intialization function from the ready handler using the component id </li>
+ * <li>Creating a call to an intialization function from the ready handler using
+ * the component id</li>
  * </ul>
  * 
+ * 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. 
+ * <p>
+ * The second parameter is obtained through a call to {@link #getConfigurationJavascript()}.
+ * 
+ * 
  * @author Erik Brakkee
  * 
+ * <ConfigType> 
  */
-public class AbstractJQueryBehavior extends CompositeBehavior {
+public class AbstractJQueryBehavior<ConfigType> 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()}.
+     * <p>
+     * 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;
+    }
 }
index 92fcf16e38e6da9563e8a242288613dcc8cc68d2..e6c001fc3c1d88c137d79c4c811a84be0a163bcf 100644 (file)
@@ -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);
     }
     
+
 }