Наверх

Простой AJAX-фильтр для MODX с помощью pdoPage

Да, ещё один способ реализации Ajax-фильтра на сайте =)

Начнём с простого вывода на странице обычного списка ресурсов. Обязательно добейтесь, чтобы нормально работала AJAX-пагинация, потому что своих механизмов работы с AJAX мы писать не будем, а будем использовать методы AJAX, которые есть в pdoPage.

<div id="pdopage">
  <div class="rows row">
  {'!pdoPage' | snippet : [
    'ajaxMode' => 'default',
    
    'parents' => 0,
    'limit' => 3,
    
    'includeTVs' => 'height,weight,speed_type',
    'tvPrefix' => '',
    
    'tpl' => '@INLINE 
      <div class="col-sm-6 col-md-4">
        <div class="thumbnail">
          <div class="caption">
            <h3>{$pagetitle}</h3>
            <p>Вес: {$weight}</p>
            <p>Высота: {$height}</p>
            <p>Тип: {$speed_type}</p>
          </div>
        </div>
      </div>',
  ]}
  </div>
  {'page.nav' | placeholder}
</div>


Для фильтров я буду использовать такую вёрстку. Но вёрстка тут особой роли не играет — главное указать правильные классы в JS-коде.

<form class="form-horizontal" id="filters" action="">
  <div class="form-group">
    <label class="col-sm-1 control-label">Вес</label>
    <div class="col-sm-5">
      <input type="number" name="weight" class="form-control" placeholder="47">
    </div>
    <label class="col-sm-1 control-label">Высота</label>
    <div class="col-sm-5">
      <input type="number" name="height" class="form-control" placeholder="120">
    </div>
  </div>
  
  <div class="form-group">
    <label class="col-sm-1 control-label">Тип</label>
    <div class="col-sm-11">
      <div class="btn-group" data-toggle="buttons">
        <label class="btn btn-default">
          <input type="radio" name="speed_type" value="fast"> Быстрые
        </label>
        <label class="btn btn-default">
          <input type="radio" name="speed_type" value="slow"> Медленные
        </label>
      </div>
    </div>
  </div>
</form>

JS-код обработки фильтров выглядит как-то так:

$(document).on('change keyup', '#filters input', function(){
    // Проверяем, что pdoPage подключён
    if (typeof(pdoPage) == 'undefined') return;
    
    // Собираем значения всех фильтров в единый массив
    var fields = {};
    $.each($('#filters').serializeArray(), function(){
        fields[this.name] = this.value;
    });
    
    // И отправляем этот массив на сервер.
    $.post(document.location.href, {
            action: 'filter',
            fields: fields,
            // Параметр hash - обязательный (он содержит настройки pdoPage)
            hash: pdoPage.configs.page.hash
        }, function(data) {
            // Просим pdoPage загрузить новый список ресурсов
            var tmp = document.location.href.split('?');
            pdoPage.keys.page = 0;
            pdoPage.loadPage(tmp[0], pdoPage.configs.page);
        });
});

Уже сейчас при изменении значения фильтров список ресурсов будет обновляться. Теперь осталось «объяснить», как обрабатывать фильтры. Для этого создаём плагин на событие OnHandleRequest:

<?php
if ($modx->context->key == 'mgr' || empty($_SERVER['HTTP_X_REQUESTED_WITH']) || $_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest') return;
switch ($_POST['action']) {
    case 'filter':
        $output = array('success' => false, 'message' => '');
        
        // Проверяем, что hash получен и параметры pdoPage существуют
        if (isset($_POST['hash']) && !empty($_POST['hash'])
            && isset($_SESSION['pdoPage'][$_POST['hash']])
            && !empty($_SESSION['pdoPage'][$_POST['hash']])) {

            $hash = (string) $_POST['hash'];
            
            // Указываем только ТВ, доступные для фильтрации
            $tvs = array('height','weight','speed_type');
            
            // Наполняем условие выборки
            $where = array();
            foreach ($tvs as $tv) {
                if (isset($_POST['fields'][$tv]) && $_POST['fields'][$tv] !== '') {
                    $where[$tv] = $_POST['fields'][$tv];
                }
            }
            
            // Добавляем это условие в параметры pdoPage "на лету"
            $_SESSION['pdoPage'][$hash]['where'] = $where;
            
            $output['message'] = $where;
            $output['success'] = true;
        } else {
            $output['message'] = 'Error';
        }
        echo $modx->toJSON($output);
        die();
        break;
    default:
        break;
}

Теперь наши фильтры работают. Единственное — pdoPage «не знает», что показывать, когда ни один результат не найден. Чтобы такой случай учесть, создадим файл pdopage.custom.js и укажем его в параметре frontend_js:

{'!pdoPage' | snippet : [
    'ajaxMode' => 'default',
    'frontend_js' => '/assets/components/pdotools/js/pdopage.custom.js',

    'parents' => 0,
    'limit' => 3,
    // ...
}

В стандартном коде мы добавим только условие else на случай, если ответ от сервера будет пустым:

// ...
pdoPage.loadPage = function (href, config, mode) {

    // ...

    $.post(config['connectorUrl'], params, function (response) {
        if (response && response['total']) {
            // ...
        } else { // Добавляем условие else
            wrapper.find(rows).html('Ничего не найдено');
            wrapper.find(pagination).html('');
            wrapper.removeClass('loading');
            wrapper.css({opacity: 1});
            if (config['mode'] == 'default') {
                $('html, body').animate({scrollTop: wrapper.position().top - 50 || 0}, 0);
            }
        }
    }, 'json');
};
// ...

На этом простой AJAX-фильтр готов.


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

    Авторизация

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

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

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



    Шаблоны MODX

    1 2 Дальше »

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