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

28 Августа 2014 5439 , , , , ,

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

1
2
3
4
5
6
7
8
9
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'));

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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));
}
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//Объявлем необходимые константы для нормальной работы с 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);

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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);
});
});

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

Подписывайтесь на обновления

Читайте RSS ленту

Комментарии

Добавить комментарий