文章目录
- 下拉框搜索分页功能开发
- 功能
- 使用
- 源码和Demo(点个赞再走咯)
- test.html
- searchable-select.css
- searchserver-select.js
下拉框搜索分页功能开发
最近需要开发一个下拉框从服务器通过Ajax请求搜索数据库并且分页的组件,源码和demo放在下面可以直接使用
功能由searchable-select改造而成
功能
- 点击下拉框,自动聚焦输入框
- 上下键可以选中数据,选中数据后回车填值,关闭下拉框
- 输入框输入值后按下回车、点击查询按钮,触发搜索事件
- 分页,由于组件空间有限仅显示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 = pageIndexres.pageSize = pageSizeres.itemCount = 105res.data = dataList//返回一个Promisereturn new Promise(function(resolve, reject){//当异步代码执行成功时,我们会调用resolve, 当异步代码失败时就会调用rejectsetTimeout(function () {resolve(res); //100ms后,代码正常返回数据!},100)});
});
源码和Demo(点个赞再走咯)
以下效果为demo,需要自行引入jquery
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 = pageIndexres.pageSize = pageSizeres.itemCount = 105res.data = dataListreturn new Promise(function(resolve, reject){//当异步代码执行成功时,我们会调用resolve, 当异步代码失败时就会调用rejectsetTimeout(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.datalet records = pager.datafor (let i = 0; i < records.length; i++) {dataList.push({value:records[i].portCode,label:records[i].displayName})}res.pageIndex = pager.pageIndexres.pageSize = pager.pageSizeres.itemCount = pager.itemCountres.data = dataListresolve(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 = $('<div tabindex="0" class="searchable-select"></div>');this.holder = $('<div class="searchable-select-holder"></div>');this.dropdown = $('<div class="searchable-select-dropdown searchable-select-hide"></div>');this.input = $('<input type="text" class="searchable-select-input" style="width: 80%" />');this.queryBtn = $('<input type="button" class="queryBtn" value="查询" />');this.inputOldValue = '';//控制查询频率this.items = $('<div class="searchable-select-items"></div>');this.caret = $('<span class="searchable-select-caret"></span>');this.clear = $('<span class="searchable-select-clear">×</span>');this.scrollPart = $('<div class="searchable-scroll"></div>');this.pager = $('<div class="searchable-pager"></div>');//当前高亮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 = $('<span class="searchable-loading">loading...</span>')_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 = $('<div class="searchable-select-item" data-value="'+dataList[i].value+'">'+dataList[i].label+'</div>');//如果选中的和当前的相等,则高亮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 = $('<span class="searchable-loading" style="background-color: #e28a8a">加载失败,请稍后</span>')_this.pager.append(loading);setTimeout(function () {$(loading).remove()},3000)})},//渲染分页内容buildPager:function(pager){let _this = this;let thisPager = _this.pager;//清空内容$(thisPager).html('')$(thisPager).append(`<span class="searchable-pager-item fl">共${pager.itemCount}条</span>`)if(pager.itemCount>0){let pageCount = Math.ceil(pager.itemCount / pager.pageSize)//渲染5个页码,最好是单数let showPageBtnCount = 5;let min = pager.pageIndexlet max = pager.pageIndexwhile (max - min + 1 < showPageBtnCount){if(min>1){min -- ;}if(max<pageCount){max++;}if(min===1 && max===pageCount){break;}}let items = $('<div class="fr"></div>')for (let i = min; i <= max; i++) {let itemif(pager.pageIndex===i){item = $(`<a class="searchable-pager-item searchable-pager-item-active">${i}</a>`);}else{item = $(`<a class="searchable-pager-item">${i}</a>`);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');},//取消hovercancelHover: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 = falsethis.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);
点个赞再走咯