select_multiple.js test

by Laurens Maneschijn

HTML

<hr>Testing an old select_multiple.js I found somewhere...<hr>

<dummyform>
	<fieldset>
		init on demand, so we can see what effect it has:<br>
		<button onclick="document.location.reload();" data-enticon="&#10227;">reload</button>
		<button onclick="SelectMultiple.init();">&#9654; SelectMultiple.init()</button>
		<label>auto init:<input type="checkbox" id="autoinit" data-store></label>
	</fieldset><fieldset>
		manually update all, or trigger change event on all:<br>
		<button onclick="SelectMultiple.update_all();">SelectMultiple.update_all()</button>
		<button onclick="fh.trigger_change_all();">all trigger change</button>
		<label>auto update_all:<input type="checkbox" id="autoupdate" data-store></label>
	</fieldset><fieldset>
		select options:
		<button onclick="fh.selectAll()">all</button>
		<button onclick="fh.selectNone()">none</button>
		<button onclick="fh.selectRandom()">random</button>
	</fieldset>
</dummyform>


<hr> basic multiple select:
<select multiple>
	<option>a</option>
	<option>b</option>
	<option>c</option>
</select>

<hr> normal (not multiple) select:
<select>
	<option></option>
	<option>a</option>
	<option>b</option>
	<option>c</option>
</select>

<hr> select with empty and duplicate values:
<select multiple>
	<option></option>
	<option>a</option>
	<option>a</option>
	<option>b</option>
	<option>b</option>
</select>

<hr> select with optgroups:
<select multiple>
	<option></option>
	<option>a</option>
	<optgroup label="Group A">
		<option>GA a</option>
		<option>GA b</option>
		<option>GA c</option>
	</optgroup>
	<optgroup label="Group B">
		<option>GB a</option>
		<option>GB b</option>
		<option>GB c</option>
	</optgroup>
	<option>x</option>
	<option>y</option>
	<option>z</option>
</select>

SCSS

body.debug {
	select {
		background: #80808010;
		resize: both;
		overflow: auto;
	}
	optgroup {
		background: #40404010;
		border: 1px solid #888;
		border-radius: 4px;																																								
	}
	option {
		/* dont set background, cant see if selected.
		background: #c0c0c020;
		*/
	}
}


dummyform,
form {
	display: block;
	background: #80808020;
	fieldset {
		float: left;
		clear: left;
		margin: 4px;
		padding: 4px;
		background: #80808020;
		border-radius: 4px;
	}
	&::after {
		display: table;
		content: '';
		clear: both;
	}
}

button[data-enticon]::before {
	content: attr(data-enticon);
	display: inline-block;
	font-size: 200%;
	margin: -10px 2px -10px 0;
	vertical-align: middle;
}

JavaScript

// [script type="text/javascript" src="select_multiple.js"][/script]
// javascript:(function(){ let s = document.createElement('script'); s.src = 'select_multiple.js'; (document.head || document.body).appendChild(s); })();

// TODO: document what it does

// TODO maybe not auto-init? that way you can config things before init.
// TODO default selector currently 'select[multiple]' , maybe 'select[multiple].select_multiple' ?
// TODO only show filter when select (or filter) has focus?
// TODO selected values summary? when do we show this? and where? optional?
// TODO if something removes the original select, the search and summary element added here will linger. fix that. see SelectSearchMap and SelectSummaryMap
// TODO handle optgroup (e.g. show/hide group if something/nothing selected in it)
(function(){
	function init_css() {
		let css = `

select[multiple] {
	transition: all 1s;
	min-width: 100px;
	min-height: 20px;
	/* allow room to click empty space without changing selected options: */
	padding-top: 1.5em;
	padding-bottom: 0;
}
select[multiple].focus,
select[multiple]:focus {
	min-width: 50vw !important;
	min-height: 50vh !important;
}
select[multiple]:not(:focus, .focus) optgroup.selected_0 ,
select[multiple]:not(:focus, .focus) option.selected_0 {
	display: none;
}
.select_multiple_search {
	display: block;
}
`;
		document.querySelector('style#style_select_multiple')?.remove();
		let style = document.createElement('style');
		style.id = 'style_select_multiple';
		(document.head || document.body).appendChild(style);
		style.innerText = css;
		
	}
	let SelectSearchMap = new Map();
	function init_select_multiple_search(el_select) {
		// NB: assigning to HTMLElement property is bad practice (possible namespace collision).
		// Use private var instead. Map() allows object keys.
		// TODO: wrap both select and search in one display: inline-block element.
		if (SelectSearchMap.get(el_select)) {
			return;
		}
		let el_search =...