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/07/01 11:20:50 UTC
svn commit: r959565 -
/click/trunk/click/extras/src/org/apache/click/extras/control/AutoCompleteTextField.java
Author: sabob
Date: Thu Jul 1 09:20:42 2010
New Revision: 959565
URL: http://svn.apache.org/viewvc?rev=959565&view=rev
Log:
simplify AutoCompleteTextField. CLK-707
Modified:
click/trunk/click/extras/src/org/apache/click/extras/control/AutoCompleteTextField.java
Modified: click/trunk/click/extras/src/org/apache/click/extras/control/AutoCompleteTextField.java
URL: http://svn.apache.org/viewvc/click/trunk/click/extras/src/org/apache/click/extras/control/AutoCompleteTextField.java?rev=959565&r1=959564&r2=959565&view=diff
==============================================================================
--- click/trunk/click/extras/src/org/apache/click/extras/control/AutoCompleteTextField.java (original)
+++ click/trunk/click/extras/src/org/apache/click/extras/control/AutoCompleteTextField.java Thu Jul 1 09:20:42 2010
@@ -18,14 +18,17 @@
*/
package org.apache.click.extras.control;
-import java.io.IOException;
-import java.io.PrintWriter;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
-import javax.servlet.http.HttpServletResponse;
-
+import org.apache.click.Behavior;
import org.apache.click.Context;
+import org.apache.click.Control;
import org.apache.click.Page;
+import org.apache.click.Partial;
+import org.apache.click.ajax.AjaxBehavior;
import org.apache.click.control.TextField;
import org.apache.click.element.CssImport;
import org.apache.click.element.Element;
@@ -33,6 +36,7 @@ import org.apache.click.element.JsImport
import org.apache.click.element.JsScript;
import org.apache.click.util.ClickUtils;
import org.apache.click.util.HtmlStringBuffer;
+import org.apache.commons.lang.StringUtils;
/**
* Provides an Auto Complete Text Field control: <input type='text'>.
@@ -50,10 +54,10 @@ import org.apache.click.util.HtmlStringB
* the abstract method <tt>getAutoCompleteList()</tt> is implemented to provide
* the list of suggested values.
*
- * <pre class="codeJava">
- * AutoCompleteTextField nameField = <span class="kw">new</span> AutoCompleteTextField(<span class="st">"name"</span>) {
+ * <pre class="prettyprint">
+ * AutoCompleteTextField nameField = new AutoCompleteTextField("name") {
* public List getAutoCompleteList(String criteria) {
- * <span class="kw">return</span> getCustomerService().getCustomerNamesLike(criteria);
+ * return getCustomerService().getCustomerNamesLike(criteria);
* }
* };
* form.add(nameField); </pre>
@@ -92,9 +96,19 @@ public abstract class AutoCompleteTextFi
/**
* The JavaScript 'script.aculo.us' Autocompleter initialization options,
- * default value is: <tt>{minChars:1}</tt>.
+ * default value is: <tt>minChars:1</tt>.
*/
- protected String autoCompleteOptions = "{minChars:1}";
+ protected String autoCompleteOptions = "minChars:1";
+
+ /**
+ * Additional parameters to send to server. Note the AutoCompleteTextField
+ * {@link #getId() id} is always sent as a parameter to the server in order
+ * for Click to identify the field.
+ */
+ protected Map<String, Object> parameters;
+
+ /** The Field Ajax Behavior provides autocomplete support. */
+ protected Behavior behavior;
// Constructors -----------------------------------------------------------
@@ -178,7 +192,7 @@ public abstract class AutoCompleteTextFi
/**
* Return the JavaScript 'script.aculo.us' Autocompleter initialization
- * options, default value is: <tt>{}</tt>.
+ * options, default value is <tt>"minChars:1"</tt>.
*
* @return the JavaScript Autocompleter initialization options
*/
@@ -188,32 +202,20 @@ public abstract class AutoCompleteTextFi
/**
* Set the JavaScript 'script.aculo.us' Autocompleter initialization
- * options, default value is: <tt>{minChars:1}</tt>.
+ * options, default value is: <tt>minChars:1</tt>.
* <p/>
- * Scriptaculous AutoCompleter supports sending arbitrary request parameters
- * as part of its options. See the Ajax-AutoCompleter
- * <a href="http://github.com/madrobby/scriptaculous/wikis/ajax-autocompleter" target="_blank">documentation</a>
- * for some examples.
+ * For the full list of available options, see the Ajax-AutoCompleter
+ * <a href="http://github.com/madrobby/scriptaculous/wikis/ajax-autocompleter" target="_blank">documentation</a>.
* <p/>
- * Below is an example of how to send extra request parameters:
+ * Below is an example of how to set some of these options:
* <pre class="prettyprint">
* public void onInit() {
* AutoCompleteTextField cityField = new AutoCompleteTextField("cityField");
- * HtmlStringBuffer buffer = new HtmlStringBuffer();
- * buffer.append("{"); // Options opens with squiggly bracket
- * buffer.append(stateField.getName());
- * buffer.append("=");
- * buffer.append(stateField.getValue());
- * buffer.append("&");
- * buffer.append(idField.getName());
- * buffer.append("=");
- * buffer.append(idField.getValue());
- * buffer.append("}"); // Options closes with squiggly bracket
- * field.setAutoCompleteOptions(options.toString());
+ * field.setAutoCompleteOptions("minChars:1, frequency: 0.6");
* } </pre>
*
- * Note that you can add any of the options specified on the
- * Ajax-AutoCompleter wiki.
+ * <b>Please note:</b> to send additional request parameters use
+ * {@link #setParameter(java.lang.String, java.lang.Object)} instead
*
* @param options the JavaScript Autocompleter initialization options
*/
@@ -222,25 +224,51 @@ public abstract class AutoCompleteTextFi
}
/**
- * @see org.apache.click.control.Field#setParent(Object)
+ * Return true if this field has additional parameters, false otherwise.
*
- * @param parent the parent of the Control
- * @throws IllegalStateException if {@link #name} is not defined
- * @throws IllegalArgumentException if the given parent instance is
- * referencing <tt>this</tt> object: <tt>if (parent == this)</tt>
+ * @return true if this field has additional parameters, false otherwise
*/
- @Override
- public void setParent(Object parent) {
- if (parent == null) {
- // If the field parent control is set to null (indicating the field
- // is being removed), also remove the field from its parent page
- Page page = getPage();
- if (page != null) {
- page.getControls().remove(this);
- page.getModel().remove(getName());
- }
+ public boolean hasParameters() {
+ return parameters != null && !parameters.isEmpty();
+ }
+
+ /**
+ * Return this field map of additional parameters.
+ *
+ * @return this field map of additional parameters
+ */
+ public Map<String, Object> getParameters() {
+ if (parameters == null) {
+ parameters = new HashMap<String, Object>();
+ }
+ return parameters;
+ }
+
+ /**
+ * Set the field parameter with the given parameter name and value. If the
+ * value is null the parameter will be removed.
+ * <p/>
+ * Scriptaculous AutoCompleter supports sending arbitrary request parameters
+ * as part of its options. See the Ajax-AutoCompleter
+ * <a href="http://github.com/madrobby/scriptaculous/wikis/ajax-autocompleter" target="_blank">documentation</a>
+ * for some examples.
+ * <p/>
+ * Below is an example of how to send additional request parameters:
+ * <pre class="prettyprint">
+ * public void onInit() {
+ * AutoCompleteTextField cityField = new AutoCompleteTextField("cityField");
+ * cityField.setParameter(stateField.getName(), stateField.getValue());
+ * } </pre>
+ *
+ * @param name the attribute name
+ * @param value the attribute value
+ */
+ public void setParameter(String name, Object value) {
+ if (value != null) {
+ getParameters().put(name, value);
+ } else {
+ getParameters().remove(name);
}
- super.setParent(parent);
}
/**
@@ -310,9 +338,30 @@ public abstract class AutoCompleteTextFi
buffer.append("new Ajax.Autocompleter(");
buffer.append("'").append(fieldId).append("'");
buffer.append(",'").append(fieldId).append("-auto-complete-div'");
- buffer.append(",'").append(contextPath).append(page.getPath()).append(
- "'");
- buffer.append(",").append(getAutoCompleteOptions()).append(");");
+ buffer.append(",'").append(contextPath).append(page.getPath()).append("'");
+
+ String id = getId();
+
+ // Include the field id as a parameter
+ buffer.append(",{parameters: '").append(id).append("=1'");
+
+ if (hasParameters()) {
+
+ for (Entry<String, Object> entry : getParameters().entrySet()) {
+ // Add additional parameters
+ buffer.append("&");
+ buffer.append(entry.getKey());
+ buffer.append("=");
+ buffer.append(entry.getValue());
+ }
+ }
+
+ if (StringUtils.isNotEmpty(getAutoCompleteOptions())) {
+ buffer.append(",").append(getAutoCompleteOptions());
+ }
+
+ buffer.append("});");
+
script.setContent(buffer.toString());
headElements.add(script);
}
@@ -332,7 +381,7 @@ public abstract class AutoCompleteTextFi
buffer.elementStart("div");
buffer.appendAttribute("class", "auto_complete");
- buffer.appendAttribute("id", getId() + "-auto-complete-div");
+ buffer.append(" id=\"").append(getId()).append("-auto-complete-div\"");
buffer.closeTag();
buffer.elementEnd("div");
}
@@ -348,70 +397,84 @@ public abstract class AutoCompleteTextFi
@Override
public void onInit() {
super.onInit();
+ super.addBehavior(getBehavior());
+ }
- Page page = getPage();
- if (page == null) {
- // If parent page is not reachable, exit early
- return;
- }
+ /**
+ * This method is not supported and throws an UnsupportedOperationException
+ * if invoked.
+ *
+ * @param behavior the behavior to add
+ * @throws UnsupportedOperationException this field uses an internal behavior
+ * instead
+ */
+ @Override
+ public void addBehavior(Behavior behavior) {
+ throw new UnsupportedOperationException("AutoCompleteTextField uses"
+ + " an internal behavior, extra behaviors are not supported");
+ }
+
+ /**
+ * This method is not supported and throws an UnsupportedOperationException
+ * if invoked.
+ *
+ * @param behavior the behavior to add
+ * @throws UnsupportedOperationException if invoked
+ */
+ @Override
+ public void removeBehavior(Behavior behavior) {
+ throw new UnsupportedOperationException("AutoCompleteTextField uses"
+ + " an internal behavior, extra behaviors are not supported");
+ }
- // See whether control has been registered at Page level.
- Object control = page.getModel().get(getName());
+ // Protected Methods ------------------------------------------------------
- // If not registered, then register control
- if (control == null) {
- // Ensure current parent control does not change
- Object parent = getParent();
- page.addControl(this);
- setParent(parent);
-
- } else if (!(control instanceof AutoCompleteTextField)) {
- String message =
- "Non AutoCompleteTextField object '"
- + control.getClass().toString()
- + "' already registered in Page as: "
- + getName();
- throw new IllegalStateException(message);
+ /**
+ * Return the field internal Ajax behavior instance.
+ *
+ * @return the field internal Ajax behavior instance
+ */
+ protected Behavior getBehavior() {
+ if(behavior == null) {
+ behavior = createBehavior();
}
+ return behavior;
}
/**
- * Process the page request and if an auto completion POST request then
- * render an list of suggested values.
- *
- * @see org.apache.click.Control#onProcess()
+ * Create the field Ajax behavior instance.
*
- * @return false if an auto complete request, otherwise returns true
+ * @return the field Ajax behavior instance
*/
- @Override
- public boolean onProcess() {
- Context context = getContext();
- if (context.isPost()) {
- // If an auto complete POST request then render suggested list,
- // otherwise continue as normal
- if (getForm().isFormSubmission()) {
- return super.onProcess();
- } else if (context.isAjaxRequest()) {
- String criteria = context.getRequestParameter(getName());
- if (criteria != null) {
- List autoCompleteList = getAutoCompleteList(criteria);
- renderAutoCompleteList(autoCompleteList);
- return false;
+ protected Behavior createBehavior() {
+ AjaxBehavior behavior = new AjaxBehavior() {
+
+ @Override
+ public Partial onAction(Control source) {
+ Partial partial = new Partial();
+
+ String contentType = getPage().getContentType();
+ partial.setContentType(contentType);
+
+ List autocompleteList = getAutoCompleteList(getValue());
+ if (autocompleteList != null) {
+ HtmlStringBuffer buffer = new HtmlStringBuffer(10 + (autocompleteList.size() * 20));
+ renderAutoCompleteList(buffer, autocompleteList);
+ partial.setContent(buffer.toString());
}
+ return partial;
}
- }
- return true;
- }
+ };
- // Protected Methods ------------------------------------------------------
+ return behavior;
+ }
/**
* Render the suggested auto completion list to the servlet response.
*
* @param autoCompleteList the suggested list of auto completion values
*/
- protected void renderAutoCompleteList(List<String> autoCompleteList) {
- HtmlStringBuffer buffer = new HtmlStringBuffer(10 + (autoCompleteList.size() * 20));
+ protected void renderAutoCompleteList(HtmlStringBuffer buffer, List<String> autoCompleteList) {
buffer.append("<ul>");
@@ -423,23 +486,5 @@ public abstract class AutoCompleteTextFi
}
buffer.append("</ul>");
-
- HttpServletResponse response = getContext().getResponse();
-
- response.setContentType(getPage().getContentType());
-
- try {
- PrintWriter writer = response.getWriter();
- writer.print(buffer.toString());
- writer.flush();
- writer.close();
-
- getPage().setPath(null);
-
- } catch (IOException ioe) {
- throw new RuntimeException(ioe);
- }
}
-
-
}