Skip to content

Commit 37c2b06

Browse files
authored
Merge pull request #56 from happyprime/fix/swipe-slider-pointer
Fix erratic mouse behavior in the swipe (slider) compare view
2 parents 8edfdf5 + f6d9822 commit 37c2b06

2 files changed

Lines changed: 38 additions & 4 deletions

File tree

templates/assets/app.js

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,13 @@
11911191
function buildSwipe(stage, img) {
11921192
var pos = 0.5;
11931193
var layer = h('div', { class: 'layer' }, [
1194-
h('img', { src: img.control, alt: 'Baseline screenshot' }),
1194+
h('img', {
1195+
src: img.control,
1196+
alt: 'Baseline screenshot',
1197+
// String 'false', not boolean: the h() helper drops false-valued
1198+
// props, and draggable is an enumerated attribute anyway.
1199+
draggable: 'false',
1200+
}),
11951201
]);
11961202
var divider = h(
11971203
'div',
@@ -1216,7 +1222,11 @@
12161222
};
12171223
var dragging = false;
12181224
var shot = h('div', { class: 'shot swipe-stage' }, [
1219-
h('img', { src: img.capture, alt: 'Current screenshot' }),
1225+
h('img', {
1226+
src: img.capture,
1227+
alt: 'Current screenshot',
1228+
draggable: 'false',
1229+
}),
12201230
layer,
12211231
divider,
12221232
h('span', { class: 'taglabel l', text: 'baseline' }),
@@ -1226,7 +1236,23 @@
12261236
var rect = shot.getBoundingClientRect();
12271237
return clamp01((e.clientX - rect.left) / rect.width);
12281238
};
1239+
var endDrag = function (e) {
1240+
dragging = false;
1241+
// Release capture so the stage stops receiving pointer events once
1242+
// the gesture is over.
1243+
if (e && shot.hasPointerCapture(e.pointerId)) {
1244+
shot.releasePointerCapture(e.pointerId);
1245+
}
1246+
};
12291247
shot.addEventListener('pointerdown', function (e) {
1248+
// Primary button / touch / pen only — ignore right- and middle-click.
1249+
if (e.button !== 0) {
1250+
return;
1251+
}
1252+
// Suppress the browser's native image drag and text selection, which
1253+
// would otherwise hijack the gesture and fire pointercancel instead
1254+
// of pointerup, leaving the divider stuck to the cursor.
1255+
e.preventDefault();
12301256
dragging = true;
12311257
shot.setPointerCapture(e.pointerId);
12321258
setPos(posFromEvent(e));
@@ -1236,7 +1262,11 @@
12361262
setPos(posFromEvent(e));
12371263
}
12381264
});
1239-
shot.addEventListener('pointerup', function () {
1265+
// End on up and on cancel/lost-capture, so an interrupted gesture can
1266+
// never leave dragging stuck on.
1267+
shot.addEventListener('pointerup', endDrag);
1268+
shot.addEventListener('pointercancel', endDrag);
1269+
shot.addEventListener('lostpointercapture', function () {
12401270
dragging = false;
12411271
});
12421272
stage.appendChild(shot);

templates/assets/reglance.css

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,11 @@ kbd {
386386
.taglabel.l { left: 10px; }
387387
.taglabel.r { right: 10px; }
388388

389-
.swipe-stage { cursor: col-resize; touch-action: none; }
389+
.swipe-stage { cursor: col-resize; touch-action: none; user-select: none; }
390+
/* The images are never the pointer target: the stage handles the whole
391+
gesture, and a non-draggable, non-selectable image can't start a native
392+
drag that would hijack it. */
393+
.swipe-stage img { pointer-events: none; -webkit-user-drag: none; user-select: none; }
390394
.divider { position: absolute; top: 0; bottom: 0; width: 0; z-index: 5; pointer-events: none; }
391395
.divider::before {
392396
content: '';

0 commit comments

Comments
 (0)