Блог им. amutyloАвтодополнение строки поиска: в ролях JavaScript, jQuery, PHP; на подхвате HTML и CSS; за кулисами трудиться AJAX

Как сделать AutoCompleter на JavaScript и jQuery.
Вольный перевеод статьи AutoCompleter Tutorial – jQuery(Ajax)/PHP/MySQL.
От автора Jamie статья языком оригинала -> www.nodstrum.com/2007/09/19/autocompleter/

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



<script src="jquery-1.2.1.pack.js" type="text/javascript"><!--mce:0--></script><script type="text/javascript"><!--mce:1--></script

Начнем
Подключаем основной скрипт библиотеки jQuery, и даем специальные команды для компилятора джава скрипта (от переводчика: я не очень понимаю эти хитрые команды компилятора для браузера IE6, но наверное без них не обойтись; если вы не собираетесь поддерживать «замечательный» IE6 то все что идет после подключения jQuery можно смело выкинуть нафиг. Прошу знатоков меня поправить!).
Использование операторов библиотеки jQuery позволит нам подключиться к серверному скрипту rpc.php (переводчик: это уже PHP) который выполнит поиск и вернет нам найденное.
Как это все работает:
Есть некая форма со строкой ввода названия области (у них это каунти — county). после набора нескольких первых букв в этой строке показывается менюшка с выбором похожих значений уже известных программе или сохраненных наперед в БД. И из этого меню можно выбрать нужное значение которое перенесется в строку поиска. (переводчик: это так кратко для тех кто сразу не понял, как это внешне работает).
Функция поиска получает значение введенных символов из строки инпута
<input id="inputString" onkeyup="lookup(<b>this.value</b>);" size="30" type="text" />

и посылает это все методом POST в rpc.php используя AJAX вызов jQuery
$.post("rpc.php", {queryString: ""+inputString+""}, function(data){....}

вот таким образом.
Если строка в поле input-а равна «0» (ноль) то
<div class="suggestionsBox"
прячется, и это правильно, если нет ничего в строке то нечего потом показывать. А если иначе, строка не пустая, то мы берем значение ‘inputString’ и посылаем его POST-ом в rpc.php страничку на сервер.
jQuery $.post() функция используется так:
$.post(url, [data], [callback])

[callback] часть нужна для связи с функцией, которая проделает всю магию аджакс запроса.
Если значение [data] больше чем ноль (то есть реально есть что показать) скрипт показывает
<div class="suggestionsBox"
и замещает HTML код информацией с возвращенными данными
вот здесь
$('#autoSuggestionsList').html(data);

Просто, а может и не просто.

Теперь о серверной части программы или как еще это называеют PHP Backend (RPC.php)
Как всегда моя страничка PHP Backend называется rpc.php (Remote Procedure Call) («вызов удаленной процедуры») но реально она этого не делает это вовсе.
?>php
// PHP5 Implementation - используем MySQLi.
$db = new mysqli('localhost', 'root' ,'', 'autoComplete');
if(!$db) {
    // показываем ошибку если не можем подключиться.
    echo 'ERROR: Could not connect to the database.';
} else {
    // Существует ли строка POST запроса 'queryString'?
    if(isset($_POST['queryString'])) {
        $queryString = $_POST['queryString'];
        // Если длинна строки больше чем 0? Там что то есть
        if(strlen($queryString) > 0) {
        // Запускаем запрос: используем LIKE '$queryString%'
        // Знак процентов(%)это wild-card, в моем примере о странах работает так...
        // $queryString = 'Uni'; если строка запроса начаниется на ...
        // Returned data = 'United States, United Kindom'; должно возвратиться ..
 
        $query = $db->query("SELECT value FROM countries WHERE value LIKE '$queryString%' LIMIT 10");
        if($query) {
            // Пока в полученном ресурсе есть результирующая информация проходимся   по всему ресурсу вытягивая обьект - результат  .
            while ($result = $query->fetch_object()) {
                // Форматируем результат, я использую <li> для списка, вы можете поменять это.
                // onClick функция заполняет textbox результатами.
            echo '</li><li onclick="fill(''.$result->value.'');
			">'.$result->value.'</li>';
            }
        } else {
            echo 'ERROR: There was a problem with the query.';
        }
    } else {
        // Ничего не делаем.
    } // Это queryString.
} else {
    echo 'There should be no direct access to this script!';
}
}
 
?>;

Я не буду вдаваться глубоко в детали потому что достаточно коментариев в коде что бы все понять и так.
По простому программа берет ‘QueryString’ и выполняет запрос со значением из ‘QueryString’ добавляя в конце wildcard %. (Это значит после значения ‘QueryString’ могут быть любые символы и буквы)
Каждый раз когда нажимается клавиша генерируется запрос по БД MySQL, это не очень правильно для больших обьемов информации в БД, но для небольших вполне пойдет.
Код PHP это та часть информации которую вам следует изменить под ваши нужды, и изменить строку запроса тоже.

CSS стиль – использую CSS3, Да да! Это намного проще, но ограничиват работу скрипта браузерами Firefox и Safari и им подобным.
.suggestionsBox {
    position: relative;
    left: 30px;
    margin: 10px 0px 0px 0px;
    width: 200px;
    background-color: #212427;
    -moz-border-radius: 7px;
    -webkit-border-radius: 7px;
    border: 2px solid #000;
    color: #fff;
}

.suggestionList {
    margin: 0px;
    padding: 0px;
}

.suggestionList li {
    margin: 0px 0px 3px 0px;
    padding: 3px;
    cursor: pointer;
}

.suggestionList li:hover {
    background-color: #659CD8;
}

CSS довольно таки стандартный ничего экстраординарного.
Основной кусок HTML
<div>
	<div>
      Type your county (for the demo):
	<input id="inputString" onkeyup="lookup(this.value);" size="30" type="text" />
      </div>
            <div class="suggestionsBox" id="suggestions" style="display: none;">
                 <img style="position: relative; top: -12px; left: 30px;" src="upArrow.png" alt="upArrow" />

            <div class="suggestionList" id="autoSuggestionsList">

		</div>

                </div>

</div>


Это основная часть HTML, действительно все что вам нужно это запустить этот код с input text box и функцией ‘onkeyup’ с установкой lookup(this.value); Еще я бы не рекоментовал бы изменить ID input box-а, если вы только не поменяете ссылку на этот ID в Javascript коде соответственно.
Еще скриншоты:



Ну и напоследок код примера полностью
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Ajax Auto Suggest</title>
<script type="text/javascript" src="jquery-1.2.1.pack.js"></script>
<script type="text/javascript">
	function lookup(inputString) {
		if(inputString.length == 0) {
			// Hide the suggestion box.
			$('#suggestions').hide();
		} else {
			$.post("rpc.php", {queryString: ""+inputString+""}, function(data){
				if(data.length >0) {
					$('#suggestions').show();
					$('#autoSuggestionsList').html(data);
				}
			});
		}
	} // lookup

	function fill(thisValue) {
		$('#inputString').val(thisValue);
		setTimeout("$('#suggestions').hide();", 200);
	}
</script>
<style type="text/css">
	body {
		font-family: Helvetica;
		font-size: 11px;
		color: #000;
	}
	h3 {
		margin: 0px;
		padding: 0px;	
	}
	.suggestionsBox {
		position: relative;
		left: 30px;
		margin: 10px 0px 0px 0px;
		width: 200px;
		background-color: #212427;
        	-moz-border-radius: 7px;
		-webkit-border-radius: 7px;
		border: 2px solid #000;	
		color: #fff;
	}
	.suggestionList {
		margin: 0px;
		padding: 0px;
	}
	.suggestionList li {
		margin: 0px 0px 3px 0px;
		padding: 3px;
		cursor: pointer;
	}
	.suggestionList li:hover {
		background-color: #659CD8;
	}
</style>
</head>
<body>
	<div>
		<form>
			<div>
				Type your county:
				<br />
				<input type="text" size="30" value="" id="inputString" onkeyup="lookup(this.value);" onblur="fill();" />
			</div>
			<div class="suggestionsBox" id="suggestions" style="display: none;">
				<img src="upArrow.png" style="position: relative; top: -12px; left: 30px;" alt="upArrow" />
				<div class="suggestionList" id="autoSuggestionsList">
					 
				</div>
			</div>
		</form>
	</div>
</body>
</html>


Думаю Вы разберетесь
  • +6
  • amutylo
  • 18 января 2011, 15:26

Комментарии (17)

Для кого нужно было транслитерировать названия в заголовке? (ХТМЛ, СиЭсЭс, ...)
Можете еще убрать лишние пустые строки в последнем фрагменте?
Убрал, но я думаю, что лишние пробелы добавляют понимание кода.
Это как будто бы собственные имена. Ну, имена людей же пишут на разных языках.
+1 меня тоже почему-то раздражает
НИ для кого, поменял.
Имена в заголовках не транслировал специально. Но если людей раздражает поменял на язык оригинала. А вообщето написали бы отзывы по сути заметки. О PHP, JS, AJAX e.c.
Я правильно понимаю, что если я скопирую текст из буфера обмена, то автодополнение не сработает?
Скопирую средней кнопкой мыши в Linux.
Почему так? Должно сработать. Только вставьте его в строку поиска с помощью Ctrl+V. Поймите, что в строке поиска набирают текст с клавиатуры а не копипастят мышкой.
Нет, некоторые это делают мышью. Но ни один модуль автодополнения не обрабатывает этого. Жаль, что в JavaScript нет события по изменению содержимого поля ввода текста.
используйте событие onblur, кто вам мешает
Нашел в поисковике: «Событие onBlur возникает при потере объектом фокуса при переходе по клику мыши или с помощью клавиатуры.»

Это ведь не то: хотелось бы, чтобы варианты автодополнения обновлялись сразу, без необходимости перевода фокуса из поля ввода текста.
Извините, но я не пойму зачем оно вам практически? Или вам скучно и не с кем поговорить.
onblur()
У меня проблема с кодировками. У вас так не было?
Пока спасаюсь с помощью iconv, но не уверена, что так правильно.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.