mixin.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _xeUtils = _interopRequireDefault(require("xe-utils"));
  7. var _ui = require("../../../ui");
  8. var _dom = require("../../../ui/src/dom");
  9. var _utils = require("../../../ui/src/utils");
  10. var _log = require("../../../ui/src/log");
  11. function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
  12. const {
  13. menus,
  14. globalEvents,
  15. GLOBAL_EVENT_KEYS
  16. } = _ui.VxeUI;
  17. var _default = exports.default = {
  18. methods: {
  19. /**
  20. * 关闭快捷菜单
  21. */
  22. _closeMenu() {
  23. const $xeTable = this;
  24. const reactData = $xeTable;
  25. Object.assign(reactData.ctxMenuStore, {
  26. visible: false,
  27. selected: null,
  28. selectChild: null,
  29. showChild: false
  30. });
  31. return $xeTable.$nextTick();
  32. },
  33. // 处理菜单的移动
  34. moveCtxMenu(evnt, ctxMenuStore, property, hasOper, operRest, menuList) {
  35. const $xeTable = this;
  36. let selectItem;
  37. const selectIndex = _xeUtils.default.findIndexOf(menuList, item => ctxMenuStore[property] === item);
  38. if (hasOper) {
  39. if (operRest && (0, _utils.hasChildrenList)(ctxMenuStore.selected)) {
  40. ctxMenuStore.showChild = true;
  41. } else {
  42. ctxMenuStore.showChild = false;
  43. ctxMenuStore.selectChild = null;
  44. }
  45. } else if (globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ARROW_UP)) {
  46. for (let len = selectIndex - 1; len >= 0; len--) {
  47. if (menuList[len].visible !== false) {
  48. selectItem = menuList[len];
  49. break;
  50. }
  51. }
  52. ctxMenuStore[property] = selectItem || menuList[menuList.length - 1];
  53. } else if (globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ARROW_DOWN)) {
  54. for (let index = selectIndex + 1; index < menuList.length; index++) {
  55. if (menuList[index].visible !== false) {
  56. selectItem = menuList[index];
  57. break;
  58. }
  59. }
  60. ctxMenuStore[property] = selectItem || menuList[0];
  61. } else if (ctxMenuStore[property] && (globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ENTER) || globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.SPACEBAR))) {
  62. $xeTable.ctxMenuLinkEvent(evnt, ctxMenuStore[property]);
  63. }
  64. },
  65. /**
  66. * 快捷菜单事件处理
  67. */
  68. handleGlobalContextmenuEvent(evnt) {
  69. const $xeTable = this;
  70. const $xeGrid = $xeTable.$xeGrid;
  71. const $xeGantt = $xeTable.$xeGantt;
  72. const props = $xeTable;
  73. const reactData = $xeTable;
  74. const internalData = $xeTable;
  75. const {
  76. xID
  77. } = $xeTable;
  78. const {
  79. mouseConfig,
  80. menuConfig
  81. } = props;
  82. const {
  83. editStore,
  84. ctxMenuStore
  85. } = reactData;
  86. const {
  87. visibleColumn
  88. } = internalData;
  89. const tableFilter = $xeTable.$refs.refTableFilter;
  90. const tableMenu = $xeTable.$refs.refTableMenu;
  91. const mouseOpts = $xeTable.computeMouseOpts;
  92. const menuOpts = $xeTable.computeMenuOpts;
  93. const el = $xeTable.$refs.refElem;
  94. const {
  95. selected
  96. } = editStore;
  97. const layoutList = ['header', 'body', 'footer'];
  98. if ((0, _utils.isEnableConf)(menuConfig)) {
  99. if (ctxMenuStore.visible && tableMenu && (0, _dom.getEventTargetNode)(evnt, tableMenu.$el).flag) {
  100. evnt.preventDefault();
  101. return;
  102. }
  103. if (internalData._keyCtx) {
  104. const type = 'body';
  105. const params = {
  106. source: 'table',
  107. type,
  108. $table: $xeTable,
  109. $grid: $xeGrid,
  110. $gantt: $xeGantt,
  111. keyboard: true,
  112. columns: visibleColumn.slice(0),
  113. $event: evnt
  114. };
  115. // 如果开启单元格区域
  116. if (mouseConfig && mouseOpts.area) {
  117. const activeArea = $xeTable.getActiveCellArea();
  118. if (activeArea && activeArea.row && activeArea.column) {
  119. params.row = activeArea.row;
  120. params.column = activeArea.column;
  121. $xeTable.handleOpenMenuEvent(evnt, type, params);
  122. return;
  123. }
  124. } else if (mouseConfig && mouseOpts.selected) {
  125. // 如果启用键盘导航且已选中单元格
  126. if (selected.row && selected.column) {
  127. params.row = selected.row;
  128. params.column = selected.column;
  129. $xeTable.handleOpenMenuEvent(evnt, type, params);
  130. return;
  131. }
  132. }
  133. }
  134. // 分别匹配表尾、内容、表尾的快捷菜单
  135. for (let index = 0; index < layoutList.length; index++) {
  136. const layout = layoutList[index];
  137. const columnTargetNode = (0, _dom.getEventTargetNode)(evnt, el, `vxe-${layout}--column`, target => {
  138. // target=td|th,直接向上找 table 去匹配即可
  139. return target.parentNode.parentNode.parentNode.getAttribute('xid') === xID;
  140. });
  141. const params = {
  142. source: 'table',
  143. type: layout,
  144. $table: $xeTable,
  145. $grid: $xeGrid,
  146. $gantt: $xeGantt,
  147. columns: visibleColumn.slice(0),
  148. $event: evnt
  149. };
  150. if (columnTargetNode.flag) {
  151. const cell = columnTargetNode.targetElem;
  152. const columnNodeRest = $xeTable.getColumnNode(cell);
  153. const column = columnNodeRest ? columnNodeRest.item : null;
  154. let typePrefix = `${layout}-`;
  155. if (column) {
  156. Object.assign(params, {
  157. column,
  158. columnIndex: $xeTable.getColumnIndex(column),
  159. cell
  160. });
  161. }
  162. if (layout === 'body') {
  163. const rowNodeRest = $xeTable.getRowNode(cell.parentNode);
  164. const row = rowNodeRest ? rowNodeRest.item : null;
  165. typePrefix = '';
  166. if (row) {
  167. params.row = row;
  168. params.rowIndex = $xeTable.getRowIndex(row);
  169. }
  170. }
  171. const eventType = `${typePrefix}cell-menu`;
  172. $xeTable.handleOpenMenuEvent(evnt, layout, params);
  173. // 在 v4 中废弃事件 cell-context-menu、header-cell-context-menu、footer-cell-context-menu
  174. if ($xeTable.$listeners[`${typePrefix}cell-context-menu`]) {
  175. (0, _log.warnLog)('vxe.error.delEvent', [`${typePrefix}cell-context-menu`, `${typePrefix}cell-menu`]);
  176. $xeTable.dispatchEvent(`${typePrefix}cell-context-menu`, params, evnt);
  177. } else {
  178. $xeTable.dispatchEvent(eventType, params, evnt);
  179. }
  180. return;
  181. } else if ((0, _dom.getEventTargetNode)(evnt, $xeTable.$el, `vxe-table--${layout}-wrapper`, target => target.getAttribute('xid') === xID).flag) {
  182. if (menuOpts.trigger === 'cell') {
  183. evnt.preventDefault();
  184. } else {
  185. $xeTable.handleOpenMenuEvent(evnt, layout, params);
  186. }
  187. return;
  188. }
  189. }
  190. }
  191. if (tableFilter && !(0, _dom.getEventTargetNode)(evnt, tableFilter.$el).flag) {
  192. $xeTable.closeFilter();
  193. }
  194. $xeTable.closeMenu();
  195. },
  196. /**
  197. * 显示快捷菜单
  198. */
  199. handleOpenMenuEvent(evnt, type, params) {
  200. const $xeTable = this;
  201. const reactData = $xeTable;
  202. const internalData = $xeTable;
  203. const {
  204. ctxMenuStore
  205. } = reactData;
  206. const isContentMenu = $xeTable.computeIsContentMenu;
  207. const menuOpts = $xeTable.computeMenuOpts;
  208. const config = menuOpts[type];
  209. const {
  210. transfer,
  211. visibleMethod
  212. } = menuOpts;
  213. if (config) {
  214. const {
  215. options,
  216. disabled
  217. } = config;
  218. if (disabled) {
  219. evnt.preventDefault();
  220. } else if (isContentMenu && options && options.length) {
  221. params.options = options;
  222. $xeTable.preventEvent(evnt, 'event.showMenu', params, () => {
  223. if (!visibleMethod || visibleMethod(params)) {
  224. evnt.preventDefault();
  225. $xeTable.updateZindex();
  226. const el = $xeTable.$refs.refElem;
  227. const tableRect = el.getBoundingClientRect();
  228. const {
  229. scrollTop,
  230. scrollLeft,
  231. visibleHeight,
  232. visibleWidth
  233. } = (0, _dom.getDomNode)();
  234. let top = evnt.clientY - tableRect.y;
  235. let left = evnt.clientX - tableRect.x;
  236. if (transfer) {
  237. top = evnt.clientY + scrollTop;
  238. left = evnt.clientX + scrollLeft;
  239. }
  240. const handleVisible = () => {
  241. internalData._currMenuParams = params;
  242. Object.assign(ctxMenuStore, {
  243. visible: true,
  244. list: options,
  245. selected: null,
  246. selectChild: null,
  247. showChild: false,
  248. style: {
  249. zIndex: internalData.tZindex,
  250. top: `${top}px`,
  251. left: `${left}px`
  252. }
  253. });
  254. $xeTable.$nextTick(() => {
  255. const tableMenu = $xeTable.$refs.refTableMenu;
  256. const ctxElem = tableMenu.$el;
  257. const clientHeight = ctxElem.clientHeight;
  258. const clientWidth = ctxElem.clientWidth;
  259. const {
  260. boundingTop,
  261. boundingLeft
  262. } = (0, _dom.getAbsolutePos)(ctxElem);
  263. const offsetTop = boundingTop + clientHeight - visibleHeight;
  264. const offsetLeft = boundingLeft + clientWidth - visibleWidth;
  265. if (offsetTop > -10) {
  266. ctxMenuStore.style.top = `${Math.max(scrollTop + 2, top - clientHeight - 2)}px`;
  267. }
  268. if (offsetLeft > -10) {
  269. ctxMenuStore.style.left = `${Math.max(scrollLeft + 2, left - clientWidth - 2)}px`;
  270. }
  271. });
  272. };
  273. const {
  274. keyboard,
  275. row,
  276. column
  277. } = params;
  278. if (keyboard && row && column) {
  279. $xeTable.scrollToRow(row, column).then(() => {
  280. const cell = $xeTable.getCellElement(row, column);
  281. if (cell) {
  282. const {
  283. boundingTop,
  284. boundingLeft
  285. } = (0, _dom.getAbsolutePos)(cell);
  286. top = boundingTop + scrollTop + Math.floor(cell.offsetHeight / 2);
  287. left = boundingLeft + scrollLeft + Math.floor(cell.offsetWidth / 2);
  288. }
  289. handleVisible();
  290. });
  291. } else {
  292. handleVisible();
  293. }
  294. } else {
  295. $xeTable.closeMenu();
  296. }
  297. });
  298. }
  299. }
  300. $xeTable.closeFilter();
  301. },
  302. ctxMenuMouseoverEvent(evnt, item, child) {
  303. const $xeTable = this;
  304. const reactData = $xeTable;
  305. const menuElem = evnt.currentTarget;
  306. const {
  307. ctxMenuStore
  308. } = reactData;
  309. evnt.preventDefault();
  310. evnt.stopPropagation();
  311. ctxMenuStore.selected = item;
  312. ctxMenuStore.selectChild = child;
  313. if (!child) {
  314. ctxMenuStore.showChild = (0, _utils.hasChildrenList)(item);
  315. if (ctxMenuStore.showChild) {
  316. $xeTable.$nextTick(() => {
  317. const childWrapperElem = menuElem.nextElementSibling;
  318. if (childWrapperElem) {
  319. const {
  320. boundingTop,
  321. boundingLeft,
  322. visibleHeight,
  323. visibleWidth
  324. } = (0, _dom.getAbsolutePos)(menuElem);
  325. const posTop = boundingTop + menuElem.offsetHeight;
  326. const posLeft = boundingLeft + menuElem.offsetWidth;
  327. let left = '';
  328. let right = '';
  329. // 是否超出右侧
  330. if (posLeft + childWrapperElem.offsetWidth > visibleWidth - 10) {
  331. left = 'auto';
  332. right = `${menuElem.offsetWidth}px`;
  333. }
  334. // 是否超出底部
  335. let top = '';
  336. let bottom = '';
  337. if (posTop + childWrapperElem.offsetHeight > visibleHeight - 10) {
  338. top = 'auto';
  339. bottom = '0';
  340. }
  341. childWrapperElem.style.left = left;
  342. childWrapperElem.style.right = right;
  343. childWrapperElem.style.top = top;
  344. childWrapperElem.style.bottom = bottom;
  345. }
  346. });
  347. }
  348. }
  349. },
  350. ctxMenuMouseoutEvent(evnt, item) {
  351. const $xeTable = this;
  352. const reactData = $xeTable;
  353. const {
  354. ctxMenuStore
  355. } = reactData;
  356. if (!item.children) {
  357. ctxMenuStore.selected = null;
  358. }
  359. ctxMenuStore.selectChild = null;
  360. },
  361. /**
  362. * 快捷菜单点击事件
  363. */
  364. ctxMenuLinkEvent(evnt, menu) {
  365. const $xeTable = this;
  366. const $xeGrid = $xeTable.$xeGrid;
  367. const $xeGantt = $xeTable.$xeGantt;
  368. const internalData = $xeTable;
  369. // 如果一级菜单有配置 code 则允许点击,否则不能点击
  370. if (!menu.disabled && (menu.code || !menu.children || !menu.children.length)) {
  371. const gMenuOpts = menus.get(menu.code);
  372. const params = Object.assign({}, internalData._currMenuParams, {
  373. menu,
  374. $table: $xeTable,
  375. $grid: $xeGrid,
  376. $gantt: $xeGantt,
  377. $event: evnt
  378. });
  379. if (gMenuOpts && gMenuOpts.menuMethod) {
  380. gMenuOpts.menuMethod(params, evnt);
  381. }
  382. // 在 v4 中废弃事件 context-menu-click
  383. if ($xeTable.$listeners['context-menu-click']) {
  384. (0, _log.warnLog)('vxe.error.delEvent', ['context-menu-click', 'menu-click']);
  385. $xeTable.dispatchEvent('context-menu-click', params, evnt);
  386. } else {
  387. $xeTable.dispatchEvent('menu-click', params, evnt);
  388. }
  389. $xeTable.closeMenu();
  390. }
  391. }
  392. }
  393. };