avatar

Фильтр выпадающим списком

Опубликовал в блог Дополнения и модули для Simpla CMS
0
При создании Интернет-магазина большое внимание стоит уделить удобному поиску нужного товара. Часто этот поиск дополнен фильтром по свойствам. По стандарту — в Simpla уже присутствует такой фильтр по свойствам — он выводит все свойства как ссылки и при нажатии на них можно фильтровать товары. Однако, если свойств достаточно много, то такой способ становится неудобным и вот тут может появиться необходимость сделать фильтр select-ом или попросту говоря выпадающим списком. Существует несколько решений это проблемы и сейчас мы разберем 3 варианта, как сделать фильтр свойств с выпадающим списком.

Первый вариант: замена ссылок на select «на лету» с помощью js

Здесь основную работу делает javascript. Он находит наши ссылки, которые используются в фильтре и создает селект с такими же свойствами. Плюс — если у клиента не будет работать js, то он увидит обычные ссылки — которые используются в стандартном фильтре. Минус — при загрузке страницы, клиент может увидеть сначала ссылки, а потом они превратятся в select-ы.

Для замены фильтра свойств на выпадающие списки, берем стандартный код выводы фильтра свойств:
{* Фильтр по свойствам *}
{if $features}
<table id="features">
	{foreach $features as $f}
	<tr>
	<td class="feature_name" data-feature="{$f->id}">
		{$f->name}:
	</td>
	<td class="feature_values">
		<a href="{url params=[$f->id=>null, page=>null]}" {if !$smarty.get.$f@key}class="selected"{/if}>Все</a>
		{foreach $f->options as $o}
		<a href="{url params=[$f->id=>$o->value, page=>null]}" {if $smarty.get.$f@key == $o->value}class="selected"{/if}>{$o->value|escape}</a>
		{/foreach}
	</td>
	</tr>
	{/foreach}
</table>
{/if}

И меняем на:
{if $features}
	<table id="features">
		{foreach $features as $f}
			<tr>
				<td class="feature_name" data-feature="{$f->id}">
					{$f->name}:
				</td>
				<td class="feature_values">
					<a href="{url params=[$f->id=>null, page=>null]}" {if !$smarty.get.$f@key}class="selected"{/if}>Все</a>
					{foreach $f->options as $o}
					<a href="{url params=[$f->id=>$o->value, page=>null]}" {if $smarty.get.$f@key == $o->value}class="selected"{/if}>{$o->value|escape}</a>
					{/foreach}
				</td>
			</tr>
		{/foreach}
	</table>
{/if}
{literal}
<script type="text/javascript">
$(function() {
	$('.feature_values').each(function(k,v) {
		var id = $(v).parent('tr').find('.feature_name').data('feature');
		$('<select name="feature_'+id+'"></select>').appendTo(v);
		$(v).find('a').each(function(k,a) {
			var href = $(a).attr('href');
			var name = $(a).html();
			selected = '';
			if ( $(a).hasClass("selected") ) {
				selected = 'selected';
			}
			$(v).find('select').append('<option value="'+href+'" '+selected+'>'+name+'</option>');
		});
		$(v).find('a').hide();
	});
	$('#features select').live('change', function(e) {
	filter = $(this).find('option:selected').val();
	location.href = filter;
	});
});
</script>
{/literal}


Второй вариант: select прописывается прямо в коде. Js выполняет поиск при выборе варианта

При этом варианте мы уже на этапе разметки определяем, что свойства фильтра будут выводиться в селект. Ну и пара строк на js заставляет поиск осуществляться. Код:
{if $features}
	<table id="features">
	{foreach $features as $f}
		<tr>
			<td class="feature_name">
			{$f->name}:
			</td>
			<td>
				<select class="feature_values" size="1" onchange="clicker(this)">
					<option value="{url params=[$f->id=>null]}"{if !$smarty.get.$f@key} selected{/if}>выбрать</option>
					{foreach $f->options as $o}
					<option value="{url params=[$f->id=>$o->value]}" {if $smarty.get.$f@key == $o->value}selected{/if}>{$o->value}</option>
					{/foreach}
				</select>
			</td>
		</tr>
	{/foreach}
	</table>
{/if}
{literal}
<script>
function clicker(that) {
var pick = that.options[that.selectedIndex].value;
location.href = pick;
}
</script>
{/literal}

Этот вариант хорош тем, что пользователь сразу увидит свойства в виде выпадающих списков. Но если у него не сработает js, то осуществить фильтрацию не удастся.

Третий способ: для тех, кому нужна кнопка «Показать»

Этот способ гораздо сложнее, чем два предыдущие, потому что позволяет выбрать несколько значений фильтра перед началом поиска. Плюс поиск не будет осуществляться, пока пользователь не нажмет на кнопку. Для реализации понадобится вносить изменения в файл на фтп.

Итак, открываем файл view/ProductsView.php (внимание, я делаю изменения на версии 2.3.6).

77 строка:
$filter['features'][$feature->id] = $val;

Меняем на:
{
	$filter['features'][$feature->id] = $val;	
	$fil[$feature->id] = $val;
}

Далее строки 89, 90:
if(isset($filter['features']))
$options_filter['features'] = $filter['features'];

Меняем на (закомментим их от выполнения):
//		if(isset($filter['features']))
//		$options_filter['features'] = $filter['features'];

Строка 108:
$this->design->assign('features', $features);

Меняем на (добавляем еще одну строку ниже):
$this->design->assign('features', $features);
$this->design->assign('fil', $fil);

На этом все. Теперь выведем полученный результат в шаблон:
{if $features}
	<form method=get enctype="multipart/form-data">
		<table id="features">
			{foreach $features as $f}
			<tr>
				<td class="feature_name">
					{$f->name}:
				</td>
				<td>
					<select class="feature_values" size="1" name="{$f->id}">
						<option value="">Выбрать</option>
						{foreach $f->options as $o}
						<option value="{$o->value}" {if $fil[$f->id] == $o->value}selected{/if}>{$o->value}</option>
						{/foreach}
					</select>
				</td>
			</tr>
			{/foreach}
		</table>
		<input type="submit" value="Показать">
	</form>
{/if}
{literal}
<script>
function clicker(that) {
var pick = that.options[that.selectedIndex].value;
location.href = pick;
}
 
function clickerb() {
var pick = getElementsByName("feature[]").options[getElementsByName("feature[]").selectedIndex].value;
}
</script>
{/literal}

Вот и все. Теперь фильтр будет работать по нажатию кнопки «Показать»
0 комментариев RSS
Нет комментариев
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.