From 8e325a37482bed4c06ffe80b028a76a4bebc1816 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Mon, 4 Nov 2013 12:41:45 -0800 Subject: [PATCH 1/2] Added preventDefaultAction flag to MouseTracker Added a boolean preventDefaultAction property (default false) to the event object passed to MouseTracker handler methods. Implemented in the following MouseTracker subscribers: * Viewer.keyboardCommandArea.innerTracker.focusHandler: preventDefaultAction == true prevents scrolling viewer into view * Viewer.keyboardCommandArea.innerTracker.keyHandler: preventDefaultAction == true prevents viewer keyboard navigation * Viewer.innerTracker.clickHandler: preventDefaultAction == true prevents viewer zoom on click * Viewer.innerTracker.dragHandler: preventDefaultAction == true prevents viewer panning with mouse/touch * Viewer.innerTracker.scrollHandler: preventDefaultAction == true prevents viewer zooming on mousewheel/pinch --- changelog.txt | 6 ++ src/mousetracker.js | 168 +++++++++++++++++++++++++++----------------- src/viewer.js | 104 ++++++++++++++------------- 3 files changed, 162 insertions(+), 116 deletions(-) diff --git a/changelog.txt b/changelog.txt index 0b52e2b6..14d090d5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -37,6 +37,12 @@ OPENSEADRAGON CHANGELOG * Fixed: IE 10 not reading DZI file correctly in certain circumstances (#218) * Added support for the 'wheel' DOM mousewheel event (#261) * Fix for non-canvas tile rendering at large size (#264) +* Added a boolean preventDefaultAction property (default false) to the event object passed to MouseTracker handler methods. Implemented in the following MouseTracker subscribers: + * Viewer.keyboardCommandArea.innerTracker.focusHandler: preventDefaultAction == true prevents scrolling viewer into view + * Viewer.keyboardCommandArea.innerTracker.keyHandler: preventDefaultAction == true prevents viewer keyboard navigation + * Viewer.innerTracker.clickHandler: preventDefaultAction == true prevents viewer zoom on click + * Viewer.innerTracker.dragHandler: preventDefaultAction == true prevents viewer panning with mouse/touch + * Viewer.innerTracker.scrollHandler: preventDefaultAction == true prevents viewer zooming on mousewheel/pinch 0.9.131: diff --git a/src/mousetracker.js b/src/mousetracker.js index a7798b97..c2a7d446 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -243,6 +243,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -266,6 +268,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -284,6 +288,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -307,6 +313,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -325,6 +333,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -347,6 +357,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -369,6 +381,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -391,6 +405,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -409,6 +425,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -427,6 +445,8 @@ * True if the shift key was pressed during this event. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -441,6 +461,8 @@ * A reference to the tracker instance. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -455,6 +477,8 @@ * A reference to the tracker instance. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -673,9 +697,10 @@ if ( tracker.focusHandler ) { propagate = tracker.focusHandler( { - eventSource: tracker, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -695,9 +720,10 @@ if ( tracker.blurHandler ) { propagate = tracker.blurHandler( { - eventSource: tracker, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -717,12 +743,13 @@ if ( tracker.keyHandler ) { propagate = tracker.keyHandler( { - eventSource: tracker, - position: getMouseRelative( event, tracker.element ), - keyCode: event.keyCode ? event.keyCode : event.charCode, - shift: event.shiftKey, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( event, tracker.element ), + keyCode: event.keyCode ? event.keyCode : event.charCode, + shift: event.shiftKey, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( !propagate ) { @@ -772,13 +799,14 @@ if ( tracker.enterHandler ) { propagate = tracker.enterHandler( { - eventSource: tracker, - position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), + eventSource: tracker, + position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), insideElementPressed: delegate.insideElementPressed, - buttonDownAny: IS_BUTTON_DOWN, - isTouchEvent: isTouch, - originalEvent: event, - userData: tracker.userData + buttonDownAny: IS_BUTTON_DOWN, + isTouchEvent: isTouch, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -828,13 +856,14 @@ if ( tracker.exitHandler ) { propagate = tracker.exitHandler( { - eventSource: tracker, - position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), + eventSource: tracker, + position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), insideElementPressed: delegate.insideElementPressed, - buttonDownAny: IS_BUTTON_DOWN, - isTouchEvent: isTouch, - originalEvent: event, - userData: tracker.userData + buttonDownAny: IS_BUTTON_DOWN, + isTouchEvent: isTouch, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); @@ -872,11 +901,12 @@ if ( tracker.pressHandler ) { propagate = tracker.pressHandler( { - eventSource: tracker, - position: getMouseRelative( eventOrTouchPoint, tracker.element ), - isTouchEvent: isTouch, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( eventOrTouchPoint, tracker.element ), + isTouchEvent: isTouch, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -967,13 +997,14 @@ if ( tracker.releaseHandler ) { propagate = tracker.releaseHandler( { - eventSource: tracker, - position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), - insideElementPressed: insideElementPressed, + eventSource: tracker, + position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), + insideElementPressed: insideElementPressed, insideElementReleased: insideElementReleased, - isTouchEvent: isTouch, - originalEvent: event, - userData: tracker.userData + isTouchEvent: isTouch, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -1085,11 +1116,12 @@ var propagate = tracker.moveHandler( { - eventSource: tracker, - position: getMouseRelative( event, tracker.element ), - isTouchEvent: false, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( event, tracker.element ), + isTouchEvent: false, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -1111,11 +1143,12 @@ function onMouseStop( tracker, originalMoveEvent ) { if ( tracker.stopHandler ) { tracker.stopHandler( { - eventSource: tracker, - position: getMouseRelative( originalMoveEvent, tracker.element ), - isTouchEvent: false, - originalEvent: originalMoveEvent, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( originalMoveEvent, tracker.element ), + isTouchEvent: false, + originalEvent: originalMoveEvent, + preventDefaultAction: false, + userData: tracker.userData } ); } } @@ -1200,13 +1233,14 @@ if ( tracker.scrollHandler ) { propagate = tracker.scrollHandler( { - eventSource: tracker, - position: getMouseRelative( event, tracker.element ), - scroll: nDelta, - shift: event.shiftKey, - isTouchEvent: isTouch, - originalEvent: originalEvent, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( event, tracker.element ), + scroll: nDelta, + shift: event.shiftKey, + isTouchEvent: isTouch, + originalEvent: originalEvent, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -1243,13 +1277,14 @@ if ( tracker.clickHandler ) { propagate = tracker.clickHandler( { - eventSource: tracker, - position: getMouseRelative( eventOrTouchPoint, tracker.element ), - quick: quick, - shift: event.shiftKey, - isTouchEvent: isTouch, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( eventOrTouchPoint, tracker.element ), + quick: quick, + shift: event.shiftKey, + isTouchEvent: isTouch, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -1281,13 +1316,14 @@ if ( tracker.dragHandler ) { propagate = tracker.dragHandler( { - eventSource: tracker, - position: getMouseRelative( eventOrTouchPoint, tracker.element ), - delta: delta, - shift: event.shiftKey, - isTouchEvent: isTouch, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( eventOrTouchPoint, tracker.element ), + delta: delta, + shift: event.shiftKey, + isTouchEvent: isTouch, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { diff --git a/src/viewer.js b/src/viewer.js index d12c007f..9133afbb 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -276,58 +276,62 @@ $.Viewer = function( options ) { this.keyboardCommandArea.innerTracker = new $.MouseTracker({ _this : this, element: this.keyboardCommandArea, - focusHandler: function(){ - var point = $.getElementPosition( this.element ); - window.scrollTo( 0, point.y ); + focusHandler: function( event ){ + if ( !event.preventDefaultAction ) { + var point = $.getElementPosition( this.element ); + window.scrollTo( 0, point.y ); + } }, keyHandler: function( event ){ - switch( event.keyCode ){ - case 61://=|+ - _this.viewport.zoomBy(1.1); - _this.viewport.applyConstraints(); - return false; - case 45://-|_ - _this.viewport.zoomBy(0.9); - _this.viewport.applyConstraints(); - return false; - case 48://0|) - _this.viewport.goHome(); - _this.viewport.applyConstraints(); - return false; - case 119://w - case 87://W - case 38://up arrow - if ( event.shift ) { + if ( !event.preventDefaultAction ) { + switch( event.keyCode ){ + case 61://=|+ _this.viewport.zoomBy(1.1); - } else { - _this.viewport.panBy(new $.Point(0, -0.05)); - } - _this.viewport.applyConstraints(); - return false; - case 115://s - case 83://S - case 40://down arrow - if ( event.shift ) { + _this.viewport.applyConstraints(); + return false; + case 45://-|_ _this.viewport.zoomBy(0.9); - } else { - _this.viewport.panBy(new $.Point(0, 0.05)); - } - _this.viewport.applyConstraints(); - return false; - case 97://a - case 37://left arrow - _this.viewport.panBy(new $.Point(-0.05, 0)); - _this.viewport.applyConstraints(); - return false; - case 100://d - case 39://right arrow - _this.viewport.panBy(new $.Point(0.05, 0)); - _this.viewport.applyConstraints(); - return false; - default: - //console.log( 'navigator keycode %s', event.keyCode ); - return true; + _this.viewport.applyConstraints(); + return false; + case 48://0|) + _this.viewport.goHome(); + _this.viewport.applyConstraints(); + return false; + case 119://w + case 87://W + case 38://up arrow + if ( event.shift ) { + _this.viewport.zoomBy(1.1); + } else { + _this.viewport.panBy(new $.Point(0, -0.05)); + } + _this.viewport.applyConstraints(); + return false; + case 115://s + case 83://S + case 40://down arrow + if ( event.shift ) { + _this.viewport.zoomBy(0.9); + } else { + _this.viewport.panBy(new $.Point(0, 0.05)); + } + _this.viewport.applyConstraints(); + return false; + case 97://a + case 37://left arrow + _this.viewport.panBy(new $.Point(-0.05, 0)); + _this.viewport.applyConstraints(); + return false; + case 100://d + case 39://right arrow + _this.viewport.panBy(new $.Point(0.05, 0)); + _this.viewport.applyConstraints(); + return false; + default: + //console.log( 'navigator keycode %s', event.keyCode ); + return true; + } } } }).setTracking( true ); // default state @@ -1474,7 +1478,7 @@ function onBlur(){ function onCanvasClick( event ) { var zoomPerClick, factor; - if ( this.viewport && event.quick ) { // ignore clicks where mouse moved + if ( !event.preventDefaultAction && this.viewport && event.quick ) { // ignore clicks where mouse moved zoomPerClick = this.zoomPerClick; factor = event.shift ? 1.0 / zoomPerClick : zoomPerClick; this.viewport.zoomBy( @@ -1493,7 +1497,7 @@ function onCanvasClick( event ) { } function onCanvasDrag( event ) { - if ( this.viewport ) { + if ( !event.preventDefaultAction && this.viewport ) { if( !this.panHorizontal ){ event.delta.x = 0; } @@ -1533,7 +1537,7 @@ function onCanvasRelease( event ) { function onCanvasScroll( event ) { var factor; - if ( this.viewport ) { + if ( !event.preventDefaultAction && this.viewport ) { factor = Math.pow( this.zoomPerScroll, event.scroll ); this.viewport.zoomBy( factor, From 626f27771f85b6bbffeb2d29cb76211d3c8bbde2 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 8 Nov 2013 08:24:44 -0800 Subject: [PATCH 2/2] MouseTracker preventDefaultAction Unit Tests --- test/events.js | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/test/events.js b/test/events.js index f2f3018c..6fb7f23c 100644 --- a/test/events.js +++ b/test/events.js @@ -212,4 +212,72 @@ viewer.open( '/test/data/testpattern.dzi' ); } ); + // ---------- + asyncTest( 'MouseTracker preventDefaultAction', function () { + var $canvas = $( viewer.element ).find( '.openseadragon-canvas' ).not( '.navigator .openseadragon-canvas' ), + tracker = viewer.innerTracker, + origClickHandler, + origDragHandler, + dragCount = 10, + originalZoom = 0, + originalBounds = null; + + var onOpen = function ( event ) { + viewer.removeHandler( 'open', onOpen ); + + // Hook viewer events to set preventDefaultAction + origClickHandler = tracker.clickHandler; + tracker.clickHandler = function ( event ) { + event.preventDefaultAction = true; + return origClickHandler( event ); + }; + origDragHandler = tracker.dragHandler; + tracker.dragHandler = function ( event ) { + event.preventDefaultAction = true; + return origDragHandler( event ); + }; + + originalZoom = viewer.viewport.getZoom(); + originalBounds = viewer.viewport.getBounds(); + + var event = { + clientX:1, + clientY:1 + }; + + $canvas.simulate( 'focus', event ); + // Drag to pan + Util.simulateViewerClickWithDrag( { + viewer: viewer, + widthFactor: 0.25, + heightFactor: 0.25, + dragCount: dragCount, + dragDx: 1, + dragDy: 1 + } ); + // Click to zoom + Util.simulateViewerClickWithDrag( { + viewer: viewer, + widthFactor: 0.25, + heightFactor: 0.25, + dragCount: 0, + dragDx: 0, + dragDy: 0 + } ); + $canvas.simulate( 'blur', event ); + + var zoom = viewer.viewport.getZoom(), + bounds = viewer.viewport.getBounds(); + + equal( zoom, originalZoom, "Zoom prevented" ); + ok( bounds.x == originalBounds.x && bounds.y == originalBounds.y, 'Pan prevented' ); + + viewer.close(); + start(); + }; + + viewer.addHandler( 'open', onOpen ); + viewer.open( '/test/data/testpattern.dzi' ); + } ); + } )();