range finalized
This commit is contained in:
parent
d7f93c8a20
commit
c2c1488d1e
3 changed files with 85 additions and 19 deletions
|
@ -104,7 +104,7 @@ x-range {
|
||||||
--elapsed-color: lightgray;
|
--elapsed-color: lightgray;
|
||||||
--remaining-color: transparent;
|
--remaining-color: transparent;
|
||||||
--radius: calc(var(--track-size)/2);
|
--radius: calc(var(--track-size)/2);
|
||||||
width: 144px;
|
width: 192px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ x-range {
|
||||||
|
|
||||||
--radius: calc(var(--track-size)/2);
|
--radius: calc(var(--track-size)/2);
|
||||||
|
|
||||||
width: 144px;
|
width: 192px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as html from "./html.js";
|
import * as html from "./html.js";
|
||||||
|
|
||||||
class Range extends HTMLElement {
|
class Range extends HTMLElement {
|
||||||
static get observedAttributes() { return ["min", "max", "value", "disabled"]; }
|
static get observedAttributes() { return ["min", "max", "value", "step", "disabled"]; }
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
@ -25,26 +25,45 @@ class Range extends HTMLElement {
|
||||||
this._update();
|
this._update();
|
||||||
|
|
||||||
this.addEventListener("mousedown", this);
|
this.addEventListener("mousedown", this);
|
||||||
|
this.addEventListener("keydown", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get _valueAsNumber() {
|
||||||
|
let raw = (this.hasAttribute("value") ? Number(this.getAttribute("value")) : 50);
|
||||||
|
return this._constrain(raw);
|
||||||
|
}
|
||||||
|
get _minAsNumber() {
|
||||||
|
return (this.hasAttribute("min") ? Number(this.getAttribute("min")) : 0);
|
||||||
|
}
|
||||||
|
get _maxAsNumber() {
|
||||||
|
return (this.hasAttribute("max") ? Number(this.getAttribute("max")) : 100);
|
||||||
|
}
|
||||||
|
get _stepAsNumber() {
|
||||||
|
return (this.hasAttribute("step") ? Number(this.getAttribute("step")) : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
get value() { return String(this._valueAsNumber); }
|
||||||
|
get valueAsNumber() { return this._valueAsNumber; }
|
||||||
|
get min() { return this.hasAttribute("min") ? this.getAttribute("min") : ""; }
|
||||||
|
get max() { return this.hasAttribute("max") ? this.getAttribute("max") : ""; }
|
||||||
|
get step() { return this.hasAttribute("step") ? this.getAttribute("step") : ""; }
|
||||||
|
get disabled() { return this.hasAttribute("disabled"); }
|
||||||
|
|
||||||
|
set _valueAsNumber(value) { this.value = String(value); }
|
||||||
set min(min) { this.setAttribute("min", min); }
|
set min(min) { this.setAttribute("min", min); }
|
||||||
set max(max) { this.setAttribute("max", max); }
|
set max(max) { this.setAttribute("max", max); }
|
||||||
set value(value) { this.setAttribute("value", value); }
|
set value(value) { this.setAttribute("value", value); }
|
||||||
|
set step(step) { this.setAttribute("step", step); }
|
||||||
set disabled(disabled) {
|
set disabled(disabled) {
|
||||||
disabled ? this.setAttribute("disabled", "") : this.removeAttribute("disabled");
|
disabled ? this.setAttribute("disabled", "") : this.removeAttribute("disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
get value() { return (this.hasAttribute("value") ? this.getAttribute("value") : "50"); }
|
|
||||||
get valueAsNumber() { return Number(this.value); }
|
|
||||||
get min() { return this.getAttribute("min"); }
|
|
||||||
get max() { return this.getAttribute("max"); }
|
|
||||||
get disabled() { return this.hasAttribute("disabled"); }
|
|
||||||
|
|
||||||
attributeChangedCallback(name, oldValue, newValue) {
|
attributeChangedCallback(name, oldValue, newValue) {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "min":
|
case "min":
|
||||||
case "max":
|
case "max":
|
||||||
case "value":
|
case "value":
|
||||||
|
case "step":
|
||||||
this._update();
|
this._update();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -68,13 +87,61 @@ class Range extends HTMLElement {
|
||||||
document.removeEventListener("mouseup", this);
|
document.removeEventListener("mouseup", this);
|
||||||
this.dispatchEvent(new CustomEvent("change"));
|
this.dispatchEvent(new CustomEvent("change"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "keydown":
|
||||||
|
if (this.disabled) { return; }
|
||||||
|
this._handleKey(e.code);
|
||||||
|
this.dispatchEvent(new CustomEvent("input"));
|
||||||
|
this.dispatchEvent(new CustomEvent("change"));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_handleKey(code) {
|
||||||
|
let min = this._minAsNumber;
|
||||||
|
let max = this._maxAsNumber;
|
||||||
|
let range = max - min;
|
||||||
|
let step = this._stepAsNumber;
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case "ArrowLeft":
|
||||||
|
case "ArrowDown":
|
||||||
|
this._valueAsNumber = this._constrain(this._valueAsNumber - step);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "ArrowRight":
|
||||||
|
case "ArrowUp":
|
||||||
|
this._valueAsNumber = this._constrain(this._valueAsNumber + step);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Home": this._valueAsNumber = this._constrain(min); break;
|
||||||
|
case "End": this._valueAsNumber = this._constrain(max); break;
|
||||||
|
|
||||||
|
case "PageUp": this._valueAsNumber = this._constrain(this._valueAsNumber + range/10); break;
|
||||||
|
case "PageDown": this._valueAsNumber = this._constrain(this._valueAsNumber - range/10); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_constrain(value) {
|
||||||
|
const min = this._minAsNumber;
|
||||||
|
const max = this._maxAsNumber;
|
||||||
|
const step = this._stepAsNumber;
|
||||||
|
|
||||||
|
value = Math.max(value, min);
|
||||||
|
value = Math.min(value, max);
|
||||||
|
|
||||||
|
value -= min;
|
||||||
|
value = Math.round(value / step) * step;
|
||||||
|
value += min;
|
||||||
|
if (value > max) { value -= step; }
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
_update() {
|
_update() {
|
||||||
let min = Number(this.min || 0);
|
let min = this._minAsNumber;
|
||||||
let max = Number(this.max || 100);
|
let max = this._maxAsNumber;
|
||||||
let frac = (this.valueAsNumber - min) / (max - min);
|
let frac = (this._valueAsNumber-min) / (max-min);
|
||||||
this._dom.thumb.style.left = `${frac * 100}%`;
|
this._dom.thumb.style.left = `${frac * 100}%`;
|
||||||
this._dom.remaining.style.left = `${frac * 100}%`;
|
this._dom.remaining.style.left = `${frac * 100}%`;
|
||||||
this._dom.elapsed.style.width = `${frac * 100}%`;
|
this._dom.elapsed.style.width = `${frac * 100}%`;
|
||||||
|
@ -86,15 +153,14 @@ class Range extends HTMLElement {
|
||||||
x = Math.max(x, rect.left);
|
x = Math.max(x, rect.left);
|
||||||
x = Math.min(x, rect.right);
|
x = Math.min(x, rect.right);
|
||||||
|
|
||||||
let min = Number(this.min || 0);
|
let min = this._minAsNumber;
|
||||||
let max = Number(this.max || 100);
|
let max = this._maxAsNumber;
|
||||||
|
|
||||||
let frac = (x-rect.left) / (rect.right-rect.left);
|
let frac = (x-rect.left) / (rect.right-rect.left);
|
||||||
let value = min + frac * (max-min);
|
let value = this._constrain(min + frac * (max-min));
|
||||||
value = Math.round(value); // fixme
|
if (value == this._valueAsNumber) { return; }
|
||||||
if (value == this.valueAsNumber) { return; }
|
|
||||||
|
|
||||||
this.value = value.toString();
|
this._valueAsNumber = value;
|
||||||
this.dispatchEvent(new CustomEvent("input"));
|
this.dispatchEvent(new CustomEvent("input"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue