MODX - Вывод случайного ресурса с помощью AJAX

Урок, на котором рассмотрим, как в MODX Revolution с помощью технологии AJAX реализовать вывод случайной статьи на странице.

Описание процесса вывода случайной статьи на странице

MODX Revolution - Вывод случайной статьи на странице
MODX Revolution - Вывод случайной статьи на странице

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

  1. Создать на стороне клиента (с помощью скрипта JavaScript) асинхронный запрос и отправить его на сервер по адресу текущей страницы.
  2. Получить запрос, отправленный клиентом, на сервере с помощью сниппета (ajaxSnippet). В этом сниппете будем обрабатывать полученный запрос, формировать ответ и отправлять его клиенту (веб-браузеру).
  3. В этот время (после того как мы отправили запрос на сервер) страница (веб-браузер) ждёт на него ответ… Как только ответ прийдет с сервера, выводим его с помощью JavaScript на страницу.

Кроме этого выводить будем не одну случайную статью после загрузки страницы, а организуем так называемое слайд-шоу. Т.е. будем заменять одну случайную статью другой через некоторое время (например, для наглядности через 5 секунд).

Схема, описывающая процесс вывода случайной статьи на страницу
Схема, описывающая процесс вывода случайной статьи на страницу

На уровне кода необходимо будет выполнить следующее:

  • В шаблоне "Пост":
    • создать контейнер (блок div) в который будем выводить случайную статью;
    • создать js-код, который будет выполнять 3 основные действия: отправлять запрос на сервер, получать от него ответ и отображать его на странице. Данный JavaScript код создадим не в самом шаблоне, а в чанке "chunk.footer", который будет вызываться из данного шаблона;
    • поместить вызов некэшируемого сниппета "ajaxSnippet". Он будет обрабатывать на сервере запрос, поступивший от клиента и отправлять ему ответ.
  • Создать в MODX сниппет, имеющий имя ajaxSnippet. Он будет выполнять действия ("магию") вышеприведённого пункта.

Код сниппета ajaxSnippet

В сниппете для получения случайной статьи будем использовать сниппет getTicket. Получать случайную статью будем из раздела, который имеет идентификатор 4.

