You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@click.apache.org by sa...@apache.org on 2010/06/12 11:35:57 UTC

svn commit: r953971 - in /click/trunk/click/framework/src/org/apache/click: Control.java control/AbstractControl.java control/AbstractLink.java control/ActionButton.java

Author: sabob
Date: Sat Jun 12 09:35:56 2010
New Revision: 953971

URL: http://svn.apache.org/viewvc?rev=953971&view=rev
Log:
added Ajax support to Control interface. CLK-653

Modified:
    click/trunk/click/framework/src/org/apache/click/Control.java
    click/trunk/click/framework/src/org/apache/click/control/AbstractControl.java
    click/trunk/click/framework/src/org/apache/click/control/AbstractLink.java
    click/trunk/click/framework/src/org/apache/click/control/ActionButton.java

Modified: click/trunk/click/framework/src/org/apache/click/Control.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/Control.java?rev=953971&r1=953970&r2=953971&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/Control.java (original)
+++ click/trunk/click/framework/src/org/apache/click/Control.java Sat Jun 12 09:35:56 2010
@@ -463,4 +463,15 @@ public interface Control extends Seriali
      * @param buffer the specified buffer to render the control's output to
      */
     public void render(HtmlStringBuffer buffer);
+
+    public boolean hasBehaviors();
+
+    public List<Behavior> getBehaviors();
+
+    // What about setCssSelector?
+    public String getCssSelector();
+
+    // TODO this method could be changed to both check and return the target
+    // behavior
+    public boolean isAjaxTarget(Context context);
 }

Modified: click/trunk/click/framework/src/org/apache/click/control/AbstractControl.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/control/AbstractControl.java?rev=953971&r1=953970&r2=953971&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/control/AbstractControl.java (original)
+++ click/trunk/click/framework/src/org/apache/click/control/AbstractControl.java Sat Jun 12 09:35:56 2010
@@ -34,6 +34,8 @@ import javax.servlet.ServletContext;
 
 import org.apache.click.ActionEventDispatcher;
 import org.apache.click.ActionListener;
+import org.apache.click.Behavior;
+import org.apache.click.CallbackDispatcher;
 import org.apache.click.Context;
 import org.apache.click.Control;
 import org.apache.click.Page;
@@ -138,6 +140,9 @@ public abstract class AbstractControl im
     /** The control's action listener. */
     protected ActionListener actionListener;
 
+    /** The control's list of {@link org.apache.click.Behavior behaviors}. */
+    protected List<Behavior> behaviors;
+
     /**
      * The list of page HTML HEAD elements including: Javascript imports,
      * Css imports, inline Javascript and inline Css.
@@ -230,6 +235,54 @@ public abstract class AbstractControl im
         this.actionListener = listener;
     }
 
+    public boolean hasBehaviors() {
+        return (behaviors != null && behaviors.size() > 0);
+    }
+
+    public void addBehavior(Behavior behavior) {
+        if (getBehaviors().contains(behavior)) {
+            return;
+        }
+
+        getBehaviors().add(behavior);
+
+        // Register control here in case behavior was added *after* the onInit event.
+        // This can occur if the behavior is added in a listener event or during
+        // onRender.
+        CallbackDispatcher.registerBehavior(this);
+    }
+
+    public void removeBehavior(Behavior behavior) {
+        getBehaviors().remove(behavior);
+    }
+
+    public List<Behavior> getBehaviors() {
+        if (behaviors == null) {
+            behaviors = new ArrayList();
+        }
+        return behaviors;
+    }
+
+    public String getCssSelector() {
+        // TODO each control could have an optimized version of cssSelector
+        // targeting specifically that control. For now we just use a generic
+        // utility impl
+        return ClickUtils.getCssSelector(this);
+    }
+
+    public boolean isAjaxTarget(Context context) {
+        // TODO each control could have an optimized version of isAjaxTarget
+        // targeting specifically that control. For now we just check that the
+        // control id is present. Not all controls can use an ID for example:
+        // ActionLink
+        String id = getId();
+        if (id != null) {
+            return context.getRequestParameter(id) != null;
+        } else {
+            return false;
+        }
+    }
+
     /**
      * Return the control HTML attribute with the given name, or null if the
      * attribute does not exist.
@@ -498,12 +551,26 @@ public abstract class AbstractControl im
     }
 
     /**
-     * This method does nothing. Subclasses may override this method to perform
-     * initialization.
+     * If a behavior has been attached to this control, it will be registered
+     * with the {@link org.apache.click.CallbackDispatcher}.
+     * <p/>
+     * <b>Please note:</b> a common problem when overriding onInit in
+     * subclasses is forgetting to call <em>super.onInit()</em>. Consider
+     * carefully whether you should call <em>super.onInit()</em> or not.
      *
      * @see org.apache.click.Control#onInit()
      */
     public void onInit() {
+        // Q: Why does onInit need to register callback instead of addBehavior?
+        // A: Because on stateful pages addBehavior might only be called once
+        //    when the control was created so we ensure the behavior is registered
+        //    before onProcess
+        //    TODO might want to extract the code below into ClickServlet itself
+        //    to ensure this code is called *before* onProcess. Leaving the code
+        //    here opens problems if subclass does not call super.onInit
+        if (hasBehaviors()) {
+           CallbackDispatcher.registerBehavior(this);
+        }
     }
 
     /**
@@ -834,6 +901,10 @@ public abstract class AbstractControl im
         if (getActionListener() != null) {
             ActionEventDispatcher.dispatchActionEvent(this, getActionListener());
         }
+
+        if (hasBehaviors()) {
+            ActionEventDispatcher.dispatchBehavior(this);
+        }
     }
 
     /**

Modified: click/trunk/click/framework/src/org/apache/click/control/AbstractLink.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/control/AbstractLink.java?rev=953971&r1=953970&r2=953971&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/control/AbstractLink.java (original)
+++ click/trunk/click/framework/src/org/apache/click/control/AbstractLink.java Sat Jun 12 09:35:56 2010
@@ -568,6 +568,20 @@ public abstract class AbstractLink exten
         this.renderLabelAndImage = renderLabelAndImage;
     }
 
+    @Override
+    public boolean isAjaxTarget(Context context) {
+        String id = getId();
+        if (id != null) {
+            return context.getRequestParameter(id) != null;
+        } else {
+            String name = getName();
+            if (name != null) {
+                return name.equals(context.getRequestParameter(ActionLink.ACTION_LINK));
+            }
+        }
+        return false;
+    }
+
     // Public Methods ---------------------------------------------------------
 
     /**

Modified: click/trunk/click/framework/src/org/apache/click/control/ActionButton.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/control/ActionButton.java?rev=953971&r1=953970&r2=953971&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/control/ActionButton.java (original)
+++ click/trunk/click/framework/src/org/apache/click/control/ActionButton.java Sat Jun 12 09:35:56 2010
@@ -435,6 +435,20 @@ public class ActionButton extends Button
         return parameters != null && !parameters.isEmpty();
     }
 
+    @Override
+    public boolean isAjaxTarget(Context context) {
+        String id = getId();
+        if (id != null) {
+            return context.getRequestParameter(id) != null;
+        } else {
+            String name = getName();
+            if (name != null) {
+                return name.equals(context.getRequestParameter(ActionButton.ACTION_BUTTON));
+            }
+        }
+        return false;
+    }
+
     /**
      * Returns the ActionButton value if the action link was processed and has
      * a value, or null otherwise.