简体   繁体   中英

How to prevent a click release from firing on background (e.g. selecting input text in popup overlay)

  • Let's say I open a popup overlay box with a background that can be clicked to close it.

  • Then in that box I have a text input.

  • If the user drags their mouse to select all the text from the input and overshots by releasing the mouse over the background, then the click event fires and the whole popup closes.

Of course I could use other events on that background like mousedown or pointerdown but it leads to a loophole with all sorts of other issues. For example, if the background uses that then all other elements of the page should use the same type of event in order to make the stopPropagation() calls work. This creates many problems, such as the fact that a button mousedown/pointerdown will trigger before an input blur , and so on.

Is there a way to know from the click event of that background that the mousedown was not initiated on that same element? (meaning it was a drag)

Otherwise, is there another simple way to deal with this issue?

CODE EXAMPLE: https://jsfiddle.net/4aLz1ft7/

EDIT: Of course it should be a reasonably simple solution (or as simple as possible). Adding an event on every input is not realistic because this content could be dynamic, could contain anything else. Ideally the solution would happen with the wrappers themselves (#overlay and #overlay_content).

so this is working by removing the click event from your overlay using a mousedown event on the content, and then adding it back 1 second after mouseup. I add this back using either of two different events, mouseup on overlay and content.

1 second is just a basic time, it could work properly with less.

I'm not sure why.stopPropagation() or.stopImmediatePropagation() is not working though...

updated the fiddle:

https://jsfiddle.net/1763toyx/1/

 ele_overlay.addEventListener('click', overlay_close, false); ele_overlay_content.addEventListener('mousedown', (v) => { ele_overlay.removeEventListener('click', overlay_close); }, false); ele_overlay_content.addEventListener('mouseup', (v) => { ele_overlay.removeEventListener('click', overlay_close); setTimeout(() => { ele_overlay.addEventListener('click', overlay_close, false); }, 1000); }, false); ele_overlay.addEventListener('mouseup', (v) => { setTimeout(() => { ele_overlay.addEventListener('click', overlay_close, false); }, 1000); }, false);

All right, if we're allowed to go (somewhat) dirty, I have another approach than the one @ThisGuy mentioned.

https://jsfiddle.net/1e0yjofc/1/

const ele_overlay = document.getElementById('overlay');
const ele_overlay_content = document.getElementById('overlay_content');

function overlay_open(){
    ele_overlay.classList.add('open');
}

function overlay_close(){
    ele_overlay.classList.remove('open', 'waitingForClick');
}

ele_overlay_content.addEventListener('pointerdown', function(v){
    v.stopPropagation();
}, false);

ele_overlay_content.addEventListener('click', function(v){
    v.stopPropagation();
    ele_overlay.classList.remove('waitingForClick');
}, false);

ele_overlay.addEventListener('pointerdown', function(v){
    ele_overlay.classList.add('waitingForClick');
}, false);

ele_overlay.addEventListener('click', function(v){
    if( ele_overlay.classList.contains('waitingForClick') )
        overlay_close();
}, false);

The idea is to set a class on the wrapper (background) of the overlay that allows the click event to trigger. And we only allow it if it is preceded by a pointerdown event, because as far as I know a click cannot happen without a pointerdown , or can it?

Of course this could also be a variable instead of a class, but then we would have to deal with declaring it somewhere and it would also make it hard to scale with highly dynamic content (like a whole library). Right now the whole code still doesn't need any global variable since the getElementById calls can be made in the functions themselves.

I find that slightly less dirty than messing around with timers, but if someone has a simpler idea I would love to hear it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM