Я запускаю этот код, чтобы установить каретку в конце предмета спора, когда div сфокусирован. Я также запускаю скрипт на клавише ввода, чтобы исправить странность разрывов строк в Firefox. По какой-то причине эти две функции не работают вместе, и я получаю следующее сообщение:
IndexSizeError: Индекс или размер отрицателен или превышает допустимую сумму
Попробуйте нажать на div и нажмите Enter в Firefox, и вы поймете, что я имею в виду. Это работает в Safari и Chrome.
Я не могу использовать текстовую область, но есть ли более чистый способ решить эту проблему? Я также добавил setTimeout
к функции placeCaretAtEnd
, потому что она иногда помещает курсор в том месте, где я нажимала, и иногда выделяет часть текста вместо того, чтобы поместить ее в конец. Время от времени он действует странно, поэтому предложения о более пуленепробиваемом способе его отображения всегда в конце приветствуются!
function placeCaretAtEnd(el) {
el.focus();
if (typeof window.getSelection != "undefined"
&& typeof document.createRange != "undefined") {
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange != "undefined") {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}
$(document).on('keydown', 'div', function(e) {
var keyCode = e.keyCode || e.which;
var $self = $(this);
var esc = keyCode == 27;
var nl = keyCode == 13;
var tab = keyCode == 9;
var shift = e.shiftKey;
var sel, node, offset, text, textBefore, textAfter, range;
if(nl)
{
sel = window.getSelection();
// the node that contains the caret
node = sel.anchorNode;
// if ENTER was pressed while the caret was inside the input field
// prevent the browsers from inserting <div>, <p>, or <br> on their own
e.preventDefault();
// the caret position inside the node
offset = sel.anchorOffset;
// insert a '\n' character at that position
text = node.textContent;
textBefore = text.slice( 0, offset );
textAfter = text.slice( offset ) || ' ';
node.textContent = textBefore + '\n' + textAfter;
// position the caret after that new-line character
range = document.createRange();
range.setStart( node, offset + 1 );
range.setEnd( node, offset + 1 );
// update the selection
sel.removeAllRanges();
sel.addRange( range );
}
});
$(document).on('focus', 'div', function(e) {
var $self = $(this);
setTimeout(function() {
placeCaretAtEnd($self[0]);
},0);
});
div {
white-space: pre-wrap;
overflow-wrap: break-word;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div contenteditable>Lots of text
Lots of text
Lots of text</div>