Бесконечная прокрутка новостей Ajax

Делимся интересными и полезными решениями
Аватара пользователя
M@dD3n
Администратор
Сообщения: 654
Зарегистрирован: 25 июн 2015, 09:20
Откуда: Russia
Благодарил (а): 28 раз
Поблагодарили: 99 раз
Контактная информация:

Бесконечная прокрутка новостей Ajax

Сообщение M@dD3n » 25 сен 2017, 13:28

Делаем простенькую прокрутку новостей, с подгрузкой по аякс и сменой url и title

Первое что понадобится это пару библиотек для jQuery, добавляем их в основной шаблон или header рубрики

Код: Выделить всё

<script src="https://cdnjs.cloudflare.com/ajax/libs/waypoints/4.0.1/jquery.waypoints.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/waypoints/4.0.1/shortcuts/inview.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/history.js/1.8/bundled/html4+html5/jquery.history.min.js"></script>


Рубрика с новостями (шаблон вывода новости)
Перед HTML пишем PHP код

Код: Выделить всё

<?
    
//-- Следующая новость

    //-- ID поля Документ из рубрики
    $field_id = 10;

    //-- Массив всех документов из данной категории
    $docs = array();

    //-- Выбираем все активные документы из этой категории (Документ из рубрики)
    $sql = $AVE_DB->Query("
        SELECT
            d.Id
        FROM
            "
 . PREFIX . "_documents AS d
        LEFT JOIN
            "
 . PREFIX . "_document_fields AS df
            ON d.Id = df.document_id    
        WHERE
            d.rubric_id = '4'
        AND
            d.document_status = '1'
        AND
            d.document_deleted = '0'
        AND
            df.rubric_field_id = '10'
        AND
            df.field_value = '"
 . get_field($field_id, '[tag:docid]') . "'
    "
);

    $doc_ii = 0;

    while ($id_doc = $sql->GetCell())
    {
        $docs['doc' . $doc_ii] = (int)$id_doc;
        $doc_ii++;
    }

    //-- Позиция текущего Документа
    $this_key = ltrim(array_search('[tag:docid]', $docs), 'doc');

    //-- Если первый, назначаем следующий документ
    if ($this_key == 0)
    {
        $netx_key = $docs['doc' . ($this_key + 1)];
    }
    //-- Если последний, назначаем ему первый документ из списка
    else if ($this_key == (count($docs) - 1))
        {
            $netx_key = $docs['doc' . 0];
        }
        //-- В остальных случаях, всегда следующий документ
        else
            
{
                $netx_key = $docs['doc' . ($this_key + 1)];
            }
    //-- Убираем ненужное
    unset ($docs, $doc_ii, $this_key);
?>


Сам шаблон (HTML)

Код: Выделить всё

<section class="full-article" id="article-[tag:docid]" data-title="[tag:title]" data-url="[tag:path][tag:alias]" data-next="<?= $netx_key; ?>" data-id="[tag:docid]">
<!-- Тут оформление новости -->
</section>


Оформляем тизер в этой рубрике, по такому же принципу

Сам шаблон тизера (HTML)
Перед HTML пишем PHP код

Код: Выделить всё

<?
    
//-- Следующая новость

    //-- ID поля Документ из рубрики
    $field_id = 10;

    //-- Массив всех документов из данной категории
    $docs = array();

    //-- Выбираем все активные документы из этой категории (Документ из рубрики)
    $sql = $AVE_DB->Query("
        SELECT
            d.Id
        FROM
            "
 . PREFIX . "_documents AS d
        LEFT JOIN
            "
 . PREFIX . "_document_fields AS df
            ON d.Id = df.document_id    
        WHERE
            d.rubric_id = '4'
        AND
            d.document_status = '1'
        AND
            d.document_deleted = '0'
        AND
            df.rubric_field_id = '10'
        AND
            df.field_value = '"
 . get_field($field_id, '[tag:docid]') . "'
    "
);

    $doc_ii = 0;

    while ($id_doc = $sql->GetCell())
    {
        $docs['doc' . $doc_ii] = (int)$id_doc;
        $doc_ii++;
    }

    //-- Позиция текущего Документа
    $this_key = ltrim(array_search('[tag:docid]', $docs), 'doc');

    //-- Если первый, назначаем следующий документ
    if ($this_key == 0)
    {
        $netx_key = $docs['doc' . ($this_key + 1)];
    }
    //-- Если последний, назначаем ему первый документ из списка
    else if ($this_key == (count($docs) - 1))
        {
            $netx_key = $docs['doc' . 0];
        }
        //-- В остальных случаях, всегда следующий документ
        else
            
{
                $netx_key = $docs['doc' . ($this_key + 1)];
            }
    //-- Убираем ненужное
    unset ($docs, $doc_ii, $this_key);
?>



Сам шаблон (HTML)

Код: Выделить всё

<section class="full-article" id="article-[tag:docid]" data-title="[tag:doctitle]" data-url="[tag:link]" data-next="<?= $next_key; ?>" data-id="[tag:docid]">
<!-- Тут оформление новости -->
</section>


Создаем Системный блок, по желанию присваиваем алиас
Ставим галочки:
Разрешить внешнее обращение по ссылке
Разрешать выполняться только по Ajax

Код: Выделить всё

<?
    if 
(isset($_REQUEST['next_id']) && is_numeric($_REQUEST['next_id']))
    {
        eval('?>' . showteaser((int)$_REQUEST['next_id']) . '<?');
    }
?>


Создаем в папке шаблона новый файл для JS кода (или используем уже имеющийся)

Код: Выделить всё

var localElement,            //-- Null
   ajaxStart = false,         //-- False
   offsetScroll = 250,         //-- Пикселей до конца страницы, прежде чем начнет выполнятся Аякс
   selectElement = 'section',   //-- Селектор
   sysblock_id = 'ring';      //-- ID или Алиас Системного блока

var Scroll = {

   initialized: false,

   initialize: function () {

      if (this.initialized)
         return;

      this.initialized = true;

      this.build();
      this.events();
   },

   build: function() {
      this.StartPoints();
   },

   events: function() {
      this.WindowHistory();
      this.WindowScroll();
   },


   WindowScroll: function()
   {
      $(window).scroll(function () {
         if ($(window).height() + $(window).scrollTop() + offsetScroll >= $(document).height()) {
            //-- ID следующего документа
            var docid = $(selectElement + ':last').data('next');

            if (ajaxStart == false)
            {
               ajaxStart = true;

               $.ajax({
                  url: '/',
                  data: {
                     sysblock: sysblock_id,
                     next_id: docid
                  },
                  type: 'POST',
                  beforeSend: function () {
                     //-- Действия перед выполнением аякса (можно показать прелоадер и тд)
                  },
                  complete: function() {
                     //-- Действия когда запрос совершен (можно убрать прелоадер и тд)
                  },
                  success: function (data) {
                     //-- Добавляем информацию после последнего элемента (селектор)
                     $(selectElement + ':last').after(data);
                     //-- Удаляем все маркеры (плагин js)
                     Waypoint.destroyAll();
                     //-- Назначаем маркеры (плагин js)
                     Scroll.StartPoints();
                     //-- False
                     ajaxStart = false;
                  }
               });
            }
         }
      });
   },

   StartPoints: function()
   {
      var Elements = $(selectElement);

      for (var i = 0; i < Elements.length; i++) {
         new Waypoint({
            element: Elements[i],
            handler: function(direction) {
               //-- Local ID != Element ID
               var element_id = $(this.element).data('id');

               //-- Local ID != Element ID
               if (localElement != element_id)
               {
                  //-- URL
                  var url = $(this.element).data('url');
                  //-- TITLE
                  var title = $(this.element).data('title');

                  //-- Object history data
                  var obj = {
                     Title: title,
                     Url: url
                  };

                  //-- Подменяем Title и URL в браузере
                  Scroll.PushState(obj);

                  localElement = element_id;
               }
            },
            offset: function () {
               return 0;
            }
         });

         new Waypoint.Inview({
            element: Elements[i],
            //-- InView Event
            exit: function(direction) {
               //-- Element ID
               var element_id = $(this.element).data('id');
               //-- Direction
               if (direction == 'up')
               {
                  //-- Local ID != Element ID
                  if (localElement != element_id)
                  {
                     //-- URL
                     var url = $(this.element).data('url');
                     //-- TITLE
                     var title = $(this.element).data('title');

                     //-- Object history data
                     var obj = {
                        Title: title,
                        Url: url
                     };

                     //-- Подменяем Title и URL в браузере
                     Scroll.PushState(obj);

                     localElement = element_id;
                  }
               }
            }
         });
      }
   },

   WindowHistory: function ()
   {
      window.History.Adapter.bind(window, 'statechange', function(event) {
         var state = window.History.getState();
      });
   },

   PushState: function (obj)
   {
      if (obj) {
         //-- Подменяем Title и URL в браузере
         window.History.pushState(obj, obj.Title, obj.Url);
         //-- Можно дописать любые дополнительные действия, например сказать Google Analytics, что мы как бы перешли на другую страницу и тд
      }
   }
};

$(document).ready(function() {
   Scroll.initialize();
});


Не забываем добавить вызов этого файла в шаблон

Все, теперь при прокрутке новости, будет подгружаться следующая, из этой категории. При скроле на нее, будут подменяться Title и Url в браузере

Это простой пример, без лишних проверок и всего подобного

Живой пример

Вернуться в «Интересные решения»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость