index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. "use strict";
  2. var __read = (this && this.__read) || function (o, n) {
  3. var m = typeof Symbol === "function" && o[Symbol.iterator];
  4. if (!m) return o;
  5. var i = m.call(o), r, ar = [], e;
  6. try {
  7. while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
  8. }
  9. catch (error) { e = { error: error }; }
  10. finally {
  11. try {
  12. if (r && !r.done && (m = i["return"])) m.call(i);
  13. }
  14. finally { if (e) throw e.error; }
  15. }
  16. return ar;
  17. };
  18. var __spread = (this && this.__spread) || function () {
  19. for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
  20. return ar;
  21. };
  22. Object.defineProperty(exports, "__esModule", { value: true });
  23. exports.Menu = void 0;
  24. var DefaultNodeMenuKey = 'lf:defaultNodeMenu';
  25. var DefaultEdgeMenuKey = 'lf:defaultEdgeMenu';
  26. var DefaultGraphMenuKey = 'lf:defaultGraphMenu';
  27. var DefaultSelectionMenuKey = 'lf:defaultSelectionMenu';
  28. var Menu = /** @class */ (function () {
  29. function Menu(_a) {
  30. var _this = this;
  31. var lf = _a.lf;
  32. this.__menuDOM = document.createElement('ul');
  33. this.lf = lf;
  34. this.menuTypeMap = new Map();
  35. this.init();
  36. this.lf.setMenuConfig = function (config) {
  37. _this.setMenuConfig(config);
  38. };
  39. this.lf.addMenuConfig = function (config) {
  40. _this.addMenuConfig(config);
  41. };
  42. this.lf.setMenuByType = function (config) {
  43. _this.setMenuByType(config);
  44. };
  45. }
  46. /**
  47. * 初始化设置默认内置菜单栏
  48. */
  49. Menu.prototype.init = function () {
  50. var _this = this;
  51. var defaultNodeMenu = [
  52. {
  53. text: '删除',
  54. callback: function (node) {
  55. _this.lf.deleteNode(node.id);
  56. },
  57. },
  58. {
  59. text: '编辑文本',
  60. callback: function (node) {
  61. _this.lf.graphModel.editText(node.id);
  62. },
  63. },
  64. {
  65. text: '复制',
  66. callback: function (node) {
  67. _this.lf.cloneNode(node.id);
  68. },
  69. },
  70. ];
  71. this.menuTypeMap.set(DefaultNodeMenuKey, defaultNodeMenu);
  72. var defaultEdgeMenu = [
  73. {
  74. text: '删除',
  75. callback: function (edge) {
  76. _this.lf.deleteEdge(edge.id);
  77. },
  78. },
  79. {
  80. text: '编辑文本',
  81. callback: function (edge) {
  82. _this.lf.graphModel.editText(edge.id);
  83. },
  84. },
  85. ];
  86. this.menuTypeMap.set(DefaultEdgeMenuKey, defaultEdgeMenu);
  87. this.menuTypeMap.set(DefaultGraphMenuKey, []);
  88. var DefaultSelectionMenu = [
  89. {
  90. text: '删除',
  91. callback: function (elements) {
  92. _this.lf.clearSelectElements();
  93. elements.edges.forEach(function (edge) { return _this.lf.deleteEdge(edge.id); });
  94. elements.nodes.forEach(function (node) { return _this.lf.deleteNode(node.id); });
  95. },
  96. },
  97. ];
  98. this.menuTypeMap.set(DefaultSelectionMenuKey, DefaultSelectionMenu);
  99. };
  100. Menu.prototype.render = function (lf, container) {
  101. var _this = this;
  102. this.__container = container;
  103. this.__currentData = null; // 当前展示的菜单所属元素的model数据
  104. this.__menuDOM.className = 'lf-menu';
  105. container.appendChild(this.__menuDOM);
  106. // 将选项的click事件委托至menu容器
  107. // 在捕获阶段拦截并执行
  108. this.__menuDOM.addEventListener('click', function (event) {
  109. event.stopPropagation();
  110. var target = event.target;
  111. // 菜单有多层dom,需要精确获取菜单项所对应的dom
  112. // 除菜单项dom外,应考虑两种情况
  113. // 1. 菜单项的子元素 2. 菜单外层容器
  114. while (Array.from(target.classList).indexOf('lf-menu-item') === -1 && Array.from(target.classList).indexOf('lf-menu') === -1) {
  115. target = target.parentElement;
  116. }
  117. if (Array.from(target.classList).indexOf('lf-menu-item') > -1) {
  118. // 如果点击区域在菜单项内
  119. target.onclickCallback(_this.__currentData);
  120. // 点击后隐藏menu
  121. _this.__menuDOM.style.display = 'none';
  122. _this.__currentData = null;
  123. }
  124. else {
  125. // 如果点击区域不在菜单项内
  126. console.warn('点击区域不在菜单项内,请检查代码!');
  127. }
  128. }, true);
  129. // 通过事件控制菜单的显示和隐藏
  130. this.lf.on('node:contextmenu', function (_a) {
  131. var data = _a.data, position = _a.position;
  132. var _b = position.domOverlayPosition, x = _b.x, y = _b.y;
  133. var id = data.id;
  134. var model = _this.lf.graphModel.getNodeModelById(id);
  135. var menuList = [];
  136. var typeMenus = _this.menuTypeMap.get(model.type);
  137. // 如果单个节点自定义了节点,以单个节点自定义为准
  138. if (model && model.menu && Array.isArray(model.menu)) {
  139. menuList = model.menu;
  140. }
  141. else if (typeMenus) { // 如果定义当前节点类型的元素
  142. menuList = typeMenus;
  143. }
  144. else { // 最后取全局默认
  145. menuList = _this.menuTypeMap.get(DefaultNodeMenuKey);
  146. }
  147. _this.__currentData = data;
  148. _this.showMenu(x, y, menuList);
  149. });
  150. this.lf.on('edge:contextmenu', function (_a) {
  151. var data = _a.data, position = _a.position;
  152. var _b = position.domOverlayPosition, x = _b.x, y = _b.y;
  153. var id = data.id;
  154. var model = _this.lf.graphModel.getEdgeModelById(id);
  155. var menuList = [];
  156. var typeMenus = _this.menuTypeMap.get(model.type);
  157. // 如果单个节点自定义了边
  158. if (model && model.menu && Array.isArray(model.menu)) {
  159. menuList = model.menu;
  160. }
  161. else if (typeMenus) { // 如果定义当前边类型的元素
  162. menuList = typeMenus;
  163. }
  164. else { // 最后取全局默认
  165. menuList = _this.menuTypeMap.get(DefaultEdgeMenuKey);
  166. }
  167. _this.__currentData = data;
  168. _this.showMenu(x, y, menuList);
  169. });
  170. this.lf.on('blank:contextmenu', function (_a) {
  171. var position = _a.position;
  172. var menuList = _this.menuTypeMap.get(DefaultGraphMenuKey);
  173. var _b = position.domOverlayPosition, x = _b.x, y = _b.y;
  174. _this.showMenu(x, y, menuList);
  175. });
  176. this.lf.on('selection:contextmenu', function (_a) {
  177. var data = _a.data, position = _a.position;
  178. var menuList = _this.menuTypeMap.get(DefaultSelectionMenuKey);
  179. var _b = position.domOverlayPosition, x = _b.x, y = _b.y;
  180. _this.__currentData = data;
  181. _this.showMenu(x, y, menuList);
  182. });
  183. this.lf.on('node:mousedown', function () {
  184. _this.__menuDOM.style.display = 'none';
  185. });
  186. this.lf.on('edge:click', function () {
  187. _this.__menuDOM.style.display = 'none';
  188. });
  189. this.lf.on('blank:click', function () {
  190. _this.__menuDOM.style.display = 'none';
  191. });
  192. };
  193. Menu.prototype.destroy = function () {
  194. var _a;
  195. (_a = this === null || this === void 0 ? void 0 : this.__container) === null || _a === void 0 ? void 0 : _a.removeChild(this.__menuDOM);
  196. this.__menuDOM = null;
  197. };
  198. Menu.prototype.showMenu = function (x, y, menuList) {
  199. if (!menuList || !menuList.length)
  200. return;
  201. var menu = this.__menuDOM;
  202. // 菜单容器不变,需要先清空内部的菜单项
  203. menu.innerHTML = '';
  204. menu.append.apply(menu, __spread(this.__getMenuDom(menuList)));
  205. // 菜单中没有项,不显示
  206. if (!menu.children.length)
  207. return;
  208. menu.style.display = 'block';
  209. menu.style.top = y + "px";
  210. menu.style.left = x + "px";
  211. };
  212. /**
  213. * 设置指定类型元素的菜单
  214. */
  215. Menu.prototype.setMenuByType = function (config) {
  216. if (!config.type || !config.menu) {
  217. return;
  218. }
  219. this.menuTypeMap.set(config.type, config.menu);
  220. };
  221. /**
  222. * 获取 Menu DOM
  223. * @param list 菜单项
  224. * @return 菜单项 DOM
  225. */
  226. Menu.prototype.__getMenuDom = function (list) {
  227. var menuList = [];
  228. list && list.length > 0 && list.forEach(function (item) {
  229. var element = document.createElement('li');
  230. if (item.className) {
  231. element.className = "lf-menu-item " + item.className;
  232. }
  233. else {
  234. element.className = 'lf-menu-item';
  235. }
  236. if (item.icon === true) {
  237. var icon = document.createElement('span');
  238. icon.className = 'lf-menu-item-icon';
  239. element.appendChild(icon);
  240. }
  241. var text = document.createElement('span');
  242. text.className = 'lf-menu-item-text';
  243. if (item.text) {
  244. text.innerText = item.text;
  245. }
  246. element.appendChild(text);
  247. element.onclickCallback = item.callback;
  248. menuList.push(element);
  249. });
  250. return menuList;
  251. };
  252. // 复写菜单
  253. Menu.prototype.setMenuConfig = function (config) {
  254. if (!config) {
  255. return;
  256. }
  257. // node
  258. config.nodeMenu !== undefined
  259. && this.menuTypeMap.set(DefaultNodeMenuKey, config.nodeMenu ? config.nodeMenu : []);
  260. // edge
  261. config.edgeMenu !== undefined
  262. && this.menuTypeMap.set(DefaultEdgeMenuKey, config.edgeMenu ? config.edgeMenu : []);
  263. // graph
  264. config.graphMenu !== undefined
  265. && this.menuTypeMap.set(DefaultGraphMenuKey, config.graphMenu ? config.graphMenu : []);
  266. };
  267. // 在默认菜单后面追加菜单项
  268. Menu.prototype.addMenuConfig = function (config) {
  269. if (!config) {
  270. return;
  271. }
  272. // 追加项时,只支持数组类型,对false不做操作
  273. if (Array.isArray(config.nodeMenu)) {
  274. var menuList = this.menuTypeMap.get(DefaultNodeMenuKey);
  275. this.menuTypeMap.set(DefaultNodeMenuKey, menuList.concat(config.nodeMenu));
  276. }
  277. if (Array.isArray(config.edgeMenu)) {
  278. var menuList = this.menuTypeMap.get(DefaultEdgeMenuKey);
  279. this.menuTypeMap.set(DefaultEdgeMenuKey, menuList.concat(config.edgeMenu));
  280. }
  281. if (Array.isArray(config.graphMenu)) {
  282. var menuList = this.menuTypeMap.get(DefaultGraphMenuKey);
  283. this.menuTypeMap.set(DefaultGraphMenuKey, menuList.concat(config.graphMenu));
  284. }
  285. };
  286. /**
  287. * @deprecated
  288. * 复写添加
  289. */
  290. Menu.prototype.changeMenuItem = function (type, config) {
  291. if (type === 'add')
  292. this.addMenuConfig(config);
  293. else if (type === 'reset')
  294. this.setMenuConfig(config);
  295. else {
  296. throw new Error('The first parameter of changeMenuConfig should be \'add\' or \'reset\'');
  297. }
  298. };
  299. Menu.pluginName = 'menu';
  300. return Menu;
  301. }());
  302. exports.Menu = Menu;
  303. exports.default = Menu;