gpt4 book ai didi

javascript - 如何测试上下文菜单是否打开或显示?

转载 作者:行者123 更新时间:2023-12-05 06:50:55 25 4
gpt4 key购买 nike

我有一个包含计算机代码的 pre 标签的页面。我有一个 mouseover 事件监听器,它突出显示 pre 标记中的所有代码。我还让它删除了 mouseout 事件上的突出显示。如果您使用键盘复制 (ctrl-C),效果非常好。

但是如果你想从上下文菜单中右键单击并复制,那就有问题了。当鼠标进入上下文菜单时,会触发pre标签的mouseout事件。

我需要一种方法来测试上下文菜单当前是否打开或显示。然后我可以取消删除突出显示。有没有办法测试上下文菜单是否打开或显示?

我不需要任何 jquery,拜托。

我对这个问题的最终选择可能是 oncontextmenu,但我不知道如果它关闭我将如何发现。除非我尝试为上下文菜单的 mouseout 事件监听事件,如果可能的话。

到目前为止,这是我的代码:

window.onload = function(){

function selectText(element) {
var range, selection;

if(window.getSelection) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);
}
}

function unSelectText() {
window.getSelection().removeAllRanges();
}

preTags = document.getElementsByTagName('PRE');

for(var i = 0; i < preTags.length; i++) {
preTags[i].onmouseover = function() {selectText(this)};
preTags[i].onmouseout = function() {unSelectText(this)};
}

codeTags = document.getElementsByTagName('CODE');

for(var i = 0; i < codeTags.length; i++) {
codeTags[i].onmouseover = function() {selectText(this)};
codeTags[i].onmouseout = function() {unSelectText(this)};
}
};

最佳答案

由于 JS 中没有事件触发上下文菜单框的关闭操作,也没有可靠的解决方法:据我从不同的研究中了解到,您的问题的答案是否定的。

但是如果您考虑类似的方法,可以使用自定义上下文菜单来解决您的问题。

简短说明

  1. 将自定义上下文菜单添加到您的 codepre 元素。在您的情况下,只需要一个项目copy(在示例中快速!非常!简化!演示为简单框)。
  2. 打开菜单时停用右键单击以避免停止选择您的代码(据我了解,这是您的问题/问题)
  3. 打开菜单时停用右键单击其他元素,这样您就不会打开其他上下文菜单
  4. 当点击菜单项时开始复制操作关闭并重置
  5. 当点击外部菜单时关闭并重置

简化示例

请注意:该示例是一个快速、肮脏且非常简单的示例,用于演示该技术。 I tsure needs to be adapt to your special project.

window.onload = function(){

// general vars
let isOpenContextMenu = false;
const $contextMenu = document.getElementById('contextMenu');
// all code/pre elements in one object to use in one loop
const $codeElements = document.querySelectorAll('pre, code');
let $actualCodeElement = {};



// methods
function selectText(element) {
var range, selection;

if(window.getSelection) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);
}
}

function unSelectText() {
window.getSelection().removeAllRanges();
}



// listeners


// block right clicke when context menu on code/pre element is open
function listenerContextMenuBlocked(evt){
evt.preventDefault();
}


// clicks when context menu on code/pre elements is open
function listenerMenuClick(ev){

let $clickedElement = ev.target;
do{

if($clickedElement == $contextMenu){

// clicked on context menu

// --> copy action
let codeToCopy = $actualCodeElement.innerText;
let temporaryInput = document.createElement('input');
temporaryInput.type = 'text';
temporaryInput.value = codeToCopy;
document.body.appendChild(temporaryInput);
temporaryInput.select();
document.execCommand('Copy');
document.body.removeChild(temporaryInput);

// --> close menu and reset
$contextMenu.classList.remove('contextMenu--active');
isOpenContextMenu = false;
window.removeEventListener('contextmenu', listenerContextMenuBlocked);
return;
}
$clickedElement = $clickedElement.parentNode;

} while($clickedElement)


// clicked outside context menu
// --> close and reset
$contextMenu.classList.remove('contextMenu--active');
isOpenContextMenu = false;
window.removeEventListener('contextmenu', listenerContextMenuBlocked);

}


// open custom context menu when right click on code/pre elements
function listenerOpenContextMenuCodeBlock(e) {

e.preventDefault();

// used to copy conten in listenerMenuClick()
$actualCodeElement = e.target;

if(false === isOpenContextMenu){

// open context menu
$contextMenu.style.top = e.clientY + 2 + 'px';
$contextMenu.style.left = e.clientX + + 2 + 'px';
$contextMenu.classList.add('contextMenu--active');

isOpenContextMenu = true;
window.addEventListener('click', listenerMenuClick);
window.addEventListener('contextmenu', listenerContextMenuBlocked);

}

}



for(var i = 0; i < $codeElements.length; i++) {

//$actualElement = $codeElements[i]; //
$codeElements[i].addEventListener('contextmenu', listenerOpenContextMenuCodeBlock);
$codeElements[i].onmouseover = function() {
if(false === isOpenContextMenu){
selectText(this)
}
};
$codeElements[i].onmouseout = function() {
if(false === isOpenContextMenu){
unSelectText(this)
}
};
}

};
/* styles needed for custom context menu */
html {
position: relative;

}
#contextMenu {
display: none;
position: absolute;
font-family: sans-serif;
font-size: 11px;
line-height: 12px;
padding: 2px 5px;
background-color: #eeeeee;
border: 1px solid #a5a5a5;
box-shadow: 2px 3px 1px -1px rgba(0,0,0,0.4);;
cursor: context-menu;
z-index: 10;
}

#contextMenu:hover {
background-color: #aad7f3;
}
#contextMenu.contextMenu--active {
display: block;
}
<!-- SIMPLIFIED custom context menu for code/pre elements = hidden on page -->
<nav id="contextMenu" style="top: 50px; left: 30px" >
<div>Copy Codeblock</div>
</nav>


<!-- example elements for code presentation / testing -->
<pre>
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
Provident magni blanditiis, ea necessitatibus esse nihil,
quae iste explicabo beatae perspiciatis quibusdam tempora minima,
eos molestias illum voluptatum voluptate ipsum perferendis!
</pre>

<code>
Li Europan lingues es membres del sam familie. Lor separat existentie
es un myth. Por scientie, musica, sport etc, litot Europa usa li sam vocabular.
Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules.
Omnicos directe al desirabilite de un nov lingua franca: On refusa continuar payar
custosi traductores.
</code>

关于javascript - 如何测试上下文菜单是否打开或显示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66285475/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com