При создании интернет-магазин часто используются фильтры товара по характеристикам , пользователей раздражает когда при изменение свойств поиска, идет перезагрузка страницы, давай те исправим это положение и сделаем полноценный фильтр на 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
|
|