Coverage Report - org.apache.tapestry.dojo.form.Autocompleter
 
Classes in this File Line Coverage Branch Coverage Complexity
Autocompleter
89% 
100% 
1.609
 
 1  
 // Copyright May 4, 2006 The Apache Software Foundation
 2  
 //
 3  
 // Licensed under the Apache License, Version 2.0 (the "License");
 4  
 // you may not use this file except in compliance with the License.
 5  
 // You may obtain a copy of the License at
 6  
 //
 7  
 //     http://www.apache.org/licenses/LICENSE-2.0
 8  
 //
 9  
 // Unless required by applicable law or agreed to in writing, software
 10  
 // distributed under the License is distributed on an "AS IS" BASIS,
 11  
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  
 // See the License for the specific language governing permissions and
 13  
 // limitations under the License.
 14  
 package org.apache.tapestry.dojo.form;
 15  
 
 16  
 import org.apache.tapestry.*;
 17  
 import org.apache.tapestry.engine.DirectServiceParameter;
 18  
 import org.apache.tapestry.engine.IEngineService;
 19  
 import org.apache.tapestry.engine.ILink;
 20  
 import org.apache.tapestry.form.ValidatableField;
 21  
 import org.apache.tapestry.form.ValidatableFieldSupport;
 22  
 import org.apache.tapestry.json.IJSONWriter;
 23  
 import org.apache.tapestry.json.JSONObject;
 24  
 import org.apache.tapestry.services.DataSqueezer;
 25  
 import org.apache.tapestry.valid.ValidatorException;
 26  
 
 27  
 import java.util.ArrayList;
 28  
 import java.util.HashMap;
 29  
 import java.util.List;
 30  
 import java.util.Map;
 31  
 
 32  
 /**
 33  
  * An html field similar to a <code>select</code> input field that 
 34  
  * is wrapped by a dojo ComboBox widget.
 35  
  * 
 36  
  * This component uses the {@link IAutocompleteModel} to retrieve and match against
 37  
  * selected values.
 38  
  * 
 39  
  * @author jkuhnert
 40  
  */
 41  6
 public abstract class Autocompleter extends AbstractFormWidget implements ValidatableField, IJSONRender, IDirect
 42  
 {
 43  
     // mode, can be remote or local (local being from html rendered option elements)
 44  
     private static final String MODE_REMOTE = "remote";
 45  
     private static final String MODE_LOCAL = "local";    
 46  
     
 47  
     /**
 48  
      * 
 49  
      * {@inheritDoc}
 50  
      */
 51  
     protected void renderFormWidget(IMarkupWriter writer, IRequestCycle cycle)
 52  
     {
 53  2
         IAutocompleteModel model = getModel();
 54  2
         if (model == null)
 55  0
             throw Tapestry.createRequiredParameterException(this, "model");
 56  
         
 57  2
         Object value = getValue();
 58  2
         Object key = value != null && !"".equals(value.toString()) ? model.getPrimaryKey(value) : null;
 59  
         
 60  2
         renderDelegatePrefix(writer, cycle);
 61  
         
 62  2
         writer.begin("select");
 63  2
         writer.attribute("name", getName());
 64  2
         writer.attribute("autocomplete", "off"); // turn off native html autocomplete
 65  
         
 66  2
         if (isDisabled())
 67  0
             writer.attribute("disabled", "disabled");
 68  
         
 69  2
         renderIdAttribute(writer, cycle);
 70  
         
 71  2
         renderDelegateAttributes(writer, cycle);
 72  
         
 73  2
         getValidatableFieldSupport().renderContributions(this, writer, cycle);
 74  
         
 75  
         // Apply informal attributes.
 76  2
         renderInformalParameters(writer, cycle);
 77  
         
 78  2
         writer.print(" ");
 79  
         
 80  2
         if (isLocal()) 
 81  
         {
 82  1
             List list = model.getValues("");
 83  4
             for (int i=0; i<list.size(); i++) 
 84  
             {
 85  3
                 Object optionKey = model.getPrimaryKey(list.get(i));
 86  
 
 87  3
                 writer.begin("option");
 88  3
                 writer.attribute("value", getDataSqueezer().squeeze(optionKey));
 89  
 
 90  3
                 if (optionKey!=null && optionKey.equals(key))
 91  1
                     writer.attribute("selected", "selected");
 92  
                 
 93  3
                 writer.print(model.getLabelFor(list.get(i)));
 94  3
                 writer.end();
 95  
             }
 96  
         }
 97  
         
 98  2
         writer.end();
 99  2
         renderDelegateSuffix(writer, cycle);
 100  
         
 101  2
         Map parms = new HashMap();
 102  2
         parms.put("id", getClientId());
 103  
         
 104  2
         JSONObject json = new JSONObject();
 105  2
         if (!isLocal())
 106  
         {
 107  1
             ILink link = getDirectService().getLink(true, new DirectServiceParameter(this));
 108  1
             json.put("dataUrl", link.getURL() + "&filter=%{searchString}");
 109  
         }
 110  
         
 111  2
         json.put("mode", isLocal() ? MODE_LOCAL : MODE_REMOTE);
 112  2
         json.put("widgetId", getName());
 113  2
         json.put("name", getName());
 114  2
         json.put("searchDelay", getSearchDelay());
 115  2
         json.put("fadeTime", getFadeTime());
 116  2
         json.put("maxListLength", getMaxListLength());
 117  2
         json.put("forceValidOption", isForceValidOption());
 118  2
         json.put("disabled", isDisabled());
 119  
         
 120  2
         json.put("value", key != null ? getDataSqueezer().squeeze(key) : "");
 121  2
         json.put("label", value != null ? model.getLabelFor(value) : "");
 122  
         
 123  2
         parms.put("props", json.toString());
 124  2
         parms.put("form", getForm().getName());
 125  2
         parms.put("widget", this);
 126  
         
 127  2
         PageRenderSupport prs = TapestryUtils.getPageRenderSupport(cycle, this);
 128  2
         getScript().execute(this, cycle, prs, parms);
 129  2
     }
 130  
     
 131  
     /**
 132  
      * {@inheritDoc}
 133  
      */
 134  
     public void renderComponent(IJSONWriter writer, IRequestCycle cycle)
 135  
     {
 136  1
         IAutocompleteModel model = getModel();
 137  
         
 138  1
         if (model == null)
 139  0
             throw Tapestry.createRequiredParameterException(this, "model");
 140  
         
 141  1
         List filteredValues = model.getValues(getFilter());
 142  
         
 143  1
         if (filteredValues == null)
 144  0
             return;
 145  
         
 146  1
         Object key = null;
 147  1
         String label = null;
 148  
         
 149  1
         JSONObject json = writer.object();
 150  
         
 151  4
         for (int i=0; i < filteredValues.size(); i++) {
 152  3
             Object value = filteredValues.get(i);
 153  
             
 154  3
             key = model.getPrimaryKey(value);
 155  3
             label = model.getLabelFor(value);
 156  
             
 157  3
             json.put(getDataSqueezer().squeeze(key), label );
 158  
         }
 159  
         
 160  1
     }
 161  
     
 162  
     /**
 163  
      * @see org.apache.tapestry.form.AbstractFormComponent#rewindFormComponent(org.apache.tapestry.IMarkupWriter, org.apache.tapestry.IRequestCycle)
 164  
      */
 165  
     protected void rewindFormWidget(IMarkupWriter writer, IRequestCycle cycle)
 166  
     {
 167  1
         String value = cycle.getParameter(getName());
 168  
         
 169  1
         Object object = null;
 170  
         
 171  
         try
 172  
         {
 173  1
             if (value != null && value.length() > 0)
 174  1
                 object = getModel().getValue(getDataSqueezer().unsqueeze(value));
 175  
             
 176  1
             getValidatableFieldSupport().validate(this, writer, cycle, object);
 177  
             
 178  1
             setValue(object);
 179  
         }
 180  0
         catch (ValidatorException e)
 181  
         {
 182  0
             getForm().getDelegate().record(e);
 183  1
         }
 184  1
     }
 185  
     
 186  
     /** 
 187  
      * {@inheritDoc}
 188  
      */
 189  
     public boolean isStateful()
 190  
     {
 191  0
         return true;
 192  
     }
 193  
     
 194  
     /**
 195  
      * Triggerd by using filterOnChange logic.
 196  
      * 
 197  
      * {@inheritDoc}
 198  
      */
 199  
     public void trigger(IRequestCycle cycle)
 200  
     {
 201  0
         setFilter(cycle.getParameter("filter"));
 202  0
     }
 203  
     
 204  
     public abstract IAutocompleteModel getModel();
 205  
     
 206  
     /** How long to wait(in ms) before searching after input is received. */
 207  
     public abstract int getSearchDelay();
 208  
     
 209  
     /** The duration(in ms) of the fade effect of list going away. */
 210  
     public abstract int getFadeTime();
 211  
     
 212  
     /** The maximum number of items displayed in select list before the scrollbar is activated. */
 213  
     public abstract int getMaxListLength();
 214  
     
 215  
     /** Forces select to only allow valid option strings. */
 216  
     public abstract boolean isForceValidOption();
 217  
     
 218  
     /** Forces select to work in local mode (no xhr). */
 219  
     public abstract boolean isLocal();    
 220  
     
 221  
     /** @since 2.2 * */
 222  
     public abstract Object getValue();
 223  
 
 224  
     /** @since 2.2 * */
 225  
     public abstract void setValue(Object value);
 226  
     
 227  
     /** @since 4.1 */
 228  
     public abstract void setFilter(String value);
 229  
     
 230  
     /** @since 4.1 */
 231  
     public abstract String getFilter();
 232  
     
 233  
     /** Injected. */
 234  
     public abstract DataSqueezer getDataSqueezer();
 235  
     
 236  
     /**
 237  
      * Injected.
 238  
      */
 239  
     public abstract ValidatableFieldSupport getValidatableFieldSupport();
 240  
 
 241  
     /**
 242  
      * Injected.
 243  
      */
 244  
     public abstract IEngineService getDirectService();
 245  
     
 246  
     /**
 247  
      * Injected.
 248  
      */
 249  
     public abstract IScript getScript();
 250  
     
 251  
     /**
 252  
      * @see org.apache.tapestry.form.AbstractFormComponent#isRequired()
 253  
      */
 254  
     public boolean isRequired()
 255  
     {
 256  1
         return getValidatableFieldSupport().isRequired(this);
 257  
     }
 258  
 
 259  
     /** 
 260  
      * {@inheritDoc}
 261  
      */
 262  
     public List getUpdateComponents()
 263  
     {
 264  3
         List comps = new ArrayList();
 265  3
         comps.add(getClientId());
 266  
         
 267  3
         return comps;
 268  
     }
 269  
     
 270  
     /** 
 271  
      * {@inheritDoc}
 272  
      */
 273  
     public boolean isAsync()
 274  
     {
 275  3
         return true;
 276  
     }
 277  
     
 278  
     /** 
 279  
      * {@inheritDoc}
 280  
      */
 281  
     public boolean isJson()
 282  
     {
 283  3
         return true;
 284  
     }
 285  
 }