UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

219 lines (218 loc) • 8.56 kB
/** * DevExtreme (esm/__internal/ui/menu/submenu.js) * Version: 25.2.3 * Build date: Fri Dec 12 2025 * * Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import "../../../ui/context_menu"; import animationPosition from "../../../common/core/animation/position"; import { getPublicElement } from "../../../core/element"; import $ from "../../../core/renderer"; import { noop } from "../../../core/utils/common"; import { extend } from "../../../core/utils/extend"; import { getHeight, getWidth, setHeight, setWidth } from "../../../core/utils/size"; import ContextMenu from "../../ui/context_menu/context_menu"; const DX_CONTEXT_MENU_CONTENT_DELIMITER_CLASS = "dx-context-menu-content-delimiter"; const DX_SUBMENU_CLASS = "dx-submenu"; class Submenu extends ContextMenu { _getMaxUsableSpace(offsetTop, windowHeight, anchorHeight) { return Math.max(offsetTop, windowHeight - offsetTop - anchorHeight) } _getDefaultOptions() { return Object.assign({}, super._getDefaultOptions(), { orientation: "horizontal", tabIndex: null, onHoverStart: noop }) } _initDataAdapter() { const { _dataAdapter: _dataAdapter } = this.option(); this._dataAdapter = _dataAdapter; if (!this._dataAdapter) { super._initDataAdapter() } } _renderContentImpl() { this._renderContextMenuOverlay(); super._renderContentImpl(); const { _parentKey: _parentKey } = this.option(); const node = this._dataAdapter.getNodeByKey(_parentKey); if (node) { this._renderItems(this._getChildNodes(node)) } this._renderDelimiter() } _renderDelimiter() { this.$contentDelimiter = $("<div>").appendTo(this._itemContainer()).addClass("dx-context-menu-content-delimiter") } _getOverlayOptions() { return extend(true, super._getOverlayOptions(), { onPositioned: this._overlayPositionedActionHandler.bind(this), position: { precise: true } }) } _overlayPositionedActionHandler(arg) { this._showDelimiter(arg) } _hoverEndHandler(e) { super._hoverEndHandler(e); this._toggleFocusClass(false, e.currentTarget) } _isMenuHorizontal() { const { orientation: orientation } = this.option(); return "horizontal" === orientation } _hoverStartHandler(e) { const { onHoverStart: onHoverStart } = this.option(); null === onHoverStart || void 0 === onHoverStart || onHoverStart(e); super._hoverStartHandler(e) } _drawSubmenu($rootItem) { var _this$_actions$onShow, _this$_actions, _this$_actions$onShow2, _this$_actions2; null === (_this$_actions$onShow = (_this$_actions = this._actions).onShowing) || void 0 === _this$_actions$onShow || _this$_actions$onShow.call(_this$_actions, { rootItem: getPublicElement($rootItem), submenu: this }); super._drawSubmenu($rootItem); null === (_this$_actions$onShow2 = (_this$_actions2 = this._actions).onShown) || void 0 === _this$_actions$onShow2 || _this$_actions$onShow2.call(_this$_actions2, { rootItem: getPublicElement($rootItem), submenu: this }) } _hideSubmenu($rootItem) { var _this$_actions$onHidi, _this$_actions3, _this$_actions$onHidd, _this$_actions4; null === (_this$_actions$onHidi = (_this$_actions3 = this._actions).onHiding) || void 0 === _this$_actions$onHidi || _this$_actions$onHidi.call(_this$_actions3, { cancel: true, rootItem: getPublicElement($rootItem), submenu: this }); super._hideSubmenu($rootItem); null === (_this$_actions$onHidd = (_this$_actions4 = this._actions).onHidden) || void 0 === _this$_actions$onHidd || _this$_actions$onHidd.call(_this$_actions4, { rootItem: getPublicElement($rootItem), submenu: this }) } _getDelimiterWidth($rootItem, $submenu) { if (this._isMenuHorizontal()) { const rootWidth = getWidth($rootItem); const submenuWidth = getWidth($submenu); return rootWidth < submenuWidth ? rootWidth : submenuWidth } return 3 } _getDelimiterHeight($rootItem, $submenu) { if (this._isMenuHorizontal()) { return 3 } const rootHeight = getHeight($rootItem); const submenuHeight = getHeight($submenu); return rootHeight < submenuHeight ? rootHeight : submenuHeight } _showDelimiter(arg) { if (!this.$contentDelimiter) { return } const { position: positionOption } = this.option(); const $submenu = this._itemContainer().children(".dx-submenu").eq(0); const $rootItem = $(null === positionOption || void 0 === positionOption ? void 0 : positionOption.of).find(".dx-context-menu-container-border"); const position = { of: $submenu, precise: true }; const containerOffset = arg.position; const vLocation = containerOffset.v.location; const hLocation = containerOffset.h.location; const rootOffset = $rootItem.offset(); const offsetLeft = Math.round((null === rootOffset || void 0 === rootOffset ? void 0 : rootOffset.left) ?? 0); const offsetTop = Math.round((null === rootOffset || void 0 === rootOffset ? void 0 : rootOffset.top) ?? 0); this.$contentDelimiter.css("display", "block"); setWidth(this.$contentDelimiter, this._getDelimiterWidth($rootItem, $submenu)); setHeight(this.$contentDelimiter, this._getDelimiterHeight($rootItem, $submenu)); if (this._isMenuHorizontal()) { if (vLocation > offsetTop) { if (Math.round(hLocation) === offsetLeft) { position.offset = "0 -2.5"; position.at = "left top"; position.my = "left top" } else { position.offset = "0 -2.5"; position.at = "right top"; position.my = "right top" } } else { setHeight(this.$contentDelimiter, 5); if (Math.round(hLocation) === offsetLeft) { position.offset = "0 5"; position.at = "left bottom"; position.my = "left bottom" } else { position.offset = "0 5"; position.at = "right bottom"; position.my = "right bottom" } } } else if (hLocation > offsetLeft) { if (Math.round(vLocation) === offsetTop) { position.offset = "-2.5 0"; position.at = "left top"; position.my = "left top" } else { position.offset = "-2.5 0"; position.at = "left bottom"; position.my = "left bottom" } } else if (Math.round(vLocation) === offsetTop) { position.offset = "2.5 0"; position.at = "right top"; position.my = "right top" } else { position.offset = "2.5 0"; position.at = "right bottom"; position.my = "right bottom" } animationPosition.setup(this.$contentDelimiter, position) } _getContextMenuPosition() { const { position: position } = this.option(); return position } isOverlayVisible() { var _this$_overlay; const { visible: visible } = (null === (_this$_overlay = this._overlay) || void 0 === _this$_overlay ? void 0 : _this$_overlay.option()) ?? {}; return visible } getOverlayContent() { var _this$_overlay2; return null === (_this$_overlay2 = this._overlay) || void 0 === _this$_overlay2 ? void 0 : _this$_overlay2.$content() } } export default Submenu;