Joshua's Docs - Javascript Events - Cheat Sheet
Light

Event Capture

Basic:

document.querySelector('a[href^="tel:"]').addEventListener('click',function(evt){
  console.group('Click to Call Link Clicked. Details:');
    console.log(evt);
  console.groupEnd();
});

JQuery:

$('a[href^="tel:"]').on('click',function(evt){
  console.group('Click to Call Link Clicked. Details:');
    console.log(evt);
  console.groupEnd();
});

Bubbling and capturing:

@TODO

Attaching Directly vs Letting Bubble

Often you will event listeners attached at the document level, wait for an event to bubble up, and then check to see if the event matches what you are looking for. Here are some examples of that pattern:

  • Vanilla JS
document.addEventListener('click',function(evt){
  if (evt.target.getAttribute('id')==='ctaLink'){
    console.log('My CTA Link Clicked!');
  }
});
  • JQuery
$(document).on('click','#ctaLink',function(evt){
  console.log('My CTA Link Clicked!');
});

Problems with this method:

The main problem with this method has to do with bubbling and capture. Consider this code:

<!-- Script from third party vendor -->
<script>
document.querySelector('#ctaLink').addEventListener('click',function(evt){
  evt.stopPropagation();
});
</script>

<!-- Your event listener -->
<script>
document.addEventListener('click',function(evt){
  if (evt.target.getAttribute('id')==='ctaLink'){
    console.log('My CTA Link Clicked!');
    // This never logs
  }
});
</script>

Because the first script used evt.stopPropagation() (MDN), once it fires, it will stop the event from bubbling up the DOM and it will never reach our document listener! However, if we attach our listener directly to the node that fires it (corresponding to evt.target), side-by-side listeners will still fire, like this:

<!-- Script from third party vendor -->
<script>
document.querySelector('#ctaLink').addEventListener('click',function(evt){
  evt.stopPropagation();
});
</script>

<!-- Your event listener -->
<script>
document.querySelector('#ctaLink').addEventListener('click',function(evt){
  console.log('My CTA Link Clicked!');
  // Success!
});
</script>

Warning: Side-by-side listeners will not work, if one listener callback uses event.stopImmediatePropagation(). This method stops all other handlers attached to the DOM node that run after it from firing, and thus should be avoided using whenever possible.

Event Generation

  • MDN Guide on creating and dispatching events

You can dispatch native events with JS:

document.querySelector('button').dispatchEvent(new Event('mouseover', {view: window, bubbles: true, cancelable: true}))

But, also your own arbitrary events can be generated with JS and dispatched to the browser/DOM with relative ease:

var customEvent = new Event('videoPlay');
document.getElementById('videoPlayer').dispatchEvent(customEvent);
// Or, dispatch on document
// document.dispatchEvent(customEvent);

For legacy IE support, there is an older way / other APIs. However, strongly not recommended when possible, as deprecated in most browsers.

var customEvent = createEvent('Event');
// initEvent signature is initEvent(eventName, bubbles, cancelable)
customEvent.initEvent('videoPlay',true,false);
document.dispatchEvent(customEvent);

Passing extra details

With CustomEvent (95%+ browser support) (CanIUse)

var customEvent = new CustomEvent('videoProgress',{detail: '25-percent'});
document.getElementById('videoPlayer').dispatchEvent(customEvent);
Markdown Source Last Updated:
Sat May 20 2023 05:26:36 GMT+0000 (Coordinated Universal Time)
Markdown Source Created:
Wed Aug 21 2019 00:46:11 GMT+0000 (Coordinated Universal Time)
© 2024 Joshua Tzucker, Built with Gatsby
Feedback