js递归无限级联

依赖jquery
可根据配置参数(方向,样式,标签名称)得到自己想要
select.js

(function ($) {
    $.fn.select = function (url, option, callback) {
        var setting = {
            el: $("body"),
            data: null,
            labels: [],
            isOpenSearch: true,
            isOpenRecoder: true,
            slideSpeed: 350,
            direction: 'horizontal',
            select: {
                '1': {
                    isClick: true,
                    type: 'select',
                    property: 'value',
                    isOnlyRead: true
                },
                '2': {
                    isClick: true,
                    type: 'select',
                    property: 'value',
                    isOnlyRead: true
                },
                '3': {
                    isClick: true,
                    type: 'select',
                    property: 'value',
                    isOnlyRead: true
                }
            },
            settingCss: {
                glSelect: {
                    selfClass: {},
                    selectGroup: {
                        selfClass: {},
                        label: {
                            selfClass: {}
                        },
                        select: {
                            selfClass: {}
                        },
                        selectContent: {
                            selfClass: {},
                            search: {
                                selfClass: {},
                                input: {
                                    selfClass: {},
                                }
                            },
                            optionWapper: {
                                selfClass: {},
                                li: {
                                    selfClass: {}
                                }
                            },
                            recoder: {
                                selfClass: {}
                            }
                        }
                    }
                }
            }

        };
        var tags = {
            input: function () {

            },
            select: function () {
                return $('<input class="select"  value="">');
            },
            image: function () {
                return $('<img class="select img">');
            },
            textarea: function () {
                return $('<textarea class="select" style="resize: none"></textarea>');
            }
        };
        var method = {
            initBind: function () {
                var modelArr = new Array();
                setting.method.getDataArr(setting.data, modelArr);

                //排除不能点击的select
                var arr = $.makeArray($('.select-group').find('.select'));
                var brr = $.makeArray($('.select-group').find('.select'));
                var crr = [];
                for (var key in setting.select) {
                    if (setting.select[key].isClick === false) {
                        arr[parseInt(key) - 1] = $(new Object);
                    }
                    if (setting.select[key].isOnlyRead === false) {
                        console.log(setting.select[key].isOnlyRead)
                        crr.push(brr[parseInt(key) - 1]);
                        brr[parseInt(key) - 1] = $(new Object);
                    }
                }
                $(brr).attr('readonly', 'readonly');
                setting.eventMethod.select.click($(arr), setting.data);
                setting.eventMethod.input.input(setting.el, modelArr);
                setting.eventMethod.select.input(setting.el, modelArr, $(crr))
                setting.eventMethod.li.click(setting.el, modelArr);
                return this;
            },
            getData: function () {
                var mydata = {
                    '河南': {
                        '商丘': [{
                            name1: '河南',
                            name2: '商丘',
                            name3: './screenshots/quick-edit.png'
                        }],
                        '郑州': [{
                            name1: '河南',
                            name2: '郑州',
                            name3: './screenshots/quick-edit.png2'
                        }]
                    },
                    '浙江': {
                        '杭州': [{
                            name1: '浙江',
                            name2: '杭州',
                            name3: './screenshots/quick-edit.png2'
                        }],
                        '宁波': [{
                            name1: '浙江',
                            name2: '宁波',
                            name3: './screenshots/quick-edit.png'
                        }]
                    }
                }
                setting.data = mydata;
                setting.labels = ['省:', '市:', '县:'];
                /*  $.ajax({
                      url: url,
                      type: 'get',
                      async: false,
                      success: function (resp) {
                            setting.data = resp.data;
                          if (setting.labels.length <= 0) {
                               setting.labels = resp.labels;
                          }
                      }
                  })*/
                return this;
            },
            initSelect: function (elem, data) {
                var depth = 0;
                this.recursionFillSelect(elem, data, depth);
                return this;
            },
            recursionFillSelect: function (elem, data, depth) {
                //记录递归深度
                depth++;
                this.createElementAndSettingRelation(elem, data, depth);

            },
            getDataArr: function (data, modelArr) {
                for (var key in data) {
                    if (!(data[key] instanceof Array)) {
                        setting.method.getDataArr(data[key], modelArr);
                    } else {
                        for (var index = 0; index < data[key].length; index++) {
                            modelArr.push(data[key][index]);
                        }
                    }

                }
            },
            funOpen: function (object, callback) {
                object.next().slideDown();
            },
            funClose: function (object, callback) {
                object.next().slideUp();
            },
            isOpenSearch: function (elem) {
                if (!setting.isOpenSearch) {
                    elem.css({
                        'display': 'none'
                    })
                }
            },
            isOpenRecoder: function (elem) {
                if (!setting.isOpenRecoder) {
                    elem.css({
                        'display': 'none'
                    })
                }
            },
            createElementAndSettingRelation(elem, data, depth) {
                elem.css(setting.settingCss.glSelect.selfClass);
                var $selectGroup = $('<div class="select-group"></div>');
                $selectGroup.css(setting.settingCss.glSelect.selectGroup.selfClass);
                setting.direction === 'vertical' ? elem.addClass(setting.direction) : $selectGroup.addClass(setting.direction);
                var $label = $('<label class="label">' + setting.labels[depth - 1] + '</label>');
                $label.css(setting.settingCss.glSelect.selectGroup.label.selfClass);
                var $select = this.getTagType(depth);
                $select.css(setting.settingCss.glSelect.selectGroup.select.selfClass);
                var $selectContent = $(' <div class="select-content hide"></div>');
                $select.css(setting.settingCss.glSelect.selectGroup.selectContent.selfClass);
                var $search = $('<div class="search"></div>');
                $search.css(setting.settingCss.glSelect.selectGroup.selectContent.search.selfClass);
                var $input = $('<input class="input" />');
                $input.css(setting.settingCss.glSelect.selectGroup.selectContent.search.input.selfClass);
                var $optionWapper = $('<ul class="option-Wapper"></ul>');
                $optionWapper.css(setting.settingCss.glSelect.selectGroup.selectContent.optionWapper.selfClass);
                var $recoder = $('<div class="recoder"></div>');
                $recoder.css(setting.settingCss.glSelect.selectGroup.selectContent.recoder.selfClass);
                //建立关系
                $search.append($input);
                $selectContent.append($search);
                $selectContent.append($optionWapper);
                $selectContent.append($recoder);
                $selectGroup.append($label);
                $selectGroup.append($select);
                $selectGroup.append($selectContent);
                elem.append($selectGroup);
                //是否开启搜索框
                this.isOpenSearch($search);
                //是否开启记录
                this.isOpenRecoder($recoder);
                this.defaultData(elem, $select, data, depth)
            },
            defaultData: function (elem, select, data, depth) {
                if (!(data instanceof Array)) {
                    for (var key in data) {
                        // select.val(key);
                        this.byTagNameGiveValue(select, select[0].tagName, key, depth);
                        this.recursionFillSelect(elem, data[key], depth);
                        break;
                    }
                } else {
                    //select.val(data[0]['name' + depth]);
                    this.byTagNameGiveValue(select, select[0].tagName, data[0]['name' + depth], depth);
                    //返回
                    var modelArr = new Array();
                    setting.method.getDataArr(setting.data, modelArr);
                    setting.method.setModel(elem.find('.select-group .select'), modelArr, callback);
                }

            },
            setModel: function (elemArr, modelArr, callback) {
                for (var index = 0; index < modelArr.length; index++) {
                    var allSome = true;
                    for (var secondIndex = 0; secondIndex < elemArr.length; secondIndex++) {
                        if (modelArr[index]['name' + (secondIndex + 1)] != $(elemArr[secondIndex]).val()) {
                            allSome = false;
                            break;
                        }
                    }
                    if (allSome) {
                        callback(modelArr[index]);
                        break;
                    }
                }
            },
            getTagType: function (depth) {
                if (setting.select[depth] && setting.select[depth].type) {
                    return tags[setting.select[depth].type]()
                } else {
                    return tags['select']
                }

            },
            byTagNameGiveValue: function (elem, tagName, val, depth) {
                var select = setting.select[depth];
                if (select === null || select === '' || select === undefined) {
                    elem.val(val);
                } else {
                    console.log(select)
                    elem.prop(select.property, val);
                }
            }
        };
        var eventMethod = {
            selectEvent: {
                change: function (event) {
                    var data = setting.data;
                    $($.makeArray($(this).parent().prevAll()).reverse()).each(function (index, elem) {
                        data = data[$(elem).find('.select-control').val()]
                    })
                    $(this).parent().nextAll().remove();
                    setting.method.recursionFillSelect(setting.el, data[$(this).val()], $(this).parent().parent().find(".select-group").index($(this).parent()) + 1);
                },
                click: function (event) {}
            },
            select: {
                click: function (elem, data) {
                    elem.off().on('click', function () {
                        var $selectContent = $('.select-group').find('.select').next();
                        var $optionWapper = $selectContent.find('.option-Wapper');
                        var $recoder = $selectContent.find('.recoder');
                        $('.select-group').find('.select').not($(this)).next().slideUp(setting.slideSpeed);
                        $(this).next().slideToggle(setting.slideSpeed);
                        var deepth = $('.select-group').find('.select').index($(this));

                        var $selectGroup = $.makeArray($(this).parent().prevAll()).reverse();
                        var tempData = data;
                        for (var index = 0; index < $selectGroup.length; index++) {
                            tempData = tempData[$($selectGroup[index]).find('.select').val()]
                        }
                        if (!(tempData instanceof Array)) {
                            $optionWapper.empty();
                            $recoder.text('共' + $(Object.keys(tempData)).length + '条数据')
                            $.each($(Object.keys(tempData)), function (index, elem) {
                                $optionWapper.append('<li class="li">' + elem + '</li>')
                            })

                        } else {
                            $optionWapper.empty();
                            $recoder.text('共' + tempData.length + '条数据')
                            $.each($(tempData), function (index, elem) {
                                $optionWapper.append('<li class="li">' + elem['name' + (deepth + 1)] + '</li>')
                            })
                        }
                        //清空搜索框
                        $(this).parents('.select-group').find('.search .input').val('');
                    })
                },
                input: function (elem, modelArr, selectArr) {
                    selectArr.on('input', function () {
                        var $that = $(this);
                        var $input = $(this).next().find('.input');
                        var deepth = setting.el.find(".select-group .select-content .search .input").index($input);
                        var $selectContent = $(this).next();
                        var $preInputs = $input.parents('.select-group').prevAll().find('.select');
                        var $optionWapper = $selectContent.find('.option-Wapper');
                        var $recoder = $selectContent.find('.recoder');
                        $optionWapper.empty();
                        var names = [];
                        //筛选满足所有父层级的model
                        var $new_modelArr = modelArr.filter(function (item) {
                            var isSame = true;
                            for (var index = 0; index < $preInputs.length; index++) {
                                if (item['name' + (index + 1)] === $($preInputs[index]).val()) {
                                    isSame = true;
                                } else {
                                    return false;
                                }
                            }
                            return isSame;
                        });
                        //筛选满足输入框的model
                        $.each($new_modelArr, function (index, elem) {
                            var name = elem['name' + (deepth + 1)];
                            if (name.startsWith($that.val())) {
                                if ($.inArray(name, names) === -1) {
                                    names.push(name);
                                }
                            }
                        });
                        $.each(names, function (index, elem) {
                            $optionWapper.append('<li class="li">' + elem + '</li>');
                        });
                        $recoder.text('共' + names.length + '条数据');
                    });
                }
            },
            input: {
                input: function (elem, modelArr) {
                    elem.on('input', '.select-group .select-content .search .input', function () {
                        var $that = $(this);
                        var deepth = setting.el.find(".select-group .select-content .search .input").index($(this));
                        var $selectContent = $(this).parent().parent();
                        var $preInputs = $(this).parents('.select-group').prevAll().find('.select');
                        var $optionWapper = $selectContent.find('.option-Wapper');
                        var $recoder = $selectContent.find('.recoder');
                        $optionWapper.empty();
                        var names = [];
                        //筛选满足所有父层级的model
                        var $new_modelArr = modelArr.filter(function (item) {
                            var isSame = true;
                            for (var index = 0; index < $preInputs.length; index++) {
                                if (item['name' + (index + 1)] === $($preInputs[index]).val()) {
                                    isSame = true;
                                } else {
                                    return false;
                                }
                            }
                            return isSame;
                        })
                        //筛选满足输入框的model
                        $.each($new_modelArr, function (index, elem) {
                            var name = elem['name' + (deepth + 1)];
                            if (name.startsWith($that.val())) {
                                if ($.inArray(name, names) === -1) {
                                    names.push(name);
                                }
                            }
                        })
                        $.each(names, function (index, elem) {
                            $optionWapper.append('<li class="li">' + elem + '</li>');
                        })
                        $recoder.text('共' + names.length + '条数据');
                    });
                },
            },
            li: {
                click: function (elem, modelArr) {
                    elem.on('click', ' .select-group .select-content .option-Wapper .li', function () {
                        var $value = $(this).text();
                        var $select = $(this).parents('.select-group').find('.select');
                        var $groupIndex = setting.el.find('.select-group').index($(this).parents('.select-group'));
                        var $preInputs = $(this).parents('.select-group').prevAll().find('.select');
                        setting.method.byTagNameGiveValue($select, $select[0].tagName, $value, $preInputs.length);
                        var $nextInputs = $(this).parents('.select-group').nextAll().find('.select');
                        var $new_modelArr = modelArr.filter(function (item) {
                            var isSame = true;
                            if (item['name' + ($groupIndex + 1)] === $value) {
                                for (var index = 0; index < $preInputs.length; index++) {
                                    if (item['name' + (index + 1)] === $($preInputs[index]).val()) {
                                        isSame = true;
                                    } else {
                                        return false;
                                    }
                                }
                            } else {
                                return false;
                            }
                            return isSame;
                        })
                        var model = $new_modelArr[0];
                        for (var index = 0; index < $nextInputs.length; index++) {
                            setting.method.byTagNameGiveValue($($nextInputs[index]), $nextInputs[index].tagName, model['name' + (($groupIndex + 1) + (index + 1))], $preInputs.length + 1 + (index + 1));
                        }
                        //隐藏搜索框
                        $(this).parents('.select-content').slideUp(setting.slideSpeed);
                        //清空搜索框
                        $(this).parents('.select-group').find('.search .input').val('');
                        //返回
                        setting.method.setModel(elem.find('.select-group .select'), modelArr, callback);
                    })
                }
            }
        };
        $.extend(setting, {
            'eventMethod': eventMethod
        }, {
            'method': method
        }, option);
        method
            .getData()
            .initSelect(setting.el, setting.data)
            .initBind();
        return this;
    }
})(jQuery)

select.css

@charset "utf-8";

.glSelect {
    margin-top: 50px;
    width: 100%;
}

.horizontal {
    box-sizing: border-box;
    width: 33%;
    float: left;
}

.vertical {
    width: 30%;
}

.select-group {
    display: flex;
    flex-wrap: wrap;
    position: relative;
    margin: 15px 0px 15px 0px;
}

.select-group .select {
    border-width: 1px;
    height: 25px;
    width: 80%;
    border-radius: 5px 5px 0px 0px;
    outline-style: hidden;
    box-shadow: 0px 0px 1px 0px white;
    -webkit-box-shadow: 0px 0px 1px 0px white;
    -moz-box-shadow: 0px 0px 1px 0px white;
    animation: changeBorderColor 3s linear;
    -webkit-animation: changeBorderColor 3s linear;
    -moz-animation: changeBorderColor 3s linear;
}

.label {
    height: 20px;
    width: 10%;
}

.select-content {
    left: 10%;
    top: 29px;
    border: 1px solid #B0E0E6;
    width: 80%;
    background-color: #F8F8FF;
    z-index: 9999;
    position: absolute;
    opacity: 0.9;
}

.search {
    margin: 10px 0px 2px 0px;
    width: 100%;
    display: flex;
    justify-content: center;
}

