Живой поиск. Как реализовать фичу
Вложений: 1
На страничке стоит живой поиск, который начинает делать выборку по городам при вводе двух символов.
Все работает, все отправляется. Но есть одно НО, нужно чтоб люди могли ТОЛЬКО выбирать из предлагаемого списка вариантов. Если совпадений не найдено,то в выводимых результатах появлялась надпись - СОВПАДЕНИЯ НЕ НАЙДЕНЫ, а при смене фокуса с поля input вводимые данные уничтожаются. <form method="POST" action=""> <input type="text" name="referal" placeholder="Живой поиск" value="" class="who" autocomplete="off"><input type="submit" name="subscribe" value="Отправить!"> <ul class="search_result" id='popup'></ul> </form> <script> jQuery(function($){ $(document).mouseup(function (e){ // событие клика по веб-документу var div = $("#popup"); // тут указываем ID элемента if (!div.is(e.target) // если клик был не по нашему блоку && div.has(e.target).length === 0) { // и не по его дочерним элементам div.hide(); // скрываем его } }); }); </script> if(!empty($_POST["referal"])){ //Принимаем данные $referal = trim(strip_tags(stripcslashes(htmlspecialchars($_POST["referal"])))); $db_referal = $mysqli -> query("SELECT * from ".PREFIX."city WHERE city LIKE '%$referal%'") or die('Ошибка №'.__LINE__.'<br>Обратитесь к администратору сайта пожалуйста, сообщив номер ошибки.'); while ($row = $db_referal -> fetch_array()) { echo "\n<li>".$row["city"]."</li>"; //$row["name"] - имя таблицы } } $(function(){ //Живой поиск $('.who').bind("change keyup input click", function() { if(this.value.length >= 2){ $.ajax({ type: 'post', url: "search.php", //Путь к обработчику data: {'referal':this.value}, response: 'text', success: function(data){ $(".search_result").html(data).fadeIn(); //Выводим полученые данные в списке } }) } }) $(".search_result").hover(function(){ $(".who").blur(); //Убираем фокус с input }) //При выборе результата поиска, прячем список и заносим выбранный результат в input $(".search_result").on("click", "li", function(){ s_user = $(this).text(); $(".search_result").fadeOut(); $(".who").val(s_user); //деактивируем input, если нужно }) }) |
$referal = trim(strip_tags(stripcslashes(htmlspecialchars($_P OST["referal"]))));
Кашу маслом не испортишь? htmlspecialchars применяется при выдаче данных клиенту чтобы избежать на клиенте XSS атак или банально не добавить ошибок в html. strip_tags, к сведению, может работать некорректно, и запрос типа "<div>1</div>" никакой опасности не представляет. Функция stripslashes удаляет экранирование и применяется, чтобы исключить действие магических кавычек, которые надо раз и навсегда отключить в конфигурации, а stripcslashes удаляет экранирование стиля С. В тоже время, хотя в запросах городов такового не может быть, но уж коли со страха режутся теги и замена на html-сущности, то надо учитывать то, что LIKE использует символы _ и % как спецсимволы, которые нужно экранировать в данных посредством addcslashes(). То есть все что понаписано в запросе никоим образом не спасет от sql-инъекции. Для этого в оригинальном расширении MySQL применяется mysql_real_escape_string, а mysqli mysqli_real_escape_string, но в mysqli лучше использовать подготовленные запросы (prepare) и метку параметров ?, а экранированием займется драйвер. По ответу клиента строится список. А что будет у клиента при получении 'Ошибка №'.__LINE__.'<br>Обратитесь к администратору сайта пожалуйста, сообщив номер ошибки.'? И вообще, если таким образом администратор будет разбираться с ошибками, то он поседеет, ибо скриптов много и одноименных линий в них куча. А пользователи не обязательно программисты, и не обязательно точно смогут описать где и при каких обстоятельствах произошло нечто. Может сперва исправите код на человеческий, измените логику общения клиент-сервер, а потом уже пояснить, что означает "люди могли ТОЛЬКО выбирать из предлагаемого списка вариантов", ибо что кроме выбора они в нем могут сделать? Иначе, если понимать это буквально, то ни LIKE, ни ввода на клиенте не нужно, и все должно быть иное. К сведению - echo "\n<li>".$row["city"]."</li>" - для html это просто мусор. |
Вложений: 1
Вот это письмецо.
Это же скрипт на столько упрощенный, чтобы вопросов не возникало. Конечно же ошибка тоже приведена для примера. По поводу самого вопроса - "люди могли ТОЛЬКО выбирать из предлагаемого списка вариантов" Означает, что люди могут выбирать город, только из предлагаемого списка вариантов. Если вариант не находится, то как во вложении выше выдается надпись - совпадений не найдено, а поле input очищается. А кроме выбора они могут сделать следующее: Вбить несуществующий город и нажать кнопку отправить. Собственно вот что и вышло, во вложении ниже. Вложение 3334 |
Цитата:
Насчет ошибки - ul кроме li ничего не должен содержать, а вы строя список на нем конечно его стилизуете. Как можно при этом вместо списка в ul втыкать сообщение об ошибке? Ведь проблема не в том, что вы номера строк в файлах сообщаете, а в том как сообщаете об ошибках, код то клиентский просто принимает и помещает. Ну разве же так делается, а если так не делается, то где реальный код? А чтобы выбирать из списка имеющегося, то код то ведь совсем иной будет при этом. Тут только возникает вопрос - а сколько позиций предлагает список, будет ли удобен при этом выбор в нем? Это ведь тоже надо обдумать, а если обдумать, то это несомненно скажется на коде как клиента, так и сервера. Или не так? То есть ваш вопрос, это нечто общее, желание, а детализация этого желания отсутствует. Значит и ответ может быть в общих чертах. ) |
http://02r.ru/news/ вот как это выглядит, чтоб было совсем понятно.
Вариантов около 1000, но пользователю предоставляется выбор. Можно ввести несколько букв города и выбрать из списка нужны, а можно просто ввести несуществующий и отправить форму. Нужно, чтобы при отсутствии вариантов выводилась строка - совпадений нет https://vk.com/edit?act=contacts как здесь. Попробуйте вбить несуществующий город. |
veg,
Ну считай сколько у тебя записей из базы возвращается... Если 0 то выводи сообщение. Что бы отчистить город как вариант можно сделать поле input type="hidden" в котором будет меняться значение в зависимости от выбора города (ну как пример). А вообще самый оптимальный вариант проводить проверку города после отправки на сервер (так то она должна быть при лбом раскладе) и если пользователь проигнорировал сообщение "нет такого города", то он сам виноват, пускай перезаполняет форму заново |
Цитата:
Вы же в вопросе написали буквально следующее "люди могли ТОЛЬКО выбирать из предлагаемого списка вариантов", а это уже не поиск, а предложения, то есть есть готовый список, выбирайте, а нет вводите свое. Но если нет в предложении, то ввод "другого", это тоже не поиск, а добавление нового субъекта в базу, который впоследствии может предлагаться. Как еще иначе понимать ваше требование? А если понимание правильное, то список предложений из 1000 городов, это уже много, думаю не стоит объяснять, что выбор в таком будет очень неудобным. В тоже время существует множество готовых плагинов AutoComplete, включая и с постраничной навигацией в списке, и прочими плюшками. Так что решайте, любо ищите готовое подходящее, либо отказываетесь от "только выбор из списка" и все-таки живой поиск, либо хорошо обдумайте "все подводные камни всех И", и тогда формулируйте вопрос. Цитата:
|
Цитата:
|
Цитата:
Если же я например введу слово jjjjaavvaascripttt, то в выпадающем поле ничего не будет, а при дальнейшем нажатии кнопки ИСКАТЬ тоже вряд ли что-то найдет. Цитата:
Цитата:
Еще раз, откройте яндекс, вбейте слово javascript, он вам выдаст с десяток часто используемых поисковых фраз(при клики на любое заполнится поле input), а их явно не 1000, скажу больше, даже не 1000 000, а вы говорите что 1000 городов - это уже много. Цитата:
Цитата:
B) Я не ясновидец, не знаю есть страничка у Вас или нет. |
$i=0; while ($row = $db_referal -> fetch_array()) { $i++; echo "\n<li><span>".$row["city"]."</span></li>"; //$row["name"] - имя таблицы } if($i == 0){echo "\n<li>Нет такого города</li>";} Сделал так. Теперь выводит что город не найден и это поля неактивно для выбора. $(".search_result").on("click", "li span", function(){ s_user = $(this).text(); $(".search_result").fadeOut(); $(".who").val(s_user); }) Теперь осталось сделать, чтобы поле input очищалось при условии, что город не найден и что был клик вне этого input. |
Все о Яндексе, все это живой поиск. Но не надо сравнивать поиск Яндекса в своем кеше или в интернете, с вашим списком городов, это большая разница. Яндекс имеет право предложить на его взгляд подходящее, а вы нет, ибо у вас выбор ограничивается строгим набором.
Из всего сказано ясно, что именно живой поиск вам и нужен, а "могли ТОЛЬКО выбирать из предлагаемого списка вариантов", это и есть ваше ограничение, и имеет иной смысл. Цитата:
А теперь по вашему. Города в базе нужно держать в отдельной таблице под уникальным идентификатором каждый. Вывод списка городов, это вывод названия города как текста опции, а его идентификатора как ее значения. Другими словами, в вашем случае лучше иметь костомизированный список, который будет работать в фонов режиме и отправлять на сервер выбор пользователя, а список UL отображать данные. Можно конечно поступить так как и у вас, но LI должны иметь в атрибутах идентификатор городов, которые передаются в скрытое поле при выборе, которое будет отправлять серверу выбор пользователя. Если пользователь может выбрать только из предлагаемого, то скрытое поле должно очищаться уже при получении фокуса полем ввода поиска. Если пользователь осведомлен, что он не может ввести произвольный город, а список предложений будет только в случае найденного, то сообщать что ничего не найдено большого смысла нет. Просто списка естественно не будет в этом, что и есть результат "не найдено", разве это не понятно и без сообщения? $i=0; while ($row = $db_referal -> fetch_array()) { $i++; Зачем этот не нужный счетчик? Сам результат запроса уже отвечает на этот вопрос - есть ли записи или нет - $db_referal->num_rows(). Если вернется более 0, значит есть совпадения, и сразу отдаем клиенту весь набор как JSON, если вместо $db_referal->fetch_array() использовать $db_referal->fetch_all(): $db_referal = $mysqli -> query("SELECT field_id, field_name from ".PREFIX."city WHERE city LIKE '%$referal%'"); //надеюсь баг с дырой будет исправлен //отдаем клиенту результат и выход exit(json_encode($db_referal->num_rows() ? $db_referal->fetch_all() : null)); //или проще, так как если не будет найдено то будет возвращен пустой массив //и проверять количество возвращенный записей нет необходимости exit(json_encode($db_referal->fetch_all() ?: null)); На клиенте: //response выбросить dataType: 'json', success: function(data){ if($data) //строим и показываем список по полученным данным else //ничего не найдено, списка не будет } И еще раз - отдавать клиенту html с намеренно добавленным \n, кстати в Win, это \r\n (в РНР для этого есть константа PHP_EOL, она сама разберется что конкретно на платформе) это просто бессмысленно, мусор это. Идеальный html, это одна длиииииинная строка, а структуру его всегда можно просмотреть в отладчике. |
Вложений: 1
Цитата:
Вложение 3337 Цитата:
Получилось следующее. Реакции на ввод данных нет. $db_referal = $mysqli -> query("SELECT id,city from ".PREFIX."city WHERE city LIKE '%$referal%'"); exit(json_encode($db_referal->fetch_all() ?: null)); data: 'json', success: function(data){ //Выводим полученные данные в списке if($data) {$(".search_result").html(data).fadeIn();}//строим и показываем список по полученным данным else {}//ничего не найдено, списка не будет } |
Заходим на страничку Гугла, Яшки, Бинг и прочих, начинаем поиск - есть ли список предложений, если робот ничего не найдет? Тоже самое и у вас. А пользователь должен знать сразу, что он может выбрать только тот город, который у вас оговорен условиями. Живой же поиск, это как раз сервис, чтобы не выводить длинную портянку, и не иметь представления о том как он работает в данное время может только пьяный ежик. )
Хотите еще и контрольный выстрел, ну так причем тут не найдено? Тогда уже сообщайте пользователю, что данный город (введенный пользователем) ваш сайт не принимает/не одобряет/или иная какая-то причина, иначе как же он узнает почему не может ввести произвольное? Уж как-то надо поставить в известность бедного пользователя. Цитата:
data = [ {"id" : 12, "city" : "Волгоград"}, {"id" : 15, "city" : "Воронеж"}, ...... ] Этот массив объектов нужно обойти циклом и построить по ним список. Или не известно как это делается, да еще посредством JQ? А если data пуст, значит нет и списка, а уж надо сообщать и что при этом решайте сами. Примечание: если JSON и показанный код ответа, то fetch_all(MYSQLI_ASSOC). Не используйте fetch_array() если в этом нет необходимости, это на будущее. Чтобы объект был именно таким {"id" : 12, "city" : "Волгоград"}, нужно указать параметры кодирования: exit(json_encode($db_referal->num_rows() ? $db_referal->fetch_all() : null, JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE)); если они доступны - первый с 5.3.3, второй с 5.4.0 |
С json работал, только средствами php все обрабатывал.
Сделал так. Все выводится, сейчас буду допиливать. $(function(){ //Живой поиск $('.who').bind("change keyup input click", function() { if(this.value.length >= 2){ $.ajax({ type: 'post', url: "search.php", //Путь к обработчику data: ({'referal':this.value,'id':this.id}), response: 'text', success: function(data){ $(".search_result").html(data).fadeIn(); //Выводим полученые данные в списке } }) } }) $(".search_result").hover(function(){ $(".who").blur(); //Убираем фокус с input }) //При выборе результата поиска, прячем список и заносим выбранный результат в input $(".search_result").on("click", "li span", function(){ s_user = $(this).value; s_id = $(this).id; $(".search_result").fadeOut(); $(".who").val(s_user); //деактивируем input, если нужно }) }) $db_referal = $mysqli -> query("SELECT id,city from ".PREFIX."city WHERE city LIKE '%$referal%'"); exit(json_encode($db_referal->fetch_all() ?: null,JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE)); |
Пусть сервер вернул показанное в примере на ввод "во", стоим список:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script> <script> $(function() { //это вернул сервер в success var data = [ {"id" : 12, "city" : "Волгоград"}, {"id" : 15, "city" : "Воронеж"} ]; //success обработчик var ul = $('ul.search_result'); $.each(data, function() { ul.append('<li data-id="' + this.id + '">' + this.city + '</li>') }) }); </script> </head> <body> <ul class="search_result"></ul> </body> </html> Список строится? Почему без ID? Или вы намерены вместо идентификаторов использовать имена? В скрытое поле нужно передвать идентификатор. А можно и в LI спрятать радио кнопки с label, и значение у которых есть идентификаторы, значение выбранной кнопка будет отправлено серверу. |
Вложений: 1
|
Цитата:
|
Ну список выше прислал, ID в li занесен будет конечно, я пока разбираюсь с json.
Не выводит список когда добавил Ваш код. url: "search.php", //Путь к обработчику data: ({'referal':this.value,'id':this.id}), success: function(){ var ul = $('ul.search_result'); $.each(data, function() { ul.append('<li data-id="' + this.id + '">' + this.city+ '</li>') }); $(".search_result").html(data).fadeIn(); //Выводим полученые данные в списке |
Поиск в базе осуществляется по введенному пользователем тексту, откуда у "неизвестного еще для сервера" может оказаться ID?
data: ({'referal':this.value,'id':this.id}) - с чего это тут появилось и откуда? Полученное нужно обработать, data, это аргумент функции обработчика, куда он исчез? То что у меня в примере это объявлено как глобальная переменная, так это только для примера, чтобы его можно было запустить для просмотра. dataType : 'json', //обязательно или если не указывать, то сервер должен передавать соответствующий заголовок success: function(data){ if(data) { //если найдены совпадения var ul = $('ul.search_result').empty().show(); //эффекты типа fadeIn() вряд ли уместны здесь //это и есть добавление в список $.each(data, function() { ul.append('<li data-id="' + this.id + '">' + this.city+ '</li>') }); //а $(".search_result").html(data) при том что data есть объект, это чушь //о fadeIn() выше сказано } else { //действия в случае если не найдено совпадений } } |
Часовой пояс GMT +3, время: 03:03. |