Skip to content
mFilter
mFilter
Фасетная фильтрация для MODX 3 с поддержкой SEO URL
  1. Компоненты
  2. mFilter

mFilter 1.6.0

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

Новые возможности

JS API для одной формы и элементов вне формы

Кнопка, ссылка или селект сортировки в шапке теперь могут управлять фильтрами:

js
const filter = mfilterGet();               // без аргумента — форма на странице

filter.setFilter('vendor_id', [5, 7]);     // выдача обновится сама
filter.addFilter('vendor_id', 9);
filter.removeFilter('vendor_id', 5);
filter.setFilter('price', { min: 1000, max: 5000 });
filter.setSort('price-asc');               // всё это — один запрос
  • mfilterGet() без аргумента возвращает форму фильтров на странице.
  • Новый метод addFilter() добавляет значения к выбранным. removeFilter() снимает значение, переданное и числом, и строкой.
  • Вызовы API сами отправляют запрос: несколько вызовов подряд уходят одним, изменение во время загрузки — следующим.
  • События mfilter:success, mfilter:afterSubmit и mfilter:contentLoaded передают filters, total, page, pageCount, sort, limit, tpl.
  • mfilter:init отправляется после регистрации формы, поэтому mfilterGet() работает уже в его обработчике.

Подробнее — JS API.

Паттерны URL для диапазонов

В шаблоне паттерна появились подстановки {min} и {max}. Паттерн ot-{min}-do-{max} для фильтра price даёт адрес /catalog/ot-1000-do-5000/ вместо /catalog/price--1000--5000/.

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

Подробнее — Паттерны URL.

Исправления

  • Паттерн URL с типом «Булево» открывал обратный фильтр. Адрес строится из значения фильтра — 1 или 0, — а при разборе 1 превращалось в 0. Теперь принимаются оба написания: 1/0 и yes/no.
  • В адресах вместо слагов разделов стояли id, а mfilter.slug_parent_prefix не действовал ни в одном режиме. Регрессия 1.5.0. Вид значения для слагов определялся по ключу фильтра, а по ключу для любого фильтра находился числовой тип. Теперь вид берётся из типа, заданного фильтру в наборе.
  • Сохранение набора фильтров в админке стирало настройки фильтров. В таблице набора видны ключ, источник, тип и заголовок; всё остальное из JSON набора — sort, pinned, hide_zero, prefix и прочее — при сохранении пропадало. Фильтр, у которого поле отличается от ключа, сохранялся под ключом поля, и у него менялись адреса, слаги и SEO-шаблоны.
  • Две строки набора могли сохраниться под одним ключом. В колонке «Ключ» стоит поле фильтра, поэтому фильтр с ключом brand и полем product_brand виден как product_brand, и строка с ключом brand молча затирала его. Теперь сохранение отклоняется с указанием строк, а настоящий ключ виден под полем.
  • Фильтры без type в наборе форма выводила только числовыми. Набор, заданный списком ключей, или запись JSON без type: форма определяла тип сама и пропускала все блоки, кроме числовых. Теперь она выводит фильтр с тем типом, с которым сервер посчитал его значения.
  • Для ключей color, size, tags источник по умолчанию был «Данные товара». В MiniShop3 это JSON-поля, синхронизируемые с опциями товара, и фильтр с таким источником не работал. Теперь для них выбирается «Опции».
  • Страница раздела без товаров отдавала 500, если на ней вызван mFilterNav с &cache=1. Пустой результат сниппет кэшировал так, что на PHP 8 это фатальная ошибка. Разделы с товарами работали.
  • submit() стирал фильтры, которых нет в форме. Фильтр, выставленный кнопкой вне формы или исключённый через &exclude, пропадал при каждой отправке, смене сортировки и переходе на страницу.
  • На SEO-адресе фильтр без поля в форме уходил на сервер слагом — каталог оказывался пустым. Теперь mFilterForm отдаёт фильтры, разобранные сервером, в атрибуте формы data-mfilter-active-filters.
  • «Назад» в браузере менял только адрес. Теперь «Назад» и «Вперёд» восстанавливают форму и выдачу, по одному запросу.
  • Управление формой из кода. Ползунок, выставленный из кода, двигается одним вызовом, и в запрос уходят точные границы, а не округлённые до шага. Селекты, текстовые поля и диапазоны сбрасываются, когда фильтр снят. Выбранная опция селекта больше не блокируется счётчиками.

Внимание при обновлении

Вызовы JS API отправляют запрос сами

setFilter() и removeFilter() раньше только меняли состояние, запрос уходил по submit(). Теперь запрос уходит сам. Цепочка setFilter(...).submit() по-прежнему отправляет один запрос, а код, который вызывал setFilter(), чтобы отметить значения без отправки, теперь получит запрос.

setSort(), setLimit() и setTpl() отправляют запрос не внутри вызова, а в следующей микрозадаче. Код, который сразу после setSort() проверял state.loading === true, увидит false.

Фильтры без type в наборе

Касается наборов, заданных списком ключей (["price", "color"]), и записей без type, внесённых в JSON вручную. Наборы, сохранённые в админке, тип задают всегда и не затронуты.

Тип назначается по ключу фильтра, поле field не учитывается:

КлючиТип
price, old_price, weight, width, height, length, menuindex, template, parentnumber
new, popular, favorite, published, deleted, hidemenu, isfolder, searchable, cacheable, richtextboolean
publishedon, createdon, editedon, pub_date, unpub_date, deletedondate
остальныеdefault

Типы parents, ms3_categories, vendors и colors для вывода и подсчёта значений по ключу не назначаются — задайте их в type явно.

До обновления форма считала такие фильтры числовыми и пропускала все нечисловые блоки. Теперь она выводит их с типом сервера, поэтому на странице могут появиться блоки, которых раньше не было.

Адреса фильтров по разделам

Адреса страниц фильтра по разделам (типы parents и ms3_categories) сменятся с category--15 на category--nazvanie-razdela. Старые адреса с id продолжают открываться.