实现一个搜索框并实时返回搜索建议项
参考:https://blog.csdn.net/rujin_shi/article/details/83657566
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS实现仿百度搜索框(实时返回搜索建议项)</title>
<style>
* {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
}
body {
background-color: #f0f3ef;
}
div {
box-sizing: border-box;
}
.container {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.bgDiv {
width: 595px;
height: 55px;
position: relative;
}
.input-wrapper {
display: flex;
justify-content: center;
width: 100%;
height: 33px;
}
.search-input-text {
width: 560px;
border: 1px solid #b6b6b6;
background-color: #fff;
font-size: 18px;
padding: 3px 0 0 7px;
}
.search-input-button {
flex: 1;
color: #fff;
font-size: 16px;
letter-spacing: 3px;
background-color: #3385ff;
border: .5px solid #2d78f4;
opacity: .9;
margin-left: -5px;
}
.search-input-button:hover {
opacity: 1;
box-shadow: 0 1px 1px #333;
cursor: pointer;
}
.suggest {
width: 516px;
position: absolute;
top: 38px;
border: 1px solid #999;
background-color: #fff;
display: none;
}
.suggest ul {
list-style: none;
}
.suggest ul li {
margin: 3px;
font-size: 17px;
line-height: 25px;
cursor: pointer;
}
.suggest ul li:hover {
background-color: #e5e5e5;
}
</style>
</head>
<!-- 向输入框动态输入关键词时,将当前关键词作为问号参数后面的值,
因为要跨域使用百度的接口,所以通过JSONP跨域创建Ajax请求,回调函数处理返回值 -->
<body>
<!-- 默认html和body是没有设置height的,在布局中对于没有设置宽高的块状盒子,宽度
默认100%,高度是由里面的内容自然撑开的 -->
<div class="container">
<div class="bgDiv">
<div class="input-wrapper">
<input type="text" class="search-input-text" value="" autofocus placeholder="关键词">
<input type="button" id="btn" class="search-input-button" value="搜索一下">
</div>
<div class="suggest">
<ul id="search-result">
<!-- 动态创建li,同时进行事件委托,键盘事件--回车键以及上下键都是进行事件委托注册的 -->
</ul>
</div>
</div>
</div>
<script>
let suggestContainer = document.getElementsByClassName('suggest')[0];
let searchInput = document.getElementsByClassName('search-input-text')[0];
let bgDiv = document.getElementsByClassName('bgDiv')[0];
let searchResult = document.getElementById('search-result');
//清除建议框内容
let clearContent = function() {
let size = searchResult.childNodes.length;
for(let i = size - 1; i >= 0; i--) {
searchResult.removeChild(searchResult.childNodes[i]);
}
}
let timer = null;
//注入输入框键盘抬起事件
searchInput.onkeyup = function(e) {
suggestContainer.style.display = 'block';
//如果输入框内容为空,清除内容且无需跨域请求
if(this.value.length === 0) {
clearContent();
return;
}
if(this.timer) {
clearTimeout(this.timer);
}
//40为Dw arrow 38位Up Arrow
if(e.keyCode !== 40 && e.keyCode !== 38) {
//函数节流优化
this.timer = setTimeout(() => {
//创建script标签JSONP跨域
let script = document.createElement("script");
script.src = "http://www.baidu.com/su?&wd=" + encodeURI(this.value.trim()) +
"&p=3&cb=handleSuggestion";
document.body.appendChild(script);
}, 130);
}
}
//回调函数处理返回值
let handleSuggestion = function(res) {
//清空之间的数据
clearContent();
let result = res.s;
//截取前五个搜索建议项
if(result.length > 4) {
result = result.slice(0, 5);
}
//动态创建li标签,显示搜索建议项
for(let i = 0; i < result.length; i++) {
let liObj = document.createElement('li');
liObj.innerHTML = result[i];
searchResult.appendChild(liObj);
}
//自执行匿名函数--删除用于跨域的script标签
(function() {
let s = document.querySelectorAll("script");
for(let i = 1, len = s.length; i < len; i++) {
document.body.removeChild(s[i]);
}
})();
}
let jumpPage = function() {
window.open(`https://www.baidu.com/s?word=${encodeURI(searchInput.value)}`);
}
//事件委托,点击li标签或者点击搜索按钮跳转到百度搜索页面
bgDiv.addEventListener('click', function(e) {
if(e.target.nodeName.toLowerCase() === 'li') {
let keywords = e.target.innerText;
searchInput.value = keywords;
jumpPage();
} else if(e.target.id === 'btn') {
jumpPage();
}
}, false);
let i = 0, flag = 1;//键盘向上和向下的区分标志
//事件委托,监听键盘事件
bgDiv.addEventListener('keydown', function(e) {
let size = searchResult.childNodes.length;
//13为enter
if(e.keyCode === 13) {
jumpPage();
}
//键盘向下事件
if(e.keyCode === 40) {
if(flag === 0) {
i = i + 2;
}
flag = 1;
e.preventDefault();
if(i >= size) {
i = 0;
}
if(i < size) {
searchInput.value = searchResult.childNodes[i++].innerText;
}
}
//键盘向上事件
if(e.keyCode === 38) {
if(flag === 1) {
i = i - 2;
}
flag = 0;
e.preventDefault();
if(i < 0) {
i = size - 1;
}
if(i > -1) {
searchInput.value = searchResult.childNodes[i--].innerText;
}
}
}, false);
//点击页面上任何其它地方,搜索结果框消失
document.onclick = () => clearContent();
</script>
</body>
</html>