依赖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都是最新的值
其中之一的效果: