layui树形组件懒加载实现
工作中需要用到Layui前端框架,但使用过程中发现需要用到树形组件懒加载方式,可惜的是Layui仍未实现树形组件懒加载,网上大神们写了好多文章介绍但总感觉不如自己写一个。以下代码比较多,可能读者没有耐心看完,我权当是自己作一下笔记吧,以后想起来的时候会持续更新下去,若有什么好的建议,希望能下方给我留言,我一定会想办法改进…
使用方式也在后方通过实例展示。代码最初不是很多的,只实现了懒加载功能,可后面持续用到懒加载下拉树、懒加载下拉框树形组件、懒加载表格下拉框树形组件,代码便这样慢慢积累起来了。很多方法及实现方式是参考的layui.js
,很希望贤心有闲心的时候完善一下layui吧。如果还是不明白,建议直接研读原码,希望能给大家带来帮助。
一、js代码如下:
/**
@Name:layui.treelazy 树,懒加载实现
@Author:xxx
@License:MIT
*/
layui.define('form', function(exports) {
"use strict";
var $ = layui.$,
form = layui.form
//模块名
,
MOD_NAME = 'treelazy'
//外部接口
,
treelazy = {
config: {},
index: layui[MOD_NAME] ? (layui[MOD_NAME].index + 10000) : 0
//设置全局项
,
set: function(options) {
var that = this;
that.config = $.extend({}, that.config, options);
return that;
}
//事件监听
,
on: function(events, callback) {
return layui.onevent.call(this, MOD_NAME, events, callback);
}
}
//操作当前实例
,
thisModule = function() {
var that = this,
options = that.config,
id = options.id || that.index;
thisModule.that[id] = that; //记录当前实例对象
thisModule.config[id] = options; //记录当前实例配置项
return {
config: options
//重置实例
,
reload: function(options) {
that.reload.call(that, options);
},
getChecked: function() {
return that.getChecked.call(that);
},
setChecked: function(id) { //设置值
return that.setChecked.call(that, id);
}
}
}
//获取当前实例配置项
,
getThisModuleConfig = function(id) {
var config = thisModule.config[id];
if (!config) hint.error('The ID option was not found in the ' + MOD_NAME + ' instance');
return config || null;
}
//字符常量
,
SHOW = 'layui-show',
HIDE = 'layui-hide',
NONE = 'layui-none',
DISABLED = 'layui-disabled'
,
ELEM_VIEW = 'layui-tree',
ELEM_SET = 'layui-tree-set',
ICON_CLICK = 'layui-tree-iconClick',
ICON_ADD = 'layui-icon-addition',
ICON_SUB = 'layui-icon-subtraction',
ELEM_ENTRY = 'layui-tree-entry',
ELEM_MAIN = 'layui-tree-main',
ELEM_TEXT = 'layui-tree-txt',
ELEM_PACK = 'layui-tree-pack',
ELEM_SPREAD = 'layui-tree-spread',
ELEM_LINE_SHORT = 'layui-tree-setLineShort',
ELEM_SHOW = 'layui-tree-showLine',
ELEM_EXTEND = 'layui-tree-lineExtend'
//构造器
,
Class = function(options) {
var that = this;
that.index = ++treelazy.index;
that.config = $.extend({}, that.config, treelazy.config, options);
that.render();
};
treelazy.setTitle = function(elem, title, id) {
elem.replace('#', '');
$('#' + elem).find('option').val(id);
var select = $('#' + elem).next().find('input').val(title);
};
treelazy.treeselect = function(param) {
var elem = param.elem; //id
var width = param.width ? param.width + 'px' : '100%'; //下拉框文本宽度,默认100%,默认单位px
var height = param.height ? param.height + 'px' : '200px'; //下拉框高,默认100px
var placeholder = param.placeholder || '请选择';
var first = param.first || false; //是否默认选中第一行
var selectFontColor = param.selectFontColor || '#9F6277'; //默认选中文本颜色,默认#9F6277
var onlyIconControl = param.onlyIconControl || false; //只能点击图标展开收缩,默认false
var onlyLeafClick = param.onlyLeafClick || false; //只有点击叶子节点才执行点击方法,默认false
var treeid = 'tree_' + elem.substring(1);
//渲染html
var select = $(elem);
if (select.next().length > 0) {
//删除layui渲染的下拉框
select.next().remove();
}
var disabled = select.attr('disabled');
var disabledClass = disabled ? 'layui-disabled' : '';
var option = $('<option>');
var form_select = $('<div class="layui-unselect layui-form-select layui-treeselect" style="width:' + width + ';">');
var select_title = $('<div class="layui-select-title">');
var input = $('<input type="text" placeholder="' + placeholder + '" readonly class="layui-input layui-unselect ' +
disabledClass + '" ' + disabled + '>');
var edge = $('<i class="layui-edge"></i>');
var anim = $('<dl class="layui-anim layui-anim-upbit" >');
var dd = $('<dd>');
dd.css('height', height);
var treeDiv = $('<div id="' + treeid + '">');
//组装入页面
select_title.append(input);
select_title.append(edge);
dd.append(treeDiv);
anim.append(dd);
form_select.append(select_title);
form_select.append(anim);
select.after(form_select);
select.append(option);
//绑定事件
select_title.on('click', function() {
var isDisabled = $(this).parent().prev().attr('disabled');
if (!isDisabled) {
$(this).next().toggle();
}
});
//初始化渲染树形组件1
treelazy.render({
elem: '#' + treeid, //绑定元素
id: treeid,
onlyIconControl: onlyIconControl,
onlyLeafClick: onlyLeafClick,
selectFontColor: selectFontColor,
load: function(node, render) {
param.load(node, function(datas) {
if (first && node.level == 0) {
option.val(datas[0].id);
input.val(datas[0].text);
}
render(datas);
});
},
click: function(obj) {
//返回选中记录
option.val(obj.data.id);
input.val(obj.data.text);
//收回下拉框
// $(elem).next().removeClass('layui-form-selected');
$(elem).next().find('.layui-anim').hide();
//回调点击方法
param.click ? param.click(obj) : '';
}
});
$(document).on("click", function(e) {
//点击下拉框外的区域时,关闭下拉框
var target = $(e.target).parents('.layui-treeselect');
var targetId = target.prev().attr('id');
if (target.length == 0 || targetId != elem.substring(1)) {
// $(elem).next().removeClass('layui-form-selected');
$(elem).next().find('.layui-anim').hide();
}
});
}
treelazy.tabletreeselect = function(param) {
//传入参数
var _tID = param.tableID;
var _td = param.td;
var _colName = param.colName;
//获取参数
var $ = layui.$,
table = layui.table,
treelazy = layui.treelazy;
var _rowIndex = _td.parent().data('index'); //获取下标
var animID = _tID + '_' + _colName + '_anim';
var cell = _td.find('.layui-table-cell').eq(0);
//获取单元格内容
var value = table.cache[_tID][_rowIndex][_colName]; //id:实际值
var text = cell.text(); //显示值
//设置单元格获取焦点时的样式
cell.css({
'border': '1px solid #008CBA',
'padding': '0',
'box-shadow': '1px 1px 20px rgba(0, 10, 10, .15)'
});
//构建单元格中下拉框的ID
var selectId = "select_" + _tID + "_" + _rowIndex;
//如果没有构建下拉框,则开始构建
if ($("#" + selectId).length == 0) {
var closeFlag = true; //标记是否销毁表格下拉框
var selectDiv = $('<div class="layui-form-select layui-table-select">');
var input = $('<input type="text" id="' + selectId + '" value="' + text +
'" readonly="" class="layui-input">');
input.data('value', value);
var edge = $('<i class="layui-edge"></i>');
//下拉图标点击事件
edge.on('click', function(e) {
input.trigger('click');
});
//下拉框失去焦点事件:判断是否销毁下拉框
input.on('blur', function(e) {
if (closeFlag) {
closeTableselect();
} else {
input.focus();
}
});
//下拉框点击事件:切换下拉框显示隐藏
input.on('click', function(e) {
if ($("#" + animID).hasClass('layui-hide')) {
$("#" + animID).removeClass('layui-hide')
} else {
$("#" + animID).addClass('layui-hide')
}
});
//将下拉框载入单元格
selectDiv.append(input).append(edge);
cell.append(selectDiv);
input.focus();
//计算下拉框弹出框的位置及样式
if ($("#" + animID).length == 0) {
//自动创建弹出框
var tree_id = animID + '_tree';
var $anim = $('<div class="layui-hide layui-table-select-anim" id="' + animID + '">');
var $anim_select = $('<div class="layui-form-select">');
var $anim_upbit = $('<dl class="layui-anim layui-anim-upbit" style="display: block;">');
var $anim_dd = $('<dd style="height: 200px;">');
var $anim_tree = $('<div id="' + tree_id + '"></div>');
//载入body
$anim_dd.append($anim_tree);
$anim_upbit.append($anim_dd);
$anim_select.append($anim_upbit);
$anim.append($anim_select);
$('body').append($anim);
//初始化渲染下拉树
treelazy.render({
elem: '#' + tree_id, //绑定元素
id: tree_id,
showCheckbox: false,
onlyIconControl: true,
onlyLeafClick: false,
load: function(node, render) {
if (param.load) {
param.load(node, render);
} else {
}
},
click: function(obj) {
$("#" + animID).addClass('layui-hide');
var id = obj.data.id;
var text = obj.data.text;
var tableselect = $(".layui-table-select");
if (tableselect.length > 0) {
tableselect.find('input').val(text);
tableselect.find('input').data("value", id);
}
if (param.click) {
param.click(obj);
}
}
});
}
$("#" + animID).find(".layui-form-select").width(cell.width());
var animTop = cell.offset().top - 1;
var animLeft = cell.offset().left;
var winHeight = $(window).height();
var animHeight = $("#" + animID).find('dd').height();
if (animTop >= winHeight - animHeight) {
animTop = animTop - animHeight - cell.height() - 18;
}
$("#" + animID).css({
'position': 'absolute',
'left': cell.offset().left + 'px',
'top': animTop + 'px'
});
//下拉框弹出框鼠标止悬停时,标记不销毁下拉框
$("#" + animID).find('dd').on('mouseover', function(e) {
closeFlag = false;
}).on('mouseleave', function(e) {
closeFlag = true;
});
//下拉框鼠标止悬停时,标记不销毁下拉框
input.next().on('mouseover', function(e) {
closeFlag = false;
}).on('mouseleave', function(e) {
closeFlag = true;
});
//窗口尺寸变化时,销毁下拉框
$(window).resize(function() {
closeTableselect();
});
//表格滚动时,销毁下拉框
cell.parents('.layui-table-main').scroll(function() {
closeTableselect();
});
// 关闭表格中的下拉树形组件方法
function closeTableselect() {
cell.css({
'border': 'none',
'padding': '0 6px',
'box-shadow': 'none'
});
var value = selectDiv.find('input').data('value');
var text = selectDiv.find('input').val();
table.cache[_tID][_rowIndex][_colName] = value;
cell.text(text);
selectDiv.remove();
$("#" + animID).addClass('layui-hide');
}
}
}
//默认配置
Class.prototype.config = {
data: [] //数据
,
showCheckbox: false //是否显示复选框
,
showLine: true //是否开启连接线
,
accordion: false //是否开启手风琴模式
,
onlyIconControl: false //是否仅允许节点左侧图标控制展开收缩
,
isJump: false //是否允许点击节点时弹出新窗口跳转
,
edit: false //是否开启节点的操作图标
//,showSearch: false //是否打开节点过滤
//,drag: false //是否开启节点拖拽
,
text: {
defaultNodeName: '未命名' //节点默认名称
,
none: '无数据' //数据为空时的文本提示
}
};
//重载实例
Class.prototype.reload = function(options) {
var that = this;
layui.each(options, function(key, item) {
if (item.constructor === Array) delete that.config[key];
});
that.config = $.extend(true, {}, that.config, options);
that.render();
};
//主体渲染
Class.prototype.render = function() {
var that = this,
options = that.config,
datas = options.data;
var initNode = {
level: 0
}
options.load(initNode, function(datas) {
that.init(datas, initNode);
});
return {
config: options,
setChecked: that.setChecked
};
};
Class.prototype.init = function(datas, node) {
var that = this;
var ELEM_SET = 'layui-tree-set';
var ELEM_PACK = 'layui-tree-pack';
var config = this.config;
var elem = config.elem; //#tree
var checkedId = config.checkedId;
var showCheckbox = config.showCheckbox; //是否显示复选框
var onlyIconControl = config.onlyIconControl; //是否仅允许节点左侧图标控制展开收缩
var onlyLeafClick = config.onlyLeafClick || false; //只有点击页子节点才执行点击事件
var ICONS = config.icons || {
ICON_ADD: ICON_ADD,
ICON_SUB: ICON_SUB,
ICON_FILE: 'layui-icon-file'
};
var selectFontColor = config.selectFontColor || '#555'; //选中节点文本颜色
var root = $(elem);
var id = that.index;
var layFilter = 'LAY-tree-' + id;
this.config.layFilter = layFilter;
var tree = root.find('.layui-tree');
var parentNode = tree;
var setHide = '';
var checkedClass = '';
var checked = false;
//创建根节点
if (parentNode.length == 0) {
setHide = 'layui-tree-setHide'; //根节点不显示线
//创建根节点
parentNode = $('<div class="layui-tree layui-form layui-tree-line" lay-filter="' + layFilter + '">');
root.append(parentNode);
} else if (node.elem) {
parentNode = node.elem.parents(".layui-tree-entry").eq(0).next('.layui-tree-pack');
//如果没有 pack,则说明需要渲染
if (parentNode.length == 0) {
parentNode = $('<div class="layui-tree-pack" style="display: block;">');
if (node.elem) {
checked = node.elem.parents('span').next().next().hasClass('layui-form-checked');
checkedClass = checked ? 'checked' : '';
}
} else {
//不需要渲染
return;
}
node.elem.parents(".layui-tree-set").eq(0).append(parentNode);
}
//创建节点
$.each(datas, function(index, item) {
var lineShort = index == datas.length - 1 ? ' layui-tree-setLineShort' : ''; //末节点显示线
var leaf = item.leaf;
var dataid = item.id;
var div_set = $('<div data-id="' + dataid + '" class="layui-tree-set ' + setHide + lineShort + '">');
var div_entry = $("<div class='layui-tree-entry'></div>");
var div_main = $("<div class='layui-tree-main'></div>");
var treeIcon = leaf ? '' : 'layui-tree-icon';
var icon = leaf ? ICONS.ICON_FILE : ICONS.ICON_ADD;
var span = $("<span class='layui-tree-iconClick " + treeIcon + "'></span>");
var i = $("<i class='layui-icon " + icon + "'></i>");
if (!leaf) {
i.bind('click', function() {
addition_click();
});
function addition_click() {
var level = i.parents(".layui-tree-set").length;
var loadNode = {
level: level,
data: item
}
config.load(loadNode, function(datas) {
var spread = i.hasClass(ICONS.ICON_ADD);
if (spread) { //展开
i.addClass(ICONS.ICON_SUB).removeClass(ICONS.ICON_ADD);
i.parents('.layui-tree-entry').next(".layui-tree-pack").slideDown(200);
} else {
i.addClass(ICONS.ICON_ADD).removeClass(ICONS.ICON_SUB);
i.parents('.layui-tree-entry').next(".layui-tree-pack").slideUp(200);
}
loadNode.elem = i;
that.init(datas, loadNode);
});
}
}
var text = $("<span class='layui-tree-txt'>" + item.text + "</span>");
text.bind('click', function() {
if (!onlyIconControl) {
i.trigger('click');
}
if ((onlyLeafClick && leaf) || !onlyLeafClick) {
root.find('.text_click').removeClass('text_click').css('color', '#555');
text.addClass('text_click');
root.find('.text_click').css('color', selectFontColor);
config.click ? config.click({
data: item,
pid: 0
}) : '';
}
});
span.append(i);
div_main.append(span);
if (showCheckbox) {
if (checkedId) {
//如果动态设置了选中,则判断新节点是否在其中
if ($.inArray(parseInt(dataid), checkedId) == -1) {
checkedClass = '';
} else {
checkedClass = 'checked';
}
}
var checkbox = $("<input type='checkbox' name='layuiTreeCheck' lay-skin='primary' value='" + dataid + "' " +
checkedClass +
">");
div_main.append(checkbox);
}
div_main.append(text);
div_entry.append(div_main);
div_set.append(div_entry);
parentNode.append(div_set);
});
if (showCheckbox) {
that.renderCheckbox();
}
}
//渲染复选框
Class.prototype.renderCheckbox = function(options) {
var that = this;
var root = $(that.config.elem);
form.render('checkbox', that.config.layFilter);
var checkbox = root.find('input[name="layuiTreeCheck"]');
var checkedids = [];
checkbox.each(function() {
let checked = $(this)[0].checked;
if (checked) {
checkedids.push($(this)[0].value);
}
});
//给复选框绑定事件
root.find('.layui-form-checkbox').bind('click', function() {
//消除动态选择的数组
delete that.config.checkedId;
var elemCheckbox = $(this).prev('input[name="layuiTreeCheck"]');
var checked = elemCheckbox.prop('checked');
//同步子节点选中状态
var childs = elemCheckbox.parents('.layui-tree-entry').eq(0).next().find('input[name="layuiTreeCheck"]');
childs.each(function() {
this.checked = checked;
});
//同步父选中状态
var setParentsChecked = function(thisNodeElem) {
//若无父节点,则终止递归
if (!thisNodeElem.parents('.' + ELEM_SET)[0]) return;
var state, parentPack = thisNodeElem.parent('.' + ELEM_PACK),
parentNodeElem = parentPack.parent(),
parentCheckbox = parentPack.prev().find('input[name="layuiTreeCheck"]');
//如果子节点有任意一条选中,则父节点为选中状态
if (checked) {
parentCheckbox.prop('checked', checked);
} else { //如果当前节点取消选中,则根据计算“兄弟和子孙”节点选中状态,来同步父节点选中状态
parentPack.find('input[name="layuiTreeCheck"]').each(function() {
if (this.checked) {
state = true;
}
});
//如果兄弟子孙节点全部未选中,则父节点也应为非选中状态
state || parentCheckbox.prop('checked', false);
}
//向父节点递归
setParentsChecked(parentNodeElem);
}
setParentsChecked(elemCheckbox.parents('.' + ELEM_SET).eq(0));
that.renderCheckbox();
});
}
function renderCheckbox() {
form.render('checkbox', that.config.layFilter);
//给复选框绑定事件
root.find('.layui-form-checkbox').bind('click', function() {
var elemCheckbox = $(this).prev('input[name="layuiTreeCheck"]');
var checked = elemCheckbox.prop('checked');
//同步子节点选中状态
var childs = elemCheckbox.parents('.layui-tree-entry').eq(0).next().find('input[name="layuiTreeCheck"]');
childs.each(function() {
this.checked = checked;
});
//同步父选中状态
var setParentsChecked = function(thisNodeElem) {
//若无父节点,则终止递归
if (!thisNodeElem.parents('.' + ELEM_SET)[0]) return;
var state, parentPack = thisNodeElem.parent('.' + ELEM_PACK),
parentNodeElem = parentPack.parent(),
parentCheckbox = parentPack.prev().find('input[name="layuiTreeCheck"]');
//如果子节点有任意一条选中,则父节点为选中状态
if (checked) {
parentCheckbox.prop('checked', checked);
} else { //如果当前节点取消选中,则根据计算“兄弟和子孙”节点选中状态,来同步父节点选中状态
parentPack.find('input[name="layuiTreeCheck"]').each(function() {
if (this.checked) {
state = true;
}
});
//如果兄弟子孙节点全部未选中,则父节点也应为非选中状态
state || parentCheckbox.prop('checked', false);
}
//向父节点递归
setParentsChecked(parentNodeElem);
}
setParentsChecked(elemCheckbox.parents('.' + ELEM_SET).eq(0));
renderCheckbox();
//调用事件
that.config.checkboxClick ? that.config.checkboxClick() : '';
});
}
//渲染表单
Class.prototype.renderForm = function(type) {
form.render(type, 'LAY-tree-' + this.index);
};
//节点解析
Class.prototype.treelazy = function(elem, children) {
var that = this,
options = that.config,
data = children || options.data;
//遍历数据
layui.each(data, function(index, item) {
var hasChild = item.children && item.children.length > 0,
packDiv = $('<div class="layui-tree-pack" ' + (item.spread ? 'style="display: block;"' : '') + '"></div>'),
entryDiv = $(['<div data-id="' + item.id + '" class="layui-tree-set' + (item.spread ? " layui-tree-spread" :
"") + (item.checked ? " layui-tree-checkedFirst" : "") + '">', '<div ' + (options.drag && !item.fixed ?
'draggable="true"' : '') + ' class="layui-tree-entry">', '<div class="layui-tree-main">'
//箭头
,
function() {
if (options.showLine) {
if (hasChild) {
return '<span class="layui-tree-iconClick layui-tree-icon"><i class="layui-icon ' + (item.spread ?
"layui-icon-subtraction" : "layui-icon-addition") + '"></i></span>';
} else {
return '<span class="layui-tree-iconClick"><i class="layui-icon layui-icon-file"></i></span>';
};
} else {
return '<span class="layui-tree-iconClick"><i class="layui-tree-iconArrow ' + (hasChild ? "" : HIDE) +
'"></i></span>';
};
}()
//复选框
,
function() {
return options.showCheckbox ? '<input type="checkbox" name="layuiTreeCheck" lay-skin="primary" ' + (item.disabled ?
"disabled" : "") + ' value="' + item.id + '">' : '';
}()
//节点
,
function() {
if (options.isJump && item.href) {
return '<a href="' + item.href + '" target="_blank" class="' + ELEM_TEXT + '">' + (item.title || item.label ||
options.text.defaultNodeName) + '</a>';
} else {
return '<span class="' + ELEM_TEXT + (item.disabled ? ' ' + DISABLED : '') + '">' + (item.title || item.label ||
options.text.defaultNodeName) + '</span>';
}
}(), '</div>'
//节点操作图标
,
function() {
if (!options.edit) return '';
var editIcon = {
add: '<i class="layui-icon layui-icon-add-1" data-type="add"></i>',
update: '<i class="layui-icon layui-icon-edit" data-type="update"></i>',
del: '<i class="layui-icon layui-icon-delete" data-type="del"></i>'
},
arr = ['<div class="layui-btn-group layui-tree-btnGroup">'];
if (options.edit === true) {
options.edit = ['update', 'del']
}
if (typeof options.edit === 'object') {
layui.each(options.edit, function(i, val) {
arr.push(editIcon[val] || '')
});
return arr.join('') + '</div>';
}
}(), '</div></div>'
].join(''));
//如果有子节点,则递归继续生成树
if (hasChild) {
entryDiv.append(packDiv);
that.treelazy(packDiv, item.children);
};
elem.append(entryDiv);
//若有前置节点,前置节点加连接线
if (entryDiv.prev('.' + ELEM_SET)[0]) {
entryDiv.prev().children('.layui-tree-pack').addClass('layui-tree-showLine');
};
//若无子节点,则父节点加延伸线
if (!hasChild) {
entryDiv.parent('.layui-tree-pack').addClass('layui-tree-lineExtend');
};
//展开节点操作
that.spread(entryDiv, item);
//选择框
if (options.showCheckbox) {
that.checkClick(entryDiv, item);
}
//操作节点
options.edit && that.operate(entryDiv, item);
});
};
//展开节点
Class.prototype.spread = function(elem, item) {
var that = this,
options = that.config,
entry = elem.children('.' + ELEM_ENTRY),
elemMain = entry.children('.' + ELEM_MAIN),
elemIcon = entry.find('.' + ICON_CLICK),
elemText = entry.find('.' + ELEM_TEXT),
touchOpen = options.onlyIconControl ? elemIcon : elemMain //判断展开通过节点还是箭头图标
,
state = '';
//展开收缩
touchOpen.on('click', function(e) {
var packCont = elem.children('.' + ELEM_PACK),
iconClick = touchOpen.children('.layui-icon')[0] ? touchOpen.children('.layui-icon') : touchOpen.find(
'.layui-tree-icon').children('.layui-icon');
//若没有子节点
if (!packCont[0]) {
state = 'normal';
} else {
if (elem.hasClass(ELEM_SPREAD)) {
elem.removeClass(ELEM_SPREAD);
packCont.slideUp(200);
iconClick.removeClass(ICON_SUB).addClass(ICON_ADD);
} else {
elem.addClass(ELEM_SPREAD);
packCont.slideDown(200);
iconClick.addClass(ICON_SUB).removeClass(ICON_ADD);
//是否手风琴
if (options.accordion) {
var sibls = elem.siblings('.' + ELEM_SET);
sibls.removeClass(ELEM_SPREAD);
sibls.children('.' + ELEM_PACK).slideUp(200);
sibls.find('.layui-tree-icon').children('.layui-icon').removeClass(ICON_SUB).addClass(ICON_ADD);
};
};
};
});
//点击回调
elemText.on('click', function() {
var othis = $(this);
//判断是否禁用状态
if (othis.hasClass(DISABLED)) return;
//判断展开收缩状态
if (elem.hasClass(ELEM_SPREAD)) {
state = options.onlyIconControl ? 'open' : 'close';
} else {
state = options.onlyIconControl ? 'close' : 'open';
}
//点击产生的回调
options.click && options.click({
elem: elem,
state: state,
data: item
});
});
};
//计算复选框选中状态
Class.prototype.setCheckbox = function(elem, item, elemCheckbox) {
var that = this,
options = that.config,
checked = elemCheckbox.prop('checked');
//同步子节点选中状态
if (typeof item.children === 'object' || elem.find('.' + ELEM_PACK)[0]) {
var childs = elem.find('.' + ELEM_PACK).find('input[name="layuiTreeCheck"]');
childs.each(function() {
if (this.disabled) return; //不可点击则跳过
this.checked = checked;
});
};
//同步父选中状态
var setParentsChecked = function(thisNodeElem) {
//若无父节点,则终止递归
if (!thisNodeElem.parents('.' + ELEM_SET)[0]) return;
var state, parentPack = thisNodeElem.parent('.' + ELEM_PACK),
parentNodeElem = parentPack.parent(),
parentCheckbox = parentPack.prev().find('input[name="layuiTreeCheck"]');
//如果子节点有任意一条选中,则父节点为选中状态
if (checked) {
parentCheckbox.prop('checked', checked);
} else { //如果当前节点取消选中,则根据计算“兄弟和子孙”节点选中状态,来同步父节点选中状态
parentPack.find('input[name="layuiTreeCheck"]').each(function() {
if (this.checked) {
state = true;
}
});
//如果兄弟子孙节点全部未选中,则父节点也应为非选中状态
state || parentCheckbox.prop('checked', false);
}
//向父节点递归
setParentsChecked(parentNodeElem);
};
setParentsChecked(elem);
that.renderForm('checkbox');
};
//复选框选择
Class.prototype.checkClick = function(elem, item) {
var that = this,
options = that.config,
entry = elem.children('.' + ELEM_ENTRY),
elemMain = entry.children('.' + ELEM_MAIN);
elemMain.on('click', 'input[name="layuiTreeCheck"]+', function(e) {
layui.stope(e); //阻止点击节点事件
var elemCheckbox = $(this).prev(),
checked = elemCheckbox.prop('checked');
if (elemCheckbox.prop('disabled')) return;
that.setCheckbox(elem, item, elemCheckbox);
//复选框点击产生的回调
options.oncheck && options.oncheck({
elem: elem,
checked: checked,
data: item
});
});
};
//节点操作
Class.prototype.operate = function(elem, item) {
var that = this,
options = that.config,
entry = elem.children('.' + ELEM_ENTRY),
elemMain = entry.children('.' + ELEM_MAIN);
entry.children('.layui-tree-btnGroup').on('click', '.layui-icon', function(e) {
layui.stope(e); //阻止节点操作
var type = $(this).data("type"),
packCont = elem.children('.' + ELEM_PACK),
returnObj = {
data: item,
type: type,
elem: elem
};
//增加
if (type == 'add') {
//若节点本身无子节点
if (!packCont[0]) {
//若开启连接线,更改图标样式
if (options.showLine) {
elemMain.find('.' + ICON_CLICK).addClass('layui-tree-icon');
elemMain.find('.' + ICON_CLICK).children('.layui-icon').addClass(ICON_ADD).removeClass('layui-icon-file');
//若未开启连接线,显示箭头
} else {
elemMain.find('.layui-tree-iconArrow').removeClass(HIDE);
};
//节点添加子节点容器
elem.append('<div class="layui-tree-pack"></div>');
};
//新增节点
var key = options.operate && options.operate(returnObj),
obj = {};
obj.title = options.text.defaultNodeName;
obj.id = key;
that.treelazy(elem.children('.' + ELEM_PACK), [obj]);
//放在新增后面,因为要对元素进行操作
if (options.showLine) {
//节点本身无子节点
if (!packCont[0]) {
//遍历兄弟节点,判断兄弟节点是否有子节点
var siblings = elem.siblings('.' + ELEM_SET),
num = 1,
parentPack = elem.parent('.' + ELEM_PACK);
layui.each(siblings, function(index, i) {
if (!$(i).children('.' + ELEM_PACK)[0]) {
num = 0;
};
});
//若兄弟节点都有子节点
if (num == 1) {
//兄弟节点添加连接线
siblings.children('.' + ELEM_PACK).addClass(ELEM_SHOW);
siblings.children('.' + ELEM_PACK).children('.' + ELEM_SET).removeClass(ELEM_LINE_SHORT);
elem.children('.' + ELEM_PACK).addClass(ELEM_SHOW);
//父级移除延伸线
parentPack.removeClass(ELEM_EXTEND);
//同层节点最后一个更改线的状态
parentPack.children('.' + ELEM_SET).last().children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(
ELEM_LINE_SHORT);
} else {
elem.children('.' + ELEM_PACK).children('.' + ELEM_SET).addClass(ELEM_LINE_SHORT);
};
} else {
//添加延伸线
if (!packCont.hasClass(ELEM_EXTEND)) {
packCont.addClass(ELEM_EXTEND);
};
//子节点添加延伸线
elem.find('.' + ELEM_PACK).each(function() {
$(this).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
});
//如果前一个节点有延伸线
if (packCont.children('.' + ELEM_SET).last().prev().hasClass(ELEM_LINE_SHORT)) {
packCont.children('.' + ELEM_SET).last().prev().removeClass(ELEM_LINE_SHORT);
} else {
//若之前的没有,说明处于连接状态
packCont.children('.' + ELEM_SET).last().removeClass(ELEM_LINE_SHORT);
};
//若是最外层,要始终保持相连的状态
if (!elem.parent('.' + ELEM_PACK)[0] && elem.next()[0]) {
packCont.children('.' + ELEM_SET).last().removeClass(ELEM_LINE_SHORT);
};
};
};
if (!options.showCheckbox) return;
//若开启复选框,同步新增节点状态
if (elemMain.find('input[name="layuiTreeCheck"]')[0].checked) {
var packLast = elem.children('.' + ELEM_PACK).children('.' + ELEM_SET).last();
packLast.find('input[name="layuiTreeCheck"]')[0].checked = true;
};
that.renderForm('checkbox');
//修改
} else if (type == 'update') {
var text = elemMain.children('.' + ELEM_TEXT).html();
elemMain.children('.' + ELEM_TEXT).html('');
//添加输入框,覆盖在文字上方
elemMain.append('<input type="text" class="layui-tree-editInput">');
//获取焦点
elemMain.children('.layui-tree-editInput').val(text).focus();
//嵌入文字移除输入框
var getVal = function(input) {
var textNew = input.val().trim();
textNew = textNew ? textNew : options.text.defaultNodeName;
input.remove();
elemMain.children('.' + ELEM_TEXT).html(textNew);
//同步数据
returnObj.data.title = textNew;
//节点修改的回调
options.operate && options.operate(returnObj);
};
//失去焦点
elemMain.children('.layui-tree-editInput').blur(function() {
getVal($(this));
});
//回车
elemMain.children('.layui-tree-editInput').on('keydown', function(e) {
if (e.keyCode === 13) {
e.preventDefault();
getVal($(this));
};
});
//删除
} else {
options.operate && options.operate(returnObj); //节点删除的回调
returnObj.status = 'remove'; //标注节点删除
//若删除最后一个,显示空数据提示
if (!elem.prev('.' + ELEM_SET)[0] && !elem.next('.' + ELEM_SET)[0] && !elem.parent('.' + ELEM_PACK)[0]) {
elem.remove();
that.elem.append(that.elemNone);
return;
};
//若有兄弟节点
if (elem.siblings('.' + ELEM_SET).children('.' + ELEM_ENTRY)[0]) {
//若开启复选框
if (options.showCheckbox) {
//若开启复选框,进行下步操作
var elemDel = function(elem) {
//若无父结点,则不执行
if (!elem.parents('.' + ELEM_SET)[0]) return;
var siblingTree = elem.siblings('.' + ELEM_SET).children('.' + ELEM_ENTRY),
parentTree = elem.parent('.' + ELEM_PACK).prev(),
checkState = parentTree.find('input[name="layuiTreeCheck"]')[0],
state = 1,
num = 0;
//若父节点未勾选
if (checkState.checked == false) {
//遍历兄弟节点
siblingTree.each(function(i, item1) {
var input = $(item1).find('input[name="layuiTreeCheck"]')[0]
if (input.checked == false && !input.disabled) {
state = 0;
};
//判断是否全为不可勾选框
if (!input.disabled) {
num = 1;
};
});
//若有可勾选选择框并且已勾选
if (state == 1 && num == 1) {
//勾选父节点
checkState.checked = true;
that.renderForm('checkbox');
//向上遍历祖先节点
elemDel(parentTree.parent('.' + ELEM_SET));
};
};
};
elemDel(elem);
};
//若开启连接线
if (options.showLine) {
//遍历兄弟节点,判断兄弟节点是否有子节点
var siblings = elem.siblings('.' + ELEM_SET),
num = 1,
parentPack = elem.parent('.' + ELEM_PACK);
layui.each(siblings, function(index, i) {
if (!$(i).children('.' + ELEM_PACK)[0]) {
num = 0;
};
});
//若兄弟节点都有子节点
if (num == 1) {
//若节点本身无子节点
if (!packCont[0]) {
//父级去除延伸线,因为此时子节点里没有空节点
parentPack.removeClass(ELEM_EXTEND);
siblings.children('.' + ELEM_PACK).addClass(ELEM_SHOW);
siblings.children('.' + ELEM_PACK).children('.' + ELEM_SET).removeClass(ELEM_LINE_SHORT);
};
//若为最后一个节点
if (!elem.next()[0]) {
elem.prev().children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
} else {
parentPack.children('.' + ELEM_SET).last().children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(
ELEM_LINE_SHORT);
};
//若为最外层最后一个节点,去除前一个结点的连接线
if (!elem.next()[0] && !elem.parents('.' + ELEM_SET)[1] && !elem.parents('.' + ELEM_SET).eq(0).next()[0]) {
elem.prev('.' + ELEM_SET).addClass(ELEM_LINE_SHORT);
};
} else {
//若为最后一个节点且有延伸线
if (!elem.next()[0] && elem.hasClass(ELEM_LINE_SHORT)) {
elem.prev().addClass(ELEM_LINE_SHORT);
};
};
};
} else {
//若无兄弟节点
var prevDiv = elem.parent('.' + ELEM_PACK).prev();
//若开启了连接线
if (options.showLine) {
prevDiv.find('.' + ICON_CLICK).removeClass('layui-tree-icon');
prevDiv.find('.' + ICON_CLICK).children('.layui-icon').removeClass(ICON_SUB).addClass('layui-icon-file');
//父节点所在层添加延伸线
var pare = prevDiv.parents('.' + ELEM_PACK).eq(0);
pare.addClass(ELEM_EXTEND);
//兄弟节点最后子节点添加延伸线
pare.children('.' + ELEM_SET).each(function() {
$(this).children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
});
} else {
//父节点隐藏箭头
prevDiv.find('.layui-tree-iconArrow').addClass(HIDE);
};
//移除展开属性
elem.parents('.' + ELEM_SET).eq(0).removeClass(ELEM_SPREAD);
//移除节点容器
elem.parent('.' + ELEM_PACK).remove();
};
elem.remove();
};
});
};
//拖拽
Class.prototype.drag = function() {
var that = this,
options = that.config;
that.elem.on('dragstart', '.' + ELEM_ENTRY, function() {
var parent = $(this).parent('.' + ELEM_SET),
pares = parent.parents('.' + ELEM_SET)[0] ? parent.parents('.' + ELEM_SET).eq(0) : '未找到父节点';
//开始拖拽触发的回调
options.dragstart && options.dragstart(parent, pares);
});
that.elem.on('dragend', '.' + ELEM_ENTRY, function(e) {
var e = e || event,
disY = e.clientY,
olds = $(this),
setParent = olds.parent('.' + ELEM_SET),
setHeight = setParent.height(),
setTop = setParent.offset().top,
elemSet = that.elem.find('.' + ELEM_SET),
elemHeight = that.elem.height(),
elemTop = that.elem.offset().top,
maxTop = elemHeight + elemTop - 13;
//原父节点
var isTree = setParent.parents('.' + ELEM_SET)[0],
nextOld = setParent.next()[0];
if (isTree) {
var parentPack = setParent.parent('.' + ELEM_PACK),
parentSet = setParent.parents('.' + ELEM_SET).eq(0),
warpPack = parentSet.parent('.' + ELEM_PACK),
parentTop = parentSet.offset().top,
siblingOld = setParent.siblings(),
num = parentSet.children('.' + ELEM_PACK).children('.' + ELEM_SET).length;
};
//原节点操作
var setDel = function(parentSet) {
//若为最后一个节点操作
if (!isTree && !nextOld) {
that.elem.children('.' + ELEM_SET).last().children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(
ELEM_LINE_SHORT);
};
//若为最外层节点,不做下列操作
if (!isTree) {
setParent.removeClass('layui-tree-setHide');
return;
};
//若为唯一子节点
if (num == 1) {
if (options.showLine) {
parentSet.find('.' + ICON_CLICK).removeClass('layui-tree-icon');
parentSet.find('.' + ICON_CLICK).children('.layui-icon').removeClass(ICON_SUB).addClass('layui-icon-file');
warpPack.addClass(ELEM_EXTEND);
warpPack.children('.' + ELEM_SET).children('.' + ELEM_PACK).each(function() {
$(this).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
});
} else {
parentSet.find('.layui-tree-iconArrow').addClass(HIDE);
};
parentSet.children('.' + ELEM_PACK).remove();
parentSet.removeClass(ELEM_SPREAD);
} else {
//若开启连接线
if (options.showLine) {
//遍历兄弟节点,判断兄弟节点是否有子节点
var number = 1;
layui.each(siblingOld, function(index, i) {
if (!$(i).children('.' + ELEM_PACK)[0]) {
number = 0;
};
});
//若兄弟节点都有子节点
if (number == 1) {
//若节点本身无子节点
if (!setParent.children('.' + ELEM_PACK)[0]) {
//父级去除延伸线,因为此时子节点里没有空节点
parentPack.removeClass(ELEM_EXTEND);
siblingOld.children('.' + ELEM_PACK).addClass(ELEM_SHOW);
siblingOld.children('.' + ELEM_PACK).children('.' + ELEM_SET).removeClass(ELEM_LINE_SHORT);
};
//若为最后一个节点
parentPack.children('.' + ELEM_SET).last().children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(
ELEM_LINE_SHORT);
//若为最外层最后一个节点,去除前一个结点的连接线
if (!nextOld && !parentSet.parents('.' + ELEM_SET)[0] && !parentSet.next()[0]) {
parentPack.children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
};
} else {
//若为最后一个节点且有延伸线
if (!nextOld && setParent.hasClass(ELEM_LINE_SHORT)) {
parentPack.children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
};
};
};
//若开启复选框
if (options.showCheckbox) {
//若开启复选框,进行下步操作
var elemRemove = function(elem) {
//若无父结点,则不执行
if (elem) {
if (!elem.parents('.' + ELEM_SET)[0]) return;
} else {
if (!parentSet[0]) return;
};
var siblingTree = elem ? elem.siblings().children('.' + ELEM_ENTRY) : siblingOld.children('.' +
ELEM_ENTRY),
parentTree = elem ? elem.parent('.' + ELEM_PACK).prev() : parentPack.prev(),
checkState = parentTree.find('input[name="layuiTreeCheck"]')[0],
state = 1,
ndig = 0;
//若父节点未勾选
if (checkState.checked == false) {
//遍历兄弟节点
siblingTree.each(function(i, item1) {
var input = $(item1).find('input[name="layuiTreeCheck"]')[0];
if (input.checked == false && !input.disabled) {
state = 0
};
//判断是否全为不可勾选框
if (!input.disabled) {
ndig = 1
};
});
//若有可勾选选择框并且已勾选
if (state == 1 && ndig == 1) {
//勾选父节点
checkState.checked = true;
that.renderForm('checkbox');
//向上遍历祖先节点
elemRemove(parentTree.parent('.' + ELEM_SET) || parentSet);
};
};
};
elemRemove();
};
};
};
//查找
elemSet.each(function() {
//筛选可插入位置
if ($(this).height() != 0) {
//若在本身位置
if ((disY > setTop && disY < setTop + setHeight)) {
options.dragend && options.dragend('drag error');
return;
};
//若仅有一个子元素
if (num == 1 && disY > parentTop && disY < setTop + setHeight) {
options.dragend && options.dragend('drag error');
return;
};
var thisTop = $(this).offset().top;
//若位于元素上
if ((disY > thisTop) && (disY < thisTop + 15)) {
//若元素无子节点
if (!$(this).children('.' + ELEM_PACK)[0]) {
if (options.showLine) {
$(this).find('.' + ICON_CLICK).eq(0).addClass('layui-tree-icon');
$(this).find('.' + ICON_CLICK).eq(0).children('.layui-icon').addClass(ICON_ADD).removeClass(
'layui-icon-file');
} else {
$(this).find(".layui-tree-iconArrow").removeClass(HIDE);
};
$(this).append('<div class="layui-tree-pack"></div>');
};
//插入元素
$(this).children('.' + ELEM_PACK).append(setParent);
setDel(parentSet);
//若开启连接线,更改线状态
if (options.showLine) {
var children = $(this).children('.' + ELEM_PACK).children('.' + ELEM_SET);
setParent.children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
if (children.length == 1) {
//遍历兄弟节点,判断兄弟节点是否有子节点
var siblings = $(this).siblings('.' + ELEM_SET),
ss = 1,
parentPack = $(this).parent('.' + ELEM_PACK);
layui.each(siblings, function(index, i) {
if (!$(i).children('.' + ELEM_PACK)[0]) {
ss = 0;
};
});
//若兄弟节点都有子节点
if (ss == 1) {
//兄弟节点添加连接线
siblings.children('.' + ELEM_PACK).addClass(ELEM_SHOW);
siblings.children('.' + ELEM_PACK).children('.' + ELEM_SET).removeClass(ELEM_LINE_SHORT);
$(this).children('.' + ELEM_PACK).addClass(ELEM_SHOW);
//父级移除延伸线
parentPack.removeClass(ELEM_EXTEND);
//同层节点最后一个去除连接线
parentPack.children('.' + ELEM_SET).last().children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(
ELEM_LINE_SHORT).removeClass('layui-tree-setHide');
} else {
$(this).children('.' + ELEM_PACK).children('.' + ELEM_SET).addClass(ELEM_LINE_SHORT).removeClass(
'layui-tree-setHide');
};
} else {
//若原子节点含有延伸线
if (setParent.prev('.' + ELEM_SET).hasClass(ELEM_LINE_SHORT)) {
setParent.prev('.' + ELEM_SET).removeClass(ELEM_LINE_SHORT);
setParent.addClass(ELEM_LINE_SHORT);
} else {
//清除之前状态
setParent.removeClass('layui-tree-setLineShort layui-tree-setHide');
//若添加节点无子节点
if (!setParent.children('.' + ELEM_PACK)[0]) {
//兄弟节点子节点添加延伸线
setParent.siblings('.' + ELEM_SET).find('.' + ELEM_PACK).each(function() {
$(this).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
});
} else {
setParent.prev('.' + ELEM_SET).children('.' + ELEM_PACK).children('.' + ELEM_SET).last().removeClass(
ELEM_LINE_SHORT);
};
};
//若无下兄弟节点
if (!$(this).next()[0]) {
setParent.addClass(ELEM_LINE_SHORT);
};
};
};
//若开启复选框,同步新增节点状态
if (options.showCheckbox) {
if ($(this).children('.' + ELEM_ENTRY).find('input[name="layuiTreeCheck"]')[0].checked) {
var packLast = setParent.children('.' + ELEM_ENTRY);
packLast.find('input[name="layuiTreeCheck"]+').click();
};
};
options.dragend && options.dragend('drag success', setParent, $(this));
return false;
//若位于元素上方
} else if (disY < thisTop) {
$(this).before(setParent);
setDel(parentSet);
//若开启连接线,更改线状态
if (options.showLine) {
var packCont = setParent.children('.' + ELEM_PACK),
setFirst = $(this).parents('.' + ELEM_SET).eq(0),
setPackLast = setFirst.children('.' + ELEM_PACK).children('.' + ELEM_SET).last();
if (packCont[0]) {
setParent.removeClass(ELEM_LINE_SHORT);
packCont.children('.' + ELEM_SET).last().removeClass(ELEM_LINE_SHORT);
//遍历兄弟节点,判断兄弟节点是否有子节点
var siblings = setParent.siblings('.' + ELEM_SET),
ss = 1;
layui.each(siblings, function(index, i) {
if (!$(i).children('.' + ELEM_PACK)[0]) {
ss = 0;
};
});
//若兄弟节点都有子节点
if (ss == 1) {
if (setFirst[0]) {
//兄弟节点添加连接线
siblings.children('.' + ELEM_PACK).addClass(ELEM_SHOW);
siblings.children('.' + ELEM_PACK).children('.' + ELEM_SET).removeClass(ELEM_LINE_SHORT);
//同层节点最后一个添加延伸线
setPackLast.children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT).removeClass(
ELEM_SHOW);
};
} else {
setParent.children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
};
//若是最外层,要始终保持相连的状态
if (!setFirst.parent('.' + ELEM_PACK)[0] && setFirst.next()[0]) {
setPackLast.removeClass(ELEM_LINE_SHORT);
};
} else {
if (!setFirst.hasClass(ELEM_EXTEND)) {
setFirst.addClass(ELEM_EXTEND);
};
//子节点添加延伸线
setFirst.find('.' + ELEM_PACK).each(function() {
$(this).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
});
//若是最外层,要始终保持相连的状态
// if(!setFirst.parent('.'+ELEM_PACK)[0] && setFirst.next()[0]){
// //setFirst.children('.'+ELEM_PACK).children('.'+ELEM_SET).last().removeClass(ELEM_LINE_SHORT);
// };
};
//若移到最外层
if (!setFirst[0]) {
//隐藏前置连接线
setParent.addClass('layui-tree-setHide');
setParent.children('.' + ELEM_PACK).children('.' + ELEM_SET).last().removeClass(ELEM_LINE_SHORT);
};
};
//开启复选框且有父节点,同步新增节点状态
if (setFirst[0] && options.showCheckbox) {
if (setFirst.children('.' + ELEM_ENTRY).find('input[name="layuiTreeCheck"]')[0].checked) {
var packLast = setParent.children('.' + ELEM_ENTRY);
packLast.find('input[name="layuiTreeCheck"]+').click();
};
};
options.dragend && options.dragend('拖拽成功,插入目标节点上方', setParent, $(this));
return false;
//若位于最下方
} else if (disY > maxTop) {
that.elem.children('.' + ELEM_SET).last().children('.' + ELEM_PACK).addClass(ELEM_SHOW);
that.elem.append(setParent);
setDel(parentSet);
//最外层保持连接
setParent.prev().children('.' + ELEM_PACK).children('.' + ELEM_SET).last().removeClass(ELEM_LINE_SHORT);
//隐藏前置连接线
setParent.addClass('layui-tree-setHide');
//最后一个子节点加延伸
setParent.children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
options.dragend && options.dragend('拖拽成功,插入最外层节点', setParent, that.elem);
return false;
};
};
});
});
};
//部分事件
Class.prototype.events = function() {
var that = this,
options = that.config,
checkWarp = that.elem.find('.layui-tree-checkedFirst');
//初始选中
layui.each(checkWarp, function(i, item) {
$(item).children('.' + ELEM_ENTRY).find('input[name="layuiTreeCheck"]+').trigger('click');
});
//搜索
that.elem.find('.layui-tree-search').on('keyup', function() {
var input = $(this),
val = input.val(),
pack = input.nextAll(),
arr = [];
//遍历所有的值
pack.find('.' + ELEM_TEXT).each(function() {
var entry = $(this).parents('.' + ELEM_ENTRY);
//若值匹配,加一个类以作标识
if ($(this).html().indexOf(val) != -1) {
arr.push($(this).parent());
var select = function(div) {
div.addClass('layui-tree-searchShow');
//向上父节点渲染
if (div.parent('.' + ELEM_PACK)[0]) {
select(div.parent('.' + ELEM_PACK).parent('.' + ELEM_SET));
};
};
select(entry.parent('.' + ELEM_SET));
};
});
//根据标志剔除
pack.find('.' + ELEM_ENTRY).each(function() {
var parent = $(this).parent('.' + ELEM_SET);
if (!parent.hasClass('layui-tree-searchShow')) {
parent.addClass(HIDE);
};
});
if (pack.find('.layui-tree-searchShow').length == 0) {
that.elem.append(that.elemNone);
};
//节点过滤的回调
options.onsearch && options.onsearch({
elem: arr
});
});
//还原搜索初始状态
that.elem.find('.layui-tree-search').on('keydown', function() {
$(this).nextAll().find('.' + ELEM_ENTRY).each(function() {
var parent = $(this).parent('.' + ELEM_SET);
parent.removeClass('layui-tree-searchShow ' + HIDE);
});
if ($('.layui-tree-emptyText')[0]) $('.layui-tree-emptyText').remove();
});
};
//得到选中节点
Class.prototype.getChecked = function() {
var that = this,
options = that.config,
checkId = [],
checkData = [];
//遍历节点找到选中索引
$(options.elem).find('.layui-form-checked').each(function() {
//如果是叶子节点,则直接放入
var pSpan = $(this).prev().prev().find('.layui-icon');
if (pSpan.hasClass('layui-icon-file')) {
checkId.push(parseInt($(this).prev()[0].value));
} else {
//如果不是叶子节点,判断其子节点复选框个数与被选中子节点复选框个数是否相等
var child = $(this).parents('.' + ELEM_ENTRY).eq(0).next();
var ckCount = child.find('.layui-form-checkbox').length;
var ckdCount = child.find('.layui-form-checked').length;
if (ckCount == ckdCount) {
checkId.push(parseInt($(this).prev()[0].value));
}
}
});
return checkId;
};
//设置选中节点
Class.prototype.setChecked = function(checkedId, clearOther) {
var that = this,
options = that.config;
clearOther = clearOther || true; //默认清除其他
//清除其他
if (clearOther) {
$(options.elem).find('.layui-form-checked').prev('input[name="layuiTreeCheck"]').prop('checked', false);
}
//若返回数字
var checkedArr = [];
if (typeof checkedId === 'number') {
checkedArr.push(checkedId);
} else {
checkedArr = checkedId;
};
options.checkedId = checkedArr;
//初始选中
for (let i = 0; i < checkedArr.length; i++) {
let dataid = checkedArr[i];
var input = $(options.elem).find('input[value="' + dataid + '"]');
if (input.length > 0 && !input[0].checked) { //若未选中
input.prop('checked', true);
input.parents('.' + ELEM_PACK).prev().find('input[name="layuiTreeCheck"]').each(function() {
this.checked = true;
});
}
}
that.renderCheckbox();
};
//展开指定节点
var time;
Class.prototype.expand = function() {
var that = this,
options = that.config;
var ICONS = options.icons || {
ICON_ADD: ICON_ADD,
ICON_SUB: ICON_SUB,
ICON_FILE: 'layui-icon-file'
};
if (options.expandAll) {
$(options.elem).find('.' + ELEM_PACK).slideDown(200);
$(options.elem).find('.' + ICONS.ICON_ADD).addClass(ICONS.ICON_SUB).removeClass(ICONS.ICON_ADD);
} else {
var expand = function() {
var addNodes = $(options.elem).find('.' + ICONS.ICON_ADD); //待展开所有节点
if (addNodes.length == 0) {
//展开所有后关闭计时器
// alert('已全部展开!');
that.config.expandAll = true;
clearInterval(time);
var successEvent = that.config.expandSuccess;
successEvent ? successEvent() : '';
return;
}
for (let i = 0; i < addNodes.length; i++) {
if (addNodes.eq(i).hasClass(ICONS.ICON_ADD)) {
addNodes.eq(i).trigger('click');
}
}
}
time = setInterval(expand, 400);
}
};
//折叠指定节点
Class.prototype.fold = function() {
if (time != null) {
clearInterval(time);
}
var that = this,
options = that.config;
var ICONS = options.icons || {
ICON_ADD: ICON_ADD,
ICON_SUB: ICON_SUB,
ICON_FILE: 'layui-icon-file'
};
$(options.elem).find('.' + ELEM_PACK).hide();
$(options.elem).find('.' + ICONS.ICON_SUB).addClass(ICONS.ICON_ADD).removeClass(ICONS.ICON_SUB);
}
//记录所有实例
thisModule.that = {}; //记录所有实例对象
thisModule.config = {}; //记录所有实例配置项
//重载实例
treelazy.reload = function(id, options) {
var that = thisModule.that[id];
that.reload(options);
return thisModule.call(that);
};
//获得选中的节点数据
treelazy.getChecked = function(id) {
var that = thisModule.that[id];
return that.getChecked();
};
//设置选中节点
treelazy.setChecked = function(id, checkedId, clear) {
var that = thisModule.that[id];
return that.setChecked(checkedId, clear);
};
//展开指定节点
treelazy.expand = function(id) {
var that = thisModule.that[id];
return that.expand();
};
//折叠指定节点
treelazy.fold = function(id) {
var that = thisModule.that[id];
return that.fold();
};
treelazy.select = function(options) {
console.log(options);
};
//核心入口
treelazy.render = function(options) {
var inst = new Class(options);
return thisModule.call(inst);
};
//核心入口
treelazy.select = function(options) {
var inst = new Class(options);
return thisModule.call(inst);
}
exports(MOD_NAME, treelazy);
})
相关CSS样式
/* layui表格中的下拉框样式 */
.layui-table-select input {
border: none;
}
.layui-table-select input:hover {
border-color: #008CBA !important;
}
.layui-table-select-anim dl {
border: none;
border-top: 1px solid #E9E9E9;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
}
.layui-table-select-anim dl dd {
overflow: overlay;
}
.layui-table-select-anim dl dd:hover {
background: white !important;
}
/* 滚动条高宽 */
.layui-table-select-anim dl dd::-webkit-scrollbar {
width: 10px;
}
/* 滚动条里面滑块 */
.layui-table-select-anim dl dd::-webkit-scrollbar-thumb {
border-radius: 10px 2px 2px 10px;
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: rgba(0, 0, 0, 0.2);
}
/* 滚动条里面轨道 */
.layui-table-select-anim dl dd::-webkit-scrollbar-track {
border-radius: 10px 2px 2px 10px;
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: rgba(0, 0, 0, 0.1);
}
/**** layui下拉树样式 ****/
.layui-treeselect dl dd {
background: white;
color: #555;
overflow: auto;
}
.layui-treeselect dl dd.layui-this {
background: white;
color: #555;
}
.layui-treeselect dl dd:hover {
background: white;
}
.layui-treeselect .layui-input {
color: #666;
}
.layui-treeselect .layui-disabled {
background: #F6F6F6;
color: #999 !important;
}
/* 滚动条样式 */
/* 滚动条高宽 */
.layui-treeselect dl dd{
overflow: overlay;
}
.layui-treeselect dl dd::-webkit-scrollbar {
width: 10px;
}
/* 滚动条里面滑块 */
.layui-treeselect dl dd::-webkit-scrollbar-thumb {
border-radius: 10px 2px 2px 10px;
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: rgba(0, 0, 0, 0.2);
}
/* 滚动条里面轨道 */
.layui-treeselect dl dd::-webkit-scrollbar-track {
border-radius: 10px 2px 2px 10px;
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: rgba(0, 0, 0, 0.1);
}
一、layui表格中下拉树形组件:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="../layui-master/dist/css/layui.css" />
<title>表格中部门选择下拉框</title>
<style>
html,
body {
overflow: hidden;
}
</style>
</head>
<body>
<div class="layui-fluid">
<div class="layui-row">
<table id="table" lay-filter="table" class="layui-hide"></table>
</div>
</div>
</body>
<script src="../layui-master/dist/layui.js" charset="utf-8"></script>
<script>
var tableID = "table";
layui.config({
base: '../../page/modules/'
}).extend({
treelazy: 'customcomponents/treelazy'
}).use(['layer', 'table', 'treelazy'], function() {
var $ = layui.$,
layer = layui.layer,
treelazy = layui.treelazy,
table = layui.table;
//初始化渲染表格
var datas = [];
for (let i = 0; i < 20; i++) {
datas.push({
id: i + 1
});
}
var tableIns = table.render({
elem: '#' + tableID,
height: 'full-1',
size: 'sm',
limit: 100,
page: true,
cols: [
[{
type: 'numbers'
},
{
field: 'id',
title: 'ID'
},
{
field: 'name',
title: '人员名称',
edit: 'text'
},
{
field: 'wsid',
title: '部门',
event: 'wsidEvent'
},
{
field: 'memo',
title: '备注'
}
]
],
data: datas
});
/********* 监听区 ********/
table.on('row(table)', function(obj) {
obj.tr.addClass("layui-table-click").siblings().removeClass("layui-table-click");
});
table.on('tool(' + tableID + ')', function(obj) {
var data = obj.data,
event = obj.event,
tr = obj.tr; //获得当前行 tr 的DOM对象;
switch (event) {
case 'wsidEvent':
treelazy.tabletreeselect({
tableID: tableID,
td: $(this),
colName: 'wsid',
load: function(node, render) {
var pid = 0;
if (node.level > 0) {
pid = node.data.id;
}
if (node.level == 0) {
render([{
id: 1,
text: '一级部门',
leaf: false
}, {
id: 2,
text: '一级部门',
leaf: false
}, {
id: 3,
text: '一级部门',
leaf: false
}, {
id: 4,
text: '一级部门',
leaf: false
}, {
id: 5,
text: '一级部门',
leaf: false
}]);
}
if (node.level == 1) {
render([{
id: 22,
text: '二级部门1',
leaf: true
}, {
id: 33,
text: '二级部门2',
leaf: true
}]);
}
},
click: function(obj) {
// console.log(obj.data);
}
});
break;
}
});
});
</script>
</html>
二、css样式:
/**** layui下拉树样式 ****/
.layui-treeselect dl dd {
background: white;
color: #555;
overflow: auto;
}
.layui-treeselect dl dd.layui-this {
background: white;
color: #555;
}
.layui-treeselect dl dd:hover {
background: white;
}
.layui-treeselect .layui-input {
color: #666;
}
.layui-treeselect .layui-disabled {
background: #F6F6F6;
color: #999 !important;
}
/* 滚动条样式 */
/* 滚动条高宽 */
.layui-treeselect dl dd{
overflow: overlay;
}
.layui-treeselect dl dd::-webkit-scrollbar {
width: 10px;
}
/* 滚动条里面滑块 */
.layui-treeselect dl dd::-webkit-scrollbar-thumb {
border-radius: 10px 2px 2px 10px;
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: rgba(0, 0, 0, 0.2);
}
/* 滚动条里面轨道 */
.layui-treeselect dl dd::-webkit-scrollbar-track {
border-radius: 10px 2px 2px 10px;
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: rgba(0, 0, 0, 0.1);
}
/* layui表格中的下拉框样式 */
.layui-table-select input {
border: none;
}
.layui-table-select input:hover {
border-color: #008CBA !important;
}
.layui-table-select-anim dl {
border: none;
border-top: 1px solid #E9E9E9;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
}
.layui-table-select-anim dl dd {
overflow: overlay;
}
.layui-table-select-anim dl dd:hover {
background: white !important;
}
/* 滚动条高宽 */
.layui-table-select-anim dl dd::-webkit-scrollbar {
width: 10px;
}
/* 滚动条里面滑块 */
.layui-table-select-anim dl dd::-webkit-scrollbar-thumb {
border-radius: 10px 2px 2px 10px;
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: rgba(0, 0, 0, 0.2);
}
/* 滚动条里面轨道 */
.layui-table-select-anim dl dd::-webkit-scrollbar-track {
border-radius: 10px 2px 2px 10px;
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: rgba(0, 0, 0, 0.1);
}