在实际应用场景中经常会碰到系统自带的select下拉框会不满足客户需求的情况,比如下拉内容太多,用户找不过来,即使按照首字母规则排序后也很难满足客户要求,这时候能有一个输入框输入关键字之后,然后下拉选项出现一些想要的内容就是很不错的选择了
应用技术:html,css,javascript,jquery,ajax,c#,asp.net,sqlserver数据库
1.思路整理
使用input和div代替select控件,通过对input注册聚焦失焦事件控制div的显示隐藏来完成select下拉的模拟,div的内容根据input输入的关键字实时获取数据库相关的信息,点击div的内容将完整的信息填入input中,即完成select的模拟
2.前端效果实现
(1)创建一个input,样式position属性设置为relative,紧跟后面创建一个div,样式position属性设置为absolute,设置1px的边框方便观看,并调整top的值,使其顶端正好处于input底端(默认应该就是这样,不用调整top值),在div内部再创建多个div,填充相关内容,然后对其内部的div都注册上鼠标移入移出事件,用于改变内部div的背景色,再注册一个鼠标按下事件用于把点击的那个内容显示到input中
(2)首先隐藏这个div,然后对input标签注册聚焦失焦事件,聚焦后显示这个div,其次需要注意的是失焦的这个情况,在点击input框触发聚焦后,显示div,接下来有1种情况需要考虑:
用户点击了div中的内容,这时候实际上是先触发input的失焦事件的,但input的失焦是让div隐藏的,所以用户点不到div,也就触发不了div的点击事件,这里我的处理方式是在input的失焦事件中的处理逻辑延时执行,可以使用计时器处理
(3)代码展示
html
<form id="form1" runat="server">
<div>
<input id="select-input" name="select-input" style="position:relative" />
<div id="searchDiv" style="display:none;">
<div name="searchDiv1">111111111111</div>
<div name="searchDiv1">222222222222</div>
<div name="searchDiv1">333333333333</div>
<div name="searchDiv1">444444444444</div>
</div>
</div>
</form>
css
#searchDiv {
border:black 1px solid;
position:absolute;
width:300px;
}
javascript
$(document).on("mouseover","div[name=searchDiv1]",function(){
this.style.backgroundColor='blue';
});
$(document).on("mouseout","div[name=searchDiv1]",function(){
this.style.backgroundColor='white';
});
//这里的作用是当点击下拉内容时,把对应的值赋给文本框,达到select的效果(这里不用做下拉的隐藏,因为当用户点击下拉内容的同时会触发input的失焦blur)
//注意:为什么这里用的是鼠标按下事件onmousedown而不是点击事件onclick,
//点击的触发条件鼠标按下再抬起才会触发, 当鼠标按下时会触发input失焦,会隐藏下拉内容,所以如果注册的是onclick事件,那么很容易点不到下拉内容,所以注册的是鼠标按下时就触发
$(document).on("mousedown","div[name=searchDiv1]",function(){
$("#select-input").val(this.innerText);
});
$("#select-input").on("focus", function () {
$("#searchDiv").show();
})
//失焦后延时10ms执行,避免失焦后searchDiv立即隐藏点不到里面的元素的问题
$("#select-input").on("blur", function () {
setTimeout(function(){
$("#searchDiv").hide();
},"10")
})
(4)效果展示
以上就完成了最简单的自制下拉框的功能,接下来就需要将数据库的内容填充给下拉框,自制下拉框的一个难点就在于避免各个事件的相互影响,如input聚焦后,下拉内容展示,点击下拉内容会先触发input失焦
3.后台数据制作(sqlserver数据库)
CREATE TABLE table1(
tab_id INT IDENTITY(1,1) PRIMARY KEY,
tab_name VARCHAR(100)
)
INSERT INTO table1(tab_name) values('上海浦东新区公司')
INSERT INTO table1(tab_name) values('上海徐汇区公司')
INSERT INTO table1(tab_name) values('上海公司')
INSERT INTO table1(tab_name) values('上海徐汇区公司')
INSERT INTO table1(tab_name) values('南京分公司1')
INSERT INTO table1(tab_name) values('南京分公司2')
INSERT INTO table1(tab_name) values('南京分公司3')
INSERT INTO table1(tab_name) values('南京分公司4')
INSERT INTO table1(tab_name) values('北京分公司1')
INSERT INTO table1(tab_name) values('北京分公司2')
INSERT INTO table1(tab_name) values('北京分公司3')
4.ashx程序编写
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Web;
namespace WebAppTest
{
/// <summary>
/// testHandler 的摘要说明
/// </summary>
public class testHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
//获取数据库操作对象
string constr = "Server=.;integrated security=SSPI;Initial Catalog=testDB";
SqlConnection sqlConnection = new SqlConnection(constr);
sqlConnection.Open();
SqlCommand sqlCommand;
if (context.Request["param"] == "getContentAll")
{
sqlCommand = new SqlCommand("SELECT * FROM table1", sqlConnection);
}
else
{
sqlCommand = new SqlCommand("SELECT * FROM table1 WHERE tab_name LIKE '%"+ context.Request["KeyID"] + "%'", sqlConnection);
}
SqlDataAdapter sda = new SqlDataAdapter(sqlCommand);
DataTable dt = new DataTable();
sda.Fill(dt);
sqlConnection.Close();
context.Response.Write(table2json(dt));
}
public bool IsReusable
{
get
{
return false;
}
}
public static string table2json(DataTable dt)
{
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < dt.Rows.Count; i++)
{
sb.Append("{");
for (int j = 0; j < dt.Columns.Count; j++)
{
if (j == dt.Columns.Count - 1)
{
sb.Append("\"" + dt.Columns[j].Caption + "\":\"" + dt.Rows[i][j].ToString() + "\"");
}
else
{
sb.Append("\"" + dt.Columns[j].Caption + "\":\"" + dt.Rows[i][j].ToString() + "\",");
}
}
if (i == dt.Rows.Count - 1)
{
sb.Append("}");
}
else
{
sb.Append("},");
}
}
sb.Append("]");
return sb.ToString();
}
}
}
5.前端代码
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebFormTest.aspx.cs" Inherits="WebAppTest.WebFormTest" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<style type="text/css">
#searchDiv {
border:black 1px solid;
position:absolute;
width:300px;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<input id="select-input" name="select-input" style="position:relative" />
<div id="searchDiv" style="display:none;">
<div name="searchDiv1">111111111111</div>
<div name="searchDiv1">222222222222</div>
<div name="searchDiv1">333333333333</div>
<div name="searchDiv1">444444444444</div>
</div>
</div>
</form>
</body>
<script src="jquery-3.3.1.min.js" charset="utf-8"></script>
<script type="text/javascript">
//鼠标移入移出的背景色设置
$(document).on("mouseover","div[name=searchDiv1]",function(){
this.style.backgroundColor='blue';
});
$(document).on("mouseout","div[name=searchDiv1]",function(){
this.style.backgroundColor='white';
});
//这里的作用是当点击下拉内容时,把对应的值赋给文本框,达到select的效果(这里不用做下拉的隐藏,因为当用户点击下拉内容的同时会触发input的失焦blur)
//注意:为什么这里用的是鼠标按下事件onmousedown而不是点击事件onclick,
//点击的触发条件鼠标按下再抬起才会触发, 当鼠标按下时会触发input失焦,会隐藏下拉内容,所以如果注册的是onclick事件,那么很容易点不到下拉内容,所以注册的是鼠标按下时就触发
$(document).on("mousedown","div[name=searchDiv1]",function(){
$("#select-input").val(this.innerText);
});
$("#select-input").on("focus", function () {
$("#searchDiv").show();
})
//失焦后延时10ms执行,避免失焦后searchDiv立即隐藏点不到里面的元素的问题
$("#select-input").on("blur", function () {
setTimeout(function(){
$("#searchDiv").hide();
},"10")
})
//对input注册keyup事件,用于实现模糊查询的效果
$("#select-input").on("keyup", function () {
$.ajax({
url: 'testHandler.ashx',
type: 'POST',
data: {'param':'getContentByName','keyID':$('#select-input').val() },
async:true,
beforeSend: function () {
},
success: function (data) {
var res = eval('(' + data + ')');
var searchDiv = $("#searchDiv");
$(searchDiv).empty();
var content = "";
for (var i = 0; i < res.length; i++) {
content += "<div name='searchDiv1' value='"+res[i].tab_id+"'>"+res[i].tab_name+"</div>";
}
$(searchDiv).html(content);
}
});
})
//下拉内容初始化
$(document).ready(function () {
$.ajax({
url: 'testHandler.ashx',
type: 'POST',
data: {'param':'getContentAll' },
async:true,
beforeSend: function () {
},
success: function (data) {
var res = eval('(' + data + ')');
var searchDiv = $("#searchDiv");
$(searchDiv).empty();
var content = "";
for (var i = 0; i < res.length; i++) {
content += "<div name='searchDiv1' value='"+res[i].tab_id+"'>"+res[i].tab_name+"</div>";
}
$(searchDiv).html(content);
}
});
})
</script>
</html>
6.效果展示
基本的实时对接后台的可搜索式下拉框已完成,当然在真实项目上肯定会对美观上有要求的,且数据量也不会这么少,选中相关的选项之后可能也会有后续的处理等等,当然,万变不离其中,只要知道了原理,这些的改变都是锦上添花,下面给出实际项目的展示图