Совершенствуем принцип отображения элементов «select» посредством jQuery и CSS3

При создании веб-дизайнов, разработчики всегда стремятся добиться оптимального отображения веб-сайта во всех браузерах. К сожалению, одним из основных элементов веб-сайта являются настройки браузера, к тому же, это значительно усложняет процесс оформления. Некоторые из спецификаций браузеров (например, элементы форм «select») вообще невозможно изменить, за исключением некоторых случаев.

По этой причине сегодня мы хотим поделиться с вами скриптом, который поможет нам заменить простой элемент «select» на более привлекательный, оставив полностью весь функционал.

HTML

Как и обычно, начнем с разработки HTML-кода. Мы будем использовать разметку HTML5, так как это даст нам некоторое преимущество (например, возможность вносить атрибуты данных, с помощью которых мы можем в целом дополнить разметку страницу.

Код

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Making Better Select Elements with jQuery and CSS3</title>

<link rel="stylesheet" type="text/css" href="css/styles.css" />

</head>
<body>

<div id="page">
  <h1>Your Product</h1>

  <form method="post" action="">

  <select name="fancySelect" class="makeMeFancy">

  <option value="0" selected="selected" data-skip="1">Choose Your Product</option>
  <option value="1" data-icon="img/products/iphone.png" data-html-text="iPhone 4<i>in stock</i>">iPhone 4</option>
  <option value="2" data-icon="img/products/ipod.png" data-html-text="iPod <i>in stock</i>">iPod</option>
  <option value="3" data-icon="img/products/air.png" data-html-text="MacBook Air<i>out of stock</i>">MacBook Air</option>
  <option value="4" data-icon="img/products/imac.png" data-html-text="iMac Station<i>in stock</i>">iMac Station</option>
  </select>
  </form>

</div>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
<script src="js/script.js"></script>

</body>
</html>


В коде можно заметить, что мы применяем атрибуты данных ко встроенной информации и в элементах опций «select». Мы вносим иконку продукта и богатое текстовое описание. Всё это будет отображено в усовершенствованной версии элемента «select».

Мы также внесли дополнительный атрибут data-skip к первому элементу, так что наш скрипт знает, чего ему не нужно включать в сгенерированный список. Можно просто проверить наличие атрибутов data-icon и data-html-text и пропустить элемент, если это потребуется.

В нижней части документа включён jQuery версии 1.4.3 (последняя версия библиотеки на момент написания этой статьи), а также наш script.js. Об этом мы расскажем в следующем этапе разработки.

jQuery

При событии document.ready, jQuery проверяет элемент «select» и, используя атрибуты данных, создаёт разметку, которую вы можете видеть ниже, которая появляется сразу же после «select»:

Код

<div style="width: 144px;" class="tzSelect">
  <div class="selectBox">iMac Station</div>
  <ul class="dropDown">
  <li><img src="img/products/iphone.png"><span>iPhone 4<i>in stock</i></span></li>
  <li><img src="img/products/ipod.png"><span>iPod <i>in stock</i></span></li>
  <li><img src="img/products/air.png"><span>MacBook Air<i>out of stock</i></span></li>
  <li><img src="img/products/imac.png"><span>iMac Station<i>in stock</i></span></li>
  </ul>
</div>


Как видно, мы создаём неупорядоченный список с элементом li, который представляет каждую опцию в «select». Сама форма «select» представлена посредством div’а с классом .selectBox.

Теперь давайте поближе взглянем на сгенерированный код.

Код

$(document).ready(function(){

  // The select element to be replaced:
  var select = $('select.makeMeFancy');

  var selectBoxContainer = $('<div>',{
  width : select.outerWidth(),
  className : 'tzSelect',
  html : '<div class="selectBox"></div>'
  });

  var dropDown = $('<ul>',{className:'dropDown'});
  var selectBox = selectBoxContainer.find('.selectBox');

  // Looping though the options of the original select element

  select.find('option').each(function(i){
  var option = $(this);

  if(i==select.attr('selectedIndex')){
  selectBox.html(option.text());
  }

  // As of jQuery 1.4.3 we can access HTML5
  // data attributes with the data() method.

  if(option.data('skip')){
  return true;
  }

  // Creating a dropdown item according to the
  // data-icon and data-html-text HTML5 attributes:

  var li = $('<li>',{
  html: '<img src="'+option.data('icon')+'" /><span>'+
  option.data('html-text')+'</span>'
  });

  li.click(function(){

  selectBox.html(option.text());
  dropDown.trigger('hide');

  // When a click occurs, we are also reflecting
  // the change on the original select element:
  select.val(option.val());

  return false;
  });

  dropDown.append(li);
  });

  selectBoxContainer.append(dropDown.hide());
  select.hide().after(selectBoxContainer);

  // Binding custom show and hide events on the dropDown:

  dropDown.bind('show',function(){

  if(dropDown.is(':animated')){
  return false;
  }

  selectBox.addClass('expanded');
  dropDown.slideDown();

  }).bind('hide',function(){

  if(dropDown.is(':animated')){
  return false;
  }

  selectBox.removeClass('expanded');
  dropDown.slideUp();

  }).bind('toggle',function(){
  if(selectBox.hasClass('expanded')){
  dropDown.trigger('hide');
  }
  else dropDown.trigger('show');
  });

  selectBox.click(function(){
  dropDown.trigger('toggle');
  return false;
  });

  // If we click anywhere on the page, while the
  // dropdown is shown, it is going to be hidden:

  $(document).click(function(){
  dropDown.trigger('hide');
  });
});


При полной загрузке страницы, скрипт сканирует опции элемента «select» и генерирует разметку в соответствии с атрибутами данных в HTML5, которые содержат эти пункты. Что касается jQuery версии 1.4.3, то посредством этой версии мы имеем доступ к значениям этих атрибутов напрямую при помощи метода data(). Это очень удобная функция, которая значительно упрощает процесс считывания встроенных данных.

Стандартный элемент «select» не уничтожается – он просто скрывается посредством метода hide(). Это важно, потому что, как вы можете видеть в коде выше, нам нужно отражать любые изменения в форме на стандартный элемент «select». Таким образом, когда вы используете «select» в качестве части формы, значения считываются правильно, а затем передаются в базу данных.

Теперь, когда наш код на месте, давайте подробнее рассмотрим CSS3.

CSS-код

Как видно из разметки в верхней части предыдущего этапа, мы используем лишь немного кода для отображения поля «select» и выпадающий список. Если мы захотим использовать методики, бывшие в употреблении до прихода CSS3, то нам придётся добавить намного больше div’ов и span’ов.

Код

#page{
  width:230px;
  margin:100px auto;
}

#page h1{
  font-weight:normal;
  text-indent:-99999px;
  overflow:hidden;
  background:url('../img/your_product.png') no-repeat;
  width:230px;
  height:36px;
}

#page form{
  margin:20px auto;
  width:200px;
}

.tzSelect{

  /* This is the container of the new select element */

  height:34px;
  display:inline-block;
  min-width:200px;
  position:relative;

  /* Preloading the background image for the dropdown */
  background:url("../img/dropdown_slice.png") no-repeat -99999px;
}

.tzSelect .selectBox{
  position:absolute;

  height:100%;
  width:100%;

  /* Font settings */

  font:13px/34px "Lucida Sans Unicode", "Lucida Grande", sans-serif;
  text-align:center;
  text-shadow:1px 1px 0 #EEEEEE;
  color:#666666;

  /* Using CSS3 multiple backgrounds and a fallback */

  background:url('../img/select_slice.png') repeat-x #ddd;
  background-image:url('../img/select_slice.png'),url('../img/select_slice.png'),url('../img/select_slice.png'),url('../img/select_slice.png');
  background-position:0 -136px, right -204px, 50% -68px, 0 0;
  background-repeat: no-repeat, no-repeat, no-repeat, repeat-x;

  cursor:pointer;

  -moz-border-radius:3px;
  -webkit-border-radius:3px;
  border-radius:3px;
}

.tzSelect .selectBox:hover,
.tzSelect .selectBox.expanded{
  background-position:0 -170px, right -238px, 50% -102px, 0 -34px;
  color:#2c5667;
  text-shadow:1px 1px 0 #9bc2d0;
}


CSS3 позволяет нам задавать различные фоновые изображения к элементам путем добавления множественных объявлений url(), разделённых запятыми. Они добавляются к элементу сверху вниз последовательно, с отдельными изображениями фона, отображенными под каждым пунктом.



На данный момент множественные фоновые изображения поддерживаются в браузерах Firefox, Safari, Chrome и Opera. Что касается Internet Explorer и ранних версий других браузеров, то здесь имеется версия для отката, т.е. задействуется стандартное фоновое изображение. Когда браузеры парсят CSS-документ, те браузеры, которые не распознают множественные фоновые изображения, будут просто игнорировать правило и использовать одно из них.

Код
.tzSelect .dropDown{
  position:absolute;
  top:40px;
  left:0;
  width:100%;
  border:1px solid #32333b;
  border-width:0 1px 1px;
  list-style:none;

  -moz-box-sizing:border-box;
  -webkit-box-sizing:border-box;
  box-sizing:border-box;

  -moz-box-shadow:0 0 4px #111;
  -webkit-box-shadow:0 0 4px #111;
  box-shadow:0 0 4px #111;
}

.tzSelect li{
  height:85px;
  cursor:pointer;
  position:relative;

  /* Again, using CSS3 multiple backgrounds */

  background:url('../img/dropdown_slice.png') repeat-x #222;
  background-image:url('../img/dropdown_slice.png'),url('../img/dropdown_slice.png'),url('../img/dropdown_slice.png');
  background-position: 50% -171px, 0 -85px, 0 0;
  background-repeat: no-repeat, no-repeat, repeat-x;
}

.tzSelect li:hover{
  background-position: 50% -256px, 0 -85px, 0 0;
}

.tzSelect li span{
  left:88px;
  position:absolute;
  top:27px;
}

.tzSelect li i{
  color:#999999;
  display:block;
  font-size:12px;
}

.tzSelect li img{
  left:9px;
  position:absolute;
  top:13px;
}


Параметр box-sizing, который мы использовали для класса .dropDown, определяет то, как границы добавляются к общему размеру элемента. По умолчанию, здесь границы будут увеличивать общую ширину на 2 пикселя, что отрицательно скажется на выравнивании. С установленным параметром box-sizing, тем не менее, общая ширина не будет превышать заранее установленную отметку, и поэтому браузеры будут использовать пространство внутри элемента.

На этом наше поле «select» на jQuery и CSS3 закончено!

Напоследок

В этой статье мы продемонстрировали некоторые полезные функции, представленные в jQuery версии 1.4.3, а также некоторые возможности CSS3. Следует отметить то, что данный скрипт сохраняет стандартное поле «select» скрытым на странице, а его значения изменяются посредством хитрости. Таким образом, когда вы подтверждаете хитрый «select», корректное значение также предоставляется на обработку.

  • FalleN

  • 3522

  • 1

  • 202

Ссылки на статью:

Похожие статьи: