JSFiddle - React, Tailwind, and code Playground
HTML
Here's an <input>:<br>
<input type="text">
<br><br>Here's a <span>:<br>
<span id="myspan" contenteditable="true" spellcheck="false"></span>
<br><br>
<span id="hello">Here the text of <span> will be displayed when it changes!</span>
CSS
span[contenteditable=true] {
display: inline-block;
width: 160px;
height: autO;
font-family: sans-serif;
font-weight: 400;
font-stretch: normal;
font-size: 13.3333px;
font-variant-ligatures: normal;
font-variant-caps: normal;
font-variant-numeric: normal;
font-variant-east-asian: normal;
text-rendering: auto;
letter-spacing: normal;
word-spacing: normal;
text-indent: 0px;
line-height: normal;
appearance: textfield;
-webkit-appearance: textfield;
cursor: text;
padding: 1px;
border-width: 1px;
-webkit-border-width: 2px;
border-style: solid;
-webkit-border-style: inset;
border-color: initial;
border-image: initial;
background-color: white;
}
JavaScript
(function() {
window.MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
let onAddedElement = function(element) {
if (!element.matches("span[contenteditable=true]"))
return;
new MutationObserver(function(mutationsList) {
if (this.innerText === this.oldInnerText)
return;
this.oldInnerText = this.innerText;
this.dispatchEvent(new Event("textchanged"));
}.bind(element)).observe(element, { attributes: false, childList: true, subtree: true, characterData: true });
}
new MutationObserver(function(mutationsList) {
for (let mutation of mutationsList) {
for (let child of mutation.addedNodes) {
if (!child.matches)
continue;
onAddedElement(child);
}
}
}).observe(document.body, { attributes: false, childList: true, subtree: true });
(function findElements(parent) {
for (let child of parent.children) {
if (child.matches)
onAddedElement(child);
findElements(child);
}
delete findElements;
})(document.body);
})();
window.addEventListener("DOMContentLoaded", function() {
let myspan = document.getElementById("myspan");
myspan.addEventListener("textchanged", function() {
document.getElementById("hello").innerText = myspan.innerText;
});
});
if (document.readyState === "complete") {
window.dispatchEvent(new Event("DOMContentLoaded"));
window.dispatchEvent(new Event("load"));
}