WebUI: migrate to fetch API
[qBittorrent.git] / src / webui / www / private / scripts / lib / vanillaSelectBox.js
blob73e33703a6245729839baa37440dc7d1ce273111
1 /*
2 Copyright (C) Philippe Meyer 2019-2021
3 Distributed under the MIT License 
5 vanillaSelectBox : v1.05 : setValue() bug correction on single mode. You could not set the value
6 vanillaSelectBox : v1.04 : select all issue fixed by https://github.com/arthur911016 
7 vanillaSelectBox : v1.03 : getResult() an new fonction to get the selected values in an array
8 vanillaSelectBox : v1.02 : Adding 2 new options "itemsSeparator" to change the default "," item separator showing in the button and translations.item to show the item in singular if there is only one.
9 vanillaSelectBox : v1.01 : Removing useless code line 550,551 issue 71 by chchch
10 vanillaSelectBox : v1.00 : Adding a package.json file 
11 vanillaSelectBox : v0.78 : Stop using inline styles in the main button. You can steal use keepInlineStyles:true to use the legacy behaviour
12 vanillaSelectBox : v0.77 : Work on place holder with bastoune help => still seems to lose placeholder value on multiple dropdown checkall
13 vanillaSelectBox : v0.76 : New changeTree function : to rebuild the original tree with new data + correcting empty() function
14 vanillaSelectBox : v0.75 : Remote search ready + local search modification : when a check on optgroup checks children only 
15                            if they not excluded from search.
16 vanillaSelectBox : v0.72 : Remote search (WIP) bugfix [x] Select all duplicated
17 vanillaSelectBox : v0.71 : Remote search (WIP) better code
18 vanillaSelectBox : v0.70 : Remote search (WIP) for users to test
19 vanillaSelectBox : v0.65 : Two levels: bug fix : groups are checked/unchecked when check all/uncheck all is clicked
20 vanillaSelectBox : v0.64 : Two levels: groups are now checkable to check/uncheck the children options 
21 vanillaSelectBox : v0.63 : Two levels: one click on the group selects / unselects children
22 vanillaSelectBox : v0.62 : New option: maxOptionWidth set a maximum width for each option for narrow menus
23 vanillaSelectBox : v0.61 : New option: maxSelect, set a maximum to the selectable options in a multiple choice menu
24 vanillaSelectBox : v0.60 : Two levels: Optgroups are now used to show two level dropdowns 
25 vanillaSelectBox : v0.59 : Bug fix : search box was overlapping first item in single selects
26 vanillaSelectBox : v0.58 : Bug fixes
27 vanillaSelectBox : v0.57 : Bug fix (minWidth option not honored)
28 vanillaSelectBox : v0.56 : The multiselect checkboxes are a little smaller, maxWidth option is now working + added minWidth option as well
29                            The button has now a style attribute to protect its appearance 
30 vanillaSelectBox : v0.55 : All attributes from the original select options are copied to the selectBox element
31 vanillaSelectBox : v0.54 : if all the options of the select are selected by the user then the check all checkbox is checked
32 vanillaSelectBox : v0.53 : if all the options of the select are selected then the check all checkbox is checked
33 vanillaSelectBox : v0.52 : Better support of select('all') => command is consistent with checkbox and selecting / deselecting while searching select / uncheck only the found items
34 vanillaSelectBox : v0.51 : Translations for select all/clear all + minor css corrections + don't select disabled items
35 vanillaSelectBox : v0.50 : PR by jaguerra2017 adding a select all/clear all check button + optgroup support !
36 vanillaSelectBox : v0.41 : Bug corrected, the menu content was misplaced if a css transform was applied on a parent
37 vanillaSelectBox : v0.40 : A click on one selectBox close the other opened boxes
38 vanillaSelectBox : v0.35 : You can enable and disable items
39 vanillaSelectBox : v0.30 : The menu stops moving around on window resize and scroll + z-index in order of creation for multiple instances
40 vanillaSelectBox : v0.26 : Corrected bug in stayOpen mode with disable() function
41 vanillaSelectBox : v0.25 : New option stayOpen, and the dropbox is no longer a dropbox but a nice multi-select
42 previous version : v0.24 : corrected bug affecting options with more than one class
43 https://github.com/PhilippeMarcMeyer/vanillaSelectBox
46 let VSBoxCounter = function () {
47     let count = 0;
48     let instances = [];
49     return {
50         set: function (instancePtr) {
51             instances.push({ offset: ++count, ptr: instancePtr });
52             return instances[instances.length - 1].offset;
53         },
54         remove: function (instanceNr) {
55             let temp = instances.filter(function (x) {
56                 return x.offset != instanceNr;
57             })
58             instances = temp.splice(0);
59         },
60         closeAllButMe: function (instanceNr) {
61             instances.forEach(function (x) {
62                 if (x.offset != instanceNr) {
63                     x.ptr.closeOrder();
64                 }
65             });
66         }
67     };
68 }();
70 function vanillaSelectBox(domSelector, options) {
71     let self = this;
72     this.instanceOffset = VSBoxCounter.set(self);
73     this.domSelector = domSelector;
74     this.root = document.querySelector(domSelector);
75     this.rootToken = null;
76     this.main;
77     this.button;
78     this.title;
79     this.isMultiple = this.root.hasAttribute("multiple");
80     this.multipleSize = this.isMultiple && this.root.hasAttribute("size") ? parseInt(this.root.getAttribute("size")) : -1;
81     this.isOptgroups = false;
82     this.currentOptgroup = 0;
83     this.drop;
84     this.top;
85     this.left;
86     this.options;
87     this.listElements;
88     this.isDisabled = false;
89     this.search = false;
90     this.searchZone = null;
91     this.inputBox = null;
92     this.disabledItems = [];
93     this.ulminWidth = 140;
94     this.ulmaxWidth = 280;
95     this.ulminHeight = 25;
96     this.maxOptionWidth = Infinity;
97     this.maxSelect = Infinity;
98     this.isInitRemote = false;
99     this.isSearchRemote = false;
100     this.onInit = null;
101     this.onSearch = null; // if isRemote is true : a user defined function that loads more options from the back
102     this.onInitSize = null;
103     this.forbidenAttributes = ["class", "selected", "disabled", "data-text", "data-value", "style"];
104     this.forbidenClasses = ["active", "disabled"];
105     this.userOptions = {
106         maxWidth: 500,
107         minWidth: -1,
108         maxHeight: 400,
109         translations: { "all": "All", "item": "item","items": "items", "selectAll": "Select All", "clearAll": "Clear All" },
110         search: false,
111         placeHolder: "",
112         stayOpen: false,
113         disableSelectAll: false,
114         buttonItemsSeparator : ","
115     }
116     this.keepInlineStyles = true;
117     this.keepInlineCaretStyles = true;
118     if (options) {
119         if(options.itemsSeparator!= undefined){
120             this.userOptions.buttonItemsSeparator = options.itemsSeparator;
121         }
122         if (options.maxWidth != undefined) {
123             this.userOptions.maxWidth = options.maxWidth;
124         }
125         if (options.minWidth != undefined) {
126             this.userOptions.minWidth = options.minWidth;
127         }
128         if (options.maxHeight != undefined) {
129             this.userOptions.maxHeight = options.maxHeight;
130         }
131         if (options.translations != undefined) {
132             for (var property in options.translations) {
133                 if (options.translations.hasOwnProperty(property)) {
134                     if (this.userOptions.translations[property]) {
135                         this.userOptions.translations[property] = options.translations[property];
136                     }
137                 }
138             }
139         }
140         if (options.placeHolder != undefined) {
141             this.userOptions.placeHolder = options.placeHolder;
142         }
143         if (options.search != undefined) {
144             this.search = options.search;
145         }
146         if (options.remote != undefined && options.remote) {
148            // user defined onInit  function
149             if (options.remote.onInit!= undefined && typeof options.remote.onInit === 'function') {
150                 this.onInit = options.remote.onInit;
151                 this.isInitRemote = true;
152             } 
153             if (options.remote.onInitSize != undefined) {
154                 this.onInitSize = options.remote.onInitSize;
155                 if (this.onInitSize < 3) this.onInitSize = 3;
156             }
157             // user defined remote search function
158             if (options.remote.onSearch != undefined && typeof options.remote.onSearch === 'function') {
159                 this.onSearch = options.remote.onSearch;
160                 this.isSearchRemote = true;
161             }
162         }
164         if (options.stayOpen != undefined) {
165             this.userOptions.stayOpen = options.stayOpen;
166         }
168         if (options.disableSelectAll != undefined) {
169             this.userOptions.disableSelectAll = options.disableSelectAll;
170         }
172         if (options.maxSelect != undefined && !isNaN(options.maxSelect) && options.maxSelect >= 1) {
173             this.maxSelect = options.maxSelect;
174             this.userOptions.disableSelectAll = true;
175         }
177         if (options.maxOptionWidth != undefined && !isNaN(options.maxOptionWidth) && options.maxOptionWidth >= 20) {
178             this.maxOptionWidth = options.maxOptionWidth;
179             this.ulminWidth = options.maxOptionWidth + 60;
180             this.ulmaxWidth = options.maxOptionWidth + 60;
181         }
183         if(options.keepInlineStyles != undefined ) {
184             this.keepInlineStyles = options.keepInlineStyles;
185         }
186         if(options.keepInlineCaretStyles != undefined ) {
187             this.keepInlineCaretStyles = options.keepInlineCaretStyles;
188         }
189         
190     }
192     this.closeOrder = function () {
193         let self = this;
194         if (!self.userOptions.stayOpen) {
195             self.drop.style.visibility = "hidden";
196             if (self.search) {
197                 self.inputBox.value = "";
198                 Array.prototype.slice.call(self.listElements).forEach(function (x) {
199                     x.classList.remove("hide");
200                 });
201             }
202         }
203     }
205     this.getCssArray = function (selector) {
206         // Why inline css ? To protect the button display from foreign css files
207         let cssArray = [];
208         if (selector === ".vsb-main button") {
209             cssArray = [
210                 { "key": "min-width", "value": "120px" },
211                 { "key": "border-radius", "value": "0" },
212                 { "key": "width", "value": "100%" },
213                 { "key": "text-align", "value": "left" },
214                 { "key": "z-index", "value": "1" },
215                 { "key": "color", "value": "#333" },
216                 { "key": "background", "value": "white !important" },
217                 { "key": "border", "value": "1px solid #999 !important" },
218                 { "key": "line-height", "value": "20px" },
219                 { "key": "font-size", "value": "14px" },
220                 { "key": "padding", "value": "6px 12px" }
221             ]
222         }
224         return cssArrayToString(cssArray);
226         function cssArrayToString(cssList) {
227             let list = "";
228             cssList.forEach(function (x) {
229                 list += x.key + ":" + x.value + ";";
230             });
231             return list;
232         }
233     }
235     this.init = function () {
236         let self = this;
237         if (self.isInitRemote) {
238             self.onInit("",self.onInitSize)
239                 .then(function (data) {
240                     self.buildSelect(data);
241                     self.createTree();
242                 });
243         } else {
244             self.createTree();
245         }
246     }
248     this.getResult = function () {
249         let self = this;
250         let result = [];
251         let collection = self.root.querySelectorAll("option");
252         collection.forEach(function (x) {
253             if (x.selected) {
254                 result.push(x.value);
255             }
256         });
257         return result;
258     }
260     this.createTree = function () {
262         this.rootToken = self.domSelector.replace(/[^A-Za-z0-9]+/, "")
263         this.root.style.display = "none";
264         let already = document.getElementById("btn-group-" + this.rootToken);
265         if (already) {
266             already.remove();
267         }
268         this.main = document.createElement("div");
269         this.root.parentNode.insertBefore(this.main, this.root.nextSibling);
270         this.main.classList.add("vsb-main");
271         this.main.setAttribute("id", "btn-group-" + this.rootToken);
272         this.main.style.marginLeft = this.main.style.marginLeft;
273         if (self.userOptions.stayOpen) {
274             this.main.style.minHeight = (this.userOptions.maxHeight + 10) + "px";
275         }
277         if (self.userOptions.stayOpen) {
278             this.button = document.createElement("div");
279         } else {
280             this.button = document.createElement("button");
281             if(this.keepInlineStyles) {
282                 var cssList = self.getCssArray(".vsb-main button");
283                 this.button.setAttribute("style", cssList);
284             }
285         }
286         this.button.style.maxWidth = this.userOptions.maxWidth + "px";
287         if (this.userOptions.minWidth !== -1) {
288             this.button.style.minWidth = this.userOptions.minWidth + "px";
289         }
291         this.main.appendChild(this.button);
292         this.title = document.createElement("span");
293         this.button.appendChild(this.title);
294         this.title.classList.add("title");
295         let caret = document.createElement("span");
296         this.button.appendChild(caret);
298         caret.classList.add("caret");
299         if(this.keepInlineCaretStyles) {
300             caret.style.position = "absolute";
301             caret.style.right = "8px";
302             caret.style.marginTop = "8px";
303         }
305         if (self.userOptions.stayOpen) {
306             caret.style.display = "none";
307             this.title.style.paddingLeft = "20px";
308             this.title.style.fontStyle = "italic";
309             this.title.style.verticalAlign = "20%";
310         }
312         this.drop = document.createElement("div");
313         this.main.appendChild(this.drop);
314         this.drop.classList.add("vsb-menu");
315         this.drop.style.zIndex = 2000 - this.instanceOffset;
316         this.ul = document.createElement("ul");
317         this.drop.appendChild(this.ul);
319         this.ul.style.maxHeight = this.userOptions.maxHeight + "px";
320         this.ul.style.minWidth = this.ulminWidth + "px";
321         this.ul.style.maxWidth = this.ulmaxWidth + "px";
322         this.ul.style.minHeight = this.ulminHeight + "px";
323         if (this.isMultiple) {
324             this.ul.classList.add("multi");
325             if (!self.userOptions.disableSelectAll) {
326                 let selectAll = document.createElement("option");
327                 selectAll.setAttribute("value", 'all');
328                 selectAll.innerText = self.userOptions.translations.selectAll;
329                 this.root.insertBefore(selectAll, (this.root.hasChildNodes())
330                     ? this.root.childNodes[0]
331                     : null);
332             }
333         }
334         let selectedTexts = ""
335         let sep = "";
336         let nrActives = 0;
338         if (this.search) {
339             this.searchZone = document.createElement("div");
340             this.ul.appendChild(this.searchZone);
341             this.searchZone.classList.add("vsb-js-search-zone");
342             this.searchZone.style.zIndex = 2001 - this.instanceOffset;
343             this.inputBox = document.createElement("input");
344             this.searchZone.appendChild(this.inputBox);
345             this.inputBox.setAttribute("type", "text");
346             this.inputBox.setAttribute("id", "search_" + this.rootToken);
347             if (this.maxOptionWidth < Infinity) {
348                 this.searchZone.style.maxWidth = self.maxOptionWidth + 30 + "px";
349                 this.inputBox.style.maxWidth = self.maxOptionWidth + 30 + "px";
350             }
352             var para = document.createElement("p");
353             this.ul.appendChild(para);
354             para.style.fontSize = "12px";
355             para.innerHTML = "&nbsp;";
356             this.ul.addEventListener("scroll", function (e) {
357                 var y = this.scrollTop;
358                 self.searchZone.parentNode.style.top = y + "px";
359             });
360         }
362         this.options = document.querySelectorAll(this.domSelector + " > option");
363         Array.prototype.slice.call(this.options).forEach(function (x) {
364             let text = x.textContent;
365             let value = x.value;
366             let originalAttrs;
367             if (x.hasAttributes()) {
368                 originalAttrs = Array.prototype.slice.call(x.attributes)
369                     .filter(function (a) {
370                         return self.forbidenAttributes.indexOf(a.name) === -1
371                     });
372             }
373             let classes = x.getAttribute("class");
374             if (classes) {
375                 classes = classes
376                     .split(" ")
377                     .filter(function (c) {
378                         return self.forbidenClasses.indexOf(c) === -1
379                     });
380             } else {
381                 classes = [];
382             }
383             let li = document.createElement("li");
384             let isSelected = x.hasAttribute("selected");
385             let isDisabled = x.hasAttribute("disabled");
387             self.ul.appendChild(li);
388             li.setAttribute("data-value", value);
389             li.setAttribute("data-text", text);
391             if (originalAttrs !== undefined) {
392                 originalAttrs.forEach(function (a) {
393                     li.setAttribute(a.name, a.value);
394                 });
395             }
397             classes.forEach(function (x) {
398                 li.classList.add(x);
399             });
401             if (self.maxOptionWidth < Infinity) {
402                 li.classList.add("short");
403                 li.style.maxWidth = self.maxOptionWidth + "px";
404             }
406             if (isSelected) {
407                 nrActives++;
408                 selectedTexts += sep + text;
409                 sep = self.userOptions.buttonItemsSeparator;
410                 li.classList.add("active");
411                 if (!self.isMultiple) {
412                     self.title.textContent = text;
413                     if (classes.length != 0) {
414                         classes.forEach(function (x) {
415                             self.title.classList.add(x);
416                         });
417                     }
418                 }
419             }
420             if (isDisabled) {
421                 li.classList.add("disabled");
422             }
423             li.appendChild(document.createTextNode(" " + text));
424         });
426         if (document.querySelector(self.domSelector + ' optgroup') !== null) {
427             self.isOptgroups = true;
428             self.options = document.querySelectorAll(self.domSelector + " option");
429             let groups = document.querySelectorAll(self.domSelector + ' optgroup');
430             Array.prototype.slice.call(groups).forEach(function (group) {
431                 let groupOptions = group.querySelectorAll('option');
432                 let li = document.createElement("li");
433                 let span = document.createElement("span");
434                 let iCheck = document.createElement("i");
435                 let labelElement = document.createElement("b");
436                 let dataWay = group.getAttribute("data-way");
437                 if (!dataWay) dataWay = "closed";
438                 if (!dataWay || (dataWay !== "closed" && dataWay !== "open")) dataWay = "closed";
439                 li.appendChild(span);
440                 li.appendChild(iCheck);
441                 self.ul.appendChild(li);
442                 li.classList.add('grouped-option');
443                 li.classList.add(dataWay);
444                 self.currentOptgroup++;
445                 let optId = self.rootToken + "-opt-" + self.currentOptgroup;
446                 li.id = optId;
447                 li.appendChild(labelElement);
448                 labelElement.appendChild(document.createTextNode(group.label));
449                 li.setAttribute("data-text", group.label);
450                 self.ul.appendChild(li);
452                 Array.prototype.slice.call(groupOptions).forEach(function (x) {
453                     let text = x.textContent;
454                     let value = x.value;
455                     let classes = x.getAttribute("class");
456                     if (classes) {
457                         classes = classes.split(" ");
458                     }
459                     else {
460                         classes = [];
461                     }
462                     classes.push(dataWay);
463                     let li = document.createElement("li");
464                     let isSelected = x.hasAttribute("selected");
465                     self.ul.appendChild(li);
466                     li.setAttribute("data-value", value);
467                     li.setAttribute("data-text", text);
468                     li.setAttribute("data-parent", optId);
469                     if (classes.length != 0) {
470                         classes.forEach(function (x) {
471                             li.classList.add(x);
472                         });
473                     }
474                     if (isSelected) {
475                         nrActives++;
476                         selectedTexts += sep + text;
477                         sep = self.userOptions.buttonItemsSeparator;
478                         li.classList.add("active");
479                         if (!self.isMultiple) {
480                             self.title.textContent = text;
481                             if (classes.length != 0) {
482                                 classes.forEach(function (x) {
483                                     self.title.classList.add(x);
484                                 });
485                             }
486                         }
487                     }
488                     li.appendChild(document.createTextNode(text));
489                 })
490             })
491         }
493         let optionsLength = self.options.length - Number(!self.userOptions.disableSelectAll);
495         if (optionsLength == nrActives) { // Bastoune idea to preserve the placeholder
496             let wordForAll = self.userOptions.translations.all;
497             selectedTexts = wordForAll;
498         } else if (self.multipleSize != -1) {
499             if (nrActives > self.multipleSize) {
500                 let wordForItems = nrActives === 1 ? self.userOptions.translations.item : self.userOptions.translations.items;
501                 selectedTexts = nrActives + " " + wordForItems;
502             }
503         }
504         if (self.isMultiple) {
505             self.title.innerHTML = selectedTexts;
506         }
507         if (self.userOptions.placeHolder != "" && self.title.textContent == "") {
508             self.title.textContent = self.userOptions.placeHolder;
509         }
510         self.listElements = self.drop.querySelectorAll("li:not(.grouped-option)");
511         if (self.search) {
512             self.inputBox.addEventListener("keyup", function (e) {
513                 let searchValue = e.target.value.toUpperCase();
514                 let searchValueLength = searchValue.length;
515                 let nrFound = 0;
516                 let nrChecked = 0;
517                 let selectAll = null;
518                 if (self.isSearchRemote) {
519                     if (searchValueLength == 0) {
520                         self.remoteSearchIntegrate(null);
521                     } else if (searchValueLength >= 3) {
522                         self.onSearch(searchValue)
523                             .then(function (data) {
524                                 self.remoteSearchIntegrate(data);
525                             });
526                     }
527                 } else {
528                     if (searchValueLength < 3) {
529                         Array.prototype.slice.call(self.listElements).forEach(function (x) {
530                             if (x.getAttribute('data-value') === 'all') {
531                                 selectAll = x;
532                             } else {
533                                 x.classList.remove("hidden-search");
534                                 nrFound++;
535                                 nrChecked += x.classList.contains('active');
536                             }
537                         });
538                     } else {
539                         Array.prototype.slice.call(self.listElements).forEach(function (x) {
540                             if (x.getAttribute('data-value') !== 'all') {
541                                 let text = x.getAttribute("data-text").toUpperCase();
542                                 if (text.indexOf(searchValue) === -1 && x.getAttribute('data-value') !== 'all') {
543                                     x.classList.add("hidden-search");
544                                 } else {
545                                     nrFound++;
546                                     x.classList.remove("hidden-search");
547                                     nrChecked += x.classList.contains('active');
548                                 }
549                             } else {
550                                 selectAll = x;
551                             }
552                         });
553                     }
554                     if (selectAll) {
555                         if (nrFound === 0) {
556                             selectAll.classList.add('disabled');
557                         } else {
558                             selectAll.classList.remove('disabled');
559                         }
560                         if (nrChecked !== nrFound) {
561                             selectAll.classList.remove("active");
562                             selectAll.innerText = self.userOptions.translations.selectAll;
563                             selectAll.setAttribute('data-selected', 'false')
564                         } else {
565                             selectAll.classList.add("active");
566                             selectAll.innerText = self.userOptions.translations.clearAll;
567                             selectAll.setAttribute('data-selected', 'true')
568                         }
569                     }
570                 }
571             }); 
572         }
574         if (self.userOptions.stayOpen) {
575             self.drop.style.visibility = "visible";
576             self.drop.style.boxShadow = "none";
577             self.drop.style.minHeight = (this.userOptions.maxHeight + 10) + "px";
578             self.drop.style.position = "relative";
579             self.drop.style.left = "0px";
580             self.drop.style.top = "0px";
581             self.button.style.border = "none";
582         } else {
583             this.main.addEventListener("click", function (e) {
584                 if (self.isDisabled) return;
585                 self.drop.style.visibility = "visible";
586                 document.addEventListener("click", docListener);
587                 e.preventDefault();
588                 e.stopPropagation();
589                 if (!self.userOptions.stayOpen) {
590                     VSBoxCounter.closeAllButMe(self.instanceOffset);
591                 }
592             });
593         }
595         this.drop.addEventListener("click", function (e) {
596             if (self.isDisabled) return;
597             if (e.target.tagName === 'INPUT') return;
598             let isShowHideCommand = e.target.tagName === 'SPAN';
599             let isCheckCommand = e.target.tagName === 'I';
600             let liClicked = e.target.parentElement;
601             if (!liClicked.hasAttribute("data-value")) {
602                 if (liClicked.classList.contains("grouped-option")) {
603                     if (!isShowHideCommand && !isCheckCommand) return;
604                     let oldClass, newClass;
605                     if (isCheckCommand) { // check or uncheck children
606                         self.checkUncheckFromParent(liClicked);
607                     } else { //open or close
608                         if (liClicked.classList.contains("open")) {
609                             oldClass = "open"
610                             newClass = "closed"
611                         } else {
612                             oldClass = "closed"
613                             newClass = "open"
614                         }
615                         liClicked.classList.remove(oldClass);
616                         liClicked.classList.add(newClass);
617                         let theChildren = self.drop.querySelectorAll("[data-parent='" + liClicked.id + "']");
618                         theChildren.forEach(function (x) {
619                             x.classList.remove(oldClass);
620                             x.classList.add(newClass);
621                         })
622                     }
623                     return;
624                 }
625             }
626             let choiceValue = e.target.getAttribute("data-value");
627             let choiceText = e.target.getAttribute("data-text");
628             let className = e.target.getAttribute("class");
630             if (className && className.indexOf("disabled") != -1) {
631                 return;
632             }
634             if (className && className.indexOf("overflow") != -1) {
635                 return;
636             }
638             if (choiceValue === 'all') {
639                 if (e.target.hasAttribute('data-selected')
640                     && e.target.getAttribute('data-selected') === 'true') {
641                     self.setValue('none')
642                 } else {
643                     self.setValue('all');
644                 }
645                 return;
646             }
648             if (!self.isMultiple) {
649                 self.root.value = choiceValue;
650                 self.title.textContent = choiceText;
651                 if (className) {
652                     self.title.setAttribute("class", className + " title");
653                 } else {
654                     self.title.setAttribute("class", "title");
655                 }
656                 Array.prototype.slice.call(self.listElements).forEach(function (x) {
657                     x.classList.remove("active");
658                 });
659                 if (choiceText != "") {
660                     e.target.classList.add("active");
661                 }
662                 self.privateSendChange();
663                 if (!self.userOptions.stayOpen) {
664                     docListener();
665                 }
666             } else {
667                 let wasActive = false;
668                 if (className) {
669                     wasActive = className.indexOf("active") != -1;
670                 }
671                 if (wasActive) {
672                     e.target.classList.remove("active");
673                 } else {
674                     e.target.classList.add("active");
675                 }
676                 if (e.target.hasAttribute("data-parent")) {
677                     self.checkUncheckFromChild(e.target);
678                 }
680                 let selectedTexts = ""
681                 let sep = "";
682                 let nrActives = 0;
683                 let nrAll = 0;
684                 for (let i = 0; i < self.options.length; i++) {
685                     nrAll++;
686                     if (self.options[i].value == choiceValue) {
687                         self.options[i].selected = !wasActive;
688                     }
689                     if (self.options[i].selected) {
690                         nrActives++;
691                         selectedTexts += sep + self.options[i].textContent;
692                         sep = self.userOptions.buttonItemsSeparator;
693                     }
694                 }
695                 if (nrAll == nrActives - Number(!self.userOptions.disableSelectAll)) {
696                     let wordForAll = self.userOptions.translations.all;
697                     selectedTexts = wordForAll;
698                 } else if (self.multipleSize != -1) {
699                     if (nrActives > self.multipleSize) {
700                         let wordForItems = nrActives === 1 ? self.userOptions.translations.item : self.userOptions.translations.items;
701                         selectedTexts = nrActives + " " + wordForItems;
702                     }
703                 }
704                 self.title.textContent = selectedTexts;
705                 self.checkSelectMax(nrActives);
706                 self.checkUncheckAll();
707                 self.privateSendChange();
708             }
709             e.preventDefault();
710             e.stopPropagation();
711             if (self.userOptions.placeHolder != "" && self.title.textContent == "") {
712                 self.title.textContent = self.userOptions.placeHolder;
713             }
714         });
715         function docListener() {
716             document.removeEventListener("click", docListener);
717             self.drop.style.visibility = "hidden";
718             if (self.search) {
719                 self.inputBox.value = "";
720                 Array.prototype.slice.call(self.listElements).forEach(function (x) {
721                     x.classList.remove("hidden-search");
722                 });
723             }
724         }
725     }
726     this.init();
727     this.checkUncheckAll();
730 vanillaSelectBox.prototype.buildSelect = function (data) {
731     let self = this;
732     if(data == null || data.length < 1) return;
733     if(!self.isOptgroups){
734         self.isOptgroups = data[0].parent != undefined && data[0].parent != "";
735     }
736   
737     if(self.isOptgroups){
738         let groups = {};
739         data = data.filter(function(x){
740             return x.parent != undefined && x.parent != "";
741         });
742     
743         data.forEach(function (x) {
744             if(!groups[x.parent]){
745                 groups[x.parent] = true;
746             }
747         });
748         for (let group in groups) {
749             let anOptgroup = document.createElement("optgroup");
750             anOptgroup.setAttribute("label", group);
751             
752             options = data.filter(function(x){
753                 return x.parent == group;
754             });
755             options.forEach(function (x) {
756                 let anOption = document.createElement("option");
757                 anOption.value = x.value;
758                 anOption.text = x.text;
759                 if(x.selected){
760                     anOption.setAttribute("selected",true)
761                 }
762                 anOptgroup.appendChild(anOption);
763             });
764             self.root.appendChild(anOptgroup);
765         }
766     }else{
767         data.forEach(function (x) {
768             let anOption = document.createElement("option");
769             anOption.value = x.value;
770             anOption.text = x.text;
771             if(x.selected){
772                 anOption.setAttribute("selected",true)
773             }
774             self.root.appendChild(anOption);
775         });
776     }
779 vanillaSelectBox.prototype.remoteSearchIntegrate = function (data) {
780     let self = this;
782     if (data == null || data.length == 0) {
783         let dataChecked = self.optionsCheckedToData();
784         if(dataChecked)
785             data = dataChecked.slice(0);
786         self.remoteSearchIntegrateIt(data);
787     } else {
788         let dataChecked = self.optionsCheckedToData();
789         if (dataChecked.length > 0){
790             for (var i = data.length - 1; i >= 0; i--) {
791                 if(dataChecked.indexOf(data[i].id) !=-1){
792                     data.slice(i,1);
793                 }
794             }
795         }
796         data = data.concat(dataChecked);
798         self.remoteSearchIntegrateIt(data);
799     }
802 vanillaSelectBox.prototype.optionsCheckedToData = function () {
803     let self = this;
804     let dataChecked = [];
805     let treeOptions = self.ul.querySelectorAll("li.active:not(.grouped-option)");
806     let keepParents = {};
807         if (treeOptions) {
808             Array.prototype.slice.call(treeOptions).forEach(function (x) {
809                 let oneData = {"value":x.getAttribute("data-value"),"text":x.getAttribute("data-text"),"selected":true};
810                 if(oneData.value !== "all"){
811                     if(self.isOptgroups){
812                         let parentId = x.getAttribute("data-parent");
813                         if(keepParents[parentId]!=undefined){
814                             oneData.parent = keepParents[parentId];
815                         }else{
816                             let parentPtr = self.ul.querySelector("#"+parentId);
817                             let parentName = parentPtr.getAttribute("data-text");
818                             keepParents[parentId] = parentName;
819                             oneData.parent = parentName;
820                         }
821                     }
822                     dataChecked.push(oneData);
823                 }
824             });
825         }
826         return dataChecked;
829 vanillaSelectBox.prototype.removeOptionsNotChecked = function (data) {
830     let self = this;
831     let minimumSize = self.onInitSize;
832     let newSearchSize = data == null ? 0 : data.length;
833     let presentSize = self.root.length;
834     if (presentSize + newSearchSize > minimumSize) {
835         let maxToRemove = presentSize + newSearchSize - minimumSize - 1;
836         let removed = 0;
837         for (var i = self.root.length - 1; i >= 0; i--) {
838             if (self.root.options[i].selected == false) {
839                 if (removed <= maxToRemove) {
840                     removed++;
841                     self.root.remove(i);
842                 }
843             }
844         }
845     }
848 vanillaSelectBox.prototype.changeTree = function (data, options) {
849     let self = this;
850     self.empty();
851     self.remoteSearchIntegrateIt(data);
852     if (options && options.onSearch) {
853         if (typeof options.onSearch === 'function') {
854             self.onSearch = options.onSearch;
855             self.isSearchRemote = true;
856         }
857     }
858     self.listElements = this.drop.querySelectorAll("li:not(.grouped-option)");
861 vanillaSelectBox.prototype.remoteSearchIntegrateIt = function (data) {
862     let self = this;
863     if (data == null || data.length == 0) return;
864     while(self.root.firstChild)
865     self.root.removeChild(self.root.firstChild);
866     
867     self.buildSelect(data);
868     self.reloadTree();
871 vanillaSelectBox.prototype.reloadTree = function () {
872     let self = this;
873     let lis = self.ul.querySelectorAll("li");
874     if (lis != null) {
875         for (var i = lis.length - 1; i >= 0; i--) {
876             if (lis[i].getAttribute('data-value') !== 'all') {
877                 self.ul.removeChild(lis[i]);
878             }
879         }
880     }
882     let selectedTexts = ""
883     let sep = "";
884     let nrActives = 0;
885     let nrAll = 0;
887     if (self.isOptgroups) {
888         if (document.querySelector(self.domSelector + ' optgroup') !== null) {
889             self.options = document.querySelectorAll(this.domSelector + " option");
890             let groups = document.querySelectorAll(this.domSelector + ' optgroup');
891             Array.prototype.slice.call(groups).forEach(function (group) {
892                 let groupOptions = group.querySelectorAll('option');
893                 let li = document.createElement("li");
894                 let span = document.createElement("span");
895                 let iCheck = document.createElement("i");
896                 let labelElement = document.createElement("b");
897                 let dataWay = group.getAttribute("data-way");
898                 if (!dataWay) dataWay = "closed";
899                 if (!dataWay || (dataWay !== "closed" && dataWay !== "open")) dataWay = "closed";
900                 li.appendChild(span);
901                 li.appendChild(iCheck);
902                 self.ul.appendChild(li);
903                 li.classList.add('grouped-option');
904                 li.classList.add(dataWay);
905                 self.currentOptgroup++;
906                 let optId = self.rootToken + "-opt-" + self.currentOptgroup;
907                 li.id = optId;
908                 li.appendChild(labelElement);
909                 labelElement.appendChild(document.createTextNode(group.label));
910                 li.setAttribute("data-text", group.label);
911                 self.ul.appendChild(li);
913                 Array.prototype.slice.call(groupOptions).forEach(function (x) {
914                     let text = x.textContent;
915                     let value = x.value;
916                     let classes = x.getAttribute("class");
917                     if (classes) {
918                         classes = classes.split(" ");
919                     }
920                     else {
921                         classes = [];
922                     }
923                     classes.push(dataWay);
924                     let li = document.createElement("li");
925                     let isSelected = x.hasAttribute("selected");
926                     self.ul.appendChild(li);
927                     li.setAttribute("data-value", value);
928                     li.setAttribute("data-text", text);
929                     li.setAttribute("data-parent", optId);
930                     if (classes.length != 0) {
931                         classes.forEach(function (x) {
932                             li.classList.add(x);
933                         });
934                     }
935                     if (isSelected) {
936                         nrActives++;
937                         selectedTexts += sep + text;
938                         sep = self.userOptions.buttonItemsSeparator;
939                         li.classList.add("active");
940                         if (!self.isMultiple) {
941                             self.title.textContent = text;
942                             if (classes.length != 0) {
943                                 classes.forEach(function (x) {
944                                     self.title.classList.add(x);
945                                 });
946                             }
947                         }
948                     }
949                     li.appendChild(document.createTextNode(text));
950                 })
951             })
952         }
953         self.listElements = this.drop.querySelectorAll("li:not(.grouped-option)");
954     } else {
955         self.options = self.root.querySelectorAll("option");
956         Array.prototype.slice.call(self.options).forEach(function (x) {
957             let text = x.textContent;
958             let value = x.value;
959             if (value != "all") {
960                 let originalAttrs;
961                 if (x.hasAttributes()) {
962                     originalAttrs = Array.prototype.slice.call(x.attributes)
963                         .filter(function (a) {
964                             return self.forbidenAttributes.indexOf(a.name) === -1
965                         });
966                 }
967                 let classes = x.getAttribute("class");
968                 if (classes) {
969                     classes = classes
970                         .split(" ")
971                         .filter(function (c) {
972                             return self.forbidenClasses.indexOf(c) === -1
973                         });
974                 } else {
975                     classes = [];
976                 }
977                 let li = document.createElement("li");
978                 let isSelected = x.hasAttribute("selected");
980                 let isDisabled = x.disabled;
982                 self.ul.appendChild(li);
983                 li.setAttribute("data-value", value);
984                 li.setAttribute("data-text", text);
986                 if (originalAttrs !== undefined) {
987                     originalAttrs.forEach(function (a) {
988                         li.setAttribute(a.name, a.value);
989                     });
990                 }
992                 classes.forEach(function (x) {
993                     li.classList.add(x);
994                 });
996                 if (self.maxOptionWidth < Infinity) {
997                     li.classList.add("short");
998                     li.style.maxWidth = self.maxOptionWidth + "px";
999                 }
1001                 if (isSelected) {
1002                     nrActives++;
1003                     selectedTexts += sep + text;
1004                     sep = self.userOptions.buttonItemsSeparator;
1005                     li.classList.add("active");
1006                     if (!self.isMultiple) {
1007                         self.title.textContent = text;
1008                         if (classes.length != 0) {
1009                             classes.forEach(function (x) {
1010                                 self.title.classList.add(x);
1011                             });
1012                         }
1013                     }
1014                 }
1015                 if (isDisabled) {
1016                     li.classList.add("disabled");
1017                 }
1018                 li.appendChild(document.createTextNode(" " + text));
1019             }
1020         });
1021     }
1025 vanillaSelectBox.prototype.disableItems = function (values) {
1026     let self = this;
1027     let foundValues = [];
1028     if (vanillaSelectBox_type(values) == "string") {
1029         values = values.split(",");
1030     }
1032     if (vanillaSelectBox_type(values) == "array") {
1033         Array.prototype.slice.call(self.options).forEach(function (x) {
1034             if (values.indexOf(x.value) != -1) {
1035                 foundValues.push(x.value);
1036                 x.setAttribute("disabled", "");
1037             }
1038         });
1039     }
1040     Array.prototype.slice.call(self.listElements).forEach(function (x) {
1041         let val = x.getAttribute("data-value");
1042         if (foundValues.indexOf(val) != -1) {
1043             x.classList.add("disabled");
1044         }
1045     });
1048 vanillaSelectBox.prototype.enableItems = function (values) {
1049     let self = this;
1050     let foundValues = [];
1051     if (vanillaSelectBox_type(values) == "string") {
1052         values = values.split(",");
1053     }
1055     if (vanillaSelectBox_type(values) == "array") {
1056         Array.prototype.slice.call(self.options).forEach(function (x) {
1057             if (values.indexOf(x.value) != -1) {
1058                 foundValues.push(x.value);
1059                 x.removeAttribute("disabled");
1060             }
1061         });
1062     }
1064     Array.prototype.slice.call(self.listElements).forEach(function (x) {
1065         if (foundValues.indexOf(x.getAttribute("data-value")) != -1) {
1066             x.classList.remove("disabled");
1067         }
1068     });
1071 vanillaSelectBox.prototype.checkSelectMax = function (nrActives) {
1072     let self = this;
1073     if (self.maxSelect == Infinity || !self.isMultiple) return;
1074     if (self.maxSelect <= nrActives) {
1075         Array.prototype.slice.call(self.listElements).forEach(function (x) {
1076             if (x.hasAttribute('data-value')) {
1077                 if (!x.classList.contains('disabled') && !x.classList.contains('active')) {
1078                     x.classList.add("overflow");
1079                 }
1080             }
1081         });
1082     } else {
1083         Array.prototype.slice.call(self.listElements).forEach(function (x) {
1084             if (x.classList.contains('overflow')) {
1085                 x.classList.remove("overflow");
1086             }
1087         });
1088     }
1091 vanillaSelectBox.prototype.checkUncheckFromChild = function (liClicked) {
1092     let self = this;
1093     let parentId = liClicked.getAttribute('data-parent');
1094     let parentLi = document.getElementById(parentId);
1095     if (!self.isMultiple) return;
1096     let listElements = self.drop.querySelectorAll("li");
1097     let childrenElements = Array.prototype.slice.call(listElements).filter(function (el) {
1098         return el.hasAttribute("data-parent") && el.getAttribute('data-parent') == parentId  && !el.classList.contains('hidden-search') ;
1099     });
1100     let nrChecked = 0;
1101     let nrCheckable = childrenElements.length;
1102     if (nrCheckable == 0) return;
1103     childrenElements.forEach(function (el) {
1104         if (el.classList.contains('active')) nrChecked++;
1105     });
1106     if (nrChecked === nrCheckable || nrChecked === 0) {
1107         if (nrChecked === 0) {
1108             parentLi.classList.remove("checked");
1109         } else {
1110             parentLi.classList.add("checked");
1111         }
1112     } else {
1113         parentLi.classList.remove("checked");
1114     }
1117 vanillaSelectBox.prototype.checkUncheckFromParent = function (liClicked) {
1118     let self = this;
1119     let parentId = liClicked.id;
1120     if (!self.isMultiple) return;
1121     let listElements = self.drop.querySelectorAll("li");
1122     let childrenElements = Array.prototype.slice.call(listElements).filter(function (el) {
1123         return el.hasAttribute("data-parent") && el.getAttribute('data-parent') == parentId && !el.classList.contains('hidden-search');
1124     });
1125     let nrChecked = 0;
1126     let nrCheckable = childrenElements.length;
1127     if (nrCheckable == 0) return;
1128     childrenElements.forEach(function (el) {
1129         if (el.classList.contains('active')) nrChecked++;
1130     });
1131     if (nrChecked === nrCheckable || nrChecked === 0) {
1132         //check all or uncheckAll : just do the opposite
1133         childrenElements.forEach(function (el) {
1134             var event = document.createEvent('HTMLEvents');
1135             event.initEvent('click', true, false);
1136             el.dispatchEvent(event);
1137         });
1138         if (nrChecked === 0) {
1139             liClicked.classList.add("checked");
1140         } else {
1141             liClicked.classList.remove("checked");
1142         }
1143     } else {
1144         //check all
1145         liClicked.classList.remove("checked");
1146         childrenElements.forEach(function (el) {
1147             if (!el.classList.contains('active')) {
1148                 var event = document.createEvent('HTMLEvents');
1149                 event.initEvent('click', true, false);
1150                 el.dispatchEvent(event);
1151             }
1152         });
1153     }
1156 vanillaSelectBox.prototype.checkUncheckAll = function () {
1157     let self = this;
1158     if (!self.isMultiple) return;
1159     let nrChecked = 0;
1160     let nrCheckable = 0;
1161     let totalAvailableElements = 0;
1162     let checkAllElement = null;
1163     if (self.listElements == null) return;
1164     Array.prototype.slice.call(self.listElements).forEach(function (x) {
1165         if (x.hasAttribute('data-value')) {
1166             if (x.getAttribute('data-value') === 'all') {
1167                 checkAllElement = x;
1168             }
1169             if (x.getAttribute('data-value') !== 'all'
1170                 && !x.classList.contains('hidden-search')
1171                 && !x.classList.contains('disabled')) {
1172                 nrCheckable++;
1173                 nrChecked += x.classList.contains('active');
1174             }
1175             if (x.getAttribute('data-value') !== 'all'
1176                 && !x.classList.contains('disabled')) {
1177                 totalAvailableElements++;
1178             }
1179         }
1180     });
1182     if (checkAllElement) {
1183         if (nrChecked === nrCheckable) {
1184             // check the checkAll checkbox
1185             if (nrChecked === totalAvailableElements) {
1186                 self.title.textContent = self.userOptions.translations.all;
1187             }
1188             checkAllElement.classList.add("active");
1189             checkAllElement.innerText = self.userOptions.translations.clearAll;
1190             checkAllElement.setAttribute('data-selected', 'true')
1191         } else if (nrChecked === 0) {
1192             // uncheck the checkAll checkbox
1193             self.title.textContent = self.userOptions.placeHolder;
1194             checkAllElement.classList.remove("active");
1195             checkAllElement.innerText = self.userOptions.translations.selectAll;
1196             checkAllElement.setAttribute('data-selected', 'false')
1197         }
1198     }
1201 vanillaSelectBox.prototype.setValue = function (values) {
1202     let self = this;
1203     let listElements = self.drop.querySelectorAll("li");
1205     if (values == null || values == undefined || values == "") {
1206         self.empty();
1207     } else {
1208         if (self.isMultiple) {
1209             if (vanillaSelectBox_type(values) == "string") {
1210                 if (values === "all") {
1211                     values = [];
1212                     Array.prototype.slice.call(listElements).forEach(function (x) {
1213                         if (x.hasAttribute('data-value')) {
1214                             let value = x.getAttribute('data-value');
1215                             if (value !== 'all') {
1216                                 if (!x.classList.contains('hidden-search') && !x.classList.contains('disabled')) {
1217                                     values.push(x.getAttribute('data-value'));
1218                                 }
1219                                 // already checked (but hidden by search)
1220                                 if (x.classList.contains('active')) {
1221                                     if (x.classList.contains('hidden-search') || x.classList.contains('disabled')) {
1222                                         values.push(value);
1223                                     }
1224                                 }
1225                             }else{
1226                                 x.classList.add("active");
1227                             }
1228                         } else if (x.classList.contains('grouped-option')) {
1229                             x.classList.add("checked");
1230                         }
1231                     });
1232                 } else if (values === "none") {
1233                     values = [];
1234                     Array.prototype.slice.call(listElements).forEach(function (x) {
1235                         if (x.hasAttribute('data-value')) {
1236                             let value = x.getAttribute('data-value');
1237                             if (value !== 'all') {
1238                                 if (x.classList.contains('active')) {
1239                                     if (x.classList.contains('hidden-search') || x.classList.contains('disabled')) {
1240                                         values.push(value);
1241                                     }
1242                                 }
1243                             }
1244                         } else if (x.classList.contains('grouped-option')) {
1245                             x.classList.remove("checked");
1246                         }
1247                     });
1248                 } else {
1249                     values = values.split(",");
1250                 }
1251             }
1252             let foundValues = [];
1253             if (vanillaSelectBox_type(values) == "array") {
1254                 Array.prototype.slice.call(self.options).forEach(function (x) {
1255                     if (values.indexOf(x.value) !== -1) {
1256                         x.selected = true;
1257                         foundValues.push(x.value);
1258                     } else {
1259                         x.selected = false;
1260                     }
1261                 });
1262                 let selectedTexts = ""
1263                 let sep = "";
1264                 let nrActives = 0;
1265                 let nrAll = 0;
1266                 Array.prototype.slice.call(listElements).forEach(function (x) {
1267                     if (x.value !== 'all') {
1268                         nrAll++;
1269                     }                    
1270                     if (foundValues.indexOf(x.getAttribute("data-value")) != -1) {
1271                         x.classList.add("active");
1272                         nrActives++;
1273                         selectedTexts += sep + x.getAttribute("data-text");
1274                         sep = self.userOptions.buttonItemsSeparator;
1275                     } else {
1276                         x.classList.remove("active");
1277                     }
1278                 });
1279                 if (nrAll == nrActives - Number(!self.userOptions.disableSelectAll)) {
1280                     let wordForAll = self.userOptions.translations.all;
1281                     selectedTexts = wordForAll;
1282                 } else if (self.multipleSize != -1) {
1283                     if (nrActives > self.multipleSize) {
1284                         let wordForItems = nrActives === 1 ? self.userOptions.translations.item : self.userOptions.translations.items;
1285                         selectedTexts = nrActives + " " + wordForItems;
1286                     }
1287                 }
1288                 self.title.textContent = selectedTexts;
1289                 self.privateSendChange();
1290             }
1291             self.checkUncheckAll();
1292         } else {
1293             let found = false;
1294             let text = "";
1295             let classNames = ""
1296             Array.prototype.slice.call(listElements).forEach(function (x) {
1297                 let liVal = x.getAttribute("data-value");
1298                 if (liVal == values) {
1299                     x.classList.add("active");
1300                     found = true;
1301                     text = x.getAttribute("data-text")
1302                 } else {
1303                     x.classList.remove("active");
1304                 }
1305             });
1306             Array.prototype.slice.call(self.options).forEach(function (x) {
1307                 if (x.value == values) {
1308                     x.selected = true;
1309                     className = x.getAttribute("class");
1310                     if (!className) className = "";
1311                 } else {
1312                     x.selected = false;
1313                 }
1314             });
1315             if (found) {
1316                 self.title.textContent = text;
1317                 if (self.userOptions.placeHolder != "" && self.title.textContent == "") {
1318                     self.title.textContent = self.userOptions.placeHolder;
1319                 }
1320                 if (className != "") {
1321                     self.title.setAttribute("class", className + " title");
1322                 } else {
1323                     self.title.setAttribute("class", "title");
1324                 }
1325             }
1326         }
1327     }
1330 vanillaSelectBox.prototype.privateSendChange = function () {
1331     let event = document.createEvent('HTMLEvents');
1332     event.initEvent('change', true, false);
1333     this.root.dispatchEvent(event);
1336 vanillaSelectBox.prototype.empty = function () {
1337     Array.prototype.slice.call(this.listElements).forEach(function (x) {
1338         x.classList.remove("active");
1339     });
1340     let parentElements = this.drop.querySelectorAll("li.grouped-option");
1341     if(parentElements){
1342         Array.prototype.slice.call(parentElements).forEach(function (x) {
1343             x.classList.remove("checked");
1344         });
1345     }
1346     Array.prototype.slice.call(this.options).forEach(function (x) {
1347         x.selected = false;
1348     });
1349     this.title.textContent = "";
1350     if (this.userOptions.placeHolder != "" && this.title.textContent == "") {
1351         this.title.textContent = this.userOptions.placeHolder;
1352     }
1353     this.checkUncheckAll();
1354     this.privateSendChange();
1357 vanillaSelectBox.prototype.destroy = function () {
1358     let already = document.getElementById("btn-group-" + this.rootToken);
1359     if (already) {
1360         VSBoxCounter.remove(this.instanceOffset);
1361         already.remove();
1362         this.root.style.display = "inline-block";
1363     }
1365 vanillaSelectBox.prototype.disable = function () {
1366     this.main.addEventListener("click", function (e) {
1367         e.preventDefault();
1368         e.stopPropagation();
1369     });
1370     let already = document.getElementById("btn-group-" + this.rootToken);
1371     if (already) {
1372         button = already.querySelector("button")
1373         if (button) button.classList.add("disabled");
1374         this.isDisabled = true;
1375     }
1377 vanillaSelectBox.prototype.enable = function () {
1378     let already = document.getElementById("btn-group-" + this.rootToken);
1379     if (already) {
1380         button = already.querySelector("button")
1381         if (button) button.classList.remove("disabled");
1382         this.isDisabled = false;
1383     }
1386 vanillaSelectBox.prototype.showOptions = function () {
1387     console.log(this.userOptions);
1389 // Polyfills for IE
1390 if (!('remove' in Element.prototype)) {
1391     Element.prototype.remove = function () {
1392         if (this.parentNode) {
1393             this.parentNode.removeChild(this);
1394         }
1395     };
1398 function vanillaSelectBox_type(target) {
1399     const computedType = Object.prototype.toString.call(target);
1400     const stripped = computedType.replace("[object ", "").replace("]", "");
1401     const lowercased = stripped.toLowerCase();
1402     return lowercased;