.search .input {
    border: 1px solid darkturquoise;
    border-radius: 5px;
    height: 25px;
    width: 85%;
}

.option-Wapper {
    width: 100%;
    max-height: 100px;
    overflow-y: scroll;
    padding-inline-start: 0px !important;
    margin-inline-start: 0px !important;
    margin-block-start: 0px !important;

}

.option-Wapper::-webkit-scrollbar {
    width: 5px;
}

.option-Wapper::-webkit-scrollbar-thumb {
    /*滚动条里面小方块*/
    border-radius: 10px;
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    background: #008B8B;
}

.option-Wapper::-webkit-scrollbar-track {
    /*滚动条里面轨道*/
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    border-radius: 10px;
    background: #F5FFFA;
}

.glSelect .select-group .select-content .option-Wapper .li {
    list-style: none;
    text-align: center;
    cursor: pointer;
}

.glSelect .select-group .select-content .option-Wapper .li:hover {
    background-color: darkturquoise;
    color: white;
}

.recoder {
    background-color: bisque;
    color: red;
    border-top: 1px solid black;
    font-size: 0.75rem;
    text-align: center;
}

.hide {
    display: none;
}

.img {
    width: 400px !important;
    height: 250px !important;
}

@keyframes changeBorderColor {
    from {
        box-shadow: 0px 0px 1px 0px white inset;
    }

    to {
        box-shadow: 0px 0px 1px 0px blue inset;
    }
}

-webkit-@keyframes changeBorderColor {
    from {
        box-shadow: 0px 0px 1px 0px white inset;
    }

    to {
        box-shadow: 0px 0px 1px 0px blue inset;
    }
}

-moz-@keyframes changeBorderColor {
    from {
        box-shadow: 0px 0px 1px 0px white inset;
    }

    to {
        box-shadow: 0px 0px 1px 0px blue inset;
    }
}

index.js

$(function () {
    var result = null;
    var option = {
        el: $(".glSelect"),
        isOpenSearch: false,
        isOpenRecoder: false,
        slideSpeed: 500,
        direction: 'vertical',
        select: {
            '1': {
                isClick: true,
                type: 'select',
                property: 'value',
                isOnlyRead: false
            },
            '2': {
                isClick: false,
                type: 'select',
                property: 'value'
            },
            '3': {
                isClick: false,
                type: 'image',
                property: 'src'
            }
        }
    }
    $.fn.select("", option, args => {
        result = args;
    });
    /* setInterval(function () {
     console.log(result)
 }, 1000)*/
})

index.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>GETTING STARTED WITH BRACKETS</title>
    <meta name="description" content="An interactive getting started guide for Brackets.">
    <script style="text/javascript" src="./jquery.js"></script>
    <link type="text/css" rel="stylesheet" href="./select/css/select.css">

