catalog.smart.filter вывод списка выбранных фильтров

Иногда бывает нужно сделать вывод проставленных фильтров, чтобы пользователь мог по ним кликнуть и фильтр был удален.

Для этого сперва в файле template.php нашего шаблона catalog.smart.filter мы добавляем следующий код в нужное нам место:


<? if(strpos($APPLICATION->GetCurPage(), 'filter') !== false)
{
	?>
		<div class="filter-selected _active">
			<? foreach($arResult["ITEMS"] as $key=>$arItem)
			{
				if (!isset($arItem["PRICE"])) continue;
				$key = $arItem["ENCODED_ID"];
				if(isset($arItem["PRICE"])) {
					if ($arItem["VALUES"]["MAX"]["VALUE"] - $arItem["VALUES"]["MIN"]["VALUE"] <= 0)
						continue;
				}

				if (!empty($arItem["VALUES"]['MIN']) && !empty($arItem["VALUES"]['MAX']) && (!empty($arItem["VALUES"]['MIN']['HTML_VALUE']) || !empty($arItem["VALUES"]['MAX']['HTML_VALUE']))) {
					?>
					
					<a href="#" class="filter-selected__item js-filter-remove-btn js-filter-remove-btn-<?=$arItem["VALUES"]["MIN"]["CONTROL_NAME"]?>" onclick="this.style.display='none';smartFilter.setParam(); $('[name=<?=$arItem["VALUES"]["MIN"]["CONTROL_NAME"]?>]').val(<?=$arItem["VALUES"]["MIN"]['VALUE']?>); $('[name=<?=$arItem["VALUES"]["MAX"]["CONTROL_NAME"]?>]').val(<?=$arItem["VALUES"]["MAX"]['VALUE']?>).trigger('change'); return false;" class="filters-tags__item-remove">
						<?=CurrencyFormat($arItem["VALUES"]['MIN']['HTML_VALUE'] ?: $arItem["VALUES"]['MIN']['VALUE'], 'RUB') ?> - <?=CurrencyFormat($arItem["VALUES"]['MAX']['HTML_VALUE'] ?: $arItem["VALUES"]['MAX']['VALUE'], 'RUB') ?>
						<span></span>
					</a>
					<?
				}
			}
			?>
			<? foreach($arResult["ITEMS"] as $key=>$arItem) {
				switch($arItem["DISPLAY_TYPE"])
				{
					//TODO
					case "B"://NUMBERS
					case "U"://CALENDAR
					case "P"://DROPDOWN TODO
						continue;
						break;
					case "A"://NUMBERS_WITH_SLIDER
					case "G"://CHECKBOXES_WITH_PICTURES
					case "H"://CHECKBOXES_WITH_PICTURES_AND_LABELS
					case "R"://DROPDOWN_WITH_PICTURES_AND_LABELS
					case "K":
					default:
						if ($arItem["DISPLAY_TYPE"] == 'A') {
							if (!empty($arItem["VALUES"]['MIN']) && !empty($arItem["VALUES"]['MAX']) && (!empty($arItem["VALUES"]['MIN']['HTML_VALUE']) || !empty($arItem["VALUES"]['MAX']['HTML_VALUE']))) {
								?>
								<a href="#" class="filter-selected__item js-filter-remove-btn js-filter-remove-btn-<?=$arItem["VALUES"]["MIN"]["CONTROL_NAME"]?>" onclick="this.style.display='none';smartFilter.setParam(); $('[name=<?=$arItem["VALUES"]["MIN"]["CONTROL_NAME"]?>]').val(<?=$arItem["VALUES"]["MIN"]['VALUE']?>); $('[name=<?=$arItem["VALUES"]["MAX"]["CONTROL_NAME"]?>]').val(<?=$arItem["VALUES"]["MAX"]['VALUE']?>).trigger('change'); return false;" class="filters-tags__item-remove">
									<?/*=$arItem["NAME"]?>: */?>
									<?=$arItem["VALUES"]['MIN']['HTML_VALUE'] ?: $arItem["VALUES"]['MIN']['VALUE'] ?> - <?=$arItem["VALUES"]['MAX']['HTML_VALUE'] ?: $arItem["VALUES"]['MAX']['VALUE'] ?>
									
									<span></span>
								</a>
								<?
							}
						}
						foreach ($arItem["VALUES"] as $val => $ar) {
							if ($ar["CHECKED"])
							{
								?>
								
								<a href="#" class="filter-selected__item js-filter-remove-btn js-filter-remove-btn-<?=$ar["CONTROL_NAME"]?>" onclick="this.style.display='none';smartFilter.setParam(); $('[name=<?=$ar["CONTROL_NAME"]?>]').trigger('click'); return false;" class="filters-tags__item-remove"><?=$ar["VALUE"] ?><span></span></a>
								<?
							}
						}
						break;
				}
			} ?>

			<?
				$filterSearch = false;
				$explodeUrl = explode('/',$APPLICATION->GetCurPage());
				foreach($explodeUrl as $keyExp => $expurl){
					if($expurl == 'filter'){
						$filterSearch = true;
						continue;
					}
					if($filterSearch != true){
						continue;
					}
				}
				array_push($explodeUrl, 'clear');
				array_push($explodeUrl, 'apply');
				$implodeUrl = implode('/', $explodeUrl);
				$urlReset = $implodeUrl.'/';
			?>
			<a href="<?=$urlReset?>" class="filter-selected__clear _active">Очистить все<span></span></a>
		</div>
	<?
}
?>

