Skip to content

Instantly share code, notes, and snippets.

@LJ1102
Created January 18, 2021 23:15
Show Gist options
  • Save LJ1102/0842e4bb56d9dc9c8d94329c6a2a16ee to your computer and use it in GitHub Desktop.
Save LJ1102/0842e4bb56d9dc9c8d94329c6a2a16ee to your computer and use it in GitHub Desktop.
ValueSlider
const sValueSliderInputEvent = new Event("input");
class ValueSlider extends HTMLElement {
constructor () {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
@import '/css/theme.css';
:host {
display: flex;
}
:host > input[type="range"] {
flex: 1 1 auto;
padding-left: 0;
}
:host > input[type="number"] {
flex: 0 0 auto;
width: 5em;
}
</style>
<style id="range-styles">
input[type="range"]::-webkit-slider-thumb,
input[type="range"]:focus::-webkit-slider-thumb {
-webkit-appearance: none;
}
input[type="range"]::-webkit-slider-runnable-track {
image-rendering: pixelated;
background-size: contain;
}
</style>
<input type="range" tabindex="-1"/>
<input type="number"/>
`;
this._connected = false;
this._styles = this.shadowRoot.querySelector('#range-styles');
this._rangeInput = this.shadowRoot.querySelector('input[type="range"]');
this._numberInput = this.shadowRoot.querySelector('input[type="number"]');
// value mirroring
this._rangeInput.addEventListener('input', () => {
this._numberInput.value = this._rangeInput.value;
this.dispatchEvent(sValueSliderInputEvent);
});
this._numberInput.addEventListener('input', () => {
this._rangeInput.value = this._numberInput.value;
this.dispatchEvent(sValueSliderInputEvent);
});
this._rangeInput.addEventListener('dblclick', () => this._numberInput.focus());
// setup attributes
this.placeholder = this.getAttribute('placeholder');
this.min = this.getAttribute('min') || 0;
this.max = this.getAttribute('max') || 1;
this.step = this.getAttribute('step') || "any";
this.autostep = this.hasAttribute('autostep');
this.value = this.getAttribute('value');
}
get name () { return this.getAttribute('name'); }
set name (v) {
if (v) this.setAttribute('name', v);
else this.removeAttribute('name');
}
get thumbColor () { return this.getAttribute('thumb-color'); }
set thumbColor (v) { this.setAttribute('thumb-color', v); }
get trackColor () { return this.getAttribute('track-color'); }
set trackColor (v) { this.setAttribute('track-color', v); }
get value () { return this._rangeInput.value; }
set value (v) {
const step = parseFloat(this.step);
if (!isNaN(step)) v = Math.round(v / step) * step;
let decimalPlaces = this.step.split(".");
if (decimalPlaces.length > 1) decimalPlaces = decimalPlaces[1].length;
else decimalPlaces = 0;
this._rangeInput.value = this._numberInput.value = v ? v.toFixed(decimalPlaces) : v;
}
get min () { return parseFloat(this.getAttribute('min')); }
set min (v) {
if (v) this.setAttribute('min', v);
else this.removeAttribute('min');
}
get max () { return parseFloat(this.getAttribute('max')); }
set max (v) {
if (v) this.setAttribute('max', v);
else this.removeAttribute('max');
}
get placeholder () { return this.getAttribute('placeholder'); }
set placeholder (v) {
if (v) this.setAttribute('placeholder', v);
else this.removeAttribute('placeholder');
}
get step () { return this.getAttribute('step'); }
set step (v) {
if (v) this.setAttribute('step', v);
else this.removeAttribute('step');
}
get autostep () { return this.hasAttribute('autostep'); }
set autostep (v) { this.toggleAttribute('autostep', v); }
_setSheetStyles () {
if (this._connected) {
this._styles.sheet.cssRules[0].style.background = this.thumbColor;
this._styles.sheet.cssRules[1].style.backgroundImage = this.trackColor;
}
}
static observedAttributes = ['min', 'max', 'placeholder', 'step', 'autostep', 'track-color', 'thumb-color'];
attributeChangedCallback (attr, oldVal, newVal) {
switch (attr) {
case 'min':
case 'max':
case 'step':
if (!isNaN(newVal)) this._rangeInput[attr] = this._numberInput[attr] = newVal;
else this._rangeInput.removeAttribute(attr), this._numberInput.removeAttribute(attr);
break;
case 'placeholder':
if (newVal) this._numberInput.placeholder = newVal;
else this._numberInput.removeAttribute('placeholder');
break;
case 'autostep':
this._rangeInput.toggleAttribute('autostep', newVal !== void 0);
this._numberInput.toggleAttribute('autostep', newVal !== void 0);
break;
case 'track-color':
case 'thumb-color':
this._setSheetStyles();
break;
}
}
connectedCallback () {
this._connected = true;
this._setSheetStyles();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment