r1477 - in xwiki/trunk: . core/src/main/java/com/xpn/xwiki core/src/main/java/com/xpn/xwiki/api core/src/main/java/com/xpn/xwiki/doc core/src/main/java/com/xpn/xwiki/objects/classes core/src/main/java/com/xpn/xwiki/objects/meta core/src/main/java/com/xpn/xwiki/validation core/src/main/resources src/main/web/skins/default src/main/web/skins/default/ajax src/main/web/skins/xwiki10 src/main/web/yui src/main/web/yui/autocomplete src/test/java/com/xpn/xwiki/test src/test/resources

Ludovic Dubost ludovic at users.forge.objectweb.org
Mon Oct 30 05:11:24 CET 2006


Author: ludovic
Date: 2006-10-30 05:11:22 +0100 (Mon, 30 Oct 2006)
New Revision: 1477

Added:
   xwiki/trunk/core/src/main/java/com/xpn/xwiki/validation/XWikiValidationStatus.java
   xwiki/trunk/src/main/web/skins/default/ajax/wzToolTip.js
   xwiki/trunk/src/main/web/skins/default/info.gif
   xwiki/trunk/src/main/web/skins/xwiki10/info.gif
   xwiki/trunk/src/main/web/yui/autocomplete/
   xwiki/trunk/src/main/web/yui/autocomplete/README
   xwiki/trunk/src/main/web/yui/autocomplete/autocomplete-debug.js
   xwiki/trunk/src/main/web/yui/autocomplete/autocomplete-min.js
   xwiki/trunk/src/main/web/yui/autocomplete/autocomplete.js
Removed:
   xwiki/trunk/core/src/main/java/com/xpn/xwiki/validation/XWikiValidationException.java
Modified:
   xwiki/trunk/core/src/main/java/com/xpn/xwiki/XWiki.java
   xwiki/trunk/core/src/main/java/com/xpn/xwiki/XWikiContext.java
   xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/Context.java
   xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/Document.java
   xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/PropertyClass.java
   xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/XWiki.java
   xwiki/trunk/core/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java
   xwiki/trunk/core/src/main/java/com/xpn/xwiki/objects/classes/BaseClass.java
   xwiki/trunk/core/src/main/java/com/xpn/xwiki/objects/classes/PropertyClass.java
   xwiki/trunk/core/src/main/java/com/xpn/xwiki/objects/meta/PropertyMetaClass.java
   xwiki/trunk/core/src/main/resources/ApplicationResources.properties
   xwiki/trunk/core/src/main/resources/xwiki.hbm.xml
   xwiki/trunk/src/test/java/com/xpn/xwiki/test/ClassAdvancedTest.java
   xwiki/trunk/src/test/java/com/xpn/xwiki/test/XWikiDocumentTest.java
   xwiki/trunk/src/test/resources/xwiki.hbm.xml
   xwiki/trunk/xwiki.iml
   xwiki/trunk/xwiki.iws
   xwiki/trunk/xwikibase.iml
Log:
Finished server-side validation (client side still needed)
Added new fields toXML and fromXML
Added field tooltips
Added server side validation tests
Corrected captcha config column names xwiki.hbm.xml


Modified: xwiki/trunk/core/src/main/java/com/xpn/xwiki/XWiki.java
===================================================================
--- xwiki/trunk/core/src/main/java/com/xpn/xwiki/XWiki.java	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/core/src/main/java/com/xpn/xwiki/XWiki.java	2006-10-30 04:11:22 UTC (rev 1477)
@@ -74,8 +74,6 @@
 import com.xpn.xwiki.util.Util;
 import com.xpn.xwiki.web.*;
 import com.xpn.xwiki.web.includeservletasstring.IncludeServletAsString;
-import com.xpn.xwiki.validation.XWikiValidationInterface;
-import com.xpn.xwiki.validation.XWikiValidationException;
 import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.UsernamePasswordCredentials;
 import org.apache.commons.httpclient.methods.GetMethod;
@@ -4167,20 +4165,7 @@
     }
 
     public boolean validateDocument(XWikiDocument doc, XWikiContext context) throws XWikiException {
-        XWikiValidationException xwe;
-        String validationScript = "";
-        XWikiRequest req = context.getRequest();
-        if (req!=null) {
-            validationScript = req.get("xvalidation");
-        }
-        if ((validationScript==null)||(validationScript.trim().equals(""))) {
-            validationScript = doc.getValidationScript();
-        }
-        if ((validationScript==null)||(validationScript.trim().equals(""))) {
-           XWikiValidationInterface validObject = (XWikiValidationInterface) parseGroovyFromPage(validationScript, context);
-           return validObject.validateDocument(doc, context);   
-        }
-        return true;
+         return doc.validate(context);
     }
 
     public String getMessage(String item, XWikiContext context) {
@@ -4202,9 +4187,29 @@
             return null;
         return parseMessage(message, context);
     }
-        
-    public String getUniquePageName(String space, XWikiContext context) {
-        String pageName = generateRandomString(16);
-        return getUniquePageName(space, pageName, context);
+
+    public String addTooltip(String html, String message, String params, XWikiContext context) {
+      StringBuffer buffer = new StringBuffer();
+        buffer.append("<span onmouseover=\"");
+        buffer.append(params);
+        buffer.append("; return escape('");
+        buffer.append(message.replaceAll("'","\\'"));
+        buffer.append("');\">");
+        buffer.append(html);
+        buffer.append("</span>");
+        return buffer.toString();
     }
+
+    public String addTooltipJS(XWikiContext context) {
+        StringBuffer buffer = new StringBuffer();
+        buffer.append("<script type=\"text/javascript\" src=\"");
+        buffer.append(getSkinFile("ajax/wzToolTip.js", context));
+        buffer.append("\"></script>");
+        // buffer.append("<div id=\"dhtmltooltip\"></div>");
+        return buffer.toString();
+    }
+
+    public String addTooltip(String html, String message, XWikiContext context) {
+        return addTooltip(html, message, "this.WIDTH='300'", context);
+    }
 }

Modified: xwiki/trunk/core/src/main/java/com/xpn/xwiki/XWikiContext.java
===================================================================
--- xwiki/trunk/core/src/main/java/com/xpn/xwiki/XWikiContext.java	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/core/src/main/java/com/xpn/xwiki/XWikiContext.java	2006-10-30 04:11:22 UTC (rev 1477)
@@ -29,12 +29,11 @@
 import com.xpn.xwiki.user.api.XWikiUser;
 import com.xpn.xwiki.util.Util;
 import com.xpn.xwiki.web.*;
+import com.xpn.xwiki.validation.XWikiValidationStatus;
 import org.apache.xmlrpc.server.XmlRpcServer;
 
 import java.net.URL;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Map;
+import java.util.*;
 
 public class XWikiContext extends Hashtable {
 
@@ -70,6 +69,8 @@
    // Used to avoir reloading archives in the same request
    private Map archiveCache = new HashMap();
 
+   private List displayedFields = new ArrayList();
+
    public XWikiContext() {
    }
 
@@ -322,5 +323,21 @@
 
     public XWikiMessageTool getMessageTool() {
       return ((XWikiMessageTool) get("msg"));
-    }    
+    }
+
+    public XWikiValidationStatus getValidationStatus() {
+        return (XWikiValidationStatus) get("validation_status");
+    }
+
+    public void setValidationStatus(XWikiValidationStatus status) {
+        put("validation_status", status);
+    }
+
+    public void addDisplayedField(String fieldname) {
+        displayedFields.add(fieldname);
+    }
+
+    public List getDisplayedFields() {
+        return displayedFields;
+    }
 }

Modified: xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/Context.java
===================================================================
--- xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/Context.java	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/Context.java	2006-10-30 04:11:22 UTC (rev 1477)
@@ -24,12 +24,15 @@
 package com.xpn.xwiki.api;
 
 import com.xpn.xwiki.XWikiContext;
+import com.xpn.xwiki.validation.XWikiValidationStatus;
 import com.xpn.xwiki.doc.XWikiDocument;
 import com.xpn.xwiki.web.XWikiRequest;
 import com.xpn.xwiki.web.XWikiResponse;
 import com.xpn.xwiki.web.XWikiURLFactory;
 
+import java.util.List;
 
+
 public class Context extends Api {
 
     public Context(XWikiContext context) {
@@ -238,4 +241,13 @@
     public String getLinksQueryString() {
         return context.getLinksQueryString();
     }
+
+    public XWikiValidationStatus getValidationStatus() {
+        return context.getValidationStatus();
+    }
+
+    public List getDisplayedFields() {
+        return context.getDisplayedFields();
+    }
+
 }

Modified: xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/Document.java
===================================================================
--- xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/Document.java	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/Document.java	2006-10-30 04:11:22 UTC (rev 1477)
@@ -702,6 +702,39 @@
         currentObj = getObject(className, nb);
     }
 
+    public String getActiveClass() {
+        if (currentObj==null)
+         return null;
+        else
+         return currentObj.getName();
+    }
+
+    public String displayPrettyName(String fieldname) {
+        if (currentObj == null)
+            return doc.displayPrettyName(fieldname, context);
+        else
+            return doc.displayPrettyName(fieldname, currentObj.getBaseObject(), context);
+    }
+
+    public String displayPrettyName(String fieldname, Object obj) {
+        if (obj == null)
+            return "";
+        return doc.displayPrettyName(fieldname, obj.getBaseObject(), context);
+    }
+
+    public String displayTooltip(String fieldname) {
+        if (currentObj == null)
+            return doc.displayTooltip(fieldname, context);
+        else
+            return doc.displayTooltip(fieldname, currentObj.getBaseObject(), context);
+    }
+
+    public String displayTooltip(String fieldname, Object obj) {
+        if (obj == null)
+            return "";
+        return doc.displayTooltip(fieldname, obj.getBaseObject(), context);
+    }
+
     public String display(String fieldname) {
         if (currentObj == null)
             return doc.display(fieldname, context);
@@ -1260,4 +1293,7 @@
         return attachment;
     }
 
+    public boolean validate() throws XWikiException {
+        return doc.validate(context);
+    }
 }

Modified: xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/PropertyClass.java
===================================================================
--- xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/PropertyClass.java	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/PropertyClass.java	2006-10-30 04:11:22 UTC (rev 1477)
@@ -1,23 +1,23 @@
-/*
- * Copyright 2006, XpertNet SARL, and individual contributors as indicated
- * by the contributors.txt.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
- */
+/*
+ * Copyright 2006, XpertNet SARL, and individual contributors as indicated
+ * by the contributors.txt.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ */
 
 
 package com.xpn.xwiki.api;
@@ -45,4 +45,21 @@
         else
          return null;
     }
+
+    public String getPrettyName() {
+        return getBasePropertyClass().getPrettyName();
+    }
+
+    public String getValidationMessage() {
+        return getBasePropertyClass().getValidationMessage();
+    }
+
+    public String getValidationRegExp() {
+        return getBasePropertyClass().getValidationRegExp();
+    }
+
+    public String getTooltip() {
+        return getBasePropertyClass().getTooltip();
+    }
+
 }

Modified: xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/XWiki.java
===================================================================
--- xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/XWiki.java	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/core/src/main/java/com/xpn/xwiki/api/XWiki.java	2006-10-30 04:11:22 UTC (rev 1477)
@@ -39,6 +39,7 @@
 import com.xpn.xwiki.stats.api.XWikiStatsService;
 import com.xpn.xwiki.stats.impl.DocumentStats;
 import com.xpn.xwiki.web.Utils;
+import com.xpn.xwiki.web.XWikiMessageTool;
 import org.suigeneris.jrcs.diff.Chunk;
 
 import java.awt.image.BufferedImage;
@@ -2068,17 +2069,52 @@
         return new PropertyClass(xwiki.getPropertyClassFromName(propPath, context), context);
     }
 
+    /**
+     * Generates a unique page name based on initial page name and already existing pages
+     * @param space
+     * @param name
+     * @return a unique page name
+     */
     public String getUniquePageName(String space, String name){
-        return "";// xwiki.getUniquePageName(space, name, context);
+        return xwiki.getUniquePageName(space, name, context);
     }
 
+    /**
+     * Cleans up the page name to make it valid
+     * @param name
+     * @return A valid page name
+     */
     public String clearName(String name){
         return xwiki.clearName(name, context);
     }
 
+    /**
+     * Inserts a tooltip using toolTip.js
+     * @param html HTML viewed
+     * @param message HTML Tooltip message
+     * @param params Parameters in Javascropt added to the tooltip config
+     * @return HTML with working tooltip
+     */
+    public String addTooltip(String html, String message, String params) {
+        return xwiki.addTooltip(html, message, params, context);
+    }
 
-    public String getUniquePageName(String space){
-        return xwiki.getUniquePageName(space, context);
+    /**
+     * Inserts a tooltip using toolTip.js
+     * @param html HTML viewed
+     * @param message HTML Tooltip message
+     * @return HTML with working tooltip
+     */
+    public String addTooltip(String html, String message) {
+        return xwiki.addTooltip(html, message, context);
     }
+
+    /**
+     * Inserts the tooltip Javascript
+     * @return
+     */
+    public String addTooltipJS() {
+        return xwiki.addTooltipJS(context);
+    }
 }
 

Modified: xwiki/trunk/core/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java
===================================================================
--- xwiki/trunk/core/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/core/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java	2006-10-30 04:11:22 UTC (rev 1477)
@@ -30,6 +30,8 @@
 import com.xpn.xwiki.XWiki;
 import com.xpn.xwiki.XWikiContext;
 import com.xpn.xwiki.XWikiException;
+import com.xpn.xwiki.validation.XWikiValidationInterface;
+import com.xpn.xwiki.validation.XWikiValidationStatus;
 import com.xpn.xwiki.api.DocumentSection;
 import com.xpn.xwiki.notify.XWikiNotificationRule;
 import com.xpn.xwiki.objects.BaseCollection;
@@ -46,6 +48,7 @@
 import com.xpn.xwiki.web.EditForm;
 import com.xpn.xwiki.web.ObjectAddForm;
 import com.xpn.xwiki.web.XWikiMessageTool;
+import com.xpn.xwiki.web.XWikiRequest;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -943,6 +946,54 @@
         this.template = template;
     }
 
