Как правильно внедриться в mFilter2?

Уважаемые коллеги. Может кто советом поможет. Ситуация такая — работает mFilter2: выводится 20 товаров на странице с стандартной пагинацией в виде кнопок. Нужно чтобы через каждые к примеру 5 товаров выводился баннер (если товаров 20 на странице, то их к примеру 3, если 40 то 6 и т.д.). При чем баннеры разные и зависят от фильтра.
Вывод баннеров понятно можно сделать в tpl написав условие
{if $banners[$idx]}{$banners[$idx]['image']}{/if}
. Но как сделать чтобы поиск самих баннеров (сам сниппет) происходил 1 раз за запрос фильтра или входа на страницу?

Сейчас реализован лишь поиск баннеров типа
{var $banners = 'getBanners' | snippet}
который возвращает список с ключом номера товара после или до которого должен стоять. Но ей Богу не запускать же этот сниппет в каждой tpl.
Евгений Лазарев
19 декабря 2020, 20:11
modx.pro
521
0

Комментарии: 4

Артур Шевченко
19 декабря 2020, 22:42
+1
Я вот тут поступил так.
1. Разместил в шаблоне блок в котором должен быть баннер с классом jsInnerBanner, скрытно.
2. Пометил все превьюхи классом к примеру jsBannerMark.
3. Повесил обработчик на событие mse2_load
$(document).on('mse2_load', function(e, data) {
            insertBanner('.jsBannerMark','.jsInnerBanner', 0.6)
        });
Сама функция insertBanner ищет скрытый блок, вытаскивает из него шаблон баннера и вставляет в нужное место, я сделал в процентах, но вы можете сделать как вам нравится.
function insertBanner(mark,banner, percent){
        var count = $(mark).length,
            banner = $(banner).clone(),
            position = Math.round(count * percent);
       banner.find('.promo').addClass('jsBanner');
        if((position % 2) != 0){
            position = position + 1;
        }
        if(count > 1){
            if(mark == '.jsBannerMark'){
                $(mark)[position - 1].after(banner[0]);
            }
            if(mark == '.jsMaterialMark'){
                $(mark)[position - 1].before(banner[0]);
            }
        }else{
            $(mark).after(banner[0]);
        }
    }
Сами баннеры я сделал в виде ресурсов и забираю их через pdoResources. Конечно в чистом виде вам моё решение не подойдет, но думаю общая идея пригодится.
    Евгений Лазарев
    31 января 2021, 13:20
    0
    Решение хорошее, но не совсем подходит, потому что оно работает после того как отобразился контент товаров.
    Евгений Лазарев
    31 января 2021, 13:27
    +1
    Вдруг кому понадобится: я решил этот момент следующим образом:
    1) создал кастомный сlass customFilter extends mse2FiltersHandler, возможность создания которого предусмотрена компонентом
    2) переназначил функцию constract
    public function __construct(mSearch2 &$mse2, array $config = array()) {
    		parent::__construct($mse2, $config);
            $this->catalogBanners();
    	}
    3) В своей функции catalogBanners() выполнил что мне нужно:
    public function catalogBanners(){
            $banners = json_decode($this->modx->resource->getTVValue('migx_catbans'),true);
    
            $fabrics = $_REQUEST['fabric'] ? explode(',',$_REQUEST['fabric']) : [];
            $metals = $_REQUEST['metal'] ? explode(',',$_REQUEST['metal']) : [];
    
            $key = md5(implode('|', array_merge($fabrics, $metals)));
    
            if (isset($_SESSION['catbans']) and $_SESSION['catbans']['key'] === $key){
                return true;
            }
            shuffle($banners);
    
            $is_main = (empty($fabrics) and empty($metals)) ? true : false;
    
            $catbans = [];
            foreach ($banners as $idx=>$banner){
                $is_good = true;
                $migx_fabric = is_array($banner['fabric']) ? $banner['fabric'] : explode(',',$banner['fabric']);
                if (empty(array_intersect($fabrics, $migx_fabric)) and !empty($banner['fabric']) and !$is_main){
                    $is_good = false;
                }
                $migx_metal = is_array($banner['metal']) ? $banner['metal'] : explode(',',$banner['metal']);
                if (empty(array_intersect($metals, $migx_metal)) and !empty($banner['metal']) and !$is_main){
                    $is_good = false;
                }
                if ($is_good){
                    //Расчет позиции нахождения баннера (3,17,35,49,67)
                    $position = 3 + count($catbans) * 14 + intdiv(count($catbans), 2) * 4;
                    $catbans[$position] = $banner;
                }
            }
    
            $_SESSION['catbans'] = $catbans;
            $_SESSION['catbans']['key'] = $key;
    
            return true;
        }
    4) в tpl mFilter2 уже обращаясь к сессии взял что мне нужно:
    {var $catbans = $.session.catbans}
    {if $catbans[$idx]}
    <a href="{$catbans[$idx]['href']}" class="banner">
        <img src="/images/{$catbans[$idx]['img']}" alt="" />
    </a>
    {/if}
    Итого:
    — вызывается 1 раз, как и нужно и с появлением контента
    — нет причин бояться обновления компонента
    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
    4