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 ? 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  3
                 writer.begin("option");
 87  3
                 writer.attribute("value", getDataSqueezer().squeeze(optionKey));
 88  3
                 if (optionKey!=null && optionKey.equals(key))
 89  1
                     writer.attribute("selected", "selected");
 90  3
                 writer.print(model.getLabelFor(list.get(i)));
 91  3
                 writer.end();
 92  
             }
 93  
         }
 94  
         
 95  2
         writer.end();
 96  2
         renderDelegateSuffix(writer, cycle);
 97  
         
 98  2
         Map parms = new HashMap();
 99  2
         parms.put("id", getClientId());
 100  
         
 101  2
         JSONObject json = new JSONObject();
 102  2
         if (!isLocal())
 103  
         {
 104  1
             ILink link = getDirectService().getLink(true, new DirectServiceParameter(this));
 105  1
             json.put("dataUrl", link.getURL() + "&filter=%{searchString}");
 106  
         }
 107  2
         json.put("mode", isLocal() ? MODE_LOCAL : MODE_REMOTE);
 108  2
         json.put("widgetId", getName());
 109  2
         json.put("name", getName());
 110  2
         json.put("searchDelay", getSearchDelay());
 111  2
         json.put("fadeTime", getFadeTime());
 112  2
         json.put("maxListLength", getMaxListLength());
 113  2
         json.put("forceValidOption", isForceValidOption());
 114  2
         json.put("disabled", isDisabled());
 115  
         
 116  2
         json.put("value", getDataSqueezer().squeeze(key));
 117  2
         json.put("label", value != null ? model.getLabelFor(value) : "");
 118  
         
 119  2
         parms.put("props", json.toString());
 120  2
         parms.put("form", getForm().getName());
 121  2
         parms.put("widget", this);
 122  
         
 123  2
         PageRenderSupport prs = TapestryUtils.getPageRenderSupport(cycle, this);
 124  2
         getScript().execute(this, cycle, prs, parms);
 125  2
     }
 126  
     
 127  
     /**
 128  
      * {@inheritDoc}
 129  
      */
 130  
     public void renderComponent(IJSONWriter writer, IRequestCycle cycle)
 131  
     {
 132  1
         IAutocompleteModel model = getModel();
 133  
         
 134  1
         if (model == null)
 135  0
             throw Tapestry.createRequiredParameterException(this, "model");
 136  
         
 137  1
         List filteredValues = model.getValues(getFilter());
 138  
         
 139  1
         if (filteredValues == null)
 140  0
             return;
 141  
         
 142  1
         Object key = null;
 143  1
         String label = null;
 144  
         
 145  1
         JSONObject json = writer.object();
 146  
         
 147  4
         for (int i=0; i < filteredValues.size(); i++) {
 148  3
             Object value = filteredValues.get(i);
 149  
             
 150  3
             key = model.getPrimaryKey(value);
 151  3
             label = model.getLabelFor(value);
 152  
             
 153  3
             json.put(getDataSqueezer().squeeze(key), label );
 154  
         }
 155  
         
 156  1
     }
 157  
     
 158  
     /**
 159  
      * @see org.apache.tapestry.form.AbstractFormComponent#rewindFormComponent(org.apache.tapestry.IMarkupWriter, org.apache.tapestry.IRequestCycle)
 160  
      */
 161  
     protected void rewindFormWidget(IMarkupWriter writer, IRequestCycle cycle)
 162  
     {
 163  1
         String value = cycle.getParameter(getName());
 164  
         
 165  1
         Object object = null;
 166  
         
 167  
         try
 168  
         {
 169  1
             if (value != null && value.length() > 0)
 170  1
                 object = getModel().getValue(getDataSqueezer().unsqueeze(value));
 171  
             
 172  1
             getValidatableFieldSupport().validate(this, writer, cycle, object);
 173  
             
 174  1
             setValue(object);
 175  
         }
 176  0
         catch (ValidatorException e)
 177  
         {
 178  0
             getForm().getDelegate().record(e);
 179  1
         }
 180  1
     }
 181  
     
 182  
     /** 
 183  
      * {@inheritDoc}
 184  
      */
 185  
     public boolean isStateful()
 186  
     {
 187  0
         return true;
 188  
     }
 189  
     
 190  
     /**
 191  
      * Triggerd by using filterOnChange logic.
 192  
      * 
 193  
      * {@inheritDoc}
 194  
      */
 195  
     public void trigger(IRequestCycle cycle)
 196  
     {
 197  0
         setFilter(cycle.getParameter("filter"));
 198  0
     }
 199  
     
 200  
     public abstract IAutocompleteModel getModel();
 201  
     
 202  
     /** How long to wait(in ms) before searching after input is received. */
 203  
     public abstract int getSearchDelay();
 204  
     
 205  
     /** The duration(in ms) of the fade effect of list going away. */
 206  
     public abstract int getFadeTime();
 207  
     
 208  
     /** The maximum number of items displayed in select list before the scrollbar is activated. */
 209  
     public abstract int getMaxListLength();
 210  
     
 211  
     /** Forces select to only allow valid option strings. */
 212  
     public abstract boolean isForceValidOption();
 213  
     
 214  
     /** Forces select to work in local mode (no xhr). */
 215  
     public abstract boolean isLocal();    
 216  
     
 217  
     /** @since 2.2 * */
 218  
     public abstract Object getValue();
 219  
 
 220  
     /** @since 2.2 * */
 221  
     public abstract void setValue(Object value);
 222  
     
 223  
     /** @since 4.1 */
 224  
     public abstract void setFilter(String value);
 225  
     
 226  
     /** @since 4.1 */
 227  
     public abstract String getFilter();
 228  
     
 229  
     /** Injected. */
 230  
     public abstract DataSqueezer getDataSqueezer();
 231  
     
 232  
     /**
 233  
      * Injected.
 234  
      */
 235  
     public abstract ValidatableFieldSupport getValidatableFieldSupport();
 236  
 
 237  
     /**
 238  
      * Injected.
 239  
      */
 240  
     public abstract IEngineService getDirectService();
 241  
     
 242  
     /**
 243  
      * Injected.
 244  
      */
 245  
     public abstract IScript getScript();
 246  
     
 247  
     /**
 248  
      * @see org.apache.tapestry.form.AbstractFormComponent#isRequired()
 249  
      */
 250  
     public boolean isRequired()
 251  
     {
 252  1
         return getValidatableFieldSupport().isRequired(this);
 253  
     }
 254  
 
 255  
     /** 
 256  
      * {@inheritDoc}
 257  
      */
 258  
     public List getUpdateComponents()
 259  
     {
 260  3
         List comps = new ArrayList();
 261  3
         comps.add(getClientId());
 262  
         
 263  3
         return comps;
 264  
     }
 265  
     
 266  
     /** 
 267  
      * {@inheritDoc}
 268  
      */
 269  
     public boolean isAsync()
 270  
     {
 271  3
         return true;
 272  
     }
 273  
     
 274  
     /** 
 275  
      * {@inheritDoc}
 276  
      */
 277  
     public boolean isJson()
 278  
     {
 279  3
         return true;
 280  
     }
 281  
 }