+    public String displayPrettyName(String fieldname, XWikiContext context) {
+        try {
+            BaseObject object = getxWikiObject();
+            if (object == null)
+                object = getFirstObject(fieldname, context);
+            return displayPrettyName(fieldname, object, context);
+        } catch (Exception e) {
+            return "";
+        }
+    }
+
+    public String displayPrettyName(String fieldname, BaseObject obj, XWikiContext context) {
+        try {
+            PropertyClass pclass = (PropertyClass) obj.getxWikiClass(context).get(fieldname);
+            return pclass.getPrettyName();
+        }
+        catch (Exception e) {
+            return "";
+            // return "||Exception showing field " + fieldname + ": " + e.getMessage() + "||";
+        }
+    }
+
+    public String displayTooltip(String fieldname, XWikiContext context) {
+        try {
+            BaseObject object = getxWikiObject();
+            if (object == null)
+                object = getFirstObject(fieldname, context);
+            return displayTooltip(fieldname, object, context);
+        } catch (Exception e) {
+            return "";
+        }
+    }
+
+    public String displayTooltip(String fieldname, BaseObject obj, XWikiContext context) {
+        try {
+            PropertyClass pclass = (PropertyClass) obj.getxWikiClass(context).get(fieldname);
+            String tooltip = pclass.getTooltip();
+            if ((tooltip!=null)&&(!tooltip.trim().equals(""))) {
+                String img = "<img src=\"" + context.getWiki().getSkinFile("info.gif", context) + "\" align=\"middle\" />";
+                return context.getWiki().addTooltip(img, tooltip, context);
+            } else
+             return "";
+        }
+        catch (Exception e) {
+            return "";
+        }
+    }
+
     public String display(String fieldname, String type, BaseObject obj, XWikiContext context) {
         try {
             type = type.toLowerCase();
@@ -959,6 +1010,7 @@
                 String fcontent = pclass.displayView(fieldname, prefix, obj, context);
                 result.append(getRenderedContent(fcontent, context));
             } else if (type.equals("edit")) {
+                context.addDisplayedField(fieldname);
                 result.append("{pre}");
                 pclass.displayEdit(result, fieldname, prefix, obj, context);
                 result.append("{/pre}");
@@ -1306,6 +1358,7 @@
         doc.setCreator(getCreator());
         doc.setDefaultLanguage(getDefaultLanguage());
         doc.setDefaultTemplate(getDefaultTemplate());
+        doc.setValidationScript(getValidationScript());
         doc.setLanguage(getLanguage());
         doc.setTranslation(getTranslation());
         doc.setxWikiClass((BaseClass) getxWikiClass().clone());
@@ -1387,6 +1440,12 @@
         if (!getTemplate().equals(doc.getTemplate()))
             return false;
 
+        if (!getDefaultTemplate().equals(doc.getDefaultTemplate()))
+            return false;
+
+        if (!getValidationScript().equals(doc.getValidationScript()))
+            return false;
+        
         if (!getxWikiClass().equals(doc.getxWikiClass()))
             return false;
 
@@ -1552,6 +1611,14 @@
         el.addText(getTemplate());
         docel.add(el);
 
+        el = new DOMElement("defaultTemplate");
+        el.addText(getDefaultTemplate());
+        docel.add(el);
+
+        el = new DOMElement("validationScript");
+        el.addText(getValidationScript());
+        docel.add(el);
+
         List alist = getAttachmentList();
         for (int ai = 0; ai < alist.size(); ai++) {
             XWikiAttachment attach = (XWikiAttachment) alist.get(ai);
@@ -1699,6 +1766,8 @@
         setLanguage(getElement(docel, "language"));
         setDefaultLanguage(getElement(docel, "defaultLanguage"));
         setTitle(getElement(docel,"title"));
+        setDefaultTemplate(getElement(docel,"defaultTemplate"));
+        setValidationScript(getElement(docel,"validationScript"));
 
         String strans = getElement(docel, "translation");
         if ((strans == null) || strans.equals(""))
@@ -2592,7 +2661,10 @@
     }
 
     public String getDefaultTemplate() {
-        return defaultTemplate;
+        if (defaultTemplate==null)
+         return "";
+        else
+         return defaultTemplate;
     }
 
     public void setDefaultTemplate(String defaultTemplate) {
@@ -2956,6 +3028,9 @@
     }
 
     public String getValidationScript() {
+        if (validationScript==null)
+         return "";
+        else
         return validationScript;
     }
 
@@ -2981,4 +3056,43 @@
         }
     }
 
+    public boolean validate(XWikiContext context) throws XWikiException {
+        boolean isValid = true;
+        for (Iterator it = getxWikiObjects().keySet().iterator(); it.hasNext();) {
+            String classname = (String) it.next();
+            BaseClass bclass = context.getWiki().getClass(classname, context);
+            Vector objects = getObjects(classname);
+
+            for (int i = 0; i < objects.size(); i++) {
+                BaseObject obj = (BaseObject) objects.get(i);
+                if (obj != null) {
+                    isValid &= bclass.validateObject(obj, context);
+                }
+            }
+        }
+
+        String validationScript = "";
+        XWikiRequest req = context.getRequest();
+        if (req!=null) {
+            validationScript = req.get("xvalidation");
+        }
+        if ((validationScript==null)||(validationScript.trim().equals(""))) {
+            validationScript = getValidationScript();
+        }
+        if ((validationScript!=null)&&(!validationScript.trim().equals(""))) {
+            isValid &= executeValidationScript(context, validationScript);
+
+        }
+        return isValid;
+    }
+
+    private boolean executeValidationScript(XWikiContext context, String validationScript) throws XWikiException {
+        try {
+        XWikiValidationInterface validObject = (XWikiValidationInterface) context.getWiki().parseGroovyFromPage(validationScript, context);
+        return validObject.validateDocument(this, context);
+        } catch (Throwable e) {
+             XWikiValidationStatus.addExceptionToContext(getFullName(), "", e, context);
+             return false;
+        }
+    }
 }

Modified: xwiki/trunk/core/src/main/java/com/xpn/xwiki/objects/classes/BaseClass.java
===================================================================
--- xwiki/trunk/core/src/main/java/com/xpn/xwiki/objects/classes/BaseClass.java	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/core/src/main/java/com/xpn/xwiki/objects/classes/BaseClass.java	2006-10-30 04:11:22 UTC (rev 1477)
@@ -25,6 +25,8 @@
 
 import com.xpn.xwiki.XWikiContext;
 import com.xpn.xwiki.XWikiException;
+import com.xpn.xwiki.validation.XWikiValidationInterface;
+import com.xpn.xwiki.validation.XWikiValidationStatus;
 import com.xpn.xwiki.objects.BaseCollection;
 import com.xpn.xwiki.objects.BaseObject;
 import com.xpn.xwiki.objects.BaseProperty;
@@ -163,9 +165,12 @@
         if (!getDefaultWeb().equals(bclass.getDefaultWeb()))
             return false;
 
+        if (!getValidationScript().equals(bclass.getValidationScript()))
+            return false;
+
         if (!getNameField().equals(bclass.getNameField()))
             return false;
-
+        
         return true;
     }
 
@@ -207,6 +212,11 @@
         el.addText((getNameField()==null) ? "" : getNameField());
         cel.add(el);
 
+        el = new DOMElement("validationScript");
+        el.addText((getValidationScript()==null) ? "" : getValidationScript());
+        cel.add(el);
+
+
         Iterator it = getFieldList().iterator();
         while (it.hasNext()) {
             PropertyClass bprop = (PropertyClass)it.next();
@@ -250,6 +260,12 @@
                 j++;
             }
 
+            Element valel = cel.element("validationScript");
+            if (valel!=null) {
+                setValidationScript(valel.getText());
+                j++;
+            }
+
             List list = cel.elements();
             for (int i=j;i<list.size();i++) {
                 Element pcel = (Element) list.get(i);
@@ -667,4 +683,31 @@
         return validationScript;
     }
 
+    public boolean validateObject(BaseObject obj, XWikiContext context) throws XWikiException {
+        boolean isValid = true;
+        Object[] props = (Object[]) getPropertyNames();
+        for (int i=0;i<props.length;i++) {
+            String propname = (String) props[i];
+            BaseProperty property = (BaseProperty) obj.get(propname);
+            PropertyClass propclass = (PropertyClass) get(propname);
+            isValid &= propclass.validateProperty(property, context);
+        }
+
+        String validSript = getValidationScript();
+        if ((validSript!=null)&&(!validSript.trim().equals("")))
+          isValid &= executeValidationScript(obj, validSript, context);
+        
+        return isValid;
+    }
+
+    private boolean executeValidationScript(BaseObject obj, String validationScript, XWikiContext context) throws XWikiException {
+        try {
+        XWikiValidationInterface validObject = (XWikiValidationInterface) context.getWiki().parseGroovyFromPage(validationScript, context);
+        return validObject.validateObject(obj, context);
+        } catch (Throwable e) {
+             XWikiValidationStatus.addExceptionToContext(getName(), "", e, context);
+             return false;
+        }
+    }
+
 }

Modified: xwiki/trunk/core/src/main/java/com/xpn/xwiki/objects/classes/PropertyClass.java
===================================================================
--- xwiki/trunk/core/src/main/java/com/xpn/xwiki/objects/classes/PropertyClass.java	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/core/src/main/java/com/xpn/xwiki/objects/classes/PropertyClass.java	2006-10-30 04:11:22 UTC (rev 1477)
@@ -25,6 +25,7 @@
 
 import com.xpn.xwiki.XWikiContext;
 import com.xpn.xwiki.XWikiException;
+import com.xpn.xwiki.validation.XWikiValidationStatus;
 import com.xpn.xwiki.objects.BaseCollection;
 import com.xpn.xwiki.objects.BaseObject;
 import com.xpn.xwiki.objects.BaseProperty;
@@ -47,7 +48,6 @@
     private BaseClass object;
     private int id;
     private PropertyMetaClass pMetaClass;
-    private String validationRegExp;
 
     public PropertyClass() {
     }
@@ -263,6 +263,26 @@
         setStringValue("prettyName", prettyName);
     }
 
+    public String getTooltip() {
+        return getLargeStringValue("tooltip");
+    }
+
+    public void setTooltip(String tooltip) {
+        setLargeStringValue("tooltip", tooltip);
+    }
+
+    public String getTranslatedPrettyName(XWikiContext context) {
+        String msgName = className + "_" + getName();
+        if ((context==null)||(context.getWiki()==null))
+         return getPrettyName();
+        
+        String prettyName = context.getWiki().getMessage(msgName, context);
+        if (prettyName.equals(msgName))
+            return getPrettyName();
+        else
+            return prettyName;
+    }
+
     public int getNumber() {
         return getIntValue("number");
     }
@@ -366,11 +386,40 @@
     }
 
     public void setValidationRegExp(String validationRegExp) {
-        this.validationRegExp = validationRegExp;
+        setStringValue("validationRegExp", validationRegExp);
     }
 
     public String getValidationRegExp() {
-        return validationRegExp;
+        return getStringValue("validationRegExp");
     }
 
+    public String getValidationMessage() {
+        return getStringValue("validationMessage");
+    }
+
+    public void setValidationMessage(String validationMessage) {
+        setStringValue("validationMessage", validationMessage);
+    }
+
+    public boolean validateProperty(BaseProperty property, XWikiContext context) {
+        boolean isValid = false;
+        String regexp = getValidationRegExp();
+        if ((regexp==null)||(regexp.trim().equals("")))
+         return true;
+
+        String value = ((property==null)||(property.getValue()==null)) ? "" : property.getValue().toString();
+        try {
+            if (context.getUtil().match(regexp, value))
+             return true;
+            else {
+                XWikiValidationStatus.addErrorToContext((getObject()==null) ? "" : getObject().getClassName(), getName(), getTranslatedPrettyName(context), getValidationMessage(), context);
+                return false;
+            }
+        } catch (Exception e) {
+            XWikiValidationStatus.addExceptionToContext(getObject().getClassName(), getName(), e, context);
+            return false;
+        }
+
+    }
+
 }

Modified: xwiki/trunk/core/src/main/java/com/xpn/xwiki/objects/meta/PropertyMetaClass.java
===================================================================
--- xwiki/trunk/core/src/main/java/com/xpn/xwiki/objects/meta/PropertyMetaClass.java	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/core/src/main/java/com/xpn/xwiki/objects/meta/PropertyMetaClass.java	2006-10-30 04:11:22 UTC (rev 1477)
@@ -49,6 +49,13 @@
         prettyname_class.setSize(40);
         safeput("prettyName", prettyname_class);
 
+        TextAreaClass tooltip_class = new TextAreaClass(this);
+        tooltip_class.setName("tooltip");
+        tooltip_class.setPrettyName("Tooltip");
+        tooltip_class.setSize(60);
+        tooltip_class.setRows(5);
+        safeput("tooltip", tooltip_class);
+
         TextAreaClass customdisplay_class = new TextAreaClass(this);
         customdisplay_class.setName("customDisplay");
         customdisplay_class.setPrettyName("Custom Display");
@@ -73,6 +80,12 @@
         validationRegExp_class.setPrettyName("Validation Regular Expression");
         validationRegExp_class.setSize(40);
         safeput("validationRegExp", validationRegExp_class);
