Как установить положение курсора в элементе contenteditable(div)?
у меня есть этот простой HTML в качестве примера:
<div id="editable" contenteditable="true">
text text text<br>
text text text<br>
text text text<br>
</div>
<button id="button">focus</button>
Я хочу простую вещь-когда я нажимаю кнопку, Я хочу поместить курсор(курсор) в определенное место в редактируемом div. Из поиска в интернете у меня есть этот JS, прикрепленный к кнопке click, но он не работает (FF, Chrome):
var range = document.createRange();
var myDiv = document.getElementById("editable");
range.setStart(myDiv, 5);
range.setEnd(myDiv, 5);
можно ли установить вручную положение каретки, как это ?
5 ответов:
в большинстве браузеров, вам нужно
Range
иSelection
объекты. Вы указываете каждую из границ выбора как узел и смещение внутри этого узла. Например, чтобы установить курсор на пятый символ второй строки текста, вы должны сделать следующее:var el = document.getElementById("editable"); var range = document.createRange(); var sel = window.getSelection(); range.setStart(el.childNodes[2], 5); range.collapse(true); sel.removeAllRanges(); sel.addRange(range);
IE
пример jsFiddle : http://jsfiddle.net/timdown/vXnCM/
большинство ответов, которые вы найдете на contenteditable позиционирование курсора довольно упрощены в том, что они обслуживают только входы с простым текстом ванили. Как только вы используете html-элементы в контейнере, введенный текст разбивается на узлы и распределяется либерально по древовидной структуре.
для установки позиции курсора у меня есть эта функция, которая обходит все дочерние текстовые узлы в пределах предоставленного узла и устанавливает диапазон от начала начального узла до chars.граф символ:
function createRange(node, chars, range) { if (!range) { range = document.createRange() range.selectNode(node); range.setStart(node, 0); } if (chars.count === 0) { range.setEnd(node, chars.count); } else if (node && chars.count >0) { if (node.nodeType === Node.TEXT_NODE) { if (node.textContent.length < chars.count) { chars.count -= node.textContent.length; } else { range.setEnd(node, chars.count); chars.count = 0; } } else { for (var lp = 0; lp < node.childNodes.length; lp++) { range = createRange(node.childNodes[lp], chars, range); if (chars.count === 0) { break; } } } } return range; };
затем я вызываю процедуру с этой функцией:
function setCurrentCursorPosition(chars) { if (chars >= 0) { var selection = window.getSelection(); range = createRange(document.getElementById("test").parentNode, { count: chars }); if (range) { range.collapse(false); selection.removeAllRanges(); selection.addRange(range); } } };
диапазоне.свернуть (false) устанавливает курсор в конец диапазона. Я протестировал его с последними версиями Chrome, IE, Mozilla и Opera, и все они работают нормально.
PS. Если кто-то заинтересован, я получаю текущую позицию курсора, используя этот код:
function isChildOf(node, parentId) { while (node !== null) { if (node.id === parentId) { return true; } node = node.parentNode; } return false; }; function getCurrentCursorPosition(parentId) { var selection = window.getSelection(), charCount = -1, node; if (selection.focusNode) { if (isChildOf(selection.focusNode, parentId)) { node = selection.focusNode; charCount = selection.focusOffset; while (node) { if (node.id === parentId) { break; } if (node.previousSibling) { node = node.previousSibling; charCount += node.textContent.length; } else { node = node.parentNode; if (node === null) { break } } } } } return charCount; };
код делает противоположность функции set-он получает текущий окно.getSelection().focusNode и focusOffset и отсчитывает назад все текстовые символы, встречающиеся до тех пор, пока он не попадает в родительский узел с идентификатором containerId. Функция isChildOf просто проверяет перед запуском, что suplied узел на самом деле является дочерним элементом поставляемого parentId.
код должен работать прямо без изменений, но я только что взял его из плагина jQuery, который я разработал, поэтому взломал пару это - дайте мне знать, если что-то не работай!
это очень трудно установить каретку в правильном положении, когда у вас есть предварительный элемент, такой как (p) (span) и т. д.Цель состоит в том, чтобы получить (текст объекта):
<div id="editable" contenteditable="true">dddddddddddddddddddddddddddd<p>dd</p>psss<p>dd</p><p>dd</p> <p>text text text</p> </div> <p id='we'></p> <button onclick="set_mouse()">focus</button> <script> function set_mouse() { var as = document.getElementById("editable"); el=as.childNodes[1].childNodes[0];//goal is to get ('we') id to write (object Text) because it work only in object text var range = document.createRange(); var sel = window.getSelection(); range.setStart(el, 1); range.collapse(true); sel.removeAllRanges(); sel.addRange(range); document.getElementById("we").innerHTML=el;// see out put of we id } </script>
если вы не хотите использовать jQuery, вы можете попробовать этот подход:
public setCaretPosition() { const editableDiv = document.getElementById('contenteditablediv'); const lastLine = this.input.nativeElement.innerHTML.replace(/.*?(<br>)/g, ''); const selection = window.getSelection(); selection.collapse(editableDiv.childNodes[editableDiv.childNodes.length - 1], lastLine.length); }
editableDiv
вы редактируемый элемент, не забудьте установитьid
для него. Тогда вам нужноinnerHTML
от элемента и отрежьте все тормозные магистрали. И просто установите коллапс со следующими аргументами.
Я пишу синтаксический маркер (и базовый редактор кода), и мне нужно было знать, как автоматически вводить символ одной кавычки и перемещать курсор назад (как и многие редакторы кода в настоящее время).
вот фрагмент моего решения, благодаря большой помощи из этого потока, MDN docs и большому количеству консолей moz..
//onKeyPress event if (evt.key === "\"") { let sel = window.getSelection(); let offset = sel.focusOffset; let focus = sel.focusNode; focus.textContent += "\""; //setting div's innerText directly creates new //nodes, which invalidate our selections, so we modify the focusNode directly let range = document.createRange(); range.selectNode(focus); range.setStart(focus, offset); range.collapse(true); sel.removeAllRanges(); sel.addRange(range); } //end onKeyPress event
это в contenteditable div элемент
Я оставляю это здесь в качестве благодарности, понимая, что уже есть принятый ответ.