DeeDi - трезвые записки

Мультиселектор форм на jQuery

Очень часто при веб разработке приходится сталкиваться с надобностью выбора нескольких категорий. Это нужно, когда товар может находится в нескольких каталогах, когда у песни может быть несколько авторов или жанров, когда у новости несколько ключевых слов. Примеров ещё уйма, и для всего этого удобнее всего использовать селектор с функцией мультиселекта. Но в стандартном виде он крайне не удобный, а уже существующие плагины слишком громоздкие и тяжело интегрируемы в существующие проекты. Это меня и с подвигло изобрести свой велосипед.

За основу я решил взять jQuery фреймворк, т.к. javascript я знаю плохо да и заморачиваться с кроссбраузерностью не охото, тем более jQuery уже используется во многих моих проектах.

Требования к плагину:

  • Малый вес js и css
  • Удобный функционал
  • Простота интеграции
  • Использование нескольких селекторов на странице

В первую очередь нужно подключить jQuery, желательно подгружать его из хранилища google:


<head>
...
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
...
</head>

Добавляем код плагина:

<script type='text/javascript'>
$(document).ready(function() {

/* дополнительная функция */
function str_replace(search, replace, subject) {
return subject.split(search).join(replace);}

/* добавление */
function add_selected() {
var ij = $(this).attr('value');
if(ij!='') {
var ij2 = $(this).find('option:selected').text();
var hid = $(this).parents('.multi_f').find('.multi_h');
var d0 = $(this).parents('.multi_f').find('.multi_s_div');
var dhtml = d0.html();
if (ij2=='') {
ij2 = $(this).text();
$(this).remove();
} else {
$(this).find(':selected').remove();
}
$(this).hide(200);
d0.html(dhtml + '<div alt="'+ij+'" class="multi_s_divs"><div class="multi_t">'+ij2+'</div><div class="multi_x"></div></div>');
var hid1 = hid.val();
hid.val(hid1 + '.' + ij + '.' );
}
}

/*если есть уже выбранные*/
$('.multi_s :selected').each(add_selected);

/*раскрытие списка*/
$('.multi_s_div').live('click', function () {
if($('.multi_s_div').hasClass('not_slade')) /* анти баблинг */
{
$('.multi_s_div').removeClass('not_slade');
}else {
var tsss = $(this).width() + 6;
$(this).next('select').css('width',tsss);
$(this).next('select').toggle(100);
}
});


$('.multi_s').click (add_selected);

/* удаление */
$(".multi_x").live('click', function (e) {
$('.multi_s_div').addClass('not_slade');
var dv = $(this).parent();
var dv_atr = dv.attr('alt');
var dv_txt = dv.find('.multi_t').html();
var rf = $(this).parents('.multi_f').find('.multi_s');
var rf_h = rf.html();
rf.html(rf_h + '<option value="'+dv_atr+'">'+dv_txt+'</option>');
var hid = $(this).parents('.multi_f').find('.multi_h');
var hid1 = hid.val();
var dv_atr2 = '.' + dv_atr + '.';
var dv_new = str_replace(dv_atr2,'',hid1);
hid.val(dv_new);
dv.remove();
});

});
</script>

Теперь можно добавить код мультиселектора на страницу. Он должен быть заключён в DIV с классом "multi_f" (<div class="multi_f">). Так же в этом диве должны находится: div для отобранных селекторов и скрытый input, который и передаёт результат. Готовый пример:

<div class="multi_f">

<input class="multi_h" type="hidden" name="ИМЯ_СЕЛЕКТОРА" value="">
<div class="multi_s_div" ></div>

<select class="multi_s ne" size="5" multiple>
<option value="1">Селектор1</option>
<option value="2">Селектор2</option>
</select>

</div>

Теперь остаётся задать стили и подогнать их под свой дизайн:

<style type="text/css">
.ne{
display:none;
}
.multi_s_div {
width:200px; height:30px; cursor:text;
box-shadow: inset 0 0 2px #8F8F8F;
-moz-box-shadow: inset 0 0 2px #8F8F8F;
-webkit-box-shadow: inset 0 0 2px #8F8F8F;
padding:2px;
vertical-align:middle;
font-size:12px;
border: 1px solid #C8C8C8;
display: table;
}
.multi_s {position:absolute; z-index:200;}
.multi_s_divs {
float : left;
border: 1px solid #C8C8C8;
margin: 3px; padding:0;
border-radius: 4px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;

}
.multi_t{
float : left; padding:3px;
}
.multi_x {
background-color: #FEE2E8; cursor:pointer;
width:22px;height:22px; float : left;
background-image:url(close.png); background-repeat:no-repeat;
background-position:50% 50%;
margin: 0 0 0 3px;
}
</style>

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

Удалось добиться всех поставленных целей, код получился очень компактный и легко настраиваемый под любой дизайн.

demo

 

Боковой текст: