From 2b53e3e2ef985a01fecede6a5854428391d83726 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Fri, 26 Nov 2021 15:51:03 +0100 Subject: =?UTF-8?q?Ajout=20pr=C3=A9sentation=20et=20programme=20du=2011/12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2021-11-13/garage/js/controllers/touch.js | 263 +++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 static/presentations/2021-11-13/garage/js/controllers/touch.js (limited to 'static/presentations/2021-11-13/garage/js/controllers/touch.js') diff --git a/static/presentations/2021-11-13/garage/js/controllers/touch.js b/static/presentations/2021-11-13/garage/js/controllers/touch.js new file mode 100644 index 0000000..5ac6a10 --- /dev/null +++ b/static/presentations/2021-11-13/garage/js/controllers/touch.js @@ -0,0 +1,263 @@ +import { isAndroid } from '../utils/device.js' +import { matches } from '../utils/util.js' + +const SWIPE_THRESHOLD = 40; + +/** + * Controls all touch interactions and navigations for + * a presentation. + */ +export default class Touch { + + constructor( Reveal ) { + + this.Reveal = Reveal; + + // Holds information about the currently ongoing touch interaction + this.touchStartX = 0; + this.touchStartY = 0; + this.touchStartCount = 0; + this.touchCaptured = false; + + this.onPointerDown = this.onPointerDown.bind( this ); + this.onPointerMove = this.onPointerMove.bind( this ); + this.onPointerUp = this.onPointerUp.bind( this ); + this.onTouchStart = this.onTouchStart.bind( this ); + this.onTouchMove = this.onTouchMove.bind( this ); + this.onTouchEnd = this.onTouchEnd.bind( this ); + + } + + /** + * + */ + bind() { + + let revealElement = this.Reveal.getRevealElement(); + + if( 'onpointerdown' in window ) { + // Use W3C pointer events + revealElement.addEventListener( 'pointerdown', this.onPointerDown, false ); + revealElement.addEventListener( 'pointermove', this.onPointerMove, false ); + revealElement.addEventListener( 'pointerup', this.onPointerUp, false ); + } + else if( window.navigator.msPointerEnabled ) { + // IE 10 uses prefixed version of pointer events + revealElement.addEventListener( 'MSPointerDown', this.onPointerDown, false ); + revealElement.addEventListener( 'MSPointerMove', this.onPointerMove, false ); + revealElement.addEventListener( 'MSPointerUp', this.onPointerUp, false ); + } + else { + // Fall back to touch events + revealElement.addEventListener( 'touchstart', this.onTouchStart, false ); + revealElement.addEventListener( 'touchmove', this.onTouchMove, false ); + revealElement.addEventListener( 'touchend', this.onTouchEnd, false ); + } + + } + + /** + * + */ + unbind() { + + let revealElement = this.Reveal.getRevealElement(); + + revealElement.removeEventListener( 'pointerdown', this.onPointerDown, false ); + revealElement.removeEventListener( 'pointermove', this.onPointerMove, false ); + revealElement.removeEventListener( 'pointerup', this.onPointerUp, false ); + + revealElement.removeEventListener( 'MSPointerDown', this.onPointerDown, false ); + revealElement.removeEventListener( 'MSPointerMove', this.onPointerMove, false ); + revealElement.removeEventListener( 'MSPointerUp', this.onPointerUp, false ); + + revealElement.removeEventListener( 'touchstart', this.onTouchStart, false ); + revealElement.removeEventListener( 'touchmove', this.onTouchMove, false ); + revealElement.removeEventListener( 'touchend', this.onTouchEnd, false ); + + } + + /** + * Checks if the target element prevents the triggering of + * swipe navigation. + */ + isSwipePrevented( target ) { + + // Prevent accidental swipes when scrubbing timelines + if( matches( target, 'video, audio' ) ) return true; + + while( target && typeof target.hasAttribute === 'function' ) { + if( target.hasAttribute( 'data-prevent-swipe' ) ) return true; + target = target.parentNode; + } + + return false; + + } + + /** + * Handler for the 'touchstart' event, enables support for + * swipe and pinch gestures. + * + * @param {object} event + */ + onTouchStart( event ) { + + if( this.isSwipePrevented( event.target ) ) return true; + + this.touchStartX = event.touches[0].clientX; + this.touchStartY = event.touches[0].clientY; + this.touchStartCount = event.touches.length; + + } + + /** + * Handler for the 'touchmove' event. + * + * @param {object} event + */ + onTouchMove( event ) { + + if( this.isSwipePrevented( event.target ) ) return true; + + let config = this.Reveal.getConfig(); + + // Each touch should only trigger one action + if( !this.touchCaptured ) { + this.Reveal.onUserInput( event ); + + let currentX = event.touches[0].clientX; + let currentY = event.touches[0].clientY; + + // There was only one touch point, look for a swipe + if( event.touches.length === 1 && this.touchStartCount !== 2 ) { + + let availableRoutes = this.Reveal.availableRoutes({ includeFragments: true }); + + let deltaX = currentX - this.touchStartX, + deltaY = currentY - this.touchStartY; + + if( deltaX > SWIPE_THRESHOLD && Math.abs( deltaX ) > Math.abs( deltaY ) ) { + this.touchCaptured = true; + if( config.navigationMode === 'linear' ) { + if( config.rtl ) { + this.Reveal.next(); + } + else { + this.Reveal.prev(); + } + } + else { + this.Reveal.left(); + } + } + else if( deltaX < -SWIPE_THRESHOLD && Math.abs( deltaX ) > Math.abs( deltaY ) ) { + this.touchCaptured = true; + if( config.navigationMode === 'linear' ) { + if( config.rtl ) { + this.Reveal.prev(); + } + else { + this.Reveal.next(); + } + } + else { + this.Reveal.right(); + } + } + else if( deltaY > SWIPE_THRESHOLD && availableRoutes.up ) { + this.touchCaptured = true; + if( config.navigationMode === 'linear' ) { + this.Reveal.prev(); + } + else { + this.Reveal.up(); + } + } + else if( deltaY < -SWIPE_THRESHOLD && availableRoutes.down ) { + this.touchCaptured = true; + if( config.navigationMode === 'linear' ) { + this.Reveal.next(); + } + else { + this.Reveal.down(); + } + } + + // If we're embedded, only block touch events if they have + // triggered an action + if( config.embedded ) { + if( this.touchCaptured || this.Reveal.isVerticalSlide() ) { + event.preventDefault(); + } + } + // Not embedded? Block them all to avoid needless tossing + // around of the viewport in iOS + else { + event.preventDefault(); + } + + } + } + // There's a bug with swiping on some Android devices unless + // the default action is always prevented + else if( isAndroid ) { + event.preventDefault(); + } + + } + + /** + * Handler for the 'touchend' event. + * + * @param {object} event + */ + onTouchEnd( event ) { + + this.touchCaptured = false; + + } + + /** + * Convert pointer down to touch start. + * + * @param {object} event + */ + onPointerDown( event ) { + + if( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === "touch" ) { + event.touches = [{ clientX: event.clientX, clientY: event.clientY }]; + this.onTouchStart( event ); + } + + } + + /** + * Convert pointer move to touch move. + * + * @param {object} event + */ + onPointerMove( event ) { + + if( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === "touch" ) { + event.touches = [{ clientX: event.clientX, clientY: event.clientY }]; + this.onTouchMove( event ); + } + + } + + /** + * Convert pointer up to touch end. + * + * @param {object} event + */ + onPointerUp( event ) { + + if( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === "touch" ) { + event.touches = [{ clientX: event.clientX, clientY: event.clientY }]; + this.onTouchEnd( event ); + } + + } + +} \ No newline at end of file -- cgit v1.2.3