PageSourceSearch

https://adultchildren.org/wp-content/themes/ACA/js/multiselect-dropdown.js?dmcb=1782820810

js adultchildren.org collected 2026-09-24 17:16:14 UTC 7,600 bytes, 224 lines download raw bytes

1var style = document.createElement('style');
2style.setAttribute("id", "multiselect_dropdown_styles");
3style.innerHTML = `
4.multiselect-dropdown{
5  display: inline-block;
6  padding: 2px 5px 0px 5px;
7  border-radius: 4px;
8  border: solid 1px #ced4da;
9  background-color: white;
10  position: relative;
11  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
12  background-repeat: no-repeat;
13  background-position: right .75rem center;
14  background-size: 16px 12px;
15}
16.multiselect-dropdown span.optext, .multiselect-dropdown span.placeholder{
17  margin-right:0.5em; 
18  margin-bottom:2px;
19  padding:1px 0; 
20  border-radius: 4px; 
21  display:inline-block;
22}
23.multiselect-dropdown span.optext{
24  background-color:lightgray;
25  padding:1px 0.75em; 
26}
27.multiselect-dropdown span.optext .optdel {
28  float: right;
29  margin: 0 -6px 1px 5px;
30  font-size: 0.7em;
31  margin-top: 2px;
32  cursor: pointer;
33  color: #666;
34}
35.multiselect-dropdown span.optext .optdel:hover { color: #c66;}
36.multiselect-dropdown span.placeholder{
37  color:#ced4da;
38}
39.multiselect-dropdown-list-wrapper{
40  box-shadow: gray 0 3px 8px;
41  z-index: 100;
42  padding:2px;
43  border-radius: 4px;
44  border: solid 1px #ced4da;
45  display: none;
46  margin: -1px;
47  position: absolute;
48  top:0;
49  left: 0;
50  right: 0;
51  background: white;
52}
53.multiselect-dropdown-list-wrapper .multiselect-dropdown-search{
54  margin-bottom:5px;
55}
56.multiselect-dropdown-list{
57  padding:2px;
58  height: 15rem;
59  overflow-y:auto;
60  overflow-x: hidden;
61}
62.multiselect-dropdown-list::-webkit-scrollbar {
63  width: 6px;
64}
65.multiselect-dropdown-list::-webkit-scrollbar-thumb {
66  background-color: #bec4ca;
67  border-radius:3px;
68}
69
70.multiselect-dropdown-list div{
71  padding: 5px;
72}
73.multiselect-dropdown-list input{
74  height: 1.15em;
75  width: 1.15em;
76  margin-right: 0.35em;  
77}
78.multiselect-dropdown-list div.checked{
79}
80.multiselect-dropdown-list div:hover{
81  background-color: #ced4da;
82}
83.multiselect-dropdown span.maxselected {width:100%;}
84.multiselect-dropdown-all-selector {border-bottom:solid 1px #999;}
85`;
86document.head.appendChild(style);
87
88function MultiselectDropdown(options) {
89	var config = {
90		search: true,
91		height: '15rem',
92		placeholder: 'select',
93		txtSelected: 'selected',
94		txtAll: 'All',
95		txtRemove: 'Remove',
96		txtSearch: 'search',
97		...options
98	};
99	function newEl(tag, attrs) {
100		var e = document.createElement(tag);
101		if (attrs !== undefined) Object.keys(attrs).forEach(k => {
102			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) }
103			else if (k === 'style') {
104				Object.keys(attrs[k]).forEach(ks => {
105					e.style[ks] = attrs[k][ks];
106				});
107			}
108			else if (k === 'text') { attrs[k] === '' ? e.innerHTML = ' ' : e.innerText = attrs[k] }
109			else e[k] = attrs[k];
110		});
111		return e;
112	}
113
114
115	document.querySelectorAll("select[multiple]").forEach((el, k) => {
116
117		var div = newEl('div', { class: 'multiselect-dropdown', style: { width: config.style?.width ?? el.clientWidth + 'px', padding: config.style?.padding ?? '' } });
118		el.style.display = 'none';
119		el.parentNode.insertBefore(div, el.nextSibling);
120		var listWrap = newEl('div', { class: 'multiselect-dropdown-list-wrapper' });
121		var list = newEl('div', { class: 'multiselect-dropdown-list', style: { height: config.height } });
122		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 });
123		listWrap.appendChild(search);
124		div.appendChild(listWrap);
125		listWrap.appendChild(list);
126
127		el.loadOptions = () => {
128			list.innerHTML = '';
129
130			if (el.attributes['multiselect-select-all']?.value == 'true') {
131				var op = newEl('div', { class: 'multiselect-dropdown-all-selector' })
132				var ic = newEl('input', { type: 'checkbox' });
133				op.appendChild(ic);
134				op.appendChild(newEl('label', { text: config.txtAll }));
135
136				op.addEventListener('click', () => {
137					op.classList.toggle('checked');
138					op.querySelector("input").checked = !op.querySelector("input").checked;
139
140					var ch = op.querySelector("input").checked;
141					list.querySelectorAll(":scope > div:not(.multiselect-dropdown-all-selector)")
142						.forEach(i => { if (i.style.display !== 'none') { i.querySelector("input").checked = ch; i.optEl.selected = ch } });
143
144					el.dispatchEvent(new Event('change'));
145				});
146				ic.addEventListener('click', (ev) => {
147					ic.checked = !ic.checked;
148				});
149				el.addEventListener('change', (ev) => {
150					let itms = Array.from(list.querySelectorAll(":scope > div:not(.multiselect-dropdown-all-selector)")).filter(e => e.style.display !== 'none')
151					let existsNotSelected = itms.find(i => !i.querySelector("input").checked);
152					if (ic.checked && existsNotSelected) ic.checked = false;
153					else if (ic.checked == false && existsNotSelected === undefined) ic.checked = true;
154				});
155
156				list.appendChild(op);
157			}
158
159			Array.from(el.options).map(o => {
160				var op = newEl('div', { class: o.selected ? 'checked' : '', optEl: o })
161				var ic = newEl('input', { type: 'checkbox', checked: o.selected });
162				op.appendChild(ic);
163				op.appendChild(newEl('label', { text: o.text }));
164
165				op.addEventListener('click', () => {
166					op.classList.toggle('checked');
167					op.querySelector("input").checked = !op.querySelector("input").checked;
168					op.optEl.selected = !!!op.optEl.selected;
169					el.dispatchEvent(new Event('change'));
170				});
171				ic.addEventListener('click', (ev) => {
172					ic.checked = !ic.checked;
173				});
174				o.listitemEl = op;
175				list.appendChild(op);
176			});
177			div.listEl = listWrap;
178
179			div.refresh = () => {
180				div.querySelectorAll('span.optext, span.placeholder').forEach(t => div.removeChild(t));
181				var sels = Array.from(el.selectedOptions);
182				if (sels.length > (el.attributes['multiselect-max-items']?.value ?? 5)) {
183					div.appendChild(newEl('span', { class: ['optext', 'maxselected'], text: sels.length + ' ' + config.txtSelected }));
184				}
185				else {
186					sels.map(x => {
187						var c = newEl('span', { class: 'optext', text: x.text, srcOption: x });
188						if ((el.attributes['multiselect-hide-x']?.value !== 'true'))
189							c.appendChild(newEl('span', { class: 'optdel', text: 'x', title: config.txtRemove, onclick: (ev) => { c.srcOption.listitemEl.dispatchEvent(new Event('click')); div.refresh(); ev.stopPropagation(); } }));
190
191						div.appendChild(c);
192					});
193				}
194				if (0 == el.selectedOptions.length) div.appendChild(newEl('span', { class: 'placeholder', text: el.attributes['placeholder']?.value ?? config.placeholder }));
195			};
196			div.refresh();
197		}
198		el.loadOptions();
199
200		search.addEventListener('input', () => {
201			list.querySelectorAll(":scope div:not(.multiselect-dropdown-all-selector)").forEach(d => {
202				var txt = d.querySelector("label").innerText.toUpperCase();
203				d.style.display = txt.includes(search.value.toUpperCase()) ? 'block' : 'none';
204			});
205		});
206
207		div.addEventListener('click', () => {
208			div.listEl.style.display = 'block';
209			search.focus();
210			search.select();
211		});
212
213		document.addEventListener('click', function (event) {
214			if (!div.contains(event.target)) {
215				listWrap.style.display = 'none';
216				div.refresh();
217			}
218		});
219	});
220}
221
222window.addEventListener('load', () => {
223	MultiselectDropdown(window.MultiselectDropdownOptions);
224});

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.