Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
malwaredllc
GitHub Repository: malwaredllc/byob
Path: blob/master/web-gui/buildyourownbotnet/assets/js/jquery.multi-select.js
1292 views
1
/*
2
* MultiSelect v0.9.8
3
* Copyright (c) 2012 Louis Cuny
4
*
5
* This program is free software. It comes without any warranty, to
6
* the extent permitted by applicable law. You can redistribute it
7
* and/or modify it under the terms of the Do What The Fuck You Want
8
* To Public License, Version 2, as published by Sam Hocevar. See
9
* http://sam.zoy.org/wtfpl/COPYING for more details.
10
*/
11
12
!function ($) {
13
14
"use strict";
15
16
17
/* MULTISELECT CLASS DEFINITION
18
* ====================== */
19
20
var MultiSelect = function (element, options) {
21
this.options = options;
22
this.$element = $(element);
23
24
this.$container = $('<div/>', { 'class': "ms-container" });
25
this.$selectableContainer = $('<div/>', { 'class': 'ms-selectable' });
26
this.$selectionContainer = $('<div/>', { 'class': 'ms-selection' });
27
this.$selectableUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' });
28
this.$selectionUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' });
29
this.scrollTo = 0;
30
this.sanitizeRegexp = new RegExp("\\W+", 'gi');
31
this.elemsSelector = 'li:visible:not(.ms-optgroup-label,.ms-optgroup-container,.'+options.disabledClass+')';
32
};
33
34
MultiSelect.prototype = {
35
constructor: MultiSelect,
36
37
init: function(){
38
var that = this,
39
ms = this.$element;
40
41
if (ms.next('.ms-container').length === 0){
42
ms.css({ position: 'absolute', left: '-9999px' });
43
ms.attr('id', ms.attr('id') ? ms.attr('id') : Math.ceil(Math.random()*1000)+'multiselect');
44
this.$container.attr('id', 'ms-'+ms.attr('id'));
45
46
ms.find('option').each(function(){
47
that.generateLisFromOption(this);
48
});
49
50
this.$selectionUl.find('.ms-optgroup-label').hide();
51
52
if (that.options.selectableHeader){
53
that.$selectableContainer.append(that.options.selectableHeader);
54
}
55
that.$selectableContainer.append(that.$selectableUl);
56
if (that.options.selectableFooter){
57
that.$selectableContainer.append(that.options.selectableFooter);
58
}
59
60
if (that.options.selectionHeader){
61
that.$selectionContainer.append(that.options.selectionHeader);
62
}
63
that.$selectionContainer.append(that.$selectionUl);
64
if (that.options.selectionFooter){
65
that.$selectionContainer.append(that.options.selectionFooter);
66
}
67
68
that.$container.append(that.$selectableContainer);
69
that.$container.append(that.$selectionContainer);
70
ms.after(that.$container);
71
72
that.activeMouse(that.$selectableUl);
73
that.activeKeyboard(that.$selectableUl);
74
75
var action = that.options.dblClick ? 'dblclick' : 'click';
76
77
that.$selectableUl.on(action, '.ms-elem-selectable', function(){
78
that.select($(this).data('ms-value'));
79
});
80
that.$selectionUl.on(action, '.ms-elem-selection', function(){
81
that.deselect($(this).data('ms-value'));
82
});
83
84
that.activeMouse(that.$selectionUl);
85
that.activeKeyboard(that.$selectionUl);
86
87
ms.on('focus', function(){
88
that.$selectableUl.focus();
89
})
90
}
91
92
var selectedValues = ms.find('option:selected').map(function(){ return $(this).val(); }).get();
93
that.select(selectedValues, 'init');
94
95
if (typeof that.options.afterInit === 'function') {
96
that.options.afterInit.call(this, this.$container);
97
}
98
},
99
100
'generateLisFromOption' : function(option){
101
var that = this,
102
ms = that.$element,
103
attributes = "",
104
$option = $(option);
105
106
for (var cpt = 0; cpt < option.attributes.length; cpt++){
107
var attr = option.attributes[cpt];
108
109
if(attr.name !== 'value' && attr.name !== 'disabled'){
110
attributes += attr.name+'="'+attr.value+'" ';
111
}
112
}
113
var selectableLi = $('<li '+attributes+'><span>'+$option.text()+'</span></li>'),
114
selectedLi = selectableLi.clone(),
115
value = $option.val(),
116
elementId = that.sanitize(value, that.sanitizeRegexp);
117
118
selectableLi
119
.data('ms-value', value)
120
.addClass('ms-elem-selectable')
121
.attr('id', elementId+'-selectable');
122
123
selectedLi
124
.data('ms-value', value)
125
.addClass('ms-elem-selection')
126
.attr('id', elementId+'-selection')
127
.hide();
128
129
if ($option.prop('disabled') || ms.prop('disabled')){
130
selectedLi.addClass(that.options.disabledClass);
131
selectableLi.addClass(that.options.disabledClass);
132
}
133
134
var $optgroup = $option.parent('optgroup');
135
136
if ($optgroup.length > 0){
137
var optgroupLabel = $optgroup.attr('label'),
138
optgroupId = that.sanitize(optgroupLabel, that.sanitizeRegexp),
139
$selectableOptgroup = that.$selectableUl.find('#optgroup-selectable-'+optgroupId),
140
$selectionOptgroup = that.$selectionUl.find('#optgroup-selection-'+optgroupId);
141
142
if ($selectableOptgroup.length === 0){
143
var optgroupContainerTpl = '<li class="ms-optgroup-container"></li>',
144
optgroupTpl = '<ul class="ms-optgroup"><li class="ms-optgroup-label"><span>'+optgroupLabel+'</span></li></ul>';
145
146
$selectableOptgroup = $(optgroupContainerTpl);
147
$selectionOptgroup = $(optgroupContainerTpl);
148
$selectableOptgroup.attr('id', 'optgroup-selectable-'+optgroupId);
149
$selectionOptgroup.attr('id', 'optgroup-selection-'+optgroupId);
150
$selectableOptgroup.append($(optgroupTpl));
151
$selectionOptgroup.append($(optgroupTpl));
152
if (that.options.selectableOptgroup){
153
$selectableOptgroup.find('.ms-optgroup-label').on('click', function(){
154
var values = $optgroup.children(':not(:selected)').map(function(){ return $(this).val() }).get();
155
that.select(values);
156
});
157
$selectionOptgroup.find('.ms-optgroup-label').on('click', function(){
158
var values = $optgroup.children(':selected').map(function(){ return $(this).val() }).get();
159
that.deselect(values);
160
});
161
}
162
that.$selectableUl.append($selectableOptgroup);
163
that.$selectionUl.append($selectionOptgroup);
164
}
165
$selectableOptgroup.children().append(selectableLi);
166
$selectionOptgroup.children().append(selectedLi);
167
} else {
168
that.$selectableUl.append(selectableLi);
169
that.$selectionUl.append(selectedLi);
170
}
171
},
172
173
'activeKeyboard' : function($list){
174
var that = this;
175
176
$list.on('focus', function(){
177
$(this).addClass('ms-focus');
178
})
179
.on('blur', function(){
180
$(this).removeClass('ms-focus');
181
})
182
.on('keydown', function(e){
183
switch (e.which) {
184
case 40:
185
case 38:
186
e.preventDefault();
187
e.stopPropagation();
188
that.moveHighlight($(this), (e.which === 38) ? -1 : 1);
189
return;
190
case 37:
191
case 39:
192
e.preventDefault();
193
e.stopPropagation();
194
that.switchList($list);
195
return;
196
case 9:
197
if(that.$element.is('[tabindex]')){
198
e.preventDefault();
199
var tabindex = parseInt(that.$element.attr('tabindex'), 10);
200
tabindex = (e.shiftKey) ? tabindex-1 : tabindex+1;
201
$('[tabindex="'+(tabindex)+'"]').focus();
202
return;
203
}else{
204
if(e.shiftKey){
205
that.$element.trigger('focus');
206
}
207
}
208
}
209
if($.inArray(e.which, that.options.keySelect) > -1){
210
e.preventDefault();
211
e.stopPropagation();
212
that.selectHighlighted($list);
213
return;
214
}
215
});
216
},
217
218
'moveHighlight': function($list, direction){
219
var $elems = $list.find(this.elemsSelector),
220
$currElem = $elems.filter('.ms-hover'),
221
$nextElem = null,
222
elemHeight = $elems.first().outerHeight(),
223
containerHeight = $list.height(),
224
containerSelector = '#'+this.$container.prop('id');
225
226
// Deactive mouseenter event when move is active
227
// It fixes a bug when mouse is over the list
228
$elems.off('mouseenter');
229
230
$elems.removeClass('ms-hover');
231
if (direction === 1){ // DOWN
232
233
$nextElem = $currElem.nextAll(this.elemsSelector).first();
234
if ($nextElem.length === 0){
235
var $optgroupUl = $currElem.parent();
236
237
if ($optgroupUl.hasClass('ms-optgroup')){
238
var $optgroupLi = $optgroupUl.parent(),
239
$nextOptgroupLi = $optgroupLi.next(':visible');
240
241
if ($nextOptgroupLi.length > 0){
242
$nextElem = $nextOptgroupLi.find(this.elemsSelector).first();
243
} else {
244
$nextElem = $elems.first();
245
}
246
} else {
247
$nextElem = $elems.first();
248
}
249
}
250
} else if (direction === -1){ // UP
251
252
$nextElem = $currElem.prevAll(this.elemsSelector).first();
253
if ($nextElem.length === 0){
254
var $optgroupUl = $currElem.parent();
255
256
if ($optgroupUl.hasClass('ms-optgroup')){
257
var $optgroupLi = $optgroupUl.parent(),
258
$prevOptgroupLi = $optgroupLi.prev(':visible');
259
260
if ($prevOptgroupLi.length > 0){
261
$nextElem = $prevOptgroupLi.find(this.elemsSelector).last();
262
} else {
263
$nextElem = $elems.last();
264
}
265
} else {
266
$nextElem = $elems.last();
267
}
268
}
269
}
270
if ($nextElem.length > 0){
271
$nextElem.addClass('ms-hover');
272
var scrollTo = $list.scrollTop() + $nextElem.position().top -
273
containerHeight / 2 + elemHeight / 2;
274
275
$list.scrollTop(scrollTo);
276
}
277
},
278
279
'selectHighlighted' : function($list){
280
var $elems = $list.find(this.elemsSelector),
281
$highlightedElem = $elems.filter('.ms-hover').first();
282
283
if ($highlightedElem.length > 0){
284
if ($list.parent().hasClass('ms-selectable')){
285
this.select($highlightedElem.data('ms-value'));
286
} else {
287
this.deselect($highlightedElem.data('ms-value'));
288
}
289
$elems.removeClass('ms-hover');
290
}
291
},
292
293
'switchList' : function($list){
294
$list.blur();
295
if ($list.parent().hasClass('ms-selectable')){
296
this.$selectionUl.focus();
297
} else {
298
this.$selectableUl.focus();
299
}
300
},
301
302
'activeMouse' : function($list){
303
var that = this;
304
305
$list.on('mousemove', function(){
306
var elems = $list.find(that.elemsSelector);
307
308
elems.on('mouseenter', function(){
309
elems.removeClass('ms-hover');
310
$(this).addClass('ms-hover');
311
});
312
});
313
},
314
315
'refresh' : function() {
316
this.destroy();
317
this.$element.multiSelect(this.options);
318
},
319
320
'destroy' : function(){
321
$("#ms-"+this.$element.attr("id")).remove();
322
this.$element.removeData('multiselect');
323
},
324
325
'select' : function(value, method){
326
if (typeof value === 'string'){ value = [value]; }
327
328
var that = this,
329
ms = this.$element,
330
msIds = $.map(value, function(val){ return(that.sanitize(val, that.sanitizeRegexp)); }),
331
selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable').filter(':not(.'+that.options.disabledClass+')'),
332
selections = this.$selectionUl.find('#' + msIds.join('-selection, #') + '-selection').filter(':not(.'+that.options.disabledClass+')'),
333
options = ms.find('option:not(:disabled)').filter(function(){ return($.inArray(this.value, value) > -1); });
334
335
if (selectables.length > 0){
336
selectables.addClass('ms-selected').hide();
337
selections.addClass('ms-selected').show();
338
options.prop('selected', true);
339
340
var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');
341
if (selectableOptgroups.length > 0){
342
selectableOptgroups.each(function(){
343
var selectablesLi = $(this).find('.ms-elem-selectable');
344
if (selectablesLi.length === selectablesLi.filter('.ms-selected').length){
345
$(this).find('.ms-optgroup-label').hide();
346
}
347
});
348
349
var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');
350
selectionOptgroups.each(function(){
351
var selectionsLi = $(this).find('.ms-elem-selection');
352
if (selectionsLi.filter('.ms-selected').length > 0){
353
$(this).find('.ms-optgroup-label').show();
354
}
355
});
356
} else {
357
if (that.options.keepOrder){
358
var selectionLiLast = that.$selectionUl.find('.ms-selected');
359
if((selectionLiLast.length > 1) && (selectionLiLast.last().get(0) != selections.get(0))) {
360
selections.insertAfter(selectionLiLast.last());
361
}
362
}
363
}
364
if (method !== 'init'){
365
ms.trigger('change');
366
if (typeof that.options.afterSelect === 'function') {
367
that.options.afterSelect.call(this, value);
368
}
369
}
370
}
371
},
372
373
'deselect' : function(value){
374
if (typeof value === 'string'){ value = [value]; }
375
376
var that = this,
377
ms = this.$element,
378
msIds = $.map(value, function(val){ return(that.sanitize(val, that.sanitizeRegexp)); }),
379
selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable'),
380
selections = this.$selectionUl.find('#' + msIds.join('-selection, #')+'-selection').filter('.ms-selected'),
381
options = ms.find('option').filter(function(){ return($.inArray(this.value, value) > -1); });
382
383
if (selections.length > 0){
384
selectables.removeClass('ms-selected').show();
385
selections.removeClass('ms-selected').hide();
386
options.prop('selected', false);
387
388
var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');
389
if (selectableOptgroups.length > 0){
390
selectableOptgroups.each(function(){
391
var selectablesLi = $(this).find('.ms-elem-selectable');
392
if (selectablesLi.filter(':not(.ms-selected)').length > 0){
393
$(this).find('.ms-optgroup-label').show();
394
}
395
});
396
397
var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');
398
selectionOptgroups.each(function(){
399
var selectionsLi = $(this).find('.ms-elem-selection');
400
if (selectionsLi.filter('.ms-selected').length === 0){
401
$(this).find('.ms-optgroup-label').hide();
402
}
403
});
404
}
405
ms.trigger('change');
406
if (typeof that.options.afterDeselect === 'function') {
407
that.options.afterDeselect.call(this, value);
408
}
409
}
410
},
411
412
'select_all' : function(){
413
var ms = this.$element,
414
values = ms.val();
415
416
ms.find('option:not(":disabled")').prop('selected', true);
417
this.$selectableUl.find('.ms-elem-selectable').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').hide();
418
this.$selectionUl.find('.ms-optgroup-label').show();
419
this.$selectableUl.find('.ms-optgroup-label').hide();
420
this.$selectionUl.find('.ms-elem-selection').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').show();
421
this.$selectionUl.focus();
422
ms.trigger('change');
423
if (typeof this.options.afterSelect === 'function') {
424
var selectedValues = $.grep(ms.val(), function(item){
425
return $.inArray(item, values) < 0;
426
});
427
this.options.afterSelect.call(this, selectedValues);
428
}
429
},
430
431
'deselect_all' : function(){
432
var ms = this.$element,
433
values = ms.val();
434
435
ms.find('option').prop('selected', false);
436
this.$selectableUl.find('.ms-elem-selectable').removeClass('ms-selected').show();
437
this.$selectionUl.find('.ms-optgroup-label').hide();
438
this.$selectableUl.find('.ms-optgroup-label').show();
439
this.$selectionUl.find('.ms-elem-selection').removeClass('ms-selected').hide();
440
this.$selectableUl.focus();
441
ms.trigger('change');
442
if (typeof this.options.afterDeselect === 'function') {
443
this.options.afterDeselect.call(this, values);
444
}
445
},
446
447
sanitize: function(value, reg){
448
return(value.replace(reg, '_'));
449
}
450
};
451
452
/* MULTISELECT PLUGIN DEFINITION
453
* ======================= */
454
455
$.fn.multiSelect = function () {
456
var option = arguments[0],
457
args = arguments;
458
459
return this.each(function () {
460
var $this = $(this),
461
data = $this.data('multiselect'),
462
options = $.extend({}, $.fn.multiSelect.defaults, $this.data(), typeof option === 'object' && option);
463
464
if (!data){ $this.data('multiselect', (data = new MultiSelect(this, options))); }
465
466
if (typeof option === 'string'){
467
data[option](args[1]);
468
} else {
469
data.init();
470
}
471
});
472
};
473
474
$.fn.multiSelect.defaults = {
475
keySelect: [32],
476
selectableOptgroup: false,
477
disabledClass : 'disabled',
478
dblClick : false,
479
keepOrder: false
480
};
481
482
$.fn.multiSelect.Constructor = MultiSelect;
483
484
}(window.jQuery);
485