| 1 | /* |
|---|
| 2 | * multiselect2side jQuery plugin |
|---|
| 3 | * |
|---|
| 4 | * Copyright (c) 2010 Giovanni Casassa (senamion.com - senamion.it) |
|---|
| 5 | * |
|---|
| 6 | * Dual licensed under the MIT (MIT-LICENSE.txt) |
|---|
| 7 | * and GPL (GPL-LICENSE.txt) licenses. |
|---|
| 8 | * |
|---|
| 9 | * http://www.senamion.com |
|---|
| 10 | * |
|---|
| 11 | */ |
|---|
| 12 | |
|---|
| 13 | (function($) |
|---|
| 14 | { |
|---|
| 15 | jQuery.fn.multiselect2side = function (o) { |
|---|
| 16 | |
|---|
| 17 | o = $.extend({ |
|---|
| 18 | selectedPosition: 'right', |
|---|
| 19 | moveOptions: true, |
|---|
| 20 | labelTop: 'Top', |
|---|
| 21 | labelBottom: 'Bottom', |
|---|
| 22 | labelUp: 'Up', |
|---|
| 23 | labelDown: 'Down', |
|---|
| 24 | labelSort: 'Sort', |
|---|
| 25 | labelsx: 'Available', |
|---|
| 26 | labeldx: 'Selected', |
|---|
| 27 | maxSelected: -1 |
|---|
| 28 | }, o); |
|---|
| 29 | |
|---|
| 30 | |
|---|
| 31 | return this.each(function () { |
|---|
| 32 | var el = $(this); |
|---|
| 33 | |
|---|
| 34 | var originalName = $(this).attr("name"); |
|---|
| 35 | if (originalName.indexOf('[') != -1) |
|---|
| 36 | originalName = originalName.substring(0, originalName.indexOf('[')); |
|---|
| 37 | |
|---|
| 38 | var nameDx = originalName + "ms2side__dx"; |
|---|
| 39 | var nameSx = originalName + "ms2side__sx"; |
|---|
| 40 | var size = $(this).attr("size"); |
|---|
| 41 | // SIZE MIN |
|---|
| 42 | if (size < 6) { |
|---|
| 43 | $(this).attr("size", "6"); |
|---|
| 44 | size = 6; |
|---|
| 45 | } |
|---|
| 46 | |
|---|
| 47 | // UP AND DOWN |
|---|
| 48 | var divUpDown = |
|---|
| 49 | "<div class='ms2side__updown'>" + |
|---|
| 50 | "<div class='Sort' title='Sort'>" + o.labelSort + "</div>" + |
|---|
| 51 | "<p class='MoveUp' title='Move up selected option'>" + o.labelUp + "</p>" + |
|---|
| 52 | "<p class='MoveDown' title='Move down selected option'>" + o.labelDown + "</p>" + |
|---|
| 53 | "<p class='MoveTop' title='Move on top selected option'>" + o.labelTop + "</p>" + |
|---|
| 54 | "<p class='MoveBottom' title='Move on bottom selected option'>" + o.labelBottom + "</p>" + |
|---|
| 55 | "</div>"; |
|---|
| 56 | |
|---|
| 57 | // CREATE NEW ELEMENT (AND HIDE IT) AFTER THE HIDDED ORGINAL SELECT |
|---|
| 58 | var htmlToAdd = |
|---|
| 59 | "<div class='ms2side__div clearfix'>" + |
|---|
| 60 | ((o.selectedPosition != 'right' && o.moveOptions) ? divUpDown : "") + |
|---|
| 61 | "<div class='ms2side__select'>" + |
|---|
| 62 | (o.labelsx ? ("<div class='ms2side__header'>" + o.labelsx + "</div>") : "") + |
|---|
| 63 | "<select title='" + o.labelsx + "' name='" + nameSx + "' id='" + nameSx + "' size='" + size + "' multiple='multiple' ></select>" + |
|---|
| 64 | "</div>" + |
|---|
| 65 | "<div class='ms2side__options'>" + |
|---|
| 66 | ((o.selectedPosition == 'right') |
|---|
| 67 | ? |
|---|
| 68 | ("<p class='RemoveOne' title='Remove Selected'>‹</p>" + |
|---|
| 69 | "<p class='RemoveAll' title='Remove All'>«</p>" + |
|---|
| 70 | "<p class='AddOne' title='Add Selected'>›</p>" + |
|---|
| 71 | "<p class='AddAll' title='Add All'>»</p>") |
|---|
| 72 | : |
|---|
| 73 | ("<p class='RemoveOne' title='Remove Selected'>‹</p>" + |
|---|
| 74 | "<p class='RemoveAll' title='Remove All'>«</p>" + |
|---|
| 75 | "<p class='AddOne' title='Add Selected'>›</p>" + |
|---|
| 76 | "<p class='AddAll' title='Add All'>»</p>") |
|---|
| 77 | ) + |
|---|
| 78 | "</div>" + |
|---|
| 79 | "<div class='ms2side__select'>" + |
|---|
| 80 | (o.labeldx ? ("<div class='ms2side__header'>" + o.labeldx + "</div>") : "") + |
|---|
| 81 | "<select title='" + o.labeldx + "' name='" + nameDx + "' id='" + nameDx + "' size='" + size + "' multiple='multiple' ></select>" + |
|---|
| 82 | ((o.selectedPosition == 'right' && o.moveOptions) ? divUpDown : "") + |
|---|
| 83 | "</div>" + |
|---|
| 84 | "</div>"; |
|---|
| 85 | $(this).after(htmlToAdd).hide(); |
|---|
| 86 | |
|---|
| 87 | // ELEMENTS |
|---|
| 88 | var allSel = $(this).next().find("select"); |
|---|
| 89 | var leftSel = (o.selectedPosition == 'right') ? allSel.eq(0) : allSel.eq(1); |
|---|
| 90 | var rightSel = (o.selectedPosition == 'right') ? allSel.eq(1) : allSel.eq(0); |
|---|
| 91 | // HEIGHT DIV |
|---|
| 92 | var heightDiv = $(".ms2side__select").eq(0).height(); |
|---|
| 93 | |
|---|
| 94 | // CENTER MOVE OPTIONS AND UPDOWN OPTIONS |
|---|
| 95 | $(this).next().find('.ms2side__options, .ms2side__updown').each(function(){ |
|---|
| 96 | /************************************************ |
|---|
| 97 | * レイアウト調整のためコメントアウト |
|---|
| 98 | var top = ((heightDiv/2) - ($(this).height()/2)); |
|---|
| 99 | if (top > 0) |
|---|
| 100 | $(this).css('padding-top', top + 'px' ); |
|---|
| 101 | *************************************************/ |
|---|
| 102 | }) |
|---|
| 103 | |
|---|
| 104 | // MOVE SELECTED OPTION TO RIGHT, NOT SELECTED TO LEFT |
|---|
| 105 | $(this).find("option:selected").clone().appendTo(rightSel); |
|---|
| 106 | $(this).find("option:not(:selected)").clone().appendTo(leftSel); |
|---|
| 107 | |
|---|
| 108 | // SELECT FIRST LEFT ITEM |
|---|
| 109 | if (!(navigator.userAgent.toLowerCase().indexOf('msie 6') != -1)) |
|---|
| 110 | leftSel.find("option").eq(0).attr("selected", true); |
|---|
| 111 | |
|---|
| 112 | // ON CHANGE REFRESH ALL BUTTON STATUS |
|---|
| 113 | allSel.change(function() { |
|---|
| 114 | var div = $(this).parent().parent(); |
|---|
| 115 | var selectSx = leftSel.children(); |
|---|
| 116 | var selectDx = rightSel.children(); |
|---|
| 117 | var selectedSx = leftSel.find("option:selected"); |
|---|
| 118 | var selectedDx = rightSel.find("option:selected"); |
|---|
| 119 | |
|---|
| 120 | if (selectedSx.size() == 0 || |
|---|
| 121 | (o.maxSelected >= 0 && (selectedSx.size() + selectDx.size()) > o.maxSelected)) |
|---|
| 122 | div.find(".AddOne").addClass('ms2side__hide'); |
|---|
| 123 | else |
|---|
| 124 | div.find(".AddOne").removeClass('ms2side__hide'); |
|---|
| 125 | |
|---|
| 126 | // FIRST HIDE ALL |
|---|
| 127 | div.find(".RemoveOne, .MoveUp, .MoveDown, .MoveTop, .MoveBottom, .SelSort").addClass('ms2side__hide'); |
|---|
| 128 | if (selectDx.size() > 1) |
|---|
| 129 | div.find(".SelSort").removeClass('ms2side__hide'); |
|---|
| 130 | if (selectedDx.size() > 0) { |
|---|
| 131 | div.find(".RemoveOne").removeClass('ms2side__hide'); |
|---|
| 132 | // ALL SELECTED - NO MOVE |
|---|
| 133 | if (selectedDx.size() < selectDx.size()) { // FOR NOW (JOE) && selectedDx.size() == 1 |
|---|
| 134 | if (selectedDx.val() != selectDx.val()) // FIRST OPTION, NO UP AND TOP BUTTON |
|---|
| 135 | div.find(".MoveUp, .MoveTop").removeClass('ms2side__hide'); |
|---|
| 136 | if (selectedDx.last().val() != selectDx.last().val()) // LAST OPTION, NO DOWN AND BOTTOM BUTTON |
|---|
| 137 | div.find(".MoveDown, .MoveBottom").removeClass('ms2side__hide'); |
|---|
| 138 | } |
|---|
| 139 | } |
|---|
| 140 | |
|---|
| 141 | if (selectSx.size() == 0 || |
|---|
| 142 | (o.maxSelected >= 0 && selectSx.size() >= o.maxSelected)) |
|---|
| 143 | div.find(".AddAll").addClass('ms2side__hide'); |
|---|
| 144 | else |
|---|
| 145 | div.find(".AddAll").removeClass('ms2side__hide'); |
|---|
| 146 | |
|---|
| 147 | if (selectDx.size() == 0) |
|---|
| 148 | div.find(".RemoveAll").addClass('ms2side__hide'); |
|---|
| 149 | else |
|---|
| 150 | div.find(".RemoveAll").removeClass('ms2side__hide'); |
|---|
| 151 | }); |
|---|
| 152 | |
|---|
| 153 | // DOUBLE CLICK ON LEFT SELECT OPTION |
|---|
| 154 | leftSel.dblclick(function () { |
|---|
| 155 | $(this).find("option:selected").each(function(i, selected){ |
|---|
| 156 | |
|---|
| 157 | if (o.maxSelected < 0 || rightSel.children().size() < o.maxSelected) { |
|---|
| 158 | $(this).remove().appendTo(rightSel); |
|---|
| 159 | el.find("[value=" + $(selected).val() + "]").attr("selected", true).remove().appendTo(el); |
|---|
| 160 | } |
|---|
| 161 | }); |
|---|
| 162 | $(this).trigger('change'); |
|---|
| 163 | }); |
|---|
| 164 | |
|---|
| 165 | // DOUBLE CLICK ON RIGHT SELECT OPTION |
|---|
| 166 | rightSel.dblclick(function () { |
|---|
| 167 | $(this).find("option:selected").each(function(i, selected){ |
|---|
| 168 | $(this).remove().appendTo(leftSel); |
|---|
| 169 | el.find("[value=" + $(selected).val() + "]").attr("selected", false).remove().appendTo(el); |
|---|
| 170 | }); |
|---|
| 171 | $(this).trigger('change'); |
|---|
| 172 | }); |
|---|
| 173 | |
|---|
| 174 | // CLICK ON OPTION |
|---|
| 175 | $(this).next().find('.ms2side__options').children().click(function () { |
|---|
| 176 | if (!$(this).hasClass("ms2side__hide")) { |
|---|
| 177 | if ($(this).hasClass("AddOne")) { |
|---|
| 178 | leftSel.find("option:selected").each(function(i, selected){ |
|---|
| 179 | $(this).remove().appendTo(rightSel); |
|---|
| 180 | el.find("[value=" + $(selected).val() + "]").attr("selected", true).remove().appendTo(el); |
|---|
| 181 | }); |
|---|
| 182 | } |
|---|
| 183 | else if ($(this).hasClass("AddAll")) { // ALL SELECTED |
|---|
| 184 | leftSel.children().appendTo(rightSel); |
|---|
| 185 | leftSel.children().remove(); |
|---|
| 186 | el.find('option').attr("selected", true); |
|---|
| 187 | // el.children().attr("selected", true); -- PROBLEM WITH OPTGROUP |
|---|
| 188 | } |
|---|
| 189 | else if ($(this).hasClass("RemoveOne")) { |
|---|
| 190 | rightSel.find("option:selected").each(function(i, selected){ |
|---|
| 191 | $(this).remove().appendTo(leftSel); |
|---|
| 192 | el.find("[value=" + $(selected).val() + "]").attr("selected", false).remove().appendTo(el); |
|---|
| 193 | }); |
|---|
| 194 | } |
|---|
| 195 | else if ($(this).hasClass("RemoveAll")) { // ALL REMOVED |
|---|
| 196 | rightSel.children().appendTo(leftSel); |
|---|
| 197 | rightSel.children().remove(); |
|---|
| 198 | el.find('option').attr("selected", false); |
|---|
| 199 | //el.children().attr("selected", false); -- PROBLEM WITH OPTGROUP |
|---|
| 200 | } |
|---|
| 201 | } |
|---|
| 202 | |
|---|
| 203 | leftSel.trigger('change'); |
|---|
| 204 | }); |
|---|
| 205 | |
|---|
| 206 | // CLICK ON UP - DOWN |
|---|
| 207 | $(this).next().find('.ms2side__updown').children().click(function () { |
|---|
| 208 | var selectedDx = rightSel.find("option:selected"); |
|---|
| 209 | var selectDx = rightSel.find("option"); |
|---|
| 210 | |
|---|
| 211 | if (!$(this).hasClass("ms2side__hide")) { |
|---|
| 212 | if ($(this).hasClass("SelSort")) { |
|---|
| 213 | // SORT SELECTED ELEMENT |
|---|
| 214 | selectDx.sort(function(a, b) { |
|---|
| 215 | var compA = $(a).text().toUpperCase(); |
|---|
| 216 | var compB = $(b).text().toUpperCase(); |
|---|
| 217 | return (compA < compB) ? -1 : (compA > compB) ? 1 : 0; |
|---|
| 218 | }) |
|---|
| 219 | // FIRST REMOVE FROM ORIGINAL SELECT |
|---|
| 220 | el.find("option:selected").remove(); |
|---|
| 221 | // AFTER ADD ON ORIGINAL AND RIGHT SELECT |
|---|
| 222 | selectDx.each(function() { |
|---|
| 223 | rightSel.append($(this).clone().attr("selected", true)); |
|---|
| 224 | el.append($(this).attr("selected", true)); |
|---|
| 225 | }); |
|---|
| 226 | } |
|---|
| 227 | else if ($(this).hasClass("MoveUp")) { |
|---|
| 228 | var prev = selectedDx.first().prev(); |
|---|
| 229 | var hPrev = el.find("[value=" + prev.val() + "]"); |
|---|
| 230 | |
|---|
| 231 | selectedDx.each(function() { |
|---|
| 232 | $(this).insertBefore(prev); |
|---|
| 233 | el.find("[value=" + $(this).val() + "]").insertBefore(hPrev); // HIDDEN SELECT |
|---|
| 234 | }); |
|---|
| 235 | } |
|---|
| 236 | else if ($(this).hasClass("MoveDown")) { |
|---|
| 237 | var next = selectedDx.last().next(); |
|---|
| 238 | var hNext = el.find("[value=" + next.val() + "]"); |
|---|
| 239 | |
|---|
| 240 | selectedDx.each(function() { |
|---|
| 241 | $(this).insertAfter(next); |
|---|
| 242 | el.find("[value=" + $(this).val() + "]").insertAfter(hNext); // HIDDEN SELECT |
|---|
| 243 | }); |
|---|
| 244 | } |
|---|
| 245 | else if ($(this).hasClass("MoveTop")) { |
|---|
| 246 | var first = selectDx.first(); |
|---|
| 247 | var hFirst = el.find("[value=" + first.val() + "]"); |
|---|
| 248 | |
|---|
| 249 | selectedDx.each(function() { |
|---|
| 250 | $(this).insertBefore(first); |
|---|
| 251 | el.find("[value=" + $(this).val() + "]").insertBefore(hFirst); // HIDDEN SELECT |
|---|
| 252 | }); |
|---|
| 253 | } |
|---|
| 254 | else if ($(this).hasClass("MoveBottom")) { |
|---|
| 255 | var last = selectDx.last(); |
|---|
| 256 | var hLast = el.find("[value=" + last.val() + "]"); |
|---|
| 257 | |
|---|
| 258 | selectedDx.each(function() { |
|---|
| 259 | last = $(this).insertAfter(last); // WITH last = SAME POSITION OF SELECTED OPTION AFTER MOVE |
|---|
| 260 | hLast = el.find("[value=" + $(this).val() + "]").insertAfter(hLast); // HIDDEN SELECT |
|---|
| 261 | }); |
|---|
| 262 | } |
|---|
| 263 | } |
|---|
| 264 | |
|---|
| 265 | leftSel.trigger('change'); |
|---|
| 266 | }); |
|---|
| 267 | |
|---|
| 268 | // HOVER ON OPTION |
|---|
| 269 | $(this).next().find('.ms2side__options, .ms2side__updown').children().hover( |
|---|
| 270 | function () { |
|---|
| 271 | $(this).addClass('ms2side_hover'); |
|---|
| 272 | }, |
|---|
| 273 | function () { |
|---|
| 274 | $(this).removeClass('ms2side_hover'); |
|---|
| 275 | } |
|---|
| 276 | ); |
|---|
| 277 | |
|---|
| 278 | // UPDATE BUTTON ON START |
|---|
| 279 | leftSel.trigger('change'); |
|---|
| 280 | // SHOW WHEN ALL READY |
|---|
| 281 | $(this).next().show(); |
|---|
| 282 | }); |
|---|
| 283 | }; |
|---|
| 284 | })(jQuery); |
|---|