I am building a simplistic and easy-to-use text editor in Javascript, basically a WYSIWYG editor. I will be using the contenteditable
attribute to the main wrapper (.wrapper
). When you press enter inside the .wrapper
, a new <p>
element with a unique id
gets appended to the wrapper.
I need a way to fetch which child element of the .wrapper
that is currently selected (i.e., being focused or having the caret/text marker inside of it).
I've searched for days without any results, and I've tried using document.elementFromPoint()
but without any proper results.
When using $(":focus")
, I get the entire .wrapper
and not the specific child element.
Edit:
Example HTML structure:
<div class="container t-wrapper" contenteditable>
</div>
Example Javascript code:
$(document).ready(function() {
$currentElement = $("[contenteditable]");
$(".t-wrapper").each(function() {
var id = generateIdentifier(6); // Ignore this
/* This creates the initial <p> child element, where you start typing. */
$(this).html('<p class="t-empty t-first" id="' + id + '"></p>');
$(this).on("mouseup", function() {
/* $currentElement = whatever element the caret is inside. */
});
$(this).on("keyup", function() {
/* $currentElement = whatever element the caret is inside. */
});
));
});
Edit 2:
I managed to get it fairly working with the mouseup
event, since you're actually clicking on something. But I need this to work when moving the caret using the keyboard. Alternatively, I need some way to get the position of the caret in pixels, and then use document.elementFromPoint()
to get the specific element.
:focus
doesn't select your elements because they are not focusable.
You can make them focusable by adding tabindex="-1"
in HTML, or tabIndex = -1
in JS.
var generateIdentifier = Math.random;
var currentElement = document.querySelector("[contenteditable]");
[].forEach.call(document.querySelectorAll(".t-wrapper"), function(el) {
var first = document.createElement('p');
first.className = "t-empty t-first";
first.id = generateIdentifier(6);
first.textContent = 'Press enter to create new paragraphs';
first.tabIndex = -1;
el.appendChild(first);
});
.container > :focus {
border: 1px solid blue;
}
<div class="container t-wrapper" contenteditable></div>
It seems that if you add it to the first paragraph, new paragraphs obtain it automatically. But if you want to be sure, I guess you could use a mutation observer or a keyup event listener to detect paragraphs without tabindex
, and add it:
el.addEventListener("keyup", function(e) {
var newChild = el.querySelector('p:not([tabindex])');
if(newChild) newChild.tabIndex = -1;
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With