4

I am loading some markup into a page, asynchronously, using Ajax.

I want to attach an EventListener to an <element> within that markup, such that when the element is parsed the EventListener fires.

What Event can I use for myEvent ?

  • onparse does not exist
  • onload does exist, but we can't apply it to <h2> or <div>. We can only apply it to:
    • <body>
    • <frame>
    • <iframe>
    • <img>
    • <input type="image">
    • <link>
    • <script>
    • <style>

Are there any other candidate Events I might use?

Or any alternative approaches to ensuring that an EventListener fires when an element is parsed?


The best approach I have come across so far (albeit a little bit unorthodox) is the

  • <img src> hack

An <img> with an undeclared src attribute will trigger the onerror EventListener when it is parsed.

Consequently the following example works:

let myHeadingLoadEventTrigger = document.getElementById('my-heading-load-event-trigger');

const updateHeading = (e) => {

  let myHeading = e.target.previousElementSibling;
  
  if (true) { // <= CONDITION HERE
    
    myHeading.textContent = 'My Updated Heading';
  }
  
  // Modern alternative to document.body.removeChild(e.target);
  e.target.remove();
}

myHeadingLoadEventTrigger.addEventListener('error', updateHeading, false);
<h2>My Heading</h2>
<img id="my-heading-load-event-trigger" src />

Solution:

Although a native onparse event does not exist, I can:

  • write my own onparse event; and
  • use a custom data-onparse attribute to fire the onparse event

Working Example:

// Create (homemade) parse event
let parseEvent = new Event('parse');

// Create Initialising Function which can be run at any time
const initialiseParseableElements = () => {

  // Get all the elements which need to respond to an onparse event
  let elementsWithParseEventListener = document.querySelectorAll('[data-onparse]');
  
  // Attach Event Listeners and Dispatch Events
  elementsWithParseEventListener.forEach((elementWithParseEventListener) => {

    elementWithParseEventListener.addEventListener('parse', updateParseEventTarget, false);
    elementWithParseEventListener.dataset.onparsed = elementWithParseEventListener.dataset.onparse;
    elementWithParseEventListener.removeAttribute('data-onparse');
    elementWithParseEventListener.dispatchEvent(parseEvent);
  });
}

// Callback function for the Parse Event Listener
const updateParseEventTarget = (e) => {
  
  switch (e.target.dataset.onparsed) {

    case ('my-heading') : e.target.textContent = 'My Updated Heading'; break;
  }
}

// Run Initialising Function
initialiseParseableElements();
<h2 data-onparse="my-heading">My Heading</h2>
Rounin
  • 27,134
  • 9
  • 83
  • 108
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/202293/discussion-on-question-by-rounin-says-je-suis-monica-is-there-an-equivalent-of-o). – Samuel Liew Nov 14 '19 at 01:00
  • 1
    @Quintin, the dupe is very old and could use a new solution as OP came up with himself which is why I retracted my vote earlier – mplungjan Nov 14 '19 at 06:15

0 Answers0