MODX Revolution - Создание сниппета ajaxSnippet
MODX Revolution -  Создание сниппета ajaxSnippet
<?php
// Если  запрос не AJAX (XMLHttpRequest), то завершить работу
if ($_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest') {return;}

// Проверяем является ли $_POST['action'] пустым. Если да, то завершаем работу
if (empty($_POST['action'])) {return;}

// В противном случае выполняем следующие действия:
// 1. Заводим переменную, которая будет хранить результат
$res = '';
// 2. Так как данный сниппет можно будет использовать и для других запросов, то выберем действие которе нужно выполнить с помощью оператора switch
switch ($_POST['action']) {
  case 'randomTicket':
    // 3. Параметры для выполнения сниппета
    $param = array(
      'sortby' => 'RAND()',
      'limit' => 1,
      'tpl'=> '@INLINE <h3>[[+pagetitle]]</h3>[[+introtext]]<p><a href="[[~[[+id]]]]" class="btn btn-primary" role="button">Читать далее...</a>',
      'parents'=> 4
    );
    // 4. Выполнить сниппет getTickets 
    $res = $modx->runSnippet('getTickets',$param);
    break;
  // При необходимости можно добавлять новые методы
}

// Если ответ не пустой, то отдаём и прерываем работу парсера MODX
if (!empty($res)) {
  // Выводит сообщение ($res) и прекращает выполнение текущего скрипта
  die($res);
}

Код шаблона "Пост"

Внесём следующие изменения в шаблон "Пост":

MODX Revolution - Изменение шаблона Пост
MODX Revolution -  Изменение шаблона Пост
  1. Поместим блок с идентификатором randomTicket в контейнер, имеющий класс col-md-4:
    <div class="col-md-4">
      [[$search]]
      <div id="randomTicket" class="thumbnail" style="padding:15px;"></div>
    
  2. Поместим вызов сниппета ajaxSnippet:
    <div class="col-md-4">
      [[$search]]
      <div id="randomTicket" class="thumbnail" style="padding:15px;"></div>
      [[!ajaxSnippet]]
    
  3. Добавим JavaScript код в чанк "chunk.footer":
    MODX Revolution - Изменение чанка chunk.footer
    MODX Revolution -  Изменение чанка chunk.footer
    <script>
    // после загрузки страницы
    $(function() {
      // вызвать функцию showRandomTicket()
      showRandomTicket();
      // смену новости будем выполнять каждые 5 секунд
      setInterval(showRandomTicket, 5000);
      // функция showRandomTicket()
      function showRandomTicket() {
        // Выполняем ajax запрос к текущей страницы (к сниппету ajaxSnippet) методом post
        $.post(document.location.href, {action: 'randomTicket'}, function(data) {
          // полученный ответ выводим в блок, имеющий идентификатор randomTicket     
          // вывод блок будем сопровождать анимацией
          $('#randomTicket').fadeOut(300, function() {
            $(this).html(data).fadeIn(800);
          });
        });
      };
    });
    </script>
    

Демонстрация работы созданного кода

Проделанную работу продемонстрируем с помощью следующего видео ролика:



   MODX Revo 0    1682 +1

Комментарии (9)

  1. Андрей # 0
    Всем привет! Подскажите, как на основании этой статьи реализовать, допустим, галерею случайных статей с фото и интротекстом? Я не понимаю, как это сделать для вывода фото с помощью ms2Gallery. На данный момент у меня это реализовано без аякса таким кодом:
    <h3 class="widget_title">Случайные статьи</h3>
    <ul>
      [[!getTickets?
        &parents=`7` 
        &depth=`1` 
        &tpl=`tpl.random.post` 
        &includeTVs=`tags` 
        &processTVs=`1`
        &includeContent=`1`
        &limit=`3`
        &sortby=`RAND()`
        &hideContainers=`1`
        &loadModels=`ms2gallery` 
        &leftJoin=`{
          "120x90": {"class":"msResourceFile","alias":"120x90", "on": "120x90.resource_id = Ticket.id AND 120x90.path LIKE '%/120x90/' AND 120x90.rank=0"}
          }`
        &select=`{"Ticket":"*","120x90":"120x90.url as 120x90"}`
        &showLog=`0`
      ]]
    </ul>
    
    Спасибо.
    1. Александр Мальцев # 0
      Всё тоже самое.
      Необходимо только изменить параметры в коде сниппета ajaxSnippet в п.3.
      1. Андрей # 0
        Сделал сниппет в пункте 3 такого содержания
        // 3. Параметры для выполнения сниппета
            $param = array(
              'sortby' => 'RAND()',
              'limit' => 3,
        	  'depth' => 1,
        	  'hideContainers' => 1,
        	  'processTVs' => 1,
        	  'includeContent' => 1,
        	  'includeTVs' => 'tags',
        	  'loadModels' => 'ms2gallery',
              'tpl'=> '@INLINE <li class="clearfix">
          <div class="scale_image_container">
        	<a href="[[~[[+id]]]]"><img src="[[+120x90]]" alt="[[+pagetitle]]" class="scale_image"></a>
        	<div class="post_image_buttons">
        	  <a href="#" class="icon_box">
        		<i class="fa fa-file-text"></i>
        	  </a>
        	</div>
          </div>
          <div class="post_text">
        	<a href="[[~[[+id]]]]"><h4>[[+pagetitle:ellipsis=`20`]]</h4></a>
        	<div class="event_date">[[+date_ago]]</div>
          </div>
        </li>',
              'parents'=> 7,
        	  'leftJoin'=> '{"120x90": {"class":"msResourceFile","alias":"120x90", "on": "120x90.resource_id = Ticket.id AND 120x90.path LIKE '%/120x90/' AND 120x90.rank=0"} }',
        	  'select'=> '{"Ticket":"*","120x90":"120x90.url as 120x90"}'
            );
        Ошибка 500, страница не грузится
        И почему-то конфликтует скрипт с jquery.tweet.js, который у меня в шаблоне
    2. Легион # 0
      <div class="col-md-4">
        [[$search]]
        <div id="randomTicket" class="thumbnail" style="padding:15px;"></div>
        [[!ajaxSnippet]
       
      Пропущена закрывающая скобка. Кстати, запустить мне так и не удалось выборку. Возможно потому, что пока только две тестовые новости.
      1. Александр Мальцев # 0
        Спасибо, исправил.
        Посмотрите, что у Вас возвращается в браузере на вкладке Network.
      2. Демьян Золин # 0
        Здравствуйте.

        Кнопку " Читать далее..." как убрать?

        Спасибо.
        1. Александр Мальцев # +1
          Необходимо отредактировать шаблон, на основании которого осуществляется вывод:
          'tpl'=> '@INLINE <h3>[[+pagetitle]]</h3>[[+introtext]]<p><a href="[[~[[+id]]]]" class="btn btn-primary" role="button">Читать далее...</a>',
          
          Т.е. в качестве значения оставить только:
          'tpl'=> '@INLINE <h3>[[+pagetitle]]</h3>[[+introtext]]<p>',
          
        2. Демьян Золин # 0
          Здравствуйте.
          Как и где добавить кнопку или ссылку «Следующая статья»
          Спасибо.
          Вывожу случайные цитаты
          Первомай
          1. Александр Мальцев # 0
            Здравствуйте. Необходимо сделать следующее:
            1. В сниппете ajaxSnippet необходимо изменить параметр tpl, а именно добавить кнопку с помощью которой пользователь будет вызывать следующую случайную запись:
            'tpl'=> '@INLINE <h3>[[+pagetitle]]</h3>[[+introtext]]<p><a href="[[~[[+id]]]]" class="btn btn-primary" role="button">Читать далее...</a> <div><button id="nextArticle" class="btn btn-danger">Следующая статья</button></div>',
            
            2. Изменить сценарий JavaScript следующим образом (т.е. добавить обработчик события click для кнопки #nextArticle):
            <script>
            $(function() {
              //...
              $(document).on('click','#nextArticle',function(){
                clearInterval(intervalShowTicket);
                showRandomTicket();
                intervalShowTicket = setInterval(showRandomTicket, 10000);
              });
            });
            </script>
            

          Вы должны авторизоваться, чтобы оставлять комментарии.