Как сделать поиск по сайту javascript
Перейти к содержимому

Как сделать поиск по сайту javascript

  • автор:

Организация поиска по веб-странице на JavaScript (без jQuery)

Пару дней назад получил тестовое задание от компании на вакансию Front-end dev. Конечно же, задание состояло из нескольких пунктов. Но сейчас речь пойдет только об одном из них — организация поиска по странице. Т.е. банальный поиск по введенному в поле тексту (аналог Ctrl+F в браузере). Особенность задания была в том, что использование каких-либо JS фреймворков или библиотек запрещено. Все писать на родном native JavaScript.

(Для наглядности далее буду сопровождать всю статью скринами и кодом, чтоб мне и вам было понятнее, о чем речь в конкретный момент)

Поиск готового решения

Первая мысль: кто-то уже точно такое писал, надо нагуглить и скопипастить. Так я и сделал. За час я нашел два неплохих скрипта, которые по сути работали одинаково, но были написаны по-разному. Выбрал тот, в коде которого лучше разобрался и вставил к себе на старничку.

Если кому интересно, код брал тут.

Скрипт сразу заработал. Я думал, что вопрос решен, но как оказалось, не в обиду автору скрипта, в нем был огромный недостаток. Скрипт вел поиск по всему содержимому тега . и, как вы уже наверное догадались, при поиске любого сочетания символов, которые напоминают тег или его атрибуты, ломалась вся страница HTML.

Почему скрипт работал некорректно?

Все просто. Скрипт работает следующим образом. Сперва в переменную записываем все содержимое тега body, затем ищем совпадения с регулярным выражением (задает пользователь при вводе в текстовое поле) и затем заменяем все совпадения на следующий код:

А затем заменяем текущий тег body на новый полученный. Разметка обновляется, меняются стили и на экране подсвечиваются желтым все найденные результаты.

Вы уже наверняка поняли, в чем проблема, но я все же объясню подробней. Представьте, что в поле поиска ввели слово «div». Как вы понимаете, внутри body есть множество других тегов, в том числе и div. И если мы всем к «div» применим стили, указанные выше, то это уже будет не блок, а непонятно что, так как конструкция ломается. В итоге после перезаписи разметки мы получим полностью сломанную веб-страницу. Выглядит это так.

Было до поиска: выложить фото в интернетПросмореть полностью
Стало после поиска: выложить фото бесплатноПросмореть полностью

Как видите, страница полностью ломается. Короче говоря, скрипт оказался нерабочим, и я решил написать свой с нуля, чему и посвящается эта статья.

Итак пишем скрипт с нуля

Как все у меня выглядит.

Сейчас нас интересует форма с поиском. Обвел ее красной линией.

Давайте немного разберемся. Я это реализовал следующим образом (пока чистый HTML). Форма с тремя тегами.

Первый — для ввода текста;
Второй — для для отмены поиска (снять выделение);
Третий — для поиска (выделить найденные результаты).

Итак, у нас есть поле для ввода и 2 кнопки. JavaScript буду писать в файле js.js. Предпложим, что его вы уже создали и подключили.

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

Давайте немного поясню что тут и зачем нужно.

Полю с текстом даем id=«text-to-find» (по этому id будем обращатсья к элементу из js).

Кнопке отмены даем такие атрибуты: type=«button» onclick=«javascript: FindOnPage(‘text-to-find’,false); return false;»

Тип: button
При нажатии вызывается функция FindOnPage(‘text-to-find’,false); и передает id поля с текстом, false

Кнопке поиска даем такие атрибуты: type=«button» onclick=«javascript: FindOnPage(‘text-to-find’,true); return false;»

Тип: submit (не кнопка потому, что тут можно юзать Enter после ввода в поле, а так можете и button использовать)
При нажатии вызывается функция FindOnPage(‘text-to-find’,true); и передает id поля с текстом, true

Вы наверняка заметили еще 1 атрибут: true/false. Его будем использовать для определения, на какую именно кнопку нажали (отменить поиск или начать поиск). Если жмем на отмену, то передаем false. Если жмем на поиск, то передаем true.

Окей, двигаемся дальше. Переходим к JavaScript

Будем считать, что вы уже создали и подключили js файл к DOM.

Прежде, чем начнем писать код, давайте отвлечемся и сперва обсудим, как все должно работать. Т.е. по сути пропишем план действий. Итак, нам надо, чтоб при вводе текста в поле шел поиск по странице, но нельзя затрагивать теги и атрибуты. Т.е. только текстовые объекты. Как этого достичь — уверен есть много способов. Но сейчас будем использовать регулярные выражения.

Итак, следующее регулярное выражение будет искать только текст след. вида: «>… текст. <«. Т.е. будет проходить поиск только текстовых объектов, в то время, как теги и атрибуты будут оставаться нетронутыми.

Так мы будем находить нужные части кода, которые будем парсить и искать совпадения с текстом, который ввел пользователь. Затем будем добавлять стили найденным объектам и после этого заменять html — код на новый.

Приступим. Сперва переменные, которые нам понадобятся.

И сразу определим locale_HTML значение независимо от того, ищем мы что-то или нет. Это нужно, чтоб сразу сохранить оригинал страницы и иметь взможность обнулять стили.

Ок, теперь уже стоит создать функцию, которая вызывается у нас из DOM. Сразу прикинем, что внутри у нас должны быть 2 функции, каждая из которых срабатывает в зависимости от нажатой кнопки. Ведь мы либо проводим поиск, либо обнуляем его. И контроллируется это атрибутом true/false, как вы помните. Так же надо понимать, что при повторном поиске прежние стили должны обнуляться. Таким образом получим следующее:

Ок, часть логики реализована, двигаемся дальше. Необходимо проверять полученное слово на количество символов. Ведь зачем нам искать 1 букву/символ. В общем, я решил эту возможность ограничить 3+ символа.

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

Сейчас поясню этот участок кода. Единственное, что могло стать не ясно — вот эта строка:

function FindOnPageBack()

Тут все просто: метод innerHTML возвращает html код объекта. В данном случае мы просто заменяем текущий body на оригинальный, который мы сохранили при загрузке всей страницы.

Двигаемся дальше. Даем значения основным переменным.

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

В общем, после того, как мы заменим текст и получим результат со стилями, надо текущий html заменить на полученный. Делаем.

По сути все готово, и скрипт уже работает. Но добавим еще пару деталей для красоты.

1) Обрежем пробелы у текста, который вводит пользователь. Вставляем этот код:

После этой строки:

2) Сделаем проверку на совпадения (если совпадений не найдено — сообщим об этом). Этот код вставляем внутрь функции function FindOnPageGo() после переменных.

Посмотреть исходник можно тут.
Скачать исходник можно тут.

Теперь все. Конечно, можно добавить скролл к первому найденному результату, живой поиск ajax, да и вообще улучшать можно бесконечно. Сейчас это довольно примитивный поиск по сайту. Целью статьи было помочь новичкам, если возникет такой же вопрос как у меня. Ведь простого готового решения я не нашел.

P.S.: для корректной работы необходимо убрать переносы текста в html документе в тех местах, где есть обычный текст между тегами.

Это не принципиально, можно от этих переносов избаляться автоматически на сервисе, но может подскажете заодно, как это пофиксить, если поймете раньше меня.

Также, если кто писал подобное, но с живым поиском, поделитесь исходником, будет интересно разобрать.

Буду рад выслушать конструкнтиную критику, мнения, может, рекомендации.

На днях дописал немного код, сделал живой поиск по странице. Так, что вопрос снят. Код HTML не менялся. JS можете посмотреть тут.

Поиск ведется по тегам с классом «place_for_live_search». Так что для того, чтоб алгоритм парсил нужный контент, добавляем класс и готово.

Building JavaScript Live (AJAX) Search

Jordan P. Raychev

During the past month or so I’ve been working on a personal project of mine that includes a JavaScript live search also known as AJAX search, so I decided to make an quick article out of it and guide you through it. As a disclaimer, I want to point out that this is not the most efficient way to build feature like this but it shows the general idea.

What we are going to build is shown on the image below. Our feature consists of a simple search bar and a drop-down bow where our search results are displayed. The search results are comprised of two parts — a title…

Jordan P. Raychev

Geek Culture

Written by Jordan P. Raychev

Network, system and software engineer with true passion about technology. Love to read and spend time in nature.

Vanilla JavaScript live search

Adding live search functionality to a Vanilla JavaScript project. 2020 Tutorial with code examples.

6 Nov, 2020 ·

Today we will work on a more real-world scenario, implementing a live search in JavaScript!

In our example, we will use an array of names and countries. We will then have a search bar. On input, it filters the array to showcase only matching search results.

Find the example code in this Codepen permalink

Try and search for something (e.g., Japan or Abel)

Step 1: HTML Structure for search input permalink

In today’s article, we are more focused on the JavaScript part than actual the HTML structure or styling, so a basic setup.

We use an input field on which we will base the results. And define an empty <UL> with the ID results .

Step 2: CSS styling to make it pretty permalink

As for the CSS, we added some basic styling to make it all centered with Flex and look a little bit nicer.

Step 3: JS code for the live search function permalink

Now on to the magic part. In this example, I prepared a random array of data consisting of the following structure:

Then we need to define the variables we are going to use.

The search variable is our input element, results are our ul list, and the search_term is whatever we input in our search field.

Now let’s create a JavaScript function to capture the search input.

Here we add an input listener to our search and capture the value (in lowercase), then we call a function called showList which we will build now.

In there, we start with clearing whatever is on the list already.

Now we want to loop over all our data elements:

We make use of the filter ES6 function.

In there, we want to check if the country’s name matches our search string.

As you can see, we match either on country OR (||) on the name. Now in the filter, we get a single item from our array. We then check if the value in lowercase matches (includes) our search term.

If so, we return this. Remember that filter will then modify on its own.

The last step is to append a new list item to our ul .

There you go! All that’s left is to call the method initially.

Place the following at the bottom of your scripts.

Thank you for reading this tutorial, and let’s connect! permalink

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

find words in html page with javascript

To find the element that word exists in, you’d have to traverse the entire tree looking in just the text nodes, applying the same test as above. Once you find the word in a text node, return the parent of that node.

this works in Firefox, no promises for IE.

What it does is start with the body element and check to see if the word exists inside that element. If it doesn’t, then that’s it, and the search stops there. If it is in the body element, then it loops through all the immediate children of the body. If it finds a text node, then see if the word is in that text node. If it finds an element, then push that into the queue. Keep on going until you’ve either found the word or there’s no more elements to search.

You can iterate through DOM elements, looking for a substring within them. Neither fast nor elegant, but for small HTML might work well enough.

I’d try something recursive, like: (code not tested)

You can try using XPath, it’s fast and accurate

Also if XPath is a bit more complicated, then you can try any javascript library like jQuery that hides the boilerplate code and makes it easier to express about what you want found.

Also, as from IE8 and the next Firefox 3.5 , there is also Selectors API implemented. All you need to do is use CSS to express what to search for.

You can probably read the body of the document tree and perform simple string tests on it fast enough without having to go far beyond that — it depends a bit on the HTML you are working with, though — how much control do you have over the pages? If you are working within a site you control, you can probably focus your search on the parts of the page likely to be different page from page, if you are working with other people’s pages you’ve got a tougher job on your hands simply because you don’t necessarily know what content you need to test against.

Again, if you are going to search the same page multiple times and your data set is large it may be worth creating some kind of index in memory, whereas if you are only going to search for a few words or use smaller documents its probably not worth the time and complexity to build that.

Probably the best thing to do is to get some sample documents that you feel will be representative and just do a whole lot of prototyping based around the approaches people have offered here.

    The Overflow Blog
Linked
Related
Hot Network Questions

Subscribe to RSS

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.6.8.43486

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *