JSFiddle - React, Tailwind, and code Playground

by alexb

HTML

<button id="addControl">Add control</button>
<div id="controlPanel"></div>

CSS

#controlPanel {
  background: lightgray;
  border: 1px outset;
  margin: 1em 0;
  padding: 1em;
}

.upcase {
  text-transform: uppercase;
}

JavaScript

/**
 * @param target {Node}
 * @param selector {string}
 * @param listener {(node: Node) => void)}
 */
function onChildNodeAdded(target, selector, listener) {
  new MutationObserver((mutations, observer) => {
    for (const mut of mutations) {
      const el = mut.target.querySelector(selector);
      if (el) {
        observer.disconnect();
        setTimeout(() => listener(el), 0);
        return;
      }
    }
  }).observe(target, { childList: true, subtree: true });
}

/**
 * @param target {Node}
 * @param listener {(node: Node) => void)}
 */
function onClassChanged(target, listener) {
  new MutationObserver(mutations => {
    setTimeout(() => listener(), 0);
  }).observe(target, {
    attributes: true,
    attributeFilter: ["class"]
  });
}

const add = document.getElementById('addControl');
const panel = document.getElementById('controlPanel');
add.addEventListener("click", e => {
	const ctrl = document.createElement('button');
  ctrl.innerText = 'Execute';
  ctrl.className = 'ctrl';
  ctrl.addEventListener("click", () => { ctrl.classList.toggle('upcase'); })
  panel.appendChild(ctrl);
});

onChildNodeAdded(panel, '.ctrl', btn => {
	onClassChanged(btn, e => {
  	console.log(btn.classList.contains('upcase') ? "what's updog?" : "not much. what's up with you?");
  });
});