Ajax бесконечная загрузка товаров virtuemart 2.x + joomla 2.5.x — модуль
Возникла идея реализовать для одного из проектов бесконечную подгрузку товаров и просмотр бесконечного ассортимента. Сам сайт реализован на joomla 2.5.9 с установленным virtuemart 2.20b. В целом моя реализация должна без проблем работать и на других версиях Joomla 2.5.x. В этой статье мы пройдемся по всем основным моментам создания компонента.
Структура модуля
Я не буду затрагивать устройства таких файлов как index.html и составления xml описания файла, при необходимости вы можете скачать или посмотреть модуль на гитхабе. Остановлюсь лишь на основных файлах.
- mod_manylazy.php — точка входа в наш модуль
- helper.php — содержит функции нашего модуля
- tmpl/default.php — шаблон вывода
- 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