Наверх

MODX и Isotope - фильтрация блоков на странице

Isotope — это jQuery плагин, который позволяет фильтровать группу блоков, сортировать блоки и располагать их, например, плиткой.

Isotope

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

Для тегов есть очень удобное дополнение от Павла Гвоздя — tvSuperSelect. Будем использовать его для распределения проектов по категориям.

Решение будет состоять условно из двух частей: первая — вывод всех тегов в виде кнопок для фильтрации, а вторая — добавление блокам соответствующих классов.

Как вывести все теги в tvSuperSelect

Сниппет tvssTags выводит теги для какого-то конкретного ресурса. Чтобы вывести вообще все теги, которые есть на сайте, нужно сделать выборку из базы данных (из таблицы tvss_options). Тут нам поможет pdoResources:
{'pdoResources' | snippet : [
    'loadModels' => 'tvsuperselect',
    'class' => 'tvssOption',
    'sortby' => '{ "value":"ASC" }'
    'groupby' => 'value',
    'tpl' => '@INLINE <li>
        <a href="{$_modx->resource.uri}#{$value}"
         data-filter=".{$value | md5}"
         class="filter">{$value}</a>
        </li>',
    'tplWrapper' => '@INLINE <ul class="nav nav-tabs">{$output}</ul>'
]}

В параметре data-filter не получится подставить просто значение тега, так как оно может содержать символы, которые не разрешается использовать в наименовании CSS-классов (например, пробел). Поэтому для получения уникального класса для каждого из тегов мы будем использовать MD5-хеш от значения тега.

Вывод ресурсов с классами для фильтрации

Чтобы фильтрация заработала, у самих блоков должны быть проставлены такие же классы, как и в параметре data-filter:
<!-- GRID ITEM -->
<div class="grid-item {'tvssTags' | snippet : [
        'id' => $id,
        'tv' => 1,
        'pageId' => $id,
        'tpl' => '@INLINE {$tag | md5}',
        'outputSeparator' => ' '
    ]}">
    <!-- GRID DETAILS -->
    <div class="grid-details">
        <a href="{$uri}">
            <h4 class="grid-title">{$pagetitle}</h4>
        </a>
    </div>
</div>
<!-- /. GRID ITEM -->

Здесь важно указать параметр outputSeparator, так как CSS-классы разделяются пробелами, ну и привести значения классов к тому же виду, что и в параметре data-filter (MD5-хеш от значения тега).

Теперь осталось только подключить плагин Isotope стандартным образом, и наша фильтрация заработает.

13 комментариев

  1. Игорь Сидлярук 28 июня 2017, 10:04 # 0
    Илья, спасибо тебе за твои советы и подборки. Нужные и полезные вещи! НО!
    Не думал ли ты сделать возможность «Добавить в избранное».
    Было бы отлично. А то многое теряется и «сползает» со временем…
    Если реализуешь — ваще прям супер было бы. ;-)
    1. Илья Уткин 28 июня 2017, 11:20 # 0
      Ты не первый с такой просьбой, видимо, действительно, нужная штука)

      Реализовал возможность добавлять статьи в избранное (звёздочка рядом с количеством комментариев на странице статьи).
      1. Игорь Сидлярук 28 июня 2017, 12:16(Комментарий был изменён) # 0
        Отлично. Спасибо ;-)
    2. Эникен Некиэн 01 ноября 2017, 10:21(Комментарий был изменён) # 0
      Илья, подскажите пожалуйста как вывести все тегированные ресурсы…
      Я просто в контент чанке каталога портфолио ваш код разместил. Но по клику на тег нет желаемого волшебного эффекта… и не выводятся. Что не так делаю? сайт
      <!-- GRID ITEM -->
      <div class="grid-item {'tvssTags' | snippet : [
              'id' => $id,
              'tv' => 2,
              'pageId' => $id,
              'tpl' => '@INLINE {$tag | md5}',
              'outputSeparator' => ' '
          ]}">
          <!-- GRID DETAILS -->
          <div class="grid-details">
              <a href="{$uri}">
                  <h4 class="grid-title">{$pagetitle}</h4>
              </a>
          </div>
      </div>
      <!-- /. GRID ITEM -->
      Предв. создал ресурсы, указал им теги,
      в расширенный заголовок ввел ->
      tag1{$.get['tag'] ? ' «'~($.get['tag']|unescape:"url")~'»' : ''}
      Это правильно сделал?

      В настройках PDOtools феном включил все «Да»...
      1. Илья Уткин 01 ноября 2017, 10:23 # 0
        А Isotope на странице подключён? Это решение не работает с get-параметрами — оно только скрывает лишнее с помощью JavaScript.
        1. Эникен Некиэн 01 ноября 2017, 10:25(Комментарий был изменён) # 0
          Подключен работает, но ресурсы не подхватывает.
          Какими get-параметрами? в Title -убрать это?

          x-grow.ru/ru/ тут работает, а то чтобы настоящие ресурсы тут вывести — пока не понял все ошибка.
          1. Эникен Некиэн 01 ноября 2017, 16:53(Комментарий был изменён) # 0
            Илья, скажиет еще плз, выводить все ресурсы с классами должен ваш код или что-то еще надо сделать? Мне бы понять куда дальше двигаться, что искать чтобы нормально привязать изотоп-галерею как на главной
            1. Илья Уткин 01 ноября 2017, 20:01 # 0
              Нет, нужен ещё вывод самих ресурсов. grid-item — это только чанк вывода.
        2. Евгений Александров 08 января 2020, 17:59 # 0
          Илья спасибо большое за статью, сделал все получилось, по тегам все фильтруется.Но у меня наверное глупый вопрос, а как сделать кнопку «показать все»? Сделать еще один TV и там ставить тег на все ресурсы «показать все» или это как то красивее можно оформить?
          1. Илья Уткин 13 января 2020, 08:23 # 0
            Думаю, нужно смотреть в документации к Isotope — там есть как раз кнопка Show all
          2. Евгений Александров 13 января 2020, 15:21 # 0
            Блин застрял я на этом izotope. Никак не пойму как сделать вывод из одного TV, а не из всех сразу
            {'pdoResources' | snippet : [
                'loadModels' => 'tvsuperselect',
                'class' => 'tvssOption',
                'sortby' => '{ "value":"ASC" }'
                'groupby' => 'value',
                'tpl' => '@INLINE <li>
                    <a href="{$_modx->resource.uri}#{$value}"
                     data-filter=".{$value | md5}"
                     class="filter">{$value}</a>
                    </li>',
                'tplWrapper' => '@INLINE <ul class="nav nav-tabs">{$output}</ul>'
            ]}
            Мне надо запрос типо такого составить
            'select'=>{ 'value': AS, 'tag': FROM ,'prefix_tvss_options': WHERE, 'tv_id': IN(5), GROUP BY: 'value' }
            но не получается у меня нет большого опыта, а сайт для дочки делаю в школу, в феврале сдавать надо (
            1. Евгений Александров 15 января 2020, 09:37 # 0
              Сам себе отвечу, 4 дня ушло на то как читать запросы к базе данных ))). Если у вас несколько TV и вы хотите вывести теги из одного TV. Надо просто добавить вот это условие
              'where' => '{"tv_id":"номер id_tv которую нужно вывести" }'
              и получится вот так
              {'pdoResources' | snippet : [
                  'loadModels' => 'tvsuperselect',
                  'class' => 'tvssOption',
                  'sortby' => '{ "value":"ASC" }'
                  'groupby' => 'value',
              'where' => '{"tv_id":"номер id_tv которую нужно вывести" }'
                  'tpl' => '@INLINE <li>
                      <a href="{$_modx->resource.uri}#{$value}"
                       data-filter=".{$value | md5}"
                       class="filter">{$value}</a>
                      </li>',
                  'tplWrapper' => '@INLINE <ul class="nav nav-tabs">{$output}</ul>'
              ]}
              Я понимаю что об этом и писать не стоит, но мало ли кто еще искать будет.Но мне тоже это полезно было так как я стал понимать как строится запрос к базе данных.
              1. Илья Уткин 15 января 2020, 12:22(Комментарий был изменён) # 0
                Спасибо, да, теперь понятно в чём дело было)

            Авторизация

            через сервис Loginza:

            Подписка или RSS

            Буду присылать новые статьи — никакого спама



            Шаблоны MODX

            1 2 Дальше »

            Объектная
            модель
            MODX