Я пытаюсь найти способ программно выбрать определенный текст в редактируемом div, но мне не повезло. Для текстовой области и полей ввода я легко делаю это следующим образом:
const el = document.getElementById("some_input_field");
const words = "Find me";
searchText = el.value; //Would use el.textContent for contenteditable div, not innerHTML
if (searchText !== "") {
foundPosition = findText(searchText, words); //Returns the start and end index of the first match ie: [5,14]
if (foundPosition != []) {
el.focus();
el.setSelectionRange(foundPosition[0], foundPosition[1]); //This is where i want to highlight the text
} else {
console.info("Word(s) not found in text");
}
} else {
console.info("No text to search");
}
но я не смог понять, как это сделать в редактируемом div. Существует множество примеров выделения всего содержимого, а не конкретного текста, на основе индексов. Я знаю, как выделить текст в div, но просто не могу понять, как выделить его программно. Я потратил кучу времени, просто выделяя фрагмент текста в div и просматривая свойства, чтобы посмотреть, смогу ли я использовать это, чтобы понять это, но я зашел в тупик. Я не могу себе представить, что нет способа сделать это. Я надеюсь, что кто-то сделал это и может предложить некоторую помощь. Спасибо,
Вы можете сделать это так (с примером немного переборщил).
const div = document.querySelector("div");
const btn = document.querySelector("button");
const inp = document.querySelector("#txt");
const chkCase = document.querySelector("#chkCase");
btn.addEventListener("click",function() {
let txt = inp.value;
if (txt) {
find(txt,div);
}
});
function find(needle, haystack) {
let sel = window.getSelection();
let range = document.createRange();
let state = chkCase.checked;
let hayTxt = haystack.textContent;
if (!state) {
hayTxt = hayTxt.toLowerCase();
needle = needle.toLowerCase();
}
if (hayTxt.indexOf(needle) >= 0) {
range.setStart(haystack.childNodes[0], hayTxt.indexOf(needle));
range.setEnd(haystack.childNodes[0], hayTxt.indexOf(needle) + needle.length);
sel.removeAllRanges();
sel.addRange(range);
}
}
<div contenteditable = "true">Where's Waldo? Where in the world is Carmen Sandiego? They both say "Find me". Well, maybe not Carmen.</div>
<button type = "button">Find</button>
<input type = "text" name = "txt" id = "txt" value = "Find me">
<input type = "checkbox" name = "chkCase" id = "chkCase" value = "1" checked>Case sensitive?
Я знаю, что этого не было в вашем исходном коде, но я хотел дать вам пример, который будет работать со всем, что вы вводите в свой элемент contenteditable
— для этого нужны входные данные и кнопка.
Возможно, вам подойдет что-то вроде этого: stackoverflow.com/questions/75323101/…
Это абсолютно идеально и работает именно так, как ожидалось. Я столкнулся с проблемой, из-за которой это не работает, если в редактируемых элементах div есть теги <span> или <p>. Например, если у меня есть пустой элемент div и я набираю предложение, выделение работает, если я вставляю необработанный текст, это не удается, поскольку вставка создает тег диапазона. Мне придется поиграть, чтобы понять, как с этим справиться. Я обнаружил, что когда-нибудь у меня может быть несколько тегов диапазона, с которыми мне придется иметь дело.