При создании интернет-магазин часто используются фильтры товара по характеристикам , пользователей раздражает когда при изменение свойств поиска, идет перезагрузка страницы, давай те исправим это положение и сделаем полноценный фильтр на ajax .
Мы будем использовать хэш что бы была возможность ложить ссылку в закладку, кидать другу и использовать историю для перехода назад к параметрам поиска .
Делать мы будем все это чудо с помощью jquery , загрузим его с гугла .
Использовать я буду стандартный модуль каталог , в нем нам надо будет изменить шаблон вывода фильтра catalog/castlerock/castlerock.catalog.filter/.default/template.php обернув его в тег с классом catalog-filter и добавить туда два скрых поля с параметрами раздела и инфоблока .
Так же надо в шаблоне фильтра catalog/castlerock/castlerock.catalog.filter/.default/ добавить файл result_modifier.php и в нем назначить вывод в массив двух переменных
В файле вывода фильтра и элементов раздела надо, добавить в модуль фильтра еще два параметра (SECTION_CODE и IBLOCK_ID) обернуть вывод элементов разделе в тег с классом list-selection-element,
Собственно теперь напишем сам скрипт на js , первая функция необходима для того что бы заполнять форму когда человек заходим с хэшем в строке, вторая функция для того что бы сократить количество кода для каждого ajax запроса, дальше функции непосредственно для ajax запросов.
Теперь напишем сам обработчик для вывод элементов каталога, постраничной навигации , его можно будет сделать любой сложности в зависимости от поступающих параметров в запросе $_POST
Для постраничной навигации я сделал свой шаблон для того что бы работал ajax , назвал я его ajaxarrow , в нем я добавил только к ссылкам id с номером страницы id="ajaxpage=<?=$sNextcount;?>" и класс ajax-navigation обертыш этого шаблона.
Вот собственно и все , первоисточник .
Мы будем использовать хэш что бы была возможность ложить ссылку в закладку, кидать другу и использовать историю для перехода назад к параметрам поиска .
Делать мы будем все это чудо с помощью jquery , загрузим его с гугла .
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script> |
Использовать я буду стандартный модуль каталог , в нем нам надо будет изменить шаблон вывода фильтра catalog/castlerock/castlerock.catalog.filter/.default/template.php обернув его в тег с классом catalog-filter и добавить туда два скрых поля с параметрами раздела и инфоблока .
<div class="catalog-filter">
<form name="<?echo $arResult["FILTER_NAME"]."_form"?>" action="<?echo $arResult["FORM_ACTION"]?>" method="get">
<!-- скрытые поля -->
<input type="hidden" name='AJAXSELECTION_IBLOCK_ID' value='<?=$arResult["IBLOCK_ID"];?>' />
<input type="hidden" name='AJAXSELECTION_SECTION_CODE' value='<?=$arResult["SECTION_CODE"];?>' />
<div class="catalog-item-filter<?if ($arResult['IS_FILTERED']):?> filter-active<?endif;?>">
<div class="catalog-item-filter-body" id="catalog_item_filter_body">
<b class="r1"></b>
<div class="catalog-item-filter-body-inner">
<table cellspacing="0" class="catalog-item-filter" id="catalog_item_filter_table">
<tbody>
<?foreach($arResult["ITEMS"] as $arItem):?>
<?if(!array_key_exists("HIDDEN", $arItem)):?>
<tr>
<td class="field-name"><?=$arItem["NAME"]?>:</td>
<td class="field-control"><span class="filter-<?=$arItem["TYPE"]?>"><?=$arItem["INPUT"]?></span></td>
</tr>
<?endif?>
<?endforeach;?>
</tbody>
<tfoot>
<tr>
<td class="field-name"> </td>
<td class="field-control"><input type="submit" name="set_filter" value="<?=GetMessage("IBLOCK_SET_FILTER")?>" /><input type="hidden" name="set_filter" value="Y" /> <input type="submit" name="del_filter" value="<?=GetMessage("IBLOCK_DEL_FILTER")?>" /></td>
</tr>
</tfoot>
</table>
</div>
<b class="r1"></b>
</div>
</div>
</form>
</div> |
Так же надо в шаблоне фильтра catalog/castlerock/castlerock.catalog.filter/.default/ добавить файл result_modifier.php и в нем назначить вывод в массив двух переменных
<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();
$arResult['IBLOCK_ID'] = $arParams["IBLOCK_ID"];
$arResult['SECTION_CODE'] = $arParams["SECTION_CODE"];
?> |
В файле вывода фильтра и элементов раздела надо, добавить в модуль фильтра еще два параметра (SECTION_CODE и IBLOCK_ID) обернуть вывод элементов разделе в тег с классом list-selection-element,
<?if($arParams["USE_FILTER"]=="Y"):?> <?$APPLICATION->IncludeComponent( "castlerock:castlerock.catalog.filter", "", Array( "IBLOCK_TYPE" => $arParams["IBLOCK_TYPE"], "IBLOCK_ID" => $arParams["IBLOCK_ID"], "FILTER_NAME" => '', "SECTION_ID" => $arResult["VARIABLES"]["SECTION_ID"], "SECTION_CODE" => $arResult["VARIABLES"]["SECTION_CODE"], "FIELD_CODE" => $arParams["FILTER_FIELD_CODE"], "PROPERTY_CODE" => $filter_property, "PRICE_CODE" => $arParams["FILTER_PRICE_CODE"], "OFFERS_FIELD_CODE" => $arParams["FILTER_OFFERS_FIELD_CODE"], "OFFERS_PROPERTY_CODE" => $arParams["FILTER_OFFERS_PROPERTY_CODE"], "CACHE_TYPE" => $arParams["CACHE_TYPE"], "CACHE_TIME" => $arParams["CACHE_TIME"], "CACHE_GROUPS" => $arParams["CACHE_GROUPS"], ), $component ); ?> <?endif?> <div class="list-selection-element"> <?$APPLICATION->IncludeComponent( "castlerock:castlerock.catalog.section", "", Array( "IBLOCK_TYPE" => $arParams["IBLOCK_TYPE"], "IBLOCK_ID" => $arParams["IBLOCK_ID"], "ELEMENT_SORT_FIELD" => $sort,//$arParams["ELEMENT_SORT_FIELD"], "ELEMENT_SORT_ORDER" => $sort_order,//$arParams["ELEMENT_SORT_ORDER"], "PROPERTY_CODE" => $arParams["LIST_PROPERTY_CODE"], "META_KEYWORDS" => $arParams["LIST_META_KEYWORDS"], "META_DESCRIPTION" => $arParams["LIST_META_DESCRIPTION"], "BROWSER_TITLE" => $arParams["LIST_BROWSER_TITLE"], "INCLUDE_SUBSECTIONS" => $arParams["INCLUDE_SUBSECTIONS"], "BASKET_URL" => $arParams["BASKET_URL"], "ACTION_VARIABLE" => $arParams["ACTION_VARIABLE"], "PRODUCT_ID_VARIABLE" => $arParams["PRODUCT_ID_VARIABLE"], "SECTION_ID_VARIABLE" => $arParams["SECTION_ID_VARIABLE"], "FILTER_NAME" => $arParams["FILTER_NAME"], "DISPLAY_PANEL" => $arParams["DISPLAY_PANEL"], "CACHE_TYPE" => $arParams["CACHE_TYPE"], "CACHE_TIME" => $arParams["CACHE_TIME"], "CACHE_FILTER" => $arParams["CACHE_FILTER"], "CACHE_GROUPS" => $arParams["CACHE_GROUPS"], "SET_TITLE" => $arParams["SET_TITLE"], "SET_STATUS_404" => $arParams["SET_STATUS_404"], "DISPLAY_COMPARE" => $arParams["USE_COMPARE"], "PAGE_ELEMENT_COUNT" => $arParams["PAGE_ELEMENT_COUNT"], "LINE_ELEMENT_COUNT" => $arParams["LINE_ELEMENT_COUNT"], "PRICE_CODE" => $arParams["PRICE_CODE"], "USE_PRICE_COUNT" => $arParams["USE_PRICE_COUNT"], "SHOW_PRICE_COUNT" => $arParams["SHOW_PRICE_COUNT"], "PRICE_VAT_INCLUDE" => $arParams["PRICE_VAT_INCLUDE"], "DISPLAY_TOP_PAGER" => $arParams["DISPLAY_TOP_PAGER"], "DISPLAY_BOTTOM_PAGER" => $arParams["DISPLAY_BOTTOM_PAGER"], "PAGER_TITLE" => $arParams["PAGER_TITLE"], "PAGER_SHOW_ALWAYS" => $arParams["PAGER_SHOW_ALWAYS"], "PAGER_TEMPLATE" => $arParams["PAGER_TEMPLATE"], "PAGER_DESC_NUMBERING" => $arParams["PAGER_DESC_NUMBERING"], "PAGER_DESC_NUMBERING_CACHE_TIME" => $arParams["PAGER_DESC_NUMBERING_CACHE_TIME"], "PAGER_SHOW_ALL" => $arParams["PAGER_SHOW_ALL"], "OFFERS_CART_PROPERTIES" => $arParams["OFFERS_CART_PROPERTIES"], "OFFERS_FIELD_CODE" => $arParams["LIST_OFFERS_FIELD_CODE"], "OFFERS_PROPERTY_CODE" => $arParams["LIST_OFFERS_PROPERTY_CODE"], "OFFERS_SORT_FIELD" => $arParams["OFFERS_SORT_FIELD"], "OFFERS_SORT_ORDER" => $arParams["OFFERS_SORT_ORDER"], "OFFERS_LIMIT" => $arParams["LIST_OFFERS_LIMIT"], "SECTION_ID" => $arResult["VARIABLES"]["SECTION_ID"], "SECTION_CODE" => $arResult["VARIABLES"]["SECTION_CODE"], "SECTION_URL" => $arResult["FOLDER"].$arResult["URL_TEMPLATES"]["section"], "DETAIL_URL" => $arResult["FOLDER"].$arResult["URL_TEMPLATES"]["element"], "COMPARE_URL" => $arResult["FOLDER"].$arResult["URL_TEMPLATES"]["compare"], "COMPARE_NAME" => $arParams["COMPARE_NAME"], "DISPLAY_IMG_WIDTH" => $arParams["DISPLAY_IMG_WIDTH"], "DISPLAY_IMG_HEIGHT" => $arParams["DISPLAY_IMG_HEIGHT"], "SHARPEN" => $arParams["SHARPEN"], "ADD_SECTIONS_CHAIN" => "Y" ), $component ); ?> </div> |
Собственно теперь напишем сам скрипт на js , первая функция необходима для того что бы заполнять форму когда человек заходим с хэшем в строке, вторая функция для того что бы сократить количество кода для каждого ajax запроса, дальше функции непосредственно для ajax запросов.
/* эта функция тоже самое что и serialize только наоборот заполняет форму из массива */
(function($)
{
$.fn.deserialize = function(data, clearForm)
{
this.each(function(){
deserialize(this, data, !!clearForm);
});
};
function deserialize(element, data, clearForm)
{
var splits = decodeURIComponent(data).split('&'),
i = 0,
split = null,
key = null,
value = null,
splitParts = null;
if (clearForm)
{
$('input[type="checkbox"],input[type="radio"]', element).removeAttr('checked');
$('select,input[type="text"],input[type="password"],input[type="hidden"],textarea', element).val('');
}
while(split = splits[i++])
{
splitParts = split.split('=');
key = splitParts[0] || '';
value = (splitParts[1] || '').replace(/\+/g, ' ');
if (key != '')
{
$('input[type="checkbox"][name="'+ key +'"][value="'+ value +'"],input[type="radio"][name="'+ key +'"][value="'+ value +'"]', element).attr('checked', 'checked');
$('select[name="'+ key +'"],input[type="text"][name="'+ key +'"],input[type="password"][name="'+ key +'"],input[type="hidden"][name="'+ key +'"],textarea[name="'+ key +'"]', element).val(value);
}
}
}
})(jQuery);
/* Function for ours ajax inquiry */
function ajaxpostshow(urlres, datares, wherecontent ){
$.ajax({
type: "POST",
url: urlres,
data: datares,
dataType: "html",
beforeSend: function(){
var elementheight = $(wherecontent).height();
$(wherecontent).prepend('<div class="ajaxloader"></div>');
$('.ajaxloader').css('height', elementheight);
$('.ajaxloader').prepend('<img class="imgcode" src="/js/ajax/ajax-loader.gif">');
},
success: function(fillter){
$(wherecontent).html(fillter);
}
});
}
/* Sending ajax inquiry with values of filters, formation of value of filters */
$(".catalog-filter input, .catalog-filter select").live("change", function(){
var arrayform = $(".catalog-filter form").serialize();
location.hash = arrayform;
var ajaxfillter = document.location.hash.substr(1);
ajaxpostshow("/include/ajax/fillter-element.php", ajaxfillter, ".list-selection-element" );
});
/* Conclusion of values from the filter with the help ajax and hashe */
$(document).ready(function(){
var hash = window.location.hash.substr(1);
if(hash != "") {
var ajaxfillter = document.location.hash.substr(1);
$(".catalog-filter form").deserialize(ajaxfillter, true);
ajaxpostshow("/include/ajax/fillter-element.php", ajaxfillter, ".list-selection-element" );
}
});
/* Event for ajax paginal navigation */
$(".ajax-navigation a").live("click", function(){
var pagenum = $(this).attr('id');
var arrayform = $(".catalog-filter form").serialize();
var ajaxfillter = arrayform + '&' + pagenum;
location.hash = ajaxfillter;
ajaxpostshow("/include/ajax/fillter-element.php", ajaxfillter, ".list-selection-element" );
return false;
}); |
Теперь напишем сам обработчик для вывод элементов каталога, постраничной навигации , его можно будет сделать любой сложности в зависимости от поступающих параметров в запросе $_POST
<?
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
/* изменяем кодировку и поступающего параметра имени */
$_POST['arrFilter_ff']['NAME'] = iconv("UTF-8", "WINDOWS-1251", $_POST['arrFilter_ff']['NAME']);
CModule::IncludeModule("sale");
CModule::IncludeModule("catalog");
CModule::IncludeModule("iblock");
if($_POST['ajaxpage']) {
$ajaxpage = $_POST['ajaxpage'];
}
else {
$ajaxpage = 1;
}
$arOrder = Array("SORT"=>"ASC");
$arFilter = array();
/* We bring section parametres in the filter */
foreach($_POST as $key => $value) {
if(substr($key, 0, 14) == 'AJAXSELECTION_'){
$key = substr($key, 14);
$arFilter[$key] = $value;
}
elseif($key == 'arrFilter_ff'){
foreach($value as $key2 => $value2) {
$arFilter[$key2] = $value2;
}
}
/* если ключ arrFilter_pf формируем логику создания массива */
elseif($key == 'arrFilter_pf'){
/* тут значение $value массив формируем новый*/
foreach($value as $key2 => $value2) {
/* проверка если $value2 массив то формируем новый массив*/
if(is_array($value2)) {
foreach($value2 as $key3 => $value3) {
$arFilter['PROPERTY_'.$key2] = $value3;
}
}
/* если $value2 не массив то формируем массив для свойства*/
else {
$arFilter['PROPERTY_'.$key2] = $value2;
}
}
}
}
/* формируем массив выборки */
$arSelect = Array("ID", "NAME", "DATE_ACTIVE_FROM", "PREVIEW_TEXT", "PREVIEW_PICTURE", "DETAIL_PICTURE" );
/* реализовываем выборку элементов инфоблока */
$res = CIBlockElement::GetList( $arOrder , $arFilter, false , Array("nPageSize"=>10 , "iNumPage"=>$ajaxpage , "bShowAll"=> false), $arSelect);
?>
<div class="catalog-item-list">
<?
while($ar_fields = $res->GetNext()){ ?>
<? $ar_res = CPrice::GetBasePrice($ar_fields['ID']);?>
<div class="catalog-item" >
<div class="catalog-item-info">
<div class="catalog-item-image">
<? echo CFile::ShowImage($ar_fields['DETAIL_PICTURE'], 75, 100, "border=0", $ar_fields['ID']."/");?>
</div>
<div class="catalog-item-desc">
<div class="catalog-item-title">
<a href="<?=$ar_fields['ID'];?>/"><?=$ar_fields['NAME']; ?></a>
</div>
<div class="catalog-item-preview-text">
<?=$ar_fields['PREVIEW_TEXT']; ?>
</div>
<div class="catalog-item-price">
<span class="catalog-item-price"><?=$ar_res['PRICE']; ?> руб</span>
</div>
</div>
</div>
<div class="catalog-item-links">
<a id="ajaxaction=add&ajaxaddid=<?=$ar_fields['ID'];?>" rel="nofollow" class="catalog-item-buy input-basket-submit" href="?action=ADD2BASKET&id=<?=$ar_fields['ID'];?>">В корзину</a>
</div>
</div>
<pre>
<?/* print_r($ar_fields); */?>
</pre>
<div class="catalog-item-separator"></div>
<?} ?>
</div>
<?
/* реализуем постраничную навигацию */
$NAV_STRING = $res->GetPageNavStringEx($navComponentObject, "", 'ajaxarrows');
echo $NAV_STRING;
?> |
Для постраничной навигации я сделал свой шаблон для того что бы работал ajax , назвал я его ajaxarrow , в нем я добавил только к ссылкам id с номером страницы id="ajaxpage=<?=$sNextcount;?>" и класс ajax-navigation обертыш этого шаблона.
Вот собственно и все , первоисточник .