Detect mouse right click outside of custom selection (highlight)

Suppose the user selected something (text / image / something) on ​​the page and then right clicked. Is there a way to determine if it clicked outside of the selection or inside it?

+3


source to share


2 answers


After many tries *, I think there is no clean solution.

I finally came up with a jstonne answer tag (which itself is MikeB's answer in the same thread) to something that might suit your needs.

It involves getting the Range

current selection on the right click (easy part), and then checking if the event node's target is in that range (hard part). Unfortunately, there is no easy way to get the nodes contained in the Range object, so we must iterate over the nodes contained between Range.startContainer

and Range.endContainer

.



* even one implying range.extractContents () and MutationObservers

NOTES:

  • Since Chrome seems to make a new range selection for us when we do a right click, it will always return true if you right click on the text.
  • When you select a tag img

    , you are actually selecting the textNodes before and after the element, so if you select the first image in the example below and you right click on the text Some Dummy Text

    it will return. But if you do the same test on the second image, it won't happen as the text is wrapped in an element <span>

    .
  • There can be many other caveats (depending on the browser, os, etc.),
    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>
          

    Run codeHide result


+1


source


Hmm, I don't know a direct answer, but you can try this:

1- in the first click get x1 = clientX and y1 = clientY

2- on mouseup get x2 = clientX and y2 = ClientY

3- right click, check if there is client X and clientY, what we get in 1- and 2- (rectangle with corners x1, y1, x2, y2)



code:

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/

0


source







All Articles