```
/**
@Name:layui.atree2.0 树组件
@Author:smallwei
@License:MIT
*/
layui.define('jquery', function (exports) {
"use strict";
var $ = layui.$,
hint = layui.hint();
//勾选集合
var changeList = [];
//变量别名
var props = {
name: 'name',
id: 'id',
children: 'children',
checkbox: 'checkbox',
spread: 'spread',
deleteBtnLabelKey: 'delete',
addBtnLabelKey: 'add',
//修改
reviseBtnLabelKey: 'revise'
};
var enterSkin = 'layui-atree-enter',
Atree = function (options) {
//缓冲重要变量
this.$vm = this;
this.$options = options || {};
this.$el = this.utils.isElementNode(this.$options.elem) ? this.$options.elem : $(this.$options.elem);
//模块的属性
this.nodes = this.$options.nodes || [];
this.props = this.$options.props || props;
//模块的别名
this.nameKey = this.props.name || props.name;
this.idKey = this.props.id || props.id;
this.childrenKey = this.props.children || props.children;
this.checkboxKey = this.props.checkbox || props.checkbox;
this.spreadKey = this.props.spread || props.spread;
this.addBtnLabelKey = this.props.addBtnLabel || props.addBtnLabel;
this.deleteBtnLabelKey = this.props.deleteBtnLabel || props.deleteBtnLabel;
this.reviseBtnLabelKey = this.props.reviseBtnLabel || props.reviseBtnLabel;
this.move = {};
};
//图标
var icon = {
arrow: ['', ''] //箭头
,
checkbox: ['', ''] //复选框
,
leaf: '' //叶节点
};
//工具包
Atree.prototype.utils = (function () {
return {
isElementNode: function (node) {
return node.nodeType === 1;
}
}
})()
//初始化
Atree.prototype.init = function () {
var that = this.$vm,
options = this.$options
that.$el.addClass('layui-box layui-atree'); //添加tree样式
if (options.skin) {
that.$el.addClass('layui-atree-skin-' + options.skin);
}
that.tree(that.$el, that.nodes);
that.on(that.$el);
// 补充 第一级
var nodes = that.nodes,len = nodes.length;
if(that.drag){
for(var i = 0; i < len; i++){
(function(i,item){
that.$el.children('li').eq(i).children('.layui-atree-node').on('mouseenter', function (){
var othis = $(this)
, move = that.move;
if (move.from) {
move.to = {
item: item,
elem: othis.parent('li')
};
othis.addClass(enterSkin);
}
})
})(i, nodes[i]);
}
}
};
//树节点解析
Atree.prototype.tree = function (elem, children, parent) {
var that = this.$vm,
options = this.$options
var nodes = children;
layui.each(nodes, function (index, item) {
var hasChild = item[that.childrenKey] && item[that.childrenKey].length > 0;
var dom = that.getDom(item);
if (parent) item.$parent = parent;
var ul = $(dom.ul(item));
var li = $(that.getNode(item));
//如果被选中加入checkbox集合里
if (item[that.checkboxKey]) {
changeList.push(item);
}
//如果有子节点,则递归继续生成树
if (hasChild) {
li.append(ul);
that.tree(ul, item[that.childrenKey], item);
}
//伸展节点
that.spread(li, item);
that.bindUlEvent(li, item);
elem.append(li);
});
};
//节点dom拼接
Atree.prototype.getDom = function (item) {
var that = this.$vm,
options = this.$options,
item = item,
hasChild = item[that.childrenKey] && item[that.childrenKey].length > 0;
return {
spread: function () {
return hasChild ? '<i class="layui-icon layui-atree-spread">' + (
item[that.spreadKey] || options.spreadAll ? icon.arrow[1] : icon.arrow[0]
) + '</i>' : '';
},
checkbox: function () {
return options.check ? (
'<i class="layui-icon layui-atree-check' + (item[that.checkboxKey] ? ' is-checked' : '') + '">' + (
item[that.checkboxKey] ? icon.checkbox[1] : icon.checkbox[0]
) + '</i>'
) : '';
},
ul: function () {
return '<ul class="' + (item[that.spreadKey] || options.spreadAll ? "layui-show" : "") + '"></ul>'
},
node: function () {
return '<a href="' + (item.href || 'javascript:;') + '" ' + (
options.target && item.href ? 'target=\"' + options.target + '\"' : ''
) + '>' +
('<cite>' + (item[that.nameKey] || '未命名') + '</cite></a>')
},
menu: function () {
return '<div class="layui-atree-menu">' +
'<span class="layui-atree-add" id="atree-add">' + that.addBtnLabelKey + '</span>' +
'<span class="layui-atree-delete">' + that.deleteBtnLabelKey + '</span>' +
'<span class="layui-atree-revise">' + that.reviseBtnLabelKey + '</span>' +
'</div>'
}
}
}
//获取树节点
Atree.prototype.getNode = function (item) {
var that = this.$vm,
options = this.$options
var dom = that.getDom(item);
var li = ['<li ' +
(item[that.spreadKey] || options.spreadAll ? 'data-spread="' + (item[that.spreadKey] || true) + '"' : '') +
(item[that.checkboxKey] ? 'data-check="' + item[that.checkboxKey] + '"' : '') +
('data-id=' + item[that.idKey]) +
'><div class="layui-atree-node">'
//展开箭头
,
dom.spread()
//复选框
,
dom.checkbox()
//节点
,
dom.node()
//菜单
,
dom.menu(),
'</div></li>'
].join('');
return li;
}
//父绑定事件
Atree.prototype.bindUlEvent = function (li, item) {
var that = this.$vm,
options = this.$options
//触发点击节点回调
typeof options.click === 'function' && that.click(li, item);
//节点选择
typeof options.change === 'function' && options.check === 'checkbox' && that.checkbox(li, item);
//新增方法
typeof options.addClick === 'function' && that.add(li, item);
//删除方法
typeof options.deleteClick === 'function' && that.delete(li, item);
//修改方式
typeof options.reviseClick === 'function' && that.revise(li, item);
//拖拽节点
options.drag && that.drag(li, item);
}
//选中回调函数
Atree.prototype.change = function () {
var that = this.$vm,
options = this.$options;
options.change(changeList);
},
//新增方法回调
Atree.prototype.add = function (elem, item) {
var that = this.$vm,
options = this.$options;
var node = elem.children('.layui-atree-node');
var addBtn = node.children('.layui-atree-menu').children('.layui-atree-add')
var arrow = node.children('.layui-atree-spread')
var ul = elem.children('ul'),
a = node.children('a');
var addEvent = function (e) {
layui.stope(e);
var _addEvent = {
add: function (itemAddObj) {
if (!item[that.childrenKey]) {
item[that.childrenKey] = [];
}
item[that.childrenKey].push(itemAddObj);
var dom = that.getDom(item);
if (!ul[0]) {
ul = $(dom.ul())
elem.append(ul);
}
if (!arrow[0]) {
arrow = $(dom.spread());
node.prepend(arrow);
that.spread(elem, item);
}
if (!elem.data('spread')) {
that.open(elem, ul, arrow)
}
var li = $(that.getNode(itemAddObj));
that.bindUlEvent(li, itemAddObj);
ul.append(li);
}
}
options.addClick(item, elem, _addEvent.add)
}
addBtn.on('click', addEvent);
}
//删除方法回调
Atree.prototype.delete = function (elem, item) {
//debugger
var that = this.$vm,
options = this.$options;
var node = elem.children('.layui-atree-node');
var deleteBtn = node.children('.layui-atree-menu').children('.layui-atree-delete')
var ul = elem.children('ul'),
a = elem.children('a');
var deleteEvent = function (e) {
layui.stope(e);
var _deleteEvent = {
done: function () {
var parent = elem.parent();
var arrow = parent.parent().children('.layui-atree-spread')
if (parent.children('li').length === 1) {
arrow.remove();
}
elem.remove();
}
}
options.deleteClick(item, elem, _deleteEvent.done)
}
deleteBtn.on('click', deleteEvent);
}
//修改方法回调
Atree.prototype.revise = function (elem, item) {
var that = this.$vm,
options = this.$options;
var node = elem.children('.layui-atree-node');
var reviseBtn = node.children('.layui-atree-menu').children('.layui-atree-revise');
var ul = elem.children('ul'),
a = node.children('a');
var reviseEvent = function (e) {
layui.stope(e);
var _reviseEvent = {
done: function () {
var htmla = a.prop('outerHTML');
var nodeName = item.name;
// a.next('div.layui-atree-menu').hide();
a.replaceWith('<input value="' + nodeName + '">');
elem.find('input').focus().change(function(){
item.name = $(this).val();
htmla = htmla.replace(nodeName, $(this).val());
$(this).blur();
}).blur(function(){
$(this).replaceWith(htmla);
a = elem.children('div').children('a');
/* layui.use(['admin','layer'], function () {
layui.admin.req({
url: layui.setter.apiUrl.SlopsApi + '/Execute',
data: {
path: 'admin/AtreeRevise.txt',
bidID: layui.data(layui.setter.tableName).bidID,
ID: item.id,
Title: item.name
},
done: function (res) {
}
})
}); */
});
}
}
options.reviseClick(item, elem, _reviseEvent.done)
}
reviseBtn.on('click', reviseEvent);
}
//点击节点回调
Atree.prototype.click = function (elem, item) {
var that = this.$vm,
options = this.$options;
var node = elem.children('.layui-atree-node');
node.children('a').on('click', function (e) {
layui.stope(e);
options.click(item)
});
};
//节点选择
Atree.prototype.checkbox = function (elem, item) {
var that = this.$vm,
options = this.$options;
var node = elem.children('.layui-atree-node');
var checkbox = node.children('.layui-atree-check')
var ul = elem.children('ul'),
a = node.children('a');
//递归设置子节点
var setAllChildCheck = function (dom, item, type) {
var list = dom.children('.layui-show').find('li');
var children = item ? item.children || [] : [];
for (var i = 0; i < list.length; i++) {
var li = $(list[i]);
setCheck(li, children[i], type);
setAllChildCheck(li, children[i], type);
}
}
//递归设置父节点
var setAllPatentCheck = function (dom, item, type) {
var parent = dom.parent().parent();
var list = parent.children('.layui-show').find('li');
var isChildrenCheck = true;
for (var i = 0; i < list.length; i++) {
var li = $(list[i]);
if (!li.data('check')) isChildrenCheck = false;
}
if (item.$parent && (isChildrenCheck || !type)) {
setCheck(parent, item.$parent, type);
setAllPatentCheck(parent, item.$parent, type);
}
}
//设置节点选中状态
var setCheck = function (elem, item, type) {
var checkbox = elem.children('.layui-atree-node').find('.layui-atree-check');
if (type) {
elem.data('check', true)
elem.attr("data-check", true);
checkbox.html(icon.checkbox[1])
checkbox.addClass(' is-checked');
} else {
elem.data('check', null);
elem.attr("data-check", null);
checkbox.removeClass(' is-checked');
checkbox.html(icon.checkbox[0])
}
if (item) {
var index = layui.findObj(changeList, item[that.idKey], that.idKey);
//debugger
if (index === -1 && type === true) {
changeList.push(item);
} else if (type === false) {
changeList.splice(index, 1);
}
}
}
var check = function () {
var checkFlag;
if (elem.data('check')) {
checkFlag = false;
} else {
checkFlag = true;
}
setCheck(elem, item, checkFlag)
setAllPatentCheck(elem, item, checkFlag);
setAllChildCheck(elem, item, checkFlag);
that.change();
}
checkbox.on('click', check);
};
//伸展节点
Atree.prototype.spread = function (elem, item) {
var that = this.$vm,
options = this.$options;
var node = elem.children('.layui-atree-node');
var arrow = node.children('.layui-atree-spread')
var ul = elem.children('ul'),
a = node.children('a');
//如果没有子节点,则不执行
if (!ul[0]) return;
arrow.on('click', function () {
that.open(elem, ul, arrow)
});
}
//打开节点
Atree.prototype.open = function (elem, ul, arrow) {
if (elem.data('spread')) {
elem.data('spread', null)
elem.attr("data-spread", null);
ul.removeClass('layui-show');
arrow.html(icon.arrow[0]);
} else {
elem.data('spread', true);
elem.attr("data-spread", true);
ul.addClass('layui-show');
arrow.html(icon.arrow[1]);
}
};
//通用事件
Atree.prototype.on = function (elem) {
var that = this.$vm,
options = this.$options;
var dragStr = 'layui-atree-drag';
//屏蔽选中文字
elem.find('i').on('selectstart', function (e) {
return false
});
//拖拽
if (options.drag) {
//mousedown:鼠标按钮被按下(左键或者右键)时触发。不能通过键盘触发。
$(document).on('mousemove', function (e) {
var move = that.move;
// 拖动状态, 增加一个
if (move.from) {
//debugger
var to = move.to
,dragElem = $('.' + dragStr);
e.preventDefault();
if(!dragElem[0]){
dragElem = $('<div class="layui-box ' + dragStr + '"></div>');
$('body').append(dragElem);
(dragElem).addClass('layui-show').html(move.from.elem.children('.layui-atree-node').children('a').html());
}
dragElem.css({
left: e.pageX + 10,
top: e.pageY + 10
});
}
//mouseup:鼠标按钮被释放弹起时触发。不能通过键盘触发。
}).on('mouseup', function () {
var move = that.move;
if (move.from) {
that.$el.find('.'+enterSkin).removeClass(enterSkin);
that.move = {};
$('.' + dragStr).remove();
if(!move.to) return;
move.from.elem.appendTo(move.to.elem);
var item = move.from.item, chds = move.from.$parent&&move.from.$parent.children, len = chds&&chds.length;
for(var i = 0; i < len; i++){
if(chds[i] === item){
chds.splice(i,1);
break;
}
}
move.to.item.children.push(item);
options.dragend && options.dragend(move.from,move.to);
that.move = {};
}
});
}
};
//拖拽节点
Atree.prototype.move = {};
Atree.prototype.drag = function (elem, item) {
var that = this.$vm,
options = this.$options;
var a = elem.children('.layui-atree-node').children('a'),
mouseenter = function () {
var othis = $(this),
move = that.move;
if (move.from) {
move.to = {
item: item,
elem: elem
};
othis.addClass(enterSkin);
}
};
// 点击后,初始拖动
a.on('mousedown', function () {
var move = that.move
move.from = {
item: item,
elem: elem
};
});
// 拖动状态经过项目时,增加经过样式,离开取消样式
elem.on('mouseenter', mouseenter)
.on('mouseleave', function () {
var othis = $(this),
move = that.move;
if (move.from) {
delete move.to;
othis.removeClass(enterSkin);
}
});
};
// 新增
Atree.prototype.addNode = function (node, parent){
var t = $.type(parent);
if(t === 'object'){
parent.children.push(node);
}else if( t === 'null' || t === 'undefined' ){
this.$options.nodes.push(node);
}else{
var parentNode = this.findNode(parent);
parentNode && parentNode.children.push(node);
}
return this;
}
// 移除节点,根据节点ID
Atree.prototype.removeNode = function (id){
var node = this.findNode(id);
var chds = node.$parent.children, len = chds.length;
for(var i = 0; i < len; i++){
if(chds[i] === node){
chds.splice(i,1);
return this;
}
}
return this;
}
Atree.prototype.findNode = function (id, node){
if(!node){
node = {};
node.children = this.$options.nodes;
}
if(node.id == id){
return node;
}
else {
var children = node.children, len = children&&children.length;
if(len){
for(var i = 0; i < len; i++){
var nd = this.findNode(id, children[i]);
if(nd){
return nd;
}
}
}
return null;
}
}
Atree.prototype.findNodeByName = function (name, node){
if(!node){
node = {};
node.children = this.$options.nodes;
}
if(node[this.nameKey]&&node[this.nameKey].indexOf(name) != -1){
return node;
}
else {
var children = node.children, len = children&&children.length;
if(len){
for(var i = 0; i < len; i++){
var nd = this.findNodeByName(name, children[i]);
if(nd){
return nd;
}
}
}
return null;
}
}
//查询到对应的值
Atree.prototype.getNodesByName = function (name, arr, node){
if(!node){
node = {};
node.children = this.$options.nodes;
}
// 相似记录 到 arr 中
if(node[this.nameKey]&&node[this.nameKey].indexOf(name) != -1){
arr.push(node);
}
// 检查是否有 子集, 有则遍历子, 无则返回
var children = node.children, len = children&&children.length;
if(len){
for(var i = 0; i < len; i++){
this.getNodesByName(name, arr, children[i]);
}
}else{
return;
}
}
Atree.prototype.updateNode = function (id, attrs){
var node = this.findNode(id);
node&&$.extend(node, attrs);
return this;
}
// 重新加载
Atree.prototype.reload = function (){
this.$el.html('');
this.init(this.$options);
return this;
}
//暴露接口
exports('atree', function (options) {
//debugger
var atree = new Atree(options = options || {});
var elem = $(options.elem);
if (!elem[0]) {
return hint.error('layui.atree 没有找到' + options.elem + '元素');
}
atree.init(elem);
return atree;
});
});
```