html给下拉框添加搜索、分页功能(通过ajax从服务器获取搜索数据)

文章目录

  • 下拉框搜索分页功能开发
    • 功能
    • 使用
    • 源码和Demo(点个赞再走咯)
      • test.html
      • searchable-select.css
      • searchserver-select.js

下拉框搜索分页功能开发

最近需要开发一个下拉框从服务器通过Ajax请求搜索数据库并且分页的组件,源码和demo放在下面可以直接使用
功能由searchable-select改造而成

html给下拉框添加搜索、分页功能(通过ajax从服务器获取搜索数据)_第1张图片

功能

  • 点击下拉框,自动聚焦输入框
  • 上下键可以选中数据,选中数据后回车填值,关闭下拉框
  • 输入框输入值后按下回车、点击查询按钮,触发搜索事件
  • 分页,由于组件空间有限仅显示5页

使用

源码和demo都已经在下面给出了,自取,demo包括ajax获取数据

1.引入组件

<script src="searchserver-select.js">script>
<link href="searchable-select.css" rel="stylesheet">

2.添加input输入框

<input id="b">

3.创建组件

自定义数据获取规则,以下为获取测试数据,真实开发Ajax demo下面有给出

//传入一个function,keyWord表示搜索框的值,另外两个不必多说
$('#b1').searchServerSelect({}, function (keyWord, pageIndex = 1, pageSize = 10) {
    let res = {}
    //以下为测试数据
    let dataList = []
    for (let i = 0; i < 10; i++) {
        dataList.push({value: keyWord + i, label: keyWord + i})
    }
    res.pageIndex = pageIndex
    res.pageSize = pageSize
    res.itemCount = 105
    res.data = dataList
    //返回一个Promise
    return new Promise(function(resolve, reject){
        //当异步代码执行成功时,我们会调用resolve, 当异步代码失败时就会调用reject
        setTimeout(function () {
            resolve(res); //100ms后,代码正常返回数据!
        },100)
    });
});

源码和Demo(点个赞再走咯)

以下效果为demo,需要自行引入jquery

html给下拉框添加搜索、分页功能(通过ajax从服务器获取搜索数据)_第2张图片

test.html

DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>下拉框搜索title>
    <script src="../jquery.min.js">script>
    <script src="searchserver-select.js">script>
    <link href="searchable-select.css" rel="stylesheet">
    <script type="text/javascript">
        //下拉搜索分页框
        $(function () {
            $('#b').searchServerSelect({}, function (keyWord, pageIndex = 1, pageSize = 10) {
                //服务器获取数据
                return getData(keyWord,pageIndex,pageSize)
            });
            $('#b1').searchServerSelect({}, function (keyWord, pageIndex = 1, pageSize = 10) {
                let res = {}
                //测试数据
                let dataList = []
                for (let i = 0; i < 10; i++) {
                    dataList.push({value: keyWord + i, label: keyWord + i})
                }
                res.pageIndex = pageIndex
                res.pageSize = pageSize
                res.itemCount = 105
                res.data = dataList
                return new Promise(function(resolve, reject){
                    //当异步代码执行成功时,我们会调用resolve, 当异步代码失败时就会调用reject
                    setTimeout(function () {
                        resolve(res); //代码正常执行!
                    },100)
                });
            });
        });
        //TODO 自定义下拉框数据
        function getData(keyWord,pageIndex = 1,pageSize = 10) {
            console.log("以下为测试数据获取方式,请自定义数据")
            let promise1 = $.ajax({
                url: "/dict/baseShipPort",
                data: {name:keyWord,current:pageIndex,pageSize:pageSize},
                type: "post",
                timeout:5000, //设置超时的时间
            })
            return new Promise(function (resolve, reject) {
                promise1.then(function (data) {
                    if (data.success) {
                        let res = {}
                        let dataList = []
                        let pager = data.data
                        let records = pager.data
                        for (let i = 0; i < records.length; i++) {
                            dataList.push({value:records[i].portCode,label:records[i].displayName})
                        }
                        res.pageIndex = pager.pageIndex
                        res.pageSize = pager.pageSize
                        res.itemCount = pager.itemCount
                        res.data = dataList
                        resolve(res)
                    }else{
                        reject(data)
                    }
                },function (data) {
                    console.log("以上为测试数据获取方式,请自定义数据")
                    reject(data)
                })
            })

        }
    script>
head>
<body>
<div style="display: flex">

    <div style="width: 240px;margin-left: 20px">
        下拉搜索分页 自定义服务器数据
        <input id="b">
    div>

    <div style="width: 240px;margin-left: 20px">
        下拉搜索分页
        <input id="b1">
        <button type="button" onclick="console.log('值为:'+$('#b1').val())" >获取值button>
    div>
div>

body>
html>

searchable-select.css

/* select */
.fr{
    float: right;
}
.fl{
    float: left;
}
.searchable-select-hide {
    display: none;
}

.searchable-select {
    display: inline-block;
    min-width: 100%;
    font-size: 14px;
    line-height: 1.428571429;
    color: #555;
    vertical-align: middle;
    position: relative;
    outline: none;
    z-index: 9
}

.searchable-select-holder{
    padding: 0 10px;
    background-color: #fff;
    background-image: none;
    border: 1px solid #d9d9d9;
    min-height: 32px;
    line-height: 31px;
    box-sizing: border-box;
    -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
    box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
    -webkit-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
    transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
}

.searchable-select-caret {
    position: absolute;
    width: 0;
    height: 0;
    box-sizing: border-box;
    border-color: #a0a0a0 transparent transparent transparent;
    top: 5px;
    bottom: 0;
    border-style: solid;
    border-width: 5px;
    margin: auto;
    right: 5px;
}
.searchable-select-clear {
    position: absolute;
    box-sizing: border-box;
    top: 5px;
    bottom: 0;
    margin: auto;
    right: 18px;
    cursor: pointer;
    font-size: 15px;
}

.searchable-select-dropdown {
    position: absolute;
    background-color: #fff;
    border: 1px solid #ccc;
    border-bottom-left-radius: 4px;
    border-bottom-right-radius: 4px;
    padding: 4px;
    border-top: none;
    top: 28px;
    left: 0;
    right: 0;
}

.searchable-select-input {
    margin-top: 5px;
    border: 1px solid #ccc;
    outline: none;
    padding: 4px;
    width: 100%;
    box-sizing: border-box;
}
.queryBtn{
    border: none;
    width: 19%;
    margin-left: 1%;
    background-color: #3f86d8;
    color: white;
    cursor: pointer;
    padding: 4px 0;
}

.searchable-scroll {
    margin-top: 4px;
    position: relative;
}

.searchable-scroll.has-privious {
    padding-top: 16px;
}

.searchable-scroll.has-next {
    padding-bottom: 16px;
}

.searchable-has-privious {
    top: 0;
}

.searchable-has-next {
    bottom: 0;
}

.searchable-has-privious, .searchable-has-next {
    height: 16px;
    left: 0;
    right: 0;
    position: absolute;
    text-align: center;
    z-index: 10;
    background-color: white;
    line-height: 8px;
    cursor: pointer;
}

.searchable-select-items {
    max-height: 400px;
    overflow-y: scroll;
    position: relative;
}

.searchable-select-items::-webkit-scrollbar {
    display: none;
}

.searchable-select-item {
    padding: 5px 5px;
    cursor: pointer;
    min-height: 30px;
    box-sizing: border-box;
    transition: all 1s ease 0s;
}

.searchable-select-item.selected{
    background: #3f86d8!important;
    color: white;
}
.searchable-select-item.hover {
    background: #9abde5;
    color: white;
}
/* select */

/*2023 0912*/
/*新增分页功能*/
.searchable-pager{
    position: relative;
    width: 100%;
    height: 20px;
}
.searchable-pager-item{
    background-color: rgba(248, 248, 248, 0.9);
    border-radius: 2px;
    color: black;
    padding: 3px 4px;
    line-height: 20px;
    border: none;
    outline: none;
    cursor: pointer;
    margin-right: 3px;
    display: inline-block;
}
.searchable-pager-item:hover{
    background-color: #d2cfcf
}
.searchable-pager-item-active{
    background-color: rgb(0,115,220);
    color: white;
}
.searchable-loading{
    position: absolute;
    top: -24px;
    right: 0;
    z-index: 999;
    background-color: #3f86d8;
    color: white;
}


searchserver-select.js

/**
 * 下拉搜索框+分页功能,从服务器获取数据
 * @Date 2023-09-12
 * @author www
 */
(function($){
    $.expr[":"].searchableSelectContains = $.expr.createPseudo(function(arg) {
        return function( elem ) {
            return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
        };
    });
    $.searchServerSelect = function(element, options) {
        this.element = element;
        this.options = options || {};
        this.init();

        var _this = this;

        this.searchableElement.click(function(event){
            // event.stopPropagation();
            _this.show();
        }).on('keydown', function(event){
            if (event.which === 13 || event.which === 40 || event.which == 38){
                event.preventDefault();
                _this.show();
            }
        });

        $(document).on('click', null, function(event){
            if(_this.searchableElement.has($(event.target)).length === 0)
                _this.hide();
        });

        //TODO 输入框变化事件
        this.input.on('keydown', function(event){
            event.stopPropagation();
            if(event.which === 13){         //enter
                //按下回车,如果没有选中的项,则查询,否则选中然后关闭
                if(!_this.hasCurrentHoverItem()){
                    //查询
                    _this.filter();
                } else {
                    //选中
                    _this.selectCurrentHoverItem();
                    _this.hide();
                }
            } else if (event.which == 27) { //ese
                _this.hide();
            } else if (event.which == 40) { //down
                _this.hoverNextItem();
            } else if (event.which == 38) { //up
                _this.hoverPreviousItem();
            }
        }).on('keyup', function(event){
            if(_this.inputOldValue === _this.input.val()){ //防止按下其他键带来的影响
                return;
            }
            //输入内容变化,那么再次回车应该触发搜索而不是选中
            if(event.which != 13 && event.which != 27 && event.which != 38 && event.which != 40){
                _this.cancelHover()
            }
        })
    }

    var $sS = $.searchServerSelect;

    $sS.fn = $sS.prototype = {
        version: '0.0.1'
    };

    $sS.fn.extend = $sS.extend = $.extend;

    $sS.fn.extend({
        //初始化
        init: function(){
            var _this = this;
            this.element.hide();
            this.searchableElement = $('
'
); this.holder = $('
'
); this.dropdown = $('
'
); this.input = $(''); this.queryBtn = $(''); this.inputOldValue = '';//控制查询频率 this.items = $('
'
); this.caret = $(''); this.clear = $('×'); this.scrollPart = $('
'
); this.pager = $('
'
); //当前高亮 this.currentHoverItem = false; //当前选中 this.currentSelectedItem = false; this.queryBtn.click(function () { _this.filter(true) }) this.clear.click(function (event) { event.stopPropagation(); _this.cancelSelected() }) this.dropdown.append(this.input); this.dropdown.append(this.queryBtn);//查询按钮 this.dropdown.append(this.scrollPart); this.scrollPart.append(this.items); this.scrollPart.append(this.pager); this.searchableElement.append(this.caret); this.searchableElement.append(this.clear); this.searchableElement.append(this.holder); this.searchableElement.append(this.dropdown); this.element.after(this.searchableElement); this.buildItems(); }, //TODO 触发搜索 filter: function(btnClick=false){ let _this = this; if(!btnClick && _this.inputOldValue === _this.input.val()){ //防止按下其他键带来的影响 return; } _this.inputOldValue = _this.input.val() _this.buildItems(); }, //TODO 初始化添加项 buildItems: function(pageIndex = 1,pageSize = 10){ var _this = this; let keyword = _this.input.val(); let promise = _this.getSelectData(keyword,pageIndex,pageSize) let loading = $('loading...') _this.pager.append(loading); promise.then(function (data) {//回调成功 //清空原有内容 $(_this.items).html(''); _this.buildPager(data) let dataList = data.data _this.currentHoverItem = false; if(dataList && dataList.length>0){ for (let i = 0; i < dataList.length; i++) { var item = $('
+dataList[i].value+'">'+dataList[i].label+'
'
); //如果选中的和当前的相等,则高亮 if(_this.currentSelectedItem && $(_this.currentSelectedItem).html() === dataList[i].label){ _this.selectItem(item); _this.hoverItem(item); } item.on('mouseenter', function(){ $(this).addClass('hover'); }).on('mouseleave', function(){ $(this).removeClass('hover'); }).click(function(event){ event.stopPropagation(); _this.selectItem($(this)); _this.hide(); }); _this.items.append(item); } } },function (err) { console.log("服务器获取数据失败! ",err) $(loading).remove() //失败提示 loading = $('加载失败,请稍后') _this.pager.append(loading); setTimeout(function () { $(loading).remove() },3000) }) }, //渲染分页内容 buildPager:function(pager){ let _this = this; let thisPager = _this.pager; //清空内容 $(thisPager).html('') $(thisPager).append(`${pager.itemCount}`) if(pager.itemCount>0){ let pageCount = Math.ceil(pager.itemCount / pager.pageSize) //渲染5个页码,最好是单数 let showPageBtnCount = 5; let min = pager.pageIndex let max = pager.pageIndex while (max - min + 1 < showPageBtnCount){ if(min>1){ min -- ; }if(max<pageCount){ max++; } if(min===1 && max===pageCount){ break; } } let items = $('
'
) for (let i = min; i <= max; i++) { let item if(pager.pageIndex===i){ item = $(`${i}`); }else{ item = $(`${i}`); item.click(function(event){ //取消原来的点击事件,防止弹框消失 event.stopPropagation(); _this.buildItems(i,pager.pageSize) }); } $(items).append(item) } $(thisPager).append(items) } }, //TODO 获取数据,服务器 getSelectData:function(keywords,pageIndex = 1,pageSize = 10){ console.log(`getSelectData(${keywords},${pageIndex},${pageSize}) `) if(!this.options.getDataFunction){ alert("未设置数据获取逻辑:getDataFunction") } return this.options.getDataFunction(keywords,pageIndex,pageSize); }, show: function(){ this.dropdown.removeClass('searchable-select-hide'); this.input.focus(); this.status = 'show'; this.dropdown.css('z-index', 100); //打开下拉列表时调高z-index层级 }, hide: function(){ if(!(this.status === 'show')) return; if(this.items.find(':not(.searchable-select-hide)').length === 0) this.input.val(''); this.dropdown.addClass('searchable-select-hide'); this.searchableElement.trigger('focus'); this.status = 'hide'; this.dropdown.css('z-index', 1); //关闭下拉列表时恢复z-index层级 }, //高亮第一个 hoverFirstNotHideItem: function(){ this.hoverItem(this.items.find('.searchable-select-item:not(.searchable-select-hide)').first()); }, //选中高亮 selectCurrentHoverItem: function(){ if(!this.currentHoverItem.hasClass('searchable-select-hide')) this.selectItem(this.currentHoverItem); }, //高亮覆盖,向前加载 hoverPreviousItem: function(){ if(!this.hasCurrentHoverItem()) this.hoverFirstNotHideItem(); else{ var prevItem = this.currentHoverItem.prevAll('.searchable-select-item:not(.searchable-select-hide):first') if(prevItem.length > 0) this.hoverItem(prevItem); } }, //高亮覆盖,向后加载 hoverNextItem: function(){ if(!this.hasCurrentHoverItem()) this.hoverFirstNotHideItem(); else{ var nextItem = this.currentHoverItem.nextAll('.searchable-select-item:not(.searchable-select-hide):first') if(nextItem.length > 0) this.hoverItem(nextItem); } }, hasCurrentSelectedItem: function(){ return this.currentSelectedItem && this.currentSelectedItem.length > 0; }, selectItem: function(item){ console.log("selectItem:",$(item)[0].innerHTML) if(this.hasCurrentSelectedItem()) this.currentSelectedItem.removeClass('selected'); this.currentSelectedItem = item; item.addClass('selected'); this.hoverItem(item); this.holder.text(item.text()); var value = item.data('value'); this.holder.data('value', value); this.element.val(value); if(this.options.afterSelectItem){ this.options.afterSelectItem.apply(this); } }, hasCurrentHoverItem: function(){ return this.currentHoverItem && this.currentHoverItem.length > 0; }, hoverItem: function(item){ if(this.hasCurrentHoverItem()) this.currentHoverItem.removeClass('hover'); if(item.outerHeight() + item.position().top > this.items.height()) this.items.scrollTop(this.items.scrollTop() + item.outerHeight() + item.position().top - this.items.height()); else if(item.position().top < 0) this.items.scrollTop(this.items.scrollTop() + item.position().top); this.currentHoverItem = item; item.addClass('hover'); }, //取消hover cancelHover:function(){ if(this.hasCurrentHoverItem()){ this.currentHoverItem.removeClass('hover'); this.currentHoverItem = false; } }, //取消选中 cancelSelected:function () { if(this.hasCurrentSelectedItem()){ this.currentSelectedItem.removeClass('selected'); this.element.val('') this.currentSelectedItem = false this.holder.text('') this.holder.data('value', ''); } } }); $.fn.searchServerSelect = function(options,getDataFunction){ options.getDataFunction = getDataFunction; this.each(function(){ var sS = new $sS($(this), options); }); return this; }; })(jQuery);

点个赞再走咯

你可能感兴趣的:(前端,html,ajax,服务器)