简体   繁体   中英

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.

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>

I would not recommend it. And these are the reasons:

  • Not documented means not reliable, can bring surprises, etc.
  • It seems that there is one event object for different event listeners of any element. So you can't achieve much with assigning data to the event object. With the same result you can assign data to window

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