Twitter typeahead.js и объект json для нескольких совпадений

Я пишу программу, которая должна быть в состоянии найти университетский курс на основе нескольких параметров курсов. У меня есть огромный объект json, содержащий 1360 объектов, и каждый объект имеет около 20-30 параметров. Однако меня интересуют только 3-5 из них.

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

Тем не мение. Я пробовал возиться с twitters typeahead.js, и, насколько я понимаю, вам нужно проанализировать его массив строк, и, насколько это кажется, он занимает только 1 массив. Нет ли простого способа (или другого модуля javascript), которым я могу это сделать?

Мой текущий объект:

var courses = [
    { "number": "<5 digits>", 
      "name": "<course name>", 
      "teacher": "<teacher name>", 
      "keywords": "<string of keywords>" }
    { ... }
    { ... }
    { ... }
    and so forth..
 ];

И это, как уже упоминалось, 1360 объектов размера.

Я хочу получить вывод, подобный этому:

введите здесь описание изображения

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

Кто-нибудь знает, как этого добиться?


person Zeliax    schedule 22.04.2016    source источник
comment
Вы работаете со статическими данными или будете получать их откуда-то (может быть, вызов ajax)? Есть ли у вас контроль над тем, как возвращаются данные?   -  person whipdancer    schedule 23.04.2016
comment
Данные загружаются вместе со страницей из локального файла json. Так что да. Пока он останется статичным. Я планирую настроить cron-job для повторного запуска моего скрипта Python в определенные моменты времени, чтобы очистить данные из базы данных курса и обновить файл.   -  person Zeliax    schedule 23.04.2016


Ответы (1)


Это очень просто, но не с typeahead.js. У него есть 231 нерешенная проблема (на момент ввода некоторые очень серьезно) и не обновлялся год.

Вместо этого используйте bootstrap3-typeahead. Он поддерживается и обновляется. Взгляните на документы, прежде чем читать дальше. Вы не предоставляете JSON, поэтому я использую другой JSON в приведенном ниже примере.

Все, что вам нужно сделать, это определить метод matcher, здесь очень простой, нечувствительный к регистру, который сравнивается со всеми атрибутами в элементе JSON:

matcher: function(item) {
  for (var attr in item) {
    if (~item[attr].toString().toLowerCase().indexOf(this.query.toLowerCase())) return true
  }
  return false
}

Вы можете переопределить, какие атрибуты/текст должны отображаться в раскрывающемся списке, используя displayText (чистый пример):

displayText: function(item) {
  return item.id + ' ' + item.label  + ' ' + item.value
}

Если вы хотите полностью переопределить рендеринг элементов в виде сложного HTML, используйте комбинацию displayText и highlighter, где каждая отображаемая строка содержит строковый JSON:

displayText: function(item) {
  return JSON.stringify(item) 
},
highlighter: function(item) {
  item = JSON.parse(item)
  return '<span><h4>'+item.value + '</h4>' + item.id  + ' ' + item.label +'</span>'
}

Когда отображаемая строка преобразована в строку, <input> необходимо обновить с помощью атрибута(ов) значения, которое должно быть выбранным значением:

afterSelect: function(item) {
  this.$element[0].value = item.value
}

Полный пример:

$('#example').typeahead( {
  source: json,
  matcher: function(item) {
    for (var attr in item) {
        if (~item[attr].toString().toLowerCase().indexOf(this.query.toLowerCase())) return true
    }
    return false
  },
  displayText: function(item) {
    return JSON.stringify(item)
  },
  highlighter: function(item) {
    item = JSON.parse(item)
    return '<span><h4>'+item.value + '</h4>' + item.id  + ' ' + item.label +'</span>'
  },
  afterSelect: function(item) {
    this.$element[0].value = item.value
  }
})                

демо -> http://jsfiddle.net/vhme3td1/

person davidkonrad    schedule 23.04.2016
comment
Вау, спасибо. Это круто! Я получу право на попробовать это! Как только я заработаю, я приму ваш ответ как ответ: P - person Zeliax; 23.04.2016
comment
@Zeliax, FYI - обновил ответ, забыл включить afterSelect для правильной передачи выбранного значения в <input>. - person davidkonrad; 23.04.2016
comment
После того, как я был очень занят, мне наконец удалось взглянуть на него, и это просто здорово! Большое спасибо дружище :Р - person Zeliax; 28.04.2016