699 lines
19 KiB
JavaScript
699 lines
19 KiB
JavaScript
|
|
/**
|
|||
|
|
* @Name: 基于layui的异步无限级联选择器
|
|||
|
|
* @Author: 前端喵
|
|||
|
|
* 创建时间: 2019/05/23
|
|||
|
|
* 使用说明: 在主文件里面使用layui.config设置,具体方法看index.html
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 参数说明:
|
|||
|
|
* width(可选) :input框宽度
|
|||
|
|
* height(可选):input框高度
|
|||
|
|
*/
|
|||
|
|
layui.define(["jquery"],(exports)=>{
|
|||
|
|
let $ = layui.jquery;
|
|||
|
|
// 私有方法,禁止外面调用的方法
|
|||
|
|
function Private(){
|
|||
|
|
//页面初始化默认值
|
|||
|
|
this.param = {
|
|||
|
|
width: 220,
|
|||
|
|
height: 40,
|
|||
|
|
prop: {
|
|||
|
|
value: "value",
|
|||
|
|
label: "label",
|
|||
|
|
children: 'children'
|
|||
|
|
},
|
|||
|
|
clicklast: false,
|
|||
|
|
time: 250,
|
|||
|
|
placeholder: "请选择",
|
|||
|
|
search: {
|
|||
|
|
show: false,
|
|||
|
|
minLabel: 10,
|
|||
|
|
placeholder: '请输入搜索词'
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
// 定义全局状态仓库
|
|||
|
|
this.store = {
|
|||
|
|
showCascader: false,
|
|||
|
|
cascaderDom: null, // 当前elem对象
|
|||
|
|
cascaderAll: null, // 生成的Dom主对象
|
|||
|
|
input: null, // input框dom
|
|||
|
|
inputI: null, // input框箭头dom
|
|||
|
|
model: null, // 下拉菜单的主dom
|
|||
|
|
li: null, // li标签
|
|||
|
|
parentNextAll: null, // 当前操作的li标签元素后面所有ul集合
|
|||
|
|
brother: null, // li标签同级dom集合
|
|||
|
|
data: [], // 所有从后端异步请求的数据集合
|
|||
|
|
chooseData: [], // 已选中的数据集
|
|||
|
|
zIndex: 2000 // 显示顺序
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 页面初始化
|
|||
|
|
Private.prototype.init = function(options){
|
|||
|
|
let store = this.store
|
|||
|
|
let param = this.param
|
|||
|
|
// dom变量初始化
|
|||
|
|
store.cascaderDom = $(options.elem)
|
|||
|
|
|
|||
|
|
// 把用户的参数值进行存储
|
|||
|
|
// 开始存储
|
|||
|
|
for (let i in options) {
|
|||
|
|
if (options[i].length !== 0) {
|
|||
|
|
if (i == "prop" | i == 'search') {
|
|||
|
|
for (let x in options[i]) {
|
|||
|
|
param[i][x] = options[i][x]
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
param[i] = options[i]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
delete param.data
|
|||
|
|
if (options.data) {
|
|||
|
|
store.data = options.data
|
|||
|
|
}
|
|||
|
|
param.device = this.checkDevice()
|
|||
|
|
// 存储结束
|
|||
|
|
if (store.cascaderDom.next().hasClass('cascader-all')) {
|
|||
|
|
store.cascaderDom.next().remove()
|
|||
|
|
}
|
|||
|
|
param.className = 'cascader-' + this.param.elem.replace('#', '')
|
|||
|
|
let phoneName = ''
|
|||
|
|
if (param.device === 1) {
|
|||
|
|
phoneName = 'cascader-model-phone'
|
|||
|
|
}
|
|||
|
|
// 渲染主dom
|
|||
|
|
store.cascaderDom.after(`
|
|||
|
|
<div class="cascader-all ` + param.className + `" style="width:`+this.param.width+`px;">
|
|||
|
|
<input type="text" class="layui-input cascader-input" placeholder="`+param.placeholder+`" readonly style="width:`+this.param.width+`px;height:`+this.param.height+`px;">
|
|||
|
|
<i class="layui-icon layui-icon-down cascader-i" style="top:`+this.param.height/2+`px;"></i>
|
|||
|
|
<div class="cascader-model ` + phoneName + `" style="z-index:`+this.store.zIndex+`;display:flex;">
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
`)
|
|||
|
|
|
|||
|
|
// 判断elem是否存在以及是否正确,elem必填
|
|||
|
|
if(!options.elem || options.elem == ""){
|
|||
|
|
layer.msg('请配置有效的elem值 ')
|
|||
|
|
}else if($(options.elem).length == 0){
|
|||
|
|
layer.msg('请配置有效的elem值 ')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
store.input = store.cascaderDom.nextAll().find('.cascader-input')
|
|||
|
|
store.inputI = store.input.next()
|
|||
|
|
store.cascaderAll = $(store.cascaderDom.nextAll()[0])
|
|||
|
|
store.model = store.cascaderDom.nextAll().find('.cascader-model')
|
|||
|
|
store.li = store.model.find('li')
|
|||
|
|
// 全局状态初始化
|
|||
|
|
store.model.hide()
|
|||
|
|
|
|||
|
|
if (store.data.length == 0) {
|
|||
|
|
param.getChildren(param.value, data => {
|
|||
|
|
store.data = data
|
|||
|
|
this.liHtml(store.data)
|
|||
|
|
if (param.checkData) {
|
|||
|
|
if (param.checkData.length > 0) {
|
|||
|
|
this.dataToshow(param.checkData)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
} else {
|
|||
|
|
this.liHtml(store.data)
|
|||
|
|
if (param.checkData) {
|
|||
|
|
if (param.checkData.length > 0) {
|
|||
|
|
this.dataToshow(param.checkData)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 先进入是否禁用判断事件
|
|||
|
|
// 不禁用则执行下面的事件
|
|||
|
|
this.disabled()
|
|||
|
|
.then(res => {
|
|||
|
|
this.inputClick(options)
|
|||
|
|
this.liClick()
|
|||
|
|
this.liHover()
|
|||
|
|
this.modelHandle()
|
|||
|
|
if (param.search.show) {
|
|||
|
|
this.handleSearch()
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 判断是否禁用
|
|||
|
|
Private.prototype.disabled = function() {
|
|||
|
|
const disabled = this.param.disabled
|
|||
|
|
const cascaderAll = this.store.cascaderAll
|
|||
|
|
const input = this.store.input
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
if (disabled) {
|
|||
|
|
cascaderAll.addClass('cascader-disabled')
|
|||
|
|
}else{
|
|||
|
|
resolve()
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// li标签赋值方法
|
|||
|
|
// key为string类型
|
|||
|
|
Private.prototype.liHtml = function(data, key, choose){
|
|||
|
|
let lis=[]
|
|||
|
|
let param = this.param
|
|||
|
|
let store = this.store
|
|||
|
|
let position = []
|
|||
|
|
let key1 = ''
|
|||
|
|
if (!key || key.length == 0) {
|
|||
|
|
key=""
|
|||
|
|
} else {
|
|||
|
|
key = key.join('-')
|
|||
|
|
key1 = key
|
|||
|
|
key = key+"-"
|
|||
|
|
}
|
|||
|
|
if (data !== "") {
|
|||
|
|
for (let i in data) {
|
|||
|
|
let li = '<li value="'+data[i][param.prop.value]+'" key="'+key+i+'"'
|
|||
|
|
if (i == choose) {
|
|||
|
|
li = li +' class="cascader-choose-active"'
|
|||
|
|
position = [i,data.length]
|
|||
|
|
}
|
|||
|
|
// 来自于陈诗樵的BUG修复,github地址:https://github.com/alasq
|
|||
|
|
// data[i].children 改为 data[i][param.prop.children]
|
|||
|
|
if (data[i].hasChild == true || data[i][param.prop.children]) {
|
|||
|
|
li = li+'>'+data[i][param.prop.label]+'<i class="layui-icon layui-icon-right"></i></li>'
|
|||
|
|
} else {
|
|||
|
|
li = li+'>'+data[i][param.prop.label]+'</li>'
|
|||
|
|
}
|
|||
|
|
lis.push(li)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
lis = lis.join('')
|
|||
|
|
if (data && data.length>0){
|
|||
|
|
if (param.search.show && data.length > param.search.minLabel) {
|
|||
|
|
lis = '<input class="layui-input cascader-model-input" key="'+ key1 + '" placeholder="'+ param.search.placeholder +'">' + lis
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
lis = '<p class="nodata">暂无数据</p>'
|
|||
|
|
console.log('数据为空,无法进行渲染')
|
|||
|
|
}
|
|||
|
|
let ul = $(`
|
|||
|
|
<ul class="cascader-ul">`+lis+`</ul>
|
|||
|
|
`)
|
|||
|
|
ul.fadeIn('fast')
|
|||
|
|
store.model.append(ul)
|
|||
|
|
this.liPosition(position)
|
|||
|
|
this.ModelPosition()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 当前选中的跳转位置
|
|||
|
|
Private.prototype.liPosition = function(position) {
|
|||
|
|
let model = this.store.model.find('ul').last()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Private.prototype.handleSearch = function() {
|
|||
|
|
let model = this.store.model
|
|||
|
|
let prop = this.param.prop
|
|||
|
|
let _this = this
|
|||
|
|
let value = ''
|
|||
|
|
let flag = true
|
|||
|
|
model.on('compositionstart',function(){
|
|||
|
|
flag = false
|
|||
|
|
})
|
|||
|
|
model.on('compositionend',function(){
|
|||
|
|
flag = true
|
|||
|
|
})
|
|||
|
|
model.on('input', 'input', function() {
|
|||
|
|
setTimeout(()=>{
|
|||
|
|
if (flag) {
|
|||
|
|
let data = _this.store.data
|
|||
|
|
if (value == this.value) {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
value = this.value
|
|||
|
|
let key = $(this).attr('key').split('-')
|
|||
|
|
let key1 = $(this).attr('key') + '-'
|
|||
|
|
if ($(this).attr('key')) {
|
|||
|
|
for (i in key) {
|
|||
|
|
if (data[key[i]][prop.children]){
|
|||
|
|
data = data[key[i]][prop.children]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
let renderData = []
|
|||
|
|
let lis = ''
|
|||
|
|
for (i in data) {
|
|||
|
|
if (data[i][prop.label].indexOf(value) > -1) {
|
|||
|
|
if (data[i][prop.children] | data[i].hasChild) {
|
|||
|
|
lis += '<li value="'+data[i][prop.value]+'" key="'+key1+i+'">'+data[i][prop.label]+'<i class="layui-icon layui-icon-right"></i></li>'
|
|||
|
|
} else {
|
|||
|
|
lis += '<li value="'+data[i][prop.value]+'" key="'+key1+i+'">'+data[i][prop.label]+'</li>'
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
renderData.push(data[i])
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
$(this.parentNode).find('li').remove()
|
|||
|
|
$(this.parentNode).append(lis)
|
|||
|
|
}
|
|||
|
|
}, 0)
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Private.prototype.modelHandle = function() {
|
|||
|
|
$(window).resize(() => { //当浏览器大小变化时
|
|||
|
|
let model = this.store.model
|
|||
|
|
this.ModelPosition()
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let modelWidth = 0
|
|||
|
|
Private.prototype.ModelPosition = function() {
|
|||
|
|
let model = this.store.model
|
|||
|
|
let input = this.store.input
|
|||
|
|
let BodyWidth = document.documentElement.clientWidth
|
|||
|
|
let positionLeft = 0,
|
|||
|
|
left = 0
|
|||
|
|
if (window.getComputedStyle(model[0]).width !== "auto") {
|
|||
|
|
modelWidth = window.getComputedStyle(model[0]).width.replace('px','')
|
|||
|
|
}
|
|||
|
|
left = input.offset().left - model.position().left
|
|||
|
|
if (BodyWidth < modelWidth) {
|
|||
|
|
positionLeft = BodyWidth - modelWidth
|
|||
|
|
}
|
|||
|
|
if (positionLeft < 0) {
|
|||
|
|
model.css("left",positionLeft - 30)
|
|||
|
|
} else {
|
|||
|
|
model.css('left',0)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 鼠标hover监听事件[li标签]
|
|||
|
|
Private.prototype.liHover = function(){
|
|||
|
|
let store = this.store
|
|||
|
|
let param = this.param
|
|||
|
|
let _this = this
|
|||
|
|
store.model.on('mouseenter', 'li', function() {
|
|||
|
|
store.parentNextAll = $(this).parent("ul").nextAll()
|
|||
|
|
store.brother = $(this).siblings()
|
|||
|
|
if ($(this).find('i').length == 0) {
|
|||
|
|
store.parentNextAll.fadeOut('fast', function() {
|
|||
|
|
store.parentNextAll.remove()
|
|||
|
|
})
|
|||
|
|
} else {
|
|||
|
|
let keys=$(this).attr('key')
|
|||
|
|
let value = $(this).attr('value')
|
|||
|
|
let data = _this.store.data
|
|||
|
|
let childrenName = _this.param.prop.children
|
|||
|
|
keys = keys.split('-')
|
|||
|
|
let goodData = data
|
|||
|
|
|
|||
|
|
for (let i in keys) {
|
|||
|
|
let key = keys[i]
|
|||
|
|
if (goodData) {
|
|||
|
|
if (goodData[key]) {
|
|||
|
|
goodData = goodData[key][childrenName]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!goodData) {
|
|||
|
|
param.getChildren(value, datax => {
|
|||
|
|
goodData = datax
|
|||
|
|
let children = data
|
|||
|
|
if (goodData && goodData.length != 0) {
|
|||
|
|
for (let i in keys) {
|
|||
|
|
if (i == keys.length - 1) {
|
|||
|
|
children = goodData
|
|||
|
|
} else {
|
|||
|
|
if (!children[keys[i]][childrenName]) {
|
|||
|
|
children[keys[i]][childrenName] = new Array()
|
|||
|
|
}
|
|||
|
|
children = children[keys[i]][childrenName]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
DataTreeAdd(data,goodData,keys)
|
|||
|
|
store.parentNextAll = $(this).parent("ul").nextAll()
|
|||
|
|
store.parentNextAll.remove()
|
|||
|
|
_this.liHtml(goodData, keys)
|
|||
|
|
} else {
|
|||
|
|
$(this).find('i').remove()
|
|||
|
|
store.parentNextAll.remove()
|
|||
|
|
DataTreeChange(data, keys)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
} else {
|
|||
|
|
store.parentNextAll.remove()
|
|||
|
|
_this.liHtml(goodData, keys)
|
|||
|
|
}
|
|||
|
|
// 增加data的树结点
|
|||
|
|
function DataTreeAdd(data, newData, keys) {
|
|||
|
|
let array = data
|
|||
|
|
for (let k in keys) {
|
|||
|
|
if (k < keys.length -1) {
|
|||
|
|
array = array[keys[k]][param.prop.children]
|
|||
|
|
} else {
|
|||
|
|
array = array[keys[k]]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
array.children = newData
|
|||
|
|
}
|
|||
|
|
function DataTreeChange(data, keys) {
|
|||
|
|
let array = data
|
|||
|
|
for (let k in keys) {
|
|||
|
|
if (k < keys.length -1) {
|
|||
|
|
array = array[keys[k]][param.prop.children]
|
|||
|
|
} else {
|
|||
|
|
array = array[keys[k]]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
array.hasChild = false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
$(this).addClass('cascader-choose-active')
|
|||
|
|
store.brother.removeClass('cascader-choose-active')
|
|||
|
|
store.parentNextAll.children().removeClass('cascader-choose-active')
|
|||
|
|
|
|||
|
|
// 获取所有的已选中的数据,并回显至input选择框中
|
|||
|
|
// _this.getChooseData();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 鼠标点击监听事件[li标签]
|
|||
|
|
Private.prototype.liClick = function() {
|
|||
|
|
let _this = this
|
|||
|
|
let store = this.store
|
|||
|
|
let param = this.param
|
|||
|
|
let className = param.className
|
|||
|
|
// store.model为一个自定义dom对象
|
|||
|
|
if (param.clicklast == false) {
|
|||
|
|
store.model.on('click', 'li', function() {
|
|||
|
|
_this.getChooseData()
|
|||
|
|
store.showCascader = !store.showCascader
|
|||
|
|
if (param.device === 1){
|
|||
|
|
|
|||
|
|
} else {
|
|||
|
|
store.model.slideUp(_this.param.time)
|
|||
|
|
}
|
|||
|
|
store.inputI.removeClass('rotate')
|
|||
|
|
})
|
|||
|
|
} else {
|
|||
|
|
store.model.on('click', 'li', function() {
|
|||
|
|
store.parentNextAll = $(this).parent("ul").nextAll()
|
|||
|
|
if (store.parentNextAll.length == 0) {
|
|||
|
|
_this.getChooseData()
|
|||
|
|
store.showCascader = !store.showCascader
|
|||
|
|
if (param.device === 1){
|
|||
|
|
|
|||
|
|
} else {
|
|||
|
|
store.model.slideUp(_this.param.time)
|
|||
|
|
}
|
|||
|
|
store.inputI.removeClass('rotate')
|
|||
|
|
_this.getThisData()
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 判断当前访问客户端是PC还是移动端
|
|||
|
|
// PC端返回1,移动端返回0
|
|||
|
|
Private.prototype.checkDevice = function() {
|
|||
|
|
if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
|
|||
|
|
return 1
|
|||
|
|
} else {
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取当前层级数据
|
|||
|
|
Private.prototype.getThisData = function() {
|
|||
|
|
let value = this.param.prop.value
|
|||
|
|
,children = this.param.prop.children
|
|||
|
|
,chooseData = this.store.chooseData
|
|||
|
|
,data = this.store.data
|
|||
|
|
,currentData = []
|
|||
|
|
for (const i in chooseData) {
|
|||
|
|
for (const x in data) {
|
|||
|
|
if (chooseData[i] == data[x][value]) {
|
|||
|
|
if (Number(i) === chooseData.length - 1) {
|
|||
|
|
currentData = JSON.parse(JSON.stringify(data[x]))
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
if (data[x][children]) {
|
|||
|
|
data = data[x][children]
|
|||
|
|
} else {
|
|||
|
|
data = data[x]
|
|||
|
|
}
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return currentData
|
|||
|
|
}
|
|||
|
|
// 鼠标监听事件[input控件]
|
|||
|
|
Private.prototype.inputClick = function(options) {
|
|||
|
|
let store = this.store
|
|||
|
|
let param = this.param
|
|||
|
|
let _this = this
|
|||
|
|
$(document).click(function(e) {
|
|||
|
|
let className = e.target.className
|
|||
|
|
className = className.split(" ")
|
|||
|
|
let other = ['cascader-input', 'cascader-model', "cascader-choose-active", "layui-icon-right", "cascader-ul", "cascader-model-input"]
|
|||
|
|
for (let i in className) {
|
|||
|
|
for (let x in other) {
|
|||
|
|
if (className[i] == other[x]) {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
store.showCascader = false
|
|||
|
|
store.model.slideUp(_this.param.time)
|
|||
|
|
store.inputI.removeClass('rotate')
|
|||
|
|
});
|
|||
|
|
store.input.click(function() {
|
|||
|
|
store.showCascader = !store.showCascader
|
|||
|
|
if (store.showCascader == true) {
|
|||
|
|
store.inputI.addClass('rotate')
|
|||
|
|
let chooseData = _this.store.chooseData
|
|||
|
|
let data = _this.store.data
|
|||
|
|
if (chooseData.length !== 0) {
|
|||
|
|
let key = []
|
|||
|
|
_this.clearModel()
|
|||
|
|
for (let i in chooseData) {
|
|||
|
|
for (let x in data) {
|
|||
|
|
if (data[x][param.prop.value] == chooseData[i]) {
|
|||
|
|
_this.liHtml(data,key,x)
|
|||
|
|
key.unshift(x)
|
|||
|
|
data = data[x][param.prop.children]
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
store.model.slideDown(_this.param.time)
|
|||
|
|
_this.ModelPosition()
|
|||
|
|
} else {
|
|||
|
|
store.model.slideUp(_this.param.time)
|
|||
|
|
store.inputI.removeClass('rotate')
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取页面中选中的数据
|
|||
|
|
Private.prototype.getChooseData = function() {
|
|||
|
|
let store = this.store
|
|||
|
|
let chooseDom = store.model.find('li.cascader-choose-active')
|
|||
|
|
let chooseData = [];
|
|||
|
|
let chooseLabel = [];
|
|||
|
|
for(let i in chooseDom){
|
|||
|
|
if(chooseDom[i].innerText){
|
|||
|
|
chooseData.push($(chooseDom[i]).attr('value'));
|
|||
|
|
chooseLabel.push(chooseDom[i].innerText);
|
|||
|
|
}else{
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
this.store.chooseData = chooseData;
|
|||
|
|
this.inputValueChange(chooseLabel);
|
|||
|
|
}
|
|||
|
|
Private.prototype.inputValueChange = function(label){
|
|||
|
|
let store = this.store;
|
|||
|
|
let param = this.param;
|
|||
|
|
if(param.showlast == true){
|
|||
|
|
label = label[label.length-1];
|
|||
|
|
}else{
|
|||
|
|
label = label.join('/');
|
|||
|
|
}
|
|||
|
|
store.input.val(label);
|
|||
|
|
let fontWidth = store.input.css('font-size').replace('px',''),
|
|||
|
|
inputWidth = store.input.width(),
|
|||
|
|
labelWidth = label.length;
|
|||
|
|
let maxLabelWidth = Math.floor(inputWidth/fontWidth);
|
|||
|
|
if(labelWidth>maxLabelWidth){
|
|||
|
|
store.input.attr('title',label);
|
|||
|
|
}else{
|
|||
|
|
store.input.attr('title',"");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 数据回显
|
|||
|
|
Private.prototype.dataToshow = function(checkData){
|
|||
|
|
let param = this.param;
|
|||
|
|
let store = this.store;
|
|||
|
|
let backData = []; //后端数据集合
|
|||
|
|
let chooseLabel=[]; //选中的项对应的label值
|
|||
|
|
let keys=[]; //checkData在数据源中的位置大全
|
|||
|
|
backData[0] = store.data;
|
|||
|
|
let flag = 1;
|
|||
|
|
if(param.getChildren){
|
|||
|
|
if (checkData.length === 1) {
|
|||
|
|
for (let i in store.data) {
|
|||
|
|
if (store.data[i][param.prop.value] == checkData[0]) {
|
|||
|
|
let label = store.data[i][param.prop.label].split(',')
|
|||
|
|
this.inputValueChange(label)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
for(let i=1; i<checkData.length; i++){
|
|||
|
|
if(i < checkData.length){
|
|||
|
|
param.getChildren(checkData[i-1],data=>{
|
|||
|
|
backData[i] = data;
|
|||
|
|
flag++;
|
|||
|
|
if(flag == checkData.length){
|
|||
|
|
for(let i=checkData.length -1;i>=0;i--){
|
|||
|
|
for(let x in backData[i]){
|
|||
|
|
if(checkData[i] == backData[i][x][param.prop.value]){
|
|||
|
|
keys.unshift(x);
|
|||
|
|
chooseLabel.unshift(backData[i][x][param.prop.label])
|
|||
|
|
if(i < checkData.length -1){
|
|||
|
|
backData[i][x][param.prop.children] = backData[i+1];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
store.data = backData[0];
|
|||
|
|
|
|||
|
|
// input框数据回显
|
|||
|
|
this.inputValueChange(chooseLabel);
|
|||
|
|
this.clearModel();
|
|||
|
|
// 选择器数据回显
|
|||
|
|
let key = [];
|
|||
|
|
for(let i in backData){
|
|||
|
|
if(i !== "0"){
|
|||
|
|
key.push(keys[i-1]);
|
|||
|
|
}
|
|||
|
|
this.liHtml(backData[i],key,keys[i]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}else{
|
|||
|
|
let storeData = store.data;
|
|||
|
|
for(let x in checkData){
|
|||
|
|
for(let i in storeData){
|
|||
|
|
if(storeData[i][param.prop.value] == checkData[x]){
|
|||
|
|
chooseLabel.push(storeData[i][param.prop.label]);
|
|||
|
|
keys.push(i)
|
|||
|
|
storeData = storeData[i][param.prop.children];
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// input框数据回显
|
|||
|
|
this.inputValueChange(chooseLabel);
|
|||
|
|
this.store.chooseData = checkData;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
// 清空ul标签
|
|||
|
|
Private.prototype.clearModel = function(){
|
|||
|
|
let store = this.store;
|
|||
|
|
store.model.html('');
|
|||
|
|
}
|
|||
|
|
// 监听下拉菜单的位置
|
|||
|
|
Private.prototype.handlePosition = function(){
|
|||
|
|
// 当前屏幕大小
|
|||
|
|
// let bodyWidth =
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let privates = new Array();
|
|||
|
|
let dom_num = 0;
|
|||
|
|
// 暴露给外界使用的方法
|
|||
|
|
let cascader = {
|
|||
|
|
|
|||
|
|
// 页面初始化
|
|||
|
|
load: function load(options) {
|
|||
|
|
let current = null
|
|||
|
|
for (let i in privates) {
|
|||
|
|
if(privates[i].elem === options.elem){
|
|||
|
|
current = i
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (!current) {
|
|||
|
|
current = dom_num
|
|||
|
|
dom_num ++
|
|||
|
|
privates[current] = new Array()
|
|||
|
|
privates[current].obj = new Private()
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
privates[current].elem = options.elem
|
|||
|
|
privates[current].obj.store.zIndex -= current
|
|||
|
|
privates[current].obj.store.data = []
|
|||
|
|
if (options.chooseData) {
|
|||
|
|
privates[current].obj.store.chooseData = options.chooseData
|
|||
|
|
} else {
|
|||
|
|
privates[current].obj.store.chooseData = []
|
|||
|
|
}
|
|||
|
|
privates[current].obj.init(options)
|
|||
|
|
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 获取页面中选中的数据,数组形式
|
|||
|
|
getChooseData: function(elem){
|
|||
|
|
let obj = this.elemCheck(elem);
|
|||
|
|
return obj.store.chooseData;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 监听方法
|
|||
|
|
on: function(type,elem,callback){
|
|||
|
|
let obj = this.elemCheck(elem)
|
|||
|
|
let className = obj.param.className
|
|||
|
|
if(type == "click"){
|
|||
|
|
$(document).on('click','.' + className + ' li',function(){
|
|||
|
|
setTimeout(function(){
|
|||
|
|
let data = obj.getThisData()
|
|||
|
|
if(obj.param.clicklast === false){
|
|||
|
|
callback(data)
|
|||
|
|
}else{
|
|||
|
|
if(obj.store.parentNextAll.length == 0){
|
|||
|
|
callback(data)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},50)
|
|||
|
|
});
|
|||
|
|
}else if(type == "hover"){
|
|||
|
|
obj.store.model.on('mouseenter','li',function(){
|
|||
|
|
callback();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// elem位置判断,禁止外界调用,因为你调也没啥卵用
|
|||
|
|
elemCheck:function(elem){
|
|||
|
|
if(!elem){
|
|||
|
|
return privates[0].obj;
|
|||
|
|
}
|
|||
|
|
for(let i in privates){
|
|||
|
|
if(privates[i].elem == elem){
|
|||
|
|
return privates[i].obj;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
layui.link(layui.cache.base + 'ajaxCascader.css');
|
|||
|
|
exports('ajaxCascader',cascader);
|
|||
|
|
});
|