2019-04-25 22:09:48 +08:00
|
|
|
import * as html from "./html.js";
|
|
|
|
|
|
|
|
class Range extends HTMLElement {
|
2019-04-26 19:48:23 +08:00
|
|
|
static get observedAttributes() { return ["min", "max", "value", "disabled"]; }
|
2019-04-25 22:09:48 +08:00
|
|
|
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
|
2019-04-26 19:48:23 +08:00
|
|
|
this._dom = {};
|
2019-04-25 22:09:48 +08:00
|
|
|
|
2019-04-26 19:48:23 +08:00
|
|
|
this.innerHTML = `
|
|
|
|
<span class="-track"></span>
|
|
|
|
<span class="-elapsed"></span>
|
|
|
|
<span class="-remaining"></span>
|
|
|
|
<div class="-inner">
|
|
|
|
<button class="-thumb"></button>
|
|
|
|
</div>
|
|
|
|
`;
|
2019-04-25 22:09:48 +08:00
|
|
|
|
2019-04-26 19:48:23 +08:00
|
|
|
Array.from(this.querySelectorAll("[class^='-']")).forEach(node => {
|
|
|
|
let name = node.className.substring(1);
|
|
|
|
this._dom[name] = node;
|
|
|
|
});
|
2019-04-25 22:09:48 +08:00
|
|
|
|
|
|
|
this._update();
|
|
|
|
|
2019-04-26 19:48:23 +08:00
|
|
|
this.addEventListener("mousedown", this);
|
2019-04-25 22:09:48 +08:00
|
|
|
}
|
|
|
|
|
2019-04-26 19:48:23 +08:00
|
|
|
set min(min) { this.setAttribute("min", min); }
|
|
|
|
set max(max) { this.setAttribute("max", max); }
|
|
|
|
set value(value) { this.setAttribute("value", value); }
|
|
|
|
set disabled(disabled) {
|
|
|
|
disabled ? this.setAttribute("disabled", "") : this.removeAttribute("disabled");
|
2019-04-25 22:09:48 +08:00
|
|
|
}
|
|
|
|
|
2019-04-26 19:48:23 +08:00
|
|
|
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"); }
|
2019-04-25 22:09:48 +08:00
|
|
|
|
|
|
|
attributeChangedCallback(name, oldValue, newValue) {
|
2019-04-26 19:48:23 +08:00
|
|
|
switch (name) {
|
|
|
|
case "min":
|
|
|
|
case "max":
|
|
|
|
case "value":
|
|
|
|
this._update();
|
|
|
|
break;
|
|
|
|
}
|
2019-04-25 22:09:48 +08:00
|
|
|
}
|
|
|
|
|
2019-04-26 19:48:23 +08:00
|
|
|
handleEvent(e) {
|
|
|
|
switch (e.type) {
|
|
|
|
case "mousedown":
|
|
|
|
if (this.disabled) { return; }
|
|
|
|
document.addEventListener("mousemove", this);
|
|
|
|
document.addEventListener("mouseup", this);
|
|
|
|
this._setToMouse(e);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "mousemove":
|
|
|
|
this._setToMouse(e);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "mouseup":
|
|
|
|
document.removeEventListener("mousemove", this);
|
|
|
|
document.removeEventListener("mouseup", this);
|
|
|
|
this.dispatchEvent(new CustomEvent("change"));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-04-25 22:09:48 +08:00
|
|
|
|
|
|
|
_update() {
|
2019-04-26 19:48:23 +08:00
|
|
|
let min = Number(this.min || 0);
|
|
|
|
let max = Number(this.max || 100);
|
|
|
|
let frac = (this.valueAsNumber - min) / (max - min);
|
|
|
|
this._dom.thumb.style.left = `${frac * 100}%`;
|
|
|
|
this._dom.remaining.style.left = `${frac * 100}%`;
|
|
|
|
this._dom.elapsed.style.width = `${frac * 100}%`;
|
|
|
|
}
|
|
|
|
|
|
|
|
_setToMouse(e) {
|
|
|
|
let rect = this._dom.inner.getBoundingClientRect();
|
|
|
|
let x = e.clientX;
|
|
|
|
x = Math.max(x, rect.left);
|
|
|
|
x = Math.min(x, rect.right);
|
|
|
|
|
|
|
|
let min = Number(this.min || 0);
|
|
|
|
let max = Number(this.max || 100);
|
|
|
|
|
|
|
|
let frac = (x-rect.left)/(rect.right-rect.left);
|
|
|
|
let value = min + frac * (max-min);
|
|
|
|
value = Math.round(value); // fixme
|
|
|
|
if (value == this.valueAsNumber) { return; }
|
|
|
|
|
|
|
|
this.value = value.toString();
|
|
|
|
this.dispatchEvent(new CustomEvent("input"));
|
2019-04-25 22:09:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
customElements.define('x-range', Range);
|