I have a contenteditable div with a keyup event attached to it. There are many p
tags created within that div as the user types.
$(".pad").keyup(function(e) {
doSomething();
});
That's the keyup
event.
How could I work out which element the user has edited/created within the contenteditable div?
I have tried the following but it doesn't seem to work:
$(".pad p").keyup(function(e) {
doSomething();
});
The goal is to have something like this:
$(".pad").keyup(function(e) {
theEditedElement = ...;
$(theEditedElement).css("color","red");
$(theEditedElement).(...);
});
We start off with:
<div class="pad" contenteditable="true">
<p>Some text</p>
</div>
This is then edited by the user to:
<div class="pad" contenteditable="true">
<p>Some text</p>
<p>Some more text</p>
<p>Even <b>more</b> text</p>
</div>
If the user decides to edit <p>Some more text</p>
, then that specific <p>
element should be retrieved.
If you want your event target to be a child of a div
that is content editable instead of the div
itself, you need to set those child nodes to be contenteditable
as well. You can do that dynamically like this.
const contentEl = document.querySelector('.pad');
const paras = contentEl.childNodes;
// here, set contenteditable attribute for all paragraphs inside of that div
for (let i = 0; i < paras.length; i++) {
if (paras[i].nodeType === document.ELEMENT_NODE) {
paras[i].setAttribute('contenteditable', true);
}
}
contentEl.addEventListener('keyup', event => {
// event.target will be the element that you are asking for
const theEditedElement = event.target;
console.log(theEditedElement);
theEditedElement.style.color = 'red';
});
<div class="pad">
<p>Some text</p>
<p>Some more text</p>
<p>Even <b>more</b> text</p>
</div>
Note that you might need to run the piece of code that sets contenteditable
attribute to div
's childs again, when a new p
element is created inside of that div
.
Another option would be to create mutation observer and let it handle the changes to the enclosing div
in case any new paragraphs are added (let it set contenteditable
attribute of the newly added paragraph).
const contentEl = document.querySelector('.pad');
const paras = contentEl.childNodes;
for (let i = 0; i < paras.length; i++) {
if (paras[i].nodeType === document.ELEMENT_NODE) {
paras[i].setAttribute('contenteditable', true);
}
}
contentEl.addEventListener('keyup', event => {
// event.target will be the element that you are asking for
const theEditedElement = event.target;
console.log(theEditedElement);
theEditedElement.style.color = 'red';
});
// this code here is just to demonstrate the change to the enclosing div
const addNewParagraph = () => {
const p = document.createElement('p');
contentEl.appendChild(p);
p.textContent = 'new paragraph';
};
const btn = document.querySelector('button');
btn.addEventListener('click', addNewParagraph);
// create mutation observer
const config = { childList: true };
const callback = function(mutationList) {
for (const mutation of mutationList) {
if (mutation.type === 'childList') {
console.log('new paragraph has been added');
// get the added node and set its contenteditable attribute
mutation.addedNodes[0].setAttribute('contenteditable', true);
}
}
}
const observer = new MutationObserver(callback);
observer.observe(contentEl, config);
<button>add new paragraph</button>
<div class="pad">
<p>Some text</p>
<p>Some more text</p>
<p>Even <b>more</b> text</p>
</div>