Наверх

Загрузка постов


CodeMatrix

A+ R A-

Оформляем тег select – просто и быстро

Уж не помню почему, но оформление тега select вызывало какие-то адские трудности. Свидетельство тому – множество постов на просторах интернета, инструктирующих по данному вопросу и зачастую обладающих теми или иными надостатками. Более того, помню что и сам как-то мучился, приводя сей тег в соответствие макету заказчика и что-то попутно высказывая в сторону неуемной фантазии дизайнеров.
И вдруг – столкнувшись снова с этой задачей после долгого перерыва – обнаружил что все трудности куда-то делись. Все уместилось в маленький файл js и несколько строк css – при этом селект остается селектом и не подменяется сложной конструкцией из копирующих его блоков div, например.

Итак, решение:

Копируем файл select-wrap.js и подключаем его к нашей странице. Все как обычно, через тег script в заголовке <head> (<script src=”путь к файлу/select-wrap.js” type=”text/javascript”></script>, как-то так).
После его подключения обнаруживаем что все селекты на странице вида:


автоматом превращаются в:

Text111

Обертка в виде div’а с классом wselect будет изображать наш селект, для чего мы придадим ей соответствующий background и прочее – все как на макете. Т.е. это будет фон нашего селекта.
Span с классом selecttext внутри обертки будет выдавать текст, копируя значение select’а (и опять же, его нужно привести в соответствие макету – цвет, высота шрифта и проч). Т.е., опять же, это текст внутри селекта.
А сам селект мы сделаем прозрачным, но кликабельным и поместим его поверх нашей div’ной обертки. Чтобы все это случилось, добавим в страницу следующие стили:

.wselect {
	position: relative; /* Чтобы он ограничил собой завернутый select. Далее добавляем ему background, border-radius, тени, бордеры, размеры, в общем все, что нашей душе угодно */
}

.selecttext {
	overflow: hidden; /* Чтобы не вылезал за пределы div-обертки */
	display: block; /* Чтобы заполнил собой весь div. И, далее, опять – стили для текста внутри, заданные макетом – высота шрифта, цвет и проч. и проч. */
}

select {
	position: absolute; /* Чтоб он выводился поверх обертки и был кликабельным */
top: 0;
	left: 0; /* Перемещаем его в верхний левый угол div-обертки  */
	width: 100%; /* …и растягиваем по длине на всю эту обертку. А чтоб и по высоте, лучше добавить соответствующий line-height */
	opacity: 0; /* И делаем его при этом прозрачным */
	cursor: pointer; /* На всякий случай */
}

(Не забудьте только удалить все пояснения между /* и */. Комментарии, как говорится, излишни).

И все.
В результате видим мы div-обертку и span-текст, а кликаем по настоящему select’у. Выпадающие options’ы при этом остаются вполне даже видимыми. Их оформление мы уже рассматривать не будем – оно зачастую и не требуется, как показывает практика.
Кстати, на всякий случай: у каждого span’а с классом selecttext есть свой id selecttext0, selecttext1, selecttext2 и далее до бесконечности, где число после selecttext равно индексу соответствующего селекта на странице.

В довесок тем, кому это интересно, предлагаю рассмотреть что же происходит в js файле. Собственно, большая его часть и без того прокомментирована:

window.onload = function() {

/* Объявление переменных. slct - массив тегов select страницы, L - их количество, i - счетчик циклов, tmp - контейнер для создаваемого тега*/
var slct = document.getElementsByTagName('select'),
	L = slct.length,
	i, tmp;

// Отключаем процесс для IE-8
if (window.navigator.userAgent.indexOf('IE 8') != -1) {L = 0;}

/* Перебираем select'ы, оборачиваем их в div с классом wselect и добавляем span с классом selecttext для вывода текста из select'а*/
for (i = 0; i < L; i++) {
	tmp = document.createElement('div');
	tmp.className = 'wselect';
	slct[i].parentNode.insertBefore(tmp, slct[i]);
	tmp.appendChild(slct[i]);
	tmp.innerHTML = '' + tmp.innerHTML;
};

//Селекты обернуты и готовы к использованию

/*Создаем функцию, которая в селекте с индексом nn определяет активный option, берет из него текст и вставляет его в span с классом selecttext, после чего увеличивает счетчик (nn) на один и, если еще есть селекты с этим индексом, запускает сама себя, обрабатывая следующий select (таким образом перебираются все селекты страницы)*/
function goSelect(nn, L) {
	myid = 'selecttext' + nn;
	fgm = 0;
for (i = 0; i < document.getElementsByTagName('select')[nn].options.length; i++) {
	if (document.getElementsByTagName('select')[nn].options[i].selected) {fgm = i;}
}
	document.getElementById(myid).innerHTML = document.getElementsByTagName('select')[nn].options[fgm].text;
	nn++;
	if (nn < L) {goSelect(nn, L);}
}

// Функция, запускающая предыдущую со стартовым индексом nn = 0
function goSelectPlus(){
	goSelect(0, L);
}

// И, наконец, функция, периодически запускающая предыдущую с интервалом 100
setInterval(goSelectPlus, 100);
}

Что же происходит? Когда window готов и загружен, в первом цикле мы оборачиваем все селекты в уже известную нам конструкцию. В конце скрипта с определенной периодичностью мы начинаем запуск функции goSelectPlus, которая стартует функцию goSelect, которая, в свою очередь, каждый раз перебирает все селекты и вставляет их текущее значение в span selecttext.

Все нормально функционирует, только для ie8 предусмотрено отключение оборачивания (а также следует сделать для него обычные стили select), ибо в нем не работает. Ну и ладно.