Интересно, какие события я должен слушать, чтобы скрыть свое настраиваемое контекстное меню, элемент <div>, отображаемый из обработчика событий oncontextmenu, как и в собственном.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Используйте событие oncontextmenu.
el.addEventListener('contextmenu', function(ev) {
ev.preventDefault();
// here what you wanna show for example the customised context menu
// myContextMenu();
return false;
}, false);
Не забудьте вернуть false, иначе стандартное контекстное меню все равно будет всплывать.
@mooga, спасибо, но как это решение может обрабатывать меню как родное (например, если вы нажмете где-нибудь на странице, меню может скрыться)
Есть несколько действий, закрывающих собственное контекстное меню:
Щелкните снаружи: Слушайте document.onmousedown и, чтобы предотвратить всплытие кликов по другим (действительным) элементам и закрытие контекстного меню, вы должны остановить его распространение в промежуточном обработчике с помощью Event.stopPropagation.
document.onclick также будет работать, но контекстное меню будет оставаться видимым до тех пор, пока вы не отпустите кнопку мыши, а не исчезнет при нажатии.
В сенсорных устройствах вы должны прослушивать document.touchstart, поскольку некоторые устройства, такие как iPad, не запускают события click.
Нажатие Esc: Прослушайте document.onkeydown и проверьте, является ли нажатая клавиша Esc, проверяя KeyboardEvent.keyCode, KeyboardEvent.which и KeyboardEvent.key.
Прокрутка мыши: В Chrome слушайте document.onmousewheel. Посмотрите здесь, чтобы получить подробный ответ о том, как обнаружить колесо мыши в разных браузерах: колесо мыши, колесо и DOMMouseScroll в JavaScript.
Когда это происходит, собственное контекстное меню закрывается, независимо от того, есть ли на странице прокрутка или нет, по крайней мере, в Chrome в Windows 10.
Вот простой пример с некоторыми из упомянутых мною опций:
const contextMenu = document.getElementById('contextMenu');
const MARGIN = 10;
document.oncontextmenu = (e) => {
e.preventDefault();
const target = e.target;
if (contextMenu === target || contextMenu.contains(target)) {
// A right-click on the context menu itself (or anything inside it) will NOT reposition it:
return;
}
contextMenu.style.left = `${ Math.min(window.innerWidth - contextMenu.offsetWidth - MARGIN, Math.max(MARGIN, e.clientX)) }px`;
contextMenu.style.top = `${ Math.min(window.innerHeight - contextMenu.offsetHeight - MARGIN, Math.max(MARGIN, e.clientY)) }px`;
contextMenu.classList.remove('hidden');
};
contextMenu.onmousedown = (e) => {
// We don't want this click to close the context menu, so we stop its propagation:
e.stopPropagation();
};
// EVENTS THAT CLOSE THE CONTEXT MENU:
window.onblur = () => {
contextMenu.classList.add('hidden');
};
document.onmousedown = () => {
contextMenu.classList.add('hidden');
};
document.onmousewheel = () => {
contextMenu.classList.add('hidden');
};
document.onkeydown = (e) => {
if (e.key === 'Escape' || e.which === 27 || e.keyCode === 27) {
contextMenu.classList.add('hidden');
}
};html,
body {
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
margin: 0;
font-family: monospace;
}
#contextMenu {
box-sizing: border-box;
padding: 5px;
width: 200px;
min-height: 50px;
max-height: calc(100vh - 20px);
background: white;
position: fixed;
border-radius: 2px;
box-shadow: 0 0 32px rgba(0, 0, 0, .25);
transition: box-shadow ease-in 50ms;
}
#contextMenu:hover {
box-shadow: 0 0 48px rgba(0, 0, 0, .25);
}
#contextMenu:active {
box-shadow: 0 0 16px rgba(0, 0, 0, .25);
}
#contextMenuImage {
width: 100%;
border-radius: 2px;
display: block;
}
.hidden {
visibility: hidden;
}<div id = "contextMenu" class = "hidden">
<img id = "contextMenuImage" src = "https://media1.giphy.com/media/3o7aTskHEUdgCQAXde/giphy.gif" />
</div>
RIGHT-CLICK TO SEE THE CONTEXT MENUОбратите внимание, что внутри обработчика oncontextmenu также есть проверка, чтобы предотвратить его изменение при щелчке правой кнопкой мыши по самому контекстному меню.
Очень полезно, спасибо. Получил свой голос. Но должен ли keyCode для escape не быть 27 вместо 70?
@BrunoEberhard Да, вы правы, только что исправили ? Спасибо (:
вам не нужен return false, просто preventDefault