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