以下代码实现了模拟下拉窗功能,鼠标与键盘都可以控制列表选项:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.box{width: 300px;height: 40px;line-height: 40px;margin: 0 auto;text-indent: 4px;}
.box span{display: block;width: 300px;height: 40px;border: solid 1px black;cursor: pointer;box-sizing: border-box}
.box ul{margin: 0;padding: 0;list-style: none;border: solid 1px black;border-top:none;width: 300px;text-indent: 8px;display: none;;padding: 4px;box-sizing: border-box;}
.box ul li.hover{background: #66f;color: #fff;}
</style>
</head>
<body>
<select name="" id="">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
<option value="深圳">深圳</option>
<option value="杭州">杭州</option>
</select>
<div class="box">
<span></span>
<ul class="list">
<li>北京</li>
<li>上海</li>
<li>广州</li>
<li>深圳</li>
<li>杭州</li>
</ul>
</div>
</body>
<script>
var ospan = document.querySelector(".box span");
var oul = document.querySelector(".list");
var ali = oul.children;
var flag=0;
// 当前确认选中的索引
var index = 0;
// 键盘控制选项的索引
var keyIndex;
setDefault()
for(var i=0;i<ali.length;i++){
ali[i].xuhao = i;
ali[i].onmouseover = function(){
this.className = "hover";
// 防止第一次鼠标进入选项,找不到keyIndex索引,而报错
if(keyIndex !== undefined){
ali[keyIndex].className = "";
}
// 鼠标进入选项时,将键盘的索引,设置为当前选项的索引
keyIndex = this.xuhao;
console.log(keyIndex);
}
ali[i].onmouseout = function(eve){
var e = eve || window.event;
stopBubble(e);
this.className = "";
// 鼠标离开选项时,将键盘的索引,设置为默认值
// keyIndex = null;
}
ali[i].onclick = function(){
ali[index].lastElementChild.remove();
index = this.xuhao;
setDefault()
oul.style.display = "none";
flag = 0;
}
}
function setDefault(){
ospan.innerHTML = ali[index].innerHTML;
var em = document.createElement("em")
em.innerHTML = "√";
ali[index].appendChild(em);
}
ospan.onclick = function(eve){
var e = eve || window.event;
stopBubble(e);
if(flag === 0){
oul.style.display = "block";
// 下拉菜单每次重新显示,都是需要将键盘所有内容设置为默认值
if(keyIndex !== undefined){
ali[keyIndex].className = "";
}
keyIndex = undefined;
flag = 1;
}else{
oul.style.display = "none";
flag = 0;
}
}
document.onclick = function(){
oul.style.display = "none";
flag = 0;
}
function stopBubble(e){
if(e.stopPropagation){
e.stopPropagation()
}else{
e.cancelBubble = true;
}
}
// ====================
// 鼠标直接离开ul,将键盘的所有内容设置为默认值
oul.onmouseout = function(){
// console.log(keyIndex);
if(keyIndex !== undefined){
ali[keyIndex].className = "";
}
keyIndex = undefined;
}
document.onkeydown = function(eve){
var e = eve || window.event;
var code = e.keyCode || e.which;
// 上
if(code === 38){
// 第一次按下键盘,需要将keyIndex设置为起点的上一个值
if(keyIndex === undefined){
keyIndex = ali.length;
}
// 计算索引
if(keyIndex === 0){
keyIndex = 0
}else{
keyIndex--;
}
// 如果索引为起点,不需要清除上一个元素的样式
if(keyIndex !== ali.length-1){
ali[keyIndex+1].className = "";
}
// 根据索引,添加样式
ali[keyIndex].className = "hover";
}
// 下
if(code === 40){
if(keyIndex === undefined){
keyIndex = -1;
}
if(keyIndex === ali.length-1){
keyIndex = ali.length-1
}else{
keyIndex++;
}
if(keyIndex !== 0){
ali[keyIndex-1].className = "";
}
ali[keyIndex].className = "hover"
}
// 回车
if(code === 13){
// 清除上一个选中的选项的选中状态
ali[index].lastElementChild.remove();
// 修改上一个选中的索引为键盘的索引
index = keyIndex;
// 设置选项的默认状态
setDefault();
// 隐藏下拉菜单
oul.style.display = "none";
// 修改下拉菜单显示状态
flag = 0;
}
}
</script>
</html>