я наконец-то удалось решить эту проблему, к сожалению, это очень Hacky ... Я действительно ненавижу contenteditable :( Надеюсь, что это помогает любому, кто борется с этим.
Хитрость заключается в том, чтобы обернуть содержимое contenteditable в тег div
или p
, к сожалению, одного этого недостаточно, поскольку пользователь может легко удалить этот тег, когда удаляет все содержимое и продолжает нажимать backspace или удалить или даже удалить все сразу, используя ctrl + a backspace ... и т. д.
Итак, нам также нужно убедиться, что наш упаковщик вставлен, если он не существует.
шаги:
- Добавить обработчик
keyup
.
- Проверьте, существует ли наша оболочка.
- Если это так, все хорошо.
Если нет:
Как-то сохранить текущую позицию каретки (я вставляю поддельный элемент, чтобы отслеживать его положение)
создайте наш элемент и оберните в него текущий контент.
- Восстановление позиции каретки (и удаление поддельного элемента).
Это слишком много работы для чего-то такого простого, я действительно надеюсь, что я ошибаюсь и что существует более простое решение.
document.execCommand('defaultParagraphSeparator', false, 'p');
const button = document.getElementById('button');
button.addEventListener('click', function() {
const range = document.createRange();
const target = document.getElementById('target');
range.selectNode(target);
range.deleteContents();
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
});
$('.wrapper').on('keyup', function(e) {
if ($('.wrapper > p').length == 0) {
pushCaretMarker();
const html = '<p>' + $(this).html() + '<br></p>';
$(this).html(html);
popCaretMarker();
}
});
function pushCaretMarker() {
const range = getRange();
const $span = $('<span id="caret-marker">|</span>');
range.insertNode($span.get(0));
range.collapse();
}
function popCaretMarker() {
const $span = $('#caret-marker');
if ($span.length > 0) {
const range = getRange();
range.selectNode($span.get(0));
range.deleteContents();
}
}
function getRange() {
return window.getSelection().getRangeAt(0);
}
.wrapper {
min-height: 20px;
}
.wrapper>p {
margin: 0;
}
.wrapper>p:not(:last-child) {
margin-bottom: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper" contenteditable="true">
<p>
Click <span id="target">Button</span> then hit enter
</p>
</div>
<button id="button">go</button>