Есть несколько действий, которые закрывают собственное контекстное меню:
Щелкните снаружи: Прослушайте document.onmousedown
и, вДля того, чтобы клики других (действительных) элементов не всплывали и не закрывали контекстное меню, вы должны остановить его распространение в промежуточном обработчике с помощью Event.stopPropagation
.
document.onclick
также будет работать, но контекстное меню будет оставаться видимым до тех пор, пока вы не отпустите кнопку мыши, а не исчезнет только при нажатии.
В сенсорных устройствах вам следует прослушать document.touchstart
, поскольку некоторые устройства, такие как iPad, не запускают события click
.
Нажатие Esc : Прослушивание document.onkeydown
и проверьте, является ли нажатая клавиша Esc проверкой KeyboardEvent.keyCode
, KeyboardEvent.which
и KeyboardEvent.key
.
Изменение вкладки / окна : прослушивание window.onblur
.
Прокрутка мыши: В Chrome, liСтен для 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
также есть проверка, чтобы предотвратить щелчок правой кнопкой мыши по контекстному меню и его позиционирование.