Filtering items in cuSel
On one of the sites that I have the honor to serve, the wonderful jQuery plugin cuSel is used to customize the select . It is convenient in that it is quite simple to configure and allows you to customize even the scroll bar.
But sometimes it happens that the list of elements can be very large. And quickly finding the right item is not so simple.
Once I got the task to realize the ability to enter text and filter elements by first letters. The list consisted of the names of Ukrainian cities and was quite long. Since the plug-in itself did not have this feature, and both the customer and I did not want to abandon the beautiful select, it was decided to make small improvements to the script code.
Today I will try to repeat all this with you. For thistake a demo from the plugin page. The archive contains all the necessary libraries and styles. On the index.html page, the author prepared several examples of connecting and using the plugin. Let's add filtering for the first select, which contains a list of countries.
To enter text, we will use a transparent text field, which will be adjusted by clicking the top layer on the select. Add the corresponding css class for this field to the css / cusel.css file and set the same dimensions for the block in which the text of the selected list item is displayed.
.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;
}
In order to be able to add filtering only to the necessary selects, we will mark them with an additional filtering class .
")
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);
}
});
What does this code do? Finds on the page all the elements with the class "cusel" because this class is used in stylized selects. Further, if the filtering class is specified for the select and it does not have a child with the search-field class (our text input field), then such a field is created and an event handler is hung on it. The handler, for each keystroke in the field, finds items in the list whose text does not match the text in the field and simply hides them.
Now we need to make sure that by clicking on the select above our transparent field appears. To do this, in the same cuselEvents function we find the click event handler. It is necessary to find the part of the code marked with the author’s comment “if they clicked on the selection itself (text)” and change it as follows.
/* если кликнули по самому селекту (текст) */
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);
}
Since the text input field is transparent so as not to overlap the background, we clear the text of the selected element in the select. Repeated click will return the original state of the item.
Now we will make that when you select an item in the list, the field is hidden on the contrary. Below, find the block marked with the author’s comment “if you selected a position in the list” and add the following code there
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();
}
//оригинальный код
}
As you can see, we make the list items hidden during filtering visible.
It would be logical if the user clicks the entire list, close the list and hide the filter field. Therefore, we find below the block marked by the comment of the author “hide the opened lists if they click outside the list” and change it as follows.
/*
скрываем раскрытые списки, если кликнули вне списка
*/
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")
}
And now the final touch. At the very end of the cuselEvents function , you will find a piece of code marked with the following comment
/*
функция отбора по нажатым символам (от Alexey Choporov)
отбор идет пока пауза между нажатиями сиволов не будет больше 0.5 сек
keypress нужен для отлова символа нажатой клавиш
*/
Alexey's function selects the appropriate value by the first letter. We realize the possibility of selection by several letters. Therefore, in order to avoid conflicts, Alexey's code must be commented out.
Source code