При создании интернет-магазин часто используются фильтры товара по характеристикам , пользователей раздражает когда при изменение свойств поиска, идет перезагрузка страницы, давай те исправим это положение и сделаем полноценный фильтр на ajax .
Мы будем использовать хэш что бы была возможность ложить ссылку в закладку, кидать другу и использовать историю для перехода назад к параметрам поиска .
Делать мы будем все это чудо с помощью 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");
/* We change the coding and the arriving parametre of a name */
$_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;
}
/* if key arrFilter_ff we form logic creation of a file */
elseif($key == 'arrFilter_ff'){
foreach($value as $key2 => $value2) {
$arFilter[$key2] = $value2;
}
}
/* we form file */
elseif($key == 'arrFilter_cf') {
$arFilter[] = array(
">=CATALOG_PRICE_1" => $value[1]['LEFT'],
"<=CATALOG_PRICE_1" => $value[1]['RIGHT'],
);
}
/* if key arrFilter_pf we form logic creation of a file */
elseif($key == 'arrFilter_pf'){
/* $value file we form file */
foreach($value as $key2 => $value2) {
/* check if $value2 file that we form a new file */
if(is_array($value2)) {
foreach($value2 as $key3 => $value3) {
$arFilter['PROPERTY_'.$key2] = $value3;
}
}
/* if $value2 not file that we form file for property */
else {
$arFilter['PROPERTY_'.$key2] = $value2;
}
}
}
}
/* we form file order */
if($_POST['sort'] && $_POST['by']){
$arOrder = array ($_POST['sort'] => $_POST['by']);
}
/* we form file samples */
$arSelect = Array("ID", "NAME", "PREVIEW_TEXT", "PREVIEW_PICTURE", "DETAIL_PICTURE", "CATALOG_GROUP_1", "PROPERTY_CML2_LINK.ID" );
/* we realise sample elements infoblock */
$res = CIBlockElement::GetList( $arOrder , $arFilter, false , Array("nPageSize"=>$_POST['pagecount'], "iNumPage"=>$ajaxpage , "bShowAll"=> false), $arSelect);
?>
<div class="catalog-item-list">
<?
while($ar_fields = $res->GetNext()){ ?>
<?
/* We find the adhered elements */
$arOrderPrice = array('sort' => 'asc');
$arFilterPrice = Array("IBLOCK_TYPE" => "offers", "PROPERTY_CML2_LINK" => $ar_fields['ID']);
$arSelectPrice = Array("ID", "NAME", "IBLOCK_ID", "CATALOG_GROUP_1", "PROPERTY_CML2_ATTRIBUTES" );
$resPrice = CIBlockElement::GetList( $arOrderPrice , $arFilterPrice, false , Array(), $arSelectPrice);
$attributes = array();
$i = 1;
while($ar_fieldsPrice = $resPrice->GetNext()){
if($i == 1) {
$basketFirst = $ar_fieldsPrice['ID'];
}
$attributes[] = array("ID" =>$ar_fieldsPrice['ID'], "PROP_VALUE" => $ar_fieldsPrice['PROPERTY_CML2_ATTRIBUTES_VALUE']) ;
$i++ ;
}
?>
<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['CODE']."/");?>
</div>
<div class="catalog-item-desc">
<div class="catalog-item-title">
<a href="<?=$ar_fields['CODE'];?>/"><?=$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_fields['CATALOG_PRICE_1']; ?> руб</span>
</div>
</div>
</div>
<div class="catalog-item-links">
<? if($attributes[0]['PROP_VALUE']):?>
<label>Размер</label>
<select>
<? foreach($attributes as $attribute):?>
<option value="<? echo $attribute['ID'];?>"><? echo $attribute['PROP_VALUE'];?></option>
<? endforeach;?>
</select> <br />
<a id="ajaxaction=add&ajaxaddid=<?=$basketFirst;?>" rel="nofollow" class="catalog-item-buy input-basket-submit input-basket-submit-property" href="?action=ADD2BASKET&id=<?=$basketFirst;?>">В корзину</a>
<? else:?>
<a id="ajaxaction=add&ajaxaddid=<?=$basketFirst;?>" rel="nofollow" class="catalog-item-buy input-basket-submit" href="?action=ADD2BASKET&id=<?=$basketFirst;?>">В корзину</a>
<? endif;?>
</div>
</div>
<div class="catalog-item-separator"></div>
<?} ?>
</div>
<?
/* we realise реализуем paginal navigation */
$NAV_STRING = $res->GetPageNavStringEx($navComponentObject, "", 'ajaxarrows');
echo $NAV_STRING;
?>
Для постраничной навигации я сделал свой шаблон для того что бы работал ajax , назвал я его ajaxarrow , в нем я добавил только к ссылкам id с номером страницы id="ajaxpage=<?=$sNextcount;?>" и класс ajax-navigation обертыш этого шаблона.
Вот собственно и все .
Опубликовано: 17 августа 2011
|
|
|