From 0b41df7c35a076be6ec128d98f4b15e9021b5290 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur <eldy@destailleur.fr>
Date: Tue, 4 Nov 2014 00:33:50 +0100
Subject: [PATCH] Clean code to manage multiselect jquery: All code is
 centralized into function multipleselectarray (except loading of css). Code
 is prepared to choose which plugin to use (only a if is required to switch or
 add a new manager). Introduce working version with multiple-select jquery
 plugin. Removed deprecated old jquery plugin.

---
 COPYRIGHT                                     |  62 +--
 htdocs/core/class/html.form.class.php         |  86 ++--
 .../jquery/plugins/multiple-select/LICENSE    |  21 +
 .../jquery/plugins/multiple-select/README.md  |  96 ++++
 .../multiple-select/jquery.multiple.select.js | 466 +++++++++++++++++
 .../multiple-select/multiple-select.css       | 183 +++++++
 .../multiple-select.jquery.json               |  28 +
 .../multiple-select/multiple-select.png       | Bin 0 -> 3342 bytes
 .../plugins/multiselect/MIT-LICENSE.txt       |  20 -
 .../multiselect/css/ui.multiselect.css        |  31 --
 .../plugins/multiselect/js/ui.multiselect.js  | 480 ------------------
 htdocs/main.inc.php                           |  11 +-
 12 files changed, 879 insertions(+), 605 deletions(-)
 create mode 100644 htdocs/includes/jquery/plugins/multiple-select/LICENSE
 create mode 100644 htdocs/includes/jquery/plugins/multiple-select/README.md
 create mode 100644 htdocs/includes/jquery/plugins/multiple-select/jquery.multiple.select.js
 create mode 100644 htdocs/includes/jquery/plugins/multiple-select/multiple-select.css
 create mode 100644 htdocs/includes/jquery/plugins/multiple-select/multiple-select.jquery.json
 create mode 100644 htdocs/includes/jquery/plugins/multiple-select/multiple-select.png
 delete mode 100644 htdocs/includes/jquery/plugins/multiselect/MIT-LICENSE.txt
 delete mode 100644 htdocs/includes/jquery/plugins/multiselect/css/ui.multiselect.css
 delete mode 100644 htdocs/includes/jquery/plugins/multiselect/js/ui.multiselect.js

diff --git a/COPYRIGHT b/COPYRIGHT
index c0d8389369c..fd54e10f354 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -9,41 +9,41 @@ More information: http://www.gnu.org/licenses/gpl-3.0.txt
 
 Dolibarr uses some external libraries released under different licenses. This is compatibility summary:
 
-Component             Version       License                     GPL Compatible  Usage
+Component              Version       License                     GPL Compatible  Usage
 -------------------------------------------------------------------------------------
 PHP libraries:
-AdoDb-Date            0.32          Modified BSD License        Yes             Date convertion (not into rpm package)
-CKEditor              4.3.3         LGPL-2.1+                   Yes             Editor WYSIWYG
-FPDI                  1.4.2         Apache Software License 2.0 Yes             PDF templates management
-FPDF_TPL              1.2           Apache Software License 2.0 Yes             PDF templates management
-GeoIP                 1.4           LGPL-2.1+                   Yes             Sample code to make geoip convert (not into deb package)
-NuSoap                0.9.5         LGPL 2.1+                   Yes             Library to develop SOAP Web services (not into rpm and deb package)
-odtPHP                1.0.1         GPL-2+  b                   Yes             Library to build/edit ODT files
-PHPExcel              1.7.8         LGPL-2.1+                   Yes             Read/Write XLS files, read ODS files
-PHPPrintIPP           1.3           GPL-2+                      Yes             Library to send print IPP requests
-TCPDF                 6.0.093       LGPL-3+                     Yes             PDF generation
+AdoDb-Date             0.32          Modified BSD License        Yes             Date convertion (not into rpm package)
+CKEditor               4.3.3         LGPL-2.1+                   Yes             Editor WYSIWYG
+FPDI                   1.4.2         Apache Software License 2.0 Yes             PDF templates management
+FPDF_TPL               1.2           Apache Software License 2.0 Yes             PDF templates management
+GeoIP                  1.4           LGPL-2.1+                   Yes             Sample code to make geoip convert (not into deb package)
+NuSoap                 0.9.5         LGPL 2.1+                   Yes             Library to develop SOAP Web services (not into rpm and deb package)
+odtPHP                 1.0.1         GPL-2+  b                   Yes             Library to build/edit ODT files
+PHPExcel               1.7.8         LGPL-2.1+                   Yes             Read/Write XLS files, read ODS files
+PHPPrintIPP            1.3           GPL-2+                      Yes             Library to send print IPP requests
+TCPDF                  6.0.093       LGPL-3+                     Yes             PDF generation
 
 JS libraries:
-jQuery                1.8.2         MIT License                 Yes             JS library
-jQuery UI             1.9.1         GPL and MIT License         Yes             JS library plugin UI
-jQuery UI Multiselect ?             GPL and MIT License         Yes             JS library plugin for sexier multiselect
-jQuery blockUI        2.43          GPL and MIT License         Yes             JS library plugin blockUI (to use ajax popups)
-jQuery Colorpicker    1.1           MIT License                 Yes             JS library for color picker for a defined list of colors
-jQuery DataTables     1.9.4         BSD                         Yes             JS library for tables output
-jQuery FileUpload     5.0.3         GPL and MIT License         Yes             JS library to upload files
-jQuery Flot           0.7           MIT License                 Yes             JS library to build graph
-jQuery JCrop          0.9.8         GPL and MIT License         Yes             JS library plugin Crop (to crop images)
-jQuery Jeditable      1.7.1         GPL and MIT License         Yes             JS library plugin jeditable (to edit in place)
-jQuery jNotify        1.1.00        Apache Software License 2.0 Yes             JS library plugin jNotify (to use ajax popups)
-jQuery jPicker        1.1.6         GPL and MIT License         Yes             JS library for color picker with not defined list of colors
-jQuery jqueryFileTree 1.0.1         GPL and MIT License         Yes             JS library for color picker with not defined list of colors
-jQuery jquerytreeview 1.4.1         MIT License                 Yes             JS library for color picker with not defined list of colors
-jQuery Layout         1.3.0rc30.74  GPL and MIT License         Yes             JS library plugin Layout (RC-29.15)
-jQuery Mobile         1.3.0         GPL and MIT License         Yes             JS library for smartphone (not used)
-jQuery TableDnD       0.6           GPL and MIT License         Yes             JS library plugin TableDnD (to reorder table rows)
-jQuery Timepicker     1.1.0         GPL and MIT License         Yes             JS library Timepicker addon for Datepicker
-jQuery Tiptip         1.3           GPL and MIT License         Yes             JS library for tooltips
-jsGantt               1.2           BSD License                 Yes             JS library (to build Gantt reports)
+jQuery                 1.8.2         MIT License                 Yes             JS library
+jQuery UI              1.9.1         GPL and MIT License         Yes             JS library plugin UI
+jQuery multiple-select 1.1.0        MIT License                 Yes             JS library plugin for sexier multiselect
+jQuery blockUI         2.43          GPL and MIT License         Yes             JS library plugin blockUI (to use ajax popups)
+jQuery Colorpicker     1.1           MIT License                 Yes             JS library for color picker for a defined list of colors
+jQuery DataTables      1.9.4         BSD                         Yes             JS library for tables output
+jQuery FileUpload      5.0.3         GPL and MIT License         Yes             JS library to upload files
+jQuery Flot            0.7           MIT License                 Yes             JS library to build graph
+jQuery JCrop           0.9.8         GPL and MIT License         Yes             JS library plugin Crop (to crop images)
+jQuery Jeditable       1.7.1         GPL and MIT License         Yes             JS library plugin jeditable (to edit in place)
+jQuery jNotify         1.1.00        Apache Software License 2.0 Yes             JS library plugin jNotify (to use ajax popups)
+jQuery jPicker         1.1.6         GPL and MIT License         Yes             JS library for color picker with not defined list of colors
+jQuery jqueryFileTree  1.0.1         GPL and MIT License         Yes             JS library for color picker with not defined list of colors
+jQuery jquerytreeview  1.4.1         MIT License                 Yes             JS library for color picker with not defined list of colors
+jQuery Layout          1.3.0rc30.74  GPL and MIT License         Yes             JS library plugin Layout (RC-29.15)
+jQuery Mobile          1.3.0         GPL and MIT License         Yes             JS library for smartphone (not used)
+jQuery TableDnD        0.6           GPL and MIT License         Yes             JS library plugin TableDnD (to reorder table rows)
+jQuery Timepicker      1.1.0         GPL and MIT License         Yes             JS library Timepicker addon for Datepicker
+jQuery Tiptip          1.3           GPL and MIT License         Yes             JS library for tooltips
+jsGantt                1.2           BSD License                 Yes             JS library (to build Gantt reports)
 
 For licenses compatibility informations:
 http://www.fsf.org/licensing/licenses/index_html
diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php
index eb7b3d8af4f..bade0344680 100644
--- a/htdocs/core/class/html.form.class.php
+++ b/htdocs/core/class/html.form.class.php
@@ -4032,9 +4032,10 @@ class Form
      *	@param  int		$translate		Translate and encode value
      * 	@param	int		$maxlen			Length maximum for labels
      * 	@param	int		$disabled		Html select box is disabled
-     *  @param	int		$sort			'ASC' or 'DESC' =Sort on label, '' or 'NONE'=Do not sort
+     *  @param	int		$sort			'ASC' or 'DESC' = Sort on label, '' or 'NONE' = Do not sort
      *  @param	string	$morecss		Add more class to css styles
      * 	@return	string					HTML select string.
+     *  @see multiselectarray
      */
     static function selectarray($htmlname, $array, $id='', $show_empty=0, $key_in_label=0, $value_as_key=0, $moreparam='', $translate=0, $maxlen=0, $disabled=0, $sort='', $morecss='')
     {
@@ -4092,54 +4093,65 @@ class Form
      *
      *	@param	string	$htmlname		Name of select
      *	@param	array	$array			Array with key+value
-     *	@param	array	$selected		Preselected keys
+     *	@param	array	$selected		Array with key+value preselected
      *	@param	int		$key_in_label   1 pour afficher la key dans la valeur "[key] value"
      *	@param	int		$value_as_key   1 to use value as key
      *	@param  string	$option         Valeur de l'option en fonction du type choisi
      *	@param  int		$translate		Translate and encode value
+     *  @param	int		$width			Force width of select box. May be used only when using jquery couch.
      *	@return	string					HTML multiselect string
+     *  @see selectarray
      */
-    function multiselectarray($htmlname, $array, $selected=array(), $key_in_label=0, $value_as_key=0, $option='', $translate=0)
+    static function multiselectarray($htmlname, $array, $selected=array(), $key_in_label=0, $value_as_key=0, $option='', $translate=0, $width=0)
     {
     	global $conf, $langs;
 
-    	$out = '<select id="'.$htmlname.'" class="multiselect" multiple="multiple" name="'.$htmlname.'[]"'.$option.'>'."\n";
+    	// Add code for jquery to use multiselect
+    	// Note: Plugin "multiselect" is no more provided by Dolibarr. You must include it and load it into your module to use it.
+    	if ((! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) && ($conf->global->MAIN_USE_JQUERY_MULTISELECT == 'multiselect'))
+    		|| (defined('REQUIRE_JQUERY_MULTISELECT') && constant('REQUIRE_JQUERY_MULTISELECT')))
+    	{
+	    	print '<!-- JS CODE FOR multiselect -->
+				<script type="text/javascript">
+				$(document).ready(function () {
+					$.extend($.ui.multiselect.locale, {
+						addAll:\''.$langs->transnoentities("AddAll").'\',
+						removeAll:\''.$langs->transnoentities("RemoveAll").'\',
+						itemsCount:\''.$langs->transnoentities("ItemsCount").'\'
+					});
+					$(function(){
+						$("#'.$htmlname.'").multiselect({
+							searchable: false,
+							width: '.($width?$width:300).',
+							height: 120
+						});
+					});
+				});
+				</script>';
+    	}
+
+        // Add code for jquery to use multiple-select
+    	// Note: Plugin "multiselect" is no more provided by Dolibarr. You must include it and load it into your module to use it.
+    	if ((! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) && ($conf->global->MAIN_USE_JQUERY_MULTISELECT == 'multiple-select'))
+    		|| (defined('REQUIRE_JQUERY_MULTISELECT') && constant('REQUIRE_JQUERY_MULTISELECT')))
+    	{
+	    	print '<!-- JS CODE FOR multiple-select -->
+			<script src="'.DOL_URL_ROOT.'/includes/jquery/plugins/multiple-select/jquery.multiple.select.js"></script>
+	    	<script type="text/javascript">
+				$(document).ready(function () {
+        			$(\'#'.$htmlname.'\').multipleSelect();
+        		});
+			</script>';
+    	}
+
+    	// Try also magic suggest
+
+    	$out = '<select id="'.$htmlname.'" class="multiselect" multiple="multiple" name="'.$htmlname.'[]"'.$option.($width?' style="width: '.$width.'px"':'').'>'."\n";
     	if (is_array($array) && ! empty($array))
     	{
     		if ($value_as_key) $array=array_combine($array, $array);
 
-    		if (! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) && is_array($selected) && ! empty($selected))
-    		{
-    			foreach ($selected as $selected_value)
-    			{
-    				foreach($array as $key => $value)
-    				{
-    					if ($selected_value == $key)
-    					{
-    						$value=$array[$selected_value];
-    						$out.= '<option value="'.$key.'" selected="selected">';
-    						$newval = ($translate ? $langs->trans(ucfirst($value)) : $value);
-    						$newval = ($key_in_label ? $key.' - '.$newval : $newval);
-    						$out.= dol_htmlentitiesbr($newval);
-    						$out.= '</option>'."\n";
-    						unset($array[$key]);
-    					}
-    				}
-    			}
-
-    			if (! empty($array))
-    			{
-    				foreach ($array as $key => $value)
-    				{
-    					$out.= '<option value="'.$key.'">';
-    					$newval = ($translate ? $langs->trans(ucfirst($value)) : $value);
-    					$newval = ($key_in_label ? $key.' - '.$newval : $newval);
-    					$out.= dol_htmlentitiesbr($newval);
-    					$out.= '</option>'."\n";
-    				}
-    			}
-    		}
-    		else
+    		if (! empty($array))
     		{
     			foreach ($array as $key => $value)
     			{
@@ -4150,7 +4162,7 @@ class Form
     				}
     				$out.= '>';
 
-    				$newval = ($translate ? $langs->trans(ucfirst($value)) : $value);
+    				$newval = ($translate ? $langs->trans($value) : $value);
     				$newval = ($key_in_label ? $key.' - '.$newval : $newval);
     				$out.= dol_htmlentitiesbr($newval);
     				$out.= '</option>'."\n";
diff --git a/htdocs/includes/jquery/plugins/multiple-select/LICENSE b/htdocs/includes/jquery/plugins/multiple-select/LICENSE
new file mode 100644
index 00000000000..c3ebd2b5248
--- /dev/null
+++ b/htdocs/includes/jquery/plugins/multiple-select/LICENSE
@@ -0,0 +1,21 @@
+(The MIT License)
+
+Copyright (c) 2012-2014 Zhixin Wen <wenzhixin2010@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/htdocs/includes/jquery/plugins/multiple-select/README.md b/htdocs/includes/jquery/plugins/multiple-select/README.md
new file mode 100644
index 00000000000..81b82ba74c0
--- /dev/null
+++ b/htdocs/includes/jquery/plugins/multiple-select/README.md
@@ -0,0 +1,96 @@
+# Multiple Select
+
+Multiple select is a jQuery plugin to select multiple elements with checkboxes :).
+
+To get started checkout examples and documentation at http://wenzhixin.net.cn/p/multiple-select
+
+## Contributors
+
+Multiple select is due to the excellent work of the following contributors:
+
+<table>
+<tbody>
+<tr><th align="left">文翼</th><td><a href="https://github.com/wenzhixin">GitHub/wenzhixin</a></td></tr>
+<tr><th align="left">Gaurav Jassal</th><td><a href="https://github.com/creativeaura">GitHub/creativeaura</a></td><</tr>
+<tr><th align="left">guli</th><td><a href="https://github.com/guli">GitHub/guli</a></td></tr>
+<tr><th align="left">jwheadon</th><td><a href="https://github.com/jwheadon">GitHub/jwheadon</a></td></tr>
+<tr><th align="left">yx</th><td><a href="https://github.com/qqfish">GitHub/qqfish</a></td></tr>
+<tr><th align="left">Tobias Macey</th><td><a href="https://github.com/blarghmatey">GitHub/blarghmatey</a></td></tr>
+<tr><th align="left">Jona Goldman</th><td><a href="https://github.com/jonagoldman">GitHub/jonagoldman</a></td></tr>
+<tr><th align="left">Alex Jeffrey</th><td><a href="https://github.com/ajeffrey">GitHub/ajeffrey</a></td></tr>
+</tbody>
+</table>
+
+## Changelog
+
+### 1.1.0
+
+* Fix #63: Add ```keepOpen``` option.
+* Fix #62: Fix ```isOpen``` and ```filter``` options are both true bug.
+* Fix #57: Fire onCheckAll event when literally select.
+* Add data attributes for support.
+* Fix #55: Add ```name``` option.
+
+### 1.0.9
+
+* Fix #42: Add ```styler``` option to custom item style.
+* Fix firefox click bug.
+* Add ```allSelected```, ```minumimCountSelected``` and ```countSelected``` options.
+* Fix #35: Add ```onFocus``` and ```onBlur``` events.
+* Fix #25: Add ```focus``` and ```blur``` methods.
+* Fix #31: Trigger the onCheckAll & onUncheckAll events when use filter to select all.
+
+### 1.0.8
+
+* Update the license to The MIT License.
+* Fix #47: Add ```No matches found``` message when there are no results found.
+* Fix #43: Add ```position``` option.
+
+### 1.0.7
+
+* Fix #44: The filters not working bugs.
+
+### 1.0.6
+
+* Fix #21: Add ```single``` option.
+* Add ```override``` option.
+* Add ```container``` option.
+* Fix #29: Update the optgroups select text.
+* Fix #30: Image is not shown in Firefox 25.0.1.
+* Fix #22: fix group filter problem.
+
+### 1.0.5
+
+* Update the button text witdh.
+* Add keyboard support.
+
+### 1.0.4
+
+* Fix #12: Add ```width``` option.
+* Fix #11: Add callback events.
+* Add ```maxHeight``` option.
+
+### 1.0.3
+
+* Fix #4: Add ```filter``` option.
+* Support mobile devices.
+* Fix #6: Add ```refresh``` method.
+
+### 1.0.2
+
+* Fix #7: Add ```selected``` and ```disabled``` options.
+* Fix #5: Add ```checkAll``` and ```uncheckAll``` methods.
+
+### 1.0.1
+
+* Fix #3: Add optgroups support.
+* Add ```placeholder``` option.
+* Fix #2: use prop method instead of attr.
+
+### 1.0.0
+
+* Initial release
+
+## LICENSE
+
+[The MIT License](https://github.com/wenzhixin/multiple-select/blob/master/LICENSE)
\ No newline at end of file
diff --git a/htdocs/includes/jquery/plugins/multiple-select/jquery.multiple.select.js b/htdocs/includes/jquery/plugins/multiple-select/jquery.multiple.select.js
new file mode 100644
index 00000000000..32e6635bbaa
--- /dev/null
+++ b/htdocs/includes/jquery/plugins/multiple-select/jquery.multiple.select.js
@@ -0,0 +1,466 @@
+/**
+ * @author zhixin wen <wenzhixin2010@gmail.com>
+ * @version 1.1.0
+ * 
+ * http://wenzhixin.net.cn/p/multiple-select/
+ */
+
+(function($) {
+
+    'use strict';
+
+    function MultipleSelect($el, options) {
+        var that = this,
+            name = $el.attr('name') || options.name || '',
+            elWidth = $el.width();
+
+        this.$el = $el.hide();
+        this.options = options;
+
+        this.$parent = $('<div class="ms-parent"></div>');
+        this.$choice = $('<button type="button" class="ms-choice"><span class="placeholder">' +
+            options.placeholder + '</span><div></div></button>');
+        this.$drop = $('<div class="ms-drop ' + options.position + '"></div>');
+        this.$el.after(this.$parent);
+        this.$parent.append(this.$choice);
+        this.$parent.append(this.$drop);
+
+        if (this.$el.prop('disabled')) {
+            this.$choice.addClass('disabled');
+        }
+        this.$choice.css('width', elWidth + 'px');
+        this.$drop.css({
+            width: (options.width || elWidth) + 'px'
+        });
+
+        if (!this.options.keepOpen) {
+            $('body').click(function(e) {
+                if ($(e.target)[0] === that.$choice[0] ||
+                    $(e.target).parents('.ms-choice')[0] === that.$choice[0]) {
+                    return;
+                }
+                if (($(e.target)[0] === that.$drop[0] ||
+                    $(e.target).parents('.ms-drop')[0] !== that.$drop[0]) &&
+                    that.options.isOpen) {
+                    that.close();
+                }
+            });
+        }
+
+        this.selectAllName = 'name="selectAll' + name + '"';
+        this.selectGroupName = 'name="selectGroup' + name + '"';
+        this.selectItemName = 'name="selectItem' + name + '"';
+    }
+
+    MultipleSelect.prototype = {
+        constructor : MultipleSelect,
+
+        init: function() {
+            var that = this,
+                html = [];
+            if (this.options.filter) {
+                html.push(
+                    '<div class="ms-search">',
+                        '<input type="text" autocomplete="off" autocorrect="off" autocapitilize="off" spellcheck="false">',
+                    '</div>'
+                );
+            }
+            html.push('<ul>');
+            if (this.options.selectAll && !this.options.single) {
+                html.push(
+                    '<li>',
+                        '<label>',
+                            '<input type="checkbox" ' + this.selectAllName + ' /> ',
+                            '[' + this.options.selectAllText + ']',
+                        '</label>',
+                    '</li>'
+                );
+            }
+            $.each(this.$el.children(), function(i, elm) {
+                html.push(that.optionToHtml(i, elm));
+            });
+            html.push('<li class="ms-no-results">No matches found</li>');
+            html.push('</ul>');
+            this.$drop.html(html.join(''));
+            this.$drop.find('ul').css('max-height', this.options.maxHeight + 'px');
+            this.$drop.find('.multiple').css('width', this.options.multipleWidth + 'px');
+
+            this.$searchInput = this.$drop.find('.ms-search input');
+            this.$selectAll = this.$drop.find('input[' + this.selectAllName + ']');
+            this.$selectGroups = this.$drop.find('input[' + this.selectGroupName + ']');
+            this.$selectItems = this.$drop.find('input[' + this.selectItemName + ']:enabled');
+            this.$disableItems = this.$drop.find('input[' + this.selectItemName + ']:disabled');
+            this.$noResults = this.$drop.find('.ms-no-results');
+            this.events();
+            this.update();
+
+            if (this.options.isOpen) {
+                this.open();
+            }
+        },
+
+        optionToHtml: function(i, elm, group, groupDisabled) {
+            var that = this,
+                $elm = $(elm),
+                html = [],
+                multiple = this.options.multiple,
+                disabled,
+                type = this.options.single ? 'radio' : 'checkbox';
+
+            if ($elm.is('option')) {
+                var value = $elm.val(),
+                    text = $elm.text(),
+                    selected = $elm.prop('selected'),
+                    style = this.options.styler(value) ? ' style="' + this.options.styler(value) + '"' : '';
+
+                disabled = groupDisabled || $elm.prop('disabled');
+                html.push(
+                    '<li' + (multiple ? ' class="multiple"' : '') + style + '>',
+                        '<label' + (disabled ? ' class="disabled"' : '') + '>',
+                            '<input type="' + type + '" ' + this.selectItemName + ' value="' + value + '"' +
+                                (selected ? ' checked="checked"' : '') +
+                                (disabled ? ' disabled="disabled"' : '') +
+                                (group ? ' data-group="' + group + '"' : '') +
+                                '/> ',
+                            text,
+                        '</label>',
+                    '</li>'
+                );
+            } else if (!group && $elm.is('optgroup')) {
+                var _group = 'group_' + i,
+                    label = $elm.attr('label');
+
+                disabled = $elm.prop('disabled');
+                html.push(
+                    '<li class="group">',
+                        '<label class="optgroup' + (disabled ? ' disabled' : '') + '" data-group="' + _group + '">',
+                            '<input type="checkbox" ' + this.selectGroupName +
+                                (disabled ? ' disabled="disabled"' : '') + ' /> ',
+                            label,
+                        '</label>',
+                    '</li>');
+                $.each($elm.children(), function(i, elm) {
+                    html.push(that.optionToHtml(i, elm, _group, disabled));
+                });
+            }
+            return html.join('');
+        },
+
+        events: function() {
+            var that = this;
+            this.$choice.off('click').on('click', function(e) {
+                e.preventDefault();
+                that[that.options.isOpen ? 'close' : 'open']();
+            })
+                .off('focus').on('focus', this.options.onFocus)
+                .off('blur').on('blur', this.options.onBlur);
+
+            this.$parent.off('keydown').on('keydown', function(e) {
+                switch (e.which) {
+                    case 27: // esc key
+                        that.close();
+                        that.$choice.focus();
+                        break;
+                }
+            });
+            this.$searchInput.off('keyup').on('keyup', function() {
+                that.filter();
+            });
+            this.$selectAll.off('click').on('click', function() {
+                var checked = $(this).prop('checked'),
+                    $items = that.$selectItems.filter(':visible');
+                if ($items.length === that.$selectItems.length) {
+                    that[checked ? 'checkAll' : 'uncheckAll']();
+                } else { // when the filter option is true
+                    that.$selectGroups.prop('checked', checked);
+                    $items.prop('checked', checked);
+                    that.options[checked ? 'onCheckAll' : 'onUncheckAll']();
+                    that.update();
+                }
+            });
+            this.$selectGroups.off('click').on('click', function() {
+                var group = $(this).parent().attr('data-group'),
+                    $items = that.$selectItems.filter(':visible'),
+                    $children = $items.filter('[data-group="' + group + '"]'),
+                    checked = $children.length !== $children.filter(':checked').length;
+                $children.prop('checked', checked);
+                that.updateSelectAll();
+                that.update();
+                that.options.onOptgroupClick({
+                    label: $(this).parent().text(),
+                    checked: checked,
+                    children: $children.get()
+                });
+            });
+            this.$selectItems.off('click').on('click', function() {
+                that.updateSelectAll();
+                that.update();
+                that.updateOptGroupSelect();
+                that.options.onClick({
+                    label: $(this).parent().text(),
+                    value: $(this).val(),
+                    checked: $(this).prop('checked')
+                });
+            });
+        },
+
+        open: function() {
+            if (this.$choice.hasClass('disabled')) {
+                return;
+            }
+            this.options.isOpen = true;
+            this.$choice.find('>div').addClass('open');
+            this.$drop.show();
+            if (this.options.container) {
+                var offset = this.$drop.offset();
+                this.$drop.appendTo($(this.options.container));
+                this.$drop.offset({ top: offset.top, left: offset.left });
+            }
+            if (this.options.filter) {
+                this.$searchInput.val('');
+                this.filter();
+            }
+            this.options.onOpen();
+        },
+
+        close: function() {
+            this.options.isOpen = false;
+            this.$choice.find('>div').removeClass('open');
+            this.$drop.hide();
+            if (this.options.container) {
+                this.$parent.append(this.$drop);
+                this.$drop.css({
+                    'top': 'auto',
+                    'left': 'auto'
+                })
+            }
+            this.options.onClose();
+        },
+
+        update: function() {
+            var selects = this.getSelects('text'),
+                $span = this.$choice.find('>span');
+            if (selects.length === this.$selectItems.length + this.$disableItems.length && this.options.allSelected) {
+                $span.removeClass('placeholder').html(this.options.allSelected);
+            } else if (selects.length > this.options.minumimCountSelected && this.options.countSelected) {
+                $span.removeClass('placeholder').html(this.options.countSelected
+                    .replace('#', selects.length)
+                    .replace('%', this.$selectItems.length + this.$disableItems.length));
+            } else if (selects.length) {
+                $span.removeClass('placeholder').html(selects.join(', '));
+            } else {
+                $span.addClass('placeholder').html(this.options.placeholder);
+            }
+            // set selects to select
+            this.$el.val(this.getSelects());
+        },
+
+        updateSelectAll: function() {
+            var $items = this.$selectItems.filter(':visible');
+            this.$selectAll.prop('checked', $items.length &&
+                $items.length === $items.filter(':checked').length);
+            if (this.$selectAll.prop('checked')) {
+                this.options.onCheckAll();
+            }
+        },
+
+        updateOptGroupSelect: function() {
+            var $items = this.$selectItems.filter(':visible');
+            $.each(this.$selectGroups, function(i, val) {
+                var group = $(val).parent().attr('data-group'),
+                    $children = $items.filter('[data-group="' + group + '"]');
+                $(val).prop('checked', $children.length &&
+                    $children.length === $children.filter(':checked').length);
+            });
+        },
+
+        //value or text, default: 'value'
+        getSelects: function(type) {
+            var that = this,
+                texts = [],
+                values = [];
+            this.$drop.find('input[' + this.selectItemName + ']:checked').each(function() {
+                texts.push($(this).parent().text());
+                values.push($(this).val());
+            });
+
+            if (type === 'text' && this.$selectGroups.length) {
+                texts = [];
+                this.$selectGroups.each(function() {
+                    var html = [],
+                        text = $.trim($(this).parent().text()),
+                        group = $(this).parent().data('group'),
+                        $children = that.$drop.find('[' + that.selectItemName + '][data-group="' + group + '"]'),
+                        $selected = $children.filter(':checked');
+
+                    if ($selected.length === 0) {
+                        return;
+                    }
+
+                    html.push('[');
+                    html.push(text);
+                    if ($children.length > $selected.length) {
+                        var list = [];
+                        $selected.each(function() {
+                            list.push($(this).parent().text());
+                        });
+                        html.push(': ' + list.join(', '));
+                    }
+                    html.push(']');
+                    texts.push(html.join(''));
+                });
+            }
+            return type === 'text' ? texts : values;
+        },
+
+        setSelects: function(values) {
+            var that = this;
+            this.$selectItems.prop('checked', false);
+            $.each(values, function(i, value) {
+                that.$selectItems.filter('[value="' + value + '"]').prop('checked', true);
+            });
+            this.$selectAll.prop('checked', this.$selectItems.length ===
+                this.$selectItems.filter(':checked').length);
+            this.update();
+        },
+
+        enable: function() {
+            this.$choice.removeClass('disabled');
+        },
+
+        disable: function() {
+            this.$choice.addClass('disabled');
+        },
+
+        checkAll: function() {
+            this.$selectItems.prop('checked', true);
+            this.$selectGroups.prop('checked', true);
+            this.$selectAll.prop('checked', true);
+            this.update();
+            this.options.onCheckAll();
+        },
+
+        uncheckAll: function() {
+            this.$selectItems.prop('checked', false);
+            this.$selectGroups.prop('checked', false);
+            this.$selectAll.prop('checked', false);
+            this.update();
+            this.options.onUncheckAll();
+        },
+
+        focus: function() {
+            this.$choice.focus();
+            this.options.onFocus();
+        },
+
+        blur: function() {
+            this.$choice.blur();
+            this.options.onBlur();
+        },
+
+        refresh: function() {
+            this.init();
+        },
+
+        filter: function() {
+            var that = this,
+                text = $.trim(this.$searchInput.val()).toLowerCase();
+            if (text.length === 0) {
+                this.$selectItems.parent().show();
+                this.$disableItems.parent().show();
+                this.$selectGroups.parent().show();
+            } else {
+                this.$selectItems.each(function() {
+                    var $parent = $(this).parent();
+                    $parent[$parent.text().toLowerCase().indexOf(text) < 0 ? 'hide' : 'show']();
+                });
+                this.$disableItems.parent().hide();
+                this.$selectGroups.each(function() {
+                    var $parent = $(this).parent();
+                    var group = $parent.attr('data-group'),
+                        $items = that.$selectItems.filter(':visible');
+                    $parent[$items.filter('[data-group="' + group + '"]').length === 0 ? 'hide' : 'show']();
+                });
+
+                //Check if no matches found
+                if (this.$selectItems.filter(':visible').length) {
+                    this.$selectAll.parent().show();
+                    this.$noResults.hide();
+                } else {
+                    this.$selectAll.parent().hide();
+                    this.$noResults.show();
+                }
+            }
+            this.updateOptGroupSelect();
+            this.updateSelectAll();
+        }
+    };
+
+    $.fn.multipleSelect = function() {
+        var option = arguments[0],
+            args = arguments,
+
+            value,
+            allowedMethods = [
+                'getSelects', 'setSelects',
+                'enable', 'disable',
+                'checkAll', 'uncheckAll',
+                'focus', 'blur',
+                'refresh'
+            ];
+
+        this.each(function() {
+            var $this = $(this),
+                data = $this.data('multipleSelect'),
+                options = $.extend({}, $.fn.multipleSelect.defaults,
+                    $this.data(), typeof option === 'object' && option);
+
+            if (!data) {
+                data = new MultipleSelect($this, options);
+                $this.data('multipleSelect', data);
+            }
+
+            if (typeof option === 'string') {
+                if ($.inArray(option, allowedMethods) < 0) {
+                    throw "Unknown method: " + option;
+                }
+                value = data[option](args[1]);
+            } else {
+                data.init();
+            }
+        });
+
+        return value ? value : this;
+    };
+
+    $.fn.multipleSelect.defaults = {
+        name: '',
+        isOpen: false,
+        placeholder: '',
+        selectAll: true,
+        selectAllText: 'Select all',
+        allSelected: 'All selected',
+        minumimCountSelected: 3,
+        countSelected: '# of % selected',
+        multiple: false,
+        multipleWidth: 80,
+        single: false,
+        filter: false,
+        width: undefined,
+        maxHeight: 250,
+        container: null,
+        position: 'bottom',
+        keepOpen: false,
+
+        styler: function() {return false;},
+
+        onOpen: function() {return false;},
+        onClose: function() {return false;},
+        onCheckAll: function() {return false;},
+        onUncheckAll: function() {return false;},
+        onFocus: function() {return false;},
+        onBlur: function() {return false;},
+        onOptgroupClick: function() {return false;},
+        onClick: function() {return false;}
+    };
+})(jQuery);
diff --git a/htdocs/includes/jquery/plugins/multiple-select/multiple-select.css b/htdocs/includes/jquery/plugins/multiple-select/multiple-select.css
new file mode 100644
index 00000000000..d824e0c7a2b
--- /dev/null
+++ b/htdocs/includes/jquery/plugins/multiple-select/multiple-select.css
@@ -0,0 +1,183 @@
+/**
+ * @author zhixin wen <wenzhixin2010@gmail.com>
+ */
+
+.ms-parent {
+    display: inline-block;
+    position: relative;
+    vertical-align: middle;
+}
+
+.ms-choice {
+    display: block;
+    height: 26px;
+    padding: 0;
+    overflow: hidden;
+    cursor: pointer;
+    border: 1px solid #aaa;
+    text-align: left;
+    white-space: nowrap;
+    line-height: 26px;
+    color: #444;
+    text-decoration: none;
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+    border-radius: 4px;
+    background-color: #fff;
+}
+
+.ms-choice.disabled {
+    background-color: #f4f4f4;
+    background-image: none;
+    border: 1px solid #ddd;
+    cursor: default;
+}
+
+.ms-choice > span {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 20px;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    display: block;
+    padding-left: 8px;
+}
+
+.ms-choice > span.placeholder {
+    color: #999;
+}
+
+.ms-choice > div {
+    position: absolute;
+    top: 0;
+    right: 0;
+    width: 20px;
+    height: 25px;
+    background: url('multiple-select.png') right top no-repeat;
+}
+
+.ms-choice > div.open {
+    background: url('multiple-select.png') left top no-repeat;
+}
+
+.ms-drop {
+    overflow: hidden;
+    display: none;
+    margin-top: -1px;
+    padding: 0;
+    position: absolute;
+    z-index: 1000;
+    background: #fff;
+    color: #000;
+    border: 1px solid #aaa;
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+    border-radius: 4px;
+}
+
+.ms-drop.bottom {
+    top: 100%;
+    -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
+    -moz-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
+    box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
+}
+
+.ms-drop.top {
+    bottom: 100%;
+    -webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
+    -moz-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
+    box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
+}
+
+.ms-search {
+    display: inline-block;
+    margin: 0;
+    min-height: 26px;
+    padding: 4px;
+    position: relative;
+    white-space: nowrap;
+    width: 100%;
+    z-index: 10000;
+}
+
+.ms-search input {
+    width: 100%;
+    height: auto !important;
+    min-height: 24px;
+    padding: 0 20px 0 5px;
+    margin: 0;
+    outline: 0;
+    font-family: sans-serif;
+    font-size: 1em;
+    border: 1px solid #aaa;
+    -webkit-border-radius: 0;
+    -moz-border-radius: 0;
+    border-radius: 0;
+    -webkit-box-shadow: none;
+    -moz-box-shadow: none;
+    box-shadow: none;
+    background: #fff url('multiple-select.png') no-repeat 100% -22px;
+    background: url('multiple-select.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee));
+    background: url('multiple-select.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%);
+    background: url('multiple-select.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%);
+    background: url('multiple-select.png') no-repeat 100% -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%);
+    background: url('multiple-select.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%);
+    background: url('multiple-select.png') no-repeat 100% -22px, linear-gradient(top, #ffffff 85%, #eeeeee 99%);
+}
+
+.ms-search, .ms-search input {
+    -webkit-box-sizing: border-box;
+    -khtml-box-sizing: border-box;
+    -moz-box-sizing: border-box;
+    -ms-box-sizing: border-box;
+    box-sizing: border-box;
+}
+
+.ms-drop ul {
+    overflow: auto;
+    margin: 0;
+    padding: 5px 8px;
+}
+
+.ms-drop ul > li {
+    list-style: none;
+    display: list-item;
+    background-image: none;
+    position: static;
+}
+
+.ms-drop ul > li .disabled {
+    opacity: .35;
+    filter: Alpha(Opacity=35);
+}
+
+.ms-drop ul > li.multiple {
+    display: block;
+    float: left;
+}
+
+.ms-drop ul > li.group {
+    clear: both;
+}
+
+.ms-drop ul > li.multiple label {
+    width: 100%;
+    display: block;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+
+.ms-drop ul > li label.optgroup {
+    font-weight: bold;
+}
+
+.ms-drop input[type="checkbox"] {
+    vertical-align: middle;
+}
+
+.ms-drop .ms-no-results {
+    display: none;
+}
\ No newline at end of file
diff --git a/htdocs/includes/jquery/plugins/multiple-select/multiple-select.jquery.json b/htdocs/includes/jquery/plugins/multiple-select/multiple-select.jquery.json
new file mode 100644
index 00000000000..dd636fda7e0
--- /dev/null
+++ b/htdocs/includes/jquery/plugins/multiple-select/multiple-select.jquery.json
@@ -0,0 +1,28 @@
+{
+    "name": "multiple-select",
+    "version": "1.1.0",
+    "title": "Multiple Select",
+    "description": "Multiple select is a jQuery plugin to select multiple elements with checkboxes :).",
+    "author": {
+        "name": "zhixin wen",
+        "email": "wenzhixin2010@gmail.com",
+        "url": "http://wenzhixin.net.cn/"
+    },
+    "licenses": [
+        {
+            "type": "MIT License",
+            "url": "http://opensource.org/licenses/MIT"
+        }
+    ],
+    "dependencies": {
+        "jquery": ">=1.7"
+    },
+    "keywords": ["multiple.select", "select.list", "multiple.choose", "checkbox"],
+    "homepage": "http://wenzhixin.net.cn/p/multiple-select/",
+    "demo": "http://wenzhixin.net.cn/p/multiple-select/#examples",
+    "bugs": {
+        "url": "https://github.com/wenzhixin/multiple-select/issues"
+    },
+    "docs": "http://wenzhixin.net.cn/p/multiple-select/#documentation",
+    "download": "https://github.com/wenzhixin/multiple-select/archive/master.zip"
+}
\ No newline at end of file
diff --git a/htdocs/includes/jquery/plugins/multiple-select/multiple-select.png b/htdocs/includes/jquery/plugins/multiple-select/multiple-select.png
new file mode 100644
index 0000000000000000000000000000000000000000..2a7ba608ea846d4873f84e00455ee2d1bbe4d13a
GIT binary patch
literal 3342
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
Y016sCsn^Dnga7~l07*qoM6N<$f>N<r+yDRo

literal 0
HcmV?d00001

diff --git a/htdocs/includes/jquery/plugins/multiselect/MIT-LICENSE.txt b/htdocs/includes/jquery/plugins/multiselect/MIT-LICENSE.txt
deleted file mode 100644
index 1076f8b4b2b..00000000000
--- a/htdocs/includes/jquery/plugins/multiselect/MIT-LICENSE.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2009 Michael Aufreiter, http://www.quasipartikel.at
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/htdocs/includes/jquery/plugins/multiselect/css/ui.multiselect.css b/htdocs/includes/jquery/plugins/multiselect/css/ui.multiselect.css
deleted file mode 100644
index 7d3a44801d2..00000000000
--- a/htdocs/includes/jquery/plugins/multiselect/css/ui.multiselect.css
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Multiselect
-----------------------------------*/
-
-.ui-multiselect { border: solid 1px; font-size: 0.8em; }
-.ui-multiselect ul { -moz-user-select: none; }
-.ui-multiselect li { margin: 0; padding: 0; cursor: default; line-height: 20px; height: 20px; font-size: 11px; list-style: none; padding-right: 18px; overflow: hidden; }
-.ui-multiselect li a { color: #999; text-decoration: none; padding: 0; display: block; float: left; cursor: pointer;}
-.ui-multiselect li.ui-draggable-dragging { padding-left: 10px; }
-
-.ui-multiselect div.selected { position: relative; padding: 0; margin: 0; border: 0; float:left; }
-.ui-multiselect ul.selected { position: relative; padding: 0; overflow: auto; overflow-x: hidden; background: #fff; margin: 0; list-style: none; border: 0; position: relative; width: 100%; }
-
-.ui-multiselect div.available { position: relative; padding: 0; margin: 0; border: 0; float:left; }
-.ui-multiselect ul.available { position: relative; padding: 0; overflow: auto; overflow-x: hidden; background: #fff; margin: 0; list-style: none; border: 0; width: 100%; }
-.ui-multiselect ul.available li { padding-left: 10px; }
-
-.ui-multiselect div.right-column { border-left: 1px solid; }
-
-.ui-multiselect .ui-state-default { border: none; margin-bottom: 1px; position: relative; padding-left: 20px;}
-.ui-multiselect .ui-state-hover { border: none; }
-.ui-multiselect .ui-widget-header {border: none; font-size: 11px; margin-bottom: 1px;}
-
-.ui-multiselect .add-all { float: right; padding: 7px;}
-.ui-multiselect .remove-all { float: right; padding: 7px;}
-.ui-multiselect .search { float: left; padding: 4px;}
-.ui-multiselect .count { float: left; padding: 7px;}
-
-.ui-multiselect li span.ui-icon-arrowthick-2-n-s { position: absolute; left: 2px; }
-.ui-multiselect li a.action { position: absolute; right: 2px; top: 2px; }
-
-.ui-multiselect input.search { height: 14px; padding: 1px; opacity: 0.5; margin: 4px; width: 100px; }
\ No newline at end of file
diff --git a/htdocs/includes/jquery/plugins/multiselect/js/ui.multiselect.js b/htdocs/includes/jquery/plugins/multiselect/js/ui.multiselect.js
deleted file mode 100644
index eb4578fc782..00000000000
--- a/htdocs/includes/jquery/plugins/multiselect/js/ui.multiselect.js
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * jQuery UI Multiselect
- *
- * Authors:
- *  Michael Aufreiter (quasipartikel.at)
- *  Yanick Rochon (yanick.rochon[at]gmail[dot]com)
- *
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- *
- * http://www.quasipartikel.at/multiselect/
- *
- *
- * Depends:
- *	ui.core.js
- *	ui.sortable.js
- *
- * Optional:
- * localization (http://plugins.jquery.com/project/localisation)
- * scrollTo (http://plugins.jquery.com/project/ScrollTo)
- *
- * Todo:
- *  Make batch actions faster
- *  Implement dynamic insertion through remote calls
- */
-
-
-(function($) {
-
-$.widget("ui.multiselect", {
-  options: {
-		sortable: true,
-		dragToAdd: true,
-		searchable: true,
-		doubleClickable: true,
-		animated: 'fast',
-		show: 'slideDown',
-		hide: 'slideUp',
-		dividerLocation: 0.6,
-		selectedContainerOnLeft: true,
-		width: null,
-		height: null,
-		nodeComparator: function(node1,node2) {
-			var text1 = node1.text(),
-			    text2 = node2.text();
-			return text1 == text2 ? 0 : (text1 < text2 ? -1 : 1);
-		},
-		includeRemoveAll: true,
-		includeAddAll: true,
-		pressEnterKeyToAddAll: false
-	},
-	_create: function() {
-		this.element.hide();
-		this.id = this.element.attr("id");
-		this.container = $('<div class="ui-multiselect ui-helper-clearfix ui-widget"></div>').insertAfter(this.element);
-		this.count = 0; // number of currently selected options
-		this.selectedContainer = $('<div class="selected"></div>');
-		if (this.options.selectedContainerOnLeft) {
-			this.selectedContainer.appendTo(this.container);
-			this.availableContainer = $('<div class="available"></div>').appendTo(this.container);
-			this.availableContainer.addClass('right-column');
-		}
-		else
-		{
-			this.availableContainer = $('<div class="available"></div>').appendTo(this.container);
-			this.selectedContainer.appendTo(this.container);
-			this.selectedContainer.addClass('right-column');
-		}
-		this.selectedActions = $('<div class="actions ui-widget-header ui-helper-clearfix"><span class="count">0 '+$.ui.multiselect.locale.itemsCount+'</span>'+(this.options.includeRemoveAll?'<a href="#" class="remove-all">'+$.ui.multiselect.locale.removeAll+'</a>':'<span class="remove-all">&nbsp;</span>')+'</div>').appendTo(this.selectedContainer);
-		this.availableActions = $('<div class="actions ui-widget-header ui-helper-clearfix"><input type="text" class="search empty ui-widget-content ui-corner-all"/>'+(this.options.includeAddAll?'<a href="#" class="add-all">'+$.ui.multiselect.locale.addAll+'</a>':'<span class="add-all">&nbsp;</span>')+'</div>').appendTo(this.availableContainer);
-		this.selectedList = $('<ul class="selected connected-list"><li class="ui-helper-hidden-accessible"></li></ul>').bind('selectstart', function(){return false;}).appendTo(this.selectedContainer);
-		this.availableList = $('<ul class="available connected-list"><li class="ui-helper-hidden-accessible"></li></ul>').bind('selectstart', function(){return false;}).appendTo(this.availableContainer);
-
-		var that = this;
-
-		var width = this.options.width;
-		if (!width) {
-			width = this.element.width();
-		}
-		var height = this.options.height;
-		if (!height) {
-			height = this.element.height();
-		}
-
-		// set dimensions
-		this.container.width(width-2);
-		if (this.options.selectedContainerOnLeft) {
-			this.selectedContainer.width(Math.floor(width*this.options.dividerLocation)-1);
-			this.availableContainer.width(Math.floor(width*(1-this.options.dividerLocation))-2);
-		}
-		else
-		{
-			this.selectedContainer.width(Math.floor(width*this.options.dividerLocation)-2);
-			this.availableContainer.width(Math.floor(width*(1-this.options.dividerLocation))-1);
-		}
-
-		// fix list height to match <option> depending on their individual header's heights
-		this.selectedList.height(Math.max(height-this.selectedActions.height(),1));
-		this.availableList.height(Math.max(height-this.availableActions.height(),1));
-
-		if ( !this.options.animated ) {
-			this.options.show = 'show';
-			this.options.hide = 'hide';
-		}
-
-		// init lists
-		this._populateLists(this.element.find('option'));
-
-		// make selection sortable
-		if (this.options.sortable) {
-			this.selectedList.sortable({
-				placeholder: 'ui-state-highlight',
-				axis: 'y',
-				update: function(event, ui) {
-					// apply the new sort order to the original selectbox
-					that.selectedList.find('li').each(function() {
-						if ($(this).data('optionLink'))
-							$(this).data('optionLink').remove().appendTo(that.element);
-					});
-				},
-				beforeStop: function (event, ui) {
-					// This lets us recognize which item was just added to
-					// the list in receive, per the workaround for not being
-					// able to reference the new element.
-					ui.item.addClass('dropped');
-				},
-				receive: function(event, ui) {
-					ui.item.data('optionLink').attr('selected', true);
-					// increment count
-					that.count += 1;
-					that._updateCount();
-					// workaround, because there's no way to reference
-					// the new element, see http://dev.jqueryui.com/ticket/4303
-					that.selectedList.children('.dropped').each(function() {
-						$(this).removeClass('dropped');
-						$(this).data('optionLink', ui.item.data('optionLink'));
-						$(this).data('idx', ui.item.data('idx'));
-						that._applyItemState($(this), true);
-					});
-
-					// workaround according to http://dev.jqueryui.com/ticket/4088
-					setTimeout(function() { ui.item.remove(); }, 1);
-				},
-				stop: function (event, ui) { that.element.change(); }
-			});
-		}
-
-		// set up livesearch
-		if (this.options.searchable) {
-			this._registerSearchEvents(this.availableContainer.find('input.search'));
-		} else {
-			$('.search').hide();
-		}
-
-		// batch actions
-		this.container.find(".remove-all").click(function() {
-			that._populateLists(that.element.find('option').removeAttr('selected'));
-			that.element.trigger('change');
-			return false;
-		});
-
-		this.container.find(".add-all").click(function() {
-			var options = that.element.find('option').not(":selected");
-			if (that.availableList.children('li:hidden').length > 1) {
-				that.availableList.children('li').each(function(i) {
-					if ($(this).is(":visible")) $(options[i-1]).attr('selected', 'selected');
-				});
-			} else {
-				options.attr('selected', 'selected');
-			}
-			that._populateLists(that.element.find('option'));
-			that.element.trigger('change');
-			if (that.options.pressEnterKeyToAddAll) {
-                    //clear input after add all
-                    $('input.search').val("");
-                }
-			
-			return false;
-		});
-	},
-	destroy: function() {
-		this.element.show();
-		this.container.remove();
-
-		$.Widget.prototype.destroy.apply(this, arguments);
-	},
-	addOption: function(option) {
-		// Append the option
-		option = $(option);
-		var select = this.element;
-		select.append(option);
-
-		var item = this._getOptionNode(option).appendTo(option.attr('selected') ? this.selectedList : this.availableList).show();
-
-		if (option.attr('selected')) {
-			this.count += 1;
-		}
-		this._applyItemState(item, option.attr('selected'));
-		item.data('idx', this.count);
-
-		// update count
-		this._updateCount();
-		this._filter.apply(this.availableContainer.find('input.search'), [this.availableList]);
-	},
-    // Redisplay the lists of selected/available options.
-    // Call this after you've selected/unselected some options programmatically.
-    // GRIPE This is O(n) where n is the length of the list - seems like
-    // there must be a smarter way of doing this, but I have not been able
-    // to come up with one. I see no way to detect programmatic setting of
-    // the option's selected property, and without that, it seems like we
-    // can't have a general-case listener that does its thing every time an
-    // option is selected.
-    refresh: function() {
-		// Redisplay our lists.
-		this._populateLists(this.element.find('option'));
-    },
-	_populateLists: function(options) {
-		this.selectedList.children('.ui-element').remove();
-		this.availableList.children('.ui-element').remove();
-		this.count = 0;
-
-		var that = this;
-		var groups = $(this.element).find("optgroup").map(function(i) {
-			return that._getOptionGroup($(this));
-		});
-		groups.appendTo(this.selectedList.add(this.availableList));
-		
-		var items = $(options.map(function(i) {
-		  var item = that._getOptionNode(this).appendTo(that._getOptionList(this)).show();
-
-			if (this.selected) that.count += 1;
-			that._applyItemState(item, this.selected);
-			item.data('idx', i);
-			return item[0];
-    }));
-
-		// update count
-		this._updateCount();
-		that._filter.apply(this.availableContainer.find('input.search'), [that.availableList]);
-  },
-	_getOptionList: function(option) {
-		var selected = option.selected;
-		option = $(option);
-		var $list = selected ? this.selectedList : this.availableList;
-		var $group = option.closest("optgroup");
-		if ($group.length === 0) {
-			return $list;
-		} else {
-			var $groupList = $list.find("ul[title='" + $group.attr("label") + "']");
-			if ($groupList.length === 0) {
-				$groupList = $("<ul class='ui-state-default ui-element available' title='" + $group.attr("label") + "'>" + $group.attr("label") + "</ul>").appendTo($list);
-			}
-			$groupList.show();
-			return $groupList;
-		}
-	},
-	_getOptionGroup : function(optgroup) {
-		var groupNode = $("<ul class='ui-state-default ui-element available' title='" + optgroup.attr("label") + "'>" + optgroup.attr("label") + "</ul>").hide();
-		return groupNode[0];
-	},
-	_updateCount: function() {
-		this.selectedContainer.find('span.count').text(this.count+" "+$.ui.multiselect.locale.itemsCount);
-	},
-	_getOptionNode: function(option) {
-		option = $(option);
-		var node = $('<li class="ui-state-default ui-element" title="'+option.text()+'"><span class="ui-icon"/>'+option.text()+'<a href="#" class="action"><span class="ui-corner-all ui-icon"/></a></li>').hide();
-		node.data('optionLink', option);
-		return node;
-	},
-	// clones an item with associated data
-	// didn't find a smarter away around this
-	_cloneWithData: function(clonee) {
-		var clone = clonee.clone(false,false);
-		clone.data('optionLink', clonee.data('optionLink'));
-		clone.data('idx', clonee.data('idx'));
-		return clone;
-	},
-	_setSelected: function(item, selected) {
-		var temp = item.data('optionLink').attr('selected', selected);
-		var parent = temp.parent();
-		temp.detach().appendTo(parent);
-		this.element.trigger('change');
-
-		if (selected) {
-			var selectedItem = this._cloneWithData(item);
-			item[this.options.hide](this.options.animated, function() { 
-				if (item.siblings().length === 0) {
-					item.closest("ul[title]").hide();
-				}
-				$(this).remove(); 
-			});
-			// get group to add it to...
-			var $list = this._getOptionList(selectedItem.data("optionLink")[0]);
-			selectedItem.appendTo($list).hide()[this.options.show](this.options.animated);
-
-			this._applyItemState(selectedItem, true);
-			return selectedItem;
-		} else {
-
-			// look for successor based on initial option index
-			var items = this.availableList.find('li'), comparator = this.options.nodeComparator;
-			var succ = null, i = item.data('idx'), direction = comparator(item, $(items[i]));
-
-			// TODO: test needed for dynamic list populating
-			if ( direction ) {
-				while (i>=0 && i<items.length) {
-					direction > 0 ? i++ : i--;
-					if ( direction != comparator(item, $(items[i])) ) {
-						// going up, go back one item down, otherwise leave as is
-						succ = items[direction > 0 ? i : i+1];
-						var group1 = item.closest("ul[title]"),
-							group2 = $(succ).closest("ul[title]");
-						if (group1.length !== 0 && group2.length !== 0) {
-							if (group1.attr("title") !== group2.attr("title")) {
-								succ = null;
-							}
-						}
-						break;
-					}
-				}
-			} else {
-				succ = items[i];
-			}
-
-			var availableItem = this._cloneWithData(item);
-			var $list = this._getOptionList(availableItem.data("optionLink")[0]);
-			succ ? availableItem.insertBefore($(succ)) : availableItem.appendTo($list);
-			item[this.options.hide](this.options.animated, function() { 
-				if (item.siblings().length === 0) {
-					item.closest("ul[title]").hide();
-				}
-				$(this).remove(); 
-			});
-			availableItem.hide()[this.options.show](this.options.animated);
-
-			this._applyItemState(availableItem, false);
-			return availableItem;
-		}
-	},
-	_applyItemState: function(item, selected) {
-		if (selected) {
-			if (this.options.sortable)
-				item.children('span').addClass('ui-icon-arrowthick-2-n-s').removeClass('ui-helper-hidden').addClass('ui-icon');
-			else
-				item.children('span').removeClass('ui-icon-arrowthick-2-n-s').addClass('ui-helper-hidden').removeClass('ui-icon');
-			item.find('a.action span').addClass('ui-icon-minus').removeClass('ui-icon-plus');
-			this._registerRemoveEvents(item.find('a.action'));
-
-		} else {
-			item.children('span').removeClass('ui-icon-arrowthick-2-n-s').addClass('ui-helper-hidden').removeClass('ui-icon');
-			item.find('a.action span').addClass('ui-icon-plus').removeClass('ui-icon-minus');
-			this._registerAddEvents(item.find('a.action'));
-		}
-
-		this._registerDoubleClickEvents(item);
-		this._registerHoverEvents(item);
-	},
-	// taken from John Resig's liveUpdate script
-	_filter: function(list) {
-		var input = $(this);
-		var rows = list.find('li'),
-			cache = rows.map(function(){
-
-				return $(this).text().toLowerCase();
-			});
-
-		var term = $.trim(input.val().toLowerCase()), scores = [];
-
-		if (!term) {
-			rows.show();
-		} else {
-			rows.hide();
-
-			cache.each(function(i) {
-				if (this.indexOf(term)>-1) { scores.push(i); }
-			});
-
-			$.each(scores, function() {
-				$(rows[this]).show();
-			});
-		}
-	},
-	_registerDoubleClickEvents: function(elements) {
-		if (!this.options.doubleClickable) return;
-		elements.dblclick(function() {
-			elements.find('a.action').click();
-		});
-	},
-	_registerHoverEvents: function(elements) {
-		elements.removeClass('ui-state-hover');
-		elements.mouseover(function() {
-			$(this).addClass('ui-state-hover');
-		});
-		elements.mouseout(function() {
-			$(this).removeClass('ui-state-hover');
-		});
-	},
-	_registerAddEvents: function(elements) {
-		var that = this;
-		elements.click(function() {
-			var item = that._setSelected($(this).parent(), true);
-			that.count += 1;
-			that._updateCount();
-
-			// Prevent extra clicks from triggering bogus add events, if a user
-			// tries clicking during the removal process.
-			$(this).unbind('click');
-
-			return false;
-		});
-
-		// make draggable
-		if (this.options.sortable && this.options.dragToAdd) {
-  		elements.each(function() {
-  			$(this).parent().draggable({
-  	      connectToSortable: that.selectedList,
-  				helper: function() {
-  					var selectedItem = that._cloneWithData($(this)).width($(this).width() - 50);
-  					selectedItem.width($(this).width());
-  					return selectedItem;
-  				},
-  				appendTo: that.container,
-  				containment: that.container,
-  				revert: 'invalid'
-  	    });
-  		});
-		}
-	},
-	_registerRemoveEvents: function(elements) {
-		var that = this;
-		elements.click(function() {
-			that._setSelected($(this).parent(), false);
-			that.count -= 1;
-			that._updateCount();
-
-			// Prevent extra clicks from triggering bogus remove events, if a
-			// user tries clicking during the removal process.
-			$(this).unbind('click');
-
-			return false;
-		});
- 	},
-	_registerSearchEvents: function(input) {
-		var that = this;
-
-		input.focus(function() {
-			$(this).addClass('ui-state-active');
-		})
-		.blur(function() {
-			$(this).removeClass('ui-state-active');
-		})
-		.keypress(function(e) {
-			if (e.keyCode == 13) {
-				if (that.options.pressEnterKeyToAddAll) {
-		            //on Enter, if a filter is present add all, then clear the input
-		            var str = $('input.search').val();
-		            if (str !== undefined && str !== null && str !== "") {
-		                $('a.add-all').click();
-		                $('input.search').val("");
-		            }
-		        }
-				return false;
-			}
-		})
-		.keyup(function() {
-			that._filter.apply(this, [that.availableList]);
-		});
-	}
-});
-
-$.extend($.ui.multiselect, {
-	locale: {
-		addAll:'Add all',
-		removeAll:'Remove all',
-		itemsCount:'items selected'
-	}
-});
-
-
-})(jQuery);
diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php
index fa6b503caa7..6698866869e 100644
--- a/htdocs/main.inc.php
+++ b/htdocs/main.inc.php
@@ -1015,10 +1015,14 @@ function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs
                 //print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/datatables/extras/ColVis/css/ColVisAlt.css'.($ext?'?'.$ext:'').'" />'."\n";
                 print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/datatables/extras/TableTools/css/TableTools.css'.($ext?'?'.$ext:'').'" />'."\n";
             }
-            if (! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) || (defined('REQUIRE_JQUERY_MULTISELECT') && constant('REQUIRE_JQUERY_MULTISELECT')))     // jQuery multiselect
+            if ((! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) && $conf->global->MAIN_USE_JQUERY_MULTISELECT == 'multiselect') || (defined('REQUIRE_JQUERY_MULTISELECT') && constant('REQUIRE_JQUERY_MULTISELECT') == 'multiselect'))     // jQuery multiselect
             {
             	print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/multiselect/css/ui.multiselect.css'.($ext?'?'.$ext:'').'" />'."\n";
             }
+            if ((! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) && $conf->global->MAIN_USE_JQUERY_MULTISELECT == 'multiple-select') || (defined('REQUIRE_JQUERY_MULTISELECT') && constant('REQUIRE_JQUERY_MULTISELECT') == 'multiple-select'))     // jQuery multiple-select
+            {
+            	print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/multiple-select/multiple-select.css'.($ext?'?'.$ext:'').'" />'."\n";
+            }
             // jQuery Timepicker
             if (! empty($conf->global->MAIN_USE_JQUERY_TIMEPICKER) || defined('REQUIRE_JQUERY_TIMEPICKER'))
             {
@@ -1178,11 +1182,6 @@ function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs
                 print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/datatables/extras/ColVis/js/ColVis.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
                 print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/datatables/extras/TableTools/js/TableTools.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
             }
-            // jQuery Multiselect
-            if (! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) || (defined('REQUIRE_JQUERY_MULTISELECT') && constant('REQUIRE_JQUERY_MULTISELECT')))
-            {
-            	print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/multiselect/js/ui.multiselect.js'.($ext?'?'.$ext:'').'"></script>'."\n";
-            }
             // jQuery Timepicker
             if (! empty($conf->global->MAIN_USE_JQUERY_TIMEPICKER) || defined('REQUIRE_JQUERY_TIMEPICKER'))
             {
-- 
GitLab