ui.context_menu.js 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  1. /**
  2. * DevExtreme (ui/context_menu/ui.context_menu.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. function _typeof(obj) {
  11. "@babel/helpers - typeof";
  12. return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(obj) {
  13. return typeof obj
  14. } : function(obj) {
  15. return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj
  16. }, _typeof(obj)
  17. }
  18. var _renderer = require("../../core/renderer");
  19. var _renderer2 = _interopRequireDefault(_renderer);
  20. var _dom_adapter = require("../../core/dom_adapter");
  21. var _dom_adapter2 = _interopRequireDefault(_dom_adapter);
  22. var _events_engine = require("../../events/core/events_engine");
  23. var _events_engine2 = _interopRequireDefault(_events_engine);
  24. var _guid = require("../../core/guid");
  25. var _guid2 = _interopRequireDefault(_guid);
  26. var _component_registrator = require("../../core/component_registrator");
  27. var _component_registrator2 = _interopRequireDefault(_component_registrator);
  28. var _common = require("../../core/utils/common");
  29. var _type = require("../../core/utils/type");
  30. var _dom = require("../../core/utils/dom");
  31. var _iterator = require("../../core/utils/iterator");
  32. var _array = require("../../core/utils/array");
  33. var _extend = require("../../core/utils/extend");
  34. var _window = require("../../core/utils/window");
  35. var _fx = require("../../animation/fx");
  36. var _fx2 = _interopRequireDefault(_fx);
  37. var _position = require("../../animation/position");
  38. var _devices = require("../../core/devices");
  39. var _devices2 = _interopRequireDefault(_devices);
  40. var _utils = require("../../events/utils");
  41. var _overlay = require("../overlay");
  42. var _overlay2 = _interopRequireDefault(_overlay);
  43. var _ui = require("./ui.menu_base");
  44. var _ui2 = _interopRequireDefault(_ui);
  45. var _deferred = require("../../core/utils/deferred");
  46. function _interopRequireDefault(obj) {
  47. return obj && obj.__esModule ? obj : {
  48. "default": obj
  49. }
  50. }
  51. function _classCallCheck(instance, Constructor) {
  52. if (!(instance instanceof Constructor)) {
  53. throw new TypeError("Cannot call a class as a function")
  54. }
  55. }
  56. function _defineProperties(target, props) {
  57. for (var i = 0; i < props.length; i++) {
  58. var descriptor = props[i];
  59. descriptor.enumerable = descriptor.enumerable || false;
  60. descriptor.configurable = true;
  61. if ("value" in descriptor) {
  62. descriptor.writable = true
  63. }
  64. Object.defineProperty(target, descriptor.key, descriptor)
  65. }
  66. }
  67. function _createClass(Constructor, protoProps, staticProps) {
  68. if (protoProps) {
  69. _defineProperties(Constructor.prototype, protoProps)
  70. }
  71. if (staticProps) {
  72. _defineProperties(Constructor, staticProps)
  73. }
  74. Object.defineProperty(Constructor, "prototype", {
  75. writable: false
  76. });
  77. return Constructor
  78. }
  79. function _get() {
  80. if ("undefined" !== typeof Reflect && Reflect.get) {
  81. _get = Reflect.get.bind()
  82. } else {
  83. _get = function(target, property, receiver) {
  84. var base = _superPropBase(target, property);
  85. if (!base) {
  86. return
  87. }
  88. var desc = Object.getOwnPropertyDescriptor(base, property);
  89. if (desc.get) {
  90. return desc.get.call(arguments.length < 3 ? target : receiver)
  91. }
  92. return desc.value
  93. }
  94. }
  95. return _get.apply(this, arguments)
  96. }
  97. function _superPropBase(object, property) {
  98. while (!Object.prototype.hasOwnProperty.call(object, property)) {
  99. object = _getPrototypeOf(object);
  100. if (null === object) {
  101. break
  102. }
  103. }
  104. return object
  105. }
  106. function _inherits(subClass, superClass) {
  107. if ("function" !== typeof superClass && null !== superClass) {
  108. throw new TypeError("Super expression must either be null or a function")
  109. }
  110. subClass.prototype = Object.create(superClass && superClass.prototype, {
  111. constructor: {
  112. value: subClass,
  113. writable: true,
  114. configurable: true
  115. }
  116. });
  117. Object.defineProperty(subClass, "prototype", {
  118. writable: false
  119. });
  120. if (superClass) {
  121. _setPrototypeOf(subClass, superClass)
  122. }
  123. }
  124. function _setPrototypeOf(o, p) {
  125. _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function(o, p) {
  126. o.__proto__ = p;
  127. return o
  128. };
  129. return _setPrototypeOf(o, p)
  130. }
  131. function _createSuper(Derived) {
  132. var hasNativeReflectConstruct = _isNativeReflectConstruct();
  133. return function() {
  134. var result, Super = _getPrototypeOf(Derived);
  135. if (hasNativeReflectConstruct) {
  136. var NewTarget = _getPrototypeOf(this).constructor;
  137. result = Reflect.construct(Super, arguments, NewTarget)
  138. } else {
  139. result = Super.apply(this, arguments)
  140. }
  141. return _possibleConstructorReturn(this, result)
  142. }
  143. }
  144. function _possibleConstructorReturn(self, call) {
  145. if (call && ("object" === _typeof(call) || "function" === typeof call)) {
  146. return call
  147. } else {
  148. if (void 0 !== call) {
  149. throw new TypeError("Derived constructors may only return object or undefined")
  150. }
  151. }
  152. return _assertThisInitialized(self)
  153. }
  154. function _assertThisInitialized(self) {
  155. if (void 0 === self) {
  156. throw new ReferenceError("this hasn't been initialised - super() hasn't been called")
  157. }
  158. return self
  159. }
  160. function _isNativeReflectConstruct() {
  161. if ("undefined" === typeof Reflect || !Reflect.construct) {
  162. return false
  163. }
  164. if (Reflect.construct.sham) {
  165. return false
  166. }
  167. if ("function" === typeof Proxy) {
  168. return true
  169. }
  170. try {
  171. Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
  172. return true
  173. } catch (e) {
  174. return false
  175. }
  176. }
  177. function _getPrototypeOf(o) {
  178. _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function(o) {
  179. return o.__proto__ || Object.getPrototypeOf(o)
  180. };
  181. return _getPrototypeOf(o)
  182. }
  183. var DX_MENU_CLASS = "dx-menu";
  184. var DX_MENU_ITEM_CLASS = DX_MENU_CLASS + "-item";
  185. var DX_MENU_ITEM_EXPANDED_CLASS = DX_MENU_ITEM_CLASS + "-expanded";
  186. var DX_MENU_PHONE_CLASS = "dx-menu-phone-overlay";
  187. var DX_MENU_ITEMS_CONTAINER_CLASS = DX_MENU_CLASS + "-items-container";
  188. var DX_MENU_ITEM_WRAPPER_CLASS = DX_MENU_ITEM_CLASS + "-wrapper";
  189. var DX_SUBMENU_CLASS = "dx-submenu";
  190. var DX_CONTEXT_MENU_CLASS = "dx-context-menu";
  191. var DX_HAS_CONTEXT_MENU_CLASS = "dx-has-context-menu";
  192. var DX_STATE_DISABLED_CLASS = "dx-state-disabled";
  193. var DX_STATE_FOCUSED_CLASS = "dx-state-focused";
  194. var DX_STATE_HOVER_CLASS = "dx-state-hover";
  195. var FOCUS_UP = "up";
  196. var FOCUS_DOWN = "down";
  197. var FOCUS_LEFT = "left";
  198. var FOCUS_RIGHT = "right";
  199. var FOCUS_FIRST = "first";
  200. var FOCUS_LAST = "last";
  201. var ACTIONS = ["onShowing", "onShown", "onSubmenuCreated", "onHiding", "onHidden", "onPositioning", "onLeftFirstItem", "onLeftLastItem", "onCloseRootSubmenu", "onExpandLastSubmenu"];
  202. var LOCAL_SUBMENU_DIRECTIONS = [FOCUS_UP, FOCUS_DOWN, FOCUS_FIRST, FOCUS_LAST];
  203. var DEFAULT_SHOW_EVENT = "dxcontextmenu";
  204. var ContextMenu = function(_MenuBase) {
  205. _inherits(ContextMenu, _MenuBase);
  206. var _super = _createSuper(ContextMenu);
  207. function ContextMenu() {
  208. _classCallCheck(this, ContextMenu);
  209. return _super.apply(this, arguments)
  210. }
  211. _createClass(ContextMenu, [{
  212. key: "getShowEvent",
  213. value: function(showEventOption) {
  214. var result = null;
  215. if ((0, _type.isObject)(showEventOption)) {
  216. if (null !== showEventOption.name) {
  217. result = showEventOption.name || DEFAULT_SHOW_EVENT
  218. }
  219. } else {
  220. result = showEventOption
  221. }
  222. return result
  223. }
  224. }, {
  225. key: "getShowDelay",
  226. value: function(showEventOption) {
  227. return (0, _type.isObject)(showEventOption) && showEventOption.delay
  228. }
  229. }, {
  230. key: "_getDefaultOptions",
  231. value: function() {
  232. return (0, _extend.extend)(_get(_getPrototypeOf(ContextMenu.prototype), "_getDefaultOptions", this).call(this), {
  233. showEvent: DEFAULT_SHOW_EVENT,
  234. closeOnOutsideClick: true,
  235. position: {
  236. at: "top left",
  237. my: "top left"
  238. },
  239. onShowing: null,
  240. onShown: null,
  241. onSubmenuCreated: null,
  242. onHiding: null,
  243. onHidden: null,
  244. onPositioning: null,
  245. submenuDirection: "auto",
  246. visible: false,
  247. target: void 0,
  248. onLeftFirstItem: null,
  249. onLeftLastItem: null,
  250. onCloseRootSubmenu: null,
  251. onExpandLastSubmenu: null
  252. })
  253. }
  254. }, {
  255. key: "_defaultOptionsRules",
  256. value: function() {
  257. return _get(_getPrototypeOf(ContextMenu.prototype), "_defaultOptionsRules", this).call(this).concat([{
  258. device: function() {
  259. return !(0, _window.hasWindow)()
  260. },
  261. options: {
  262. animation: null
  263. }
  264. }])
  265. }
  266. }, {
  267. key: "_initActions",
  268. value: function() {
  269. var _this = this;
  270. this._actions = {};
  271. (0, _iterator.each)(ACTIONS, function(index, action) {
  272. _this._actions[action] = _this._createActionByOption(action) || _common.noop
  273. })
  274. }
  275. }, {
  276. key: "_setOptionsByReference",
  277. value: function() {
  278. _get(_getPrototypeOf(ContextMenu.prototype), "_setOptionsByReference", this).call(this);
  279. (0, _extend.extend)(this._optionsByReference, {
  280. animation: true,
  281. selectedItem: true
  282. })
  283. }
  284. }, {
  285. key: "_focusInHandler",
  286. value: function() {}
  287. }, {
  288. key: "_itemContainer",
  289. value: function() {
  290. return this._overlay ? this._overlay.$content() : (0, _renderer2.default)()
  291. }
  292. }, {
  293. key: "_eventBindingTarget",
  294. value: function() {
  295. return this._itemContainer()
  296. }
  297. }, {
  298. key: "itemsContainer",
  299. value: function() {
  300. return this._overlay ? this._overlay.$content() : void 0
  301. }
  302. }, {
  303. key: "_supportedKeys",
  304. value: function() {
  305. var _this2 = this;
  306. var selectItem = function() {
  307. var $item = (0, _renderer2.default)(_this2.option("focusedElement"));
  308. _this2.hide();
  309. if (!$item.length || !_this2._isSelectionEnabled()) {
  310. return
  311. }
  312. _this2.selectItem($item[0])
  313. };
  314. return (0, _extend.extend)(_get(_getPrototypeOf(ContextMenu.prototype), "_supportedKeys", this).call(this), {
  315. space: selectItem,
  316. esc: this.hide
  317. })
  318. }
  319. }, {
  320. key: "_getActiveItem",
  321. value: function() {
  322. var $availableItems = this._getAvailableItems();
  323. var $focusedItem = $availableItems.filter(".".concat(DX_STATE_FOCUSED_CLASS));
  324. var $hoveredItem = $availableItems.filter(".".concat(DX_STATE_HOVER_CLASS));
  325. var $hoveredItemContainer = $hoveredItem.closest(".".concat(DX_MENU_ITEMS_CONTAINER_CLASS));
  326. if ($hoveredItemContainer.find(".".concat(DX_MENU_ITEM_CLASS)).index($focusedItem) >= 0) {
  327. return $focusedItem
  328. }
  329. if ($hoveredItem.length) {
  330. return $hoveredItem
  331. }
  332. return _get(_getPrototypeOf(ContextMenu.prototype), "_getActiveItem", this).call(this)
  333. }
  334. }, {
  335. key: "_moveFocus",
  336. value: function(location) {
  337. var $items = this._getItemsByLocation(location);
  338. var $oldTarget = this._getActiveItem(true);
  339. var $hoveredItem = this.itemsContainer().find(".".concat(DX_STATE_HOVER_CLASS));
  340. var $focusedItem = (0, _renderer2.default)(this.option("focusedElement"));
  341. var $activeItemHighlighted = !!($focusedItem.length || $hoveredItem.length);
  342. var $newTarget;
  343. switch (location) {
  344. case FOCUS_UP:
  345. $newTarget = $activeItemHighlighted ? this._prevItem($items) : $oldTarget;
  346. if ($oldTarget.is($items.first())) {
  347. this._actions.onLeftFirstItem($oldTarget)
  348. }
  349. break;
  350. case FOCUS_DOWN:
  351. $newTarget = $activeItemHighlighted ? this._nextItem($items) : $oldTarget;
  352. if ($oldTarget.is($items.last())) {
  353. this._actions.onLeftLastItem($oldTarget)
  354. }
  355. break;
  356. case FOCUS_RIGHT:
  357. $newTarget = this.option("rtlEnabled") ? this._hideSubmenuHandler() : this._expandSubmenuHandler($items, location);
  358. break;
  359. case FOCUS_LEFT:
  360. $newTarget = this.option("rtlEnabled") ? this._expandSubmenuHandler($items, location) : this._hideSubmenuHandler();
  361. break;
  362. case FOCUS_FIRST:
  363. $newTarget = $items.first();
  364. break;
  365. case FOCUS_LAST:
  366. $newTarget = $items.last();
  367. break;
  368. default:
  369. return _get(_getPrototypeOf(ContextMenu.prototype), "_moveFocus", this).call(this, location)
  370. }
  371. if (0 !== $newTarget.length) {
  372. this.option("focusedElement", (0, _dom.getPublicElement)($newTarget))
  373. }
  374. }
  375. }, {
  376. key: "_getItemsByLocation",
  377. value: function(location) {
  378. var $activeItem = this._getActiveItem(true);
  379. var $items;
  380. if ((0, _array.inArray)(location, LOCAL_SUBMENU_DIRECTIONS) >= 0) {
  381. $items = $activeItem.closest(".".concat(DX_MENU_ITEMS_CONTAINER_CLASS)).children().children()
  382. }
  383. $items = this._getAvailableItems($items);
  384. return $items
  385. }
  386. }, {
  387. key: "_getAriaTarget",
  388. value: function() {
  389. return this.$element()
  390. }
  391. }, {
  392. key: "_refreshActiveDescendant",
  393. value: function() {
  394. if ((0, _type.isDefined)(this._overlay)) {
  395. var $target = this._overlay.$content();
  396. _get(_getPrototypeOf(ContextMenu.prototype), "_refreshActiveDescendant", this).call(this, $target)
  397. }
  398. }
  399. }, {
  400. key: "_hideSubmenuHandler",
  401. value: function() {
  402. var $curItem = this._getActiveItem(true);
  403. var $parentItem = $curItem.parents(".".concat(DX_MENU_ITEM_EXPANDED_CLASS)).first();
  404. if ($parentItem.length) {
  405. this._hideSubmenusOnSameLevel($parentItem);
  406. this._hideSubmenu($curItem.closest(".".concat(DX_SUBMENU_CLASS)));
  407. return $parentItem
  408. }
  409. this._actions.onCloseRootSubmenu($curItem);
  410. return $curItem
  411. }
  412. }, {
  413. key: "_expandSubmenuHandler",
  414. value: function($items, location) {
  415. var $curItem = this._getActiveItem(true);
  416. var itemData = this._getItemData($curItem);
  417. var node = this._dataAdapter.getNodeByItem(itemData);
  418. var isItemHasSubmenu = this._hasSubmenu(node);
  419. var $submenu = $curItem.children(".".concat(DX_SUBMENU_CLASS));
  420. if (isItemHasSubmenu && !$curItem.hasClass(DX_STATE_DISABLED_CLASS)) {
  421. if (!$submenu.length || "hidden" === $submenu.css("visibility")) {
  422. this._showSubmenu($curItem)
  423. }
  424. return this._nextItem(this._getItemsByLocation(location))
  425. }
  426. this._actions.onExpandLastSubmenu($curItem);
  427. return $curItem
  428. }
  429. }, {
  430. key: "_clean",
  431. value: function() {
  432. if (this._overlay) {
  433. this._overlay.$element().remove();
  434. this._overlay = null
  435. }
  436. this._detachShowContextMenuEvents(this._getTarget());
  437. _get(_getPrototypeOf(ContextMenu.prototype), "_clean", this).call(this)
  438. }
  439. }, {
  440. key: "_initMarkup",
  441. value: function() {
  442. this.$element().addClass(DX_HAS_CONTEXT_MENU_CLASS);
  443. _get(_getPrototypeOf(ContextMenu.prototype), "_initMarkup", this).call(this)
  444. }
  445. }, {
  446. key: "_render",
  447. value: function() {
  448. _get(_getPrototypeOf(ContextMenu.prototype), "_render", this).call(this);
  449. this._renderVisibility(this.option("visible"));
  450. this._addWidgetClass()
  451. }
  452. }, {
  453. key: "_renderContentImpl",
  454. value: function() {
  455. this._detachShowContextMenuEvents(this._getTarget());
  456. this._attachShowContextMenuEvents()
  457. }
  458. }, {
  459. key: "_attachKeyboardEvents",
  460. value: function() {
  461. !this._keyboardProcessor && this._focusTarget().length && _get(_getPrototypeOf(ContextMenu.prototype), "_attachKeyboardEvents", this).call(this)
  462. }
  463. }, {
  464. key: "_renderContextMenuOverlay",
  465. value: function() {
  466. if (this._overlay) {
  467. return
  468. }
  469. var overlayOptions = this._getOverlayOptions();
  470. this._overlay = this._createComponent((0, _renderer2.default)("<div>").appendTo(this._$element), _overlay2.default, overlayOptions);
  471. var $overlayContent = this._overlay.$content();
  472. $overlayContent.addClass(DX_CONTEXT_MENU_CLASS);
  473. this._addCustomCssClass($overlayContent);
  474. this._addPlatformDependentClass($overlayContent);
  475. this._attachContextMenuEvent()
  476. }
  477. }, {
  478. key: "_itemContextMenuHandler",
  479. value: function(e) {
  480. _get(_getPrototypeOf(ContextMenu.prototype), "_itemContextMenuHandler", this).call(this, e);
  481. e.stopPropagation()
  482. }
  483. }, {
  484. key: "_addPlatformDependentClass",
  485. value: function($element) {
  486. if (_devices2.default.current().phone) {
  487. $element.addClass(DX_MENU_PHONE_CLASS)
  488. }
  489. }
  490. }, {
  491. key: "_detachShowContextMenuEvents",
  492. value: function(target) {
  493. var showEvent = this.getShowEvent(this.option("showEvent"));
  494. if (!showEvent) {
  495. return
  496. }
  497. var eventName = (0, _utils.addNamespace)(showEvent, this.NAME);
  498. if (this._showContextMenuEventHandler) {
  499. _events_engine2.default.off(_dom_adapter2.default.getDocument(), eventName, target, this._showContextMenuEventHandler)
  500. } else {
  501. _events_engine2.default.off((0, _renderer2.default)(target), eventName)
  502. }
  503. }
  504. }, {
  505. key: "_attachShowContextMenuEvents",
  506. value: function() {
  507. var _this3 = this;
  508. var target = this._getTarget();
  509. var showEvent = this.getShowEvent(this.option("showEvent"));
  510. if (!showEvent) {
  511. return
  512. }
  513. var eventName = (0, _utils.addNamespace)(showEvent, this.NAME);
  514. var contextMenuAction = this._createAction(function(e) {
  515. var delay = _this3.getShowDelay(_this3.option("showEvent"));
  516. if (delay) {
  517. setTimeout(function() {
  518. return _this3._show(e.event)
  519. }, delay)
  520. } else {
  521. _this3._show(e.event)
  522. }
  523. }, {
  524. validatingTargetName: "target"
  525. });
  526. var handler = function(e) {
  527. return contextMenuAction({
  528. event: e,
  529. target: (0, _renderer2.default)(e.currentTarget)
  530. })
  531. };
  532. contextMenuAction = this._createAction(contextMenuAction);
  533. if ((0, _type.isRenderer)(target) || target.nodeType || (0, _type.isWindow)(target)) {
  534. this._showContextMenuEventHandler = void 0;
  535. _events_engine2.default.on(target, eventName, handler)
  536. } else {
  537. this._showContextMenuEventHandler = handler;
  538. _events_engine2.default.on(_dom_adapter2.default.getDocument(), eventName, target, this._showContextMenuEventHandler)
  539. }
  540. }
  541. }, {
  542. key: "_hoverEndHandler",
  543. value: function(e) {
  544. _get(_getPrototypeOf(ContextMenu.prototype), "_hoverEndHandler", this).call(this, e);
  545. e.stopPropagation()
  546. }
  547. }, {
  548. key: "_renderDimensions",
  549. value: function() {}
  550. }, {
  551. key: "_renderContainer",
  552. value: function($wrapper, submenuContainer) {
  553. var $holder = submenuContainer || this._itemContainer();
  554. $wrapper = (0, _renderer2.default)("<div>");
  555. $wrapper.appendTo($holder).addClass(DX_SUBMENU_CLASS).css("visibility", submenuContainer ? "hidden" : "visible");
  556. var $itemsContainer = _get(_getPrototypeOf(ContextMenu.prototype), "_renderContainer", this).call(this, $wrapper);
  557. if (submenuContainer) {
  558. return $itemsContainer
  559. }
  560. if (this.option("width")) {
  561. return $itemsContainer.css("minWidth", this.option("width"))
  562. }
  563. if (this.option("height")) {
  564. return $itemsContainer.css("minHeight", this.option("height"))
  565. }
  566. return $itemsContainer
  567. }
  568. }, {
  569. key: "_renderSubmenuItems",
  570. value: function(node, $itemFrame) {
  571. this._renderItems(this._getChildNodes(node), $itemFrame);
  572. this._actions.onSubmenuCreated({
  573. itemElement: (0, _dom.getPublicElement)($itemFrame),
  574. itemData: node.internalFields.item,
  575. submenuElement: (0, _dom.getPublicElement)($itemFrame.children(".".concat(DX_SUBMENU_CLASS)))
  576. })
  577. }
  578. }, {
  579. key: "_getOverlayOptions",
  580. value: function() {
  581. var position = this.option("position");
  582. var overlayOptions = {
  583. focusStateEnabled: this.option("focusStateEnabled"),
  584. animation: this.option("animation"),
  585. innerOverlay: true,
  586. closeOnOutsideClick: this._closeOnOutsideClickHandler.bind(this),
  587. propagateOutsideClick: true,
  588. closeOnTargetScroll: true,
  589. deferRendering: false,
  590. position: {
  591. at: position.at,
  592. my: position.my,
  593. of: this._getTarget(),
  594. collision: "flipfit"
  595. },
  596. shading: false,
  597. showTitle: false,
  598. height: "auto",
  599. width: "auto",
  600. onShown: this._overlayShownActionHandler.bind(this),
  601. onHiding: this._overlayHidingActionHandler.bind(this),
  602. onHidden: this._overlayHiddenActionHandler.bind(this)
  603. };
  604. return overlayOptions
  605. }
  606. }, {
  607. key: "_overlayShownActionHandler",
  608. value: function(arg) {
  609. this._actions.onShown(arg)
  610. }
  611. }, {
  612. key: "_overlayHidingActionHandler",
  613. value: function(arg) {
  614. this._actions.onHiding(arg);
  615. if (!arg.cancel) {
  616. this._hideAllShownSubmenus();
  617. this._setOptionSilent("visible", false)
  618. }
  619. }
  620. }, {
  621. key: "_overlayHiddenActionHandler",
  622. value: function(arg) {
  623. this._actions.onHidden(arg)
  624. }
  625. }, {
  626. key: "_closeOnOutsideClickHandler",
  627. value: function(e) {
  628. var closeOnOutsideClick = this.option("closeOnOutsideClick");
  629. if ((0, _type.isFunction)(closeOnOutsideClick)) {
  630. return closeOnOutsideClick(e)
  631. }
  632. if (!closeOnOutsideClick) {
  633. return false
  634. }
  635. if (_dom_adapter2.default.isDocument(e.target)) {
  636. return true
  637. }
  638. var $activeItemContainer = this._getActiveItemsContainer(e.target);
  639. var $itemContainers = this._getItemsContainers();
  640. var $clickedItem = this._searchActiveItem(e.target);
  641. var $rootItem = this.$element().parents(".".concat(DX_MENU_ITEM_CLASS));
  642. var isRootItemClicked = $clickedItem[0] === $rootItem[0] && $clickedItem.length && $rootItem.length;
  643. var isInnerOverlayClicked = this._isIncludeOverlay($activeItemContainer, $itemContainers) && $clickedItem.length;
  644. if (isInnerOverlayClicked || isRootItemClicked) {
  645. if ("onClick" === this._getShowSubmenuMode()) {
  646. this._hideAllShownChildSubmenus($clickedItem)
  647. }
  648. return false
  649. }
  650. return true
  651. }
  652. }, {
  653. key: "_getActiveItemsContainer",
  654. value: function(target) {
  655. return (0, _renderer2.default)(target).closest(".".concat(DX_MENU_ITEMS_CONTAINER_CLASS))
  656. }
  657. }, {
  658. key: "_getItemsContainers",
  659. value: function() {
  660. return this._overlay._$content.find(".".concat(DX_MENU_ITEMS_CONTAINER_CLASS))
  661. }
  662. }, {
  663. key: "_searchActiveItem",
  664. value: function(target) {
  665. return (0, _renderer2.default)(target).closest(".".concat(DX_MENU_ITEM_CLASS)).eq(0)
  666. }
  667. }, {
  668. key: "_isIncludeOverlay",
  669. value: function($activeOverlay, $allOverlays) {
  670. var isSame = false;
  671. (0, _iterator.each)($allOverlays, function(index, $overlay) {
  672. if ($activeOverlay.is($overlay) && !isSame) {
  673. isSame = true
  674. }
  675. });
  676. return isSame
  677. }
  678. }, {
  679. key: "_hideAllShownChildSubmenus",
  680. value: function($clickedItem) {
  681. var _this4 = this;
  682. var $submenuElements = $clickedItem.find(".".concat(DX_SUBMENU_CLASS));
  683. var shownSubmenus = (0, _extend.extend)([], this._shownSubmenus);
  684. if ($submenuElements.length > 0) {
  685. (0, _iterator.each)(shownSubmenus, function(index, $submenu) {
  686. var $context = _this4._searchActiveItem($submenu.context).parent();
  687. if ($context.parent().is($clickedItem.parent().parent()) && !$context.is($clickedItem.parent())) {
  688. _this4._hideSubmenu($submenu)
  689. }
  690. })
  691. }
  692. }
  693. }, {
  694. key: "_showSubmenu",
  695. value: function($item) {
  696. var node = this._dataAdapter.getNodeByItem(this._getItemData($item));
  697. this._hideSubmenusOnSameLevel($item);
  698. if (!this._hasSubmenu(node)) {
  699. return
  700. }
  701. var $submenu = $item.children(".".concat(DX_SUBMENU_CLASS));
  702. var isSubmenuRendered = $submenu.length;
  703. _get(_getPrototypeOf(ContextMenu.prototype), "_showSubmenu", this).call(this, $item);
  704. if (!isSubmenuRendered) {
  705. this._renderSubmenuItems(node, $item)
  706. }
  707. if (!this._isSubmenuVisible($submenu)) {
  708. this._drawSubmenu($item)
  709. }
  710. }
  711. }, {
  712. key: "_hideSubmenusOnSameLevel",
  713. value: function($item) {
  714. var $expandedItems = $item.parent(".".concat(DX_MENU_ITEM_WRAPPER_CLASS)).siblings().find(".".concat(DX_MENU_ITEM_EXPANDED_CLASS));
  715. if ($expandedItems.length) {
  716. $expandedItems.removeClass(DX_MENU_ITEM_EXPANDED_CLASS);
  717. this._hideSubmenu($expandedItems.find(".".concat(DX_SUBMENU_CLASS)))
  718. }
  719. }
  720. }, {
  721. key: "_hideSubmenuGroup",
  722. value: function($submenu) {
  723. if (this._isSubmenuVisible($submenu)) {
  724. this._hideSubmenuCore($submenu)
  725. }
  726. }
  727. }, {
  728. key: "_isSubmenuVisible",
  729. value: function($submenu) {
  730. return "visible" === $submenu.css("visibility")
  731. }
  732. }, {
  733. key: "_drawSubmenu",
  734. value: function($itemElement) {
  735. var animation = this.option("animation") ? this.option("animation").show : {};
  736. var $submenu = $itemElement.children(".".concat(DX_SUBMENU_CLASS));
  737. var submenuPosition = this._getSubmenuPosition($itemElement);
  738. if (this._overlay && this._overlay.option("visible")) {
  739. if (!(0, _type.isDefined)(this._shownSubmenus)) {
  740. this._shownSubmenus = []
  741. }
  742. if ((0, _array.inArray)($submenu, this._shownSubmenus)) {
  743. this._shownSubmenus.push($submenu)
  744. }
  745. if (animation) {
  746. _fx2.default.stop($submenu)
  747. }(0, _position.setup)($submenu, submenuPosition);
  748. if (animation) {
  749. if ((0, _type.isPlainObject)(animation.to)) {
  750. animation.to.position = submenuPosition
  751. }
  752. this._animate($submenu, animation)
  753. }
  754. $submenu.css("visibility", "visible")
  755. }
  756. }
  757. }, {
  758. key: "_animate",
  759. value: function($container, options) {
  760. _fx2.default.animate($container, options)
  761. }
  762. }, {
  763. key: "_getSubmenuPosition",
  764. value: function($rootItem) {
  765. var submenuDirection = this.option("submenuDirection").toLowerCase();
  766. var $rootItemWrapper = $rootItem.parent(".".concat(DX_MENU_ITEM_WRAPPER_CLASS));
  767. var position = {
  768. collision: "flip",
  769. of: $rootItemWrapper,
  770. offset: {
  771. h: 0,
  772. v: -1
  773. }
  774. };
  775. switch (submenuDirection) {
  776. case "left":
  777. position.at = "left top";
  778. position.my = "right top";
  779. break;
  780. case "right":
  781. position.at = "right top";
  782. position.my = "left top";
  783. break;
  784. default:
  785. if (this.option("rtlEnabled")) {
  786. position.at = "left top";
  787. position.my = "right top"
  788. } else {
  789. position.at = "right top";
  790. position.my = "left top"
  791. }
  792. }
  793. return position
  794. }
  795. }, {
  796. key: "_updateSubmenuVisibilityOnClick",
  797. value: function(actionArgs) {
  798. if (!actionArgs.args.length) {
  799. return
  800. }
  801. var itemData = actionArgs.args[0].itemData;
  802. var node = this._dataAdapter.getNodeByItem(itemData);
  803. if (!node) {
  804. return
  805. }
  806. var $itemElement = (0, _renderer2.default)(actionArgs.args[0].itemElement);
  807. var $submenu = $itemElement.find(".".concat(DX_SUBMENU_CLASS));
  808. var shouldRenderSubmenu = this._hasSubmenu(node) && !$submenu.length;
  809. if (shouldRenderSubmenu) {
  810. this._renderSubmenuItems(node, $itemElement);
  811. $submenu = $itemElement.find(".".concat(DX_SUBMENU_CLASS))
  812. }
  813. if ($itemElement.context === $submenu.context && "visible" === $submenu.css("visibility")) {
  814. return
  815. }
  816. var notCloseMenuOnItemClick = itemData && false === itemData.closeMenuOnClick;
  817. if (!itemData || itemData.disabled || notCloseMenuOnItemClick) {
  818. return
  819. }
  820. this._updateSelectedItemOnClick(actionArgs);
  821. if (0 === $submenu.length) {
  822. var $prevSubmenu = (0, _renderer2.default)($itemElement.parents(".".concat(DX_SUBMENU_CLASS))[0]);
  823. this._hideSubmenu($prevSubmenu);
  824. if (!actionArgs.canceled && this._overlay && this._overlay.option("visible")) {
  825. this.option("visible", false)
  826. }
  827. } else {
  828. if (this._shownSubmenus && this._shownSubmenus.length > 0) {
  829. if (this._shownSubmenus[0].is($submenu)) {
  830. this._hideSubmenu($submenu)
  831. }
  832. }
  833. this._showSubmenu($itemElement)
  834. }
  835. }
  836. }, {
  837. key: "_hideSubmenu",
  838. value: function($curSubmenu) {
  839. var _this5 = this;
  840. var shownSubmenus = (0, _extend.extend)([], this._shownSubmenus);
  841. (0, _iterator.each)(shownSubmenus, function(index, $submenu) {
  842. if ($curSubmenu.is($submenu) || (0, _dom.contains)($curSubmenu[0], $submenu[0])) {
  843. $submenu.parent().removeClass(DX_MENU_ITEM_EXPANDED_CLASS);
  844. _this5._hideSubmenuCore($submenu)
  845. }
  846. })
  847. }
  848. }, {
  849. key: "_hideSubmenuCore",
  850. value: function($submenu) {
  851. var index = (0, _array.inArray)($submenu, this._shownSubmenus);
  852. var animation = this.option("animation") ? this.option("animation").hide : null;
  853. if (index >= 0) {
  854. this._shownSubmenus.splice(index, 1)
  855. }
  856. this._stopAnimate($submenu);
  857. animation && this._animate($submenu, animation);
  858. $submenu.css("visibility", "hidden")
  859. }
  860. }, {
  861. key: "_stopAnimate",
  862. value: function($container) {
  863. _fx2.default.stop($container, true)
  864. }
  865. }, {
  866. key: "_hideAllShownSubmenus",
  867. value: function() {
  868. var _this6 = this;
  869. var shownSubmenus = (0, _extend.extend)([], this._shownSubmenus);
  870. var $expandedItems = this._overlay.$content().find(".".concat(DX_MENU_ITEM_EXPANDED_CLASS));
  871. $expandedItems.removeClass(DX_MENU_ITEM_EXPANDED_CLASS);
  872. (0, _iterator.each)(shownSubmenus, function(_, $submenu) {
  873. _this6._hideSubmenu($submenu)
  874. })
  875. }
  876. }, {
  877. key: "_visibilityChanged",
  878. value: function(visible) {
  879. if (visible) {
  880. this._renderContentImpl()
  881. }
  882. }
  883. }, {
  884. key: "_optionChanged",
  885. value: function(args) {
  886. if ((0, _array.inArray)(args.name, ACTIONS) > -1) {
  887. this._initActions();
  888. return
  889. }
  890. switch (args.name) {
  891. case "visible":
  892. this._renderVisibility(args.value);
  893. break;
  894. case "showEvent":
  895. case "position":
  896. case "submenuDirection":
  897. this._invalidate();
  898. break;
  899. case "target":
  900. args.previousValue && this._detachShowContextMenuEvents(args.previousValue);
  901. this._invalidate();
  902. break;
  903. case "closeOnOutsideClick":
  904. break;
  905. default:
  906. _get(_getPrototypeOf(ContextMenu.prototype), "_optionChanged", this).call(this, args)
  907. }
  908. }
  909. }, {
  910. key: "_renderVisibility",
  911. value: function(showing) {
  912. return showing ? this._show() : this._hide()
  913. }
  914. }, {
  915. key: "_toggleVisibility",
  916. value: function() {}
  917. }, {
  918. key: "_show",
  919. value: function(event) {
  920. var args = {
  921. jQEvent: event
  922. };
  923. var promise = (new _deferred.Deferred).reject().promise();
  924. this._actions.onShowing(args);
  925. if (args.cancel) {
  926. return promise
  927. }
  928. var position = this._positionContextMenu(event);
  929. if (position) {
  930. if (!this._overlay) {
  931. this._renderContextMenuOverlay();
  932. this._overlay.$content().addClass(this._widgetClass());
  933. this._renderFocusState();
  934. this._attachHoverEvents();
  935. this._attachClickEvent();
  936. this._renderItems(this._dataAdapter.getRootNodes())
  937. }
  938. this._setOptionSilent("visible", true);
  939. this._overlay.option("position", position);
  940. promise = this._overlay.show();
  941. event && event.stopPropagation();
  942. this._setAriaAttributes()
  943. }
  944. return promise
  945. }
  946. }, {
  947. key: "_setAriaAttributes",
  948. value: function() {
  949. this._overlayContentId = "dx-".concat(new _guid2.default);
  950. this.setAria("owns", this._overlayContentId);
  951. this.setAria({
  952. id: this._overlayContentId,
  953. role: "menu"
  954. }, this._overlay.$content())
  955. }
  956. }, {
  957. key: "_cleanAriaAttributes",
  958. value: function() {
  959. this._overlay && this.setAria("id", null, this._overlay.$content());
  960. this.setAria("owns", void 0)
  961. }
  962. }, {
  963. key: "_getTarget",
  964. value: function() {
  965. return this.option("target") || this.option("position").of || (0, _renderer2.default)(_dom_adapter2.default.getDocument())
  966. }
  967. }, {
  968. key: "_getContextMenuPosition",
  969. value: function() {
  970. return (0, _extend.extend)({}, this.option("position"), {
  971. of: this._getTarget()
  972. })
  973. }
  974. }, {
  975. key: "_positionContextMenu",
  976. value: function(jQEvent) {
  977. var position = this._getContextMenuPosition();
  978. var isInitialPosition = this._isInitialOptionValue("position");
  979. var positioningAction = this._createActionByOption("onPositioning", actionArgs);
  980. if (jQEvent && jQEvent.preventDefault && isInitialPosition) {
  981. position.of = jQEvent
  982. }
  983. var actionArgs = {
  984. position: position,
  985. event: jQEvent
  986. };
  987. positioningAction(actionArgs);
  988. if (actionArgs.cancel) {
  989. position = null
  990. } else {
  991. if (actionArgs.event) {
  992. actionArgs.event.cancel = true;
  993. jQEvent.preventDefault()
  994. }
  995. }
  996. return position
  997. }
  998. }, {
  999. key: "_refresh",
  1000. value: function() {
  1001. if (!(0, _window.hasWindow)()) {
  1002. _get(_getPrototypeOf(ContextMenu.prototype), "_refresh", this).call(this)
  1003. } else {
  1004. if (this._overlay) {
  1005. var lastPosition = this._overlay.option("position");
  1006. _get(_getPrototypeOf(ContextMenu.prototype), "_refresh", this).call(this);
  1007. this._overlay && this._overlay.option("position", lastPosition)
  1008. } else {
  1009. _get(_getPrototypeOf(ContextMenu.prototype), "_refresh", this).call(this)
  1010. }
  1011. }
  1012. }
  1013. }, {
  1014. key: "_hide",
  1015. value: function() {
  1016. var promise;
  1017. if (this._overlay) {
  1018. promise = this._overlay.hide();
  1019. this._setOptionSilent("visible", false)
  1020. }
  1021. this._cleanAriaAttributes();
  1022. this.option("focusedElement", null);
  1023. return promise || (new _deferred.Deferred).reject().promise()
  1024. }
  1025. }, {
  1026. key: "toggle",
  1027. value: function(showing) {
  1028. var visible = this.option("visible");
  1029. showing = void 0 === showing ? !visible : showing;
  1030. return this._renderVisibility(showing)
  1031. }
  1032. }, {
  1033. key: "show",
  1034. value: function() {
  1035. return this.toggle(true)
  1036. }
  1037. }, {
  1038. key: "hide",
  1039. value: function() {
  1040. return this.toggle(false)
  1041. }
  1042. }]);
  1043. return ContextMenu
  1044. }(_ui2.default);
  1045. (0, _component_registrator2.default)("dxContextMenu", ContextMenu);
  1046. module.exports = ContextMenu;