Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   модифицировать скрипт поиска (https://javascript.ru/forum/project/71246-modificirovat-skript-poiska.html)

JAMLIGHT 04.11.2017 11:08

модифицировать скрипт поиска
 
данный код рассматривался не раз на данном сайте,однако решения небыло найдено.Задача-модифицировать скрипт поиска таким образом ,чтобы поиск происходил только по тексту контента страницы,например только в тегах h1 или p.В данном скрипте ниже наблюдается поломка кода HTML,содержащего текст,например ломаются атрибуты title и alt картинок на странице в своих текстовых значениях.
<script type="text/javascript">
var lastResFind=""; // последний удачный результат
var copy_page=""; // копия страницы в исходном виде
function TrimStr(s) {
     s = s.replace( /^\s+/g, '');
  return s.replace( /\s+$/g, '');
}
function FindOnPage(inputId) {//ищет текст на странице, в параметр передается ID поля для ввода
  var obj = window.document.getElementById(inputId);
  var textToFind;
 
  if (obj) {
    textToFind = TrimStr(obj.value);//обрезаем пробелы
  } else {
    alert("Введенная фраза не найдена");
    return;
  }
  if (textToFind == "") {
    alert("Вы ничего не ввели");
    return;
  }
  
  if(document.body.innerHTML.indexOf(textToFind)=="-1")
  alert("Ничего не найдено, проверьте правильность ввода!");
  
  if(copy_page.length>0)
        document.body.innerHTML=copy_page;
  else copy_page=document.body.innerHTML;

  if (textToFind.length < 3) {
    alert("Введите не менее 3-х символов!");
    return;
  }
  document.body.innerHTML = document.body.innerHTML.replace(eval("/name="+lastResFind+"/gi")," ");//стираем предыдущие якори для скрола
  document.body.innerHTML = document.body.innerHTML.replace(eval("/"+textToFind+"/gi"),"<a name="+textToFind+" style='background:grey'>"+textToFind+"</a>"); //Заменяем найденный текст ссылками с якорем;
  lastResFind=textToFind; // сохраняем фразу для поиска, чтобы в дальнейшем по ней стереть все ссылки
  window.location = '#'+textToFind;//перемещаем скрол к последнему найденному совпадению
 } 
</script>
<h2>JavaScript поиск по странице</h2>
<input type="text" id="text-to-find" value=""> 
<input type="button" onClick="javascript: FindOnPage('text-to-find'); return false;" value="Искать"/>
<br/><i>Введите слово или фразу для поиска.</i>
<hr/>

JAMLIGHT 05.11.2017 12:26

Если document.body заменить на document.getElementById("") тогда возвращает только один элемент, т.к. id должен быть уникален.Если подставить document.querySelectorAll('.one') то почему то не работает.Где ошибка?
<!doctype html>
<html>
<head>
<script type="text/javascript">
var lastResFind=""; // последний удачный результат
var copy_page=""; // копия страницы в исходном виде
function TrimStr(s) {
     s = s.replace( /^\s+/g, '');
  return s.replace( /\s+$/g, '');
}
function FindOnPage(inputId) {//ищет текст на странице, в параметр передается ID поля для ввода
  var obj = window.document.getElementById(inputId);
  var textToFind;
 
  if (obj) {
    textToFind = TrimStr(obj.value);//обрезаем пробелы
  } else {
    alert("Введенная фраза не найдена");
    return;
  }
  if (textToFind == "") {
    alert("Вы ничего не ввели");
    return;
  }
  
  if(document.querySelectorAll('.one').innerHTML.indexOf(textToFind)=="-1")
  alert("Ничего не найдено, проверьте правильность ввода!");
  
  if(copy_page.length>0)
        document.querySelectorAll('.one').innerHTML=copy_page;
  else copy_page=document.querySelectorAll('.one').innerHTML;

  if (textToFind.length < 3) {
    alert("Введите не менее 3-х символов!");
    return;
  }
  document.querySelectorAll('.one').innerHTML = document.querySelectorAll('.one').innerHTML.replace(eval("/name="+lastResFind+"/gi")," ");//стираем предыдущие якори для скрола
  document.querySelectorAll('.one').innerHTML = document.querySelectorAll('.one').innerHTML.replace(eval("/"+textToFind+"/gi"),"<a name="+textToFind+" style='background:grey'>"+textToFind+"</a>"); //Заменяем найденный текст ссылками с якорем;
  lastResFind=textToFind; // сохраняем фразу для поиска, чтобы в дальнейшем по ней стереть все ссылки
  window.location = '#'+textToFind;//перемещаем скрол к последнему найденному совпадению
 } 
</script>
</head>
<body>


<body>
<h2>JavaScript поиск по странице</h2>
<input type="text" id="text-to-find" value=""> 
<input type="button" onClick="javascript: FindOnPage('text-to-find'); return false;" value="Искать"/>
<br/><i>Введите слово или фразу для поиска.</i>
<hr/>


      <p class="one">
      text1 content content content content content content content content  content content content content content content content content content
      </p>
      <p class="one">
      text2 content content content content content content content content  content content content content content content content content content
      </p>
      <p class="one">
      text3 content content content content content content content content  content content content content content content content content content
      </p>
      <p class="one">
      text4 content content content content content content content content  content content content content content content content content content
      </p>      

</body>
</html>

laimas 05.11.2017 12:45

Цитата:

Сообщение от JAMLIGHT
Где ошибка

querySelectorAll() возвращает объект типа NodeList, у которого нет метода innerHTML.

JAMLIGHT 05.11.2017 12:51

окей, что делать? Как сделать выборку? пробовал getElementsByClassName() тоже не работает и тоже возвращает обьект типа NodeList.Какие варианты?

рони 05.11.2017 13:02

Цитата:

Сообщение от laimas
Какие варианты?

цикл по списку элементов

laimas 05.11.2017 13:08

Цитата:

Сообщение от JAMLIGHT
что делать?

https://developer.mozilla.org/ru/docs/Web/API/NodeList

JAMLIGHT 05.11.2017 15:16

не имею опыта перебирать в цикле.Могу найти только по индексу тега

laimas 05.11.2017 15:27

Цитата:

Сообщение от JAMLIGHT
не имею опыта перебирать в цикле.Могу найти только по индексу

Ну так итератор цикла и будет индексом элемента в наборе, используйте цикл for.

JAMLIGHT 05.11.2017 16:32

перебрал, нашёл ,что дальше?
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>
    <div>
        <h3>p теги с текстом</h3>
        <p>Первый абзац</p>
        <p>Второй абзац</p>
    </div>
<script>
var pElements = document.getElementsByTagName("p");
 
for (var i = 0; i < pElements.length; i++) {
    alert("Текст параграфа: " + pElements[i].innerText + " нашёл");
}
</script>
</body>
</html>

laimas 05.11.2017 18:39

Цитата:

Сообщение от JAMLIGHT
что дальше?

А чего надо? Вы пытались вставить в коллекцию, теперь знаете как. Только хотя innerText и поддерживается теперь не только IE, это свойство не считается стандартным и будет ли таковым не известно. Лучше не его использовать, а textContent.

JAMLIGHT 05.11.2017 18:44

так правильно?
<script type="text/javascript">
var pElements = document.getElementsByTagName("p");
 
for (var i = 0; i < pElements.length; i++) {
    document.getElementsByTagName("p").innerHTML = document.getElementsByTagName("p").innerHTML.replace(eval("/name="+lastResFind+"/gi")," ");//стираем предыдущие якори для скрола;
    document.getElementsByTagName("p").innerHTML = document.getElementsByTagName("p").innerHTML.replace(eval("/"+textToFind+"/gi"),"<a name="+textToFind+" style='background:grey'>"+textToFind+"</a>"); //Заменяем найденный текст ссылками с якорем;
}
var lastResFind=""; // последний удачный результат
var copy_page=""; // копия страницы в исходном виде
function TrimStr(s) {
     s = s.replace( /^\s+/g, '');
  return s.replace( /\s+$/g, '');
}
function FindOnPage(inputId) {//ищет текст на странице, в параметр передается ID поля для ввода
  var obj = window.document.getElementById(inputId);
  var textToFind;
 
  if (obj) {
    textToFind = TrimStr(obj.value);//обрезаем пробелы
  } else {
    alert("Введенная фраза не найдена");
    return;
  }
  if (textToFind == "") {
    alert("Вы ничего не ввели");
    return;
  }
  
  if(document.getElementsByTagName("p").innerHTML.indexOf(textToFind)=="-1")
  alert("Ничего не найдено, проверьте правильность ввода!");
  
  if(copy_page.length>0)
        document.getElementsByTagName("p").innerHTML=copy_page;
  else copy_page=document.getElementsByTagName("p").innerHTML;

  if (textToFind.length < 3) {
    alert("Введите не менее 3-х символов!");
    return;
  }

  lastResFind=textToFind; // сохраняем фразу для поиска, чтобы в дальнейшем по ней стереть все ссылки
  window.location = '#'+textToFind;//перемещаем скрол к последнему найденному совпадению
 } 
</script>
<body>
<h2>JavaScript поиск по странице</h2>
<input type="text" id="text-to-find" value=""> 
<input type="button" onClick="javascript: FindOnPage('text-to-find'); return false;" value="Искать"/>
<br/><i>Введите слово или фразу для поиска.</i>
<hr/>


    <div>
        <h3>p теги с текстом</h3>
        <p>Первый абзац С помощью вызова document.getElementsByTagName("p") находим все элементы параграфов. Этот вызов возвращает массив найденных элементов. Поэтому, чтобы получить отдельные элементы массива, необходимо пробежаться по ним в цикле.С помощью вызова document.getElementsByTagName("p") находим все элементы параграфов. Этот вызов возвращает массив найденных элементов. Поэтому, чтобы получить отдельные элементы массива, необходимо пробежаться по ним в цикле.</p>
        <p>Второй абзац С помощью вызова document.getElementsByTagName("p") находим все элементы параграфов. Этот вызов возвращает массив найденных элементов. Поэтому, чтобы получить отдельные элементы массива, необходимо пробежаться по ним в цикле.С помощью вызова document.getElementsByTagName("p") находим все элементы параграфов. Этот вызов возвращает массив найденных элементов. Поэтому, чтобы получить отдельные элементы массива, необходимо пробежаться по ним в цикле.</p>
        <p>Третий абзац С помощью вызова document.getElementsByTagName("p") находим все элементы параграфов. Этот вызов возвращает массив найденных элементов. Поэтому, чтобы получить отдельные элементы массива, необходимо пробежаться по ним в цикле.С помощью вызова document.getElementsByTagName("p") находим все элементы параграфов. Этот вызов возвращает массив найденных элементов. Поэтому, чтобы получить отдельные элементы массива, необходимо пробежаться по ним в цикле.</p>
    </div>

</script>

laimas 05.11.2017 18:50

Цитата:

Сообщение от JAMLIGHT
так правильно?

То есть прежние разговоры о том, что коллекция не обладает свойством innerHTML и:

document.getElementsByTagName("p").innerHTML=copy_ page;
copy_page=document.getElementsByTagName("p").inner HTML;

так нельзя, ни к чему, и нужно заново повторять?

JAMLIGHT 05.11.2017 18:58

там
if(copy_page.length>0)
        document.getElementsByTagName("p").innerHTML=copy_page;
        else copy_page=document.getElementsByTagName("p").innerHTML;

laimas 05.11.2017 19:05

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

JAMLIGHT 05.11.2017 19:06

Цитата:

Сообщение от laimas (Сообщение 469273)
То есть прежние разговоры о том, что коллекция не обладает свойством innerHTML

А какая обладает?

JAMLIGHT 05.11.2017 19:09

Цитата:

Сообщение от laimas (Сообщение 469276)
Если коллекция элементов, то получить/изменить ее свойство innerHTML можно только обратившись к каждому ее элементу, то есть обходом коллекции в цикле.

Поясните кодом.Там вроде как изменяется только найденный из цикла элемент.

JAMLIGHT 05.11.2017 19:13

Цитата:

Сообщение от laimas (Сообщение 469273)
То есть прежние разговоры о том, что коллекция не обладает свойством innerHTML

тоесть выражение document.getElementsByTagName("p").innerHTML -это бред?

laimas 05.11.2017 19:15

Цитата:

Сообщение от JAMLIGHT
А какая обладает?

Никакая, у <p>1</p> можно получить/изменить значение этого свойства, а у набора <p>1</p><p>2</p><p>3</p>..., сразу у всех нет.

laimas 05.11.2017 19:20

Цитата:

Сообщение от JAMLIGHT
document.getElementsByTagName("p").innerHTML -это бред?

Полный, так как вернет undefined, а при попытки изменения ничего не произойдет.

JAMLIGHT 05.11.2017 19:21

окей, как обратиться в цикле?

laimas 05.11.2017 19:25

А это нечто иное?

JAMLIGHT 05.11.2017 20:55

так тоже не работает
var pElements = document.getElementsByTagName("p");
 
for (var i = 0; i < pElements.length; i++) {
    pElements[i].innerHTML = pElements[i].innerHTML.replace(eval("/name="+lastResFind+"/gi")," ");//стираем предыдущие якори для скрола;
    pElements[i].innerHTML = pElements[i].innerHTML.replace(eval("/"+textToFind+"/gi"),"<a name="+textToFind+" style='background:grey'>"+textToFind+"</a>"); //Заменяем найденный текст ссылками с якорем;

laimas 06.11.2017 00:20

JAMLIGHT,
оно в любом случае не будет работать корректно даже если и записать это правильно.

Это можно назвать принципом поиска, но далеко не готовым кодом для этого и вот почему.

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

Таким образом если изначально в параграфах был текст, то с каждым запросом он засоряется html-тегами от предыдущего поиска. А что будет если найти нужно будет сочетания слов одно из которых при этом будет обрамлено таким тегом? А если в "боевых условиях", где содержимое параграфов не гарантия "чистого текста", а различные html теги? А может получится в итоге ужас на странице.

<html>
<head>
<meta charset="utf-8">
<body>

<p>какой-то текст с чем-то <a name="для" style="background:grey">для</a> поиска</p>
<p>какой-то текст с чем-то <a name="для" style="background:grey">для</a> поиска</p>

<script>
var pElements = document.getElementsByTagName("p"),
    lastResFind = "для",
    textToFind = "чем-то",
    last = new RegExp('name="'+lastResFind+'"', 'gi'),
    find = new RegExp(textToFind, 'gi');
  
for (var i = 0; i < pElements.length; i++) {
    pElements[i].innerHTML = pElements[i].innerHTML.replace(last, " ").replace(find, '<a name="'+textToFind+'" style="background:grey">'+textToFind+'</a>');
}

</script>
</body>
</html>

JAMLIGHT 06.11.2017 06:30

Ну мне бы под свои нужды хотя бы. У меня в тегах p чистый текст будет.Тоесть скрипт очищает только текст якоря , а теги якоря остаются?А что делает данный код
pElements[i].innerHTML = pElements[i].innerHTML.replace(eval("/name="+lastResFind+"/gi")," ");//стираем предыдущие якори для скрола;
?Ну это если только до перезагрузки страницы .Ясно, что можно придумать?

laimas 06.11.2017 06:59

Цитата:

Сообщение от JAMLIGHT
что можно придумать?

Удалять нужно теги подсветки прежнего поиска:

<html>
<head>
<meta charset="utf-8">
<style>
.higlight {
    background-color: #8FDB83;
}
</style>
</head>
<body>

<p>какой-то текст с чем-то <a class="higlight">для</a> поиска</p>
<p>какой-то текст с чем-то <a class="higlight">для</a> поиска</p>

<script>
var pElements = document.getElementsByTagName("p"),
    lastResFind = "для",
    textToFind = "чем-то",
    last = new RegExp('<a.+>'+lastResFind+'</a>', 'gi'),
    find = new RegExp(textToFind, 'gi');
  
for (var i = 0; i < pElements.length; i++) {
    pElements[i].innerHTML = pElements[i].innerHTML.replace(last, lastResFind).replace(find, '<a class="higlight">'+textToFind+'</a>');
}

</script>
</body>
</html>


Атрибут name тегу не добавлять, а только класс, которому в CSS определять цвет подсветки.

JAMLIGHT 06.11.2017 08:17

без атрибута name не будет перемещения к якорю

laimas 06.11.2017 08:18

Ну добавляйте, только каждое имя должно быть уникально.

JAMLIGHT 06.11.2017 08:20

соберите код воедино.Я не пишу на яваскрипте и синтаксиса не знаю.Задача модифицировать скрипт,Подсказки мне что русскому на китайском

laimas 06.11.2017 08:25

Цитата:

Сообщение от JAMLIGHT
хотябы некорректно бы работало

Пример, что я показал работает? Выбрасывайте eval(...), заменяя на RegExp как показано. Определяйте при вставке и имена, но учтите, если в имя вставляется текст поиска, то значение тега нужно обрамлять кавычками как показано, иначе при поиске сочетаний будут проблемы.

Все. Далее можете в сети более глубоко углубиться в тему, например тут:

https://habrahabr.ru/sandbox/101260/
https://habrahabr.ru/post/257025/

Под jQuery есть готовый плагин http://johannburkard.de/blog/program...ry-plugin.html

JAMLIGHT 06.11.2017 08:42

обрывок кода подсветки работает,но надо его прикрутить ещё к общей обьектой модели кода модуля поиска

JAMLIGHT 06.11.2017 08:47

Цитата:

Сообщение от laimas (Сообщение 469343)

как раз таки опять там document.body.innerHTML ,который ломает разметку

JAMLIGHT 06.11.2017 09:03

[quote=laimas;469343]
https://habrahabr.ru/post/257025/

/QUOTE]

это интересное решение на Jquery. Обычно и пользуюсь Jquery. Просто заинтересовало решение на Javascript

laimas 06.11.2017 09:12

Цитата:

Сообщение от JAMLIGHT
document.body.innerHTML ,который ломает разметку

Это всего лишь свойство, а "поломается" ли что-то при его использовании зависит только от вас.

JAMLIGHT 06.11.2017 09:24

дауж .Особенно от моих навыков кодить на языке Яваскрипт. Использовал решение на Jquery-работает.Спасибо

JAMLIGHT 06.11.2017 15:21

А что делать если у меня контент в айфрейме и скрипт не может прокрутить скролл страницы до нужного места так как крутит скролл айфрейма? это новую тему создавать?


Часовой пояс GMT +3, время: 15:58.