diff --git a/examples/index.html b/examples/index.html
index cd8113b..e14fcdc 100644
--- a/examples/index.html
+++ b/examples/index.html
@@ -28,7 +28,7 @@
-
+
@@ -39,6 +39,10 @@
+
+
+
+
diff --git a/range-slider-element.js b/range-slider-element.js
index b12f39c..8726e16 100644
--- a/range-slider-element.js
+++ b/range-slider-element.js
@@ -1,7 +1,7 @@
import * as style from './styles.css';
const UPDATE_EVENTS = ['input', 'change'];
-const REFLECTED_ATTRIBUTES = ['min', 'max', 'step', 'value', 'disabled'];
+const REFLECTED_ATTRIBUTES = ['min', 'max', 'step', 'value', 'disabled', 'value-precision'];
class RangeSliderElement extends HTMLElement {
constructor() {
@@ -25,12 +25,14 @@ class RangeSliderElement extends HTMLElement {
get max() { return this.getAttribute('max') || '100'; }
get step() { return this.getAttribute('step') || '1'; }
get value() { return this.getAttribute('value') || this._defaultValue; }
+ get disabled() { return this.getAttribute('disabled') || false }
get valuePrecision() { return this.getAttribute('label-precision') || ''; }
set min(min) { this.setAttribute('min', min); }
set max(max) { this.setAttribute('max', max); }
set step(step) { this.setAttribute('step', step); }
set value(value) { this.setAttribute('value', value); }
+ set disabled(disabled) { this.setAttribute('disabled', disabled); }
set valuePrecision(precision) { this.setAttribute('label-precision', precision); }
connectedCallback() {
@@ -61,13 +63,16 @@ class RangeSliderElement extends HTMLElement {
}
_startHandler = e => {
+ this.classList.add('touch-active');
+
+ // Click and drag
this.setPointerCapture(e.pointerId);
this.addEventListener('pointermove', this._moveHandler, false);
- this.classList.add('touch-active');
- console.log(e);
- if (e.target.matches('.thumb')) return;
- this._reflectValue(e);
+ // Click jump
+ if (!e.target.matches('.thumb')) {
+ this._reflectValue(e);
+ }
}
_moveHandler = e => {
@@ -76,9 +81,9 @@ class RangeSliderElement extends HTMLElement {
}
_endHandler = e => {
+ this.classList.remove('touch-active');
this.releasePointerCapture(e.pointerId);
this.removeEventListener('pointermove', this._moveHandler, false);
- this.classList.remove('touch-active');
// TODO: check if value changed
this.dispatchEvent(new Event('change', { bubbles: true }));
@@ -88,19 +93,28 @@ class RangeSliderElement extends HTMLElement {
const min = Number(this.min);
const max = Number(this.max);
const step = Number(this.step);
- const oldValue = Number(this.value);
+ const oldValue = this.value;
const valuePrecision = Number(this.valuePrecision) || getPrescision(this.step) || 0;
const fullWidth = event.target.offsetWidth;
- const offsetX = event.offsetX;
- const stepInPixels = (max > 0) ? fullWidth / max : fullWidth / min;
- const tmpValue = Math.min(Math.max(offsetX / stepInPixels, min), max);
- const nearestValue = Math.ceil(tmpValue / step) * step; // Rounding in steps
- const newValue = valuePrecision
- ? nearestValue.toFixed(valuePrecision)
- : Math.round(nearestValue).toString()
- ;
+ const offsetX = Math.min(Math.max(event.offsetX, 0), fullWidth);
+ const percentComplete = offsetX / fullWidth;
+
+ // TODO: RTL support
+ // if (this.adapter_.isRTL()) {
+ // percentComplete = 1 - percentComplete;
+ // }
- console.log({ fullWidth, offsetX, stepInPixels, oldValue, newValue});
+ // Fit the percentage complete between the range [min,max]
+ // by remapping from [0, 1] to [min, min+(max-min)].
+ const computedValue = min + percentComplete * (max - min);
+
+ // Rounding in steps
+ const nearestValue = Math.round(computedValue / step) * step;
+
+ // Value precision
+ const newValue = valuePrecision ? nearestValue.toFixed(valuePrecision) : Math.round(nearestValue).toString();
+
+ console.log({ fullWidth, offsetX, oldValue, computedValue, newValue});
if (oldValue !== newValue) {
this.value = newValue;
@@ -108,11 +122,19 @@ class RangeSliderElement extends HTMLElement {
}
}
+ _stepUp(amount = this.step) {
+ this.value += amount;
+ }
+
+ _stepDown(amount = this.step) {
+ this.value -= amount;
+ }
+
_update() {
const min = Number(this.min);
const max = Number(this.max);
const value = Number(this.value);
- const percent = (max > 0) ? (100 * (value - min)) / (max - min) : (100 * (value - max)) / (min - max);
+ const percent = (100 * (value - min)) / (max - min);
if (this._valueDisplay) {
this._valueDisplay.textContent = value;
diff --git a/styles.css b/styles.css
index 80e32c9..90846cd 100644
--- a/styles.css
+++ b/styles.css
@@ -2,7 +2,8 @@ range-slider {
position: relative;
display: flex;
height: 24px;
- width: 130px;
+ width: 100%;
+ min-width: 130px;
margin: 2px;
overflow: visible;
@@ -16,7 +17,7 @@ range-slider[disabled] {
}
range-slider::before {
- --height: 3px;
+ --height: 5px;
content: "";
display: block;
@@ -24,19 +25,18 @@ range-slider::before {
top: calc(50% - var(--height) / 2);
left: 0;
width: 100%;
- height: 3px;
+ height: var(--height);
border-radius: 1px;
- box-shadow: 0 -.5px 0 rgba(0,0,0,0.3), inset 0 .5px 0 rgba(255,255,255,0.2), 0 .5px 0 rgba(255,255,255,0.3);
- background: linear-gradient(#FF0080, #FF0080) 0/ var(--value-percent, 0%) 100% no-repeat #eee;
+ /* box-shadow: 0 -.5px 0 rgba(0,0,0,0.3), inset 0 .5px 0 rgba(255,255,255,0.2), 0 .5px 0 rgba(255,255,255,0.3); */
+ background: linear-gradient(#6221ea, #6221ea) 0/ var(--value-percent, 0%) 100% no-repeat #c6afe5;
}
.thumb {
- pointer-events: none;
position: absolute;
bottom: 6px;
left: var(--value-percent, 0%);
margin-left: -6px;
- background: url('data:image/svg+xml,') center no-repeat #FF0080;
+ background: url('data:image/svg+xml,') center no-repeat #6221ea;
border-radius: 50%;
width: 12px;
height: 12px;