contextMenu.js 9.2 KB

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