cuSel — нестандартные select на jQuery
Подготовил:
Евгений Рыжков
Дата публикации: 24.06.2010
Последнее обновление: 28.06.2011
Задача
Изменить дизайн select. Например на такой:
Требования
- легкость интеграции
- кроссбраузерность
- быстрая скорость работы
- максимальная приближенность к работе обычного select:
- на сервер передается значение (value выбранного option)
- по клику на option выпавший список скрывается
- по клику вне select выпавший список скрывается
- в выпадающем списке показ полностью длинных значений option
- учет атрибута disabled
- учет атрибута selected
- если явно не указан selected, select принимает значение первого в списке option
- учет события onchange
- скроллинг выпадающего списка прокручивается колесом мыши
- возможность получения фокуса (update 31.07.10)
- участие в tab обходе (update 31.07.10)
- смена значения select стрелками вверх/вниз (update 31.07.10) — после выбора нужного значения требуется нажатие enter
- смена значения select по нажатию клавиш букв (update 31.07.10)
- подсветка select при наведении и получении фокуса (update 31.07.10)
- закрытие списка по Esc (update 3.08.10)
- при отключенном javascript остаются обычные select
- удобное динамическое обновление оптионов
- простота динамического добавления select
- дополнительные приятные возможности:
- подсветка в выпадающем списке выбранного значения
- подсветка в выпадающем списке значения при наведении
- возможность ручного управления видом скроллинга выпадающего списка
- возможность оформления option с помощью CSS
- возможность вставки тегов в option
- плавное обрезание невмещающегося текста
Демо пример возможностей cuSel (или можно забрать архивом). Проверено в:
- IE 6-8
- Firefox 4
- Opera 9.5-11
- Safari 5
- Chrome 4
Что качать
Заметка
Для плавного обрезания текста спрайт должен иметь градиент, переходящий от фона селекта в прозрачность и расположенный левее правой кнопки списка:
При таком эффекте для IE6 подключаем DD_belatedPNG.
Если охота посмотреть код
Быстрый старт
Подключаем необходимые стили и библиотеки:
HTML
01 | < link rel = "stylesheet" type = "text/css" href = "path-to/cusel.css" /> |
02 | < script type = "text/javascript" src = "path-to/jquery-1.6.1.js" ></ script > |
03 | < script type = "text/javascript" src = "path-to/cusel-min.js" ></ script > |
09 | jQuery(document).ready(function(){ |
12 | var w = parseInt(jQuery(this).width()), |
13 | scrollPanel = jQuery(this).find(".cusel-scroll-pane"); |
14 | if(w>=scrollPanel.width()) |
16 | jQuery(this).find(".jScrollPaneContainer").width(w); |
Инициализируем cusel, указывая, где и как стилизовать select:
Javascript
1 | jQuery(document).ready(function(){ |
3 | changedEl: ".lineForm select" , |
А теперь подробней.
Как это работает
При загрузке страницы, если у пользователя включен javascript:
- находятся все указанные селекты на странице
- заменяется каждый select
HTML
1 | < select id = "idSelect" name = "nameSelect" > |
2 | < option value = "значение option 1" >текст option 1</ option > |
4 | < option value = "значение option N" >текст option N</ option > |
на конструкцию вида:
HTML
01 | < div class = "cusel" id = "cuselFrame-idSelect" > |
02 | < div class = "cuselFrameRight" ></ div > |
03 | < div class = "cuselText" >текст option 1</ div > |
04 | < div class = "cusel-scroll-wrap" > |
05 | < div class = "cusel-scroll-pane" id = "cusel-scroll-idSelect" > |
06 | < span class = "cuselActive" value = "значение option 1" >текст option 1</ span > |
08 | < span value = "значение option N" >текст option N</ span > |
11 | < input id = "idSelect" name = "nameSelect" value = "значение option 1" type = "hidden" /> |
- обычные select удаляются
Заметка
Обязательным условием является указание id селекту, т.к. на основании этого уникального идентификатора гарантируется работа скроллингов в выпадающих меню.
Инициализация cuSel
Функции
cuSel |
производит замену обычных select на стилизованные. Меняет только те, которые указаны в параметре changedEl. |
cuSelRefresh |
производит обновление селекта. Необходимо при изменении количества option в select и при показе скрытого select. Обновляет селекты, указанные в параметре refreshEl. |
Параметры
changedEl |
указываем селекторы (за основу взяты базовые селекторы CSS1) , к которым будет применен cuSel. Можно указать элемент (тег), класс, id. Обязательный параметр. Используется только в функции cuSel. |
visRows |
количество видимых строк выпадающего списка. Если в списке элементов будет больше заданного числа, у списка появится вертикальная прокрутка. Если число не задано, все значения списка будут видимы. |
scrollArrows |
отражать или нет стрелочки в блоке с прокруткой. Возможные значения: true/false (по умолчанию false) |
refreshEl |
id селектов через запятую, которые требуется обновить. Параметр обязателен. Используется только в функции cuSelRefresh. |
Примеры
Меняем все селекты на странице, без ограничения по высоте для выпадающих списков:
Javascript
Меняем один конкретный селект по id, число видимых элементов выпадающего списка 7:
Javascript
Цепляем onchange списку. Сusel-селект имеет структуру, построенную на div и span. Это нужно учитывать при динамическом изменении содержимого списков:
HTML
1 | < select id = "city" name = "city" onChange = "alert('произошел onchange')" > |
2 | < option value = "1" >Киев</ option > |
3 | < option value = "2" >Львов</ option > |
4 | < option value = "3" >Дон</ option > |
5 | < option value = "4" >Ялта</ option > |
Javascript
Если при загрузке страницы select был скрыт, то при его показе ему нужно обязательно указывать width и провести обновление:
Javascript
01 | jQuery( "#showSel" ).click( |
04 | jQuery( "#hidden-select" ) |
05 | .css( "display" , "block" ) |
06 | .css( "width" , "100px" ); |
08 | refreshEl: "#hidden-select" , |
Этого указания ширины можно избежать, если изначально select был присвоен класс, с заданной шириной через !important. Тут же, покажу как обновить сразу два селекта, которые были скрыты:
HTML
01 | < div id = "hidden-block" style = "display: none" > |
02 | < select id = "city2" name = "city2" class = "wid100" > |
03 | < option value = "1" >Киев</ option > |
04 | < option value = "2" >Львов</ option > |
05 | < option value = "3" >Донецк</ option > |
06 | < option value = "4" >Ялта</ option > |
08 | < select id = "city3" name = "city3" class = "wid100" > |
09 | < option value = "1" >Киев</ option > |
10 | < option value = "2" >Львов</ option > |
11 | < option value = "3" >Донецк</ option > |
12 | < option value = "4" >Ялта</ option > |
CSS
2 | width : 100px !important ; |
Javascript
1 | jQuery( "#hidden-block" ).css( "display" , "block" ); |
3 | refreshEl: "#city2, #city3" , |
Динамическое добавление select:
Javascript
01 | jQuery( "#addSelect" ).click( |
04 | var addedSelect = '<select id="add-select" name="add-select">' + |
05 | '<option value="1">доллар США</option>' + |
06 | '<option value="2">доллар канадский</option>' + |
07 | '<option value="3">доллар новозеландский</option>' + |
09 | jQuery(this).replaceWith(addedSelect); |
12 | changedEl: "#add-select" , |
Динамическое добавление опционов:
Javascript
01 | jQuery( "#addAnimals" ).click( |
05 | var newAnimals = '<span val="4">Слон</span><span val="5">Жираф африканский</span>' ; |
08 | jQuery( "#cusel-scroll-animals" ).append(newAnimals); |
13 | refreshEl: "#animals" , |
Дополнительные теги внутри option реализуются через дополнительный атрибут addTags. Если он присутствует, его содержимое добавится в соответствующий "новый" option:
HTML
1 | < select id = "animals" name = "animals" > |
2 | < option value = "1" addTags="<div class = 'kv' ></ div >">Медведь</ option > |
3 | < option value = "2" addTags="<input type = 'checkbox' />">Волк</ option > |
4 | < option value = "3" >Заяц</ option > |
5 | < option value = "4" >Ежик</ option > |
Часто задаваемые вопросы
Как на одной странице сделать два селекта разного вида
Нужно привязывать оформление селекта относительно своего родителя:
CSS
Можно подключить разные фоны, использовать разные цветовые схемы, шрифты и т.п.
Или же можно использовать дополнительный класс:
HTML
1 | < select id = "select1" name = "select1" > |
3 | < select id = "select2" name = "select2" class = "cusel2" > |
CSS
Как убрать выделение выбранного пункта в выпадающем списке
Из CSS удаляем класс .cuselActive.
Как задать ширину стилизированного select
В CSS указать явно ширину классу .cusel или добавить класс, с явно заданной шириной заменяемому select.
В прозрачной части cuSel виден фон, который находится под ним
Следует делать спрайт более длинным, чтобы непрозрачный фон являлся подложкой селекту, тогда прозрачный участок ляжет сверху на эту подложку и cusel просвечиваться не будет.
Как убрать подсветку select при наведении и получении фокуса (update 31.07.10)
Достаточно убрать из стилей:
CSS
05 | .cusel:hover .cuselFrameRight, |
07 | .cusel:focus .cuselFrameRight, |
09 | .cuselFocus .cuselFrameRight { |
10 | background-image : url (path-to/selects-focus.png); |
Как динамически управлять disabled
Пример приведен в перечне доработок версии 2.3.
Улучшения по сравнению с предыдущей версией:
- работает в разы быстрее. Даже в IE6 при довольно большом количестве селектов на странице, замена происходит достаточно быстро.
- скрипт стал в 2 раза легче
- cuSel по поведению более похож на обычный селект
- более прост в обращении, особенно для программистов, которым теперь не нужно ломать голову как привязать onchange
Предыдущая версия
Баги/недостатки cuSel
У option должен обязательно быть атрибут value, хотя бы пустой — это исправлять пока не вижу смысла, потому что нет понту от селекта, который не передает значения. А для исключений можно дописать value="". устранено
- список выпадает всегда вниз
- в IE6 есть нет реакции на :hover
- если по пунктам выпавшего списка пробовать перемещаться и мышью и клавиатурой, могут проскакивать некоторые глюки
- нет поддержки <optgroup>, более того, скорей всего селект, содержащий optgroup не будет функционировать.
Пожелания / предложения
- by f0rmateg: раскрытие списка по нажатию на пробел, по аналогии как реализовано в Opera для обычных select
- by Олег Панов: предусмотреть реализацию для списков вида <select multiple size="1">
by Николай: предусмотреть возможность динамически дизэйблить и энэйблить селекты. реализовано
Апдейты: что было исправлено/добавлено