1function MultiselectDropdown(options){ 2 var config={ 3 search:true, 4 height:'15rem', 5 placeholder:'select', 6 txtSelected:'selected', 7 txtAll:'All', 8 txtRemove: 'Remove', 9 txtSearch:'search', 10 ...options 11 }; 12 function newEl(tag,attrs){ 13 var e=document.createElement(tag); 14 if(attrs!==undefined) Object.keys(attrs).forEach(k=>{ 15 if(k==='class') { Array.isArray(attrs[k]) ? attrs[k].forEach(o=>o!==''?e.classList.add(o):0) : (attrs[k]!==''?e.classList.add(attrs[k]):0)} 16 else if(k==='style'){ 17 Object.keys(attrs[k]).forEach(ks=>{ 18 e.style[ks]=attrs[k][ks]; 19 }); 20 } 21 else if(k==='text'){attrs[k]===''?e.innerHTML=' ':e.innerText=attrs[k]} 22 else e[k]=attrs[k]; 23 }); 24 return e; 25 } 26 27 28 document.querySelectorAll("select[multiple]").forEach((el,k)=>{ 29 30 var div=newEl('div',{class:'multiselect-dropdown',style:{width:config.style?.width??el.clientWidth+'px',padding:config.style?.padding??''}}); 31 el.style.display='none'; 32 el.parentNode.insertBefore(div,el.nextSibling); 33 var listWrap=newEl('div',{class:'multiselect-dropdown-list-wrapper'}); 34 var list=newEl('div',{class:'multiselect-dropdown-list',style:{height:config.height}}); 35 var search=newEl('input',{class:['multiselect-dropdown-search'].concat([config.searchInput?.class??'form-control']),style:{width:'100%',display:el.attributes['multiselect-search']?.value==='true'?'block':'none'},placeholder:config.txtSearch}); 36 listWrap.appendChild(search); 37 div.appendChild(listWrap); 38 listWrap.appendChild(list); 39 40 el.loadOptions=()=>{ 41 list.innerHTML=''; 42 43 if(el.attributes['multiselect-select-all']?.value=='true'){ 44 var op=newEl('div',{class:'multiselect-dropdown-all-selector'}) 45 var ic=newEl('input',{type:'checkbox'}); 46 op.appendChild(ic); 47 op.appendChild(newEl('label',{text:config.txtAll})); 48 49 op.addEventListener('click',()=>{ 50 op.classList.toggle('checked'); 51 op.querySelector("input").checked=!op.querySelector("input").checked; 52 53 var ch=op.querySelector("input").checked; 54 list.querySelectorAll(":scope > div:not(.multiselect-dropdown-all-selector)") 55 .forEach(i=>{if(i.style.display!=='none'){i.querySelector("input").checked=ch; i.optEl.selected=ch}}); 56 57 el.dispatchEvent(new Event('change')); 58 }); 59 ic.addEventListener('click',(ev)=>{ 60 ic.checked=!ic.checked; 61 }); 62 63 list.appendChild(op); 64 } 65 66 Array.from(el.options).map(o=>{ 67 var op=newEl('div',{class:o.selected?'checked':'',optEl:o}) 68 var ic=newEl('input',{type:'checkbox',checked:o.selected}); 69 op.appendChild(ic); 70 op.appendChild(newEl('label',{text:o.text})); 71 72 op.addEventListener('click',()=>{ 73 op.classList.toggle('checked'); 74 op.querySelector("input").checked=!op.querySelector("input").checked; 75 op.optEl.selected=!!!op.optEl.selected; 76 el.dispatchEvent(new Event('change')); 77 }); 78 ic.addEventListener('click',(ev)=>{ 79 ic.checked=!ic.checked; 80 }); 81 o.listitemEl=op; 82 list.appendChild(op); 83 }); 84 div.listEl=listWrap; 85 86 div.refresh=()=>{ 87 div.querySelectorAll('span.optext, span.placeholder').forEach(t=>div.removeChild(t)); 88 var sels=Array.from(el.selectedOptions); 89 if(sels.length>(el.attributes['multiselect-max-items']?.value??5)){ 90 div.appendChild(newEl('span',{class:['optext','maxselected'],text:sels.length+' '+config.txtSelected})); 91 } 92 else{ 93 sels.map(x=>{ 94 var c=newEl('span',{class:'optext',text:x.text, srcOption: x}); 95 if((el.attributes['multiselect-hide-x']?.value !== 'true')) 96 c.appendChild(newEl('span',{class:'optdel',text:'ð',title:config.txtRemove, onclick:(ev)=>{c.srcOption.listitemEl.dispatchEvent(new Event('click'));div.refresh();ev.stopPropagation();}})); 97 98 div.appendChild(c); 99 }); 100 } 101 if(0==el.selectedOptions.length) div.appendChild(newEl('span',{class:'placeholder',text:el.attributes['placeholder']?.value??config.placeholder})); 102 }; 103 div.refresh(); 104 } 105 el.loadOptions(); 106 107 search.addEventListener('input',()=>{ 108 list.querySelectorAll(":scope div:not(.multiselect-dropdown-all-selector)").forEach(d=>{ 109 var txt=d.querySelector("label").innerText.toUpperCase(); 110 d.style.display=txt.includes(search.value.toUpperCase())?'flex':'none'; 111 }); 112 }); 113 114 div.addEventListener('click',()=>{ 115 div.listEl.style.display='block'; 116 search.focus(); 117 search.select(); 118 }); 119 120 document.addEventListener('click', function(event) { 121 if (!div.contains(event.target)) { 122 listWrap.style.display='none'; 123 div.refresh(); 124 } 125 }); 126 }); 127} 128 129//window.addEventListener('load',()=>{ 130// MultiselectDropdown(window.MultiselectDropdownOptions); 131//});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.