I have one div which has contenteditable property true. I want whenever new line is entered then that should be inside a span tag and that span should be inside p tag but whenever i am clicking on enter it just create new div.
Initial
<div contenteditable="true"></div>
Entering this text
- some text
- some new text
- some more new text
What i am getting
<div contenteditable="true">
some text
<div>some new text</div>
<div>some more new text</div>
</div>
What i want
<div contenteditable="true">
<p><span>some text</span></p>
<p><span>some new text</span></p>
<p><span>some more new text</span></p>
</div>
How can i achieve above pattern using javascript.
CodePudding user response:
Is there a need for the div to be initialized empty?
If not. You can already leave the initialized div with content with the formatting tags the way you want. Ex:
div {
width: 150px;
height: 150px;
border: 1px solid red;
}
<div contenteditable="true">
<p><span>Some Text</span></p>
</div>
So each time a user inserts a newline, it will be with the formatting and content tags already present in the div.
CodePudding user response:
You can do that by listening for the insertion of a line break and replacing it with the required elements, here is an example:
const elm = document.querySelector('#ce');
elm.addEventListener('beforeinput', (event) => {
if (['insertLineBreak', 'insertParagraph'].includes(event.inputType)) {
event.preventDefault();
event.stopPropagation();
const paragraph = document.createElement('p');
const span = document.createElement('span');
span.innerHTML = '​';
paragraph.append(span);
elm.append(paragraph);
const range = new Range();
range.selectNode(span);
range.setStart(span, 0);
range.collapse(true);
const selection = document.getSelection();
if (selection.rangeCount > 0) {
selection.removeAllRanges();
}
selection.addRange(range);
}
});
#ce {
width: 200px;
height: 100px;
border: 1px solid black;
}
<div id="ce" contenteditable="true"></div>
Here, I'm using the beforeinput
listener to check when a new line is inserted, I'm preventing that event event.preventDefault()
and then,
I'm creating the required elements (a <span>
inside a <p>
) and I'm using the Selection API to set the caret inside the newly created <span>
.
The only unusual thing here is this:
span.innerHTML = '​';
I'm using this because the caret will not be positioned correctly if the <span>
doesn't have any content. ​
is a zero width space character.
There are probably better ways of setting the caret's position.