Author: gseitz
Date: Fri May  9 16:44:20 2008
New Revision: 654981

URL: http://svn.apache.org/viewvc?rev=654981&view=rev
Log:
WICKET-1608: make AutoCompleteBehavior's configuration more flexible
WICKET-1595: provide a scrolling mechanism that's actually usable
WICKET-1562:  Autocomplete should display the selection list even if the input 
field is empty

Added:
    
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteSettings.java
   (with props)
Modified:
    
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AbstractAutoCompleteBehavior.java
    
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteBehavior.java
    
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteTextField.java
    
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/wicket-autocomplete.js

Modified: 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AbstractAutoCompleteBehavior.java
URL: 
http://svn.apache.org/viewvc/wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AbstractAutoCompleteBehavior.java?rev=654981&r1=654980&r2=654981&view=diff
==============================================================================
--- 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AbstractAutoCompleteBehavior.java
 (original)
+++ 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AbstractAutoCompleteBehavior.java
 Fri May  9 16:44:20 2008
@@ -16,6 +16,7 @@
  */
 package org.apache.wicket.extensions.ajax.markup.html.autocomplete;
 
+
 import org.apache.wicket.RequestCycle;
 import org.apache.wicket.ResourceReference;
 import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
@@ -37,21 +38,47 @@
 
        protected boolean preselect = false;
 
+       protected AutoCompleteSettings settings = new AutoCompleteSettings();
+
        /**
         * @see 
org.apache.wicket.ajax.AbstractDefaultAjaxBehavior#renderHead(org.apache.wicket.markup.html.IHeaderResponse)
         */
+
        public void renderHead(IHeaderResponse response)
        {
                super.renderHead(response);
                response.renderJavascriptReference(AUTOCOMPLETE_JS);
                final String id = getComponent().getMarkupId();
-               response.renderOnDomReadyJavascript("new Wicket.AutoComplete('" 
+ id + "','" +
-                       getCallbackUrl() + "'," + preselect + ");");
+               String initJS = constructInitJS();
+               response.renderOnDomReadyJavascript(initJS);
+       }
+
+       protected final String constructInitJS()
+       {
+               StringBuffer sb = new StringBuffer();
+               sb.append("new Wicket.AutoComplete('")
+                       .append(getComponent().getMarkupId())
+                       .append("','")
+                       .append(getCallbackUrl())
+                       .append("',")
+                       .append(constructSettingsJS())
+                       .append(");");
+               return sb.toString();
+       }
+
+       protected final String constructSettingsJS()
+       {
+               StringBuffer sb = new StringBuffer();
+               
sb.append("{preselect:").append(settings.getPreselect()).append(",maxHeight:").append(
+                       
settings.getMaxHeightInPx()).append(",showListOnEmptyInput:").append(
+                       settings.getShowListOnEmptyInput()).append("}");
+               return sb.toString();
        }
 
        /**
         * @see org.apache.wicket.ajax.AbstractDefaultAjaxBehavior#onBind()
         */
