contextMenu.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /**
  2. * 右键菜单模块
  3. * date:2019-04-23 License By http://easyweb.vip
  4. */
  5. layui.define(["jquery"], function (exports) {
  6. var $ = layui.jquery;
  7. var contextMenu = {
  8. // 绑定元素
  9. bind: function (elem, items) {
  10. $(elem).bind('contextmenu', function (e) {
  11. contextMenu.show(items, e.clientX, e.clientY);
  12. return false;
  13. });
  14. },
  15. // 构建无限级
  16. getHtml: function (items, pid) {
  17. var htmlStr = '';
  18. for (var i = 0; i < items.length; i++) {
  19. var item = items[i];
  20. item.itemId = 'ctxMenu-' + pid + i;
  21. if (item.subs && item.subs.length > 0) {
  22. htmlStr += '<div class="ctxMenu-item haveMore" lay-id="' + item.itemId + '">';
  23. htmlStr += '<a>';
  24. if (item.icon) {
  25. htmlStr += '<i class="' + item.icon + ' ctx-icon"></i>';
  26. }
  27. htmlStr += item.name;
  28. htmlStr += '<i class="layui-icon layui-icon-right icon-more"></i>';
  29. htmlStr += '</a>';
  30. htmlStr += '<div class="ctxMenu-sub" style="display: none;">';
  31. htmlStr += contextMenu.getHtml(item.subs, pid + i);
  32. htmlStr += '</div>';
  33. } else {
  34. htmlStr += '<div class="ctxMenu-item" lay-id="' + item.itemId + '">';
  35. htmlStr += '<a>';
  36. if (item.icon) {
  37. htmlStr += '<i class="' + item.icon + ' ctx-icon"></i>';
  38. }
  39. htmlStr += item.name;
  40. htmlStr += '</a>';
  41. }
  42. htmlStr += '</div>';
  43. if (item.hr == true) {
  44. htmlStr += '<hr/>';
  45. }
  46. }
  47. return htmlStr;
  48. },
  49. // 设置事件监听
  50. setEvents: function (items) {
  51. for (var i = 0; i < items.length; i++) {
  52. var item = items[i];
  53. if (item.click) {
  54. $('.ctxMenu').on('click', '[lay-id="' + item.itemId + '"]', item.click);
  55. }
  56. if (item.subs && item.subs.length > 0) {
  57. contextMenu.setEvents(item.subs);
  58. }
  59. }
  60. },
  61. // 移除所有
  62. remove: function () {
  63. var ifs = top.window.frames;
  64. for (var i = 0; i < ifs.length; i++) {
  65. var tif = ifs[i];
  66. try {
  67. tif.layui.jquery('body>.ctxMenu').remove();
  68. } catch (e) {
  69. }
  70. }
  71. try {
  72. top.layui.jquery('body>.ctxMenu').remove();
  73. } catch (e) {
  74. }
  75. },
  76. // 获取浏览器高度
  77. getPageHeight: function () {
  78. return document.documentElement.clientHeight || document.body.clientHeight;
  79. },
  80. // 获取浏览器宽度
  81. getPageWidth: function () {
  82. return document.documentElement.clientWidth || document.body.clientWidth;
  83. },
  84. // 在指定坐标显示菜单
  85. show: function (items, x, y) {
  86. var xy = 'left: ' + x + 'px; top: ' + y + 'px;';
  87. var htmlStr = '<div class="ctxMenu" style="' + xy + '">';
  88. htmlStr += contextMenu.getHtml(items, '');
  89. htmlStr += ' </div>';
  90. contextMenu.remove();
  91. $('body').append(htmlStr);
  92. // 调整溢出位置
  93. var $ctxMenu = $('.ctxMenu');
  94. if (x + $ctxMenu.outerWidth() > contextMenu.getPageWidth()) {
  95. x -= $ctxMenu.outerWidth();
  96. }
  97. if (y + $ctxMenu.outerHeight() > contextMenu.getPageHeight()) {
  98. y = y - $ctxMenu.outerHeight();
  99. if (y < 0) {
  100. y = 0;
  101. }
  102. }
  103. $ctxMenu.css({'top': y, 'left': x});
  104. // 添加item点击事件
  105. contextMenu.setEvents(items);
  106. // 显示子菜单事件
  107. $('.ctxMenu-item.haveMore').on('mouseenter', function () {
  108. var $item = $(this).find('>a');
  109. var $sub = $(this).find('>.ctxMenu-sub');
  110. var top = $item.offset().top;
  111. var left = $item.offset().left + $item.outerWidth();
  112. if (left + $sub.outerWidth() > contextMenu.getPageWidth()) {
  113. left = $item.offset().left - $sub.outerWidth();
  114. }
  115. if (top + $sub.outerHeight() > contextMenu.getPageHeight()) {
  116. top = top - $sub.outerHeight() + $item.outerHeight();
  117. if (top < 0) {
  118. top = 0;
  119. }
  120. }
  121. $(this).find('>.ctxMenu-sub').css({
  122. 'top': top,
  123. 'left': left,
  124. 'display': 'block'
  125. });
  126. }).on('mouseleave', function () {
  127. $(this).find('>.ctxMenu-sub').css('display', 'none');
  128. });
  129. },
  130. // 获取css代码
  131. getCommonCss: function () {
  132. var cssStr = '.ctxMenu, .ctxMenu-sub {';
  133. cssStr += ' max-width: 250px;';
  134. cssStr += ' min-width: 110px;';
  135. cssStr += ' background: white;';
  136. cssStr += ' border-radius: 2px;';
  137. cssStr += ' padding: 5px 0;';
  138. cssStr += ' white-space: nowrap;';
  139. cssStr += ' position: fixed;';
  140. cssStr += ' z-index: 2147483647;';
  141. cssStr += ' box-shadow: 0 2px 4px rgba(0, 0, 0, .12);';
  142. cssStr += ' border: 1px solid #d2d2d2;';
  143. cssStr += ' overflow: visible;';
  144. cssStr += ' }';
  145. cssStr += ' .ctxMenu-item {';
  146. cssStr += ' position: relative;';
  147. cssStr += ' }';
  148. cssStr += ' .ctxMenu-item > a {';
  149. cssStr += ' font-size: 14px;';
  150. cssStr += ' color: #666;';
  151. cssStr += ' padding: 0 26px 0 35px;';
  152. cssStr += ' cursor: pointer;';
  153. cssStr += ' display: block;';
  154. cssStr += ' line-height: 36px;';
  155. cssStr += ' text-decoration: none;';
  156. cssStr += ' position: relative;';
  157. cssStr += ' }';
  158. cssStr += ' .ctxMenu-item > a:hover {';
  159. cssStr += ' background: #f2f2f2;';
  160. cssStr += ' color: #666;';
  161. cssStr += ' }';
  162. cssStr += ' .ctxMenu-item > a > .icon-more {';
  163. cssStr += ' position: absolute;';
  164. cssStr += ' right: 5px;';
  165. cssStr += ' top: 0;';
  166. cssStr += ' font-size: 12px;';
  167. cssStr += ' color: #666;';
  168. cssStr += ' }';
  169. cssStr += ' .ctxMenu-item > a > .ctx-icon {';
  170. cssStr += ' position: absolute;';
  171. cssStr += ' left: 12px;';
  172. cssStr += ' top: 0;';
  173. cssStr += ' font-size: 15px;';
  174. cssStr += ' color: #666;';
  175. cssStr += ' }';
  176. cssStr += ' .ctxMenu hr {';
  177. cssStr += ' background-color: #e6e6e6;';
  178. cssStr += ' clear: both;';
  179. cssStr += ' margin: 5px 0;';
  180. cssStr += ' border: 0;';
  181. cssStr += ' height: 1px;';
  182. cssStr += ' }';
  183. cssStr += ' .ctx-ic-lg {';
  184. cssStr += ' font-size: 18px !important;';
  185. cssStr += ' left: 11px !important;';
  186. cssStr += ' }';
  187. return cssStr;
  188. }
  189. };
  190. // 点击任意位置关闭菜单
  191. $(document).off('click.ctxMenu').on('click.ctxMenu', function () {
  192. contextMenu.remove();
  193. });
  194. // 点击有子菜单的节点不关闭菜单
  195. $(document).off('click.ctxMenuMore').on('click.ctxMenuMore', '.ctxMenu-item', function (e) {
  196. if ($(this).hasClass('haveMore')) {
  197. if (e !== void 0) {
  198. e.preventDefault();
  199. e.stopPropagation();
  200. }
  201. } else {
  202. contextMenu.remove();
  203. }
  204. });
  205. $('head').append('<style>' + contextMenu.getCommonCss() + '</style>');
  206. exports("contextMenu", contextMenu);
  207. });