Использование Twitter typehead для работы панели поиска

Я использую Twitter typehead, чтобы моя панель поиска работала, но сталкиваюсь с некоторыми проблемами.

Назначение строки поиска:

Строка поиска будет использоваться для поиска имен пользователей, зарегистрированных на сайте.

Подход:

В head из home.php:

<script src="typeahead.min.js"></script>

header.php (который входит в home.php):

<input type="text" class="form-control" placeholder="Search user" name="typeahead">

  <script>
    $(document).ready(function(){
    $('input.typeahead').typeahead({
        name: 'typeahead',
        remote:'search.php?key=%QUERY',
        limit : 10
    });
});
    </script>

search.php:

<?php
include("connect.php");

    $key=$_GET['key'];
    $array = array();
    $query = mysqli_query("SELECT * FROM users WHERE username LIKE '%{$key}%'");
    while($row=mysqli_fetch_assoc($query)){
      $array[] = $row['username'];
    }

    echo json_encode($array);
?>

Текущие результаты:

Если с приведенным выше кодом, на home.php я попытаюсь найти пользователя Alice, который является реальным пользователем (кстати, я не нажимаю на поиск, я просто набираю ее имя в строке поиска. Я ожидаю, если Алиса реальный пользователь, ее имя появится в раскрывающемся списке). Но если я ищу ее, URL-адрес меняется.

Резюме: если я наберу Алису (не нажимая поиск), ничего не произойдет. Я ожидаю, что появится раскрывающийся список, поскольку Алиса — настоящее имя пользователя.

Если я наберу Алису и нажму кнопку поиска, URL-адрес изменится на:

http://localhost/home.php?typeahead=Alice

Как я ожидаю, что это будет работать: введите здесь описание изображения

Изменить:

Другой подход, который я пробовал в header.php:

<input type="text" class="form-control" placeholder="Search user" name="typeahead">

<?php  
// getting all usernames from db
        $statement = mysqli_prepare ($connect, "SELECT * FROM users WHERE account_type ='user'");
        mysqli_stmt_execute($statement);
        $usernames = array();
        $result = mysqli_stmt_get_result($statement);
        while($get_data = mysqli_fetch_assoc ($result)){
            $usernames[]       = $get_data['username'];
        }
        mysqli_stmt_close($statement);     
    ?>

<script>
    var substringMatcher = function(strs) {
  return function findMatches(q, cb) {
    var matches, substringRegex;

    // an array that will be populated with substring matches
    matches = [];

    // regex used to determine if a string contains the substring `q`
    substrRegex = new RegExp(q, 'i');

    $.each(strs, function(i, str) {
      if (substrRegex.test(str)) {
        matches.push(str);
      }
    });

    cb(matches);
  };
};

var username = <?php echo json_encode($usernames); ?>;

$('#the-basics .typeahead').typeahead({
  hint: true,
  highlight: true,
  minLength: 1
},
{
  name: 'usernames',
  source: substringMatcher(username)
});
    </script>

Следующий подход был взят из Github.

При таком подходе я все еще не получаю раскрывающийся список, в котором отображаются совпадающие имена.


person Freddy    schedule 19.04.2016    source источник


Ответы (1)


Проблема в вашем объявлении для typeahead. Typeahead не может напрямую использовать удаленный источник. Это должно быть предоставлено либо через функцию, либо через объект ищейки.

Если вы посмотрите документацию по typeahead, вы увидите, что для remote нет настроек.

На странице примеров также есть несколько хороших идей для начала.

Мне нравится использовать объект ищейки, но он немного усложнить дело.

Создайте объект ищейки:

var taSource = new Bloodhound({
  datumTokenizer: Bloodhound.tokenizers.obj.whitespace('Value'),
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  identify: function(obj) {
    return obj.Value;
  },
  remote: todos
});

Я отделяю свой хэш объекта remote:

var todos = {
  url: urlRoot + '/todos',
  prepare: function(query, settings) {
    settings.url += '?q=' + query;
    return settings;
  },
  filter: function(data) {
    return $.map(data, function(obj) {
        console.log(obj)
        return {
        Id: obj.id,
        Value: obj.title
      };
    });
  }
};

Таким образом, объявление typehead выглядит следующим образом:

$('#search-input').typeahead({
  hint: true,
  highlight: true,
  minLength: 3
}, {
  name: 'myMatches',
  source: taSource,
  display: 'Value'
});

В этом случае я ищу title в JSON, который сопоставляется с Value в объекте, переданном в typeahead. На самом деле JSON выглядит так:

[
  {
    "userId": 1,
    "id": 1,
    "title": "delectus aut autem",
    "completed": false
  },
  {
    "userId": 1,
    "id": 2,
    "title": "quis ut nam facilis et officia qui",
    "completed": false
  },
  {
    "userId": 1,
    "id": 3,
    "title": "fugiat veniam minus",
    "completed": false
  },
  {
    "userId": 1,
    "id": 4,
    "title": "et porro tempora",
    "completed": true
  }...

Вот демонстрация скрипки.

person whipdancer    schedule 20.04.2016
comment
Привет, спасибо за ответ. Я пытался реализовать ваш подход, и я все еще получаю те же результаты. Но я думаю, что не помещаю код в правильные файлы. Где создать объект bloodhound? В настоящее время я создал объект bloodhound, remote и объявление в header.php, где создается панель поиска. Кроме того, пожалуйста, смотрите мое редактирование. Я попробовал другой подход, используя примеры, предоставленные вами. - person Freddy; 21.04.2016
comment
Весь код в этом примере зависит от document.ready. Я предполагаю, что теги <script> в header.php выводятся в браузер. В этом случае весь этот код мог бы находиться внутри $(document).ready(function(){}); - person whipdancer; 21.04.2016