Save This Page
Home » struts-2.1.8.1-src » org.apache.struts2.dojo » components » [javadoc | source]
    1   /*
    2    * $Id: Autocompleter.java 720918 2008-11-26 17:06:40Z musachy $
    3    *
    4    * Licensed to the Apache Software Foundation (ASF) under one
    5    * or more contributor license agreements.  See the NOTICE file
    6    * distributed with this work for additional information
    7    * regarding copyright ownership.  The ASF licenses this file
    8    * to you under the Apache License, Version 2.0 (the
    9    * "License"); you may not use this file except in compliance
   10    * with the License.  You may obtain a copy of the License at
   11    *
   12    *  http://www.apache.org/licenses/LICENSE-2.0
   13    *
   14    * Unless required by applicable law or agreed to in writing,
   15    * software distributed under the License is distributed on an
   16    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   17    * KIND, either express or implied.  See the License for the
   18    * specific language governing permissions and limitations
   19    * under the License.
   20    */
   21   
   22   package org.apache.struts2.dojo.components;
   23   
   24   import java.util.Random;
   25   
   26   import javax.servlet.http.HttpServletRequest;
   27   import javax.servlet.http.HttpServletResponse;
   28   
   29   import org.apache.struts2.components.ComboBox;
   30   import org.apache.struts2.views.annotations.StrutsTag;
   31   import org.apache.struts2.views.annotations.StrutsTagAttribute;
   32   import org.apache.struts2.views.annotations.StrutsTagSkipInheritance;
   33   
   34   import com.opensymphony.xwork2.util.ValueStack;
   35   
   36   /**
   37    * <!-- START SNIPPET: javadoc -->
   38    * <p>The autocomplete tag is a combobox that can autocomplete text entered on the input box. If an action
   39    * is used to populate the autocompleter, the output of the action must be a well formed JSON string. </p>
   40    * <p>The autocompleter follows this rule to find its datasource:<p>
   41    * <p>1. If the response is an array, assume that it contains 2-dimension array elements, like:
   42    * <pre>
   43    * [
   44    *      ["Alabama", "AL"],
   45    *      ["Alaska", "AK"]
   46    * ]
   47    * </pre>
   48    * <p>2. If a value is specified in the "dataFieldName" attribute, and the response has a field with that
   49    * name, assume that's the datasource, which can be an array of 2-dimension array elements, or a map, 
   50    * like (assuming dataFieldName="state"):</p>
   51    * <pre>
   52    * {
   53    *      "state" : [
   54    *           ["Alabama","AL"],
   55    *           ["Alaska","AK"]
   56    *      ]
   57    * }     
   58    * or
   59    * {
   60    *      "state" : {
   61    *            "Alabama" : "AL",
   62    *            "Alaska" : "AK"
   63    *      }
   64    * }
   65    * </pre>
   66    * </pre>
   67    * <p>3. If there is a field that starts with the value specified on the "name" attribute, assume 
   68    * that's the datasource, like (assuming name="state"):</p>
   69    * <pre>
   70    * {
   71    *      "states" : [
   72    *           ["Alabama","AL"],
   73    *           ["Alaska","AK"]
   74    *      ]
   75    * }
   76    * </pre>
   77    * <p>4. Use first array that is found, like:<p>
   78    * <pre>
   79    * {
   80    *      "anything" : [
   81    *            ["Alabama", "AL"],
   82    *            ["Alaska", "AK"]
   83    *     ]       
   84    * }
   85    * <p>5. If the response is a map, use it (recommended as it is the easiest one to generate):
   86    * <pre>
   87    * {
   88    *      "Alabama" : "AL",
   89    *      "Alaska" : "AK"
   90    * }
   91    * </pre>
   92    * <!-- END SNIPPET: javadoc -->
   93    * <p>Examples</p>
   94    * <!-- START SNIPPET: example1 -->
   95    * &lt;sx:autocompleter name="autocompleter1" href="%{jsonList}"/&gt;
   96    * <!-- END SNIPPET: example1 -->
   97    * 
   98    * <!-- START SNIPPET: example2 -->
   99    * &lt;s:autocompleter name="test"  list="{'apple','banana','grape','pear'}" autoComplete="false"/&gt;
  100    * <!-- END SNIPPET: example2 -->
  101    * 
  102    * <!-- START SNIPPET: example3 -->
  103    * &lt;sx:autocompleter name="mvc" href="%{jsonList}" loadOnTextChange="true" loadMinimumCount="3"/&gt;
  104    * 
  105    * The text entered on the autocompleter is passed as a parameter to the url specified in "href", like (text is "struts"):
  106    *  
  107    * http://host/example/myaction.do?mvc=struts
  108    * <!-- END SNIPPET: example3 -->
  109    * 
  110    * <!-- START SNIPPET: example4 -->
  111    * &lt;form id="selectForm"&gt;
  112    *      &lt;sx:autocompleter  name="select" list="{'fruits','colors'}"  valueNotifyTopics="/changed" /&gt;
  113    * &lt;/form&gt;  
  114    * &lt;sx:autocompleter  href="%{jsonList}" formId="selectForm" listenTopics="/changed"/&gt;
  115    * <!-- END SNIPPET: example4 -->
  116    * 
  117    * <!-- START SNIPPET: example5 -->
  118    * &lt;sx:autocompleter  href="%{jsonList}" id="auto"/&gt;
  119    * &lt;script type="text/javascript"&gt;
  120    *   function getValues() {
  121    *      var autoCompleter = dojo.widget.byId("auto");
  122    *      
  123    *      //key (in the states example above, "AL")
  124    *      var key = autoCompleter.getSelectedKey();
  125    *      alert(key);
  126    *      
  127    *      //value (in the states example above, "Alabama")
  128    *      var value = autoCompleter.getSelectedValue();
  129    *      alert(value);
  130    *      
  131    *      //text currently on the textbox (anything the user typed)
  132    *      var text = autoCompleter.getText();
  133    *      alert(text);
  134    *   }
  135    * 
  136    *   function setValues() {
  137    *      var autoCompleter = dojo.widget.byId("auto");
  138    *      
  139    *      //key (key will be set to "AL" and value to "Alabama")
  140    *      autoCompleter.setSelectedKey("AL");
  141    *      
  142    *      //value (key will be set to "AL" and value to "Alabama")
  143    *      autoCompleter.setAllValues("AL", "Alabama");
  144    *   }
  145    * &lt;/script&gt;
  146    * <!-- END SNIPPET: example5 -->
  147    * 
  148    * <!-- START SNIPPET: example6 -->
  149    * &lt;script type="text/javascript"&gt;
  150    * dojo.event.topic.subscribe("/before", function(event, widget){
  151    *     alert('inside a topic event. before request');
  152    *     //event: set event.cancel = true, to cancel request
  153    *     //widget: widget that published the topic
  154    * });
  155    * &lt;/script&gt;         
  156    * 
  157    * &lt;sx:autocompleter beforeNotifyTopics="/before" href="%{#ajaxTest} /&gt;
  158    * <!-- END SNIPPET: example6 -->
  159    * 
  160    * <!-- START SNIPPET: example7 -->
  161    * &lt;script type="text/javascript"&gt;
  162    * dojo.event.topic.subscribe("/after", function(data, request, widget){
  163    *     alert('inside a topic event. after request');
  164    *     //data : JavaScript object from parsing response
  165    *     //request: XMLHttpRequest object
  166    *     //widget: widget that published the topic
  167    * });
  168    * &lt;/script&gt;        
  169    * 
  170    * &lt;sx:autocompleter afterNotifyTopics="/after" href="%{#ajaxTest}" /&gt;
  171    * <!-- END SNIPPET: example7 -->
  172    * 
  173    * <!-- START SNIPPET: example8-->
  174    * &lt;script type="text/javascript"&gt;
  175    * dojo.event.topic.subscribe("/error", function(error, request, widget){
  176    *     alert('inside a topic event. on error');
  177    *     //error : error object (error.message has the error message)
  178    *     //request: XMLHttpRequest object
  179    *     //widget: widget that published the topic
  180    * });
  181    * &lt;/script&gt;
  182    * 
  183    * &lt;sx:autocompleter errorNotifyTopics="/error" href="%{#ajaxTest}" /&gt;
  184    * <!-- END SNIPPET: example8 -->
  185    * 
  186    * <!-- START SNIPPET: example9 -->
  187    * &lt;script type="text/javascript"&gt;
  188    * dojo.event.topic.subscribe("/value", function(value, key, text, widget){
  189    *     alert('inside a topic event. after value changed');
  190    *     //value : selected value (like "Florida" in example above)
  191    *     //key: selected key (like "FL" in example above)
  192    *     //text: text typed into textbox
  193    *     //widget: widget that published the topic
  194    * });
  195    * &lt;/script&gt;   
  196    * 
  197    * &lt;sx:autocompleter valueNotifyTopics="/value" href="%{#ajaxTest}" /&gt;
  198    * <!-- END SNIPPET: example9 -->
  199    */
  200   @StrutsTag(name="autocompleter", tldTagClass="org.apache.struts2.dojo.views.jsp.ui.AutocompleterTag", description="Renders a combobox with autocomplete and AJAX capabilities")
  201   public class Autocompleter extends ComboBox {
  202       public static final String TEMPLATE = "autocompleter";
  203       final private static String COMPONENT_NAME = Autocompleter.class.getName();
  204       private final static transient Random RANDOM = new Random();
  205   
  206       protected String forceValidOption;
  207       protected String searchType;
  208       protected String autoComplete;
  209       protected String delay;
  210       protected String disabled;
  211       protected String href;
  212       protected String dropdownWidth;
  213       protected String dropdownHeight;
  214       protected String formId;
  215       protected String formFilter;
  216       protected String listenTopics;
  217       protected String notifyTopics;
  218       protected String indicator;
  219       protected String loadOnTextChange;
  220       protected String loadMinimumCount;
  221       protected String showDownArrow;
  222       protected String templateCssPath;
  223       protected String iconPath;
  224       protected String keyName;
  225       protected String dataFieldName;
  226       protected String beforeNotifyTopics;
  227       protected String afterNotifyTopics;
  228       protected String errorNotifyTopics;
  229       protected String valueNotifyTopics;
  230       protected String resultsLimit;
  231       protected String transport;
  232       protected String preload;
  233       protected String keyValue;
  234           
  235       public Autocompleter(ValueStack stack, HttpServletRequest request,
  236               HttpServletResponse response) {
  237           super(stack, request, response);
  238       }
  239   
  240       protected String getDefaultTemplate() {
  241           return TEMPLATE;
  242       }
  243   
  244       public String getComponentName() {
  245           return COMPONENT_NAME;
  246       }
  247   
  248   
  249       public void evaluateExtraParams() {
  250           super.evaluateExtraParams();
  251   
  252           if (forceValidOption != null)
  253               addParameter("forceValidOption", findValue(forceValidOption,
  254                       Boolean.class));
  255           if (searchType != null) {
  256               String type =  findString(searchType);
  257               if(type != null)
  258                   addParameter("searchType", type.toUpperCase());
  259           }
  260           if (autoComplete != null)
  261               addParameter("autoComplete", findValue(autoComplete, Boolean.class));
  262           if (delay != null)
  263               addParameter("delay", findValue(delay, Integer.class));
  264           if (disabled != null)
  265               addParameter("disabled", findValue(disabled, Boolean.class));
  266           if (href != null) {
  267               addParameter("href", findString(href));
  268               addParameter("mode", "remote");
  269           }
  270           if (dropdownHeight != null)
  271               addParameter("dropdownHeight", findValue(dropdownHeight, Integer.class));
  272           if (dropdownWidth != null)
  273               addParameter("dropdownWidth", findValue(dropdownWidth, Integer.class));
  274           if (formFilter != null)
  275             addParameter("formFilter", findString(formFilter));
  276           if (formId != null)
  277             addParameter("formId", findString(formId));
  278           if (listenTopics != null)
  279             addParameter("listenTopics", findString(listenTopics));
  280           if (notifyTopics != null)
  281             addParameter("notifyTopics", findString(notifyTopics));
  282           if (indicator != null)
  283               addParameter("indicator", findString(indicator));
  284           if (loadOnTextChange != null)
  285               addParameter("loadOnTextChange", findValue(loadOnTextChange, Boolean.class));
  286           if (loadMinimumCount != null)
  287               addParameter("loadMinimumCount", findValue(loadMinimumCount, Integer.class));
  288           if (showDownArrow != null)
  289               addParameter("showDownArrow", findValue(showDownArrow, Boolean.class));
  290           else
  291               addParameter("showDownArrow", Boolean.TRUE);
  292           if (templateCssPath != null)
  293               addParameter("templateCssPath", findString(templateCssPath));
  294           if (iconPath != null)
  295               addParameter("iconPath", findString(iconPath));
  296           if (dataFieldName != null)
  297               addParameter("dataFieldName", findString(dataFieldName));
  298           if (keyName != null)
  299               addParameter("keyName", findString(keyName));
  300           else {
  301               keyName = name + "Key";
  302               addParameter("keyName", findString(keyName));
  303           }
  304           if (transport != null)
  305               addParameter("transport", findString(transport));
  306           if (preload != null)
  307               addParameter("preload", findValue(preload, Boolean.class));
  308           
  309           if (keyValue != null)
  310               addParameter("nameKeyValue", findString(keyValue));
  311           else {
  312               String keyNameExpr = "%{" + keyName + "}";
  313               addParameter("nameKeyValue", findString(keyNameExpr));
  314           }
  315           
  316           
  317           if (beforeNotifyTopics != null)
  318               addParameter("beforeNotifyTopics", findString(beforeNotifyTopics));
  319           if (afterNotifyTopics != null)
  320               addParameter("afterNotifyTopics", findString(afterNotifyTopics));
  321           if (errorNotifyTopics != null)
  322               addParameter("errorNotifyTopics", findString(errorNotifyTopics));
  323           if (valueNotifyTopics != null)
  324               addParameter("valueNotifyTopics", findString(valueNotifyTopics));
  325           if (resultsLimit != null)
  326               addParameter("searchLimit", findString(resultsLimit));
  327           
  328           // generate a random ID if not explicitly set and not parsing the content
  329           Boolean parseContent = (Boolean)stack.getContext().get(Head.PARSE_CONTENT);
  330           boolean generateId = (parseContent != null ? !parseContent : true);
  331           
  332           addParameter("pushId", generateId);
  333           if ((this.id == null || this.id.length() == 0) && generateId) {
  334               // resolves Math.abs(Integer.MIN_VALUE) issue reported by FindBugs 
  335               // http://findbugs.sourceforge.net/bugDescriptions.html#RV_ABSOLUTE_VALUE_OF_RANDOM_INT
  336               int nextInt = RANDOM.nextInt();
  337               nextInt = nextInt == Integer.MIN_VALUE ? Integer.MAX_VALUE : Math.abs(nextInt);  
  338               this.id = "widget_" + String.valueOf(nextInt);
  339           }
  340       }
  341   
  342       @Override
  343       @StrutsTagSkipInheritance
  344       public void setTheme(String theme) {
  345           super.setTheme(theme);
  346       }
  347       
  348       @Override
  349       public String getTheme() {
  350           return "ajax";
  351       }
  352       
  353       protected Object findListValue() {
  354           return (list != null) ? findValue(list, Object.class) : null;
  355       }
  356   
  357       @StrutsTagAttribute(description="Whether autocompleter should make suggestion on the textbox", type="Boolean", defaultValue="false")
  358       public void setAutoComplete(String autoComplete) {
  359           this.autoComplete = autoComplete;
  360       }
  361   
  362       @StrutsTagAttribute(description="Enable or disable autocompleter", type="Boolean", defaultValue="false")
  363       public void setDisabled(String disabled) {
  364           this.disabled = disabled;
  365       }
  366   
  367       @StrutsTagAttribute(description="Force selection to be one of the options", type="Boolean", defaultValue="false")
  368       public void setForceValidOption(String forceValidOption) {
  369           this.forceValidOption = forceValidOption;
  370       }
  371   
  372       @StrutsTagAttribute(description="The URL used to load the options")
  373       public void setHref(String href) {
  374           this.href = href;
  375       }
  376   
  377       @StrutsTagAttribute(description="Delay before making the search", type="Integer", defaultValue="100")
  378       public void setDelay(String searchDelay) {
  379           this.delay = searchDelay;
  380       }
  381   
  382       @StrutsTagAttribute(description="how the search must be performed, options are: 'startstring', 'startword' " +
  383                   "and 'substring'", defaultValue="stringstart")
  384       public void setSearchType(String searchType) {
  385           this.searchType = searchType;
  386       }
  387   
  388       @StrutsTagAttribute(description="Dropdown's height in pixels", type="Integer", defaultValue="120")
  389       public void setDropdownHeight(String height) {
  390           this.dropdownHeight = height;
  391       }
  392   
  393       @StrutsTagAttribute(description="Dropdown's width", type="Integer", defaultValue="same as textbox")
  394       public void setDropdownWidth(String width) {
  395           this.dropdownWidth = width;
  396       }
  397   
  398       @StrutsTagAttribute(description="Function name used to filter the fields of the form")
  399       public void setFormFilter(String formFilter) {
  400         this.formFilter = formFilter;
  401       }
  402   
  403       @StrutsTagAttribute(description="Form id whose fields will be serialized and passed as parameters")
  404       public void setFormId(String formId) {
  405         this.formId = formId;
  406       }
  407   
  408       @StrutsTagAttribute(description="Topic that will trigger a reload")
  409       public void setListenTopics(String listenTopics) {
  410         this.listenTopics = listenTopics;
  411       }
  412   
  413       @StrutsTagAttribute(description="Topics that will be published when content is reloaded")
  414       public void setNotifyTopics(String onValueChangedPublishTopic) {
  415         this.notifyTopics = onValueChangedPublishTopic;
  416       }
  417   
  418       @StrutsTagAttribute(description="Id of element that will be shown while request is made")
  419       public void setIndicator(String indicator) {
  420           this.indicator = indicator;
  421       }
  422   
  423       @StrutsTagAttribute(description="Minimum number of characters that will force the content to be loaded", type="Integer", defaultValue="3")
  424       public void setLoadMinimumCount(String loadMinimumCount) {
  425           this.loadMinimumCount = loadMinimumCount;
  426       }
  427   
  428       @StrutsTagAttribute(description="Options will be reloaded everytime a character is typed on the textbox", type="Boolean", defaultValue="true")
  429       public void setLoadOnTextChange(String loadOnType) {
  430           this.loadOnTextChange = loadOnType;
  431       }
  432   
  433       @StrutsTagAttribute(description="Show or hide the down arrow button", type="Boolean", defaultValue="true")
  434       public void setShowDownArrow(String showDownArrow) {
  435           this.showDownArrow = showDownArrow;
  436       }
  437   
  438       // Override as not required
  439       @StrutsTagAttribute(description="Iteratable source to populate from.")
  440       public void setList(String list) {
  441           super.setList(list);
  442       }
  443       
  444       @StrutsTagAttribute(description="Template css path")
  445       public void setTemplateCssPath(String templateCssPath) {
  446           this.templateCssPath = templateCssPath;
  447       }
  448       
  449       @StrutsTagAttribute(description="Path to icon used for the dropdown")
  450       public void setIconPath(String iconPath) {
  451           this.iconPath = iconPath;
  452       }
  453       
  454       @StrutsTagAttribute(description="Name of the field to which the selected key will be assigned")
  455       public void setKeyName(String keyName) {
  456          this.keyName = keyName;
  457       }
  458   
  459       @StrutsTagAttribute(description="Name of the field in the returned JSON object that contains the data array", defaultValue="Value specified in 'name'")
  460       public void setDataFieldName(String dataFieldName) {
  461           this.dataFieldName = dataFieldName;
  462       }
  463       
  464       @StrutsTagAttribute(description="The css class to use for element")
  465       public void setCssClass(String cssClass) {
  466           super.setCssClass(cssClass);
  467       }
  468   
  469       @StrutsTagAttribute(description="The css style to use for element")
  470       public void setCssStyle(String cssStyle) {
  471           super.setCssStyle(cssStyle);
  472       }
  473   
  474       @StrutsTagAttribute(description="The id to use for the element")
  475       public void setId(String id) {
  476           super.setId(id);
  477       }
  478   
  479       @StrutsTagAttribute(description="The name to set for element")
  480       public void setName(String name) {
  481           super.setName(name);
  482       }
  483   
  484       @StrutsTagAttribute(description="Preset the value of input element")
  485       public void setValue(String arg0) {
  486           super.setValue(arg0);
  487       }
  488       
  489       @StrutsTagAttribute(description="Comma delimmited list of topics that will published after the request(if the request succeeds)")
  490       public void setAfterNotifyTopics(String afterNotifyTopics) {
  491           this.afterNotifyTopics = afterNotifyTopics;
  492       }
  493   
  494       @StrutsTagAttribute(description="Comma delimmited list of topics that will published before the request")
  495       public void setBeforeNotifyTopics(String beforeNotifyTopics) {
  496           this.beforeNotifyTopics = beforeNotifyTopics;
  497       }
  498   
  499       @StrutsTagAttribute(description="Comma delimmited list of topics that will published after the request(if the request fails)")
  500       public void setErrorNotifyTopics(String errorNotifyTopics) {
  501           this.errorNotifyTopics = errorNotifyTopics;
  502       }
  503   
  504       @StrutsTagAttribute(description="Comma delimmited list of topics that will published when a value is selected")
  505       public void setValueNotifyTopics(String valueNotifyTopics) {
  506           this.valueNotifyTopics = valueNotifyTopics;
  507       }
  508       
  509       @StrutsTagAttribute(description="Limit how many results are shown as autocompletion options, set to -1 for unlimited results", defaultValue="30", type = "Integer")
  510       public void setResultsLimit(String resultsLimit) {
  511           this.resultsLimit = resultsLimit;
  512       }
  513       
  514       @StrutsTagAttribute(description="Transport used by Dojo to make the request", defaultValue="XMLHTTPTransport")
  515       public void setTransport(String transport) {
  516           this.transport = transport;
  517       }
  518       
  519       @StrutsTagAttribute(description="Load options when page is loaded", type="Boolean", defaultValue="true")
  520       public void setPreload(String preload) {
  521           this.preload = preload;
  522       }
  523   
  524       @StrutsTagAttribute(description="Initial key value")
  525       public void setKeyValue(String keyValue) {
  526           this.keyValue = keyValue;
  527       }
  528   }

Save This Page
Home » struts-2.1.8.1-src » org.apache.struts2.dojo » components » [javadoc | source]