I am trying to find a way to programatically select specific text within a contenteditable div and not having any luck. For textarea and input fields, I do this easily as follows;
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.log("Word(s) not found in text");
}
} else {
console.log("No text to search");
}
but I have not been able to figure out how to do this in a contenteditable div. There are many examples of selecting the entire contents but not specific text based on indexes. I know how to get highlighted text in a div but I just can't figure out how I can highlight it programatically. I've spent a bunch of time just highlighting a piece of text in the div and looking through the properties to see if I could use that to figure this out but I'm hitting a dead end. I can't imagine there isn't a way to do this. I'm hoping someone has done this and can offer some assistance. Thanks,
You can do it like this (went a little overboard with the example).
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?
I know this wasn't in your original code, but I wanted to give you an example which would work with whatever you enter within your contenteditable
element - that's what the inputs and the button for.