select

Better select widgets in vanilla javascript.  https://p.ce9e.org/select/demo/
git clone https://git.ce9e.org/select.git

commit
be39a24fd0a77d4fe89e4851ae861bf3c7e25f64
parent
7962c233fb8e9bbbec3fdb56917804beeda36540
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2023-01-16 15:21
refactor validation

-	all validation errors from `original` are displayed on `input`, not
	just `required`
-	validation can be updated by triggering a change event on `original`,
	e.g. when `required` changes

Diffstat

M select.js 34 +++++++++++++++++++++++-----------
M tags.js 9 ++++++++-

2 files changed, 31 insertions, 12 deletions


diff --git a/select.js b/select.js

@@ -31,6 +31,7 @@ export class Select {
   31    31 		this.original = original;
   32    32 		this.focus = -1;
   33    33 		this.indexMap = [];
   -1    34 		this.inputDirty = false;
   34    35 
   35    36 		this.createElements();
   36    37 		original.hidden = true;
@@ -69,6 +70,14 @@ export class Select {
   69    70 			}
   70    71 		};
   71    72 
   -1    73 		this.original.oninvalid = () => {
   -1    74 			this.updateValidity();
   -1    75 			this.input.reportValidity();
   -1    76 		};
   -1    77 		this.original.onchange = () => {
   -1    78 			this.updateValidity();
   -1    79 		};
   -1    80 
   72    81 		// Prevent blurring input. This also ensures dragging the cursor away from
   73    82 		// the list item will cancel the selection
   74    83 		this.dropdown.onmousedown = event => {
@@ -104,7 +113,8 @@ export class Select {
  104   113 	updateValue() {
  105   114 		if (this.original.multiple) {
  106   115 			this.input.value = '';
  107    -1 			this.input.setCustomValidity('');
   -1   116 			this.inputDirty = false;
   -1   117 			this.updateValidity();
  108   118 			this.values.innerHTML = '';
  109   119 			Array.from(this.original.options).forEach((op, i) => {
  110   120 				if (op.selected && op.label) {
@@ -122,11 +132,18 @@ export class Select {
  122   132 		} else {
  123   133 			if (this.original.selectedOptions.length) {
  124   134 				this.input.value = this.original.selectedOptions[0].label;
  125    -1 				this.input.setCustomValidity('');
   -1   135 				this.inputDirty = false;
   -1   136 				this.updateValidity();
  126   137 			}
  127   138 		}
   -1   139 	}
  128   140 
  129    -1 		this.input.required = this.original.required && !this.original.value;
   -1   141 	updateValidity() {
   -1   142 		if (this.inputDirty) {
   -1   143 			this.input.setCustomValidity('invalid choice');
   -1   144 		} else {
   -1   145 			this.input.setCustomValidity(this.original.validationMessage);
   -1   146 		}
  130   147 	}
  131   148 
  132   149 	createOption(op, i) {
@@ -250,11 +267,9 @@ export class Select {
  250   267 		} else {
  251   268 			this.close();
  252   269 		}
  253    -1 		if (Array.from(this.original.options).some(op => this.isMatch(op.label))) {
  254    -1 			this.input.setCustomValidity('');
  255    -1 		} else {
  256    -1 			this.input.setCustomValidity('invalid choice');
  257    -1 		}
   -1   270 		var ops = Array.from(this.original.options);
   -1   271 		this.inputDirty = !ops.some(op => this.isMatch(op.label));
   -1   272 		this.updateValidity();
  258   273 	}
  259   274 
  260   275 	onblur(event) {
@@ -266,9 +281,6 @@ export class Select {
  266   281 		} else if (this.indexMap.length) {
  267   282 			this.setValue(this.indexMap[this.focus]);
  268   283 		}
  269    -1 		if (!this.original.checkValidity()) {
  270    -1 			this.input.setCustomValidity(this.original.validationMessage);
  271    -1 		}
  272   284 	}
  273   285 }
  274   286 

diff --git a/tags.js b/tags.js

@@ -48,6 +48,14 @@ export class TagInput {
   48    48 		this.input.onkeydown = this.onkeydown.bind(this);
   49    49 		this.input.onchange = this.onchange.bind(this);
   50    50 
   -1    51 		this.original.oninvalid = () => {
   -1    52 			this.input.setCustomValidity(this.original.validationMessage);
   -1    53 			this.input.reportValiditiy();
   -1    54 		};
   -1    55 		this.original.onchange = () => {
   -1    56 			this.input.setCustomValidity(this.original.validationMessage);
   -1    57 		};
   -1    58 
   51    59 		this.updateValue();
   52    60 	}
   53    61 
@@ -109,7 +117,6 @@ export class TagInput {
  109   117 				op.remove();
  110   118 			}
  111   119 		});
  112    -1 		this.input.required = this.original.required && !this.original.value;
  113   120 	}
  114   121 }
  115   122