自定义带搜索框的下拉列表插件

最近项目所需,开发了一个附带搜索框的下拉列表插件,在搜索框中输入关键字的同时,捕捉键盘按键释放事件,更新下拉列表显示内容。

jquery插件开发参考:
http://blog.csdn.net/xyr05288/article/details/51094644

一. 插件源文件

css源文件:

.my-dropdownContainer{
    position: relative;
    height: 30px;
    width: 200px; 
    background: #fff;
    /* z-index:20; */
}
.my-dropdownDefault{
    border:1px solid #ddd;
    line-height: 28px;
    text-indent: 0.5em;
    border-radius:5px;
}
.my-dropdown-menu-div{
    position: absolute;
    top:100%;
    /*width: 100%;*/
    width:250px;
    left: 0;
    display:none;
    border:1px solid #ddd;
    border-radius:5px;
    padding:5px;
    background: #fff;
    overflow: auto;
    /*height: 150px;*/
    max-height:150px;

    z-index:20;

}
.my-dropdown-menu{
    padding-left:0px;
    background: #fff;
    margin-top:5px;
}
.my-dropdown-menu li{
    /*line-height: 24px;*/
    list-style:none;
}

.my-dropdown-menu li div.li-div-class:hover{
    background-color: #0078b6;  
    color: #fff;    
}
/* .hoverClass div{
    background-color: #0078b6;  
    color: #fff;    
} */
.arrow{
    width: 0;
    height: 0;
    display: inline-block;
    cursor: pointer;
}
.downArrow{
    position: absolute;
    right: 5px;
    top: 10px;
    border-left: 3.5px solid transparent;
    border-right: 3.5px solid transparent;
    border-top: 7px solid #555;
}
.upArrow{
    position: absolute;
    right: 5px;
    top: 10px;
    border-left: 3.5px solid transparent;
    border-right: 3.5px solid transparent;
    border-bottom: 7px solid #555;
}

.li-div-class{
    position: relative;
    height:45px;
}

.user-image-class{
    position: absolute;
    left: 2px;
    top: 5px;
    height: 30px;
    width: 30px;
}

.user-image-class img{
    height: 30px;
    width: 30px;
}
.user-name-class{
    position: absolute;
    left: 38px;
    top: 5px;
    font-size: 12px;
}
.user-depart-class{
    position: absolute;
    left: 38px;
    top: 20px;
    font-size: 12px;
    /*div只显示一行*/
    width:80%;
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow:hidden;
}

js源文件:

//20170111 自定义下拉列表插件
//20160406 构造对象
var defaultOptions  = {
    listData: [], //直接设置原始数据
    url:"",//通过url动态获取数据
    keyword:"" //url只接受keyword参数
};

var $options = defaultOptions;

$.fn.customeDownList = function(){
        var options = {};
        if(arguments.length == 1){//一个参数
            if(typeof(arguments[0]) == 'object'){//初始化options
                initDownList(this[0],arguments[0]);
            }
        }else if(arguments.length == 2){
            if(typeof(arguments[0]) == 'string' && typeof(arguments[1]) == 'object'){//调用方法
                if(arguments[0] == 'setData'){
                    var ulObj = this.find('.my-dropdown-menu-div').find('.my-dropdown-menu').get(0);
                    setData(ulObj,arguments[1]);
                }
            }
        }


};

function initDownList(obj,options){
        //这里其实就是合并多个对象为一个。这里就是,如果你在调用的时候写了新的参数,就用你新的参数,如果没有写,就用默认的参数。  
        $options = $.extend(defaultOptions,options);
        console.log(obj);

        var dataStr = "";
        var listData = $options.listData;
        var url = $options.url;
        if(url != ""){
            var keyword = $options.keyword;
            listData = getListDataByUrl(url,keyword);
        }
        if(listData != undefined && listData.length>0){
            for(var i=0; i<listData.length; i++){
                dataStr += '<li><div class="li-div-class">'+'<div class="user-image-class"><img src = "'+ listData[i].image  + '"/></div>' 
                        + '<div class="user-name-class">'+ listData[i].name + '</div>'
                        + '<div class="user-depart-class" ' + 'title=' + listData[i].depart + '>'
                        + listData[i].depart + '</div>' 
                        + '</div></li>';
            }
        }

        //插件中动态添加的DOM元素统统用类标识  不要用ID 元素之间的获取借助DOM树结构
        var htmlStr = "";
        htmlStr += '<div class="my-dropdownContainer">';
        htmlStr += '<div class="my-dropdownDefault"></div>';
        htmlStr += '<span class="downArrow arrow"></span>';
        htmlStr += '<div class="my-dropdown-menu-div">';
        //下拉列表输入框的键盘释放事件
        htmlStr += '<input onkeyup="javascript:onkeyupInput(this);" type="text" style="width:100%;height:27px;border:1px solid #ddd;border-radius:5px;" />';
        htmlStr += '<ul class="my-dropdown-menu">';
        htmlStr += dataStr;     
        htmlStr += '</ul>';
        htmlStr += '</div>';
        htmlStr += '</div>';

        obj.innerHTML = htmlStr;

        //箭头的点击事件
        $(".my-dropdownContainer .arrow").unbind("click").click(function(){
            console.log("click obj parent parent: ");
            console.log($(this).parent().parent());
            if($(this).hasClass("downArrow")){
                $(this).siblings(".my-dropdown-menu-div").show();

                //清空输入框 重新初始化下拉列表
                var inputObj = $(this).siblings(".my-dropdown-menu-div").find('input').get(0);
                inputObj.value = "";
                onkeyupInput(inputObj);

                $(this).removeClass("downArrow");
                $(this).addClass("upArrow");
            }else if($(this).hasClass("upArrow")){
                $(this).siblings(".my-dropdown-menu-div").hide();
                $(this).removeClass("upArrow");
                $(this).addClass("downArrow");
            }
        });

       //列表项的点击事件
        $(".my-dropdown-menu li .li-div-class").unbind("click").click(function(){
            var $nameObj = $(this).find('.user-name-class');
            $(this).parent().parent().parent().siblings(".my-dropdownDefault").html($nameObj.html());
            $(this).parent().parent().parent().hide();

            var arrowObj = $(this).parent().parent().parent().siblings(".arrow");
            if(arrowObj.hasClass("upArrow")){
                arrowObj.siblings(".my-dropdown-menu-div").hide();
                arrowObj.removeClass("upArrow");
                arrowObj.addClass("downArrow");
            }
        });

}


function setData(ulObj, data){
    //将选择的值重新拼接为html字符串  添加在ul中
    var htmlStr = "";
    for(var i=0; i<data.length; i++){
        htmlStr += '<li><div class="li-div-class">'+'<div class="user-image-class"><img src = "'+ data[i].image  + '"/></div>' 
        + '<div class="user-name-class">'+ data[i].name   + '</div>'
        + '<div class="user-depart-class" ' + 'title=' + data[i].depart + '>'
        + data[i].depart + '</div>' 
        + '</div></li>';
    }

    ulObj.innerHTML = htmlStr;


    /*$(".li-div-class").mouseover(function(){

        if(!$(this).hasClass("hoverClass")){   
            $(this).addClass("hoverClass");
        }
    });
    $(".li-div-class").mouseout(function(){

        if($(this).hasClass("hoverClass")){    
            $(this).removeClass("hoverClass");
        }
    });*/
    //动态生成的DOM元素click事件需重新绑定
    $(".my-dropdown-menu li .li-div-class").unbind("click").click(function(){

        var $nameObj = $(this).find('.user-name-class');
        $(this).parent().parent().parent().siblings(".my-dropdownDefault").html($nameObj.html());
        $(this).parent().parent().parent().hide();

        var arrowObj = $(this).parent().parent().parent().siblings(".arrow");
        if(arrowObj.hasClass("upArrow")){
            arrowObj.siblings(".my-dropdown-menu-div").hide();
            arrowObj.removeClass("upArrow");
            arrowObj.addClass("downArrow");
        }
    });
}

//必须定义到外面 定义到闭包函数里面时  无法获取
function onkeyupInput(obj){
    var value = obj.value;
    console.log("value: " + value);
    var ulObj = $(obj).siblings(".my-dropdown-menu").get(0);//jquery对象转DOM对象
    console.log(ulObj);
    var liElementArr = ulObj.getElementsByTagName("li");
    console.log("liElementArr: " + liElementArr.length);

    var newValues = [];
    var url = $options.url;

    if(url == ""){
        var listData = $options.listData;
        $.each(listData,function(index,tempValue){

            if(tempValue.indexOf(value) >= 0){
                newValues.push(tempValue);
            }
        });
    }else{
        keyword = value;
        newValues = getListDataByUrl(url,keyword);
    }

    console.log("newValues: ");
    console.log(newValues);

    //将选择的值重新拼接为html字符串  添加在ul中
    setData(ulObj,newValues);
}

function getListDataByUrl(url,keyword){
    var listData = [];
    $.ajax({
        async: false,//同步
        type:"POST",
        url:url,
        dataType:"json",
        data:{
            "keyword":keyword
        },
        error:function(){                   
            alert("列表数据获取失败");              
        },
        success:function(responseInfo){

            if(responseInfo['status'] == 1){        
                alert("列表数据获取失败");
            }  
            if(responseInfo["status"] == 0){
                console.log(responseInfo.data);
                listData = responseInfo.data.listData;

            }
        }//end success
    });

    return listData;
}

html中调用形式:

<!-- html -->
<div id="downListDIV">
</div>
<script text/type="javascript">
    $("#downListDIV").customeDownList({url:'/common/getUserListData'});
</script>

获取选择数据:

var value = $("#downListDIV").find('.my-dropdownDefault').html();

二. 所遇问题
(1)在页面中增加了两个下拉列表组件时,点击第一个组件右边的箭头时,onclick事件会被触发两次,导致下拉列表选项内容无法显示出来。

原因:Click事件 进行了累加绑定,每当我调用一次时,他便增加一次绑定

解决方法: 每次绑定前先解绑

$('#sub').unbind('click').click(function () {
    ...
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值