Merge pull request #14 from PoongalOO/modern-events/ticket7

modernisation des événements d’entrée
This commit is contained in:
PoongalOO 2026-06-08 23:22:48 +02:00 committed by GitHub
commit c4fea9c6b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 84 additions and 15 deletions

View File

@ -15,6 +15,7 @@ La compatibilité avec tous les navigateurs et appareils modernes n'est pas enco
## Modifications réalisées ## Modifications réalisées
- Migration des enregistrements d'événements internes depuis les anciens patterns jQuery `.bind()` / `.unbind()` vers `.on()` / `.off()`. - Migration des enregistrements d'événements internes depuis les anciens patterns jQuery `.bind()` / `.unbind()` vers `.on()` / `.off()`.
- Modernisation des événements d'entrée pour privilégier Pointer Events quand ils sont disponibles, tout en conservant les chemins touch et souris en fallback.
- Ajout de namespaces d'événements : - Ajout de namespaces d'événements :
- `.turn` pour les événements du livre et du document ; - `.turn` pour les événements du livre et du document ;
- `.turnFlip` pour les événements internes des pages pliées. - `.turnFlip` pour les événements internes des pages pliées.

View File

@ -15,6 +15,7 @@ Compatibility is not yet guaranteed for every modern browser or device. Safari/W
## What Changed ## What Changed
- Updated internal event registration from deprecated jQuery `.bind()` / `.unbind()` patterns to `.on()` / `.off()`. - Updated internal event registration from deprecated jQuery `.bind()` / `.unbind()` patterns to `.on()` / `.off()`.
- Modernized input events to prefer Pointer Events when available, with the existing touch and mouse paths kept as fallbacks.
- Added event namespaces: - Added event namespaces:
- `.turn` for book-level and document-level turn.js events. - `.turn` for book-level and document-level turn.js events.
- `.turnFlip` for internal flip-page events. - `.turnFlip` for internal flip-page events.

View File

@ -23,6 +23,11 @@ function createFixture(pageCount = 4, windowOptions = {}) {
}); });
Object.entries(windowOptions).forEach(([key, value]) => { Object.entries(windowOptions).forEach(([key, value]) => {
if (value === undefined) {
delete dom.window[key];
return;
}
Object.defineProperty(dom.window, key, { Object.defineProperty(dom.window, key, {
value, value,
configurable: true, configurable: true,
@ -718,16 +723,67 @@ describe('turn.js jQuery plugin', () => {
.map(call => call[0]) .map(call => call[0])
.filter(name => typeof name === 'string'); .filter(name => typeof name === 'string');
const pointerEvents = $.isTouch
? ['touchstart.turn', 'touchmove.turn', 'touchend.turn']
: ['mousedown.turn', 'mousemove.turn', 'mouseup.turn'];
expect(eventNames).toContain('turned.turn'); expect(eventNames).toContain('turned.turn');
expect(eventNames).toEqual(expect.arrayContaining(pointerEvents)); expect(eventNames).toContain('pointerdown.turn');
expect(eventNames).toContain('pointermove.turn');
expect(eventNames).toContain('pointerup.turn pointercancel.turn');
expect(eventNames).toContain('pressed.turnFlip'); expect(eventNames).toContain('pressed.turnFlip');
expect(eventNames).toContain('released.turnFlip'); expect(eventNames).toContain('released.turnFlip');
expect(eventNames).toContain('start.turnFlip'); expect(eventNames).toContain('start.turnFlip');
expect(eventNames).toContain('end.turnFlip'); expect(eventNames).toContain('end.turnFlip');
expect(eventNames).toContain('flip.turnFlip'); expect(eventNames).toContain('flip.turnFlip');
}); });
it('falls back to touch events when Pointer Events are unavailable', () => {
fixture.window.close();
fixture = createFixture(4, {
PointerEvent: undefined
});
const { $ } = fixture;
const onSpy = vi.spyOn($.fn, 'on');
$('#book').turn({
width: 600,
height: 400,
display: 'double',
gradients: false,
acceleration: false
});
const eventNames = onSpy.mock.calls
.map(call => call[0])
.filter(name => typeof name === 'string');
expect(eventNames).toContain('touchstart.turn');
expect(eventNames).toContain('touchmove.turn');
expect(eventNames).toContain('touchend.turn');
});
it('removes pointer event handlers on destroy', () => {
fixture.window.close();
fixture = createFixture();
const { $ } = fixture;
const offSpy = vi.spyOn($.fn, 'off');
const $book = $('#book');
$book.turn({
width: 600,
height: 400,
display: 'double',
gradients: false,
acceleration: false
});
$book.turn('destroy');
const eventNames = offSpy.mock.calls
.map(call => call[0])
.filter(name => typeof name === 'string');
expect(eventNames).toContain('pointerdown.turn');
expect(eventNames).toContain('pointermove.turn');
expect(eventNames).toContain('pointerup.turn pointercancel.turn');
});
}); });

29
turn.js
View File

@ -29,9 +29,14 @@ var has3d,
A90 = PI/2, A90 = PI/2,
hasPointer = 'PointerEvent' in window,
isTouch = 'ontouchstart' in window, isTouch = 'ontouchstart' in window,
events = (isTouch) ? {start: 'touchstart', move: 'touchmove', end: 'touchend'} usesTouchEvents = !hasPointer && isTouch,
events = (hasPointer) ? {start: 'pointerdown', move: 'pointermove', end: 'pointerup pointercancel'}
: (usesTouchEvents) ? {start: 'touchstart', move: 'touchmove', end: 'touchend'}
: {start: 'mousedown', move: 'mousemove', end: 'mouseup'}, : {start: 'mousedown', move: 'mousemove', end: 'mouseup'},
frameTime = (window.performance && window.performance.now) ? frameTime = (window.performance && window.performance.now) ?
@ -207,6 +212,12 @@ var has3d,
return Object.prototype.hasOwnProperty.call(object, property); return Object.prototype.hasOwnProperty.call(object, property);
}, },
namespacedEvents = function(names, namespace) {
return $.map(names.split(' '), function(name) {
return name + namespace;
}).join(' ');
},
clamp = function(value, min, max) { clamp = function(value, min, max) {
value = parseFloat(value); value = parseFloat(value);
return Math.max(min, Math.min(max, isNaN(value) ? min : value)); return Math.max(min, Math.min(max, isNaN(value) ? min : value));
@ -474,10 +485,10 @@ turnMethods = {
} }
}; };
$(this).on(events.start + turnEventNamespace, data.eventHandlers.start); $(this).on(namespacedEvents(events.start, turnEventNamespace), data.eventHandlers.start);
$(document).on(events.move + turnEventNamespace, data.eventHandlers.move). $(document).on(namespacedEvents(events.move, turnEventNamespace), data.eventHandlers.move).
on(events.end + turnEventNamespace, data.eventHandlers.end); on(namespacedEvents(events.end, turnEventNamespace), data.eventHandlers.end);
data.done = true; data.done = true;
@ -500,10 +511,10 @@ turnMethods = {
this.off(turnEventNamespace); this.off(turnEventNamespace);
if (data.eventHandlers) { if (data.eventHandlers) {
this.off(events.start + turnEventNamespace, data.eventHandlers.start); this.off(namespacedEvents(events.start, turnEventNamespace), data.eventHandlers.start);
$(document). $(document).
off(events.move + turnEventNamespace, data.eventHandlers.move). off(namespacedEvents(events.move, turnEventNamespace), data.eventHandlers.move).
off(events.end + turnEventNamespace, data.eventHandlers.end); off(namespacedEvents(events.end, turnEventNamespace), data.eventHandlers.end);
} }
for (page in data.pageObjs) { for (page in data.pageObjs) {
@ -1569,7 +1580,7 @@ flipMethods = {
return false; return false;
} }
e = (isTouch) ? e.originalEvent.touches : [e]; e = (usesTouchEvents) ? e.originalEvent.touches : [e];
var data = flipData(this), var data = flipData(this),
pos = data.parent.offset(), pos = data.parent.offset(),
@ -2066,7 +2077,7 @@ flipMethods = {
var data = this.data().f; var data = this.data().f;
if (!data.disabled) { if (!data.disabled) {
e = (isTouch) ? e.originalEvent.touches : [e]; e = (usesTouchEvents) ? e.originalEvent.touches : [e];
if (data.corner) { if (data.corner) {

2
turn.min.js vendored

File diff suppressed because one or more lines are too long