Как сделать поиск с подсказками?

Всем привет!

Есть задача реализовать поисковую строку на сайте, которая бы работал не просто как поиск, а при попытке введении запроса выдавала бы подсказки-ссылки на конкретные разделы сайта. Соответственно переход в итоге должен осуществляться на конкретный раздел, а не на список релевантных страниц.

Например, начинает пользователь вводить в строке «до...», и тут появляется всплывающее окно (аля подсказки Яндекса) с возможными вариантами: "дом в пригороде", "домашняя мебель", "домашние животные" — это все существующие разделы сайта, пользователю потребуется что-то выбрать.

Можно ли такое реализовать, какие сниппеты использовать?

Заранее спасибо за ответы!
Сергей
Сергей
28 июля 2015, 07:33
modx.pro
16 971

Комментарии: 18

Василий Наумкин
28 июля 2015, 10:46
Платный mSearch2 это умеет. Проверить можно на этом сайте, в строке поиска справа.
Максим Кузнецов
28 июля 2015, 10:51
— Через jquery на событие keyup вешается функция отправки уже введенных пользователем данных при помощи ajax'a на php-скрипт (+ здесь же можно реализовать проверку того, что алгоритм начнет работать только если пользователь ввел 3 или более символов)
— Пишется пхп, который находит в базе данных или из введенного вами перечня (можно даже из файла) подходящие результаты.
— Через аякс возвращаются результаты.

Пример:
<form id="form">
	<input type="text" id="searchForm">
	<ul id="searchHelper" style="display: none;"></ul>
</form>

<script type="text/javascript">
	$('#searchForm').keyup(function(){
		if($(this).val().length>3){
			//заместо адреса можно перенаправлять на текущую страницу, при условии что на ней вызывается сниппет, перехватывающий ajax-значения
			$.get('адрес_до_пхп_файла',{'query':$(this).val()},function(data){
				data = eval('('+data+')');
				if(data.length!=undefined && data.length>0){
					$("#searchHelper").html('');
					for(i in data){
						$('#searchHelper').append('<li>'+data[i]+'</li>');
					}
					$('#searchHelper').css('display', 'block');
				}
			});
		}
	});

	$('#searchHelper > li').live('click',function(){
		$('#searchForm').val($(this).text());
		$('#form').submit();
	});

