001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.extensions.ajax.markup.html.autocomplete;
018
019import org.apache.wicket.util.io.IClusterable;
020
021/**
022 * This class encapsulates various settings for {@link AbstractAutoCompleteBehavior}. See the
023 * documentation for the property accessors of this class for further information.
024 * <p>
025 * Default settings:
026 * <table>
027 * <caption>Default settings</caption>
028 * <tr>
029 * <th>setting</th>
030 * <th>default value</th>
031 * </tr>
032 * <tr>
033 * <td>preselect</td>
034 * <td>false</td>
035 * </tr>
036 * <tr>
037 * <td>maxHeightInPx</td>
038 * <td>-1</td>
039 * </tr>
040 * <tr>
041 * <td>showListOnEmptyInput</td>
042 * <td>false</td>
043 * </tr>
044 * </table>
045 * </p>
046 * 
047 * @author Gerolf Seitz
048 */
049public final class AutoCompleteSettings implements IClusterable
050{
051        private static final long serialVersionUID = 1L;
052
053        private boolean preselect = false;
054
055        private int maxHeightInPx = -1;
056
057        private boolean showListOnEmptyInput = false;
058
059        private boolean useSmartPositioning = false;
060
061        private boolean ignoreBordersWhenPositioning = true;
062
063        private String cssClassName = null;
064
065        private boolean adjustInputWidth = true;
066
067        private boolean showListOnFocusGain = false;
068
069        private boolean showCompleteListOnFocusGain = false;
070
071        private int throttleDelay = 300;
072
073        private String parameterName = "q";
074
075        private int minInputLength = 1;
076
077        private KeyTabBehavior keyTabBehavior = KeyTabBehavior.SELECT_FOCUS_NEXT_ELEMENT;
078
079        /**
080         * Indicates whether the first item in the list is automatically selected when the autocomplete
081         * list is shown.
082         * 
083         * @return true if the first item of the autocomplete list should be preselected, false
084         *         (default) otherwise
085         */
086        public boolean getPreselect()
087        {
088                return preselect;
089        }
090
091        /**
092         * Sets whether the first item in the autocomplete list should be selected when the autocomplete
093         * list is shown.
094         * 
095         * @param preselect
096         *            the flag
097         * @return this {@link AutoCompleteSettings}
098         */
099        public AutoCompleteSettings setPreselect(final boolean preselect)
100        {
101                this.preselect = preselect;
102                return this;
103        }
104
105        /**
106         * set the throttle delay how long the browser will wait before sending a request to the browser
107         * after the user released a key.
108         * 
109         * @param throttleDelay
110         *            The delay in milliseconds.
111         * @return this {@link AutoCompleteSettings}
112         */
113        public AutoCompleteSettings setThrottleDelay(final int throttleDelay)
114        {
115                this.throttleDelay = throttleDelay;
116                return this;
117        }
118
119        /**
120         * get the throttle delay how long the browser will wait before sending a request to the browser
121         * after the user released a key.
122         * 
123         * @return the throttle delay in milliseconds (default 300)
124         */
125        public int getThrottleDelay()
126        {
127                return throttleDelay;
128        }
129
130        /**
131         * Gets the maximum height of the autocomplete list in pixels. <code>-1</code> indicates that
132         * the autocomplete list should have no maximum height.
133         * 
134         * @return the maximum height in pixels
135         */
136        public int getMaxHeightInPx()
137        {
138                return maxHeightInPx;
139        }
140
141        /**
142         * Sets the maximum height in pixels of the autocomplete list.
143         * <p>
144         * The maximum height can also be specified via css (and by setting maxHeightInPx to -1):
145         * 
146         * <pre>
147         * div.wicket-aa-container { maxHeight: 100px; }
148         * </pre>
149         * 
150         * Note that this does not work in IE6.
151         * </p>
152         * 
153         * @param maxHeightInPx
154         *            the maximum height in pixels
155         * @return this {@link AutoCompleteSettings}
156         */
157        public AutoCompleteSettings setMaxHeightInPx(final int maxHeightInPx)
158        {
159                this.maxHeightInPx = maxHeightInPx;
160                return this;
161        }
162
163        /**
164         * Indicates whether the popup positioning will take into account the borders of the input
165         * element and its ancestors.
166         * 
167         * @return true if borders are ignored, false otherwise.
168         */
169        public boolean getIgnoreBordersWhenPositioning()
170        {
171                return ignoreBordersWhenPositioning;
172        }
173
174        /**
175         * Sets whether the popup positioning will take into account the borders of the input element
176         * and its ancestors (by including the <code>clientLeft</code> and <code>clientTop</code> DOM
177         * properties in the computation).
178         * 
179         * @param ignoreBordersWhenPositioning
180         *            the flag
181         * @return this {@link AutoCompleteSettings}.
182         */
183        public AutoCompleteSettings setIgnoreBordersWhenPositioning(
184                final boolean ignoreBordersWhenPositioning)
185        {
186                this.ignoreBordersWhenPositioning = ignoreBordersWhenPositioning;
187                return this;
188        }
189
190        /**
191         * Indicates whether the popup positioning will take into account browser window visible area or
192         * not. (so always show popup bottom-right or not)
193         * 
194         * @return true if popup smart positioning is used, false otherwise.
195         */
196        public boolean getUseSmartPositioning()
197        {
198                return useSmartPositioning;
199        }
200
201        /**
202         * Indicates whether the autocomplete list will be shown if the input is empty.
203         * 
204         * @return true if the autocomlete list will be shown if the input string is empty, false
205         *         otherwise
206         */
207        public boolean getShowListOnEmptyInput()
208        {
209                return showListOnEmptyInput;
210        }
211
212        /**
213         * Sets whether the list should be shown when the input is empty.
214         * 
215         * @param showListOnEmptyInput
216         *            the flag
217         * @return this {@link AutoCompleteSettings}
218         */
219        public AutoCompleteSettings setShowListOnEmptyInput(final boolean showListOnEmptyInput)
220        {
221                this.showListOnEmptyInput = showListOnEmptyInput;
222                return this;
223        }
224
225        /**
226         * Get CSS class name to add to the autocompleter markup container
227         * 
228         * @return CSS class name, or <code>null</code> if not used
229         */
230        public String getCssClassName()
231        {
232                return cssClassName;
233        }
234
235        /**
236         * Sets an CSS class name to add to the autocompleter markup container
237         * <p/>
238         * This makes it easier to have multiple autocompleters in your application with different style
239         * and layout.
240         * 
241         * @param cssClassName
242         *            valid CSS class name
243         * @return this {@link AutoCompleteSettings}.
244         */
245        public AutoCompleteSettings setCssClassName(final String cssClassName)
246        {
247                this.cssClassName = cssClassName;
248                return this;
249        }
250
251        /**
252         * Tells if wicket should adjust the width of the autocompleter selection window to the width of
253         * the related input field.
254         * 
255         * @return <code>true</code> if the autocompleter should have the same size as the input field,
256         *         <code>false</code> for default browser behavior
257         */
258        public boolean isAdjustInputWidth()
259        {
260                return adjustInputWidth;
261        }
262
263        /**
264         * Adjust the width of the autocompleter selection window to the width of the related input
265         * field.
266         * <p/>
267         * Otherwise the size will depend on the default browser behavior and CSS.
268         * 
269         * @param adjustInputWidth
270         *            <code>true</code> if the autocompleter should have the same size as the input
271         *            field, <code>false</code> for default browser behavior
272         * @return this {@link AutoCompleteSettings}.
273         */
274        public AutoCompleteSettings setAdjustInputWidth(final boolean adjustInputWidth)
275        {
276                this.adjustInputWidth = adjustInputWidth;
277                return this;
278        }
279
280        /**
281         * Indicates whether the autocomplete list will be shown when the input field receives focus.
282         * 
283         * @return true if the autocomplete list will be shown when the input field receives focus,
284         *         false otherwise
285         */
286        public boolean getShowListOnFocusGain()
287        {
288                return showListOnFocusGain;
289        }
290
291        /**
292         * Sets whether the list should be shown when the input field receives focus.
293         * 
294         * @param showCompleteListOnFocusGain
295         *            the flag
296         * @return this {@link AutoCompleteSettings}.
297         */
298        public AutoCompleteSettings setShowCompleteListOnFocusGain(
299                final boolean showCompleteListOnFocusGain)
300        {
301                this.showCompleteListOnFocusGain = showCompleteListOnFocusGain;
302                return this;
303        }
304
305        /**
306         * Indicates whether the autocomplete list will be shown when the input field receives focus.
307         * 
308         * @return true if the autocomplete list will be shown when the input field receives focus,
309         *         false otherwise
310         */
311        public boolean getShowCompleteListOnFocusGain()
312        {
313                return showCompleteListOnFocusGain;
314        }
315
316        /**
317         * Sets whether the list should be shown when the input field receives focus.
318         * 
319         * @param showListOnFocusGain
320         *            the flag
321         * @return this {@link AutoCompleteSettings}.
322         */
323        public AutoCompleteSettings setShowListOnFocusGain(final boolean showListOnFocusGain)
324        {
325                this.showListOnFocusGain = showListOnFocusGain;
326                return this;
327        }
328
329        /**
330         * Sets whether the popup positioning will take into account browser window visible area or not.
331         * (so always show popup bottom-right or not)<br>
332         *
333         * @param useSmartPositioning
334         *            the flag
335         * @return this {@link AutoCompleteSettings}.
336         */
337        public AutoCompleteSettings setUseSmartPositioning(final boolean useSmartPositioning)
338        {
339                this.useSmartPositioning = useSmartPositioning;
340                return this;
341        }
342
343        /**
344         * Sets the name of the request parameter that will bring the value of the user input
345         * 
346         * @param parameterName
347         *            the name of the request parameter that will bring the value of the user input
348         * @return this {@link AutoCompleteSettings}
349         */
350        public AutoCompleteSettings setParameterName(final String parameterName)
351        {
352                this.parameterName = parameterName;
353                return this;
354        }
355
356        /**
357         * @return the name of the request parameter that will bring the value of the user input
358         */
359        public String getParameterName()
360        {
361                return parameterName;
362        }
363
364        /**
365         * @return the minimum input length required to display the autocomplete list
366         */
367        public int getMinInputLength()
368        {
369                return minInputLength;
370        }
371
372        /**
373         * Set the minimum input length required to display the autocomplete list
374         *
375         * @param minInputLength
376         *            the minimum input length required to display the autocomplete list
377         * @return this {@link AutoCompleteSettings}
378         */
379        public AutoCompleteSettings setMinInputLength(int minInputLength)
380        {
381                this.minInputLength = minInputLength;
382                return this;
383        }
384
385        /**
386         * Indicates how the Tab key should be handled when having an item in the autocomplete list
387         * selected, {@link KeyTabBehavior#SELECT_FOCUS_NEXT_ELEMENT} is the default behavior.
388         *
389         * @return the behavior that should be used when the Tab key is pressed
390         */
391        public KeyTabBehavior getKeyTabBehavior()
392        {
393                return keyTabBehavior;
394        }
395
396        /**
397         * Set how the Tab key should be handled when having an item in the autocomplete list selected.
398         *
399         * @param keyTabBehavior the behavior that should be used when the Tab key is pressed,
400         * {@link KeyTabBehavior#SELECT_FOCUS_NEXT_ELEMENT} is the default behavior
401         * @return this {@link AutoCompleteSettings}
402         */
403        public AutoCompleteSettings setKeyTabBehavior(KeyTabBehavior keyTabBehavior)
404        {
405                this.keyTabBehavior = keyTabBehavior;
406                return this;
407        }
408
409        /**
410         * A behavior that can be used to control how the Tab key should be handled when having an item
411         * in the autocomplete list is marked.
412         */
413        public enum KeyTabBehavior
414        {
415                /**
416                 * Select the currently marked item and move the focus to the next focusable element.
417                 */
418                SELECT_FOCUS_NEXT_ELEMENT("selectFocusNextElement"),
419                /**
420                 * Select the currently marked item and move the focus to the auto complete input field.
421                 */
422                SELECT_FOCUS_INPUT("selectFocusAutocompleteInput");
423
424                private final String value;
425
426                KeyTabBehavior(String value)
427                {
428                        this.value = value;
429                }
430
431                public String getValue()
432                {
433                        return value;
434                }
435        }
436}