diff --git a/app/app.css b/app/app.css index 0487480..a9160ad 100644 --- a/app/app.css +++ b/app/app.css @@ -95,6 +95,33 @@ select { .multiline h2 { font-weight: normal; } +x-range { + width: 144px; + height: 16px; + position: relative; + --thumb: 6px; + --track: 4px; + padding: 0 var(--thumb); +} +x-range .-track, +x-range .-elapsed { + position: absolute; + top: calc(50% - var(--track)/2); + height: var(--track); + left: 0; +} +x-range .-track { + width: 100%; +} +x-range .-thumb { + position: absolute; + top: 50%; + border-radius: 50%; + width: calc(2*var(--thumb)); + height: calc(2*var(--thumb)); + background-color: #fff; + transform: translate(-50%, -50%); +} main { flex-grow: 1; overflow: hidden; diff --git a/app/css/app.less b/app/css/app.less index ec1b377..cc3a90e 100644 --- a/app/css/app.less +++ b/app/css/app.less @@ -55,6 +55,7 @@ select { @import "font.less"; @import "icons.less"; @import "mixins.less"; +@import "range.less"; @import "main.less"; @import "nav.less"; @import "player.less"; diff --git a/app/css/range.less b/app/css/range.less new file mode 100644 index 0000000..a6d6e01 --- /dev/null +++ b/app/css/range.less @@ -0,0 +1,36 @@ +x-range { + width: 144px; + height: 16px; + position: relative; + + --thumb: 6px; + --track: 4px; + padding: 0 var(--thumb); + + .-track, .-elapsed { + position: absolute; + top: calc(50% - var(--track)/2); + height: var(--track); + left: 0; + } + + .-track { + width: 100%; + } + + .-elapsed { + + } + + .-thumb { + position: absolute; + top: 50%; + + border-radius: 50%; + width: calc(2*var(--thumb)); + height: calc(2*var(--thumb)); + background-color: #fff; + + transform: translate(-50%, -50%); + } +} diff --git a/app/index.html b/app/index.html index ec21672..a28bfb7 100644 --- a/app/index.html +++ b/app/index.html @@ -29,6 +29,7 @@
+
diff --git a/app/js/app.js b/app/js/app.js index 57dd3e2..0b56910 100644 --- a/app/js/app.js +++ b/app/js/app.js @@ -2,6 +2,7 @@ import * as nav from "./nav.js"; import * as mpd from "./lib/mpd.js"; import * as player from "./player.js"; import * as html from "./lib/html.js"; +import * as range from "./lib/range.js"; import * as queue from "./queue.js"; import * as library from "./library.js"; diff --git a/app/js/lib/range.js b/app/js/lib/range.js new file mode 100644 index 0000000..291dd82 --- /dev/null +++ b/app/js/lib/range.js @@ -0,0 +1,59 @@ +import * as html from "./html.js"; + +class Range extends HTMLElement { + static get observedAttributes() { return ["min", "max", "value"]; } + + constructor() { + super(); + + this._data = { + min: 0, + max: 100, + value: 50 + }; + + this.track = html.node("span", {className:"-track"}); + this.elapsed = html.node("span", {className:"-elapsed"}); + this.thumb = html.node("span", {className:"-thumb"}); + + this.appendChild(this.track); + this.appendChild(this.elapsed); + this.appendChild(this.thumb); + + this._update(); + } + + set value(value) { + value = Math.max(value, this._data.min); + value = Math.min(value, this._data.max); + this._data.value = value; + this._update(); + } + + set min(min) { + this._data.min = Math.min(min, this._data.max); + this._update(); + } + + set max(max) { + this._data.max = Math.max(max, this._data.max); + this._update(); + } + + attributeChangedCallback(name, oldValue, newValue) { + this[name] = newValue; + } + + get value() { return this._data.value; } + get valueAsNumber() { return Number(this._data.value); } + get min() { return this._data.min; } + get max() { return this._data.max; } + + _update() { + let frac = (this._data.value - this._data.min) / (this._data.max - this._data.min); + this.thumb.style.left = `${frac * 100}%`; + this.elapsed.style.width = `${frac * 100}%`; + } +} + +customElements.define('x-range', Range);