</script>
    Сергей
    28 июля 2015, 21:41
    То что надо! Спасибо!
    Роман Садоян
    28 июля 2015, 11:49
    Делал через jQuery.autocomplete, но предварительно распарсил базу по ключам, для вывода связанных ключей:
    --Ключ1:
    ---------Ключ1.1
    ---------Ключ1.2
    --------------------Ключ 1.2.1
    --------------------Ключ 1.2.2
    --------------------Ключ 1.2.3
    ---------Ключ1.3
    --Ключ2
    --Ключ3
    Делал давно еще на Evo, буквально неделю переносил подобное на Revo.
    Делал при помощи своего снипета, форму вывел через AjaxForm
      Сергей
      28 июля 2015, 21:41
      Ага, понял, что jQuery.autocomplete — то что нужно, спасибо!
      Сергей
      29 июля 2015, 06:56
      В итоге решил остановиться на варианте с использованием jQuery.autocomplete — пока получается:

      <script>
      	$(function() {
      		$("#tags").autocomplete({
      		source: tags.php,
      		minLength: 3
      		});
      	});
      </script>
      <input class="input_window" type="text" id="tags" />

      Теперь вопрос:
      1. Как мне в tags.php запихнуть массив с тегами, которые задаются в админке при создании новой страницы через дополнительное поле.
      2. Как реализовать действие, чтобы при нажатии на пункт (тег) в выпадающем поле автоподстановки, загружалась страница с соответствующим тегом?

      Заранее спасибо!
        Максим Кузнецов
        29 июля 2015, 08:05
        1. Вам необходимо в файле вызвать службы модкса, после чего реализовать выборку.
        <?php
        	define('MODX_API_MODE', true);
        
        	require 'адрес_до_корневого_index.php_модкс';
        	
        	// Запускает нужные службы MODX
        	$modx->getService('error','error.modError');
        	$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
        	$modx->setLogTarget(XPDO_CLI_MODE ? 'ECHO' : 'HTML');
        
        	//здесь запускаем сниппет, который вернет нам результаты (например, tagLister)

        2. Опять же tagLister, как вариант. Или можно создать отдельную страницу с поиском по тегам, например вот так.
          Сергей
          29 июля 2015, 08:33
          //здесь запускаем сниппет, который вернет нам результаты (например, tagLister)
          Вот здесь можно подробнее? Я представляю себе это как обращение к БД, где можно вытащить массив нужного доп. поля, но как это сделать — ума не приложу.

          Спасибо.
            Максим Кузнецов
            29 июля 2015, 08:42
            Допустим, у нас есть сниппет, который потенциально может иметь вид: [[!name@config? &param1=`value1` &param2=`value2`]]. Вот как его вызов можно транспонировать в код:

            <?php
            	//объявляем массив параметров сниппета name:
            	$allParams = array();
            	
            	//если у сниппета есть параметры, вынесенные в системные наборы параметров c названием config:
            	$configProperty = $modx->getObject('modPropertySet', array ('name' => 'config')); 
            	$allParams = $configProperty->getProperties();
            	
            	//перечисляем обычные параметры сниппета для вызова:
            	$allParams['param1'] = 'value1';
            	$allParams['param2'] = 'value2';
            
            	//запускаем сниппет name с заданным массивом параметров:
            	$result = $modx->runSnippet('name', $allParams);
            
            	//возвращаем
            	return $result;

            — Т.е. вы можете писать как прямые запросы к базе через pdo (об этом лучше почитать отдельно), так и запускать через php целенаправленные сниппеты и возвращать результат.
      Сергей
      30 июля 2015, 02:58
      В общем заработало у меня вот как:

      <script>
      	$(function() {
      		var availableTags = [
      			[[pdoResources? &tpl=`tplTags` &limit=`0` &depth=`0` &parents=`1` &includeTVs=`tag`]]
      		];
      		$( "#tags" ).autocomplete({
      		source: availableTags,
      		minLength: 2,
      		select:function(e,ui) {
      			location.href = ui.item.the_link;              
      			}
      		});
      	});
      </script>
      Чанк tplTags содержит:

      {label:"[[+tv.tag]]", the_link:"/[[~[[+id]]]]"},

      И все бы хорошо, но теперь встали следующие два вопроса:

      1. Как вынести этот скрипт в файл .js? (pdoResources из файла .js не запускается)
      2. Если пользователь вбивает значение, отсутствующее в tv.tag, как вывести сообщение аля: «По Вашему запросу ничего не найдено»?

      Спасибо!
        Максим Кузнецов
        30 июля 2015, 03:42
        1. Ajax. Или оставлять в шаблоне.

        2. Проверять перед добавлением длину результата скрипта и ставить соответствующее условие на вывод.

        $(function() {
        	$("#tags").autocomplete({
        		//ваши параметры        
        		response: function(event, ui) {
        			if (ui.content.length === 0) {
        				$("#empty").text("Результатов по запросу не найдено").css("display", "block");
        			}
        			else {
        				$("#empty").text("").css("display", "none");
        			}
        		}
        	});
        });​
          Сергей
          30 июля 2015, 04:50
          1. Ajax — это как?
          2. Что-то не запустилось — вот что в коде сейчас:
          <script>
          	$(function() {
          		var availableTags = [
          			[[pdoResources? &tpl=`tplTags` &limit=`0` &depth=`0` &parents=`1` &includeTVs=`tag`]]
          		];
          		$( "#tags" ).autocomplete({
          			source: availableTags,
          			minLength: 2,
          			select:function(e,ui) {
          				location.href = ui.item.the_link;              
          			}
          			response:function(event,ui) {
          				if (ui.content.length === 0) {
          					$("#empty").text("Результатов по запросу не найдено").css("display", "block");
          				}
          				else {
          					$("#empty").text("").css("display", "none");
          				}
          			}
          		});
          	});
          </script>
          Верно?

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