Skip to content

Commit

Permalink
Multi-Thumb Slider: Add ability to move thumbs by clicking rail (pull #…
Browse files Browse the repository at this point in the history
…3172)

Fixed issue #3118.
Updates the multi-thumb slider so clicking the rail moves one of the thumbs. The thumb closest to the click is moved.
Also updates javascript code style to use const and let instead of var.
  • Loading branch information
jongund authored Dec 12, 2024
1 parent b0c04c4 commit d93a99a
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
.slider-multithumb .slider-group .range {
fill: currentcolor;
opacity: 0.4;
pointer-events: none;
}

.slider-multithumb .slider-group .thumb {
Expand Down
85 changes: 60 additions & 25 deletions content/patterns/slider-multithumb/examples/js/slider-multithumb.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

'use strict';

class SliderMultithumb {
constructor(domNode) {
this.isMoving = false;
Expand All @@ -21,6 +22,9 @@ class SliderMultithumb {
this.railNode = domNode.querySelector('.rail rect');
this.rangeNode = domNode.querySelector('.range rect');

this.minSliderPosition = 0;
this.maxSliderPosition = 0;

this.minSliderNode = domNode.querySelector('[role=slider].minimum');
this.maxSliderNode = domNode.querySelector('[role=slider].maximum');

Expand All @@ -36,7 +40,7 @@ class SliderMultithumb {
// Dimensions of the slider focus ring, thumb and rail

this.svgWidth = 360;
this.svgHeight = 80;
this.svgHeight = 100;

this.valueTop = 24;
this.valueHeight = this.minSliderValueNode.getBoundingClientRect().height;
Expand Down Expand Up @@ -122,6 +126,8 @@ class SliderMultithumb {
this.maxSliderNode.addEventListener('focus', this.onSliderFocus.bind(this));
this.maxSliderNode.addEventListener('blur', this.onSliderBlur.bind(this));

this.railNode.addEventListener('click', this.onRailClick.bind(this));

this.moveSliderTo(this.minSliderNode, this.getValue(this.minSliderNode));
this.moveSliderTo(this.maxSliderNode, this.getValue(this.maxSliderNode));
}
Expand Down Expand Up @@ -149,30 +155,29 @@ class SliderMultithumb {
}

isInRange(sliderNode, value) {
let valueMin = this.getValueMin(sliderNode);
let valueMax = this.getValueMax(sliderNode);
const valueMin = this.getValueMin(sliderNode);
const valueMax = this.getValueMax(sliderNode);
return value <= valueMax && value >= valueMin;
}

isOutOfRange(value) {
let valueMin = this.getValueMin(this.minSliderNode);
let valueMax = this.getValueMax(this.maxSliderNode);
const valueMin = this.getValueMin(this.minSliderNode);
const valueMax = this.getValueMax(this.maxSliderNode);
return value > valueMax || value < valueMin;
}

getXFromThumb(node) {
var points = node.getAttribute('points').split(',');
const points = node.getAttribute('points').split(',');
return parseInt(points[0]);
}

moveSliderTo(sliderNode, value) {
var valueMax,
valueMin,
pos,
x,
points = '',
width,
dollarValue;
let valueMax;
let valueMin;
let pos;
let points = '';
let x;
let width;

if (this.isMinSlider(sliderNode)) {
valueMin = this.getValueMin(this.minSliderNode);
Expand All @@ -185,7 +190,7 @@ class SliderMultithumb {
value = Math.min(Math.max(value, valueMin), valueMax);

sliderNode.setAttribute('aria-valuenow', value);
dollarValue = '$' + value;
const dollarValue = `$${value}`;

pos = this.railX;
pos += Math.round(
Expand All @@ -194,6 +199,8 @@ class SliderMultithumb {
);

if (this.isMinSlider(sliderNode)) {
this.minSliderPosition = pos;

// update ARIA attributes
this.minSliderValueNode.textContent = dollarValue;
this.maxSliderNode.setAttribute('aria-valuemin', value);
Expand All @@ -209,14 +216,16 @@ class SliderMultithumb {

// Position value
width = this.minSliderValueNode.getBoundingClientRect().width;
pos = pos + (this.thumbWidth - width) / 2;
pos += (this.thumbWidth - width) / 2;
if (pos + width > this.maxSliderLeft - 2) {
pos = this.maxSliderLeft - width - 2;
}
this.minSliderValueNode.setAttribute('x', pos);
this.minSliderRight = pos;
} else {
// update label and ARIA attributes
this.maxSliderPosition = pos;

this.maxSliderValueNode.textContent = dollarValue;
this.minSliderNode.setAttribute('aria-valuemax', value);

Expand All @@ -229,7 +238,10 @@ class SliderMultithumb {
points += ` ${pos + this.thumb2Width},${this.thumbBottom}`;
this.maxSliderThumbNode.setAttribute('points', points);

width = this.maxSliderValueNode.getBoundingClientRect().width;
width = Math.max(
0,
this.maxSliderValueNode.getBoundingClientRect().width
);
pos = pos + this.thumbWidth + (this.thumbWidth - width) / 2;
if (pos - width < this.minSliderRight + 2) {
pos = this.minSliderRight + width + 2;
Expand All @@ -249,11 +261,11 @@ class SliderMultithumb {
}

onSliderKeydown(event) {
var flag = false;
var sliderNode = event.currentTarget;
var value = this.getValue(sliderNode);
var valueMin = this.getValueMin(sliderNode);
var valueMax = this.getValueMax(sliderNode);
let flag = false;
const sliderNode = event.currentTarget;
const value = this.getValue(sliderNode);
const valueMin = this.getValueMin(sliderNode);
const valueMax = this.getValueMax(sliderNode);

switch (event.key) {
case 'ArrowLeft':
Expand Down Expand Up @@ -326,14 +338,14 @@ class SliderMultithumb {
this.movingSliderNode &&
this.domNode.contains(event.target)
) {
var x = this.getSVGPoint(event).x - this.railX;
let x = this.getSVGPoint(event).x - this.railX;
if (this.isMinSliderMoving) {
x = Math.max(0, x - this.thumbWidth / 3);
} else {
x = Math.max(0, x - (5 * this.thumbWidth) / 3);
}
x = Math.min(x, this.railWidth - this.thumbWidth);
var value = Math.round(
const value = Math.round(
(x * this.sliderDiffValue) / (this.railWidth - this.thumbWidth)
);
this.moveSliderTo(this.movingSliderNode, value);
Expand All @@ -347,11 +359,34 @@ class SliderMultithumb {
this.isMoving = false;
this.movingSliderNode = false;
}

// handle click event on the rail
onRailClick(event) {
const x = this.getSVGPoint(event).x - this.railX;
const diffMin = x - this.minSliderPosition - (3 * this.thumbWidth) / 2;
const diffMax = this.maxSliderPosition - x;
const sliderNode =
(x < this.minSliderPosition || diffMin < diffMax) &&
x < this.maxSliderPosition
? this.minSliderNode
: this.maxSliderNode;

let p = Math.max(0, x - this.thumbWidth);
p = Math.min(p, this.railWidth - this.thumbWidth);
const value = Math.round(
(p * this.sliderDiffValue) / (this.railWidth - this.thumbWidth)
);

this.moveSliderTo(sliderNode, value);

event.preventDefault();
event.stopPropagation();
}
}

// Initialize Multithumb Slider widgets on the page
window.addEventListener('load', function () {
var slidersMultithumb = document.querySelectorAll('.slider-multithumb');
window.addEventListener('load', () => {
const slidersMultithumb = document.querySelectorAll('.slider-multithumb');

for (let i = 0; i < slidersMultithumb.length; i++) {
new SliderMultithumb(slidersMultithumb[i]);
Expand Down

0 comments on commit d93a99a

Please sign in to comment.