tree.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /**
  2. @Name:layui.tree 树组件
  3. @Author:贤心
  4. @License:MIT
  5. */
  6. layui.define('jquery', function(exports){
  7. "use strict";
  8. var $ = layui.$
  9. ,hint = layui.hint();
  10. var enterSkin = 'layui-tree-enter', Tree = function(options){
  11. this.options = options;
  12. };
  13. //图标
  14. var icon = {
  15. arrow: ['', ''] //箭头
  16. ,checkbox: ['', ''] //复选框
  17. ,radio: ['', ''] //单选框
  18. ,branch: ['', ''] //父节点
  19. ,leaf: '' //叶节点
  20. };
  21. //初始化
  22. Tree.prototype.init = function(elem){
  23. var that = this;
  24. elem.addClass('layui-box layui-tree'); //添加tree样式
  25. if(that.options.skin){
  26. elem.addClass('layui-tree-skin-'+ that.options.skin);
  27. }
  28. that.tree(elem);
  29. that.on(elem);
  30. };
  31. //树节点解析
  32. Tree.prototype.tree = function(elem, children){
  33. var that = this, options = that.options
  34. var nodes = children || options.nodes;
  35. layui.each(nodes, function(index, item){
  36. var hasChild = item.children && item.children.length > 0;
  37. var ul = $('<ul class="'+ (item.spread ? "layui-show" : "") +'"></ul>');
  38. var li = $(['<li '+ (item.spread ? 'data-spread="'+ item.spread +'"' : '') +'>'
  39. //展开箭头
  40. ,function(){
  41. return hasChild ? '<i class="layui-icon layui-tree-spread">'+ (
  42. item.spread ? icon.arrow[1] : icon.arrow[0]
  43. ) +'</i>' : '';
  44. }()
  45. //复选框/单选框
  46. ,function(){
  47. return options.check ? (
  48. '<i class="layui-icon layui-tree-check">'+ (
  49. options.check === 'checkbox' ? icon.checkbox[0] : (
  50. options.check === 'radio' ? icon.radio[0] : ''
  51. )
  52. ) +'</i>'
  53. ) : '';
  54. }()
  55. //节点
  56. ,function(){
  57. return '<a href="'+ (item.href || 'javascript:;') +'" '+ (
  58. options.target && item.href ? 'target=\"'+ options.target +'\"' : ''
  59. ) +'>'
  60. + ('<i class="layui-icon layui-tree-'+ (hasChild ? "branch" : "leaf") +'">'+ (
  61. hasChild ? (
  62. item.spread ? icon.branch[1] : icon.branch[0]
  63. ) : icon.leaf
  64. ) +'</i>') //节点图标
  65. + ('<cite>'+ (item.name||'未命名') +'</cite></a>');
  66. }()
  67. ,'</li>'].join(''));
  68. //如果有子节点,则递归继续生成树
  69. if(hasChild){
  70. li.append(ul);
  71. that.tree(ul, item.children);
  72. }
  73. elem.append(li);
  74. //触发点击节点回调
  75. typeof options.click === 'function' && that.click(li, item);
  76. //伸展节点
  77. that.spread(li, item);
  78. //拖拽节点
  79. options.drag && that.drag(li, item);
  80. });
  81. };
  82. //点击节点回调
  83. Tree.prototype.click = function(elem, item){
  84. var that = this, options = that.options;
  85. elem.children('a').on('click', function(e){
  86. layui.stope(e);
  87. options.click(item)
  88. });
  89. };
  90. //伸展节点
  91. Tree.prototype.spread = function(elem, item){
  92. var that = this, options = that.options;
  93. var arrow = elem.children('.layui-tree-spread')
  94. var ul = elem.children('ul'), a = elem.children('a');
  95. //执行伸展
  96. var open = function(){
  97. if(elem.data('spread')){
  98. elem.data('spread', null)
  99. ul.removeClass('layui-show');
  100. arrow.html(icon.arrow[0]);
  101. a.find('.layui-icon').html(icon.branch[0]);
  102. } else {
  103. elem.data('spread', true);
  104. ul.addClass('layui-show');
  105. arrow.html(icon.arrow[1]);
  106. a.find('.layui-icon').html(icon.branch[1]);
  107. }
  108. };
  109. //如果没有子节点,则不执行
  110. if(!ul[0]) return;
  111. arrow.on('click', open);
  112. a.on('dblclick', open);
  113. }
  114. //通用事件
  115. Tree.prototype.on = function(elem){
  116. var that = this, options = that.options;
  117. var dragStr = 'layui-tree-drag';
  118. //屏蔽选中文字
  119. elem.find('i').on('selectstart', function(e){
  120. return false
  121. });
  122. //拖拽
  123. if(options.drag){
  124. $(document).on('mousemove', function(e){
  125. var move = that.move;
  126. if(move.from){
  127. var to = move.to, treeMove = $('<div class="layui-box '+ dragStr +'"></div>');
  128. e.preventDefault();
  129. $('.' + dragStr)[0] || $('body').append(treeMove);
  130. var dragElem = $('.' + dragStr)[0] ? $('.' + dragStr) : treeMove;
  131. (dragElem).addClass('layui-show').html(move.from.elem.children('a').html());
  132. dragElem.css({
  133. left: e.pageX + 10
  134. ,top: e.pageY + 10
  135. })
  136. }
  137. }).on('mouseup', function(){
  138. var move = that.move;
  139. if(move.from){
  140. move.from.elem.children('a').removeClass(enterSkin);
  141. move.to && move.to.elem.children('a').removeClass(enterSkin);
  142. that.move = {};
  143. $('.' + dragStr).remove();
  144. }
  145. });
  146. }
  147. };
  148. //拖拽节点
  149. Tree.prototype.move = {};
  150. Tree.prototype.drag = function(elem, item){
  151. var that = this, options = that.options;
  152. var a = elem.children('a'), mouseenter = function(){
  153. var othis = $(this), move = that.move;
  154. if(move.from){
  155. move.to = {
  156. item: item
  157. ,elem: elem
  158. };
  159. othis.addClass(enterSkin);
  160. }
  161. };
  162. a.on('mousedown', function(){
  163. var move = that.move
  164. move.from = {
  165. item: item
  166. ,elem: elem
  167. };
  168. });
  169. a.on('mouseenter', mouseenter).on('mousemove', mouseenter)
  170. .on('mouseleave', function(){
  171. var othis = $(this), move = that.move;
  172. if(move.from){
  173. delete move.to;
  174. othis.removeClass(enterSkin);
  175. }
  176. });
  177. };
  178. //暴露接口
  179. exports('tree', function(options){
  180. var tree = new Tree(options = options || {});
  181. var elem = $(options.elem);
  182. if(!elem[0]){
  183. return hint.error('layui.tree 没有找到'+ options.elem +'元素');
  184. }
  185. tree.init(elem);
  186. });
  187. });