strokoff

Ajax бесконечная загрузка товаров virtuemart 2.x + joomla 2.5.x — модуль

lazyloadВозникла идея реализовать для одного из проектов бесконечную подгрузку товаров и просмотр бесконечного ассортимента. Сам сайт реализован на joomla 2.5.9 с установленным virtuemart 2.20b. В целом моя реализация должна без проблем работать и на других версиях Joomla 2.5.x. В этой статье мы пройдемся по всем основным моментам создания компонента.

Структура модуля

manylazy

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

  1. mod_manylazy.php — точка входа в наш модуль
  2. helper.php — содержит функции нашего модуля
  3. tmpl/default.php — шаблон вывода
  4. ajax.php — обработка ajax запросов в модуле

Сам модуль не претендует на готовое решение и должен настраиваться вывод товаров для каждого магазина в отдельности в зависимости от шаблона, я постарался сделать все максимально простым и понятным для редактирования.

Начнем с точки входа в наш модуль файл mod_manylazy.php

[cce lang=»php»]

defined(‘_JEXEC’) or die(‘Restricted access’);
// Подключение файла helper.php
require_once JPATH_BASE.’/modules/mod_manylazy/helper.php’;

//Сколько показывать в начале.
$prod_count = $params->get(‘prod_count’);

//Подключаем шаблон mod_manylazy
require(JModuleHelper::getLayoutPath(‘mod_manylazy’));

[/cce]

Ничего особенного, все остальное мы будем делать в helper.php

[cce lang=»php»]

defined(‘_JEXEC’) or die(‘Restricted access’);
/**
* Lazy load ддя продуктов virtemart 2 и joomla 2.5.x.
* by webislife.ru
*/
class ModManyLazyHelper
{
// Получаем продукты из базы данных в определенном количестве.
public static function getProdsRand($col)
{
//Таким вот запросом, получаем имя товара, имя категории товара, его цену и ссылку на изображение товара из разных таблиц.
$sql_query = «SELECT catru.category_name, cat.virtuemart_category_id, pru.virtuemart_product_id, pru.product_name, pm.file_url, pri.product_price
FROM #__virtuemart_product_categories AS cat
INNER JOIN #__virtuemart_categories_ru_ru AS catru ON (catru.virtuemart_category_id = cat.virtuemart_category_id)
INNER JOIN #__virtuemart_products_ru_ru AS pru ON (pru.virtuemart_product_id = cat.virtuemart_product_id)
INNER JOIN #__virtuemart_product_medias AS med ON (med.virtuemart_product_id = cat.virtuemart_product_id)
INNER JOIN #__virtuemart_medias AS pm ON (pm.virtuemart_media_id = med.virtuemart_media_id)
INNER JOIN #__virtuemart_product_prices AS pri ON (pri.virtuemart_product_id = cat.virtuemart_product_id)
ORDER BY RAND()»;

$db = JFactory::getDbo();

//Выполняем запрос с ограничением $col
$db->setQuery($sql_query,0,$col);

//Для удобства пройдемся по полученным объектам и представим удобный массив для будущих ссылок
//Все это сделано в основном ради убирания .0000 у цены и построения правильных SEF ссылок в нашем магазине
$prods = array();
foreach ($db->loadObjectlist() as $key => $p)
{
$product = array();
$product[‘name’] = $p->product_name;
$product[‘cat_name’] = $p->category_name;
$product[‘cat_url’] = JRoute::_(‘index.php?option=com_virtuemart&view=category&virtuemart_category_id=’.$p->virtuemart_category_id);
$product[‘product_url’] = JRoute::_(‘index.php?option=com_virtuemart&view=productdetails&virtuemart_product_id=’.$p->virtuemart_product_id.’&virtuemart_category_id=’.$p->virtuemart_category_id);
$product[‘price’] = round($p->product_price);
$product[‘image_url’] = $p->file_url;
$prods[$key] = $product;
}

//Возвращаем массив товаров
return $prods;
}

//Простенькая функция для получения того же количества товаров из бд, только в json виде.
public static function getJsonProds($col)
{
return json_encode(self::getProdsRand($col));
}
}

[/cce]

Логика модуля очень проста. Мы подтягиваем из базы данных информацию о товаре, имя, цену, категорию, формируем SEF ссылки и все упаковываем в массив. Для будущих ajax запросов дописываем простенькую функцию. Для выполнения ajax запросов в модулях joomla 2.5 к сожалению каких-то стандартизированных решений нет и я использовал универсальный метод с обращением к joomla.

[cce lang=»php»]

//Объявлем необходимые константы для нормальной работы с Joomla
define(‘_JEXEC’, 1);
define(‘JPATH_BASE’, dirname(__FILE__) . ‘/../..’ );
define(‘DS’, DIRECTORY_SEPARATOR);

//Подключаем необходимы для работы файлы
require_once(JPATH_BASE.DS.’includes’.DS.’defines.php’);
require_once(JPATH_BASE.DS.’includes’.DS.’framework.php’);

//Отслеживаем инициализацию сайта
JFactory::getApplication(‘site’)->initialise();

//Подключаем хелпер нашего модуля
require_once JPATH_BASE.’/modules/mod_manylazy/helper.php’;

//Получаем сколько нам надо товаров за раз.
$prods = ModManyLazyHelper::getJsonProds(8);

//Для ускорения процесса умираем с выдачей результата
die($prods);

[/cce]

Вот и все обработка запроса. Теперь перейдем непосредственно к шаблону и javascript коду.

В шаблоне default.php изначально вызываем нашу функцию из хелпера и получаем первые товары. Далее массивом в html выводим наши товары.

[cce lang=»php»]

defined(‘_JEXEC’) or die(‘Restricted access’);
//Получаем товары
$prods = ModManyLazyHelper::getProdsRand($prod_count);

[/cce]

Вот html шаблон. В моем случае по умолчанию блок спрятан и только после клика по ссылке «Перейти к бесконечному просмотру» мы добавляем слушатель события для window.scroll и показываем основной контейнер. Суть автоподгрузки проста, как только в поле зрения попадает блок «Загружаем еще» мы отправляем ajax запрос к серверу на получение новых случайных товаров и выводим их через javascript

[cce lang=»html»]

<div class=»row-fluid»>
<div class=»span12″>
<div class=»lazy_start_show»>Посмотреть бесконечный ассортимент!</div>
</div>
</div>
<div class=»row-fluid» id=»main_lazy_container»>

<div class=»span12 lazy_container_prods»>
<?
foreach($prods as $p)
{
?>
<div class=»lazy_block_product»>
<div class=»lazy_block_image image_cont»>
<img src=»<? echo $p[‘image_url’]; ?>» alt=»<? echo $p[‘name’]; ?>»>
</div>
<div class=»product_price_block»>
<? echo $p[‘price’].’ руб.’; ?>
</div>
<div class=»product_title»>
<p class=»lazy_category_link»>
Категория: <a href=»<? echo $p[‘cat_url’];?>»><? echo $p[‘cat_name’]; ?></a>
</p>
<a class=»lazy_product_link» href=»<? echo $p[‘product_url’];?>»><? echo $p[‘name’]; ?></a>
</div>
</div>
<?
}
?>
</div>
<div class=»span12″>
<div class=»lazy_loader_trigger»><p class=»lazy_loader»>Загружаем еще…</p></div>
</div>
</div>

[/cce]

[cce lang=»javascript»]

jQuery(document).ready(function($) {
//Текущий статус загрузки, чтобы не плодить кочу запросов к серверу. Пока не выполнен один запрос, второй отсылать не будем.
var currentload = false;

//Наша функция подгрузки товаров
var lazyLoader = function()
{
//Определяем высоту прокрутки
var wt = $(window).scrollTop();

//Получаем позицию низа экрана
var wb = wt + $(window).height();

//Получаем значение отступа нашего блока подгрузчика
var lt = $(‘.lazy_loader_trigger’).offset().top;

//Если низ экрана стал ниже отступа блока подгрузчика и текущая загрузка не запущена
if(wb > lt && currentload == false)
{
//Посылаем запрос
$.ajax({

//Все стандартно, при необходимости можно и данные передать
url: ‘/modules/mod_manylazy/ajax.php’,
type: ‘POST’,
dataType: ‘json’,
data: {},
success: function(data, status)
{
//Формируем html шаблон из возвращенного json ответа
var html = »;
var l = data.length;
for(var key in data)
{
var val = data[key];
//Иногда ответ может придти пустым… проверяем.
if(val[‘price’] != undefined) {
//Разметка
html += ‘<div class=»lazy_block_product»>’;
html += ‘<div class=»lazy_block_image image_cont»>’;
html += ‘<img src=»‘+val[‘image_url’]+'» alt=»‘+val[‘name’]+'» /></div>’;
html += ‘<div class=»product_price_block»>’+val[‘price’]+’ руб.</div>’;
html += ‘<div class=»product_title»>’;
html += ‘<p class=»lazy_category_link»>Категория: <a href=»http://manytomany.ru’+val[‘cat_url’]+'»>’+val[‘cat_name’]+'</a></p>’;
html += ‘<a class=»lazy_product_link» href=»http://manytomany.ru’+val[‘product_url’]+'»>’+val[‘name’]+'</a>’;
html += ‘</div>’;
html += ‘</div>’;
}
}
//Добавляем новые блоки
$(‘.lazy_container_prods’).append(html);
currentload = false;
},
//Перед отправкой показываем лоадер
before: function()
{
$(‘.lazy_loader’).show();
currentload = true;
},
//Ошибку просто выводим в консоль
error: function(data)
{
console.error(data);
}

});

}
}
//По клику приступить к просмотру, добавляем событие на скролл окна и показываем контейнер с товарами
$(‘.lazy_start_show’).on(‘click’, function()
{
$(‘#main_lazy_container’).show(300);
$(window).on(‘scroll’, lazyLoader);
});
});

[/cce]

CSS Разметку я приводить не буду и в модуле ее по умолчанию нету т.к. этот момент на мой взгляд сугубо индивидуальный и установка с настройкой подобного модуля подразумевает присутствие у вас некоторых навыков в HTML, javascript и php. Посмотреть пример работы модуля вы можете на сайте manytomany.ru скачать и ознакомиться с кодом вы можете на github