Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I safely set a custom property on an Event object in JavaScript?

I'd like to set a custom property on a click event in a listener, and read this property in another event listener further up:

document.body.addEventListener('click', function(e) {
    if (e.someCustomProperty) {
        // ...
    }
});

document.getElementById('some-element').addEventListener('click', function(e) {
    e.someCustomProperty = someValue;
});

This seems to work fine in the latest version of all the browsers I could try:

  • Windows: IE11, Edge, Chrome, Firefox
  • iPhone: Safari, Edge, Chrome, Firefox

The event object retains the custom property when bubbling up.

This makes me quite confident that this behaviour is widely supported, but I could not find any envidence that this is standard though.

Can I trust that this behaviour works, and will continue to work, in all modern browsers?

If not, what is the standard way to do this?


I found a similar question from 2011, but the only answer is quite outdated now, mentioning it not working on IE8 (which I don't care today).


Background

Maybe I should give a little background to what I'm trying to achieve, and why the alternatives offered below - I think - do not help:

I have a modal window, that's basically a fixed DIV at the center of the screen:

<body>
    <div id="modal">
        <!-- content -->
    </div>
</body>

When the modal is open, I setup a click listener on the body, that checks if a click has happened inside or outside the modal:

  • if the click happened inside the modal, the listener does nothing
  • if the click happened outside the modal, the listener closes the modal

Hence the following code:

document.body.addEventListener('click', function(e) {
    if (! e.insideModal) {
        modal.close();
    }
});

document.getElementById('modal').addEventListener('click', function(e) {
    e.insideModal = true;
});

Failed alternatives:

  • I can't just stopPropagation() inside the modal click listener, as other listeners on body must still be able to catch the click;
  • I can't use document.getElementById('modal').contains(e.target) inside the body click listener, as by the time the click bubbles up to the body, the content of the modal may have already changed, and the click target may be gone;
  • I can't use a property on window, in the target element's dataset or anywhere else, as I fail to see how that will help me know whether this particular click has hit the modal before hitting the body; if you do, feel free to chime in!

This is why the event looks like the best place to put this information.

like image 953
BenMorel Avatar asked Nov 07 '22 01:11

BenMorel


1 Answers

In order to make modal window close on click outside a very simple technique can be used: modal window is wrapped with a transparent overlay that covers all the screen and has an onclick event listener inside which it compares event.target(an element which emits click event) and event.currentTarget (an element which has event listener appended). Equality means the overlay was clicked. Inquality means the modal was clicked.

function openModal() {
    document.getElementById('overlay').classList.add('visible');
}

document.getElementById('overlay').addEventListener('click', event => {
    if(event.target === event.currentTarget){
       event.target.classList.remove('visible');
    }
});
.overlay {
  display: none;
  background: transparent;
  height: 100vh;
  width: 100vw;
  position: fixed;
  top: 0;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.overlay.visible {
  display: flex
}

.modal {
  width: 100px;
  height: 100px;
  background: grey;
}
<button onclick="openModal()">Open modal</button>
<div id="overlay" class="overlay">
   <div class="modal"/>
</div>
like image 145
Volodymyr Avatar answered Nov 14 '22 21:11

Volodymyr