Фасетный поиск на JavaScript + Underscore + jQuery

В сегодняшнем уроке мы с вами попробуем воссоздать имитацию фасетного (фасеточного) поиска средствами Javascript. Я подразумеваю, что вы уже знаете что такое фасетный поиск, раз читаете данный туториал, в противном случае погуглите или загляните на Amazon или мою Демку.

Для начала нам понадобится библиотека github.com/eikes/facetedsearch. Скачайте её и подключите файл facetedsearch.js к нашему проекту. Так же нам понадобятся библиотеки jQuery и Underscore.

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

Итак для начала сделаем простенькую разметку с подключенными зависимостями:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
    <script src="dependencies/jquery-1.6.2.js"></script>
    <script src="dependencies/underscore-1.1.6.js"></script>
    <script src="facetedsearch.js"></script>
</head>
<body>

  <div id=facets></div> // Сюда мы выведем фасетные фильтры
  <div id=results></div> // А тут будут наши элементы
  
</body>
</html>

Теперь нам нужно описать настройки нашего приложения и создать шаблон вывода элементов массива которые мы будем сортировать при помощи фасетов:

    <script>
      $(function(){
          var item_template = // Описывем шаблон
           '<div class="col-sm-3 col-xs-6 itm">' +
             '<img src="<%= obj.imageURL %>" class="img-responsive">' +
             '<h4><%= obj.lastname %>, <%= obj.firstname %></h4>' +
             '<p class="tags">' +
             '<% if (obj.category) {  %><%= obj.category %><% } %>' +
             '<% if (obj.continent) {  %>, <%= obj.continent %><% } %>' +
             '<% if (obj.language) {  %>, <%= obj.language %><% } %>' +
             '</p>' +
             '<p class="desc"><%= obj.description %></p>' +
           '</div>';
        settings = {
          items            : example_items,
          facets           : { // Указывем категории фасетов
                              'category'     : 'What Category',
                              'continent'    : 'Which Continent',
                              'language'     : 'Programming Language'
          },
          resultSelector   : '#results', // DOM элемент куда мы выводим результаты
          facetSelector    : '#facets', // DOM элемент для фасетов
          resultTemplate   : item_template,
          paginationCount  : 8, // Колличество элементов на страницу
          orderByOptions   : {'firstname': 'First name', 'lastname': 'Last name', 'category': 'Category', 'RANDOM': 'Random'},
          facetSortOption  : {'continent': ["North America", "South America"]}
        }

        $.facetelize(settings);

      });
    </script>

Ну и собственно создать сам JSON массив с элементами для отображения в нашем фасетном поиске на JS:

      var items = [
        {
          "firstname": "Mary",
          "lastname": "Smith",
          "imageURL": "http://lorempixel.com/150/150/cats/2",
          "description": "Sed Ea Amet. Stet Voluptua. Nonumy Magna Takimata ",
          "category": "Mouse",
          "language": ["Smalltalk", "XSLT"],
          "continent": "Africa"
        },
        {
          "firstname": "Patricia",
          "lastname": "Johnson",
          "imageURL": "http://lorempixel.com/150/150/cats/3",
          "description": "Ut Takimata Sit Aliquyam Labore Aliquyam Sit Sit Lorem Amet. Ipsum Rebum. ",
          "category": "Lion",
          "continent": "North America"
          },
          ...
        ];

Данный массив я бы вынес в отдельный JS файл который бы формировался динамически, из БД например.

Вот собственно и всё, мы получаем фасетный поиск на JavaScript и можем его кастомизировать. Далее я привожу переведённую документации библиотеки, где вы можете подсмотреть необходимые вам триггеры.

Документация

Эта библиотека зависит от jQuery и Underscore JS.

Функции

Две функции экспортируются в пространство имен jQuery.

facetelize Используется для инициализации фасетного поиска с заданными настройками.

facetUpdate Может использоваться, если вы хотите изменить состояние фасетного поиска извне.

Настройки объектов

items : Массив элементов, которые будут отфильтрованы и отсортированы в процессе.

facets : Объект, для которого ключи соответствуют ключам элементов и значениям, является заголовком для этого фасета. Элементы будут отфильтрованы на основе того, какое значение они имеют для этих ключей.

orderByOptions : Подобно фасетам, за исключением того, что эти пары «ключ-значение» используются только для сортировки. Когда ключ RANDOM включен, результаты могут быть рандомизированы.

facetSelector : Это селектор, который используется для поиска DOM-узла, из которого выбираются фильтры фасетов.

resultSelector : Это селектор, который используется для поиска DOM-узла, где отображаются результаты.

resultTemplate : Строка, которая используется Underscore шаблонизатором Для рендеринга каждого элемента из массива items. Следующие атрибуты добавляются к каждому элементу, который также можно использовать в шаблоне: batchItemNr, batchItemCount и totalItemCount.

state : Этот объект сохраняет текущие фильтры, сортирует: currentResult и прочие. Вы можете предоставить строку orderBy или объект filters для их предварительной настройки.

enablePagination : Boolean для включения пагиналора и кнопи "load more", по умолчанию true.

paginationCount : Если включен пагинатор, задаёт количество элементов на страницу, по умолчанию - 50.

facetSortOption : Используйте эту функцию, чтобы изменить порядок элементов фасетов. Принимает объект, в котором ключи соответствуют именам фасетов и значениям в массив значений фасетов, которые могут быть расположены в том порядке, в котором вы хотели бы их видеть. В этом примере будут отсортированы континенты в другом порядке, элементы, не включенные в массив, будут добавлены в алфавитном порядке:

      facetSortOption  : {'continent': ["North America", "South America"]}
      

Есть еще несколько шаблонов, пожалуйста, посмотрите исходный код facetedsearch.js, чтобы увидеть все доступные параметры шаблона.

События

Вы можете привязываться к некоторым событиям, которые должны отправить уведомления, когда произошли некоторые действия. Для этого используем систему событий jquery:

facetuicreated : Вы можете привязать эту функцию к DOM элементу settings.facetSelector который должен быть уведомлен, когда пользовательский интерфейс был создан.

facetedsearchresultupdate : Вы можете привязать эту функцию к DOM элементу settings.resultSelector что бы получить уведомление о результатах обновления.

facetedsearchfacetclick : Это событие вызывается при щелчке фасета и его срабатывании на settings.facetSelector элементе. Который получает идентификатор фасета как аргумент.

facetedsearchorderby : Это событие вызывается при щелчке элемента сортировки по элементу settings.facetSelector. Он получает ID order в качестве аргумента.

        $(settings.resultSelector).bind("facetedsearchresultupdate", function(){
          // do something, maybe
        });