Делаем выпадающий список (select) с картинками на событиях mouseleave и mouseover jQuery

Делаем выпадающий список (select) с картинками на событиях mouseleave и mouseover jQuery

Выпадающий список, он же select, это один из самых часто используемых элементов html. Однако, в то время, когда стандарт разметки создавался, никто и представить себе не мог, что могут понадобиться выпадающие списки с картинками и анимацией. Поэтому, несмотря на то, что браузеры, стандарты стилей (css) и само понимание html ушло уже довольно далеко от первоначального, сами контролы тега select и их представления остаются прежними. Именно по этой причине, сегодня существует масса jQuery скриптов для имитации списков, которые скрывают изначальный тег select и создают подобие меню на любых других тэгах, как div. Безусловно, созданные элементы управления выглядят красиво, но у них есть ряд проблем:

  • Во-первых, выбранные значения всегда приходится дублировать.  
  • Во-вторых, усложняется способ использования самих тегов select, так как вы не можете изменять их значения напрямую. Вам необходимо использовать функции скриптовых оберток (плагинов).
  • В-третьих, если вам необходимо использовать дополнительные скрипты, которые должны вызываться в определенных событиях, то вы столкнетесь с проблемами интеграции. Так, например, достаточная часть плагинов рассчитана только на события "change" и "click", поэтому если вы захотели, например, показывать всплывающие подсказки, при наведении мышки на список, то сделать это будет очень не просто (придется копаться в html коде, чтобы понять, как сделано меню и на какие элементы вы сможете повесить обработчики).
  • В-четвертых, такие обертки/плагины обычно сложно модифицируются под ваши нужды. Другими словами, выглядят они красиво, но адаптировать их под задачи будет достаточно не просто.

Тем не менее, если у вас используются выпадающие списки с небольшим набором элементов (например, состояния, уровни доступа и так далее), то легко можно сделать выпадающий список с картинками, и не заменяя тег select другими конструкциями. И в этой статье будет показано, как при помощи css, а так же событий mouseleave и mouseover сделать такой список.

 

Рассмотрим проблему с картинками в тегах option внутри select-а

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

Напишем небольшой css:

option

{

    padding-left: 20px;

    padding-top: 3px;

    padding-bottom: 3px;

}

 

option:hover

{

    background-color: #eee;

}

 

.icon-ok

{

    background: url('../images/icon-ok.png') no-repeat;

    background-size: 20px;

    padding-left: 20px;

    background-position: 0 1px;

}

 

.icon-error

{

    background: url('/../images/icon-fail.png') no-repeat;

    background-size: 20px;

    padding-left: 20px;

    background-position: 0 1px;

}

Напишем простой html-код, внутри которого попробуем вначале расположить теги img внутри option, затем указать для того же select-а атрибут size, чтобы отображалось сразу несколько элементов. А затем попробуем применить к последнему списку описанные ранее классы в css.

<div class="form">

    <label>Некая пользовательская настройка (обычный список)</label>

    <br/><br/>

    <select class="select-test">

        <option value="1" class="icon-ok"><img src="/images/icon-ok.png" /> Вкл.</option> 

        <option value="0" class="icon-error"><img src="/images/icon-fail.png" /> Выкл.</option> 

    </select>

</div>

<div class="form">

    <label>Некая пользовательская настройка (мультисписок с картинками внутри)</label>

    <br/><br/>

    <select class="select-multi" size="2">

        <option value="1"><img src="/images/icon-ok.png" /> Вкл.</option> 

        <option value="0"><img src="/images/icon-fail.png" /> Выкл.</option> 

    </select>

</div>

<div class="form">

    <label>Некая пользовательская настройка (мультисписок на основе css)</label>

    <br/><br/>

    <select class="select-multi" size="2">

        <option value="1" class="icon-ok">Вкл.</option> 

        <option value="0" class="icon-error">Выкл.</option> 

    </select>

</div>

 

Результат, вы можете увидеть на следующей картинке:

Выпадающий список (select) с картинками внутри option и css 

Как видите, в первом варианте "select > option > img" ничего не произошло, список продолжил отображаться ровно так же, как и если бы вы ничего не указывали. Во втором варианте, когда у select был указан атрибут size, картинки так же не появились, но зато стало видно, что к option стало применяться больше стилей, так, например, можно отчетливо заметить "padding-left" (отступ слева). Третий же вариант, оказался наиболее удачным. За счет свойства "background: url('...')" рядом с элементами option, появились картинки.

Однако, у третьего варианта все же есть несколько проблем. Во-первых, выпадающий список на то и выпадающий, чтобы пользователю отображался только текущий выбранный элемент. Во-вторых, достаточно часто, при виде списков с несколькими отображенными элементами, пользователи ассоциируют такие select-ы с мультисписками, подразумевающими множественный выбор. В-третьих, полоса прокрутки на малом количестве элементов, как минимум, смотрится некрасиво. 

 

Делаем выпадающий список select с картинками в option на событиях mouseleave и mouseover jQuery

В отличии от option, к самому тегу select можно применять большинство стилей, вне зависимости от того, отображается ли выпадающий список, как мультисписок или нет. Это означает, что отображать картинку выбранного элемента вы можете в любой момент времени, просто добавляя необходимые стили, например, через классы css, к самому списку. Остается только лишь реализовать удобный для пользователей механизм перехода от обычного выпадающего списка к множественному. И в этом деле, как раз и пригодятся, события mouseleave и mouseover. Но, обо всем по порядку. Вначале необходимо подключить jQuery следующим образом

<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>

Затем дополним стили css.

select

{

    width: 200px;

}

 

option

{

    padding-left: 20px;

    padding-top: 3px;

    padding-bottom: 3px;

}

 

option:hover

{

    background-color: #eee;

}

 

.icon-ok

{

    background: url('../images/icon-ok.png') no-repeat;

    background-size: 20px;

    padding-left: 20px;

    background-position: 0 1px;

}

 

.icon-error

{

    background: url('/../images/icon-fail.png') no-repeat;

    background-size: 20px;

    padding-left: 20px;

    background-position: 0 1px;

}

 

select.icon-ok,

select.icon-error

{

    padding-top: 2px;

    padding-bottom: 3px;

    padding-left: 16px;

    background-position: 0 1px;

}

Как видите, в основном добились лишь небольшие правки к расположению картинки для тега select, а так же подсветка при наведении для option (для красоты).

После чего допишем html код

<div class="form">

    <label>Некая пользовательская настройка</label>

    <br/><br/>

    <select class="select-events">

        <option value="1" class="icon-ok">Вкл.</option> 

        <option value="0" class="icon-error">Выкл.</option> 

    </select>

</div>

Несложно заметить, что особых изменений нет, по сравнению с третьим вариантом (мультисписок с классами для option), кроме только лишь того, что к тегу добавился класс "select-events" (для простого выбора селектором в jQuery).

И напишем небольшой jQuery-скрипт:

// Функция очистки класса

function cleanSelect (select) {

    // Очищаем от стилей

    return $(select).removeClass('icon-ok').removeClass('icon-error')

}

 

// Формируем select и его обработчики

function formSelect() {

    // получаем выпадающий список с уже очищенными классами

    var select = cleanSelect('.select-events');

 

    // Добавляем класс, который соответствует выбранному элементу

    select.addClass(select.val() == '1' ? 'icon-ok' : 'icon-error');

 

    // Добавляем стили, чтобы у списка не было видно полосы прокрутки

    select.css({ height: 'auto', overflow: 'hidden', zIndex: '40000' });

 

    // Определяем обработчик на событие ухода мышки с области элемента

    select.on('mouseleave', function () {

        // Устанавливаем обычный размер

        this.size = 1;

        // Добавляем класс стиля в соответствии с выбранным элементом

        cleanSelect(this).addClass($(this).val() == '1' ? 'icon-ok' : 'icon-error');

    });

 

    // Определяем обработчик на событие ухода мышки с области элемента

    select.on('mouseover', function () {

        // Очищаем стиль списка, чтобы он не мешал отображению

        cleanSelect(this);

        // Устанавливаем размер, равный количеству элементов

        this.size = $(this).find('option').length;

    });

}

 

// После загрузки DOM - получаем список

$(function () {

    formSelect();

});

Как видите, скрипт достаточно простой. Функция "cleanSelect" очищает css классы у списка, чтобы во время выбора стили не накладывались друг на друга. А функция "formSelect" формирует все необходимые обработчики, скрывает стилями полосу прокрутки и указывает для select-а класс выбранного элемента.

Теперь, в тот момент, когда вы наведете мышку (событие mouseover) на выпадающий список, он автоматически раскроется до мультисписка со всеми элементами (строка "this.size = $(this).find('option').length;"). После того, как вы выберите элемент и отведете мышку в сторону (событие mouseleave), список снова станет стандартным (строка "this.size = 1;"). Вот картинка с результатом:

Делаем выпадающий список (select) с картинками на событиях mouseleave и mouseover jQuery

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

Скачать архив с демо-проектом вы можете по этой ссылке:

select-img.zip

☕ Понравился обзор? Поделитесь с друзьями!

Комментарии / отзывы  

0 # Я 01.07.2017 16:34
А если нужно больше чем 2 пункта, но с картинками?
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
0 # Игорь (Администратор) 02.07.2017 10:11
Добавляете пункты, для них так же определяете CSS классы.

Потом только строчку
Цитата:
cleanSelect(this).addClass($(this).val() == '1' ? 'icon-ok' : 'icon-error');
необходимо подредактировать, чтобы у списка появлялась подходящая иконка
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
0 # Денис 30.05.2018 15:57
Игорь добрый день!
Есть у меня такая задумка....а именно.. как сделать чтобы надпись под каждым названием в селекторе было переадресовано путь к картинке при этом чтобы она открывался в определенном месте на данной странице где находиться данный селектор!?
Спасибо за внимание!
Еще это сделать нужно с разделением на томы в данном селекторе!
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
0 # Игорь (Администратор) 30.05.2018 20:58
Постарайтесь сформулировать свою мысль более четко. Пишите лучше в почту, может чего подскажу.
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору

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

Комментарий - это вежливое и наполненное смыслом сообщение (правила).



* Нажимая на кнопку "Отправить", Вы соглашаетесь с политикой конфиденциальности.
Присоединяйтесь
 

 

Программы (Freeware, OpenSource...)