JSFiddle - React, Tailwind, and code Playground

by Michael Naumov

HTML

<input type="text" id="myTextBox">
<div>
    <button data-text="debugger">Set 'debugger' text into textbox - triggers debugger</button>
</div>
<div>
    <button data-text="alert">Set 'alert' text into textbox - triggers alert</button>
</div>
<div>
    <button data-text="bad">Set 'bad' text into textbox - will be replaced with 'good' text</button>
</div>

CSS

div {
  white-space: pre;
}

JavaScript

function injectPropertyEvents(element, propertyName) {
    if (!(propertyName in element))
        throw new Error("Element does not have property " + propertyName);

    var propertyHolder = element;
    var descriptor;
    while (propertyHolder !== null) {
        descriptor = Object.getOwnPropertyDescriptor(propertyHolder, propertyName);
        if (descriptor)
            break;
        propertyHolder = Object.getPrototypeOf(propertyHolder);
    }

    if (!descriptor)
        throw new Error("Could not find property desciptor " + propertyName);

    if (propertyHolder.propertyEventsInjected)
        return;

    function raiseEvent(element, eventName, eventDetails) {
        var event;
        var bubbles = false;
        var cancelable = false;
        try {
            event = new CustomEvent(eventName, {
                bubbles: bubbles,
                cancelable: cancelable,
                detail: eventDetails
            });
        } catch (e) {
            event = document.createEvent("CustomEvent");
            event.initCustomEvent(eventName, bubbles, cancelable, eventDetails);
        }
        element.dispatchEvent(event);
    }

    Object.defineProperty(propertyHolder, propertyName, {
        configurable: true,
        get: function get() {
            var eventDetails = {
                value: descriptor.get.call(this)
            }
            raiseEvent(this, propertyName + "Getting", eventDetails);
            return eventDetails.value;
        },
        set: function set(value) {
            var eventDetails = {
                oldValue: descriptor.get.call(this),
                newValue: value
            };
            raiseEvent(this, propertyName + "Changing", eventDetails);
            descriptor.set.call(this, eventDetails.newValue);
            raiseEvent(this, propertyName + "Changed", eventDetails);
        }
    });

    propertyHolder.propertyEventsInjected = true;
}

var myTextBox =...