swisnl / jQuery-contextMenu

jQuery contextMenu plugin & polyfill
https://swisnl.github.io/jQuery-contextMenu/
MIT License
2.24k stars 744 forks source link

window.getSelection not updated on repeated right-click #657

Open Arithmomaniac opened 6 years ago

Arithmomaniac commented 6 years ago

Using a registered event similar to this:

$.contextMenu({
        selector: ".foo",
        build: function($triggerElement, e){
            console.log(window.getSelection().getRangeAt(0));
            return {zIndex: 10, items: getMenuItems(), reposition: false};
        }
    })

If I repeatedly right-click (as in #104) on a text element, the logged message remains the same; window.getSelection() is not updated. This is despite having reposition: false.

I tested this with the browser's native context menu:

document.addEventListener("selectionchange", function(e) {
  console.log(window.getSelection().getRangeAt(0));
});

and that does refresh.

using jQuery.contextMenu v2.7.0, Chrome 67

Arithmomaniac commented 6 years ago

This is the workaround I have been using, but the ideal would really be to re-fire the right-click event as if it was the first time:

//if a contextmenu event is triggered by a library, the clientX values may be missing
//https://gist.github.com/branneman/fc66785c082099298955
var clientX = e.clientX || (e.pageX - document.body.scrollLeft - document.documentElement.scrollLeft);
var clientY = e.clientY || (e.pageY - document.body.scrollTop - document.documentElement.scrollTop);

var pointRange =  document.caretRangeFromPoint(clientX, clientY); 
var selectionRange = window.getSelection().getRangeAt(0); 

//refocus select if right-click outside of selection range 
if (pointRange.startOffset < selectionRange.startOffset 
    || pointRange.endOffset > selectionRange.endOffset)  
{ 
    selectionRange = pointRange.cloneRange(); 
    window.getSelection().removeAllRanges(); 
    window.getSelection().addRange(selectionRange); 
}