Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Живой поиск. Как реализовать фичу (https://javascript.ru/forum/dom-window/65687-zhivojj-poisk-kak-realizovat-fichu.html)

veg 02.11.2016 21:42

Живой поиск. Как реализовать фичу
 
Вложений: 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, если нужно
        
    })

})

laimas 03.11.2016 01:31

$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 это просто мусор.

veg 03.11.2016 03:20

Вложений: 1
Вот это письмецо.
Это же скрипт на столько упрощенный, чтобы вопросов не возникало. Конечно же ошибка тоже приведена для примера.

По поводу самого вопроса - "люди могли ТОЛЬКО выбирать из предлагаемого списка вариантов"
Означает, что люди могут выбирать город, только из предлагаемого списка вариантов. Если вариант не находится, то как во вложении выше выдается надпись - совпадений не найдено, а поле input очищается.
А кроме выбора они могут сделать следующее:
Вбить несуществующий город и нажать кнопку отправить. Собственно вот что и вышло, во вложении ниже.
Вложение 3334

laimas 03.11.2016 04:03

Цитата:

Сообщение от veg
Это же скрипт на столько упрощенный, чтобы вопросов не возникало.

trim(strip_tags(stripcslashes(htmlspecialchars($_P OST["referal"])))) - это не упрощение, а бесполезное усложнение, как следствие непонимания назначения указанных функций.

Насчет ошибки - ul кроме li ничего не должен содержать, а вы строя список на нем конечно его стилизуете. Как можно при этом вместо списка в ul втыкать сообщение об ошибке? Ведь проблема не в том, что вы номера строк в файлах сообщаете, а в том как сообщаете об ошибках, код то клиентский просто принимает и помещает. Ну разве же так делается, а если так не делается, то где реальный код?

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

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

veg 03.11.2016 11:38

http://02r.ru/news/ вот как это выглядит, чтоб было совсем понятно.
Вариантов около 1000, но пользователю предоставляется выбор. Можно ввести несколько букв города и выбрать из списка нужны, а можно просто ввести несуществующий и отправить форму.

Нужно, чтобы при отсутствии вариантов выводилась строка - совпадений нет https://vk.com/edit?act=contacts как здесь. Попробуйте вбить несуществующий город.

Гробовщик 03.11.2016 13:10

veg,
Ну считай сколько у тебя записей из базы возвращается... Если 0 то выводи сообщение.
Что бы отчистить город как вариант можно сделать поле input type="hidden" в котором будет меняться значение в зависимости от выбора города (ну как пример).
А вообще самый оптимальный вариант проводить проверку города после отправки на сервер (так то она должна быть при лбом раскладе) и если пользователь проигнорировал сообщение "нет такого города", то он сам виноват, пускай перезаполняет форму заново

laimas 03.11.2016 13:28

Цитата:

Сообщение от veg
Вариантов около 1000, но пользователю предоставляется выбор. Можно ввести несколько букв города и выбрать из списка нужны, а можно просто ввести несуществующий и отправить форму.

Живой поиск (или плагины AutoComplete) потому и называется живым, что находит совпадения по мере ввода.

Вы же в вопросе написали буквально следующее "люди могли ТОЛЬКО выбирать из предлагаемого списка вариантов", а это уже не поиск, а предложения, то есть есть готовый список, выбирайте, а нет вводите свое. Но если нет в предложении, то ввод "другого", это тоже не поиск, а добавление нового субъекта в базу, который впоследствии может предлагаться.

Как еще иначе понимать ваше требование? А если понимание правильное, то список предложений из 1000 городов, это уже много, думаю не стоит объяснять, что выбор в таком будет очень неудобным. В тоже время существует множество готовых плагинов AutoComplete, включая и с постраничной навигацией в списке, и прочими плюшками.

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

Цитата:

Сообщение от veg
Попробуйте вбить несуществующий город.

Не буду пробовать: а) я и так прекрасно знаю как работает AutoComplete; б) конкретно на ВК посмотреть не могу - не был и не буду участником соцболот, а регистрироваться у них ради пощелкать тем более. )

veg 03.11.2016 15:54

Цитата:

Сообщение от Гробовщик (Сообщение 433886)
veg,
Ну считай сколько у тебя записей из базы возвращается... Если 0 то выводи сообщение.
Что бы отчистить город как вариант можно сделать поле input type="hidden" в котором будет меняться значение в зависимости от выбора города (ну как пример).
А вообще самый оптимальный вариант проводить проверку города после отправки на сервер (так то она должна быть при лбом раскладе) и если пользователь проигнорировал сообщение "нет такого города", то он сам виноват, пускай перезаполняет форму заново

Спасибо. Позже отпишу что получилось.

veg 03.11.2016 22:56

Цитата:

Сообщение от laimas (Сообщение 433887)
Живой поиск (или плагины AutoComplete) потому и называется живым, что находит совпадения по мере ввода.

Так он совпадения и находит, пользователь должен выбрать из совпавшего, как в яндексе, зайдите поглядите, там регистрироваться не нужно. Если я ввожу например слово javascript в яндексе, то он предлагает мне несколько вариантов совпадений, при клике на который уже заполняется поле input. Далее нажимаю кнопку поиск и он выдает результаты по моему запросу.

Если же я например введу слово jjjjaavvaascripttt, то в выпадающем поле ничего не будет, а при дальнейшем нажатии кнопки ИСКАТЬ тоже вряд ли что-то найдет.


Цитата:

Сообщение от laimas (Сообщение 433887)
Вы же в вопросе написали буквально следующее "люди могли ТОЛЬКО выбирать из предлагаемого списка вариантов", а это уже не поиск, а предложения, то есть есть готовый список, выбирайте, а нет вводите свое. Но если нет в предложении, то ввод "другого", это тоже не поиск, а добавление нового субъекта в базу, который впоследствии может предлагаться.

А яндекс что не предлагает? Когда в поисковике вводите фразу, он и выдает Вам совпадения из списка часто используемых поисковых фраз. Добавлять в базу новый город через форму мне не нужно.
Цитата:

Сообщение от laimas (Сообщение 433887)
Как еще иначе понимать ваше требование? А если понимание правильное, то список предложений из 1000 городов, это уже много, думаю не стоит объяснять, что выбор в таком будет очень неудобным. В тоже время существует множество готовых плагинов AutoComplete, включая и с постраничной навигацией в списке, и прочими плюшками.

Чем глаголить в пустую не разобравшись, открыли бы пример, а если нечего по делу сказать, лучше даже не пишите.

Еще раз, откройте яндекс, вбейте слово javascript, он вам выдаст с десяток часто используемых поисковых фраз(при клики на любое заполнится поле input), а их явно не 1000, скажу больше, даже не 1000 000, а вы говорите что 1000 городов - это уже много.
Цитата:

Сообщение от laimas (Сообщение 433887)
Так что решайте, любо ищите готовое подходящее, либо отказываетесь от "только выбор из списка" и все-таки живой поиск, либо хорошо обдумайте "все подводные камни всех И", и тогда формулируйте вопрос.

Какие камни? Я ж не собираюсь корпорацию открывать. Взламывать мой доходяшный сайтик вряд кто будет, его еще сперва найти надо.
Цитата:

Сообщение от laimas (Сообщение 433887)
Не буду пробовать: а) я и так прекрасно знаю как работает AutoComplete; б) конкретно на ВК посмотреть не могу - не был и не буду участником соцболот, а регистрироваться у них ради пощелкать тем более. )

a) autocomplete у меня вообще OFF стоит.
B) Я не ясновидец, не знаю есть страничка у Вас или нет.

veg 04.11.2016 00:26

$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.


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