среда, 26 июня 2013 г.

Фильтрация элементов в cuSel

image

На одном из сайтов, который я имею честь обслуживать, для кастомизации селекта используется замечательный jQuery-плагин cuSel. Он удобен тем, что достаточно прост в настройке и позволяет кастомизировать даже полосу прокрутки.

Но иногда случается так, что список элементов может быть очень большим. И быстро найти нужный пункт не так просто.



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


Сегодня я постараюсь повторить все это вместе с вами. Для этого возьмем демонстрационный пример со странички плагина. В архиве содержаться все необходимые библиотеки и стили. На странице index.html автор подготовил несколько примеров подключения и использования плагина. Давайте добавим фильтрацию для первого селекта, в котором содержится список стран.


Для ввода текста мы будем использовать прозрачное текстовое поле, которое по клику будет налаживаться верхним слоем на селект. Добавим для этого поля соответствующий css-класс в файл css/cusel.css и установим такие же размеры для блока, в котором отображается текст выбранного элемента списка.



.cusel .search-field {
position: absolute;
outline:0;
border: 0;
background: transparent;
display:none;
}
.cusel .search-field, .cuselText {
width: 144px;
height: 20px;
line-height:20px;
padding: 3px 30px 3px 6px;
}


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



<select class="sel80 filtering" id="country" name="country" tabindex="2">


Откроем файл js/cusel.js и добавим следующий код в функцию cuselEvents.



jQuery(".cusel").each(function () {
var itv;
var elm = $(this);
if (elm.hasClass("filtering") && elm.find(".search-field").length == 0) {
var f = $("<input type='text' />")
f.addClass("search-field");
f.keydown(function () {
clearInterval(itv);
var list = elm.find(".cusel-scroll-pane > span");
itv = setInterval(function () {
list.each(function () {
var item = $(this);
item.show();
if (item.text().toLowerCase().indexOf(f.val().toLowerCase()) != 0)
item.hide();
});
var d = elm.find(".cusel-scroll-pane").eq(0).attr("id");
jQuery("#" + d)[0].scrollTo(0);
clearInterval(itv);
}, 100);
});
f.click(function () {
$(this).val('').hide();
elm.focus();
});
elm.append(f);
}
});


Что делает данный код? Находит на странице все элементы с классом «cusel» т.к. именно этот класс используется в стилизированных селектах. Далее, если для селекта указан класс «filtering» и он не имеет дочерний элемент с классом «search-field» (наше поле для ввода текста), то такое поле создается и на него вешается обработчик события. Обработчик, по каждому нажатию клавиш в поле, находит пункты в списке, текст которых не соответствует тексту в поле и просто скрывает их.


Теперь нам нужно сделать так, чтобы по клику на селекте над ним появлялось наше прозрачное поле. Для этого в той же функцие cuselEvents найдем обработчик события «click». В нем необходимо отыскать часть кода помеченную комментарием автора «если кликнули по самому селекту (текст)» и изменить следующим образом.



/* если кликнули по самому селекту (текст) */
if((clickedClass.indexOf("cuselText")!=-1 || clickedClass.indexOf("cuselFrameRight")!=-1) && clicked.parent().prop("class").indexOf("classDisCusel")==-1)
{
var cuselWrap = clicked.parent().find(".cusel-scroll-wrap").eq(0);

var parent = clicked.parents(".cusel");
if (parent.hasClass("filtering")) {
var txt = parent.children(".cuselText");
var sf = parent.children(".search-field");
if(sf.is(":hidden")) {
txt.text("");
sf.show().focus();
}
else {
txt.text(parent.find(".cuselActive").eq(0).text());
sf.val("").hide();
}
}

/* если выпадающее меню скрыто - показываем */
cuselShowList(cuselWrap);
}


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


Теперь сделаем, чтобы при выборе элемента в списке, поле наоборот скрывалось. Ниже найдите блок помеченный комментарием автора «если выбрали позицию в списке» и добавьте туда следующий код



else if(clicked.is(".cusel-scroll-wrap span") && clickedClass.indexOf("cuselActive")==-1) {

var parent = clicked.parents(".cusel");
if (parent.hasClass("filtering")) {
parent.children(".search-field").val('').hide();
parent.find(".cusel-scroll-pane > span").show();
}

//оригинальный код
}


Как видно при этом мы делаем видимыми скрытые при фильтрации элементы списка.


Логично бы было, если пользователь кликнет все списка, закрыть список и спрятать поле фильтра. Поэтому находим ниже блок, помеченный комментарием автора «скрываем раскрытые списки, если кликнули вне списка» и изменяем его следующим образом.



/*
скрываем раскрытые списки, если кликнули вне списка
*/
else {
var wrap = jQuery(".cusel-scroll-wrap");
var parent = wrap.parents(".cusel");

parent.each(function () {
var elm = $(this);
if (elm.hasClass("filtering")) {
elm.find(".cuselText").text(elm.find(".cuselActive").eq(0).text());
elm.find(".search-field").val('').hide();
elm.find(".cusel-scroll-pane > span").show();
}
});

wrap.hide();
parent.removeClass("cuselOpen")
}


И теперь последний штрих. В самом конце функции cuselEvents вы найдете кусок кода помеченный следующим комментарием



/*
функция отбора по нажатым символам (от Alexey Choporov)
отбор идет пока пауза между нажатиями сиволов не будет больше 0.5 сек
keypress нужен для отлова символа нажатой клавиш
*/


Функция Алексея подбирает подходящее значение по первой букве. Мы же реализовываем возможность отбора по нескольким буквам. Поэтому во избежание конфликтов код Алексея необходимо закомментировать.


Исходники


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


Комментариев нет:

Отправить комментарий