- commit
- f81416682f28548e9422585c83bd758a9bdd774c
- parent
- 09bca6cff2d8edcb9abde017ba19b52f0b5fe6d9
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2023-08-08 11:18
display values inside of input This is achived by setting textIndent and paddingTop on the input to leave space for the absolutely positioned values.
Diffstat
| M | select.css | 19 | ++++++++++++++++++- |
| M | values.js | 53 | +++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 71 insertions, 1 deletions
diff --git a/select.css b/select.css
@@ -9,7 +9,7 @@ 9 9 10 10 .select__dropdown { 11 11 position: absolute;12 -1 z-index: 1;-1 12 z-index: 2; 13 13 list-style: none; 14 14 margin: 0; 15 15 padding: 0; @@ -64,13 +64,23 @@ 64 64 padding-left: 2em; 65 65 } 66 66 -1 67 .select__input { -1 68 position: relative; -1 69 } -1 70 .select__input input { -1 71 position: relative; /* on top of values */ -1 72 } -1 73 67 74 .select__values { -1 75 position: absolute; 68 76 display: inline; 69 77 padding: 0; 70 78 margin: 0; 71 79 } 72 80 .select__values li { 73 81 display: inline-block; -1 82 position: relative; -1 83 z-index: 1; /* on top of input */ 74 84 margin: 0.1em 0.2em; 75 85 margin-inline-start: 0; 76 86 cursor: default; @@ -82,3 +92,10 @@ 82 92 border: 1px solid ThreeDShadow; 83 93 border-radius: 0.3em; 84 94 } -1 95 -1 96 .select__measure { -1 97 width: 0; -1 98 height: 0; -1 99 overflow: hidden; -1 100 white-space: pre; -1 101 }
diff --git a/values.js b/values.js
@@ -1,12 +1,64 @@ 1 1 import { create } from './utils.js'; 2 2 -1 3 var createMeasure = function(target) { -1 4 var wrapper = create('<div class="select__measure" aria-hidden="true">'); -1 5 var span = document.createElement('span'); -1 6 target.after(wrapper); -1 7 wrapper.append(span); -1 8 -1 9 return text => { -1 10 span.textContent = text; -1 11 var rect = span.getBoundingClientRect(); -1 12 return rect.width; -1 13 }; -1 14 }; -1 15 3 16 export class Values { 4 17 constructor(input, valueClass) { -1 18 this.gap = 4; 5 19 this.input = input; 6 20 this.valueClass = valueClass || 'select__value'; 7 21 -1 22 this.measure = createMeasure(input); 8 23 this.el = create('<ul class="select__values" aria-live="polite">'); 9 24 input.before(this.el); -1 25 -1 26 input.addEventListener('input', this.updateSize.bind(this)); -1 27 window.addEventListener('resize', this.updateSize.bind(this)); -1 28 } -1 29 -1 30 updateSize() { -1 31 var style = getComputedStyle(this.input); -1 32 -1 33 // We may already have changed paddingTop, so we assume that original -1 34 // paddingTop and paddingBottom are the same -1 35 var paddingTop = parseInt(style.paddingBottom, 10); -1 36 -1 37 this.el.style.top = paddingTop + 'px'; -1 38 this.el.style.bottom = style.paddingBottom; -1 39 this.el.style.left = style.paddingLeft; -1 40 this.el.style.right = style.paddingRight; -1 41 -1 42 var n = this.el.children.length; -1 43 if (n > 0) { -1 44 var first = this.el.children[0].getBoundingClientRect(); -1 45 var last = this.el.children[n - 1].getBoundingClientRect(); -1 46 var height = last.top - first.top; -1 47 var width = style.direction === 'ltr' -1 48 ? last.right - first.left -1 49 : first.right - last.left; -1 50 -1 51 if (width + this.gap + this.measure(this.input.value) < this.el.clientWidth) { -1 52 this.input.style.paddingTop = `${paddingTop + height}px`; -1 53 this.input.style.textIndent = `${width + this.gap}px`; -1 54 } else { -1 55 this.input.style.paddingTop = `${paddingTop + height + last.height + this.gap}px`; -1 56 this.input.style.textIndent = '0'; -1 57 } -1 58 } else { -1 59 this.input.style.paddingTop = `${paddingTop}px`; -1 60 this.input.style.textIndent = '0'; -1 61 } 10 62 } 11 63 12 64 update(original, onChange) { @@ -25,5 +77,6 @@ export class Values { 25 77 op.remove(); 26 78 } 27 79 }); -1 80 this.updateSize(); 28 81 } 29 82 }