Скрипт поиска по странице из поисковой строки

https://jsfiddle.net/n3ywjhxt/ - пример скрипта

На странице: поле поиска и текст на странице. Задача - найти все совпадения, которые встречаються на странице, после введения текста в поисковую строку и нажатия на кнопку Поиск

<input type = "submit" value = "Поиск">

<p class = "h2">Заголовок первый</p>
<p>Текст первого заголовка</p>

<p>Тут еще какой то текст</p>

<p class = "h2">Заголовок второй</p>
<p>Текст второго заголовка</p>

<p class = "h2">Заголовок для первого абзаца</p>
<p>Заголовок первый</p>

Скрипт для поиска:

let str = document.querySelector('.search').value;
//let str = 'Заголовок второй на https://javascript.info';
let regexp = /второй/ig;

let result;

while (result = regexp.exec(str)) {
  alert( `Найдено ${result[0]} на позиции ${result.index}` );
} 

должен работать таким образом что после того как пользователь ввел слово, которое встречается в этом тексте - ему алертом выдало это слово и количество слов которые есть на этой странице.
Вопроса 2 по этому скрипту:

  1. Как реализовать точное совпадение введенного слова из инпута (вместо этого let regexp = /второй/ig; ), почему там regexp? и есть ли другой какой то метод для поиска чтобы выбирать точные совпадения?
  2. Сделать поиск не по всем словам на странице, которые встречаються, а только по тем, которые с class = “h2”
  1. Вместо RegExp можете использовать indexOf.
  2. Получите текст всех заголовков в массив строк и делайте поиск по нему.
1 лайк

Тут трохи не зрозуміло
Все ж таки - “алертом выдало это слово и количество слов которые есть на этой странице” ?
Або як у коді
На кожне співпадіння має видаватись алерт?

Або
Чи один алерт з першим співпадінням та загальна кількість співпадінь?

Може бути щось таке;

    var searchString = 'typedValue';
    var elems = document.querySelectorAll('h2');
    var matches = 0;

    elems.forEach((elem, index) => {
      if (elem.innerText.toLowerCase().indexOf(searchString.toLowerCase()) >= 0) { 
         matches++;
      }
    });
    alert( `Слово ${searchString} найдено ${matches} раз`);

спасибо за подсказку, но если заменить regexp на indexOf - то выдает ошибку
indexOfFirst.exec is not a function
Пример кода тут https://jsfiddle.net/n3ywjhxt/2/
Или ошибка - не в замене методов, а в чем то другом?

нет, не на каждое. Alert здесь нужен для JSFiddle потому что там console.log не отображаеться, поэтому там алерт нагляднее чтобы не копировать код и не открывать у себя…
Цель задачи - найти совпадения (все которые встречаються в тексте на странице) после того как пользователь ввел слово и нажал на кнопку Поиск. Вместо заданного примера в переменной
var searchString = ‘typedValue’;
задать значение в эту переменную слово которое будет вводить пользователь:
var searchString = document.querySelector(‘.search’).value;

Вот на этом этапе не понимаю как сделать. Результатом должно быть одно или несколько слов (в зависимости от того что ввел пользователь, если ввел слово “Заголовок” - то в консоль должно три слова Заголовок выпасть (потому что 3 раза встречаеться в h2), если ввел “второй” - то только одно).
Результатом работы скрипта в дальнейшем должна быть манипуляция с DOM (если слово в тексте найдено - значит его отметить, например жирным шрифтом). Это сейчас пример с алертом - чтобы упростить задачу (разбить на подзадачи).

Працюємо з клік івентом сабміту та запускаємо функцію пошуку.
Виводимо кількість знайдених елементів.
щось таке?

1 лайк

