Я сделал скрипт поиска по странице, вродебы все норм но есть одно но. А именно то что например если в поле поиска ввести "div"(или любой другой тег, или любой атрибут тега\тегов) скрипт выделит этот тег и "сломается" html код страницы.
Sergo Zar, всё верно – если тип 1 Node.ELEMENT_NODE – надо внутрь него рекурсивно заглядывать той же функцией и перебирать его childNodes. А если тип 3 Node.TEXT_NODE – искать - оборачивать в тег.
Сергей Соколов, либо я чтото не правильно понял, либо я тупой
Как мне тогда выделить текст, если я его найду, ведь в текстовом узле может же быть текстовый узел, напрмер <b> и если искать b то тоже html "сломается"?
Внутри текстового узла не будет других элементов. Например содержание диваThis <b>is</b> textэто три узла: текстовый "This ", элемент, и снова текстовый " text".
Примерно так предлагаю:
const parseNode = (node, search, replace) => {
node.childNodes.forEach((subnode) => {
if (subnode.nodeType === Node.ELEMENT_NODE) {
parseNode(subnode, search, replace); // рекурсия!
} else if (subnode.nodeType === Node.TEXT_NODE) {
// работаем с только-текстом
const parts = subnode.textContent.split(search);
if (0 === parts.length) return;
const content = parts.reduce((acc, c, i, arr) => {
acc.push(document.createTextNode(c));
if (i < arr.length - 1) acc.push(replace.cloneNode(true));
return acc;
}, []);
subnode.replaceWith(...content);
}
})
}
// использовать:
const findText = "will"; // для примера
// создать образец обёрнутого в тег поискового текста
const replace = document.createElement('span');
replace.className = 'mark';
replace.textContent = findText;
parseNode(document.querySelector('.text7'), findText, replace);
Sergo Zar, да, тут нужно пояснить. Вот есть у нас текстовый узел - в нём только строка текста и в ней встречается искомая строка ("is") один или несколько раз: "thisis a test".
Чтобы выделить подстроку, заменю её на копии готового узла <span class="mark">is</span> и получится колбаса, где чередуются просто-текстовые узлы с не-искомым текстом и узлы элементов, заменившие собой подстроку:
this is a test
--^^-^^-------
[text("th"), el("is"), text(" "), el("is"), text(" a test")]
Чтобы это сделать, разбиваю исходный текст в массив, используя поисковую строку как разделитель. Так получится массив из только-текстовых кусков. Каждый становится отдельным текстовым узлом. А между ними, в каждом пробеле, нужно вставить копию узла Элемента - обёртки вокруг строки поиска.
Тут и помогает reduce() – «уменьшитель» – метод, который из массива делает на выходе какой-то единственное значение. В данном случае я собираю на выход другой массив. Вставляю каждый встреченный текст - как текстовый узел. И если это ещё не последний элемент, то добавляю доп. элемент – обёртку вокруг поисковой строки:
// вход:
[t, t, t]
// выход:
[T, E, T, E, T]
Ну и в конце исходный только-текстовый узел заменяю на колбасный набор этих узлов.
Sergo Zar, твой скрин картинкой ничего не поясняет. Мой код работает — я его проверял.
Сделай jsFiddle, демонстрирующий проблему. Ну и хоть немного попытайся сам разобраться – тут мы помогаем друг другу, а не делаем работу за лентяя.