+
+        StringClass validationMessage_class = new StringClass(this);
+        validationMessage_class.setName("validationMessage");
+        validationMessage_class.setPrettyName("Validation Message");
+        validationMessage_class.setSize(80);
+        safeput("validationMessage", validationMessage_class);
     }
 
     public BaseCollection getObject() {

Deleted: xwiki/trunk/core/src/main/java/com/xpn/xwiki/validation/XWikiValidationException.java
===================================================================
--- xwiki/trunk/core/src/main/java/com/xpn/xwiki/validation/XWikiValidationException.java	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/core/src/main/java/com/xpn/xwiki/validation/XWikiValidationException.java	2006-10-30 04:11:22 UTC (rev 1477)
@@ -1,27 +0,0 @@
-/*
- * Copyright 2006, XpertNet SARL, and individual contributors as indicated
- * by the contributors.txt.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
- * @author jeremi
- */
-package com.xpn.xwiki.validation;
-
-import com.xpn.xwiki.XWikiException;
-
-public class XWikiValidationException extends XWikiException {
-}

Copied: xwiki/trunk/core/src/main/java/com/xpn/xwiki/validation/XWikiValidationStatus.java (from rev 1408, xwiki/trunk/core/src/main/java/com/xpn/xwiki/validation/XWikiValidationException.java)
===================================================================
--- xwiki/trunk/core/src/main/java/com/xpn/xwiki/validation/XWikiValidationException.java	2006-10-19 02:23:21 UTC (rev 1408)
+++ xwiki/trunk/core/src/main/java/com/xpn/xwiki/validation/XWikiValidationStatus.java	2006-10-30 04:11:22 UTC (rev 1477)
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2006, XpertNet SARL, and individual contributors as indicated
+ * by the contributors.txt.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * @author jeremi
+ */
+package com.xpn.xwiki.validation;
+
+import com.xpn.xwiki.XWikiContext;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import org.apache.velocity.VelocityContext;
+
+public class XWikiValidationStatus {
+
+    private List errorObjects = new ArrayList();
+    private List propertyErrors = new ArrayList();
+    private List errors = new ArrayList();
+    private List exceptions = new ArrayList();
+
+
+    public XWikiValidationStatus() {
+    }
+
+    public static void addErrorToContext(String className, String propName, String propPrettyName, String validationMessage, XWikiContext context) {
+        XWikiValidationStatus errors = getValidationStatus(context);
+        errors.addError(className, propName, propPrettyName, validationMessage, context);
+
+    }
+
+    private static XWikiValidationStatus getValidationStatus(XWikiContext context) {
+        XWikiValidationStatus errors = (XWikiValidationStatus) context.getValidationStatus();
+        if (errors==null) {
+            errors = new XWikiValidationStatus();
+            context.setValidationStatus(errors);
+        }
+        return errors;
+    }
+
+    public static void addExceptionToContext(String className, String propName, Throwable e, XWikiContext context) {
+        XWikiValidationStatus errors = getValidationStatus(context);
+        errors.addException(className, propName, e, context);
+    }
+
+    public void addError(String className, String propName, String propPrettyName, String validationMessage, XWikiContext context) {
+        getErrorObjects().add(className);
+        getPropertyErrors().add(propName);
+
+        if ((validationMessage!=null)&&(!validationMessage.trim().equals("")))
+            getErrors().add(validationMessage);
+        else {
+            VelocityContext vcontext = (VelocityContext) context.get("vcontext");
+            if (vcontext==null)
+                getErrors().add("Validation error for property " + propPrettyName + " in class " + className);
+            else {
+                vcontext.put("className", className);
+                vcontext.put("propName", propPrettyName);
+                String message = context.getWiki().parseMessage("validation_error", context);
+                getErrors().add(message);
+            }
+        }
+    }
+
+    public void addException(String className, String propName, Throwable e, XWikiContext context) {
+        getExceptions().add(e);
+    }
+
+    public boolean hasExceptions() {
+        return (getExceptions().size()>0);
+    }
+
+    public List getExceptions() {
+        return exceptions;
+    }
+
+    public List getErrorObjects() {
+        return errorObjects;
+    }
+
+    public void setErrorObjects(List errorObjects) {
+        this.errorObjects = errorObjects;
+    }
+
+    public List getPropertyErrors() {
+        return propertyErrors;
+    }
+
+    public void setPropertyErrors(List propertyErrors) {
+        this.propertyErrors = propertyErrors;
+    }
+
+    public List getErrors() {
+        return errors;
+    }
+
+    public void setErrors(List errors) {
+        this.errors = errors;
+    }
+
+    public void setExceptions(List exceptions) {
+        this.exceptions = exceptions;
+    }
+}

Modified: xwiki/trunk/core/src/main/resources/ApplicationResources.properties
===================================================================
--- xwiki/trunk/core/src/main/resources/ApplicationResources.properties	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/core/src/main/resources/ApplicationResources.properties	2006-10-30 04:11:22 UTC (rev 1477)
@@ -488,4 +488,5 @@
 comment_anonymous=Anonymous
 comment_registered=Registered
 comment=Comment
-confirmcommentnotcorrect=Confirm to avoid spam robots. Please try again !!
\ No newline at end of file
+confirmcommentnotcorrect=Confirm to avoid spam robots. Please try again !!
+validationerror=Field $propName is incorrect.
\ No newline at end of file

Modified: xwiki/trunk/core/src/main/resources/xwiki.hbm.xml
===================================================================
--- xwiki/trunk/core/src/main/resources/xwiki.hbm.xml	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/core/src/main/resources/xwiki.hbm.xml	2006-10-30 04:11:22 UTC (rev 1477)
@@ -39,11 +39,11 @@
         </property>
 
         <property name="contentUpdateDate" type="timestamp">
-            <column name="XWD_CONTENT_UPDATE_DATE" />
+            <column name="XWD_CONTENT_UPDATE_DATE" not-null="true" />
         </property>
 
         <property name="creationDate" type="timestamp">
-            <column name="XWD_CREATION_DATE" />
+            <column name="XWD_CREATION_DATE" not-null="true" />
         </property>
 
         <property name="author" type="string">
@@ -88,11 +88,11 @@
         </property>
 
         <property name="defaultTemplate" type="string">
-            <column name="XWD_DEFAULT_TEMPLATE" />
+            <column name="XWD_DEFAULT_TEMPLATE"  not-null="true"/>
         </property>
 
         <property name="validationScript" type="string">
-            <column name="XWD_VALIDATION_SCRIPT" />
+            <column name="XWD_VALIDATION_SCRIPT"  not-null="true" />
         </property>
 
     </class>
@@ -103,7 +103,7 @@
             <generator class="assigned" />
         </id>
         <property name="archive" type="string">
-            <column name="XWD_ARCHIVE" length="200000" not-null="false"/>
+            <column name="XWD_ARCHIVE" length="200000" not-null="false" />
         </property>
     </class>
 
@@ -718,19 +718,19 @@
             <column name="XWP_LANGUAGES" length="255" />
         </property>
         <property name="registration_anonymous" type="string">
-            <column name="XWP_REGISTRATION_ANONYMUOS" length="255" />
+            <column name="XWP_REGISTRATION_ANONYMOUS" length="255" />
         </property>
         <property name="registration_registered" type="string">
             <column name="XWP_REGISTRATION_REGISTERED" length="255" />
         </property>
         <property name="edit_anonymous" type="string">
-            <column name="XWP_EDIT_ANONYMUOS" length="255" />
+            <column name="XWP_EDIT_ANONYMOUS" length="255" />
         </property>
         <property name="edit_registered" type="string">
             <column name="XWP_EDIT_REGISTERED" length="255" />
         </property>
         <property name="comment_anonymous" type="string">
-            <column name="XWP_COMMENT_ANONYMUOS" length="255" />
+            <column name="XWP_COMMENT_ANONYMOUS" length="255" />
         </property>
         <property name="comment_registered" type="string">
             <column name="XWP_COMMENT_REGISTERED" length="255" />

Added: xwiki/trunk/src/main/web/skins/default/ajax/wzToolTip.js
===================================================================
--- xwiki/trunk/src/main/web/skins/default/ajax/wzToolTip.js	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/src/main/web/skins/default/ajax/wzToolTip.js	2006-10-30 04:11:22 UTC (rev 1477)
@@ -0,0 +1,478 @@
+/* This notice must be untouched at all times.
+
+wz_tooltip.js    v. 3.38
+
+The latest version is available at
+http://www.walterzorn.com
+or http://www.devira.com
+or http://www.walterzorn.de
+
+Copyright (c) 2002-2005 Walter Zorn. All rights reserved.
+Created 1. 12. 2002 by Walter Zorn (Web: http://www.walterzorn.com )
+Last modified: 9. 12. 2005
+
+Cross-browser tooltips working even in Opera 5 and 6,
+as well as in NN 4, Gecko-Browsers, IE4+, Opera 7+ and Konqueror.
+No onmouseouts required.
+Appearance of tooltips can be individually configured
+via commands within the onmouseovers.
+
+LICENSE: LGPL
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License (LGPL) as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+For more details on the GNU Lesser General Public License,
+see http://www.gnu.org/copyleft/lesser.html
+*/
+
+
+
+////////////////  GLOBAL TOOPTIP CONFIGURATION  /////////////////////
+var ttAbove       = false;        // tooltip above mousepointer? Alternative: true
+var ttBgColor     = "#e6ecff";
+var ttBgImg       = "";           // path to background image;
+var ttBorderColor = "#003399";
+var ttBorderWidth = 1;
+var ttDelay       = 500;          // time span until tooltip shows up [milliseconds]
+var ttFontColor   = "#000066";
+var ttFontFace    = "arial,helvetica,sans-serif";
+var ttFontSize    = "11px";
+var ttFontWeight  = "normal";     // alternative: "bold";
+var ttLeft        = false;        // tooltip on the left of the mouse? Alternative: true
+var ttOffsetX     = 12;           // horizontal offset of left-top corner from mousepointer
+var ttOffsetY     = 15;           // vertical offset                   "
+var ttOpacity     = 100;          // opacity of tooltip in percent (must be integer between 0 and 100)
+var ttPadding     = 3;            // spacing between border and content
+var ttShadowColor = "";
+var ttShadowWidth = 0;
+var ttStatic      = false;        // tooltip NOT move with the mouse? Alternative: true
+var ttSticky      = false;        // do NOT hide tooltip on mouseout? Alternative: true
+var ttTemp        = 0;            // time span after which the tooltip disappears; 0 (zero) means "infinite timespan"
+var ttTextAlign   = "left";
+var ttTitleColor  = "#ffffff";    // color of caption text
+var ttWidth       = 300;
+////////////////////  END OF TOOLTIP CONFIG  ////////////////////////
+
+
+
+//////////////  TAGS WITH TOOLTIP FUNCTIONALITY  ////////////////////
+// List may be extended or shortened:
+var tt_tags = new Array("a","area","b","big","caption","center","code","dd","div","dl","dt","em","h1","h2","h3","h4","h5","h6","i","img","input","li","map","ol","p","pre","s", "select", "small","span","strike","strong","sub","sup","table","td","th","tr","tt","u","var","ul","layer");
+/////////////////////////////////////////////////////////////////////
+
+
+
+///////// DON'T CHANGE ANYTHING BELOW THIS LINE /////////////////////
+var tt_obj = null,         // current tooltip
+tt_ifrm = null,            // iframe to cover windowed controls in IE
+tt_objW = 0, tt_objH = 0,  // width and height of tt_obj
+tt_objX = 0, tt_objY = 0,
+tt_offX = 0, tt_offY = 0,
+xlim = 0, ylim = 0,        // right and bottom borders of visible client area
+tt_sup = false,            // true if T_ABOVE cmd
+tt_sticky = false,         // tt_obj sticky?
+tt_wait = false,
+tt_act = false,            // tooltip visibility flag
+tt_sub = false,            // true while tooltip below mousepointer
+tt_u = "undefined",
+tt_mf = null,              // stores previous mousemove evthandler
+// Opera: disable href when hovering <a>
+tt_tag = null;             // stores hovered dom node, href and previous statusbar txt
+
+
+var tt_db = (document.compatMode && document.compatMode != "BackCompat")? document.documentElement : document.body? document.body : null,
+tt_n = navigator.userAgent.toLowerCase(),
+tt_nv = navigator.appVersion;
+// Browser flags
+var tt_op = !!(window.opera && document.getElementById),
+tt_op6 = tt_op && !document.defaultView,
+tt_op7 = tt_op && !tt_op6,
+tt_ie = tt_n.indexOf("msie") != -1 && document.all && tt_db && !tt_op,
+tt_ie6 = tt_ie && parseFloat(tt_nv.substring(tt_nv.indexOf("MSIE")+5)) >= 5.5,
+tt_n4 = (document.layers && typeof document.classes != tt_u),
+tt_n6 = (!tt_op && document.defaultView && typeof document.defaultView.getComputedStyle != tt_u),
+tt_w3c = !tt_ie && !tt_n6 && !tt_op && document.getElementById;
+
+function tt_Int(t_x)
+{
+	var t_y;
+	return isNaN(t_y = parseInt(t_x))? 0 : t_y;
+}
+function wzReplace(t_x, t_y)
+{
+	var t_ret = "",
+	t_str = this,
+	t_xI;
+	while((t_xI = t_str.indexOf(t_x)) != -1)
+	{
+		t_ret += t_str.substring(0, t_xI) + t_y;
+		t_str = t_str.substring(t_xI + t_x.length);
+	}
+	return t_ret+t_str;
+}
+String.prototype.wzReplace = wzReplace;
+function tt_N4Tags(tagtyp, t_d, t_y)
+{
+	t_d = t_d || document;
+	t_y = t_y || new Array();
+	var t_x = (tagtyp=="a")? t_d.links : t_d.layers;
+	for(var z = t_x.length; z--;) t_y[t_y.length] = t_x[z];
+	for(z = t_d.layers.length; z--;) t_y = tt_N4Tags(tagtyp, t_d.layers[z].document, t_y);
+	return t_y;
+}
+function tt_Htm(tt, t_id, txt)
+{
+	var t_bgc = (typeof tt.T_BGCOLOR != tt_u)? tt.T_BGCOLOR : ttBgColor,
+	t_bgimg   = (typeof tt.T_BGIMG != tt_u)? tt.T_BGIMG : ttBgImg,
+	t_bc      = (typeof tt.T_BORDERCOLOR != tt_u)? tt.T_BORDERCOLOR : ttBorderColor,
+	t_bw      = (typeof tt.T_BORDERWIDTH != tt_u)? tt.T_BORDERWIDTH : ttBorderWidth,
+	t_ff      = (typeof tt.T_FONTFACE != tt_u)? tt.T_FONTFACE : ttFontFace,
+	t_fc      = (typeof tt.T_FONTCOLOR != tt_u)? tt.T_FONTCOLOR : ttFontColor,
+	t_fsz     = (typeof tt.T_FONTSIZE != tt_u)? tt.T_FONTSIZE : ttFontSize,
+	t_fwght   = (typeof tt.T_FONTWEIGHT != tt_u)? tt.T_FONTWEIGHT : ttFontWeight,
+	t_opa     = (typeof tt.T_OPACITY != tt_u)? tt.T_OPACITY : ttOpacity,
+	t_padd    = (typeof tt.T_PADDING != tt_u)? tt.T_PADDING : ttPadding,
+	t_shc     = (typeof tt.T_SHADOWCOLOR != tt_u)? tt.T_SHADOWCOLOR : (ttShadowColor || 0),
+	t_shw     = (typeof tt.T_SHADOWWIDTH != tt_u)? tt.T_SHADOWWIDTH : (ttShadowWidth || 0),
+	t_algn    = (typeof tt.T_TEXTALIGN != tt_u)? tt.T_TEXTALIGN : ttTextAlign,
+	t_tit     = (typeof tt.T_TITLE != tt_u)? tt.T_TITLE : "",
+	t_titc    = (typeof tt.T_TITLECOLOR != tt_u)? tt.T_TITLECOLOR : ttTitleColor,
+	t_w       = (typeof tt.T_WIDTH != tt_u)? tt.T_WIDTH  : ttWidth;
+	if(t_shc || t_shw)
+	{
+		t_shc = t_shc || "#cccccc";
+		t_shw = t_shw || 5;
+	}
+	if(tt_n4 && (t_fsz == "10px" || t_fsz == "11px")) t_fsz = "12px";
+
+	var t_optx = (tt_n4? '' : tt_n6? ('-moz-opacity:'+(t_opa/100.0)) : tt_ie? ('filter:Alpha(opacity='+t_opa+')') : ('opacity:'+(t_opa/100.0))) + ';';
+	var t_y = '<div id="'+t_id+'" style="position:absolute;z-index:1010;';
+	t_y += 'left:0px;top:0px;width:'+(t_w+t_shw)+'px;visibility:'+(tt_n4? 'hide' : 'hidden')+';'+t_optx+'">' +
+		'<table border="0" cellpadding="0" cellspacing="0"'+(t_bc? (' bgcolor="'+t_bc+'" style="background:'+t_bc+';"') : '')+' width="'+t_w+'">';
+	if(t_tit)
+	{
+		t_y += '<tr><td style="padding-left:3px;padding-right:3px;" align="'+t_algn+'"><font color="'+t_titc+'" face="'+t_ff+'" ' +
+			'style="color:'+t_titc+';font-family:'+t_ff+';font-size:'+t_fsz+';"><b>' +
+			(tt_n4? '&nbsp;' : '')+t_tit+'</b></font></td></tr>';
+	}
+	t_y += '<tr><td><table border="0" cellpadding="'+t_padd+'" cellspacing="'+t_bw+'" width="100%">' +
+		'<tr><td'+(t_bgc? (' bgcolor="'+t_bgc+'"') : '')+(t_bgimg? ' background="'+t_bgimg+'"' : '')+' style="text-align:'+t_algn+';';
+	if(tt_n6) t_y += 'padding:'+t_padd+'px;';
+	t_y += '" align="'+t_algn+'"><font color="'+t_fc+'" face="'+t_ff+'"' +
+		' style="color:'+t_fc+';font-family:'+t_ff+';font-size:'+t_fsz+';font-weight:'+t_fwght+';">';
+	if(t_fwght == 'bold') t_y += '<b>';
+	t_y += txt;
+	if(t_fwght == 'bold') t_y += '</b>';
+	t_y += '</font></td></tr></table></td></tr></table>';
+	if(t_shw)
+	{
+		var t_spct = Math.round(t_shw*1.3);
+		if(tt_n4)
+		{
+			t_y += '<layer bgcolor="'+t_shc+'" left="'+t_w+'" top="'+t_spct+'" width="'+t_shw+'" height="0"></layer>' +
+				'<layer bgcolor="'+t_shc+'" left="'+t_spct+'" align="bottom" width="'+(t_w-t_spct)+'" height="'+t_shw+'"></layer>';
+		}
+		else
+		{
+			t_optx = tt_n6? '-moz-opacity:0.85;' : tt_ie? 'filter:Alpha(opacity=85);' : 'opacity:0.85;';
+			t_y += '<div id="'+t_id+'R" style="position:absolute;background:'+t_shc+';left:'+t_w+'px;top:'+t_spct+'px;width:'+t_shw+'px;height:1px;overflow:hidden;'+t_optx+'"></div>' +
+				'<div style="position:relative;background:'+t_shc+';left:'+t_spct+'px;top:0px;width:'+(t_w-t_spct)+'px;height:'+t_shw+'px;overflow:hidden;'+t_optx+'"></div>';
+		}
+	}
+	return(t_y+'</div>' +
+		(tt_ie6 ? '<iframe id="TTiEiFrM" src="javascript:false" scrolling="no" frameborder="0" style="filter:Alpha(opacity=0);position:absolute;top:0px;left:0px;display:none;"></iframe>' : ''));
+}
+function tt_EvX(t_e)
+{
+	var t_y = tt_Int(t_e.pageX || t_e.clientX || 0) +
+		tt_Int(tt_ie? tt_db.scrollLeft : 0) +
+		tt_offX;
+	if(t_y > xlim) t_y = xlim;
+	var t_scr = tt_Int(window.pageXOffset || (tt_db? tt_db.scrollLeft : 0) || 0);
+	if(t_y < t_scr) t_y = t_scr;
+	return t_y;
+}
+function tt_EvY(t_e)
+{
+	var t_y = tt_Int(t_e.pageY || t_e.clientY || 0) +
+		tt_Int(tt_ie? tt_db.scrollTop : 0);
+	if(tt_sup) t_y -= (tt_objH + tt_offY - 15);
+	else if(t_y > ylim || !tt_sub && t_y > ylim-24)
+	{
+		t_y -= (tt_objH + 5);
+		tt_sub = false;
+	}
+	else
+	{
+		t_y += tt_offY;
+		tt_sub = true;
+	}
+	return t_y;
+}
+function tt_ReleasMov()
+{
+	if(document.onmousemove == tt_Move)
+	{
+		if(!tt_mf && document.releaseEvents) document.releaseEvents(Event.MOUSEMOVE);
+		document.onmousemove = tt_mf;
+	}
+}
+function tt_ShowIfrm(t_x)
+{
+	if(!tt_obj || !tt_ifrm) return;
+	if(t_x)
+	{
+		tt_ifrm.style.width = tt_objW+'px';
+		tt_ifrm.style.height = tt_objH+'px';
+		tt_ifrm.style.display = "block";
+	}
+	else tt_ifrm.style.display = "none";
+}
+function tt_GetDiv(t_id)
+{
+	return(
+		tt_n4? (document.layers[t_id] || null)
+		: tt_ie? (document.all[t_id] || null)
+		: (document.getElementById(t_id) || null)
+	);
+}
+function tt_GetDivW()
+{
+	return tt_Int(
+		tt_n4? tt_obj.clip.width
+		: (tt_obj.style.pixelWidth || tt_obj.offsetWidth)
+	);
+}
+function tt_GetDivH()
+{
+	return tt_Int(
+		tt_n4? tt_obj.clip.height
+		: (tt_obj.style.pixelHeight || tt_obj.offsetHeight)
+	);
+}
+
+// Compat with DragDrop Lib: Ensure that z-index of tooltip is lifted beyond toplevel dragdrop element
+function tt_SetDivZ()
+{
+	var t_i = tt_obj.style || tt_obj;
+	if(t_i)
+	{
+		if(window.dd && dd.z)
+			t_i.zIndex = Math.max(dd.z+1, t_i.zIndex);
+		if(tt_ifrm) tt_ifrm.style.zIndex = t_i.zIndex-1;
+	}
+}
+function tt_SetDivPos(t_x, t_y)
+{
+	var t_i = tt_obj.style || tt_obj;
+	var t_px = (tt_op6 || tt_n4)? '' : 'px';
+	t_i.left = (tt_objX = t_x) + t_px;
+	t_i.top = (tt_objY = t_y) + t_px;
+	if(tt_ifrm)
+	{
+		tt_ifrm.style.left = t_i.left;
+		tt_ifrm.style.top = t_i.top;
+	}
+}
+function tt_ShowDiv(t_x)
+{
+	tt_ShowIfrm(t_x);
+	if(tt_n4) tt_obj.visibility = t_x? 'show' : 'hide';
+	else tt_obj.style.visibility = t_x? 'visible' : 'hidden';
+	tt_act = t_x;
+}
+function tt_OpDeHref(t_e)
+{
+	var t_tag;
+	if(t_e)
+	{
+		t_tag = t_e.target;
+		while(t_tag)
+		{
+			if(t_tag.hasAttribute("href"))
+			{
+				tt_tag = t_tag
+				tt_tag.t_href = tt_tag.getAttribute("href");
+				tt_tag.removeAttribute("href");
+				tt_tag.style.cursor = "hand";
+				tt_tag.onmousedown = tt_OpReHref;
+				tt_tag.stats = window.status;
+				window.status = tt_tag.t_href;
+				break;
+			}
+			t_tag = t_tag.parentElement;
+		}
+	}
+}
+function tt_OpReHref()
+{
+	if(tt_tag)
+	{
+		tt_tag.setAttribute("href", tt_tag.t_href);
+		window.status = tt_tag.stats;
+		tt_tag = null;
+	}
+}
+function tt_Show(t_e, t_id, t_sup, t_delay, t_fix, t_left, t_offx, t_offy, t_static, t_sticky, t_temp)
+{
+	if(tt_obj) tt_Hide();
+	tt_mf = document.onmousemove || null;
+	if(window.dd && (window.DRAG && tt_mf == DRAG || window.RESIZE && tt_mf == RESIZE)) return;
+	var t_sh, t_h;
+
+	tt_obj = tt_GetDiv(t_id);
+	if(tt_obj)
+	{
+		t_e = t_e || window.event;
+		tt_sub = !(tt_sup = t_sup);
+		tt_sticky = t_sticky;
+		tt_objW = tt_GetDivW();
+		tt_objH = tt_GetDivH();
+		tt_offX = t_left? -(tt_objW+t_offx) : t_offx;
+		tt_offY = t_offy;
+		if(tt_op7) tt_OpDeHref(t_e);
+		if(tt_n4)
+		{
+			if(tt_obj.document.layers.length)
+			{
+				t_sh = tt_obj.document.layers[0];
+				t_sh.clip.height = tt_objH - Math.round(t_sh.clip.width*1.3);
+			}
+		}
+		else
+		{
+			t_sh = tt_GetDiv(t_id+'R');
+			if(t_sh)
+			{
+				t_h = tt_objH - tt_Int(t_sh.style.pixelTop || t_sh.style.top || 0);
+				if(typeof t_sh.style.pixelHeight != tt_u) t_sh.style.pixelHeight = t_h;
+				else t_sh.style.height = t_h+'px';
+			}
+		}
+
+		xlim = tt_Int((tt_db && tt_db.clientWidth)? tt_db.clientWidth : window.innerWidth) +
+			tt_Int(window.pageXOffset || (tt_db? tt_db.scrollLeft : 0) || 0) -
+			tt_objW -
+			(tt_n4? 21 : 0);
+		ylim = tt_Int(window.innerHeight || tt_db.clientHeight) +
+			tt_Int(window.pageYOffset || (tt_db? tt_db.scrollTop : 0) || 0) -
+			tt_objH - tt_offY;
+
+		tt_SetDivZ();
+		if(t_fix) tt_SetDivPos(tt_Int((t_fix = t_fix.split(','))[0]), tt_Int(t_fix[1]));
+		else tt_SetDivPos(tt_EvX(t_e), tt_EvY(t_e));
+
+		var t_txt = 'tt_ShowDiv(\'true\');';
+		if(t_sticky) t_txt += '{'+
+				'tt_ReleasMov();'+
+				'window.tt_upFunc = document.onmouseup || null;'+
+				'if(document.captureEvents) document.captureEvents(Event.MOUSEUP);'+
+				'document.onmouseup = new Function("window.setTimeout(\'tt_Hide();\', 10);");'+
+			'}';
+		else if(t_static) t_txt += 'tt_ReleasMov();';
+		if(t_temp > 0) t_txt += 'window.tt_rtm = window.setTimeout(\'tt_sticky = false; tt_Hide();\','+t_temp+');';
+		window.tt_rdl = window.setTimeout(t_txt, t_delay);
+
+		if(!t_fix)
+		{
+			if(document.captureEvents) document.captureEvents(Event.MOUSEMOVE);
+			document.onmousemove = tt_Move;
+		}
+	}
+}
+var tt_area = false;
+function tt_Move(t_ev)
+{
+	if(!tt_obj) return;
+	if(tt_n6 || tt_w3c)
+	{
+		if(tt_wait) return;
+		tt_wait = true;
+		setTimeout('tt_wait = false;', 5);
+	}
+	var t_e = t_ev || window.event;
+	tt_SetDivPos(tt_EvX(t_e), tt_EvY(t_e));
+	if(tt_op6)
+	{
+		if(tt_area && t_e.target.tagName != 'AREA') tt_Hide();
+		else if(t_e.target.tagName == 'AREA') tt_area = true;
+	}
+}
+function tt_Hide()
+{
+	if(window.tt_obj)
+	{
+		if(window.tt_rdl) window.clearTimeout(tt_rdl);
+		if(!tt_sticky || !tt_act)
+		{
+			if(window.tt_rtm) window.clearTimeout(tt_rtm);
+			tt_ShowDiv(false);
+			tt_SetDivPos(-tt_objW, -tt_objH);
+			tt_obj = null;
+			if(typeof window.tt_upFunc != tt_u) document.onmouseup = window.tt_upFunc;
+		}
+		tt_sticky = false;
+		if(tt_op6 && tt_area) tt_area = false;
+		tt_ReleasMov();
+		if(tt_op7) tt_OpReHref();
+	}
+}
+function tt_Init()
+{
+	if(!(tt_op || tt_n4 || tt_n6 || tt_ie || tt_w3c)) return;
+
+	var htm = tt_n4? '<div style="position:absolute;"></div>' : '',
+	tags,
+	t_tj,
+	over,
+	esc = 'return escape(';
+	var i = tt_tags.length; while(i--)
+	{
+		tags = tt_ie? (document.all.tags(tt_tags[i]) || 1)
+			: document.getElementsByTagName? (document.getElementsByTagName(tt_tags[i]) || 1)
+			: (!tt_n4 && tt_tags[i]=="a")? document.links
+			: 1;
+		if(tt_n4 && (tt_tags[i] == "a" || tt_tags[i] == "layer")) tags = tt_N4Tags(tt_tags[i]);
+		var j = tags.length; while(j--)
+		{
+			if(typeof (t_tj = tags[j]).onmouseover == "function" && t_tj.onmouseover.toString().indexOf(esc) != -1 && !tt_n6 || tt_n6 && (over = t_tj.getAttribute("onmouseover")) && over.indexOf(esc) != -1)
+			{
+				if(over) t_tj.onmouseover = new Function(over);
+				var txt = unescape(t_tj.onmouseover());
+				htm += tt_Htm(
+					t_tj,
+					"tOoLtIp"+i+""+j,
+					txt.wzReplace("& ","&")
+				);
+
+				t_tj.onmouseover = new Function('e',
+					'tt_Show(e,'+
+					'"tOoLtIp' +i+''+j+ '",'+
+					((typeof t_tj.T_ABOVE != tt_u)? t_tj.T_ABOVE : ttAbove)+','+
+					((typeof t_tj.T_DELAY != tt_u)? t_tj.T_DELAY : ttDelay)+','+
+					((typeof t_tj.T_FIX != tt_u)? '"'+t_tj.T_FIX+'"' : '""')+','+
+					((typeof t_tj.T_LEFT != tt_u)? t_tj.T_LEFT : ttLeft)+','+
+					((typeof t_tj.T_OFFSETX != tt_u)? t_tj.T_OFFSETX : ttOffsetX)+','+
+					((typeof t_tj.T_OFFSETY != tt_u)? t_tj.T_OFFSETY : ttOffsetY)+','+
+					((typeof t_tj.T_STATIC != tt_u)? t_tj.T_STATIC : ttStatic)+','+
+					((typeof t_tj.T_STICKY != tt_u)? t_tj.T_STICKY : ttSticky)+','+
+					((typeof t_tj.T_TEMP != tt_u)? t_tj.T_TEMP : ttTemp)+
+					');'
+				);
+				t_tj.onmouseout = tt_Hide;
+				if(t_tj.alt) t_tj.alt = "";
+				if(t_tj.title) t_tj.title = "";
+			}
+		}
+	}
+	document.write(htm);
+	if(document.getElementById) tt_ifrm = document.getElementById("TTiEiFrM");
+}
+tt_Init();

Added: xwiki/trunk/src/main/web/skins/default/info.gif
===================================================================
(Binary files differ)


Property changes on: xwiki/trunk/src/main/web/skins/default/info.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: xwiki/trunk/src/main/web/skins/xwiki10/info.gif
===================================================================
(Binary files differ)


Property changes on: xwiki/trunk/src/main/web/skins/xwiki10/info.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: xwiki/trunk/src/main/web/yui/autocomplete/README
===================================================================
--- xwiki/trunk/src/main/web/yui/autocomplete/README	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/src/main/web/yui/autocomplete/README	2006-10-30 04:11:22 UTC (rev 1477)
@@ -0,0 +1,40 @@
+AutoComplete Release Notes
+
+
+
+*** version 0.11.3 ***
+
+* The iFrameSrc property has been deprecated. Implementers no longer need to
+specify an https URL to avoid IE security warnings when working with sites over
+SSL.
+
+
+
+*** version 0.11.0 ***
+
+* The method getListIds() has been deprecated for getListItems(), which returns
+an array of DOM references.
+
+* All classnames have been prefixed with "yui-ac-".
+
+* Container elements should no longer have CSS property "display" set to "none".
+
+* The useIFrame property can now be set after instantiation.
+
+* On some browsers, the unmatchedItemSelectEvent may not be fired properly when
+delimiter characters are defined.
+
+* On some browsers, defining delimiter characters while enabling forceSelection
+may result in unexpected behavior.
+
+
+
+*** version 0.10.0 ***
+
+* Initial release
+
+* In order to enable the useIFrame property, it should be set in the
+constructor.
+
+* On some browsers, defining delimiter characters while enabling forceSelection
+may result in unexpected behavior.

Added: xwiki/trunk/src/main/web/yui/autocomplete/autocomplete-debug.js
===================================================================
--- xwiki/trunk/src/main/web/yui/autocomplete/autocomplete-debug.js	2006-10-26 20:56:29 UTC (rev 1476)
+++ xwiki/trunk/src/main/web/yui/autocomplete/autocomplete-debug.js	2006-10-30 04:11:22 UTC (rev 1477)
@@ -0,0 +1,2788 @@
+/*
+Copyright (c) 2006, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.txt
+version: 0.11.3
+*/
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+/**
+ * Class providing the customizable functionality of a plug-and-play DHTML
+ * auto complete widget.  Some key features:
+ * <ul>
+ * <li>Navigate with up/down arrow keys and/or mouse to pick a selection</li>
+ * <li>The drop down container can "roll down" or "fly out" via configurable
+ * animation</li>
+ * <li>UI look-and-feel customizable through CSS, including container
+ * attributes, borders, position, fonts, etc</li>
+ * </ul>
+ *
+ * requires YAHOO.util.Dom Dom utility
+ * requires YAHOO.util.Event Event utility
+ * requires YAHOO.widget.DataSource Data source class
+ * see YAHOO.util.Animation Animation utility
+ * see JSON JSON library
+ *
+ * @constructor
+ * @param {element | string} inputEl DOM element reference or string ID of the auto complete input field
+ * @param {element | string} containerEl DOM element reference or string ID of the auto complete &lt;div&gt;
+ *                              container
+ * @param {object} oDataSource Instance of YAHOO.widget.DataSource for query/results
+ * @param {object} oConfigs Optional object literal of config params
+ */
+YAHOO.widget.AutoComplete = function(inputEl,containerEl,oDataSource,oConfigs) {
+    if(inputEl && containerEl && oDataSource) {
+        // Validate data source
+        if (oDataSource && (oDataSource instanceof YAHOO.widget.DataSource)) {
+            this.dataSource = oDataSource;
+        }
+        else {
+            YAHOO.log("Could not instantiate AutoComplete due to an invalid DataSource", "error", this.toString());
+            return;
+        }
+
+        // Validate input element
+        if(YAHOO.util.Dom.inDocument(inputEl)) {
+            if(typeof inputEl == "string") {
+                    this._sName = "instance" + YAHOO.widget.AutoComplete._nIndex + " " + inputEl;
+                    this._oTextbox = document.getElementById(inputEl);
+            }
+            else {
+                this._sName = (inputEl.id) ?
+                    "instance" + YAHOO.widget.AutoComplete._nIndex + " " + inputEl.id:
+                    "instance" + YAHOO.widget.AutoComplete._nIndex;
+                this._oTextbox = inputEl;
+            }
+        }
+        else {
+            YAHOO.log("Could not instantiate AutoComplete due to an invalid input element", "error", this.toString());
+            return;
+        }
+
+        // Validate container element
+        if(YAHOO.util.Dom.inDocument(containerEl)) {
+            if(typeof containerEl == "string") {
+                    this._oContainer = document.getElementById(containerEl);
+            }
+            else {
+                this._oContainer = containerEl;
+            }
+            if(this._oContainer.style.display == "none") {
+                YAHOO.log("The container may not display properly if display is set to \"none\" in CSS", "warn", this.toString());
+            }
+        }
+        else {
+            YAHOO.log("Could not instantiate AutoComplete due to an invalid container element", "error", this.toString());
+            return;
+        }
+
+        // Set any config params passed in to override defaults
+        if (typeof oConfigs == "object") {
+            for(var sConfig in oConfigs) {
+                if (sConfig) {
+                    this[sConfig] = oConfigs[sConfig];
+                }
+            }
+        }
+
+        // Initialization sequence
+        this._initContainer();
+        this._initProps();
+        this._initList();
+        this._initContainerHelpers();
+
+        // Set up events
+        var oSelf = this;
+        var oTextbox = this._oTextbox;
+        // Events are actually for the content module within the container
+        var oContent = this._oContainer._oContent;
+
+        // Dom events
+        YAHOO.util.Event.addListener(oTextbox,"keyup",oSelf._onTextboxKeyUp,oSelf);
+        YAHOO.util.Event.addListener(oTextbox,"keydown",oSelf._onTextboxKeyDown,oSelf);
+        YAHOO.util.Event.addListener(oTextbox,"keypress",oSelf._onTextboxKeyPress,oSelf);
+        YAHOO.util.Event.addListener(oTextbox,"focus",oSelf._onTextboxFocus,oSelf);
+        YAHOO.util.Event.addListener(oTextbox,"blur",oSelf._onTextboxBlur,oSelf);
+        YAHOO.util.Event.addListener(oContent,"mouseover",oSelf._onContainerMouseover,oSelf);
+        YAHOO.util.Event.addListener(oContent,"mouseout",oSelf._onContainerMouseout,oSelf);
+        YAHOO.util.Event.addListener(oContent,"scroll",oSelf._onContainerScroll,oSelf);
+        YAHOO.util.Event.addListener(oContent,"resize",oSelf._onContainerResize,oSelf);
+        if(oTextbox.form) {
+            YAHOO.util.Event.addListener(oTextbox.form,"submit",oSelf._onFormSubmit,oSelf);
+        }
+
+        // Custom events
+        this.textboxFocusEvent = new YAHOO.util.CustomEvent("textboxFocus", this);
+        this.textboxKeyEvent = new YAHOO.util.CustomEvent("textboxKey", this);
+        this.dataRequestEvent = new YAHOO.util.CustomEvent("dataRequest", this);
+        this.dataReturnEvent = new YAHOO.util.CustomEvent("dataReturn", this);
+        this.dataErrorEvent = new YAHOO.util.CustomEvent("dataError", this);
+        this.containerExpandEvent = new YAHOO.util.CustomEvent("containerExpand", this);
+        this.typeAheadEvent = new YAHOO.util.CustomEvent("typeAhead", this);
+        this.itemMouseOverEvent = new YAHOO.util.CustomEvent("itemMouseOver", this);
+        this.itemMouseOutEvent = new YAHOO.util.CustomEvent("itemMouseOut", this);
+        this.itemArrowToEvent = new YAHOO.util.CustomEvent("itemArrowTo", this);
+        this.itemArrowFromEvent = new YAHOO.util.CustomEvent("itemArrowFrom", this);
+        this.itemSelectEvent = new YAHOO.util.CustomEvent("itemSelect", this);
+        this.unmatchedItemSelectEvent = new YAHOO.util.CustomEvent("unmatchedItemSelect", this);
+        this.selectionEnforceEvent = new YAHOO.util.CustomEvent("selectionEnforce", this);
+        this.containerCollapseEvent = new YAHOO.util.CustomEvent("containerCollapse", this);
+        this.textboxBlurEvent = new YAHOO.util.CustomEvent("textboxBlur", this);
+        
+        // Finish up
+        oTextbox.setAttribute("autocomplete","off");
+        YAHOO.widget.AutoComplete._nIndex++;
+        YAHOO.log("AutoComplete initialized","info",this.toString());
+    }
+    // Required arguments were not found
+    else {
+        YAHOO.log("Could not instantiate AutoComplete due invalid arguments", "error", this.toString());
+    }
+};
+
+/***************************************************************************
+ * Public member variables
+ ***************************************************************************/
+/**
+ * The data source object that encapsulates the data used for auto completion.
+ * This object should be an inherited object from YAHOO.widget.DataSource.
+ *
+ * @type object
+ */
+YAHOO.widget.AutoComplete.prototype.dataSource = null;
+
+/**
+ * Number of characters that must be entered before querying for results.
+ * Default: 1.
+ *
+ * @type number
+ */
+YAHOO.widget.AutoComplete.prototype.minQueryLength = 1;
+
+/**
+ * Maximum number of results to display in auto complete container. Default: 10.
+ *
+ * @type number
+ */
+YAHOO.widget.AutoComplete.prototype.maxResultsDisplayed = 10;
+
+/**
+ * Number of seconds to delay before submitting a query request.  If a query
+ * request is received before a previous one has completed its delay, the
+ * previous request is cancelled and the new request is set to the delay.
+ * Default: 0.5.
+ *
+ * @type number
+ */
+YAHOO.widget.AutoComplete.prototype.queryDelay = 0.5;
+
+/**
+ * Class name of a highlighted item within the auto complete container.
+ * Default: "yui-ac-highlight".
+ *
+ * @type string
+ */
+YAHOO.widget.AutoComplete.prototype.highlightClassName = "yui-ac-highlight";
+
+/**
+ * Class name of a pre-highlighted item within the auto complete container.
+ * Default: null.
+ *
+ * @type string
+ */
+YAHOO.widget.AutoComplete.prototype.prehighlightClassName = null;
+
+/**
+ * Query delimiter. A single character separator for multiple delimited
+ * selections. Multiple delimiter characteres may be defined as an array of
+ * strings. A null value or empty string indicates that query results cannot
+ * be delimited. This feature is not recommended if you need forceSelection to
+ * be true. Default: null.
+ *
+ * @type string or array
+ */
+YAHOO.widget.AutoComplete.prototype.delimChar = null;
+
+/**
+ * Whether or not the first item in the auto complete container should be
+ * automatically highlighted on expand. Default: true.
+ *
+ * @type boolean
+ */
+YAHOO.widget.AutoComplete.prototype.autoHighlight = true;
+
+/**
+ * Whether or not the auto complete input field should be automatically updated
+ * with the first query result as the user types, auto-selecting the substring
+ * that the user has not typed. Default: false.
+ *
+ * @type boolean
+ */
+YAHOO.widget.AutoComplete.prototype.typeAhead = false;
+
+/**
+ * Whether or not to animate the expansion/collapse of the auto complete
+ * container in the horizontal direction. Default: false.
+ *
+ * @type boolean
+ */
+YAHOO.widget.AutoComplete.prototype.animHoriz = false;
+
+/**
+ * Whether or not to animate the expansion/collapse of the auto complete
+ * container in the vertical direction. Default: true.
+ *
+ * @type boolean
+ */
+YAHOO.widget.AutoComplete.prototype.animVert = true;
+
+/**
+ * Speed of container expand/collapse animation, in seconds. Default: 0.3.
+ *
+ * @type number
+ */
+YAHOO.widget.AutoComplete.prototype.animSpeed = 0.3;
+
+/**
+ * Whether or not to force the user's selection to match one of the query
+ * results. Enabling this feature essentially transforms the auto complete form
+ * input field into a &lt;select&gt; field. This feature is not recommended
+ * with delimiter character(s) defined. Default: false.
+ *
+ * @type boolean
+ */
+YAHOO.widget.AutoComplete.prototype.forceSelection = false;
+
+/**
+ * Whether or not to allow browsers to cache user-typed input in the input
+ * field. Disabling this feature will prevent the widget from setting the
+ * autocomplete="off" on the auto complete input field. When autocomplete="off"
+ * and users click the back button after form submission, user-typed input can
+ * be prefilled by the browser from its cache. This caching of user input may
+ * not be desired for sensitive data, such as credit card numbers, in which
+ * case, implementers should consider setting allowBrowserAutocomplete to false.
+ * Default: true.
+ *
+ * @type boolean
+ */
+YAHOO.widget.AutoComplete.prototype.allowBrowserAutocomplete = true;
+
+/**
+ * Whether or not the auto complete container should always be displayed.
+ * Enabling this feature prevents the toggling of the container to a collapsed
+ * state. Default: false.
+ *
+ * @type boolean
+ */
+YAHOO.widget.AutoComplete.prototype.alwaysShowContainer = false;
+
+/**
+ * Whether or not to use an iFrame to layer over Windows form elements in
+ * IE. Set to true only when the auto complete container will be on top of a
+ * &lt;select&gt; field in IE and thus exposed to the IE z-index bug (i.e.,
+ * 5.5 < IE < 7). Default:false.
+ *
+ * @type boolean
+ */
+YAHOO.widget.AutoComplete.prototype.useIFrame = false;
+
+/**
+ * Whether or not the auto complete container should have a shadow. Default:false.
+ *
+ * @type boolean
+ */
+YAHOO.widget.AutoComplete.prototype.useShadow = false;
+
+/***************************************************************************
+ * Public methods
+ ***************************************************************************/
+ /**
+ * Public accessor to the unique name of the auto complete instance.
+ *
+ * @return {string} Unique name of the auto complete instance
+ */
+YAHOO.widget.AutoComplete.prototype.toString = function() {
+    return "AutoComplete " + this._sName;
+};
+
+/**
+ * Public accessor to the internal array of DOM &lt;li&gt; elements that
+ * display query results within the auto complete container.
+ *
+ * @return {array} Array of &lt;li&gt; elements within the auto complete
+ *                 container
+ */
+YAHOO.widget.AutoComplete.prototype.getListItems = function() {
+    return this._aListItems;
+};
+
+/**
+ * Public accessor to the data held in an &lt;li&gt; element of the
+ * auto complete container.
+ *
+ * @return {object or array} Object or array of result data or null
+ */
+YAHOO.widget.AutoComplete.prototype.getListItemData = function(oListItem) {
+    if(oListItem._oResultData) {
+        return oListItem._oResultData;
+    }
+    else {
+        return false;
+    }
+};
+
+/**
+ * Sets HTML markup for the auto complete container header. This markup will be
+ * inserted within a &lt;div&gt; tag with a class of "ac_hd".
+ *
+ * @param {string} sHeader HTML markup for container header
+ */
+YAHOO.widget.AutoComplete.prototype.setHeader = function(sHeader) {
+    if(sHeader) {
+        if(this._oContainer._oContent._oHeader) {
+            this._oContainer._oContent._oHeader.innerHTML = sHeader;
+            this._oContainer._oContent._oHeader.style.display = "block";
+        }
+    }
+    else {
+        this._oContainer._oContent._oHeader.innerHTML = "";
+        this._oContainer._oContent._oHeader.style.display = "none";
+    }
+};
+
+/**
+ * Sets HTML markup for the auto complete container footer. This markup will be
+ * inserted within a &lt;div&gt; tag with a class of "ac_ft".
+ *
+ * @param {string} sFooter HTML markup for container footer
+ */
+YAHOO.widget.AutoComplete.prototype.setFooter = function(sFooter) {
+    if(sFooter) {
+        if(this._oContainer._oContent._oFooter) {
+            this._oContainer._oContent._oFooter.innerHTML = sFooter;
+            this._oContainer._oContent._oFooter.style.display = "block";
+        }
+    }
+    else {
+        this._oContainer._oContent._oFooter.innerHTML = "";
+        this._oContainer._oContent._oFooter.style.display = "none";
+    }
+};
+
+/**
+ * Sets HTML markup for the auto complete container body. This markup will be
+ * inserted within a &lt;div&gt; tag with a class of "ac_bd".
+ *
+ * @param {string} sHeader HTML markup for container body
+ */
+YAHOO.widget.AutoComplete.prototype.setBody = function(sBody) {
+    if(sBody) {
+        if(this._oContainer._oContent._oBody) {
+            this._oContainer._oContent._oBody.innerHTML = sBody;
+            this._oContainer._oContent._oBody.style.display = "block";
+            this._oContainer._oContent.style.display = "block";
+        }
+    }
+    else {
+        this._oContainer._oContent._oBody.innerHTML = "";
+        this._oContainer._oContent.style.display = "none";
+    }
+    this._maxResultsDisplayed = 0;
+};
+
+/**
+ * Overridable method that converts a result item object into HTML markup
+ * for display. Return data values are accessible via the oResultItem object,
+ * and the key return value will always be oResultItem[0]. Markup will be
+ * displayed within &lt;li&gt; element tags in the container.
+ *
+ * @param {object} oResultItem Result item object representing one query result
+ * @param {string} sQuery The current query string
+ * @return {string} HTML markup of formatted result data
+ */
+YAHOO.widget.AutoComplete.prototype.formatResult = function(oResultItem, sQuery) {
+    var sResult = oResultItem[0];
+    if(sResult) {
+        return sResult;
+    }
+    else {
+        return "";
+    }
+};
+
+/**
+ * Makes query request to the data source.
+ *
+ * @param {string} sQuery Query string.
+ */
+YAHOO.widget.AutoComplete.prototype.sendQuery = function(sQuery) {
+    if(sQuery) {
+        this._sendQuery(sQuery);
+    }
+    else {
+        YAHOO.log("Query could not be sent because the string value was empty or null.","warn",this.toString());
+        return;
+    }
+};
+
+/***************************************************************************
+ * Events
+ ***************************************************************************/
+/**
+ * Fired when the auto complete text input box receives focus. Subscribers
+ * receive the following array:<br>
+ *     -  args[0] The auto complete object instance
+ */
+YAHOO.widget.AutoComplete.prototype.textboxFocusEvent = null;
+
+/**
+ * Fired when the auto complete text input box receives key input. Subscribers
+ * receive the following array:<br>
+ *     - args[0] The auto complete object instance
+ *     - args[1] The keycode number
+ */
+YAHOO.widget.AutoComplete.prototype.textboxKeyEvent = null;
+
+/**
+ * Fired when the auto complete instance makes a query to the data source.
+ * Subscribers receive the following array:<br>
+ *     - args[0] The auto complete object instance
+ *     - args[1] The query string
+ */
+YAHOO.widget.AutoComplete.prototype.dataRequestEvent = null;
+
+/**
+ * Fired when the auto complete instance receives query results from the data
+ * source. Subscribers receive the following array:<br>
+ *     - args[0] The auto complete object instance
+ *     - args[1] The query string
+ *     - args[2] Results array
+ */
+YAHOO.widget.AutoComplete.prototype.dataReturnEvent = null;
+
+/**
+ * Fired when the auto complete instance does not receive query results from the
+ * data source due to an error. Subscribers receive the following array:<br>
+ *     - args[0] The auto complete object instance
+ *     - args[1] The query string
+ */
+YAHOO.widget.AutoComplete.prototype.dataErrorEvent = null;
+
+/**
+ * Fired when the auto complete container is expanded. If alwaysShowContainer is
+ * enabled, then containerExpandEvent will be fired when the container is
+ * populated with results. Subscribers receive the following array:<br>
+ *     - args[0] The auto complete object instance
+ */
+YAHOO.widget.AutoComplete.prototype.containerExpandEvent = null;
+
+/**
+ * Fired when the auto complete textbox has been prefilled by the type-ahead
+ * feature. Subscribers receive the following array:<br>
+ *     - args[0] The auto complete object instance
+ *     - args[1] The query string
+ *     - args[2] The prefill string
+ */
+YAHOO.widget.AutoComplete.prototype.typeAheadEvent = null;
+
+/**
+ * Fired when result item has been moused over. Subscribers receive the following
+ * array:<br>
+ *     - args[0] The auto complete object instance
+ *     - args[1] The &lt;li&gt element item moused to
+ */
+YAHOO.widget.AutoComplete.prototype.itemMouseOverEvent = null;
+
+/**
+ * Fired when result item has been moused out. Subscribers receive the
+ * following array:<br>
+ *     - args[0] The auto complete object instance
+ *     - args[1] The &lt;li&gt; element item moused from
+ */
+YAHOO.widget.AutoComplete.prototype.itemMouseOutEvent = null;
+
+/**
+ * Fired when result item has been arrowed to. Subscribers receive the following
+ * array:<br>
+ *     - args[0] The auto complete object instance
+ *     - args[1] The &lt;li&gt; element item arrowed to
+ */
+YAHOO.widget.AutoComplete.prototype.itemArrowToEvent = null;
+
+/**
+ * Fired when result item has been arrowed away from. Subscribers receive the
+ * following array:<br>
+ *     - args[0] The auto complete object instance
+ *     - args[1] The &lt;li&gt; element item arrowed from
+ */
+YAHOO.widget.AutoComplete.prototype.itemArrowFromEvent = null;
+
+/**
+ * Fired when an item is selected via mouse click, ENTER key, or TAB key.
+ * Subscribers receive the following array:<br>
+ *     - args[0] The auto complete object instance
+ *     - args[1] The selected &lt;li&gt; element item
+ *     - args[2] The data returned for the item, either as an object, or mapped from the schema into an array
+ */
+YAHOO.widget.AutoComplete.prototype.itemSelectEvent = null;
+
+/**
+ * Fired when an user selection does not match any of the displayed result items.
+ * Note that this event may not behave as expected when delimiter characters
+ * have been defined. Subscribers receive the following array:<br>
+ *     - args[0] The auto complete object instance
+ *     - args[1] The user selection
+ */
+YAHOO.widget.AutoComplete.prototype.unmatchedItemSelectEvent = null;
+
+/**
+ * Fired if forceSelection is enabled and the user's input has been cleared
+ * because it did not match one of the returned query results. Subscribers
+ * receive the following array:<br>
+ *     - args[0] The auto complete object instance
+ */
+YAHOO.widget.AutoComplete.prototype.selectionEnforceEvent = null;
+
+/**
+ * Fired when the auto complete container is collapsed. If alwaysShowContainer is
+ * enabled, then containerCollapseEvent will be fired when the container is
+ * cleared of results. Subscribers receive the following array:<br>
+ *     - args[0] The auto complete object instance
+ */
+YAHOO.widget.AutoComplete.prototype.containerCollapseEvent = null;
+
+/**
+ * Fired when the auto complete text input box loses focus. Subscribers receive
+ * an array of the following array:<br>
+ *     - args[0] The auto complete object instance
+ */
+YAHOO.widget.AutoComplete.prototype.textboxBlurEvent = null;
+
+/***************************************************************************
+ * Private member variables
+ ***************************************************************************/
+/**
+ * Internal class variable to index multiple auto complete instances.
+ *
+ * @type number
+ * @private
+ */
+YAHOO.widget.AutoComplete._nIndex = 0;
+
+/**
+ * Name of auto complete instance.
+ *
+ * @type string
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._sName = null;
+
+/**
+ * Text input box DOM element.
+ *
+ * @type object
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._oTextbox = null;
+
+/**
+ * Whether or not the textbox is currently in focus. If query results come back
+ * but the user has already moved on, do not proceed with auto complete behavior.
+ *
+ * @type boolean
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._bFocused = true;
+
+/**
+ * Animation instance for container expand/collapse.
+ *
+ * @type boolean
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._oAnim = null;
+
+/**
+ * Container DOM element.
+ *
+ * @type object
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._oContainer = null;
+
+/**
+ * Whether or not the auto complete container is currently open.
+ *
+ * @type boolean
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._bContainerOpen = false;
+
+/**
+ * Whether or not the mouse is currently over the auto complete
+ * container. This is necessary in order to prevent clicks on container items
+ * from being text input box blur events.
+ *
+ * @type boolean
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._bOverContainer = false;
+
+/**
+ * Array of &lt;li&gt; elements references that contain query results within the
+ * auto complete container.
+ *
+ * @type array
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._aListItems = null;
+
+/**
+ * Number of &lt;li&gt; elements currently displayed in auto complete container.
+ *
+ * @type number
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._nDisplayedItems = 0;
+
+/**
+ * Internal count of &lt;li&gt; elements displayed and hidden in auto complete container.
+ *
+ * @type number
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._maxResultsDisplayed = 0;
+
+/**
+ * Current query string
+ *
+ * @type string
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._sCurQuery = null;
+
+/**
+ * Past queries this session (for saving delimited queries).
+ *
+ * @type string
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._sSavedQuery = null;
+
+/**
+ * Pointer to the currently highlighted &lt;li&gt; element in the container.
+ *
+ * @type object
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._oCurItem = null;
+
+/**
+ * Whether or not an item has been selected since the container was populated
+ * with results. Reset to false by _populateList, and set to true when item is
+ * selected.
+ *
+ * @type boolean
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._bItemSelected = false;
+
+/**
+ * Key code of the last key pressed in textbox.
+ *
+ * @type number
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._nKeyCode = null;
+
+/**
+ * Delay timeout ID.
+ *
+ * @type number
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._nDelayID = -1;
+
+/**
+ * Src to iFrame used when useIFrame = true. Supports implementations over SSL
+ * as well.
+ *
+ * @type string
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._iFrameSrc = "javascript:false;";
+
+/***************************************************************************
+ * Private methods
+ ***************************************************************************/
+/**
+ * Updates and validates latest public config properties.
+ *
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._initProps = function() {
+    // Correct any invalid values
+    var minQueryLength = this.minQueryLength;
+    if(isNaN(minQueryLength) || (minQueryLength < 1)) {
+        minQueryLength = 1;
+    }
+    var maxResultsDisplayed = this.maxResultsDisplayed;
+    if(isNaN(this.maxResultsDisplayed) || (this.maxResultsDisplayed < 1)) {
+        this.maxResultsDisplayed = 10;
+    }
+    var queryDelay = this.queryDelay;
+    if(isNaN(this.queryDelay) || (this.queryDelay < 0)) {
+        this.queryDelay = 0.5;
+    }
+    var aDelimChar = (this.delimChar) ? this.delimChar : null;
+    if(aDelimChar) {
+        if(typeof aDelimChar == "string") {
+            this.delimChar = [aDelimChar];
+        }
+        else if(aDelimChar.constructor != Array) {
+            this.delimChar = null;
+        }
+    }
+    var animSpeed = this.animSpeed;
+    if((this.animHoriz || this.animVert) && YAHOO.util.Anim) {
+        if(isNaN(animSpeed) || (animSpeed < 0)) {
+            animSpeed = 0.3;
+        }
+        if(!this._oAnim ) {
+            oAnim = new YAHOO.util.Anim(this._oContainer._oContent, {}, this.animSpeed);
+            this._oAnim = oAnim;
+        }
+        else {
+            this._oAnim.duration = animSpeed;
+        }
+    }
+    if(this.forceSelection && this.delimChar) {
+        YAHOO.log("The forceSelection feature has been enabled with delimChar defined.","warn", this.toString());
+    }
+    if(this.alwaysShowContainer && (this.useShadow || this.useIFrame)) {
+        YAHOO.log("The features useShadow and useIFrame are not compatible with the alwaysShowContainer feature.","warn", this.toString());
+    }
+
+    if(this.alwaysShowContainer) {
+        this._bContainerOpen = true;
+    }
+};
+
+/**
+ * Initializes the auto complete container helpers if they are enabled and do
+ * not exist
+ *
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._initContainerHelpers = function() {
+    if(this.useShadow && !this._oContainer._oShadow) {
+        var oShadow = document.createElement("div");
+        oShadow.className = "yui-ac-shadow";
+        this._oContainer._oShadow = this._oContainer.appendChild(oShadow);
+    }
+    if(this.useIFrame && !this._oContainer._oIFrame) {
+        var oIFrame = document.createElement("iframe");
+        oIFrame.src = this._iFrameSrc;
+        oIFrame.frameBorder = 0;
+        oIFrame.scrolling = "no";
+        oIFrame.style.position = "absolute";
+        oIFrame.style.width = "100%";
+        oIFrame.style.height = "100%";
+        this._oContainer._oIFrame = this._oContainer.appendChild(oIFrame);
+    }
+};
+
+/**
+ * Initializes the auto complete container once at object creation
+ *
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._initContainer = function() {
+    if(!this._oContainer._oContent) {
+        // The oContent div helps size the iframe and shadow properly
+        var oContent = document.createElement("div");
+        oContent.className = "yui-ac-content";
+        oContent.style.display = "none";
+        this._oContainer._oContent = this._oContainer.appendChild(oContent);
+
+        var oHeader = document.createElement("div");
+        oHeader.className = "yui-ac-hd";
+        oHeader.style.display = "none";
+        this._oContainer._oContent._oHeader = this._oContainer._oContent.appendChild(oHeader);
+
+        var oBody = document.createElement("div");
+        oBody.className = "yui-ac-bd";
+        this._oContainer._oContent._oBody = this._oContainer._oContent.appendChild(oBody);
+
+        var oFooter = document.createElement("div");
+        oFooter.className = "yui-ac-ft";
+        oFooter.style.display = "none";
+        this._oContainer._oContent._oFooter = this._oContainer._oContent.appendChild(oFooter);
+    }
+    else {
+        YAHOO.log("Could not initialize the container","warn",this.toString());
+    }
+};
+
+/**
+ * Clears out contents of container body and creates up to
+ * YAHOO.widget.AutoComplete#maxResultsDisplayed &lt;li&gt; elements in an
+ * &lt;ul&gt; element.
+ *
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._initList = function() {
+    this._aListItems = [];
+    while(this._oContainer._oContent._oBody.hasChildNodes()) {
+        var oldListItems = this.getListItems();
+        if(oldListItems) {
+            for(var oldi = oldListItems.length-1; oldi >= 0; i--) {
+                oldListItems[oldi] = null;
+            }
+        }
+        this._oContainer._oContent._oBody.innerHTML = "";
+    }
+
+    var oList = document.createElement("ul");
+    oList = this._oContainer._oContent._oBody.appendChild(oList);
+    for(var i=0; i<this.maxResultsDisplayed; i++) {
+        var oItem = document.createElement("li");
+        oItem = oList.appendChild(oItem);
+        this._aListItems[i] = oItem;
+        this._initListItem(oItem, i);
+    }
+    this._maxResultsDisplayed = this.maxResultsDisplayed;
+};
+
+/**
+ * Initializes each &lt;li&gt; element in the container list.
+ *
+ * @param {object} oItem The &lt;li&gt; DOM element
+ * @param {number} nItemIndex The index of the element
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._initListItem = function(oItem, nItemIndex) {
+    var oSelf = this;
+    oItem.style.display = "none";
+    oItem._nItemIndex = nItemIndex;
+
+    oItem.mouseover = oItem.mouseout = oItem.onclick = null;
+    YAHOO.util.Event.addListener(oItem,"mouseover",oSelf._onItemMouseover,oSelf);
+    YAHOO.util.Event.addListener(oItem,"mouseout",oSelf._onItemMouseout,oSelf);
+    YAHOO.util.Event.addListener(oItem,"click",oSelf._onItemMouseclick,oSelf);
+};
+
+/**
+ * Handles &lt;li&gt; element mouseover events in the container.
+ *
+ * @param {event} v The mouseover event
+ * @param {object} oSelf The auto complete instance
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._onItemMouseover = function(v,oSelf) {
+    if(oSelf.prehighlightClassName) {
+        oSelf._togglePrehighlight(this,"mouseover");
+    }
+    else {
+        oSelf._toggleHighlight(this,"to");
+    }
+
+    oSelf.itemMouseOverEvent.fire(oSelf, this);
+};
+
+/**
+ * Handles &lt;li&gt; element mouseout events in the container.
+ *
+ * @param {event} v The mouseout event
+ * @param {object} oSelf The auto complete instance
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._onItemMouseout = function(v,oSelf) {
+    if(oSelf.prehighlightClassName) {
+        oSelf._togglePrehighlight(this,"mouseout");
+    }
+    else {
+        oSelf._toggleHighlight(this,"from");
+    }
+
+    oSelf.itemMouseOutEvent.fire(oSelf, this);
+};
+
+/**
+ * Handles &lt;li&gt; element click events in the container.
+ *
+ * @param {event} v The click event
+ * @param {object} oSelf The auto complete instance
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._onItemMouseclick = function(v,oSelf) {
+    // In case item has not been moused over
+    oSelf._toggleHighlight(this,"to");
+    oSelf._selectItem(this);
+};
+
+/**
+ * Handles container mouseover events.
+ *
+ * @param {event} v The mouseover event
+ * @param {object} oSelf The auto complete instance
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._onContainerMouseover = function(v,oSelf) {
+    oSelf._bOverContainer = true;
+};
+
+/**
+ * Handles container mouseout events.
+ *
+ * @param {event} v The mouseout event
+ * @param {object} oSelf The auto complete instance
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._onContainerMouseout = function(v,oSelf) {
+    oSelf._bOverContainer = false;
+    // If container is still active
+    if(oSelf._oCurItem) {
+        oSelf._toggleHighlight(oSelf._oCurItem,"to");
+    }
+};
+
+/**
+ * Handles container scroll events.
+ *
+ * @param {event} v The scroll event
+ * @param {object} oSelf The auto complete instance
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._onContainerScroll = function(v,oSelf) {
+    oSelf._oTextbox.focus();
+};
+
+/**
+ * Handles container resize events.
+ *
+ * @param {event} v The resize event
+ * @param {object} oSelf The auto complete instance
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._onContainerResize = function(v,oSelf) {
+    oSelf._toggleContainerHelpers(oSelf._bContainerOpen);
+};
+
+
+/**
+ * Handles textbox keydown events of functional keys, mainly for UI behavior.
+ *
+ * @param {event} v The keydown event
+ * @param {object} oSelf The auto complete instance
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._onTextboxKeyDown = function(v,oSelf) {
+    var nKeyCode = v.keyCode;
+
+    switch (nKeyCode) {
+        case 9: // tab
+            if(oSelf.delimChar && (oSelf._nKeyCode != nKeyCode)) {
+                if(oSelf._bContainerOpen) {
+                    YAHOO.util.Event.stopEvent(v);
+                }
+            }
+            // select an item or clear out
+            if(oSelf._oCurItem) {
+                oSelf._selectItem(oSelf._oCurItem);
+            }
+            else {
+                oSelf._clearList();
+            }
+            break;
+        case 13: // enter
+            if(oSelf._nKeyCode != nKeyCode) {
+                if(oSelf._bContainerOpen) {
+                    YAHOO.util.Event.stopEvent(v);
+                }
+            }
+            if(oSelf._oCurItem) {
+                oSelf._selectItem(oSelf._oCurItem);
+            }
+            else {
+                oSelf._clearList();
+            }
+            break;
+        case 27: // esc
+            oSelf._clearList();
+            return;
+        case 39: // right
+            oSelf._jumpSelection();
+            break;
+        case 38: // up
+            YAHOO.util.Event.stopEvent(v);
+            oSelf._moveSelection(nKeyCode);
+            break;
+        case 40: // down
+            YAHOO.util.Event.stopEvent(v);
+            oSelf._moveSelection(nKeyCode);
+            break;
+        default:
+            break;
+    }
+};
+
+/**
+ * Handles textbox keypress events, for stopEvent in Safari and FF 1.5/Mac
+ *
+ * @param {event} v The keyup event
+ * @param {object} oSelf The auto complete instance
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._onTextboxKeyPress = function(v,oSelf) {
+    var nKeyCode = v.keyCode;
+
+    switch (nKeyCode) {
+    case 9: // tab
+    case 13: // enter
+        if((oSelf._nKeyCode != nKeyCode)) {
+                YAHOO.util.Event.stopEvent(v);
+        }
+        break;
+    case 38: // up
+    case 40: // down
+        YAHOO.util.Event.stopEvent(v);
+        break;
+    default:
+        break;
+    }
+};
+
+/**
+ * Handles textbox keyup events that trigger queries.
+ *
+ * @param {event} v The keyup event
+ * @param {object} oSelf The auto complete instance
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._onTextboxKeyUp = function(v,oSelf) {
+    // Check to see if any of the public properties have been updated
+    oSelf._initProps();
+
+    var nKeyCode = v.keyCode;
+    oSelf._nKeyCode = nKeyCode;
+    var sChar = String.fromCharCode(nKeyCode);
+    var sText = this.value; //string in textbox
+
+    // Filter out chars that don't trigger queries
+    if (oSelf._isIgnoreKey(nKeyCode) || (sText.toLowerCase() == oSelf._sCurQuery)) {
+        return;
+    }
+    else {
+        oSelf.textboxKeyEvent.fire(oSelf, nKeyCode);
+    }
+
+    // Set timeout on the request
+    if (oSelf.queryDelay > 0) {
+        var nDelayID =
+            setTimeout(function(){oSelf._sendQuery(sText);},(oSelf.queryDelay * 1000));
+
+        if (oSelf._nDelayID != -1) {
+            clearTimeout(oSelf._nDelayID);
+        }
+
+        oSelf._nDelayID = nDelayID;
+    }
+    else {
+        // No delay so send request immediately
+        oSelf._sendQuery(sText);
+    }
+};
+
+/**
+ * Whether or not key is functional or should be ignored. Note that the right
+ * arrow key is NOT an ignored key since it triggers queries for certain intl
+ * charsets.
+ *
+ * @param {number} nKeycode Code of key pressed
+ * @return {boolean} Whether or not to be ignore key
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._isIgnoreKey = function(nKeyCode) {
+    if ((nKeyCode == 9) || (nKeyCode == 13)  || // tab, enter
+            (nKeyCode == 16) || (nKeyCode == 17) || // shift, ctl
+            (nKeyCode >= 18 && nKeyCode <= 20) || // alt,pause/break,caps lock
+            (nKeyCode == 27) || // esc
+            (nKeyCode >= 33 && nKeyCode <= 35) || // page up,page down,end
+            (nKeyCode >= 36 && nKeyCode <= 38) || // home,left,up
+            (nKeyCode == 40) || // down
+            (nKeyCode >= 44 && nKeyCode <= 45)) { // print screen,insert
+        return true;
+    }
+    return false;
+};
+
+/**
+ * Handles text input box receiving focus.
+ *
+ * @param {event} v The focus event
+ * @param {object} oSelf The auto complete instance
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._onTextboxFocus = function (v,oSelf) {
+    oSelf._oTextbox.setAttribute("autocomplete","off");
+    oSelf._bFocused = true;
+    oSelf.textboxFocusEvent.fire(oSelf);
+};
+
+/**
+ * Handles text input box losing focus.
+ *
+ * @param {event} v The focus event
+ * @param {object} oSelf The auto complete instance
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._onTextboxBlur = function (v,oSelf) {
+    // Don't treat as a blur if it was a selection via mouse click
+    if(!oSelf._bOverContainer || (oSelf._nKeyCode == 9)) {
+        // Current query needs to be validated
+        if(!oSelf._bItemSelected) {
+            if(!oSelf._bContainerOpen || (oSelf._bContainerOpen && !oSelf._textMatchesOption())) {
+                if(oSelf.forceSelection) {
+                    oSelf._clearSelection();
+                }
+                else {
+                    oSelf.unmatchedItemSelectEvent.fire(oSelf, oSelf._sCurQuery);
+                }
+            }
+        }
+
+        if(oSelf._bContainerOpen) {
+            oSelf._clearList();
+        }
+        oSelf._bFocused = false;
+        oSelf.textboxBlurEvent.fire(oSelf);
+    }
+};
+
+/**
+ * Handles form submission event.
+ *
+ * @param {event} v The submit event
+ * @param {object} oSelf The auto complete instance
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._onFormSubmit = function(v,oSelf) {
+    if(oSelf.allowBrowserAutocomplete) {
+        oSelf._oTextbox.setAttribute("autocomplete","on");
+    }
+    else {
+        oSelf._oTextbox.setAttribute("autocomplete","off");
+    }
+};
+
+/**
+ * Makes query request to the data source.
+ *
+ * @param {string} sQuery Query string.
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._sendQuery = function(sQuery) {
+    // Delimiter has been enabled
+    var aDelimChar = (this.delimChar) ? this.delimChar : null;
+    if(aDelimChar) {
+        // Loop through all possible delimiters and find the latest one
+        // A " " may be a false positive if they are defined as delimiters AND
+        // are used to separate delimited queries
+        var nDelimIndex = -1;
+        for(var i = aDelimChar.length-1; i >= 0; i--) {
+            var nNewIndex = sQuery.lastIndexOf(aDelimChar[i]);
+            if(nNewIndex > nDelimIndex) {
+                nDelimIndex = nNewIndex;
+            }
+        }
+        // If we think the last delimiter is a space (" "), make sure it is NOT
+        // a false positive by also checking the char directly before it
+        if(aDelimChar[i] == " ") {
+            for (var j = aDelimChar.length-1; j >= 0; j--) {
+                if(sQuery[nDelimIndex - 1] == aDelimChar[j]) {
+                    nDelimIndex--;
+                    break;
+                }
+            }
+        }
+        // A delimiter has been found so extract the latest query
+        if (nDelimIndex > -1) {
+            var nQueryStart = nDelimIndex + 1;
+            // Trim any white space from the beginning...
+            while(sQuery.charAt(nQueryStart) == " ") {
+                nQueryStart += 1;
+            }
+            // ...and save the rest of the string for later
+            this._sSavedQuery = sQuery.substring(0,nQueryStart);
+            // Here is the query itself
+            sQuery = sQuery.substr(nQueryStart);
+        }
+        else if(sQuery.indexOf(this._sSavedQuery) < 0){
+            this._sSavedQuery = null;
+        }
+    }
+
+    // Don't search queries that are too short
+    if (sQuery.length < this.minQueryLength) {
+        if (this._nDelayID != -1) {
+            clearTimeout(this._nDelayID);
+        }
+        this._clearList();
+        return;
+    }
+
+    sQuery = encodeURIComponent(sQuery);
+    this._nDelayID = -1;    // Reset timeout ID because request has been made
+    this.dataRequestEvent.fire(this, sQuery);
+    this.dataSource.getResults(this._populateList, sQuery, this);
+};
+
+/**
+ * Hides all visuals related to the array of &lt;li&gt; elements in the container.
+ *
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._clearList = function() {
+    this._oContainer._oContent.scrollTop = 0;
+    var aItems = this._aListItems;
+
+    if(aItems && (aItems.length > 0)) {
+        for(var i = aItems.length-1; i >= 0 ; i--) {
+            aItems[i].style.display = "none";
+        }
+    }
+
+    if (this._oCurItem) {
+        this._toggleHighlight(this._oCurItem,"from");
+    }
+
+    this._oCurItem = null;
+    this._nDisplayedItems = 0;
+    this._sCurQuery = null;
+    this._toggleContainer(false);
+};
+
+/**
+ * Populates the array of &lt;li&gt; elements in the container with query
+ * results. This method is passed to YAHOO.widget.DataSource#getResults as a
+ * callback function so results from the datasource are returned to the
+ * auto complete instance.
+ *
+ * @param {string} sQuery The query string
+ * @param {object} aResults An array of query result objects from the data source
+ * @param {string} oSelf The auto complete instance
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._populateList = function(sQuery, aResults, oSelf) {
+    if(aResults === null) {
+        oSelf.dataErrorEvent.fire(oSelf, sQuery);
+    }
+    if (!oSelf._bFocused || !aResults) {
+        return;
+    }
+
+    var isOpera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
+    var contentStyle = oSelf._oContainer._oContent.style;
+    contentStyle.width = (!isOpera) ? null : "";
+    contentStyle.height = (!isOpera) ? null : "";
+
+    var sCurQuery = decodeURIComponent(sQuery);
+    oSelf._sCurQuery = sCurQuery;
+    oSelf._bItemSelected = false;
+
+    if(oSelf._maxResultsDisplayed != oSelf.maxResultsDisplayed) {
+        oSelf._initList();
+    }
+
+    var nItems = Math.min(aResults.length,oSelf.maxResultsDisplayed);
+    oSelf._nDisplayedItems = nItems;
+    if (nItems > 0) {
+        oSelf._initContainerHelpers();
+        var aItems = oSelf._aListItems;
+
+        // Fill items with data
+        for(var i = nItems-1; i >= 0; i--) {
+            var oItemi = aItems[i];
+            var oResultItemi = aResults[i];
+            oItemi.innerHTML = oSelf.formatResult(oResultItemi, sCurQuery);
+            oItemi.style.display = "list-item";
+            oItemi._sResultKey = oResultItemi[0];
+            oItemi._oResultData = oResultItemi;
+
+        }
+
+        // Empty out remaining items if any
+        for(var j = aItems.length-1; j >= nItems ; j--) {
+            var oItemj = aItems[j];
+            oItemj.innerHTML = null;
+            oItemj.style.display = "none";
+            oItemj._sResultKey = null;
+            oItemj._oResultData = null;
+        }
+
+        if(oSelf.autoHighlight) {
+            // Go to the first item
+            var oFirstItem = aItems[0];
+            oSelf._toggleHighlight(oFirstItem,"to");
+            oSelf.itemArrowToEvent.fire(oSelf, oFirstItem);
+            oSelf._typeAhead(oFirstItem,sQuery);
+        }
+        else {
+            oSelf._oCurItem = null;
+        }
+
+        // Expand the container
+        oSelf._toggleContainer(true);
+    }
+    else {
+        oSelf._clearList();
+    }
+    oSelf.dataReturnEvent.fire(oSelf, sQuery, aResults);
+};
+
+/**
+ * When YAHOO.widget.AutoComplete#bForceSelection is true and the user attempts
+ * leave the text input box without selecting an item from the query results,
+ * the user selection is cleared.
+ *
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._clearSelection = function() {
+    var sValue = this._oTextbox.value;
+    var sChar = (this.delimChar) ? this.delimChar[0] : null;
+    var nIndex = (sChar) ? sValue.lastIndexOf(sChar, sValue.length-2) : -1;
+    if(nIndex > -1) {
+        this._oTextbox.value = sValue.substring(0,nIndex);
+    }
+    else {
+         this._oTextbox.value = "";
+    }
+    this._sSavedQuery = this._oTextbox.value;
+
+    // Fire custom event
+    this.selectionEnforceEvent.fire(this);
+};
+
+/**
+ * Whether or not user-typed value in the text input box matches any of the
+ * query results.
+ *
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._textMatchesOption = function() {
+    var foundMatch = false;
+
+    for(var i = this._nDisplayedItems-1; i >= 0 ; i--) {
+        var oItem = this._aListItems[i];
+        var sMatch = oItem._sResultKey.toLowerCase();
+        if (sMatch == this._sCurQuery.toLowerCase()) {
+            foundMatch = true;
+            break;
+        }
+    }
+    return(foundMatch);
+};
+
+/**
+ * Updates in the text input box with the first query result as the user types,
+ * selecting the substring that the user has not typed.
+ *
+ * @param {object} oItem The &lt;li&gt; element item whose data populates the input field
+ * @param {string} sQuery Query string
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._typeAhead = function(oItem, sQuery) {
+    // Don't update if turned off
+    if (!this.typeAhead) {
+        return;
+    }
+
+    var oTextbox = this._oTextbox;
+    var sValue = this._oTextbox.value; // any saved queries plus what user has typed
+
+    // Don't update with type-ahead if text selection is not supported
+    if(!oTextbox.setSelectionRange && !oTextbox.createTextRange) {
+        return;
+    }
+
+    // Select the portion of text that the user has not typed
+    var nStart = sValue.length;
+    this._updateValue(oItem);
+    var nEnd = oTextbox.value.length;
+    this._selectText(oTextbox,nStart,nEnd);
+    var sPrefill = oTextbox.value.substr(nStart,nEnd);
+    this.typeAheadEvent.fire(this,sQuery,sPrefill);
+};
+
+/**
+ * Selects text in a text input box.
+ *
+ * @param {object} oTextbox Text input box element in which to select text
+ * @param {number} nStart Starting index of text string to select
+ * @param {number} nEnd Ending index of text selection
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._selectText = function(oTextbox, nStart, nEnd) {
+    if (oTextbox.setSelectionRange) { // For Mozilla
+        oTextbox.setSelectionRange(nStart,nEnd);
+    }
+    else if (oTextbox.createTextRange) { // For IE
+        var oTextRange = oTextbox.createTextRange();
+        oTextRange.moveStart("character", nStart);
+        oTextRange.moveEnd("character", nEnd-oTextbox.value.length);
+        oTextRange.select();
+    }
+    else {
+        oTextbox.select();
+    }
+};
+
+/**
+ * Syncs auto complete container with its helpers.
+ *
+ * @param {boolean} bShow True if container is expanded, false if collapsed
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._toggleContainerHelpers = function(bShow) {
+    var bFireEvent = false;
+    var width = this._oContainer._oContent.offsetWidth + "px";
+    var height = this._oContainer._oContent.offsetHeight + "px";
+
+    if(this.useIFrame && this._oContainer._oIFrame) {
+        bFireEvent = true;
+        if(this.alwaysShowContainer || bShow) {
+            this._oContainer._oIFrame.style.width = width;
+            this._oContainer._oIFrame.style.height = height;
+        }
+        else {
+            this._oContainer._oIFrame.style.width = 0;
+            this._oContainer._oIFrame.style.height = 0;
+        }
+    }
+    if(this.useShadow && this._oContainer._oShadow) {
+        bFireEvent = true;
+        if(this.alwaysShowContainer || bShow) {
+            this._oContainer._oShadow.style.width = width;
+            this._oContainer._oShadow.style.height = height;
+        }
+        else {
+           this._oContainer._oShadow.style.width = 0;
+            this._oContainer._oShadow.style.height = 0;
+        }
+    }
+};
+
+/**
+ * Animates expansion or collapse of the container.
+ *
+ * @param {boolean} bShow True if container should be expanded, false if
+ *                        container should be collapsed
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._toggleContainer = function(bShow) {
+    // Implementer has container always open so don't mess with it
+    if(this.alwaysShowContainer) {
+        // Fire these events to give implementers a hook into the container
+        // being populated and being emptied
+        if(bShow) {
+            this.containerExpandEvent.fire(this);
+        }
+        else {
+            this.containerCollapseEvent.fire(this);
+        }
+        this._bContainerOpen = bShow;
+        return;
+    }
+
+    var oContainer = this._oContainer;
+    // Container is already closed
+    if (!bShow && !this._bContainerOpen) {
+        oContainer._oContent.style.display = "none";
+        return;
+    }
+
+    // If animation is enabled...
+    var oAnim = this._oAnim;
+    if (oAnim && oAnim.getEl() && (this.animHoriz || this.animVert)) {
+        // If helpers need to be collapsed, do it right away...
+        // but if helpers need to be expanded, wait until after the container expands
+        if(!bShow) {
+            this._toggleContainerHelpers(bShow);
+        }
+
+        if(oAnim.isAnimated()) {
+            oAnim.stop();
+        }
+
+        // Clone container to grab current size offscreen
+        var oClone = oContainer._oContent.cloneNode(true);
+        oContainer.appendChild(oClone);
+        oClone.style.top = "-9000px";
+        oClone.style.display = "block";
+
+        // Current size of the container is the EXPANDED size
+        var wExp = oClone.offsetWidth;
+        var hExp = oClone.offsetHeight;
+
+        // Calculate COLLAPSED sizes based on horiz and vert anim
+        var wColl = (this.animHoriz) ? 0 : wExp;
+        var hColl = (this.animVert) ? 0 : hExp;
+
+        // Set animation sizes
+        oAnim.attributes = (bShow) ?
+            {width: { to: wExp }, height: { to: hExp }} :
+            {width: { to: wColl}, height: { to: hColl }};
+
+        // If opening anew, set to a collapsed size...
+        if(bShow && !this._bContainerOpen) {
+            oContainer._oContent.style.width = wColl+"px";
+            oContainer._oContent.style.height = hColl+"px";
+        }
+        // Else, set it to its last known size.
+        else {
+            oContainer._oContent.style.width = wExp+"px";
+            oContainer._oContent.style.height = hExp+"px";
+        }
+
+        oContainer.removeChild(oClone);
+        oClone = null;
+
+    	var oSelf = this;
+    	var onAnimComplete = function() {
+            // Finish the collapse
+    		oAnim.onComplete.unsubscribeAll();
+
+            if(bShow) {
+                oSelf.containerExpandEvent.fire(oSelf);
+            }
+            else {
+                oContainer._oContent.style.display = "none";
+                oSelf.containerCollapseEvent.fire(oSelf);
+            }
+            oSelf._toggleContainerHelpers(bShow);
+     	};
+
+        // Display container and animate it
+        oContainer._oContent.style.display = "block";
+        oAnim.onComplete.subscribe(onAnimComplete);
+        oAnim.animate();
+        this._bContainerOpen = bShow;
+    }
+    // Else don't animate, just show or hide
+    else {
+        if(bShow) {
+            oContainer._oContent.style.display = "block";
+            this.containerExpandEvent.fire(this);
+        }
+        else {
+            oContainer._oContent.style.display = "none";
+            this.containerCollapseEvent.fire(this);
+        }
+        this._toggleContainerHelpers(bShow);
+        this._bContainerOpen = bShow;
+   }
+
+};
+
+/**
+ * Toggles the highlight on or off for an item in the container, and also cleans
+ * up highlighting of any previous item.
+ *
+ * @param {object} oNewItem New The &lt;li&gt; element item to receive highlight
+ *                              behavior
+ * @param {string} sType "mouseover" will toggle highlight on, and "mouseout"
+ *                       will toggle highlight off.
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._toggleHighlight = function(oNewItem, sType) {
+    var sHighlight = this.highlightClassName;
+    if(this._oCurItem) {
+        // Remove highlight from old item
+        YAHOO.util.Dom.removeClass(this._oCurItem, sHighlight);
+    }
+
+    if((sType == "to") && sHighlight) {
+        // Apply highlight to new item
+        YAHOO.util.Dom.addClass(oNewItem, sHighlight);
+        this._oCurItem = oNewItem;
+    }
+};
+
+/**
+ * Toggles the pre-highlight on or off for an item in the container.
+ *
+ * @param {object} oNewItem New The &lt;li&gt; element item to receive highlight
+ *                              behavior
+ * @param {string} sType "mouseover" will toggle highlight on, and "mouseout"
+ *                       will toggle highlight off.
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._togglePrehighlight = function(oNewItem, sType) {
+    if(oNewItem == this._oCurItem) {
+        return;
+    }
+
+    var sPrehighlight = this.prehighlightClassName;
+    if((sType == "mouseover") && sPrehighlight) {
+        // Apply prehighlight to new item
+        YAHOO.util.Dom.addClass(oNewItem, sPrehighlight);
+    }
+    else {
+        // Remove prehighlight from old item
+        YAHOO.util.Dom.removeClass(oNewItem, sPrehighlight);
+    }
+};
+
+/**
+ * Updates the text input box value with selected query result. If a delimiter
+ * has been defined, then the value gets appended with the delimiter.
+ *
+ * @param {object} oItem The &lt;li&gt; element item with which to update the value
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._updateValue = function(oItem) {
+    var oTextbox = this._oTextbox;
+    var sDelimChar = (this.delimChar) ? this.delimChar[0] : null;
+    var sSavedQuery = this._sSavedQuery;
+    var sResultKey = oItem._sResultKey;
+    oTextbox.focus();
+
+    // First clear text field
+    oTextbox.value = "";
+    // Grab data to put into text field
+    if(sDelimChar) {
+        if(sSavedQuery) {
+            oTextbox.value = sSavedQuery;
+        }
+        oTextbox.value += sResultKey + sDelimChar;
+        if(sDelimChar != " ") {
+            oTextbox.value += " ";
+        }
+    }
+    else { oTextbox.value = sResultKey; }
+
+    // scroll to bottom of textarea if necessary
+    if(oTextbox.type == "textarea") {
+        oTextbox.scrollTop = oTextbox.scrollHeight;
+    }
+
+    // move cursor to end
+    var end = oTextbox.value.length;
+    this._selectText(oTextbox,end,end);
+
+    this._oCurItem = oItem;
+};
+
+/**
+ * Selects a result item from the container
+ *
+ * @param {object} oItem The selected &lt;li&gt; element item
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._selectItem = function(oItem) {
+    this._bItemSelected = true;
+    this._updateValue(oItem);
+    this.itemSelectEvent.fire(this, oItem, oItem._oResultData);
+    this._clearList();
+};
+
+/**
+ * For values updated by type-ahead, the right arrow key jumps to the end
+ * of the textbox, otherwise the container is closed.
+ *
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._jumpSelection = function() {
+    if(!this.typeAhead) {
+        return;
+    }
+    else {
+        this._clearList();
+    }
+};
+
+/**
+ * Triggered by up and down arrow keys, changes the current highlighted
+ * &lt;li&gt; element item. Scrolls container if necessary.
+ *
+ * @param {number} nKeyCode Code of key pressed
+ * @private
+ */
+YAHOO.widget.AutoComplete.prototype._moveSelection = function(nKeyCode) {
+    if(this._bContainerOpen) {
+        // Determine current item's id number
+        var oCurItem = this._oCurItem;
+        var nCurItemIndex = -1;
+
+        if (oCurItem) {
+            nCurItemIndex = oCurItem._nItemIndex;
+        }
+
+        var nNewItemIndex = (nKeyCode == 40) ?
+                (nCurItemIndex + 1) : (nCurItemIndex - 1);
+
+        // Out of bounds
+        if (nNewItemIndex < -2 || nNewItemIndex >= this._nDisplayedItems) {
+            return;
+        }
+
+        if (oCurItem) {
+            // Unhighlight current item
+            this._toggleHighlight(oCurItem, "from");
+            this.itemArrowFromEvent.fire(this, oCurItem);
+        }
+        if (nNewItemIndex == -1) {
+           // Go back to query (remove type-ahead string)
+            if(this.delimChar && this._sSavedQuery) {
+                if (!this._textMatchesOption()) {
+                    this._oTextbox.value = this._sSavedQuery;
+                }
+                else {
+                    this._oTextbox.value = this._sSavedQuery + this._sCurQuery;
+                }
+            }
+            else {
+                this._oTextbox.value = this._sCurQuery;
+            }
+            this._oCurItem = null;
+            return;
+        }
+        if (nNewItemIndex == -2) {
+            // Close container
+            this._clearList();
+            return;
+        }
+
+        var oNewItem = this._aListItems[nNewItemIndex];
+
+        // Scroll the container if necessary
+        var oContent = this._oContainer._oContent;
+        var scrollOn = ((YAHOO.util.Dom.getStyle(oContent,"overflow") == "auto") ||
+            (YAHOO.util.Dom.getStyle(oContent,"overflowY") == "auto"));
+        if(scrollOn && (nNewItemIndex > -1) &&
+        (nNewItemIndex < this._nDisplayedItems)) {
+            // User is keying down
+            if(nKeyCode == 40) {
+                // Bottom of selected item is below scroll area...
+                if((oNewItem.offsetTop+oNewItem.offsetHeight) > (oContent.scrollTop + oContent.offsetHeight)) {
+                    // Set bottom of scroll area to bottom of selected item
+                    oContent.scrollTop = (oNewItem.offsetTop+oNewItem.offsetHeight) - oContent.offsetHeight;
+                }
+                // Bottom of selected item is above scroll area...
+                else if((oNewItem.offsetTop+oNewItem.offsetHeight) < oContent.scrollTop) {
+                    // Set top of selected item to top of scroll area
+                    oContent.scrollTop = oNewItem.offsetTop;
+
+                }
+            }
+            // User is keying up
+            else {
+                // Top of selected item is above scroll area
+                if(oNewItem.offsetTop < oContent.scrollTop) {
+                    // Set top of scroll area to top of selected item
+                    this._oContainer._oContent.scrollTop = oNewItem.offsetTop;
+                }
+                // Top of selected item is below scroll area
+                else if(oNewItem.offsetTop > (oContent.scrollTop + oContent.offsetHeight)) {
+                    // Set bottom of selected item to bottom of scroll area
+                    this._oContainer._oContent.scrollTop = (oNewItem.offsetTop+oNewItem.offsetHeight) - oContent.offsetHeight;
+                }
+            }
+        }
+
+        this._toggleHighlight(oNewItem, "to");
+        this.itemArrowToEvent.fire(this, oNewItem);
+        if(this.typeAhead) {
+            this._updateValue(oNewItem);
+        }
+    }
+};
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+/**
+ *