日期:2014-05-16  浏览次数:20385 次

JS-自动提示组件
注:源自Ajax实战

实现自动提示功能:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
    <head>
        <title>Type Ahead</title>
        <%@ include file="/views/js/importjs.jsp" %>
        <script type="text/javascript">
            
            window.onload = function(){
                var elemSpan = document.createElement("span");
                elemSpan.id = "spanOutput";
                elemSpan.className = "spanTextDropdown";
                document.body.appendChild(elemSpan);
                
                /* 用来给文本框设置属性,用定制的对象给这个属性赋值,这样就能够在整个脚本中引用它来获取值,而不是使用全局变量来获取值 */
                document.getElementById('txtUserInput').obj = SetProperties(document.getElementById('txtUserInput'), $('txtUserValue'), 'TypeAheadAction-getContent.action', true, true, true, true, "No matching Data", false, null);
            };
            
            /**
             * 将属性分配给对象
             * @param {Object} xElem 要分配输入前提示功能的文本框
             * @param {Object} xHidden 用来保存值的hidden元素
             * @param {Object} xserverCode 服务器端URL
             * @param {Object} xignoreCase 搜索过程中忽略大小写?
             * @param {Object} xmatchAnywhere 字符串中匹配任意位置的文本?
             * @param {Object} xmatchTextBoxWidth 匹配文本框宽度?
             * @param {Object} xshowNoMatchMessage 显示无匹配消息?
             * @param {Object} xnoMatchingDataMessage 用于显示的消息
             * @param {Object} xuseTimeout 选项显示一段时间后是否隐藏?
             * @param {Object} xtheVisibleTime span保持打开的时间
             */
            function SetProperties(xElem, xHidden, xserverCode, xignoreCase, xmatchAnywhere, xmatchTextBoxWidth, xshowNoMatchMessage, xnoMatchingDataMessage, xuseTimeout, xtheVisibleTime){
            
                /**
                 * 对于xignoreCase,xmatchAnywhere的处理,没有在属性中保持布尔值,而是保存了等价的正则表达式
                 * 在正则表达式中使用i来忽略大小写,使用^来匹配字符串的开始位置
                 * 在这里设置正则表达式参数,而不是在每次调用函数时使用if语句,对我们来说更加容易些
                 */
                var props = {
                    elem: xElem,
                    hidden: xHidden,
                    serverCode: xserverCode,
                    regExFlags: ((xignoreCase) ? "i" : ""),
                    regExAny: ((xmatchAnywhere) ? "" : "^"),
                    matchAnywhere: xmatchAnywhere,
                    matchTextBoxWidth: xmatchTextBoxWidth,
                    theVisibleTime: xtheVisibleTime,
                    showNoMatchMessage: xshowNoMatchMessage,
                    noMatchingDataMessage: xnoMatchingDataMessage,
                    useTimeout: xuseTimeout
                };
                /* 将事件处理函数分配给文本框 */
                AddHandler(xElem);
                return props;
            }
            /**
             * 附加事件处理函数,监听用户的输入、是否离开了文本框
             */
            function AddHandler(objText){
                /* 键盘按键释放 */
                objText.onkeyup = GiveOptions;
                objText.onblur = function(){
                    if (this.obj.useTimeout) 
                        StartTimeout();
                }
                
                /* Opera浏览器出发onkeyup事件处理函数的方式与其他浏览器不同。
                 * 当触发onkeyup事件时,Opera不会再包括当前按键的文本框中显示值
                 * 我们为Opera添加onkeypress事件处理函数纠正了这个问题
                 */
                if (Browser.isOpera) {
                    objText.onkeypress = GiveOptions;
                }
            }
            
            
            var arrOptions = new Array();/* 从服务器查询中获取的所有可用选项 */
            var strLastValue = "";/* 文本框中包含的最后的字符串 */
            var bMadeRequest;/* 请求是否已经发送到服务器,而不必持续发送附加的请求,该标志正对快速打字员,这样我们就不必操心使用像Google那样的超时设置了 */
            var theTextBox;/* 保存对拥有焦点的文本框的引用 */
            var objLastActive;/* 最后激活的文本框 ,如果用户切换了文本框,这个变量将用来确定数据集是否需要重新刷新。在一个拥有多个文本框的窗口中实现这个解决方案,就需要知道哪一个文本框拥有焦点 */
            var currentValueSelected = -1;/* 作用于选择列表的selectedIndex类似,-1表示没有选项被选中 */
            var bNoResults = false;/* 是否有结果?这样我们就不必费心去试图找到任何结果了 */
            var isTi