JS实现多级下拉列表框

一、编写HTML

<link type="text/css" rel="stylesheet" href="css/hm-multi-select.css" />
<script type="text/javascript" src="js/hm-multi-select.js"></script>
<script type="text/javascript" src="js/self-dynamic.js"></script>

<div id="hm-select-div"></div>

二、编写CSS

.disabled-div {
    display : none;
}
#hm-select-div input {
    width : 176px;
    height: 30px;
    border-radius: 3px;
    float:left;
    display:block;
    padding:6px 12px;
    font-size: 14px;
    line-height: 1.42854143;
    outline: 0;
    border: 1px solid #e9e9e9;
}
#hm-select-div input:focus {
    border-color: #66afe9;
    outline: 0;
    box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102,175,233,.6);
}
#hm-select-div{
    display: inline-block;
}

.content-div {
    margin-top:9px;
    background: beige;
    width : 176px;
    z-index: 200;
    position: absolute;
    border: 1px solid #e9e9e9;
}
.content-div ul {
    width: 176px;
    margin:0 ;
    padding:0;
}
.content-div ul li{
    display: block;
    font-size: 14px;
    height:40px;
    line-height: 40px;
    list-style: none;
    width: 168px;
    padding-left:8px;
    /*border-bottom: 1px solid #eee;*/
}
.content-div ul li:hover{
    cursor: pointer;
    color: #000;
    background: cyan;
}
.choose-li{
    background : #F5F7FA;
}

三、编写JS

模拟数据

// 设置数据源
let data = [{
    id : 1,
    type : 0,
    name : ‘是非得失‘
},{
    id : 1,
    type : 0,
    name : ‘塞翁失马‘
},{
    id : 1,
    type : 1,
    name : ‘烦得很发过火‘
},{
    id : 1,
    type : 1,
    name : ‘千万人就开了‘
},{
    id : 1,
    type : 1,
    name : ‘第三方存在‘
},{
    id : 1,
    type : 1,
    name : ‘和谐号占领太平洋‘
}];

window.onload = function() {
    mainFloorInit(data);
}

// 下拉列表
window.addEventListener(‘li-hover-event‘, function(event) {
    // 通过父级id取得子级data,并创建新的显示层
    if(JSON.stringify(event.detail.type) === ‘1‘){
        clearRedundantLi(event.detail.element);
        return;
    }
    createNewDiv(data, event.detail.element);
});

效果文件

let floor = 1;

/**
 * 删除多余的层级
 * @param element li元素
 */
function clearRedundantLi(element) {
    // 取得当前层级
    let parentNode = element.parentNode.parentNode;
    let currentFloor = Number(parentNode.getAttribute(‘floor‘));
    // 删除多余的显示div
    let outDiv = document.getElementById(‘hover-select‘);
    let divArray = document.querySelectorAll(‘.content-div‘);
    for(let divEle of divArray) {
        let divFloor = divEle.getAttribute(‘floor‘);
        if(divFloor>currentFloor){
            outDiv.removeChild(divEle);
        }
    }
}

/**
 * 创建多级select
 * @param data
 * @param element li元素
 */
function createNewDiv(data, element) {
    // 取得当前层级
    let parentNode = element.parentNode.parentNode;
    let currentFloor = Number(parentNode.getAttribute(‘floor‘));
    // 删除多余的显示div
    clearRedundantLi(element);
    let divELe = createSelectDiv(null, data);
    // 设置新显示div的位置
    divELe.style.position = ‘absolute‘;
    divELe.style.left = (Number(parentNode.offsetLeft) + Number(parentNode.offsetWidth)) + ‘px‘;
    divELe.style.top = parentNode.offsetTop + element.offsetTop + ‘px‘;
    divELe.setAttribute(‘floor‘,String(currentFloor + 1));
}

/**
 * 为input设置内容
 * @param element 当前点击触发的li元素
 */
function setValue(element) {
    // 为input设置内容
    document.getElementById(‘selectText‘).value = element.innerHTML;
    document.getElementById(‘selectText‘).setAttribute(‘val‘,element.value);
    hideContainer();
    let setValueEvent = new CustomEvent(‘select-set-value‘, {
        detail : {
            title : ‘set-value‘,
            value : element.value,
            text : element.innerHTML,
            type : element.getAttribute(‘self-type‘)
        }
    });
    window.dispatchEvent(setValueEvent);
}

/**
 * 隐藏主图层
 */
function hideContainer() {
    // 隐藏主图层
    let outDiv = document.getElementById(‘hover-select‘);
    outDiv.setAttribute(‘class‘,‘disabled-div‘);
    // 清空多余的div
    let divArray = document.querySelectorAll(‘.content-div‘);
    for(let divEle of divArray) {
        if(Number(divEle.getAttribute(‘floor‘))!==1){
            outDiv.removeChild(divEle);
        }
    }
}

/**
 * 初始化第一层
 */
function mainFloorInit(data){
    let container = document.getElementById(‘hm-select-div‘);
    // 创建input元素
    let inputEle = document.createElement(‘input‘);
    inputEle.setAttribute(‘id‘,‘selectText‘);
    inputEle.setAttribute(‘type‘,‘text‘);
    inputEle.setAttribute(‘placeholder‘,‘请选择相关部门‘);
    container.appendChild(inputEle);
    container.appendChild(document.createElement(‘br‘));
    // 创建select层容器
    let hoverDivELe = document.createElement(‘div‘);
    hoverDivELe.setAttribute(‘id‘,‘hover-select‘);
    // 隐藏select显示层
    hoverDivELe.setAttribute(‘class‘,‘disabled-div‘);
    // 新建一层
    let firstFloorDivELe = createSelectDiv(hoverDivELe, data);
    firstFloorDivELe.setAttribute(‘floor‘,‘1‘);
    hoverDivELe.appendChild(firstFloorDivELe);
    container.appendChild(hoverDivELe);
    inputEle.onclick = function() {
        let showClass = hoverDivELe.getAttribute(‘class‘);
        if(showClass !== ‘disabled-div‘){
            hoverDivELe.setAttribute(‘class‘,‘disabled-div‘);
            hideContainer();
        } else {
            hoverDivELe.removeAttribute(‘class‘);
        }
    }
}

/**
 * 创建一个新的select
 * @param parentNode 父节点
 * @param data 数据列表
 * @returns {Element}
 */
function createSelectDiv(parentNode, data) {
    if(parentNode == null){
        parentNode = document.getElementById(‘hover-select‘);
    }
    // 新建一层
    let divELe = document.createElement(‘div‘);
    divELe.setAttribute(‘class‘,‘content-div‘);
    // 新建ul
    let ulEle =  document.createElement(‘ul‘);
    // 循环新建li
    for(let item of data){
        let liEle =  document.createElement(‘li‘);
        liEle.setAttribute(‘class‘,‘content-li‘);
        liEle.innerHTML = item.name;
        liEle.value = item.id;
        liEle.setAttribute(‘self-type‘,item.type);
        liEle.onclick = function() {
            setValue(this);
        };
        liEle.onmouseenter = function() {
            let liHoverEvent = new CustomEvent(‘li-hover-event‘, {
                detail : {
                    title : ‘li-hove‘,
                    id : liEle.value,
                    type : item.type,
                    element : liEle
                }
            });
            // 触发事件,创建新显示层
            window.dispatchEvent(liHoverEvent);
        };
        liEle.onmouseout = function(event) {
            let floorDiv = liEle.parentNode.parentNode;
            clearLiClass(floorDiv);
            // 取得当前坐标
            let x = event.clientX;
            let y = event.clientY;
            // 父级div坐标
            let left = floorDiv.offsetLeft;
            let top = floorDiv.offsetTop;
            let right = floorDiv.offsetLeft + floorDiv.offsetWidth;
            let bottom = floorDiv.offsetTop + floorDiv.offsetHeight;
            // 判断鼠标是否离开div
            if( x < left || x > right || y < top || y > bottom){
                liEle.setAttribute(‘class‘,‘content-li choose-li‘);
            }
        };
        ulEle.appendChild(liEle);
    }
    divELe.appendChild(ulEle);
    divELe.onmouseenter = function(event) {
        let floorDiv = event.target;
        clearLiClass(floorDiv);
    }
    parentNode.appendChild(divELe);
    return divELe;
}

function clearLiClass(element) {
    let liElements = element.childNodes[0].childNodes;
    for(let liEle of liElements) {
        liEle.setAttribute(‘class‘,‘content-li‘);
    }
}

JS实现多级下拉列表框

上一篇:vue实现form表单提交文件上传


下一篇:js处理数字两位小数以及不能输入英文校验