From d1ea179296f269a22fb0fab4f7f8aff2bb150991 Mon Sep 17 00:00:00 2001
From: Oeystein Lygre <oystein@ramsalt.com>
Date: Mon, 21 Aug 2017 22:38:44 +0200
Subject: [PATCH] manage preventDefaultAction flag in canvas-double-click
 viewer event

Trigger the canvas-double-click event before default double tap to zoom happens on the viewer
---
 src/viewer.js          | 37 ++++++++++++---------
 test/modules/events.js | 73 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+), 16 deletions(-)

diff --git a/src/viewer.js b/src/viewer.js
index 0921eca8..dc1d7438 100644
--- a/src/viewer.js
+++ b/src/viewer.js
@@ -2611,16 +2611,14 @@ function onCanvasClick( event ) {
 function onCanvasDblClick( event ) {
     var gestureSettings;
 
-    if ( !event.preventDefaultAction && this.viewport ) {
-        gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
-        if ( gestureSettings.dblClickToZoom ) {
-            this.viewport.zoomBy(
-                event.shift ? 1.0 / this.zoomPerClick : this.zoomPerClick,
-                this.viewport.pointFromPixel( event.position, true )
-            );
-            this.viewport.applyConstraints();
-        }
-    }
+    var canvasDblClickEventArgs = {
+        tracker: event.eventSource,
+        position: event.position,
+        shift: event.shift,
+        originalEvent: event.originalEvent,
+        preventDefaultAction: event.preventDefaultAction
+    };
+
     /**
      * Raised when a double mouse press/release or touch/remove occurs on the {@link OpenSeadragon.Viewer#canvas} element.
      *
@@ -2632,14 +2630,21 @@ function onCanvasDblClick( event ) {
      * @property {OpenSeadragon.Point} position - The position of the event relative to the tracked element.
      * @property {Boolean} shift - True if the shift key was pressed during this event.
      * @property {Object} originalEvent - The original DOM event.
+     * @property {Boolean} preventDefaultAction - Set to true to prevent default double tap to zoom behaviour. Default: false.
      * @property {?Object} userData - Arbitrary subscriber-defined object.
      */
-    this.raiseEvent( 'canvas-double-click', {
-        tracker: event.eventSource,
-        position: event.position,
-        shift: event.shift,
-        originalEvent: event.originalEvent
-    });
+    this.raiseEvent( 'canvas-double-click', canvasDblClickEventArgs);
+
+    if ( !canvasDblClickEventArgs.preventDefaultAction && this.viewport ) {
+        gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
+        if ( gestureSettings.dblClickToZoom ) {
+            this.viewport.zoomBy(
+                event.shift ? 1.0 / this.zoomPerClick : this.zoomPerClick,
+                this.viewport.pointFromPixel( event.position, true )
+            );
+            this.viewport.applyConstraints();
+        }
+    }
 }
 
 function onCanvasDrag( event ) {
diff --git a/test/modules/events.js b/test/modules/events.js
index 7e681d05..af226a44 100644
--- a/test/modules/events.js
+++ b/test/modules/events.js
@@ -833,6 +833,79 @@
         viewer.open('/test/data/testpattern.dzi');
     });
 
+    // ----------
+    asyncTest('Viewer: preventDefaultAction in dblClickHandler', function() {
+        var tracker = viewer.innerTracker;
+        var epsilon = 0.0000001;
+
+        function simulateDblTap() {
+            var touches = [];
+            TouchUtil.reset();
+
+            touches.push(TouchUtil.start([0,0]));
+            TouchUtil.end( touches[0] );
+            touches.push(TouchUtil.start([0,0]));
+            TouchUtil.end( touches[1] );
+        }
+
+        var onOpen = function() {
+            viewer.removeHandler('open', onOpen);
+
+            var originalZoom = viewer.viewport.getZoom();
+
+            var origDblClickHandler = tracker.dblClickHandler;
+            tracker.dblClickHandler = function(event) {
+                event.preventDefaultAction = true;
+                return origDblClickHandler(event);
+            };
+
+            TouchUtil.initTracker(tracker);
+            simulateDblTap();
+
+            var zoom = viewer.viewport.getZoom();
+            Util.assessNumericValue(originalZoom, zoom, epsilon,
+                "Zoom on double tap should be prevented");
+
+            // Reset event handler to original
+            tracker.dblClickHandler = origDblClickHandler;
+
+            simulateDblTap();
+            originalZoom = originalZoom * viewer.zoomPerClick;
+
+            var zoom = viewer.viewport.getZoom();
+            Util.assessNumericValue(originalZoom, zoom, epsilon,
+                "Zoom on double tap should not be prevented");
+
+
+            var dblClickHandler = function(event) {
+                event.preventDefaultAction = true;
+            }
+
+            viewer.addHandler('canvas-double-click', dblClickHandler);
+
+            var zoom = viewer.viewport.getZoom();
+            Util.assessNumericValue(originalZoom, zoom, epsilon,
+                "Zoom on double tap should be prevented");
+
+            // Remove custom event handler
+            viewer.removeHandler('canvas-double-click', dblClickHandler);
+
+            simulateDblTap();
+            originalZoom = originalZoom * viewer.zoomPerClick;
+
+            var zoom = viewer.viewport.getZoom();
+            Util.assessNumericValue(originalZoom, zoom, epsilon,
+                "Zoom on double tap should not be prevented");
+
+            TouchUtil.resetTracker(tracker);
+            viewer.close();
+            start();
+        };
+
+        viewer.addHandler('open', onOpen);
+        viewer.open('/test/data/testpattern.dzi');
+    });
+
     // ----------
     asyncTest( 'EventSource/MouseTracker/Viewer: event.originalEvent event.userData canvas-drag canvas-drag-end canvas-release canvas-click', function () {
         var $canvas = $( viewer.element ).find( '.openseadragon-canvas' ).not( '.navigator .openseadragon-canvas' ),