Skip to content

Commit 5d55605

Browse files
committed
Allow responsive sliders
1 parent 7d72159 commit 5d55605

File tree

1 file changed

+86
-24
lines changed

1 file changed

+86
-24
lines changed

src/range_slider.js

Lines changed: 86 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ export default class extends Controller {
261261
createScale() {
262262
this.stepWidth = this.sliderWidth / (this.values.range.length - 1);
263263

264+
this.scale.innerHTML = "";
265+
264266
for (let i = 0; i < this.values.range.length; i++) {
265267
const labelContainer = document.createElement("div");
266268
const label = document.createElement("span");
@@ -272,15 +274,37 @@ export default class extends Controller {
272274

273275
labelContainer.appendChild(label);
274276
this.scale.appendChild(labelContainer);
277+
275278
labelContainer.style.width =
276279
i === this.values.range.length - 1 ? 0 : this.stepWidth + "px";
277280

278-
label.innerHTML = this.labelsValue
279-
? this.formatStr(this.values.range[i])
280-
: "";
281+
const labelPosition = i * this.stepWidth;
282+
283+
if (this.labelsValue) {
284+
label.innerHTML = this.formatStr(this.values.range[i]);
285+
286+
label.style.position = "absolute";
287+
label.style.left = labelPosition + "px";
288+
label.style.transform = "translateX(-50%)"; // This centers the label
289+
290+
// Determine which labels to show based on available space
291+
const totalLabels = this.values.range.length;
292+
const availableWidth = this.sliderWidth;
293+
const approxLabelWidth = 50; // Estimate of average label width in pixels
294+
const maxLabelsToShow = Math.floor(availableWidth / approxLabelWidth);
281295

282-
label.style.whiteSpace = "nowrap";
283-
label.style.marginLeft = (label.clientWidth / 2) * -1 + "px";
296+
// Show all labels if there's enough space, otherwise show a subset
297+
if (
298+
totalLabels <= maxLabelsToShow ||
299+
i === 0 ||
300+
i === totalLabels - 1 ||
301+
i % Math.ceil(totalLabels / maxLabelsToShow) === 0
302+
) {
303+
label.style.display = "inline-block";
304+
} else {
305+
label.style.display = "none";
306+
}
307+
}
284308
}
285309
}
286310

@@ -301,11 +325,21 @@ export default class extends Controller {
301325
this.values.start = this.values.end;
302326
}
303327

328+
const maxPosition = (this.values.range.length - 1) * this.stepWidth;
329+
304330
if (this.isRange) {
305-
this.pointerL.style.left =
306-
this.values.start * this.stepWidth - this.pointerWidth / 2 + "px";
307-
this.pointerR.style.left =
308-
this.values.end * this.stepWidth - this.pointerWidth / 2 + "px";
331+
// Calculate pointer positions based on values
332+
let leftPosition = this.values.start * this.stepWidth;
333+
let rightPosition = this.values.end * this.stepWidth;
334+
335+
// Adjust to ensure pointers don't go out of bounds
336+
leftPosition = Math.max(0, Math.min(leftPosition, maxPosition));
337+
rightPosition = Math.max(0, Math.min(rightPosition, maxPosition));
338+
339+
// Set pointer positions
340+
this.pointerL.style.left = leftPosition - this.pointerWidth / 2 + "px";
341+
this.pointerR.style.left = rightPosition - this.pointerWidth / 2 + "px";
342+
309343
if (this.tooltipValue) {
310344
this.tipL.innerHTML = this.formatStr(
311345
this.values.range[this.values.start]
@@ -314,19 +348,25 @@ export default class extends Controller {
314348
this.values.range[this.values.end]
315349
);
316350
}
351+
352+
// Set selected area position and width
353+
this.selected.style.left = leftPosition + "px";
354+
this.selected.style.width = rightPosition - leftPosition + "px";
317355
} else {
318-
this.pointerL.style.left =
319-
this.values.end * this.stepWidth - this.pointerWidth / 2 + "px";
356+
let position = this.values.end * this.stepWidth;
357+
position = Math.max(0, Math.min(position, maxPosition));
358+
359+
this.pointerL.style.left = position - this.pointerWidth / 2 + "px";
360+
320361
if (this.tooltipValue) {
321362
this.tipL.innerHTML = this.formatStr(
322363
this.values.range[this.values.end]
323364
);
324365
}
325-
}
326366

327-
this.selected.style.width =
328-
(this.values.end - this.values.start) * this.stepWidth + "px";
329-
this.selected.style.left = this.values.start * this.stepWidth + "px";
367+
this.selected.style.width = position + "px";
368+
this.selected.style.left = "0px";
369+
}
330370

331371
this.updateInput();
332372
}
@@ -403,18 +443,23 @@ export default class extends Controller {
403443
if (!this.activePointer) return;
404444

405445
let coordX = e.touches ? e.touches[0].pageX : e.pageX;
406-
let relativePosition = coordX - this.sliderLeft;
407-
let percentage = relativePosition / this.sliderWidth;
408-
let index = Math.round(percentage * (this.values.range.length - 1));
446+
// Calculate position relative to slider
447+
let position = coordX - this.sliderLeft;
409448

410-
// Ensure index is within valid range
411-
index = Math.max(0, Math.min(index, this.values.range.length - 1));
449+
// Convert to percentage of slider width
450+
let percentage = position / this.sliderWidth;
412451

452+
// Clamp percentage between 0 and 1
453+
percentage = Math.max(0, Math.min(1, percentage));
454+
455+
// Convert to index in range values array
456+
let index = Math.round(percentage * (this.values.range.length - 1));
457+
458+
// Update values based on which pointer is active
413459
if (this.isRange) {
414460
if (this.activePointer === this.pointerL) {
415-
this.values.start = Math.min(index, this.values.end);;
416-
}
417-
if (this.activePointer === this.pointerR) {
461+
this.values.start = Math.min(index, this.values.end);
462+
} else if (this.activePointer === this.pointerR) {
418463
this.values.end = Math.max(index, this.values.start);
419464
}
420465
} else {
@@ -449,10 +494,27 @@ export default class extends Controller {
449494
}
450495

451496
onResize() {
497+
// Save current values before resizing
498+
const currentStart = this.values.start;
499+
const currentEnd = this.values.end;
500+
501+
// Update dimensions
452502
this.sliderLeft = this.slider.getBoundingClientRect().left;
453503
this.sliderWidth = this.slider.clientWidth;
504+
this.pointerWidth = this.pointerL.clientWidth;
505+
506+
// Update step width
507+
this.stepWidth = this.sliderWidth / (this.values.range.length - 1);
454508

455-
this.updateScale();
509+
// Recreate the scale with new dimensions
510+
this.createScale();
511+
512+
// Restore values
513+
this.values.start = currentStart;
514+
this.values.end = currentEnd;
515+
516+
// Update visual representation
517+
this.setSliders();
456518
}
457519

458520
parseRange(min, max, step) {

0 commit comments

Comments
 (0)