После этого при нажатии на эти ссылки у вас будет выполняться AJAX запрос так, будто вы сняли галочку в фильтре и перезагружаться страница. Так же нужно внести небольшие изменения в файл script.js, чтобы переход выполнялся автоматически:

Примерно на 35 строчке добавляем новую функцию:


JCSmartFilter.prototype.setParam = function()
{
	this.permamentGoToLink = true;
};

И в функции postHandler примерно на 212 строке добавляем условие:

if (this.permamentGoToLink) {
				window.location.href = result.FILTER_URL;
			}

По идее, на этом можно было бы и остановиться, но данный способ не очень хорош, т.к. он выполняется с задержкой.

Чтобы задержки не было в файле result_modifier.php добавляем следующий код, который формирует для каждого установленно значения фильтра массив, без самого значения:


$currentFilters = [];
foreach($arResult["ITEMS"] as $key=>$arItem)
{
	if (!isset($arItem["PRICE"])) continue;
	$key = $arItem["ENCODED_ID"];
	if(isset($arItem["PRICE"])) {
		if ($arItem["VALUES"]["MAX"]["VALUE"] - $arItem["VALUES"]["MIN"]["VALUE"] <= 0)
			continue;
	}

	if (!empty($arItem["VALUES"]['MIN']) && !empty($arItem["VALUES"]['MAX']) && (!empty($arItem["VALUES"]['MIN']['HTML_VALUE']) || !empty($arItem["VALUES"]['MAX']['HTML_VALUE']))) {
		$currentFilters[$arItem["VALUES"]["MIN"]["CONTROL_NAME"]] = $arItem["VALUES"]["MIN"]['VALUE'];
		$currentFilters[$arItem["VALUES"]["MAX"]["CONTROL_NAME"]] = $arItem["VALUES"]["MAX"]['VALUE'];
	}
}

foreach($arResult["ITEMS"] as $key=>$arItem) {
	switch($arItem["DISPLAY_TYPE"])
	{
		//TODO
		case "B"://NUMBERS
		case "U"://CALENDAR
		case "P"://DROPDOWN
			continue;
			break;
		case "A"://NUMBERS_WITH_SLIDER
		case "G"://CHECKBOXES_WITH_PICTURES
		case "H"://CHECKBOXES_WITH_PICTURES_AND_LABELS
		case "R"://DROPDOWN_WITH_PICTURES_AND_LABELS
		case "K":
		default:
			if ($arItem["DISPLAY_TYPE"] == 'A') {
				if (!empty($arItem["VALUES"]['MIN']) && !empty($arItem["VALUES"]['MAX']) && (!empty($arItem["VALUES"]['MIN']['HTML_VALUE']) || !empty($arItem["VALUES"]['MAX']['HTML_VALUE']))) {
					$currentFilters[$arItem["VALUES"]["MIN"]["CONTROL_NAME"]] = $arItem["VALUES"]["MIN"]['VALUE'];
					$currentFilters[$arItem["VALUES"]["MAX"]["CONTROL_NAME"]] = $arItem["VALUES"]["MAX"]['VALUE'];
				}
			}
			foreach ($arItem["VALUES"] as $val => $ar) {
				if ($ar["CHECKED"])
				{
					$currentFilters[$ar["CONTROL_NAME"]] = $ar["VALUE"];
				}
			}
			break;
	}
}

$arResult["currentFilters"] = $currentFilters;

 Теперь в файле template.php добавляем скрипт, который после загрузки документа сделает ajax запрос и в этих ссылках удалит onclick и вставит нужный href:


<? if (!empty($arResult["currentFilters"]))
{
	$filter_delete_variants = [];
	foreach($arResult["currentFilters"] as $filter_name => $value) {
		$_current_filters = $arResult["currentFilters"];
		if (strpos($filter_name, '_MAX') !== false) {
			continue;
		}

		if (strpos($filter_name, '_MIN') !== false) {
			unset($_current_filters[$filter_name]);
			unset($_current_filters[str_replace('_MIN', '_MAX', $filter_name)]);
		} else {
			unset($_current_filters[$filter_name]);
		}

		foreach($_current_filters as $k => $val) {
			if (!(strpos($k, '_MIN') !== false || strpos($k, '_MAX') !== false)) {
				$_current_filters[$k] = 'Y';
			}
		}

		$filter_delete_variants[$filter_name] = $_current_filters;
	}
	?>
	<script>
		window.onload = () => {
			<? foreach($filter_delete_variants as $name => $values)
			{
				?>
				BX.ajax.loadJSON(
					'<?=$APPLICATION->GetCurPage(false)?>/?ajax=y&' + '<?=http_build_query($values)?>',
					{},
					function(result) {
						if (typeof result.FILTER_URL != typeof undefined) {
							let filter_clear_btn = document.querySelector('.js-filter-remove-btn-<?=$name?>');
							if (filter_clear_btn) {
								filter_clear_btn.setAttribute('href', result.FILTER_URL);
								filter_clear_btn.removeAttribute('onclick');
							}
						}
					}
				);
				<?
			}
			?>
		}
	</script>
	<?
}
?>