Diff
Modified: trunk/Source/WebInspectorUI/ChangeLog (215356 => 215357)
--- trunk/Source/WebInspectorUI/ChangeLog 2017-04-14 04:46:56 UTC (rev 215356)
+++ trunk/Source/WebInspectorUI/ChangeLog 2017-04-14 04:47:19 UTC (rev 215357)
@@ -1,3 +1,62 @@
+2017-04-13 Ross Kirsling <ross.kirsl...@sony.com>
+
+ Web Inspector: No context menu available via ENABLE_INSPECTOR_SERVER
+ https://bugs.webkit.org/show_bug.cgi?id=170705
+
+ Reviewed by Joseph Pecoraro.
+
+ Reintroduce old SoftContextMenu class (removed in r157278) and apply various fixes:
+ - Remove legacy globals and prototype extensions.
+ - Align JS/CSS style with current front-end code.
+ - Update UI and fix UX to replicate the macOS native context menu.
+
+ * Scripts/copy-user-interface-resources.pl:
+ Add copyright line for Sony Interactive Entertainment.
+
+ * UserInterface/Base/InspectorFrontendHostStub.js:
+ (WebInspector.InspectorFrontendHostStub.prototype.showContextMenu):
+ Use SoftContextMenu.
+
+ * UserInterface/Main.html:
+ Include SoftContextMenu.
+
+ * UserInterface/Views/SoftContextMenu.css: Added.
+ (.soft-context-menu-glass-pane):
+ (.soft-context-menu):
+ (.soft-context-menu > .item):
+ (.soft-context-menu > .item.disabled):
+ (.soft-context-menu > .item.highlighted):
+ (.soft-context-menu > .item > .checkmark):
+ (.soft-context-menu > .item > .label):
+ (.soft-context-menu > .item > .submenu-arrow):
+ (.soft-context-menu > .separator):
+ (.soft-context-menu > .separator > .line):
+
+ * UserInterface/Views/SoftContextMenu.js: Added.
+ (WebInspector.SoftContextMenu):
+ (WebInspector.SoftContextMenu.prototype.show):
+ (WebInspector.SoftContextMenu.prototype._consumeEvent):
+ (WebInspector.SoftContextMenu.prototype._parentGlassPaneElement):
+ (WebInspector.SoftContextMenu.prototype._createMenuItem):
+ (WebInspector.SoftContextMenu.prototype._createSeparator):
+ (WebInspector.SoftContextMenu.prototype._repositionMenuOnScreen):
+ (WebInspector.SoftContextMenu.prototype._showSubMenu):
+ (WebInspector.SoftContextMenu.prototype._hideSubMenu):
+ (WebInspector.SoftContextMenu.prototype._menuItemContextMenu):
+ (WebInspector.SoftContextMenu.prototype._menuItemMouseDown):
+ (WebInspector.SoftContextMenu.prototype._menuItemMouseUp):
+ (WebInspector.SoftContextMenu.prototype._menuItemMouseOver):
+ (WebInspector.SoftContextMenu.prototype._menuItemMouseOut):
+ (WebInspector.SoftContextMenu.prototype._menuKeyDown):
+ (WebInspector.SoftContextMenu.prototype._glassPaneMouseDown):
+ (WebInspector.SoftContextMenu.prototype._focus):
+ (WebInspector.SoftContextMenu.prototype._triggerAction):
+ (WebInspector.SoftContextMenu.prototype._highlightMenuItem):
+ (WebInspector.SoftContextMenu.prototype._highlightPrevious):
+ (WebInspector.SoftContextMenu.prototype._highlightNext):
+ (WebInspector.SoftContextMenu.prototype._discardMenu):
+ (WebInspector.SoftContextMenu.prototype._discardSubMenus):
+
2017-04-13 Brian Burg <bb...@apple.com>
Web Inspector: RTL: goto arrow is floated to the wrong side
Modified: trunk/Source/WebInspectorUI/Scripts/copy-user-interface-resources.pl (215356 => 215357)
--- trunk/Source/WebInspectorUI/Scripts/copy-user-interface-resources.pl 2017-04-14 04:46:56 UTC (rev 215356)
+++ trunk/Source/WebInspectorUI/Scripts/copy-user-interface-resources.pl 2017-04-14 04:47:19 UTC (rev 215357)
@@ -107,6 +107,7 @@
* Copyright (C) 2014 Antoine Quint
* Copyright (C) 2015 Tobias Reiss <tobi+web...@basecode.de>
* Copyright (C) 2015-2016 Devin Rousso <dcrousso+web...@gmail.com>. All rights reserved.
+ * Copyright (C) 2017 Sony Interactive Entertainment Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
Modified: trunk/Source/WebInspectorUI/UserInterface/Base/InspectorFrontendHostStub.js (215356 => 215357)
--- trunk/Source/WebInspectorUI/UserInterface/Base/InspectorFrontendHostStub.js 2017-04-14 04:46:56 UTC (rev 215356)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/InspectorFrontendHostStub.js 2017-04-14 04:47:19 UTC (rev 215357)
@@ -164,6 +164,7 @@
showContextMenu: function(event, menuObject)
{
+ new WebInspector.SoftContextMenu(menuObject).show(event);
},
unbufferedLog: function()
Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (215356 => 215357)
--- trunk/Source/WebInspectorUI/UserInterface/Main.html 2017-04-14 04:46:56 UTC (rev 215356)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html 2017-04-14 04:47:19 UTC (rev 215357)
@@ -157,6 +157,7 @@
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
+ <link rel="stylesheet" href=""
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
@@ -659,6 +660,7 @@
<script src=""
<script src=""
<script src=""
+ <script src=""
<script src=""
<script src=""
<script src=""
Added: trunk/Source/WebInspectorUI/UserInterface/Views/SoftContextMenu.css (0 => 215357)
--- trunk/Source/WebInspectorUI/UserInterface/Views/SoftContextMenu.css (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SoftContextMenu.css 2017-04-14 04:47:19 UTC (rev 215357)
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2011 Google Inc. All Rights Reserved.
+ * Copyright (C) 2017 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.soft-context-menu-glass-pane {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ z-index: 20000;
+}
+
+.soft-context-menu {
+ position: absolute;
+ border: 1px solid hsla(0, 0%, 77%, 0.9);
+ border-top: 1px solid hsla(0, 0%, 77%, 0.5);
+ border-bottom: 1px solid hsla(0, 0%, 59%, 0.9);
+ padding: 4px 0;
+ border-radius: 6px;
+ background-color: hsl(0, 0%, 94%);
+ box-shadow: 0 5px 10px hsla(0, 0%, 0%, 0.25);
+ color: hsl(0, 0%, 24%);
+ outline: none;
+}
+
+.soft-context-menu > .item {
+ display: flex;
+ align-items: center;
+ line-height: 13px;
+ font-size: 14px;
+ padding: 2px 12px 4px 5px;
+ white-space: nowrap;
+}
+
+.soft-context-menu > .item.disabled {
+ color: hsl(0, 0%, 72%);
+ pointer-events: none;
+}
+
+.soft-context-menu > .item.highlighted {
+ background-color: hsl(215, 95%, 64%);
+ color: hsl(0, 0%, 100%);
+}
+
+.soft-context-menu > .item > .checkmark {
+ width: 16px;
+ pointer-events: none;
+}
+
+.soft-context-menu > .item > .label {
+ flex: 1;
+ padding-right: 8px;
+ pointer-events: none;
+}
+
+.soft-context-menu > .item > .submenu-arrow {
+ width: 39px;
+ line-height: 12px;
+ font-size: 11px;
+ text-align: right;
+ pointer-events: none;
+}
+
+.soft-context-menu > .separator {
+ height: 12px;
+}
+
+.soft-context-menu > .separator > .line {
+ padding-bottom: 5px;
+ border-bottom: 2px solid hsl(0, 0%, 87%);
+ pointer-events: none;
+}
Added: trunk/Source/WebInspectorUI/UserInterface/Views/SoftContextMenu.js (0 => 215357)
--- trunk/Source/WebInspectorUI/UserInterface/Views/SoftContextMenu.js (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SoftContextMenu.js 2017-04-14 04:47:19 UTC (rev 215357)
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2011 Google Inc. All Rights Reserved.
+ * Copyright (C) 2017 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SoftContextMenu = class SoftContextMenu
+{
+ constructor(items, parentMenu)
+ {
+ this._items = items;
+ this._parentMenu = parentMenu;
+ }
+
+ // Public
+
+ show(event)
+ {
+ const isSubMenu = !!this._parentMenu;
+
+ this._contextMenuElement = document.createElement("div");
+ this._contextMenuElement.className = "soft-context-menu";
+ this._contextMenuElement.style.left = event.pageX + "px";
+ this._contextMenuElement.style.top = event.pageY + "px";
+ this._contextMenuElement.tabIndex = 0;
+ this._contextMenuElement.addEventListener("keydown", this._menuKeyDown.bind(this), false);
+ for (let item of this._items)
+ this._contextMenuElement.appendChild(this._createMenuItem(item));
+
+ // Install glass pane capturing events.
+ if (!isSubMenu) {
+ this._glassPaneElement = document.createElement("div");
+ this._glassPaneElement.className = "soft-context-menu-glass-pane";
+ this._glassPaneElement.addEventListener("mousedown", this._glassPaneMouseDown.bind(this), false);
+ this._glassPaneElement.appendChild(this._contextMenuElement);
+ document.body.appendChild(this._glassPaneElement);
+ this._focus();
+ this._consumeEvent(event, true);
+ } else
+ this._parentGlassPaneElement().appendChild(this._contextMenuElement);
+
+ this._repositionMenuOnScreen(isSubMenu);
+ }
+
+ // Private
+
+ _consumeEvent(event, preventDefault)
+ {
+ event.stopImmediatePropagation();
+
+ if (preventDefault)
+ event.preventDefault();
+
+ event.handled = true;
+ }
+
+ _parentGlassPaneElement()
+ {
+ if (!this._parentMenu)
+ return null;
+
+ if (this._parentMenu._glassPaneElement)
+ return this._parentMenu._glassPaneElement;
+
+ return this._parentMenu._parentGlassPaneElement();
+ }
+
+ _createMenuItem(item)
+ {
+ if (item.type === "separator")
+ return this._createSeparator();
+
+ const checkmark = "\u2713";
+ const blackRightPointingTriangle = "\u25b6";
+
+ const menuItemElement = document.createElement("div");
+ menuItemElement.className = "item";
+ if (!item.enabled)
+ menuItemElement.classList.add("disabled");
+
+ const checkMarkElement = document.createElement("span");
+ checkMarkElement.textContent = item.checked ? checkmark : "";
+ checkMarkElement.className = "checkmark";
+ menuItemElement.appendChild(checkMarkElement);
+
+ const labelElement = document.createElement("span");
+ labelElement.textContent = item.label;
+ labelElement.className = "label";
+ menuItemElement.appendChild(labelElement);
+
+ if (item.type === "subMenu") {
+ const subMenuArrowElement = document.createElement("span");
+ subMenuArrowElement.textContent = blackRightPointingTriangle;
+ subMenuArrowElement.className = "submenu-arrow";
+ menuItemElement.appendChild(subMenuArrowElement);
+
+ menuItemElement._subItems = item.subItems;
+ } else
+ menuItemElement._actionId = item.id;
+
+ menuItemElement.addEventListener("contextmenu", this._menuItemContextMenu.bind(this), false);
+ menuItemElement.addEventListener("mousedown", this._menuItemMouseDown.bind(this), false);
+ menuItemElement.addEventListener("mouseup", this._menuItemMouseUp.bind(this), false);
+ menuItemElement.addEventListener("mouseover", this._menuItemMouseOver.bind(this), false);
+ menuItemElement.addEventListener("mouseout", this._menuItemMouseOut.bind(this), false);
+
+ return menuItemElement;
+ }
+
+ _createSeparator()
+ {
+ const separatorElement = document.createElement("div");
+ separatorElement.className = "separator";
+ separatorElement._isSeparator = true;
+ separatorElement.createChild("div", "line");
+
+ separatorElement.addEventListener("contextmenu", this._menuItemContextMenu.bind(this), false);
+ separatorElement.addEventListener("mousedown", this._menuItemMouseDown.bind(this), false);
+ separatorElement.addEventListener("mouseup", this._menuItemMouseUp.bind(this), false);
+ separatorElement.addEventListener("mouseover", this._menuItemMouseOver.bind(this), false);
+
+ return separatorElement;
+ }
+
+ _repositionMenuOnScreen(isSubMenu)
+ {
+ if (this._contextMenuElement.offsetLeft + this._contextMenuElement.offsetWidth > document.body.offsetWidth) {
+ if (isSubMenu) {
+ const parentContextMenuElement = this._parentMenu._contextMenuElement;
+ const leftOfParent = parentContextMenuElement.offsetLeft - this._contextMenuElement.offsetWidth + 2;
+ const fromParentRight = this._contextMenuElement.offsetLeft - this._contextMenuElement.offsetWidth + 2;
+ this._contextMenuElement.style.left = (leftOfParent >= 0 ? leftOfParent : fromParentRight) + "px";
+ } else {
+ const leftOfCursor = this._contextMenuElement.offsetLeft - this._contextMenuElement.offsetWidth;
+ const fromRightEdge = document.body.offsetWidth - this._contextMenuElement.offsetWidth;
+ this._contextMenuElement.style.left = (leftOfCursor >= 0 ? leftOfCursor : fromRightEdge) + "px";
+ }
+ }
+
+ if (this._contextMenuElement.offsetTop + this._contextMenuElement.offsetHeight > document.body.offsetHeight) {
+ const aboveCursor = this._contextMenuElement.offsetTop - this._contextMenuElement.offsetHeight;
+ const fromBottomEdge = document.body.offsetHeight - this._contextMenuElement.offsetHeight;
+ this._contextMenuElement.style.top = (!isSubMenu && aboveCursor >= 0 ? aboveCursor : fromBottomEdge) + "px";
+ }
+ }
+
+ _showSubMenu(menuItemElement)
+ {
+ if (menuItemElement._subMenuTimer) {
+ clearTimeout(menuItemElement._subMenuTimer);
+ menuItemElement._subMenuTimer = 0;
+ }
+
+ if (this._subMenu)
+ return;
+
+ this._subMenu = new WebInspector.SoftContextMenu(menuItemElement._subItems, this);
+ this._subMenu.show({
+ pageX: this._contextMenuElement.offsetLeft + menuItemElement.offsetWidth,
+ pageY: this._contextMenuElement.offsetTop + menuItemElement.offsetTop - 4
+ });
+ }
+
+ _hideSubMenu()
+ {
+ if (!this._subMenu)
+ return;
+
+ this._subMenu._discardSubMenus();
+ this._focus();
+ }
+
+ _menuItemContextMenu(event)
+ {
+ // Prevent our non-native context menu from getting a native context menu on right-click.
+ this._consumeEvent(event, true);
+ }
+
+ _menuItemMouseDown(event)
+ {
+ // Prevent menu from disappearing before mouseup.
+ this._consumeEvent(event, true);
+ }
+
+ _menuItemMouseUp(event)
+ {
+ this._triggerAction(event.target, event);
+ this._consumeEvent(event);
+ }
+
+ _menuItemMouseOver(event)
+ {
+ this._highlightMenuItem(event.target._isSeparator ? null : event.target);
+ }
+
+ _menuItemMouseOut(event)
+ {
+ const shouldUnhighlight = !this._subMenu || !event.relatedTarget ||
+ this._contextMenuElement.isSelfOrAncestor(event.relatedTarget) ||
+ event.relatedTarget.classList.contains("soft-context-menu-glass-pane");
+
+ if (shouldUnhighlight)
+ this._highlightMenuItem(null);
+ }
+
+ _menuKeyDown(event)
+ {
+ switch (event.keyIdentifier) {
+ case "Up":
+ this._highlightPrevious();
+ break;
+ case "Down":
+ this._highlightNext();
+ break;
+ case "Left":
+ if (this._parentMenu) {
+ this._highlightMenuItem(null);
+ this._parentMenu._hideSubMenu();
+ }
+ break;
+ case "Enter":
+ if (!isEnterKey(event))
+ break;
+ // falls through
+ case "U+0020": // Space
+ if (this._highlightedMenuItemElement && !this._highlightedMenuItemElement._subItems)
+ this._triggerAction(this._highlightedMenuItemElement, event);
+ // falls through
+ case "Right":
+ if (this._highlightedMenuItemElement && this._highlightedMenuItemElement._subItems) {
+ this._showSubMenu(this._highlightedMenuItemElement);
+ this._subMenu._focus();
+ this._subMenu._highlightNext();
+ }
+ break;
+ case "U+001B": // Escape
+ this._discardMenu(true, event);
+ break;
+ }
+ this._consumeEvent(event, true);
+ }
+
+ _glassPaneMouseDown(event)
+ {
+ this._discardMenu(true, event);
+ this._consumeEvent(event);
+ }
+
+ _focus()
+ {
+ this._contextMenuElement.focus();
+ }
+
+ _triggerAction(menuItemElement, event)
+ {
+ if (!menuItemElement._subItems) {
+ this._discardMenu(true, event);
+ if (typeof menuItemElement._actionId === "number") {
+ WebInspector.ContextMenu.contextMenuItemSelected(menuItemElement._actionId);
+ menuItemElement._actionId = null;
+ }
+ return;
+ }
+
+ this._showSubMenu(menuItemElement);
+ this._consumeEvent(event);
+ }
+
+ _highlightMenuItem(menuItemElement, skipSubMenuExpansion)
+ {
+ if (this._highlightedMenuItemElement === menuItemElement)
+ return;
+
+ this._hideSubMenu();
+ if (this._highlightedMenuItemElement) {
+ this._highlightedMenuItemElement.classList.remove("highlighted");
+
+ if (this._highlightedMenuItemElement._subItems && this._highlightedMenuItemElement._subMenuTimer) {
+ clearTimeout(this._highlightedMenuItemElement._subMenuTimer);
+ this._highlightedMenuItemElement._subMenuTimer = 0;
+ }
+ }
+
+ this._highlightedMenuItemElement = menuItemElement;
+ if (this._highlightedMenuItemElement) {
+ this._highlightedMenuItemElement.classList.add("highlighted");
+ this._contextMenuElement.focus();
+
+ if (!skipSubMenuExpansion && this._highlightedMenuItemElement._subItems && !this._highlightedMenuItemElement._subMenuTimer)
+ this._highlightedMenuItemElement._subMenuTimer = setTimeout(this._showSubMenu.bind(this, this._highlightedMenuItemElement), 150);
+ }
+ }
+
+ _highlightPrevious()
+ {
+ let menuItemElement = this._highlightedMenuItemElement ? this._highlightedMenuItemElement.previousSibling : this._contextMenuElement.lastChild;
+
+ while (menuItemElement && menuItemElement._isSeparator)
+ menuItemElement = menuItemElement.previousSibling;
+
+ if (menuItemElement)
+ this._highlightMenuItem(menuItemElement, true);
+ }
+
+ _highlightNext()
+ {
+ let menuItemElement = this._highlightedMenuItemElement ? this._highlightedMenuItemElement.nextSibling : this._contextMenuElement.firstChild;
+
+ while (menuItemElement && menuItemElement._isSeparator)
+ menuItemElement = menuItemElement.nextSibling;
+
+ if (menuItemElement)
+ this._highlightMenuItem(menuItemElement, true);
+ }
+
+ _discardMenu(closeParentMenus, event)
+ {
+ if (this._subMenu && !closeParentMenus)
+ return;
+
+ if (this._glassPaneElement) {
+ const glassPane = this._glassPaneElement;
+ this._glassPaneElement = null;
+ // This can re-enter discardMenu due to blur.
+ document.body.removeChild(glassPane);
+
+ if (this._parentMenu) {
+ this._parentMenu._subMenu = null;
+ if (closeParentMenus)
+ this._parentMenu._discardMenu(closeParentMenus, event);
+ }
+
+ if (event)
+ this._consumeEvent(event, true);
+ } else if (this._parentMenu && this._contextMenuElement.parentElement) {
+ this._discardSubMenus();
+
+ if (closeParentMenus)
+ this._parentMenu._discardMenu(closeParentMenus, event);
+
+ if (event)
+ this._consumeEvent(event, true);
+ }
+ }
+
+ _discardSubMenus()
+ {
+ if (this._subMenu)
+ this._subMenu._discardSubMenus();
+
+ if (this._contextMenuElement.parentElement)
+ this._contextMenuElement.parentElement.removeChild(this._contextMenuElement);
+
+ if (this._parentMenu)
+ this._parentMenu._subMenu = null;
+ }
+};