+
        protected void onBind()
        {
                // add empty AbstractDefaultAjaxBehavior to the component, to 
force
@@ -61,6 +88,7 @@
                {
                        private static final long serialVersionUID = 1L;
 
+
                        protected void respond(AjaxRequestTarget target)
                        {
                        }
@@ -81,6 +109,7 @@
        /**
         * @see 
org.apache.wicket.ajax.AbstractDefaultAjaxBehavior#respond(org.apache.wicket.ajax.AjaxRequestTarget)
         */
+
        protected void respond(AjaxRequestTarget target)
        {
                final RequestCycle requestCycle = RequestCycle.get();

Modified: 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteBehavior.java
URL: 
http://svn.apache.org/viewvc/wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteBehavior.java?rev=654981&r1=654980&r2=654981&view=diff
==============================================================================
--- 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteBehavior.java
 (original)
+++ 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteBehavior.java
 Fri May  9 16:44:20 2008
@@ -28,6 +28,8 @@
  * This behavior builds on top of [EMAIL PROTECTED] 
AbstractAutoCompleteBehavior} by introducing the concept of
  * a [EMAIL PROTECTED] IAutoCompleteRenderer} to make response writing easier.
  * 
+ * @param
+ * 
  * @see IAutoCompleteRenderer
  * 
  * @since 1.2
@@ -63,23 +65,37 @@
         */
        public AutoCompleteBehavior(IAutoCompleteRenderer renderer, boolean 
preselect)
        {
+               this(renderer, new 
AutoCompleteSettings().setPreselect(preselect));
+       }
+
+       /**
+        * Constructor
+        * 
+        * @param renderer
+        *            renderer that will be used to generate output
+        * @param settings
+        *            settings for the autocomplete list
+        */
+       public AutoCompleteBehavior(IAutoCompleteRenderer renderer, 
AutoCompleteSettings settings)
+       {
                if (renderer == null)
                {
                        throw new IllegalArgumentException("renderer cannot be 
null");
                }
+               if (settings == null)
+               {
+                       settings = new AutoCompleteSettings();
+               }
                this.renderer = renderer;
-               this.preselect = preselect;
+               this.settings = settings;
        }
 
-
        protected final void onRequest(final String val, RequestCycle 
requestCycle)
        {
                IRequestTarget target = new IRequestTarget()
                {
-
                        public void respond(RequestCycle requestCycle)
                        {
-
                                WebResponse r = 
(WebResponse)requestCycle.getResponse();
 
                                // Determine encoding

Added: 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteSettings.java
URL: 
http://svn.apache.org/viewvc/wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteSettings.java?rev=654981&view=auto
==============================================================================
--- 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteSettings.java
 (added)
+++ 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteSettings.java
 Fri May  9 16:44:20 2008
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.extensions.ajax.markup.html.autocomplete;
+
+import org.apache.wicket.IClusterable;
+
+/**
+ * This class encapsulates various settings for [EMAIL PROTECTED] 
AbstractAutoCompleteBehavior}. See the
+ * documentation for the property accessors of this class for further 
information.
+ * <p>
+ * Default settings: <table>
+ * <tr>
+ * <th>setting</th>
+ * <th>default value</th>
+ * </tr>
+ * <tr>
+ * <td>preselect</td>
+ * <td>false</td>
+ * </tr>
+ * <tr>
+ * <td>maxHeightInPx</td>
+ * <td>-1</td>
+ * </tr>
+ * <tr>
+ * <td>showListOnEmptyInput</td>
+ * <td>false</td>
+ * </tr>
+ * </table>
+ * </p>
+ * 
+ * @author Gerolf Seitz
+ */
+public final class AutoCompleteSettings implements IClusterable
+{
+       private static final long serialVersionUID = 1L;
+
+       private boolean preselect = false;
+
+       private int maxHeightInPx = -1;
+
+       private boolean showListOnEmptyInput = false;
+
+       /**
+        * Indicates whether the first item in the list is automatically 
selected when the autocomplete
+        * list is shown.
+        * 
+        * @return true if the first item of the autocomplete list should be 
preselected, false
+        *         (default) otherwise
+        */
+       public boolean getPreselect()
+       {
+               return preselect;
+       }
+
+       /**
+        * Sets whether the first item in the autocomplete list should be 
selected when the autocomplete
+        * list is shown.
+        * 
+        * @param preselect
+        *            the flag
+        * @return this [EMAIL PROTECTED] AutoCompleteSettings}
+        */
+       public AutoCompleteSettings setPreselect(boolean preselect)
+       {
+               this.preselect = preselect;
+               return this;
+       }
+
+       /**
+        * Gets the maximum height of the autocomplete list in pixels. 
<code>-1</code> indicates that
+        * the autocomplete list should have no maximum height.
+        * 
+        * @return the maximum height in pixels
+        */
+       public int getMaxHeightInPx()
+       {
+               return maxHeightInPx;
+       }
+
+       /**
+        * Sets the maximum height in pixels of the autocomplete list.
+        * <p>
+        * The maximum height can also be specified via css (and by setting 
maxHeightInPx to -1):
+        * 
+        * <pre>
+        * div.wicket-aa-container { maxHeight: 100px; }
+        * </pre>
+        * 
+        * Note that this does not work in IE6.
+        * </p>
+        * 
+        * @param maxHeightInPx
+        *            the maximum height in pixels
+        * @return this [EMAIL PROTECTED] AutoCompleteSettings}
+        */
+       public AutoCompleteSettings setMaxHeightInPx(int maxHeightInPx)
+       {
+               this.maxHeightInPx = maxHeightInPx;
+               return this;
+       }
+
+       /**
+        * Indicates whether the autocomplete list will be shown if the input 
is empty.
+        * 
+        * @return true if the autocomlete list will be shown if the input 
string is empty, false
+        *         otherwise
+        */
+       public boolean getShowListOnEmptyInput()
+       {
+               return showListOnEmptyInput;
+       }
+
+       /**
+        * Sets whether the list should be shown when the input is empty.
+        * 
+        * @param showListOnEmptyInput
+        *            the flag
+        * @return this [EMAIL PROTECTED] AutoCompleteSettings}
+        */
+       public AutoCompleteSettings setShowListOnEmptyInput(boolean 
showListOnEmptyInput)
+       {
+               this.showListOnEmptyInput = showListOnEmptyInput;
+               return this;
+       }
+}
\ No newline at end of file

Propchange: 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteSettings.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteTextField.java
URL: 
http://svn.apache.org/viewvc/wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteTextField.java?rev=654981&r1=654980&r2=654981&view=diff
==============================================================================
--- 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteTextField.java
 (original)
+++ 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AutoCompleteTextField.java
 Fri May  9 16:44:20 2008
@@ -32,6 +32,9 @@
  * @since 1.2
  * 
  * @author Igor Vaynberg (ivaynberg)
+ * 
+ * @param The
+ *            model object type
  */
 public abstract class AutoCompleteTextField extends TextField
 {
@@ -57,8 +60,20 @@
        public AutoCompleteTextField(String id, IModel model, Class type, 
boolean preselect)
        {
                this(id, model, type, StringAutoCompleteRenderer.INSTANCE, 
preselect);
+       }
 
-       } 
+       /**
+        * Construct.
+        * 
+        * @param id
+        * @param model
+        * @param type
+        * @param settings
+        */
+       public AutoCompleteTextField(String id, IModel model, Class type, 
AutoCompleteSettings settings)
+       {
+               this(id, model, type, StringAutoCompleteRenderer.INSTANCE, 
settings);
+       }
 
        /**
         * @param id
@@ -70,6 +85,18 @@
                this(id, object, (Class)null, preselect);
        }
 
+       /**
+        * Construct.
+        * 
+        * @param id
+        * @param object
+        * @param settings
+        */
+       public AutoCompleteTextField(String id, IModel object, 
AutoCompleteSettings settings)
+       {
+               this(id, object, (Class)null, settings);
+       }
+
 
        /**
         * @param id
@@ -87,6 +114,17 @@
        public AutoCompleteTextField(String id, boolean preselect)
        {
                this(id, (IModel)null, preselect);
+       }
+
+       /**
+        * Construct.
+        * 
+        * @param id
+        * @param settings
+        */
+       public AutoCompleteTextField(String id, AutoCompleteSettings settings)
+       {
+               this(id, (IModel)null, settings);
 
        }
 
@@ -138,12 +176,26 @@
        public AutoCompleteTextField(String id, IModel model, Class type,
                IAutoCompleteRenderer renderer, boolean preselect)
        {
-               super(id, model, type);
+               this(id, model, type, renderer, new 
AutoCompleteSettings().setPreselect(preselect));
+       }
 
+       /**
+        * Construct.
+        * 
+        * @param id
+        * @param model
+        * @param type
+        * @param renderer
+        * @param settings
+        */
+       public AutoCompleteTextField(String id, IModel model, Class type,
+               IAutoCompleteRenderer renderer, AutoCompleteSettings settings)
+       {
+               super(id, model, type);
                // this disables Firefox autocomplete
                add(new SimpleAttributeModifier("autocomplete", "off"));
 
-               add(new AutoCompleteBehavior(renderer, preselect)
+               add(new AutoCompleteBehavior(renderer, settings)
                {
 
                        private static final long serialVersionUID = 1L;
@@ -154,7 +206,6 @@
                        }
 
                });
-
        }
 
        /**
@@ -170,5 +221,10 @@
         */
        protected abstract Iterator getChoices(String input);
 
+       protected int getMaxHeightInPx()
+       {
+               return 50;
+       }
+
 
 }

Modified: 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/wicket-autocomplete.js
URL: 
http://svn.apache.org/viewvc/wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/wicket-autocomplete.js?rev=654981&r1=654980&r2=654981&view=diff
==============================================================================
--- 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/wicket-autocomplete.js
 (original)
+++ 
wicket/branches/wicket-1.3.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/wicket-autocomplete.js
 Fri May  9 16:44:20 2008
@@ -27,7 +27,7 @@
        enterHidesWithNoSelection : false
 };
 
-Wicket.AutoComplete=function(elementId, callbackUrl, preselect){
+Wicket.AutoComplete=function(elementId, callbackUrl, cfg){
     var KEY_TAB=9;
     var KEY_ENTER=13;
     var KEY_ESC=27;
@@ -87,7 +87,7 @@
                        } else {
                            render();
                        }
-                   if(navigator.appVersion.indexOf('AppleWebKit')>0)return 
killEvent(event);
+                   if(Wicket.Browser.isSafari())return killEvent(event);
                        break;
                 case KEY_DOWN:
                                if(selected<elementCount-1){
@@ -99,7 +99,7 @@
                            render();
                        showAutoComplete();
                        }
-                   if(navigator.appVersion.indexOf('AppleWebKit')>0)return 
killEvent(event);
+                   if(Wicket.Browser.isSafari())return killEvent(event);
                        break;
                 case KEY_ESC:
                    hideAutoComplete();
@@ -166,24 +166,38 @@
     function getAutocompleteMenu() {
         var choiceDiv=document.getElementById(getMenuId());
         if (choiceDiv==null) {
+               var container = document.createElement("div");
+               container.className="wicket-aa-container";
+               document.body.appendChild(container);
+               container.style.display="none";
+               container.style.overflow="auto";
+            container.style.position="absolute";            
+            container.id=getMenuId()+"-container";
+               
+            container.show = function() { wicketShow(this.id) };
+            container.hide = function() { wicketHide(this.id) };
+            
             choiceDiv=document.createElement("div");
-            document.body.appendChild(choiceDiv);
+            container.appendChild(choiceDiv);
             choiceDiv.id=getMenuId();
             choiceDiv.className="wicket-aa";
-            choiceDiv.style.display="none";
-            choiceDiv.style.position="absolute";
+            
             
             // WICKET-1350/WICKET-1351
-            choiceDiv.onmouseout=function() {mouseactive=0;};
-            choiceDiv.onmouseover=function() {mouseactive=1;};
+            container.onmouseout=function() {mouseactive=0;};
+            container.onmousemove=function() {mouseactive=1;};
         }
 
-        choiceDiv.show = function() { wicketShow(this.id) }
-        choiceDiv.hide = function() { wicketHide(this.id) }
 
         return choiceDiv;
     }
     
+    function getAutocompleteContainer() {
+       var node=getAutocompleteMenu().parentNode;
+       
+        return node;
+    }
+    
     function killEvent(event){
         if(!event)event=window.event;
         if(!event)return false;
@@ -203,7 +217,7 @@
     }
 
     function updateChoices(){
-        if(preselect==true){
+        if(cfg.preselect==true){
                selected = 0;
         }
         else{
@@ -220,14 +234,14 @@
 
     function showAutoComplete(){
         var position=getPosition(wicketGet(elementId));
-        var menu = getAutocompleteMenu();
+        var container = getAutocompleteContainer();
         var input=wicketGet(elementId);
-        var index=getOffsetParentZIndex(elementId);        
-        menu.show();
-        menu.style.zIndex=(Number(index)!=Number.NaN?Number(index)+1:index);
-        menu.style.left=position[0]+'px'
-        menu.style.top=(input.offsetHeight+position[1])+'px';
-        menu.style.width=input.offsetWidth+'px';
+        var index=getOffsetParentZIndex(elementId);
+        container.show();
+        
container.style.zIndex=(Number(index)!=Number.NaN?Number(index)+1:index);
+        container.style.left=position[0]+'px'
+        container.style.top=(input.offsetHeight+position[1])+'px';
+        container.style.width=input.offsetWidth+'px';
         visible=1;
         hideShowCovered();
     }
@@ -235,9 +249,9 @@
     function hideAutoComplete(){
         visible=0;
         selected=-1;
-        if ( document.getElementById(getMenuId()) )
+        if ( getAutocompleteContainer() )
         {
-               getAutocompleteMenu().hide();
+               getAutocompleteContainer().hide();
            hideShowCovered();
         }
     }
@@ -257,7 +271,7 @@
     
        // check if the input hasn't been cleared in the meanwhile
        var input=wicketGet(elementId);
-               if (input.value==null || input.value=="") {
+               if (!cfg.showListOnEmptyInput && (input.value==null || 
input.value=="")) {
                        hideAutoComplete();
                        return;
                }
@@ -303,7 +317,7 @@
     function scheduleEmptyCheck() {
        window.setTimeout(function() {
                var input=wicketGet(elementId);
-               if (input.value==null || input.value=="") {
+               if (!cfg.showListOnEmptyInput && (input.value==null || 
input.value=="")) {
                        hideAutoComplete();
                }
        }, 100);
@@ -332,11 +346,22 @@
     function stripHTML(str) {
         return str.replace(/<[^>]+>/g,"");
     }
+    
+    function adjustScrollOffset(menu, item) {          
+       if (item.offsetTop + item.offsetHeight > menu.scrollTop + 
menu.offsetHeight) {
+                       menu.scrollTop = item.offsetTop + item.offsetHeight - 
menu.offsetHeight;
+               } else
+               // adjust to the top
+               if (item.offsetTop < menu.scrollTop) {
+                       menu.scrollTop = item.offsetTop;
+               }       
+    }
 
     function render(){
-        var element= getAutocompleteMenu();
+        var menu=getAutocompleteMenu();
+        var height=0;
         for(var i=0;i<elementCount;i++){
-            var node=element.firstChild.childNodes[i];
+            var node=menu.firstChild.childNodes[i];
 
             var classNames=node.className.split(" ");
             for (var j=0; j<classNames.length; j++) {
@@ -347,13 +372,18 @@
 
             if(selected==i){
                 classNames.push('selected');
-                node.scrollIntoView(true);
+                adjustScrollOffset(menu.parentNode, node);
             }
-
+            
             node.className=classNames.join(" ");
+            height+=node.offsetHeight;
+        }
+        if (cfg.maxHeight != -1) {
+               height = height<cfg.maxHeight?height:cfg.maxHeight;
+               menu.parentNode.style.height=height+"px";
         }
     }
-
+    
     // From 
http://www.robertnyman.com/2006/04/24/get-the-rendered-style-of-an-element/
     function getStyle(obj,cssRule) {
        var cssRuleAlt = cssRule.replace(/\-(\w)/g,function(strMatch,p1){return 
p1.toUpperCase();});
@@ -398,7 +428,7 @@
     }
     
     function hideShowCoveredTimeout(){
-               var el=getAutocompleteMenu();
+               var el=getAutocompleteContainer();
         var p=getPosition(el);
 
         var acLeftX=p[0];


Reply via email to