1. 程式人生 > >基於jQuery的autocomplete(自動補全)類

基於jQuery的autocomplete(自動補全)類

最近很多人在群裡求autocomplete類,那我就獻下醜,把自己寫的分享一下:

/*! JQuery autocomplete
 * Author: Vilien
 * Date: 2013-7-12
 *
 * [email protected] {uri:"uri", eachRequest:false, width:0}
 * > 該執行庫引數採用jQuery風格,引數說明如下
 *
 * @param uri
 * > 返回json資料的資源地址,必須,可包含一個自動適配變數:key
 * > 取值示例:{uri: "http://abc.com/auto.jsp?words=:key"}
 * > :key將由JS根據輸入框輸入字元自動解析
 * > uri資源返回的json資料格式必須為 ["字串1","字串2","字串3"...]
 *
 * @param eachRequest
 * > 逐個字元請求資源開關,可省略,預設為false
 * > 當開啟該開關時,使用者每輸入一個字元,都將向伺服器請求一次結果
 * > 關閉該開關(將該值設為false)時,只在輸入第一個字元時向伺服器請求一次,後續輸入將自動過濾
 *
 * @param width
 * > 自動完成顯示寬度,可省略,預設為0 (為零則自動獲取)
 * > 預設狀態下,程式會自動獲取寬度,但也可以用該選項設定一個固定寬度
 */

;(function($){$.fn.extend({

autocomplete: function(options){

    var defaults = {            ///  預設配置引數
        uri         : ":key",   ///< 可返回json資料格式的uri,:key將由JS自動解析(例:http://xx/?s=:key)
        eachRequest : false,    ///< 逐個字元請求開關(預設關閉,即只在輸入第一個字元時向伺服器請求一次)
        width       : 0         ///< 顯示寬度(為零則自動獲取)
    };

    /* -============ 自動完成樣式 ==========-
     * 可根據需要修改
     */
    var style1 = {
        "border": "1px solid #bbb",
        "background-color": "#fff",
        "line-height": "1.2",
        "cursor": "default"
    };

    /* -============ 自動完成滑鼠經過樣式 ==========-
     * 可根據需要修改
     */
    var style2 = {
        "background-color": "#ebebeb"
    };

    // 樣式處理
    if ($("style[id=autocompletecss]").length<1) {
        var styleText = ".AUTOCOMPLETE{"; // 用於封裝style
        for (var i in style1) { styleText += i + ":" + style1[i] + ";"; }
        styleText    += "}.AUTOCOMPLETE p.cur{";
        for (var i in style2) { styleText += i + ":" + style2[i] + ";"; }
        styleText    += "}";
        $("head").append("<style id=\"autocompletecss\" type=\"text/css\">"+styleText+"</style>");
    }

    $(this).each(function(){
        if (!$(this).is(":text")) {return true;}// 檢測選中元素是否是單行輸入框,不是則退出

        // 初始化
        var settings = $.extend({}, defaults, options); // 合併引數
        var _self = $(this);
        _self.prop("autocomplete", "off"); // 關閉系統自動完成

        var list,
            width= settings.width ? settings.width : _self.innerWidth(),
            wrap = $("<div class=\"AUTOCOMPLETE\"></div>").css({
                "position" : "absolute",
                "z-index" : 9999,
                "width" : width,
                "display" : "none",
                "overflow" : "hidden",
                "text-align" : "left"
            });

        _self.after(wrap);

        // 顯示自動完成
        function complete(list, val) {
            wrap.children().remove();
            if (!settings.eachRequest) {
                for (var i in list) {
                    if (list[i].substring(0, val.length) == val) {
                        wrap.append("<p style=\"margin:0;padding:0 5px\">"+list[i]+"</p>");
                    }
                }
            } else {
                for (var i in list) {
                    wrap.append("<p style=\"margin:0;padding:0 5px\">"+list[i]+"</p>");
                }
            }
            var pos = _self.position();
            wrap.css({
                "top" : pos.top + _self.outerHeight(),
                "left" : pos.left
            });
            wrap.find("p").length>0 ? wrap.show() : wrap.hide();
        }

        // 上下鍵效果
        function walkList(code) {
            var pList = wrap.children("p");
            if (!wrap.is(":visible") && pList.length < 1) {
                return false;
            }
            var idx = wrap.children("p.cur").index();
            code === 40 ? idx++ : 0;
            code === 38 ? idx-- : 0;
            idx >= pList.length ? idx = 0 : 0;
            idx < 0 ? idx = pList.length-1 : 0;
            pList.eq(idx).mouseover();
            return true;
        }
        _self.on("keydown",function(e){
            var code = e.keyCode;
            if (code===40 || code===38) {
                walkList(code);
            } else if (code===13) {
                wrap.children("p.cur").click();
            }
            return true;
        });

        _self.on("keyup",function(e){
            var code = e.keyCode,
                val = $(this).val();

            if (code===40 || code===38 || code===13) {
                return true;
            }
            if (val.length === 0) {
                wrap.hide();
                return true;
            }
            if (val.length > 1 && !settings.eachRequest && list) { // 無需請求
                complete(list, val);
            } else {
                $.getJSON(settings.uri.replace(":key", val), function(result){
                    list = result;
                    complete(list, val);
                })
            }
        });

        $("body").on("click",function(e){
            wrap.hide();
        });

        wrap.on("click", "p", function(){
            _self.val($(this).text());
        });

        wrap.on("mouseover", "p", function(){
            $(this).addClass("cur").siblings().removeClass("cur");
        });

        wrap.on("mouseout", function(){
            $(this).children("p").removeClass("cur");
        });

    });
}

})})(jQuery);

使用方法:

<input id="auto" type="text" />
<script type="text/javascript">
$("#auto").autocomplete({uri:"http://www.mysite.com/autocomplete.php?word=:key"});
</script>