123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125 |
- /**
-
- @Name:layui.tree 树
- @Author:star1029
- @License:MIT
- */
- layui.define('form', function(exports){
- "use strict";
-
- var $ = layui.$
- ,form = layui.form
-
- //模块名
- ,MOD_NAME = 'tree'
- //外部接口
- ,tree = {
- 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 = ++tree.index;
- that.config = $.extend({}, that.config, tree.config, options);
- that.render();
- };
- //默认配置
- 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;
- var temp = $('<div class="layui-tree'+ (options.showCheckbox ? " layui-form" : "") + (options.showLine ? " layui-tree-line" : "") +'" lay-filter="LAY-tree-'+ that.index +'"></div>');
- that.tree(temp);
- var othis = options.elem = $(options.elem);
- if(!othis[0]) return;
- if(options.showSearch){
- temp.prepend('<input type="text" class="layui-input layui-tree-search" placeholder="请输入关键字进行过滤">');
- };
-
-
- //索引
- that.key = options.id || that.index;
-
-
- //插入组件结构
- that.elem = temp;
- that.elemNone = $('<div class="layui-tree-emptyText">'+ options.text.none +'</div>');
- othis.html(that.elem);
- if(that.elem.find('.layui-tree-set').length == 0){
- return that.elem.append(that.elemNone);
- };
- //拖拽事件
- options.drag && that.drag();
-
- //复选框渲染
- if(options.showCheckbox){
- that.renderForm('checkbox');
- };
- that.elem.find('.layui-tree-set').each(function(){
- var othis = $(this);
- //最外层
- if(!othis.parent('.layui-tree-pack')[0]){
- othis.addClass('layui-tree-setHide');
- };
- //没有下一个节点 上一层父级有延伸线
- if(!othis.next()[0] && othis.parents('.layui-tree-pack').eq(1).hasClass('layui-tree-lineExtend')){
- othis.addClass(ELEM_LINE_SHORT);
- };
-
- //没有下一个节点 外层最后一个
- if(!othis.next()[0] && !othis.parents('.layui-tree-set').eq(0).next()[0]){
- othis.addClass(ELEM_LINE_SHORT);
- };
- });
- that.events();
- };
-
- //渲染表单
- Class.prototype.renderForm = function(type){
- form.render(type, 'LAY-tree-'+ this.index);
- };
- //节点解析
- Class.prototype.tree = 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.tree(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.tree(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 = [];
-
- //遍历节点找到选中索引
- that.elem.find('.layui-form-checked').each(function(){
- checkId.push($(this).prev()[0].value);
- });
-
- //遍历节点
- var eachNodes = function(data, checkNode){
- layui.each(data, function(index, item){
- layui.each(checkId, function(index2, item2){
- if(item.id == item2){
- var cloneItem = $.extend({}, item);
- delete cloneItem.children;
-
- checkNode.push(cloneItem);
-
- if(item.children){
- cloneItem.children = [];
- eachNodes(item.children, cloneItem.children);
- }
- return true
- }
- });
- });
- };
- eachNodes($.extend({}, options.data), checkData);
-
- return checkData;
- };
- //设置选中节点
- Class.prototype.setChecked = function(checkedId){
- var that = this
- ,options = that.config;
- //初始选中
- that.elem.find('.'+ELEM_SET).each(function(i, item){
- var thisId = $(this).data('id')
- ,input = $(item).children('.'+ELEM_ENTRY).find('input[name="layuiTreeCheck"]')
- ,reInput = input.next();
-
- //若返回数字
- if(typeof checkedId === 'number'){
- if(thisId == checkedId){
- if(!input[0].checked){
- reInput.click();
- };
- return false;
- };
- }else{
- //若返回数组
- if($.inArray(thisId, checkedId) != -1){
- if(!input[0].checked){
- reInput.click();
- };
- };
- };
- });
- };
- //记录所有实例
- thisModule.that = {}; //记录所有实例对象
- thisModule.config = {}; //记录所有实例配置项
-
- //重载实例
- tree.reload = function(id, options){
- var that = thisModule.that[id];
- that.reload(options);
-
- return thisModule.call(that);
- };
-
- //获得选中的节点数据
- tree.getChecked = function(id){
- var that = thisModule.that[id];
- return that.getChecked();
- };
-
- //设置选中节点
- tree.setChecked = function(id, checkedId){
- var that = thisModule.that[id];
- return that.setChecked(checkedId);
- };
-
- //核心入口
- tree.render = function(options){
- var inst = new Class(options);
- return thisModule.call(inst);
- };
- exports(MOD_NAME, tree);
- })
|