щось таке, дякую…
Додала до цього скрипта роботу з ДОМ (додавання кольору до всіх знайдених співпадінь, але чомусь застосовується колір тільки до першого знайденого співпадіння (хоча співпадінь знаходить 3 штуки)
https://jsfiddle.net/5xnqfcvw/
Там потрібно також циклом присвоювати? (для змінної де присвоюється колір - перебирати елементи циклом), але хоча і там і там цикл…навіщо їх аж два… Чи причина не в цьому?

Да, присваивать тоже придется в цикле, но не обязательно создавать еще один. У тебя ведь уже есть цикл, в котором ты проверяешь строки на совпадение:

    if (elem.innerText.toLowerCase().indexOf(searchString.toLowerCase()) >= 0) {
       matches++;
    }

Также обрати внимание, что у тебя вот тут происходит:

  var matches = 0;
  var match = document.querySelector('p');

...

  matches = match;
  match.style.color = "red";

matches - это счетчик совпадений
match - это первый элемент p на странице (при этом он никогда не меняется). Ты присваиваешь одно другому и потом назначаешь ему цвет, поэтому всегда будет подсвечиваться только первый p.

Попробуй написать сама, если не получится, посмотри cюда

А также:

  1. Как вернуть цвет строки обратно, если мы введем другое значение для поиска?
  2. Что если в одной строке искомое значение встречается несколько раз (текст текст)?
1 лайк

почему создала еще одну переменную для цвета текста, - потому что нельзя применить его для переменной matches
Если записать
var matches = document.querySelector(‘p’); – тогда не присваивает цвет вообще нигде


спасибо за ответ

это уже совсем вместо меня задачу сделали)))
интереснее было самостоятельно поковырять почему не работает
Ок, хорошо, спасибо

Если записать
var matches = document.querySelector(‘p’); – тогда не присваивает цвет вообще нигде

Ну конечно, matches - это же просто счетчик совпадений. Просто число.

Ну я же потому и написал, “Сначала попробуй сама” 😂

После того как значение найдено в строке поиска (подсвечено красным), если стереть из строки искомое слово и ввести заново другое - скрипт срабатывает так что первое совпадение становится черным как и было раньше, а новое - выделяется красным. Там уже ничего дописывать в работу этого скрипта не надо. Или я не понимаю вопрос.

оно находит один раз и подсвечивает всю строку… https://jsfiddle.net/c3mu69yh/
я тогда тут не понимаю почему скрипт не выдает 2 совпадения.

тот есть если переменной изначально задавать числовое значение, а потом повторно навешать на нее стили - то она воспринимаеться как число? (а числу стиль применить нельзя). То есть одной переменной нельзя присваивать 2 разных значения - числовое и нечисловое (ДОМ-узел)?

Одной переменной можно присваивать разные значения, но это в любом случае будет либо DOM-элемент, либо число. DOM-элементу можно навешивать стиль. Числу - нельзя.

вот тут
elem.innerText.toLowerCase().indexOf(searchString.toLowerCase()) >= 0
ты же не проверяешь, сколько раз встречается совпадение. Просто проверяешь, что оно есть.

но мы же не знаем сколько раз будет встречаться одно и то же слово в одном предложении. По этому не можем написать условие
elem.innerText.toLowerCase().indexOf(searchString.toLowerCase()) > 1
Или там надо как то проверять - что если в innerText который относиться к селектору .h2 - и подставлять это условие elem.innerText.toLowerCase().indexOf(searchString.toLowerCase()) > 1
?
Или вообще не то?

Да, тебе нужно проверять содержимое innerText, но indexOf в том виде, в котором ты его используешь, не подходит, потому что он возвращает только первое совпадение. Грубо говоря, показывает тебе, есть ли в строке то, что ты ищешь, или нет.

Попробуй посмотреть сюда. Вполне себе подходящий пример, как мне кажется.

Добавила это в коде https://jsfiddle.net/c3mu69yh/1/
В итоге - на этой строке
elem.indexOf(searchString, matches + 1);
выдает ошибку что
elem.indexOf is not a function
Что здесь имеется ввиду? Оно же elem.indexOf не есть функцией, а присваивание какого то метода. Почему в консоли определяется как функция?