Skip to content

Commit

Permalink
fixed pointer bug
Browse files Browse the repository at this point in the history
  • Loading branch information
jongund committed Nov 29, 2023
1 parent 6729e7c commit 7383879
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 113 deletions.
14 changes: 10 additions & 4 deletions content/patterns/slider/examples/css/slider-rating.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@

.rating-slider {
color: #005a9c;
-webkit-touch-callout: none;

Check failure on line 9 in content/patterns/slider/examples/css/slider-rating.css

View workflow job for this annotation

GitHub Actions / spelling

Unknown word (callout)

Check failure on line 9 in content/patterns/slider/examples/css/slider-rating.css

View workflow job for this annotation

GitHub Actions / spelling

Unknown word (callout)
user-select: none;
user-select: none;
user-select: none;
user-select: none;
user-select: none;
}

.rating-slider svg {
Expand All @@ -19,7 +25,7 @@
fill-opacity: 0;
}

.rating-slider svg .value {
.rating-slider svg .target {
stroke-width: 2px;
stroke: currentcolor;
fill-opacity: 0;
Expand All @@ -36,7 +42,7 @@
fill: canvastext;
}

.rating-slider svg .current .value {
.rating-slider svg .current .target {
fill: currentcolor;
fill-opacity: 1;
}
Expand Down Expand Up @@ -69,7 +75,7 @@
fill: linktext;
}

.rating-slider svg .value {
.rating-slider svg .target {
stroke: linktext;
}

Expand All @@ -81,7 +87,7 @@
fill: linktext;
}

.rating-slider svg .current .value {
.rating-slider svg .current .target {
fill: linktext;
}

Expand Down
163 changes: 74 additions & 89 deletions content/patterns/slider/examples/js/slider-rating.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,34 @@ class RatingSlider {
this.svgNode = domNode.querySelector('svg');
this.focusRect = domNode.querySelector('.focus-ring');

this.ratingRects = Array.from(
domNode.querySelectorAll('g.rating rect.value')
this.targetRects = Array.from(
domNode.querySelectorAll('g.rating rect.target')
);

this.ratingRectLabels = Array.from(
this.labelTexts = Array.from(
domNode.querySelectorAll('g.rating text.label')
);

[this.infoRatingRects, this.railWidth] = this.calcRatingRects();
[this.infoTargetRects, this.railWidth] = this.calcRatingRects();
this.infoDefaultFocusRect = this.calcDefaultFocusRect();

this.valueMin = this.getValueMin();
this.valueMax = this.getValueMax();

this.svgPoint = this.svgNode.createSVGPoint();

// define possible slider positions

this.sliderNode.addEventListener(
'keydown',
this.onSliderKeydown.bind(this)
);

this.svgNode.addEventListener('click', this.onRailClick.bind(this));
this.svgNode.addEventListener(
'pointerdown',
this.onSliderPointerDown.bind(this)
);
this.labelTexts.forEach((lt) => {
lt.addEventListener('click', this.onTargetClick.bind(this));
});

// bind a pointermove event handler to move pointer
this.svgNode.addEventListener('pointermove', this.onPointerMove.bind(this));
this.targetRects.forEach((tr) => {
tr.addEventListener('click', this.onTargetClick.bind(this));
tr.addEventListener('pointerdown', this.onSliderPointerDown.bind(this));
tr.addEventListener('pointermove', this.onPointerMove.bind(this));
});

// bind a pointerup event handler to stop tracking pointer movements
document.addEventListener('pointerup', this.onPointerUp.bind(this));
Expand All @@ -68,13 +65,6 @@ class RatingSlider {
this.setFocusRing(0);
}

// Get point in global SVG space
getSVGPoint(event) {
this.svgPoint.x = event.clientX;
this.svgPoint.y = event.clientY;
return this.svgPoint.matrixTransform(this.svgNode.getScreenCTM().inverse());
}

getValue() {
return parseFloat(this.sliderNode.getAttribute('aria-valuenow'));
}
Expand Down Expand Up @@ -182,29 +172,29 @@ class RatingSlider {

let left = RAIL_LEFT;

for (let i = 0; i < this.ratingRects.length; i += 1) {
const rectNode = this.ratingRects[i];
const labelNode = this.ratingRectLabels[i];
for (let i = 0; i < this.targetRects.length; i += 1) {
const targetNode = this.targetRects[i];
const labelNode = this.labelTexts[i];

rectNode.setAttribute('x', left);
rectNode.setAttribute('y', RAIL_TOP);
rectNode.setAttribute('width', rectWidth);
rectNode.setAttribute('height', RAIL_HEIGHT);
rectNode.removeAttribute('rx');
targetNode.setAttribute('x', left);
targetNode.setAttribute('y', RAIL_TOP);
targetNode.setAttribute('width', rectWidth);
targetNode.setAttribute('height', RAIL_HEIGHT);
targetNode.removeAttribute('rx');

this.setLabelPosition(labelNode, left, rectWidth);

const infoRect = {
const infoTarget = {
x: left,
y: RAIL_TOP,
width: rectWidth,
height: RAIL_HEIGHT,
rx: 0,
};

infoRatingRects[i] = infoRect;
infoRatingRects[i] = infoTarget;

rectNode.parentNode.classList.remove('current');
targetNode.parentNode.classList.remove('current');

left += rectWidth;
}
Expand All @@ -231,61 +221,61 @@ class RatingSlider {
}

resetRects() {
for (let i = 0; i < this.ratingRects.length; i += 1) {
const rectNode = this.ratingRects[i];
const infoRect = this.infoRatingRects[i];
const labelNode = this.ratingRectLabels[i];
for (let i = 0; i < this.targetRects.length; i += 1) {
const targetNode = this.targetRects[i];
const infoTarget = this.infoTargetRects[i];
const labelNode = this.labelTexts[i];

rectNode.setAttribute('x', infoRect.x);
rectNode.setAttribute('y', infoRect.y);
rectNode.setAttribute('width', infoRect.width);
rectNode.setAttribute('height', infoRect.height);
rectNode.removeAttribute('rx');
targetNode.setAttribute('x', infoTarget.x);
targetNode.setAttribute('y', infoTarget.y);
targetNode.setAttribute('width', infoTarget.width);
targetNode.setAttribute('height', infoTarget.height);
targetNode.removeAttribute('rx');

this.setLabelPosition(labelNode, infoRect.x, infoRect.width);
this.setLabelPosition(labelNode, infoTarget.x, infoTarget.width);

rectNode.parentNode.classList.remove('current');
targetNode.parentNode.classList.remove('current');
}
}

setSelectedRatingRect(value) {
let labelNode, rectNode, infoRect;
let labelNode, targetNode, infoTarget;

const leftValue = value - 1;
const rightValue = value + 1;

if (value > 0) {
rectNode = this.ratingRects[value - 1];
infoRect = this.infoRatingRects[value - 1];
labelNode = this.ratingRectLabels[value - 1];
targetNode = this.targetRects[value - 1];
infoTarget = this.infoTargetRects[value - 1];
labelNode = this.labelTexts[value - 1];

rectNode.parentNode.classList.add('current');
targetNode.parentNode.classList.add('current');

const rectWidth = infoRect.width + 2 * SELECTED_SIZE;
const x = infoRect.x - SELECTED_SIZE;
const rectWidth = infoTarget.width + 2 * SELECTED_SIZE;
const x = infoTarget.x - SELECTED_SIZE;

rectNode.setAttribute('x', x);
rectNode.setAttribute('y', infoRect.y - SELECTED_SIZE);
rectNode.setAttribute('width', rectWidth);
rectNode.setAttribute('height', infoRect.height + 2 * SELECTED_SIZE);
rectNode.setAttribute('rx', SELECTED_SIZE);
targetNode.setAttribute('x', x);
targetNode.setAttribute('y', infoTarget.y - SELECTED_SIZE);
targetNode.setAttribute('width', rectWidth);
targetNode.setAttribute('height', infoTarget.height + 2 * SELECTED_SIZE);
targetNode.setAttribute('rx', SELECTED_SIZE);

this.setLabelPosition(labelNode, x, rectWidth, '120%');
}

if (leftValue > 0) {
rectNode = this.ratingRects[leftValue - 1];
infoRect = this.infoRatingRects[leftValue - 1];
targetNode = this.targetRects[leftValue - 1];
infoTarget = this.infoTargetRects[leftValue - 1];

rectNode.setAttribute('width', infoRect.width - SELECTED_SIZE);
targetNode.setAttribute('width', infoTarget.width - SELECTED_SIZE);
}

if (rightValue <= this.valueMax && value > 0) {
rectNode = this.ratingRects[rightValue - 1];
infoRect = this.infoRatingRects[rightValue - 1];
targetNode = this.targetRects[rightValue - 1];
infoTarget = this.infoTargetRects[rightValue - 1];

rectNode.setAttribute('x', infoRect.x + SELECTED_SIZE);
rectNode.setAttribute('width', infoRect.width - SELECTED_SIZE);
targetNode.setAttribute('x', infoTarget.x + SELECTED_SIZE);
targetNode.setAttribute('width', infoTarget.width - SELECTED_SIZE);
}
}

Expand All @@ -312,12 +302,12 @@ class RatingSlider {
const size = 2 * SELECTED_SIZE;

if (value > 0 && value <= this.valueMax) {
const infoRect = this.infoRatingRects[value - 1];
const infoTarget = this.infoTargetRects[value - 1];

this.focusRect.setAttribute('x', infoRect.x - size);
this.focusRect.setAttribute('y', infoRect.y - size);
this.focusRect.setAttribute('width', infoRect.width + 2 * size);
this.focusRect.setAttribute('height', infoRect.height + 2 * size);
this.focusRect.setAttribute('x', infoTarget.x - size);
this.focusRect.setAttribute('y', infoTarget.y - size);
this.focusRect.setAttribute('width', infoTarget.width + 2 * size);
this.focusRect.setAttribute('height', infoTarget.height + 2 * size);
this.focusRect.setAttribute('rx', size);
} else {
// Set ring around entire control
Expand Down Expand Up @@ -392,13 +382,10 @@ class RatingSlider {
this.sliderNode.setAttribute('aria-valuetext', valuetext);
}

onRailClick(event) {
const x = this.getSVGPoint(event).x;
const diffX = x - RAIL_LEFT;
const rating = (diffX * this.valueMax) / this.railWidth;
const value = Math.ceil(rating);

this.moveSliderTo(value);
onTargetClick(event) {
this.moveSliderTo(
event.currentTarget.parentNode.getAttribute('data-value')
);

event.preventDefault();
event.stopPropagation();
Expand All @@ -408,35 +395,33 @@ class RatingSlider {
}

onSliderPointerDown(event) {
this.isMoving = true;

if (!this.isMoving) {
this.isMoving = true;
}
event.preventDefault();
event.stopPropagation();

// Set focus to the clicked handle
this.sliderNode.focus();
}

onPointerMove(event) {
if (this.isMoving) {
const x = this.getSVGPoint(event).x;
const diffX = x - RAIL_LEFT;
const rating = (diffX * this.valueMax) / this.railWidth;
const value = Math.ceil(rating);

this.moveSliderTo(value);

this.moveSliderTo(
event.currentTarget.parentNode.getAttribute('data-value')
);
event.preventDefault();
event.stopPropagation();
}
}

onPointerUp() {
this.isMoving = false;
if (this.isMoving) {
this.isMoving = false;
// Set focus to the clicked handle
this.sliderNode.focus();
}
}

onResize() {
[this.infoRatingRects, this.railWidth] = this.calcRatingRects();
[this.infoTargetRects, this.railWidth] = this.calcRatingRects();
this.infoDefaultFocusRect = this.calcDefaultFocusRect();
this.setSelectedRatingRect(this.getValue());
this.setFocusRing(this.getValue());
Expand Down
40 changes: 20 additions & 20 deletions content/patterns/slider/examples/slider-rating.html
Original file line number Diff line number Diff line change
Expand Up @@ -73,45 +73,45 @@ <h2 id="ex_label">Example</h2>

<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="800" height="110">
<rect class="focus-ring" x="23" y="2" width="54" height="90" rx="5" />
<g class="rating">
<rect class="value" height="24" width="32" x="13" y="30"></rect>
<g class="rating" data-value="1">
<rect class="target" height="24" width="32" x="13" y="30"></rect>
<text class="label" x="25" y="47">1</text>
<text class="description" x="13" y="20">Extremely Unsatisfied</text>
</g>
<g class="rating">
<rect class="value" height="24" width="32" x="45" y="30"></rect>
<g class="rating" data-value="2">
<rect class="target" height="24" width="32" x="45" y="30"></rect>
<text class="label" x="58" y="47">2</text>
</g>
<g class="rating">
<rect class="value" height="24" width="32" x="77" y="30"></rect>
<g class="rating" data-value="3">
<rect class="target" height="24" width="32" x="77" y="30"></rect>
<text class="label" x="91" y="47">3</text>
</g>
<g class="rating">
<rect class="value" height="24" width="32" x="109" y="30"></rect>
<g class="rating" data-value="4">
<rect class="target" height="24" width="32" x="109" y="30"></rect>
<text class="label" x="121" y="47">4</text>
</g>
<g class="rating">
<rect class="value" height="24" width="32" x="141" y="30"></rect>
<g class="rating" data-value="5">
<rect class="target" height="24" width="32" x="141" y="30"></rect>
<text class="label" x="153" y="47">5</text>
</g>
<g class="rating">
<rect class="value" height="24" width="32" x="173" y="30"></rect>
<g class="rating" data-value="6">
<rect class="target" height="24" width="32" x="173" y="30"></rect>
<text class="label" x="185" y="47">6</text>
</g>
<g class="rating">
<rect class="value" height="24" width="32" x="205" y="30"></rect>
<g class="rating" data-value="7">
<rect class="target" height="24" width="32" x="205" y="30"></rect>
<text class="label" x="217" y="47">7</text>
</g>
<g class="rating">
<rect class="value" height="24" width="32" x="237" y="30"></rect>
<g class="rating" data-value="8">
<rect class="target" height="24" width="32" x="237" y="30"></rect>
<text class="label" x="249" y="47">8</text>
</g>
<g class="rating">
<rect class="value" height="24" width="32" x="269" y="30"></rect>
<g class="rating" data-value="9">
<rect class="target" height="24" width="32" x="269" y="30"></rect>
<text class="label" x="281" y="47">9</text>
</g>
<g class="rating">
<rect class="value" height="24" width="32" x="301" y="30"></rect>
<g class="rating" data-value="10">
<rect class="target" height="24" width="32" x="301" y="30"></rect>
<text class="label" x="310" y="47">10</text>
<text class="description" x="208" y="20">Extremely Satisfied</text>
</g>
Expand Down

0 comments on commit 7383879

Please sign in to comment.