</head>

<body>
    <div class="glSelect"></div>
    <script type="text/javascript" src="./select/js/select.js"></script>
    <script type="text/javascript" src="index/index.js"></script>
</body>

</html>

插件参数详解

el:根div      jquery对象
data:数据    
labels:[]   标签
isOPenSearcher: 布尔值 是否开启具有搜索功能的下拉菜单
slideSpeed: 拉下菜单展开和关闭速度  单位:毫秒
settingCss:样式设置
direction:控制显示方向  “horizontal”横向显示,"vertical"纵向显示
 select: {
                '1': {//select的索引,从1开始
                    isClick: true,//click事件是否能出发(点击后是否有下拉口框)
                    type: 'select',//标签库有image,select,textarea三种
                    property: 'value',//对应标签的赋值属性
                    isOnlyRead: true//是否仅读
                }
            },
settingCss:{
                glSelect:{ 
                    selfClass:{},//.glSelect样式设置
                    selectGroup:{
                        selfClass:{},//select-group样式设置
                        label:{
                            selfClass:{}//.label样式设置
                        },
                        select:{
                            selfClass:{}//.select样式设置
                        },
                        selectContent:{
                            selfClass:{},//.select-content样式设置
                            search:{
                                selfClass:{},//.search样式设置
                                input:{
                                    selfClass:{},//.input样式设置
                                }
                            },
                            optionWapper:{
                                selfClass:{},//.option-Wapper:样式设置
                                li:{
                                    selfClass:{}//.li:样式设置
                                }
                            },
                            recoder:{
                                selfClass:{}//.recoder:样式设置
                            }
                        }
                    }
                }
            }

使用方式:
$(function () {
var result=null;
    var option = {
        el: $(".glSelect"),
        isOpenSearch: false,
        slideSpeed:100,
        direction:'vertical'
    }
    $.fn.select(basePath + "/project/getSelect",option,args=>{
        result=args;
    });

})
result就是我们最终需要的model
每次修改result都是最新的值

其中之一的效果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/sunboylife/article/details/109994938