【问题标题】:Detect right mouse click outside of the user selection (highlight)检测用户选择之外的鼠标右键单击(突出显示)
【发布时间】:2015-07-30 09:33:38
【问题描述】:

假设用户在页面上选择了一些东西(文本/图像/任何东西),然后他点击了鼠标右键。有什么方法可以检测他是点击了选择之外还是里面?

【问题讨论】:

  • 检查一下这可能对你有帮助codeproject.com/Articles/11222/…
  • 对不起,这不是我想要达到的。
  • 对于那个非常具体的情况,我认为您没有很多解决方案,您可以获得的最接近的是:1)检测用户何时选择某些东西(简单)。 2) 检索该元素的父节点。 3) 用包含占位符类的较新元素替换所选元素。 4) 在该类上添加一个右键单击事件侦听器,并在 dom 的其余部分添加一个右键单击事件侦听器。一些可能对您有所帮助的参考资料:stackoverflow.com/questions/3731328/on-text-highlight-eventstackoverflow.com/questions/1206203/…
  • @briosheje 所以如果你选择一个单独的 textNode 直接放在正文中,你会复制完整的文档吗?另外,您如何处理选择的部分/多个元素?您提供的第一个链接只能获取选择的文本内容,不能获取其他元素。
  • @Danny,你找到解决方案了吗?我在回答中列举的要点总是正确的(主要是不同浏览器的行为)。也许你应该给我们一个更准确的上下文,说明你在这里需要什么。

标签: javascript html


【解决方案1】:

经过多次尝试*,我认为没有干净的解决方案。

我终于想出了对jstonneanswer 的调整(这本身就是对同一线程上MikeBanswer 的调整)可能适合您的需求。

这意味着右键单击获取当前选择的Range(简单部分),然后检查事件的目标节点是否在此范围内(棘手部分)。遗憾的是,没有简单的方法来获取 Range 对象中包含的节点,因此我们必须遍历 Range.startContainerRange.endContainer 之间包含的节点。

*甚至一个暗示 range.extractContents() 和 MutationObservers

注意事项:

  • 由于 Chrome 似乎在我们右键单击时为我们做出了新的范围选择,所以如果您右键单击文本,它将始终返回 true。
  • 当你选择img标签时,你实际上是在选择元素前后的textNodes,所以如果你在下面的例子中选择第一张图片,然后右键单击Some Dummy Text文本,它会返回真。但是,如果您对第二张图片进行相同的测试,则不会,因为文本被包裹在 <span> 元素中。
  • 可能还有很多其他警告(取决于浏览器、操作系统等)
    function isInsideSelection(event){
        event.preventDefault();
    	var p = document.querySelector('#result');
    	p.innerHTML= ''
    	var sel = window.getSelection();
    
    	if(!sel.rangeCount) return;
    	var range = sel.getRangeAt(0);
    	// nothing selected : don't do anything
    	if(range.collapsed) return;
    	// Firefox allows us to get the real node we clicked on
    	var result = isTargetInRange(range, event.explicitOriginalTarget, event.target);
    	p.innerHTML= 'clicked in the target: '+result;
    }
    	
    function getNextNode(node) {
        if (node.firstChild)
            return node.firstChild;
    
        while (node) {
            if (node.nextSibling) return node.nextSibling;
            node = node.parentNode;
        }
    }
    
    function isTargetInRange(range, nodeTarget, elementTarget) {
        var start = range.startContainer.childNodes[range.startOffset] || range.startContainer;
        var end = range.endContainer.childNodes[range.endOffset] || range.endContainer;
        var commonAncestor = range.commonAncestorContainer;
        var nodes = [];
        var node;
        var result=false;
        for (node = start.parentNode; node; node = node.parentNode)
        {
        	// our target is an element
        	if(!nodeTarget && elementTarget === node ){
        		result=true;
        		break;
        		}
            nodes.push(node);
            if (node == commonAncestor)
                break;
        }
        nodes.reverse();
    
        // walk children and siblings from start until end is found
        for (node = start; node; node = getNextNode(node))
        {
    		// our target can be a textNode
    		if((nodeTarget && nodeTarget === node) || (!nodeTarget && elementTarget === node)){
    			result=true;
    			break;
    			}
            if (node == end)
                break;
        }
        return result;
    };
    
    document.addEventListener('contextmenu', isInsideSelection, false);
    #result{position: fixed; bottom:0;right:0}
    <p id="result"></p>
    <img src="http://lorempixel.com/50/50"/>
    Some Dummy Text
    <p>Some other text</p>
    <div><img src="http://lorempixel.com/60/60"/><span>with</span> some text</div>

【讨论】:

    【解决方案2】:

    嗯,我不知道直接的答案,但你可以试试这个:

    1- 在第一次点击中获取 x1= clientX 和 y1= clientY

    2- 在 mouseup 上获取 x2= clientX 和 y2= ClientY

    3- 右键单击​​检查 clientX 和 clientY 是否介于我们在 1- 和 2- 中得到的内容(带角 x1,y1,x2,y2 的矩形)

    代码:

    var x1,x2,y1,y2;
    var selected = false;
    document.onmousedown = function(e){
    ...
    }
    document.onmouseup = function(e){
        x2 = e.clientX;
        y2 = e.clientY;
        selected = true;
    }
    

    http://jsfiddle.net/htpfwwgy/

    【讨论】:

    • 我想这是我能得到的最接近的解决方案。有什么 sn-ps 可以轻松实现这一点吗?我想到的另一个是获取包含选择的元素列表,然后在右键单击事件时循环它们。
    • 非常感谢。我有点困惑。当用户单击外部选择时,如何正确管理案例?简单的else 或反转&gt;&lt; 不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-10
    • 1970-01-01
    • 2019-01-19
    • 1970-01-01
    • 2012-08-18
    • 1970-01-01
    相关资源
    最近更新 更多