Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: prevent non-primary for pointer events #796

Merged
merged 1 commit into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/js/signature_pad.umd.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/js/signature_pad.umd.min.js.map

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions src/signature_pad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ export default class SignaturePad extends SignatureEventTarget {
};

private _handlePointerDown = (event: PointerEvent): void => {
if (!this._isLeftButtonPressed(event) || this._drawingStroke) {
if (!event.isPrimary || !this._isLeftButtonPressed(event) || this._drawingStroke) {
return;
}

Expand All @@ -386,6 +386,9 @@ export default class SignaturePad extends SignatureEventTarget {
};

private _handlePointerMove = (event: PointerEvent): void => {
if (!event.isPrimary) {
return;
}
if (!this._isLeftButtonPressed(event, true) || !this._drawingStroke) {
// Stop when primary button not pressed or multiple buttons pressed
this._strokeEnd(this._pointerEventToSignatureEvent(event), false);
Expand All @@ -397,7 +400,7 @@ export default class SignaturePad extends SignatureEventTarget {
};

private _handlePointerUp = (event: PointerEvent): void => {
if (this._isLeftButtonPressed(event)) {
if (!event.isPrimary || this._isLeftButtonPressed(event)) {
return;
}

Expand Down
2 changes: 2 additions & 0 deletions tests/__snapshots__/signature_pad.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ exports[`#toSVG returns SVG image with backgroundColor 1`] = `"<svg xmlns="http:
exports[`#toSVG returns SVG image with high DPI 1`] = `"<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 300 150" width="300" height="150"><circle r="1.5" cx="125" cy="54" fill="black"></circle><circle r="1.5" cx="175" cy="54" fill="black"></circle><path d="M 83.000,57.000 C 83.174,60.510 84.000,60.000 85.000,63.000" stroke-width="5.508" stroke="black" fill="none" stroke-linecap="round"></path><path d="M 85.000,63.000 C 89.060,68.048 88.674,68.010 94.000,72.000" stroke-width="4.407" stroke="black" fill="none" stroke-linecap="round"></path><path d="M 94.000,72.000 C 99.488,75.519 99.060,76.048 105.000,79.000" stroke-width="3.402" stroke="black" fill="none" stroke-linecap="round"></path><path d="M 105.000,79.000 C 108.700,82.157 108.988,81.519 113.000,84.000" stroke-width="3.497" stroke="black" fill="none" stroke-linecap="round"></path><path d="M 113.000,84.000 C 119.500,86.000 119.200,86.657 126.000,88.000" stroke-width="3.228" stroke="black" fill="none" stroke-linecap="round"></path><path d="M 126.000,88.000 C 132.402,90.416 132.500,90.000 139.000,92.000" stroke-width="3.211" stroke="black" fill="none" stroke-linecap="round"></path><path d="M 139.000,92.000 C 144.961,93.475 144.902,93.416 151.000,94.000" stroke-width="3.258" stroke="black" fill="none" stroke-linecap="round"></path><path d="M 151.000,94.000 C 156.569,94.652 156.461,94.475 162.000,94.000" stroke-width="3.366" stroke="black" fill="none" stroke-linecap="round"></path><path d="M 162.000,94.000 C 168.992,92.460 169.069,93.152 176.000,91.000" stroke-width="3.078" stroke="black" fill="none" stroke-linecap="round"></path><path d="M 176.000,91.000 C 181.072,90.285 180.992,89.960 186.000,89.000" stroke-width="3.372" stroke="black" fill="none" stroke-linecap="round"></path><path d="M 186.000,89.000 C 192.582,87.232 192.572,87.285 199.000,85.000" stroke-width="3.133" stroke="black" fill="none" stroke-linecap="round"></path><path d="M 199.000,85.000 C 204.297,83.565 204.082,83.232 209.000,81.000" stroke-width="3.290" stroke="black" fill="none" stroke-linecap="round"></path><path d="M 209.000,81.000 C 215.334,77.407 215.297,77.565 221.000,73.000" stroke-width="3.113" stroke="black" fill="none" stroke-linecap="round"></path><path d="M 221.000,73.000 C 224.115,70.107 224.334,70.407 227.000,67.000" stroke-width="3.535" stroke="black" fill="none" stroke-linecap="round"></path></svg>"`;

exports[`user interactions allows user to paint on the pad 1`] = `"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMzAwIDE1MCIgd2lkdGg9IjMwMCIgaGVpZ2h0PSIxNTAiPjxjaXJjbGUgcj0iMS41IiBjeD0iNTAiIGN5PSIzMCIgZmlsbD0iYmxhY2siPjwvY2lyY2xlPjxjaXJjbGUgcj0iMS41IiBjeD0iMjQwIiBjeT0iMzAiIGZpbGw9ImJsYWNrIj48L2NpcmNsZT48Y2lyY2xlIHI9IjEuNSIgY3g9IjE1MCIgY3k9IjEyMCIgZmlsbD0iYmxhY2siPjwvY2lyY2xlPjwvc3ZnPg=="`;

exports[`user interactions non-primary pointer events are ignored 1`] = `"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMzAwIDE1MCIgd2lkdGg9IjMwMCIgaGVpZ2h0PSIxNTAiPjxjaXJjbGUgcj0iMS41IiBjeD0iNTAiIGN5PSIzMCIgZmlsbD0iYmxhY2siPjwvY2lyY2xlPjwvc3ZnPg=="`;
57 changes: 57 additions & 0 deletions tests/signature_pad.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ describe('user interactions', () => {
const pad = new SignaturePad(canvas);
canvas.dispatchEvent(
new PointerEvent('pointerdown', {
isPrimary: true,
clientX: 50,
clientY: 30,
pressure: 1,
Expand All @@ -275,13 +276,15 @@ describe('user interactions', () => {
);
window.dispatchEvent(
new PointerEvent('pointerup', {
isPrimary: true,
clientX: 50,
clientY: 30,
pressure: 1,
}),
);
canvas.dispatchEvent(
new PointerEvent('pointerdown', {
isPrimary: true,
clientX: 240,
clientY: 30,
pressure: 1,
Expand All @@ -290,13 +293,15 @@ describe('user interactions', () => {
);
window.dispatchEvent(
new PointerEvent('pointerup', {
isPrimary: true,
clientX: 240,
clientY: 30,
pressure: 1,
}),
);
canvas.dispatchEvent(
new PointerEvent('pointerdown', {
isPrimary: true,
clientX: 150,
clientY: 120,
pressure: 1,
Expand All @@ -305,6 +310,7 @@ describe('user interactions', () => {
);
window.dispatchEvent(
new PointerEvent('pointerup', {
isPrimary: true,
clientX: 150,
clientY: 120,
pressure: 1,
Expand All @@ -313,12 +319,52 @@ describe('user interactions', () => {
expect(pad.toDataURL('image/svg+xml')).toMatchSnapshot();
});

it('non-primary pointer events are ignored', () => {
const pad = new SignaturePad(canvas);
canvas.dispatchEvent(
new PointerEvent('pointerdown', {
isPrimary: true,
clientX: 50,
clientY: 30,
pressure: 1,
buttons: 1,
}),
);
canvas.dispatchEvent(
new PointerEvent('pointerdown', {
isPrimary: false,
clientX: 240,
clientY: 30,
pressure: 1,
buttons: 1,
}),
);
window.dispatchEvent(
new PointerEvent('pointerup', {
isPrimary: false,
clientX: 240,
clientY: 30,
pressure: 1,
}),
);
window.dispatchEvent(
new PointerEvent('pointerup', {
isPrimary: true,
clientX: 50,
clientY: 30,
pressure: 1,
}),
);
expect(pad.toDataURL('image/svg+xml')).toMatchSnapshot();
});

it('call endStroke on pointerup outside canvas', () => {
const pad = new SignaturePad(canvas);
const endStroke = jest.fn();
pad.addEventListener('endStroke', endStroke);
canvas.dispatchEvent(
new PointerEvent('pointerdown', {
isPrimary: true,
clientX: 50,
clientY: 30,
pressure: 1,
Expand All @@ -327,6 +373,7 @@ describe('user interactions', () => {
);
window.dispatchEvent(
new PointerEvent('pointermove', {
isPrimary: true,
clientX: 240,
clientY: 30,
pressure: 1,
Expand All @@ -335,6 +382,7 @@ describe('user interactions', () => {
);
window.dispatchEvent(
new PointerEvent('pointerup', {
isPrimary: true,
clientX: 150,
clientY: 120,
pressure: 1,
Expand All @@ -359,6 +407,7 @@ describe('user interactions', () => {

externalCanvas.dispatchEvent(
new PointerEvent('pointerdown', {
isPrimary: true,
clientX: 50,
clientY: 30,
pressure: 1,
Expand All @@ -367,6 +416,7 @@ describe('user interactions', () => {
);
externalCanvas.dispatchEvent(
new PointerEvent('pointermove', {
isPrimary: true,
clientX: 240,
clientY: 30,
pressure: 1,
Expand All @@ -376,6 +426,7 @@ describe('user interactions', () => {
// check that original document is not affected
window.dispatchEvent(
new PointerEvent('pointerup', {
isPrimary: true,
clientX: 150,
clientY: 120,
pressure: 1,
Expand All @@ -385,6 +436,7 @@ describe('user interactions', () => {
// check that external document emits
externalDocument.dispatchEvent(
new PointerEvent('pointerup', {
isPrimary: true,
clientX: 150,
clientY: 120,
pressure: 1,
Expand Down Expand Up @@ -505,6 +557,7 @@ describe('Signature events.', () => {
describe(`${param.eventName}.`, () => {
function createPointerEvent(dispatchedEventName: string) {
return new PointerEvent(dispatchedEventName, {
isPrimary: true,
clientX: 50,
clientY: 30,
pressure: 1,
Expand Down Expand Up @@ -554,6 +607,7 @@ describe('Signature events.', () => {

it('the event should be dispatched.', () => {
const eventInitObj = <PointerEventInit>{
isPrimary: true,
clientX: 50,
clientY: 30,
pressure: 1,
Expand Down Expand Up @@ -581,6 +635,7 @@ describe('Signature events.', () => {

canvas.dispatchEvent(
new PointerEvent('pointerdown', {
isPrimary: true,
clientX: 50,
clientY: 30,
pressure: 1,
Expand All @@ -589,6 +644,7 @@ describe('Signature events.', () => {
);
canvas.dispatchEvent(
new PointerEvent('pointermove', {
isPrimary: true,
clientX: 50,
clientY: 40,
pressure: 1,
Expand All @@ -597,6 +653,7 @@ describe('Signature events.', () => {
);
window.dispatchEvent(
new PointerEvent('pointerup', {
isPrimary: true,
clientX: 50,
clientY: 40,
pressure: 1,
Expand Down
Loading