Фильтрация элементов в 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 нужен для отлова символа нажатой клавиш        */ 

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

Исходники

ссылка на оригинал статьи http://habrahabr.ru/post/175623/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *