cuSel — нестандартные select на jQuery
Дата публикации: 24.06.2010
Задача
Изменить дизайн select. Например на такой:
Требования
- легкость интеграции
- кроссбраузерность
- быстрая скорость работы
- максимальная приближенность к работе обычного select:
- на сервер передается значение (value выбранного option)
- по клику на option выпавший список скрывается
- по клику вне select выпавший список скрывается
- в выпадающем списке показ полностью длинных значений option
- учет атрибута disabled
- учет атрибута selected
- если явно не указан selected, select принимает значение первого в списке option
- учет события onchange
- скроллинг выпадающего списка прокручивается колесом мыши
- при отключенном javascript остаются обычные select
- удобное динамическое обновление оптионов
- простота динамического добавления select
- дополнительные приятные возможности:
- подсветка в выпадающем списке выбранного значения
- подсветка в выпадающем списке значения при наведении
- возможность ручного управления видом скроллинга выпадающего списка
- возможность оформления option с помощью CSS
- возможность вставки тегов в option
- плавное обрезание невмещающегося текста
Демо пример возможностей cuSel. Проверено в:
- IE 6-8
- Firefox 3.6
- Opera 9.5-10
- Safari 4
- Chrome 4
Что качать
- библиотеку jquery версии не ниже 1.4.2
- cusel-min-2.1.js (15Kb)
- cusel.css
- спрайт для образца
Заметка
Для плавного обрезания текста спрайт должен иметь градиент, переходящий от фона селекта в прозрачность и расположенный левее правой кнопки списка:
При таком эффекте для IE6 подключаем DD_belatedPNG.
Если охота посмотреть код
- библиотеки jScrollPane.js (оригинал был изменен) и jquery.mousewheel.js для реализации прокрутки в выпадающем списке
- cusel.js
Быстрый старт
Подключаем необходимые стили и библиотеки:
<link rel="stylesheet" type="text/css" href="path-to/cusel.css" /> <script type="text/javascript" src="path-to/jquery-1.4.2.js"></script> <script type="text/javascript" src="path-to/cusel-min.js"></script> <!-- если требуется поддержка ie6, учим его понимать альфапрозрачность для плавного обрезания текста --> <!--[if IE 6]> <script type="text/javascript" src="path-to/DD_belatedPNG.js"></script> <script type="text/javascript"> DD_belatedPNG.fix(".cuselFrameRight"); <!-- именно этот элемент имеет полупрозрачность --> </script> <![endif]-->
Инициализируем cusel, указывая, где и как стилизовать select:
var params = { changedEl: ".lineForm select", visRows: 5, scrollArrows: true } cuSel(params);
А теперь подробней.
Как это работает
При загрузке страницы, если у пользователя включен javascript:
- находятся все указанные селекты на странице
- заменяется каждый select
<select id="idSelect" name="nameSelect"> <option value="значение option 1">текст option 1</option> ... <option value="значение option N">текст option N</option> </select>
на конструкцию вида:
<div class="cusel" id="cuselFrame-idSelect"> <div class="cuselFrameRight"></div> <div class="cuselText">текст option 1</div> <div class="cusel-scroll-wrap"> <div class="cusel-scroll-pane" id="cusel-scroll-idSelect"> <span class="cuselActive" value="значение option 1">текст option 1</span> ... <span value="значение option N">текст option N</span> </div> </div> <input id="idSelect" name="nameSelect" value="значение option 1" type="hidden"/> </div>
- обычные select удаляются
Инициализация cuSel
Функции
cuSel | производит замену обычных select на стилизованные. Меняет только те, которые указаны в параметре changedEl. |
---|---|
cuSelRefresh | производит обновление селекта. Необходимо при изменении количества option в select и при показе скрытого select. Обновляет селекты, указанные в параметре refreshEl. |
Параметры
changedEl | указываем селекторы (за основу взяты базовые селекторы CSS1) , к которым будет применен cuSel. Можно указать элемент (тег), класс, id. Обязательный параметр. Используется только в функции cuSel. |
---|---|
visRows | количество видимых строк выпадающего списка. Если в списке элементов будет больше заданного числа, у списка появится вертикальная прокрутка. Если число не задано, все значения списка будут видимы. |
scrollArrows | отражать или нет стрелочки в блоке с прокруткой. Возможные значения: true/false (по умолчанию false) |
checkZIndex | пересчитать ли z-index cusel-селектов после добавления нового. Необходимо при добавлении select над или под другим cusel-селектом. Возможные значения: true/false (по умолчанию false) |
refreshEl | id селектов через запятую, которые требуется обновить. Параметр обязателен. Используется только в функции cuSelRefresh. |
Примеры
Меняем все селекты на странице, без ограничения по высоте для выпадающих списков:
var params = { changedEl: "select" } cuSel(params);
Меняем один конкретный селект по id, число видимых элементов выпадающего списка 7:
var params = { changedEl: "#city", visRows: 7 } cuSel(params);
Цепляем onchange списку. Сusel-селект имеет структуру, построенную на div и span. Это нужно учитывать при динамическом изменении содержимого списков:
<select id="city" name="city" onChange="alert('произошел onchange')"> <option value="1">Киев</option> <option value="2">Львов</option> <option value="3">Дон</option> <option value="4">Ялта</option> </select>
var params = { changedEl: "#city" } cuSel(params);
Если при загрузке страницы select был скрыт, то при его показе ему нужно обязательно указывать width и провести обновление:
jQuery("#showSel").click( function() { jQuery("#hidden-select") .css("display","block") .css("width","100px"); /* показанному селект указываем width */ params = { refreshEl: "#hidden-select", visRows: 4 } cuSelRefresh(params); });
Этого указания ширины можно избежать, если изначально select был присвоен класс, с заданной шириной через !important. Тут же, покажу как обновить сразу два селекта, которые были скрыты:
<div id="hidden-block" style="display: none"> <select id="city2" name="city2" class="wid100"> <option value="1">Киев</option> <option value="2">Львов</option> <option value="3">Донецк</option> <option value="4">Ялта</option> </select> <select id="city3" name="city3" class="wid100"> <option value="1">Киев</option> <option value="2">Львов</option> <option value="3">Донецк</option> <option value="4">Ялта</option> </select>
.wid100 { width: 100px !important; /* !important обязателен */ }
jQuery("#hidden-block").css("display","block"); params = { refreshEl: "#city2, #city3", /* перечисляем через запятую id селектов, которые нужно обновить */ visRows: 4 } cuSelRefresh(params);
Динамическое добавление select:
jQuery("#addSelect").click( function() { var addedSelect = '<select id="add-select" name="add-select">'+ '<option value="1">доллар США</option>'+ '<option value="2">доллар канадский</option>'+ '<option value="3">доллар новозеландский</option>'+ '</select>'; jQuery(this).replaceWith(addedSelect); var params = { changedEl: "#add-select", visRows: 4, checkZIndex: true } cuSel(params); });
Динамическое добавление опционов:
jQuery("#addAnimals").click( function() { /* при добавлении следует учитывать, что option были заменены на span */ var newAnimals = '<span value="4">Слон</span><span value="5">Жираф африканский</span>'; /* id контенера, где содержаться "option" получаем соединяя префикс cusel-scroll- и id select */ jQuery("#cusel-scroll-animals").append(newAnimals); var params = { refreshEl: "#animals", visRows: 4 } cuSelRefresh(params); });
Дополнительные теги внутри option реализуются через дополнительный атрибут addTags. Если он присутствует, его содержимое добавится в соответствующий «новый» option:
<select id="animals" name="animals"> <option value="1" addTags="<div class='kv'></div>">Медведь</option> <option value="2" addTags="<input type='checkbox' />">Волк</option> <option value="3">Заяц</option> <option value="4">Ежик</option> </select>
Часто задаваемые вопросы
Как на одной странице сделать два селекта разного вида
Нужно привязывать оформление селекта относительно своего родителя:
.parent1 .cusel { /* описываем оформление селекта первого вида */ } .parent2 .cusel { /* описываем оформление селекта второго вида */ }
Можно подключить разные фоны, использовать разные цветовые схемы, шрифты и т.п.
Или же можно использовать дополнительный класс:
<select id="select1" name="select1"> ... <select id="select2" name="select2" class="cusel2"> ...
.cusel { /* описываем оформление селекта первого вида */ } .cusel2 { /* описываем оформление селекта второго вида */ }
Как убрать выделение выбранного пункта в выпадающем списке
Из CSS удаляем класс .cuselActive.
Как задать ширину стилизированного select
В CSS указать явно ширину классу .cusel или добавить класс, с явно заданной шириной заменяемому select.
В прозрачной части cuSel виден фон, который находится под ним
Следует делать спрайт более длинным, чтобы непрозрачный фон являлся подложкой селекту, тогда прозрачный участок ляжет сверху на эту подложку и cusel просвечиваться не будет.
Улучшения по сравнению с предыдущей версией:
- работает в разы быстрее. Даже в IE6 при довольно большом количестве селектов на странице, замена происходит достаточно быстро.
- скрипт стал в 2 раза легче
- cuSel по поведению более похож на обычный селект
- более прост в обращении, особенно для программистов, которым теперь не нужно ломать голову как привязать onchange
Предыдущая версия
- selects.png (370b) — составная картинка для всех частей селекта (удобно использовать в качестве примера)
- selects.css (3.5 Kb) — таблица стилей для нестандартных select
- selectsComments.css (6.5 Kb) — таблица стилей с комментариями
- jquery.js (55.9 Kb) — библиотека jQuery версии 1.3.2
- jsScroll.js (8.13 Kb) — библиотека для реализации нестандартно оформленного скроллинга
- jquery.selects.js (12 Kb) — библиотека замены select на нестандартные
- jquery.selects_pack.js (3 Kb) — сжатый скрипт
Баги/недостатки cuSel
- У option должен обязательно быть атрибут value, хотя бы пустой — это исправлять пока не вижу смысла, потому что нет понту от селекта, который не передает значения. А для исключений можно дописать value=»».
- выпадающий список может быть шире самого селекта на ширину боковых бордюр. Чтобы это устранить настраиваем стили таким образом, чтобы на ширину контейнера не влияли бордюры — смотрим классы .cusel-scroll-wrap и .jScrollPaneContainer
- не получает фокус
- выпадает из tab-обхода
- нет перехода на первое значение, соотвествующее нажатому символу
- список выпадает всегда вниз
в Opera 10.5 прокрутка мышью выпадающего списка приводит к прокрутке всего окна браузераисправленопри прокрутке скролом мыши по окончанию списка прокручивается окно браузераисправленона клик по текущему значению в выпадающем списке плагин никак не реагирует (список должен закрываться)исправленопри выборе значений в выпадающем списке, рядом располженый label (в принципе любой элемент) немного «прыгает»исправлено- в IE6 есть несколько багов: нет реакции на :hover в списке и ширина выпадаюшего списка не всегда правильно подстравивается под ширину каркаса селекта (на эти баги осознанно проигнорровал в сторону большей гибкости для нормальных браузеров)