mirror of
https://github.com/openseadragon/openseadragon.git
synced 2025-01-31 23:21:42 +03:00
Merge pull request #369 from msalsbery/Pointer-Event-Model
New Multi-Touch MouseTracker
This commit is contained in:
commit
7ae0452546
@ -7,8 +7,12 @@ OPENSEADRAGON CHANGELOG
|
||||
* The drawer element is no longer accessible via viewer.canvas.firstChild but via viewer.drawersContainer.firstChild or viewer.drawer.canvas.
|
||||
* The overlays elements are no longer accessible via viewer.canvas.childNodes but via viewer.overlaysContainer.childNodes or viewer.currentOverlays[i].element.
|
||||
* BREAKING CHANGE: Pseudo full screen mode on IE<11 using activex has been dropped. OpenSeadragon will run in full page if full screen mode is requested.
|
||||
* BREAKING CHANGE: MouseTracker touch pinch gestures are no longer converted to scroll events. MouseTracker.pinchHandler should be used instead. (#369)
|
||||
* DEPRECATION: overlay functions have been moved from Drawer to Viewer (#331)
|
||||
* DEPRECATION: OpenSeadragon.cancelFullScreen has been renamed OpenSeadragon.exitFullScreen (#358)
|
||||
* DEPRECATION: The 'isTouchEvent' property passed in MouseTracker events is deprecated and has been replaced with 'pointerType', which is a String value "mouse", "touch", "pen", etc. to support multiple simultaneous pointing devices (#369)
|
||||
* DEPRECATION: The 'buttonDownAny' property passed in MouseTracker enter and exit events (enterHandler/exitHandler) is deprecated and has been replaced with 'buttons', which indicates the button(s) currently pressed (#369)
|
||||
* DEPRECATION: The 'buttonDownAny' property passed in Viewer's 'container-enter' and 'container-exit' events is deprecated and has been replaced with 'buttons', which indicates the button(s) currently pressed (#369)
|
||||
* Added layers support. Multiple images can now been displayed on top of each other with transparency via the Viewer.addLayer method (#298)
|
||||
* Improved overlay functions (#331)
|
||||
* Fixed: Nav button highlight states aren't quite aligned on Firefox (#303)
|
||||
@ -17,7 +21,7 @@ OPENSEADRAGON CHANGELOG
|
||||
* Added crossOriginPolicy drawer configuration to enable or disable CORS image requests (#364)
|
||||
* Disabled CORS by default (#377)
|
||||
* Added a ControlAnchor.ABSOLUTE enumeration. Enables absolute positioning of control elements in the viewer (#310)
|
||||
* Added a 'navigator-scroll' event to Navigator. Fired when mousewheel/pinch events occur in the navigator (#310)
|
||||
* Added a 'navigator-scroll' event to Navigator. Fired when mousewheel events occur in the navigator (#310)
|
||||
* Added a navigatorMaintainSizeRatio option. If set to true, the navigator minimap resizes when the viewer element is resized (#310)
|
||||
* Added 'ABSOLUTE' as a navigatorPosition option, along with corresponding navigatorTop, navigatorLeft options. Allows the navigator minimap to be placed anywhere in the viewer (#310)
|
||||
* Enhanced the navigatorTop, navigatorLeft, navigatorHeight, and navigatorWidth options to allow a number for pixel units or a string for other element units (%, em, etc.) (#310)
|
||||
@ -30,6 +34,20 @@ OPENSEADRAGON CHANGELOG
|
||||
* Various fixes to bring OpenSeadragon into W3C compliance (#375)
|
||||
* Added separate flags for turning off each of the nav buttons (#376)
|
||||
* Added support for query parameters in DZI tileSource URL (#378)
|
||||
* Enhanced MouseTracker for multi-touch (#369)
|
||||
* Added support for tracking multiple touch-points on multiple/simultaneous pointing devices
|
||||
* Added support for the W3C Pointer Events event model. Enables touch/multi-touch on IE10+
|
||||
* Added a dragEndHandler event callback, called when a drag gesture ends
|
||||
* Added a pinchHandler event callback, called as a pinch gesture (2 touch points) is occurring
|
||||
* Added real-time velocity (speed and direction) tracking to drag operations. 'speed' and 'direction' values are passed in the dragHandler and dragEndHandler event data
|
||||
* Enhanced Viewer for multi-touch (#369)
|
||||
* Added pinch zoom with the new MouseTracker pinchHandler. The 'pan' and 'zoom' Viewer events can be used to detect changes resulting in pinch gestures
|
||||
* Added a "canvas-pinch" event fired by the pinch event handler
|
||||
* Added flick gesture with the new MouseTracker dragEndHandler
|
||||
* Added a "canvas-drag-end" event fired by the drag-end event handler
|
||||
* Added a GestureSettings class for per-device gesture options. Currently has settings to enable/disable zoom-on-scroll, zoom-on-pinch, zoom-on-click, and flick gesture settings.
|
||||
* Added GestureSettings objects for mouse, touch, and pen devices to the Viewer options giving users the ability to customize gesture handling in the viewer
|
||||
* Added velocity (speed and direction) properties to the "canvas-drag" event
|
||||
|
||||
1.0.0:
|
||||
|
||||
|
2614
src/mousetracker.js
2614
src/mousetracker.js
File diff suppressed because it is too large
Load Diff
@ -185,10 +185,6 @@
|
||||
*
|
||||
* @property {String} [debugGridColor='#437AB2']
|
||||
*
|
||||
* @property {Number} [animationTime=1.2]
|
||||
* Specifies the animation duration per each {@link OpenSeadragon.Spring}
|
||||
* which occur when the image is dragged or zoomed.
|
||||
*
|
||||
* @property {Number} [blendTime=0]
|
||||
* Specifies the duration of animation as higher or lower level tiles are
|
||||
* replacing the existing tile.
|
||||
@ -265,8 +261,6 @@
|
||||
* achieved. Setting this to 0 and wrapHorizontal ( or wrapVertical ) to
|
||||
* true will provide the effect of an infinitely scrolling viewport.
|
||||
*
|
||||
* @property {Number} [springStiffness=7.0]
|
||||
*
|
||||
* @property {Number} [imageLoaderLimit=0]
|
||||
* The maximum number of image requests to make concurrently. By default
|
||||
* it is set to 0 allowing the browser to make the maximum number of
|
||||
@ -280,11 +274,53 @@
|
||||
* If a mouse or touch drag occurs and the distance to the starting drag
|
||||
* point is less than this many pixels, ignore the drag event.
|
||||
*
|
||||
* @property {Number} [springStiffness=5.0]
|
||||
*
|
||||
* @property {Number} [animationTime=1.2]
|
||||
* Specifies the animation duration per each {@link OpenSeadragon.Spring}
|
||||
* which occur when the image is dragged or zoomed.
|
||||
*
|
||||
* @property {OpenSeadragon.GestureSettings} [gestureSettingsMouse]
|
||||
* Settings for gestures generated by a mouse pointer device. (See {@link OpenSeadragon.GestureSettings})
|
||||
* @property {Boolean} [gestureSettingsMouse.scrollToZoom=true] - Zoom on scroll gesture
|
||||
* @property {Boolean} [gestureSettingsMouse.clickToZoom=true] - Zoom on click gesture
|
||||
* @property {Boolean} [gestureSettingsMouse.pinchToZoom=false] - Zoom on pinch gesture
|
||||
* @property {Boolean} [gestureSettingsMouse.flickEnabled=false] - Enable flick gesture
|
||||
* @property {Number} [gestureSettingsMouse.flickMinSpeed=20] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second)
|
||||
* @property {Number} [gestureSettingsMouse.flickMomentum=0.40] - If flickEnabled is true, the momentum factor for the flick gesture
|
||||
*
|
||||
* @property {OpenSeadragon.GestureSettings} [gestureSettingsTouch]
|
||||
* Settings for gestures generated by a touch pointer device. (See {@link OpenSeadragon.GestureSettings})
|
||||
* @property {Boolean} [gestureSettingsTouch.scrollToZoom=false] - Zoom on scroll gesture
|
||||
* @property {Boolean} [gestureSettingsTouch.clickToZoom=false] - Zoom on click gesture
|
||||
* @property {Boolean} [gestureSettingsTouch.pinchToZoom=true] - Zoom on pinch gesture
|
||||
* @property {Boolean} [gestureSettingsTouch.flickEnabled=true] - Enable flick gesture
|
||||
* @property {Number} [gestureSettingsTouch.flickMinSpeed=20] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second)
|
||||
* @property {Number} [gestureSettingsTouch.flickMomentum=0.40] - If flickEnabled is true, the momentum factor for the flick gesture
|
||||
*
|
||||
* @property {OpenSeadragon.GestureSettings} [gestureSettingsPen]
|
||||
* Settings for gestures generated by a pen pointer device. (See {@link OpenSeadragon.GestureSettings})
|
||||
* @property {Boolean} [gestureSettingsPen.scrollToZoom=false] - Zoom on scroll gesture
|
||||
* @property {Boolean} [gestureSettingsPen.clickToZoom=true] - Zoom on click gesture
|
||||
* @property {Boolean} [gestureSettingsPen.pinchToZoom=false] - Zoom on pinch gesture
|
||||
* @property {Boolean} [gestureSettingsPen.flickEnabled=false] - Enable flick gesture
|
||||
* @property {Number} [gestureSettingsPen.flickMinSpeed=20] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second)
|
||||
* @property {Number} [gestureSettingsPen.flickMomentum=0.40] - If flickEnabled is true, the momentum factor for the flick gesture
|
||||
*
|
||||
* @property {OpenSeadragon.GestureSettings} [gestureSettingsUnknown]
|
||||
* Settings for gestures generated by unknown pointer devices. (See {@link OpenSeadragon.GestureSettings})
|
||||
* @property {Boolean} [gestureSettingsUnknown.scrollToZoom=true] - Zoom on scroll gesture
|
||||
* @property {Boolean} [gestureSettingsUnknown.clickToZoom=false] - Zoom on click gesture
|
||||
* @property {Boolean} [gestureSettingsUnknown.pinchToZoom=true] - Zoom on pinch gesture
|
||||
* @property {Boolean} [gestureSettingsUnknown.flickEnabled=true] - Enable flick gesture
|
||||
* @property {Number} [gestureSettingsUnknown.flickMinSpeed=20] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second)
|
||||
* @property {Number} [gestureSettingsUnknown.flickMomentum=0.40] - If flickEnabled is true, the momentum factor for the flick gesture
|
||||
*
|
||||
* @property {Number} [zoomPerClick=2.0]
|
||||
* The "zoom distance" per mouse click or touch tap. <em><strong>Note:</strong> Setting this to 1.0 effectively disables the click-to-zoom feature.</em>
|
||||
* The "zoom distance" per mouse click or touch tap. <em><strong>Note:</strong> Setting this to 1.0 effectively disables the click-to-zoom feature (also see gestureSettings[Mouse|Touch|Pen].clickToZoom).</em>
|
||||
*
|
||||
* @property {Number} [zoomPerScroll=1.2]
|
||||
* The "zoom distance" per mouse scroll or touch pinch. <em><strong>Note:</strong> Setting this to 1.0 effectively disables the mouse-wheel zoom feature.</em>
|
||||
* The "zoom distance" per mouse scroll or touch pinch. <em><strong>Note:</strong> Setting this to 1.0 effectively disables the mouse-wheel zoom feature (also see gestureSettings[Mouse|Touch|Pen].scrollToZoom}).</em>
|
||||
*
|
||||
* @property {Number} [zoomPerSecond=1.0]
|
||||
* The number of seconds to animate a single zoom event over.
|
||||
@ -486,6 +522,34 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Settings for gestures generated by a pointer device.
|
||||
*
|
||||
* @typedef {Object} GestureSettings
|
||||
* @memberof OpenSeadragon
|
||||
*
|
||||
* @property {Boolean} scrollToZoom
|
||||
* Set to false to disable zooming on scroll gestures.
|
||||
*
|
||||
* @property {Boolean} clickToZoom
|
||||
* Set to false to disable zooming on click gestures.
|
||||
*
|
||||
* @property {Boolean} pinchToZoom
|
||||
* Set to false to disable zooming on pinch gestures.
|
||||
*
|
||||
* @property {Boolean} flickEnabled
|
||||
* Set to false to disable the kinetic panning effect (flick) at the end of a drag gesture.
|
||||
*
|
||||
* @property {Number} flickMinSpeed
|
||||
* If flickEnabled is true, the minimum speed (in pixels-per-second) required to cause the kinetic panning effect (flick) at the end of a drag gesture.
|
||||
*
|
||||
* @property {Number} flickMomentum
|
||||
* If flickEnabled is true, a constant multiplied by the velocity to determine the distance of the kinetic panning effect (flick) at the end of a drag gesture.
|
||||
* A larger value will make the flick feel "lighter", while a smaller value will make the flick feel "heavier".
|
||||
* Note: springStiffness and animationTime also affect the "spring" used to stop the flick animation.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* The names for the image resources used for the image navigation buttons.
|
||||
*
|
||||
@ -825,13 +889,17 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){
|
||||
maxZoomLevel: null,
|
||||
|
||||
//UI RESPONSIVENESS AND FEEL
|
||||
springStiffness: 7.0,
|
||||
clickTimeThreshold: 300,
|
||||
clickDistThreshold: 5,
|
||||
springStiffness: 5.0,
|
||||
animationTime: 1.2,
|
||||
gestureSettingsMouse: { scrollToZoom: true, clickToZoom: true, pinchToZoom: false, flickEnabled: false, flickMinSpeed: 20, flickMomentum: 0.40 },
|
||||
gestureSettingsTouch: { scrollToZoom: false, clickToZoom: false, pinchToZoom: true, flickEnabled: true, flickMinSpeed: 20, flickMomentum: 0.40 },
|
||||
gestureSettingsPen: { scrollToZoom: false, clickToZoom: true, pinchToZoom: false, flickEnabled: false, flickMinSpeed: 20, flickMomentum: 0.40 },
|
||||
gestureSettingsUnknown: { scrollToZoom: false, clickToZoom: false, pinchToZoom: true, flickEnabled: true, flickMinSpeed: 20, flickMomentum: 0.40 },
|
||||
zoomPerClick: 2,
|
||||
zoomPerScroll: 1.2,
|
||||
zoomPerSecond: 1.0,
|
||||
animationTime: 1.2,
|
||||
blendTime: 0,
|
||||
alwaysBlend: false,
|
||||
autoHideControls: true,
|
||||
@ -1123,6 +1191,21 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Determines if a point is within the bounding rectangle of the given element (hit-test).
|
||||
* @function
|
||||
* @param {Element|String} element
|
||||
* @param {OpenSeadragon.Point} point
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
pointInElement: function( element, point ) {
|
||||
element = $.getElement( element );
|
||||
var offset = $.getElementOffset( element ),
|
||||
size = $.getElementSize( element );
|
||||
return point.x >= offset.x && point.x < offset.x + size.x && point.y < offset.y + size.y && point.y >= offset.y;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Gets the latest event, really only useful internally since its
|
||||
* specific to IE behavior.
|
||||
@ -1586,9 +1669,6 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){
|
||||
return function ( element, eventName, handler, useCapture ) {
|
||||
element = $.getElement( element );
|
||||
element.attachEvent( 'on' + eventName, handler );
|
||||
if ( useCapture && element.setCapture ) {
|
||||
element.setCapture();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
throw new Error( "No known event model." );
|
||||
@ -1615,9 +1695,6 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){
|
||||
return function( element, eventName, handler, useCapture ) {
|
||||
element = $.getElement( element );
|
||||
element.detachEvent( 'on' + eventName, handler );
|
||||
if ( useCapture && element.releaseCapture ) {
|
||||
element.releaseCapture();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
throw new Error( "No known event model." );
|
||||
|
190
src/viewer.js
190
src/viewer.js
@ -275,7 +275,13 @@ $.Viewer = function( options ) {
|
||||
style.position = "absolute";
|
||||
style.top = "0px";
|
||||
style.left = "0px";
|
||||
}( this.canvas.style ));
|
||||
// Disable browser default touch handling
|
||||
if (style["touch-action"] !== undefined) {
|
||||
style["touch-action"] = "none";
|
||||
} else if (style["-ms-touch-action"] !== undefined) {
|
||||
style["-ms-touch-action"] = "none";
|
||||
}
|
||||
}(this.canvas.style));
|
||||
|
||||
//the container is created through applying the ControlDock constructor above
|
||||
this.container.className = "openseadragon-container";
|
||||
@ -384,8 +390,10 @@ $.Viewer = function( options ) {
|
||||
clickDistThreshold: this.clickDistThreshold,
|
||||
clickHandler: $.delegate( this, onCanvasClick ),
|
||||
dragHandler: $.delegate( this, onCanvasDrag ),
|
||||
dragEndHandler: $.delegate( this, onCanvasDragEnd ),
|
||||
releaseHandler: $.delegate( this, onCanvasRelease ),
|
||||
scrollHandler: $.delegate( this, onCanvasScroll )
|
||||
scrollHandler: $.delegate( this, onCanvasScroll ),
|
||||
pinchHandler: $.delegate( this, onCanvasPinch )
|
||||
}).setTracking( this.mouseNavEnabled ? true : false ); // default state
|
||||
|
||||
this.outerTracker = new $.MouseTracker({
|
||||
@ -1770,7 +1778,27 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
||||
div.parentNode.removeChild(div);
|
||||
delete this.messageDiv;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets this viewer's gesture settings for the given pointer device type.
|
||||
* @method
|
||||
* @param {String} type - The pointer device type to get the gesture settings for ("mouse", "touch", "pen", etc.).
|
||||
* @return {OpenSeadragon.GestureSettings}
|
||||
*/
|
||||
gestureSettingsByDeviceType: function ( type ) {
|
||||
switch ( type ) {
|
||||
case 'mouse':
|
||||
return this.gestureSettingsMouse;
|
||||
case 'touch':
|
||||
return this.gestureSettingsTouch;
|
||||
case 'pen':
|
||||
return this.gestureSettingsPen;
|
||||
default:
|
||||
return this.gestureSettingsUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
@ -2204,16 +2232,17 @@ function onBlur(){
|
||||
}
|
||||
|
||||
function onCanvasClick( event ) {
|
||||
var zoomPerClick,
|
||||
factor;
|
||||
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(
|
||||
factor,
|
||||
this.viewport.pointFromPixel( event.position, true )
|
||||
);
|
||||
this.viewport.applyConstraints();
|
||||
var gestureSettings;
|
||||
|
||||
if ( !event.preventDefaultAction && this.viewport && event.quick ) {
|
||||
gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
|
||||
if ( gestureSettings.clickToZoom ) {
|
||||
this.viewport.zoomBy(
|
||||
event.shift ? 1.0 / this.zoomPerClick : this.zoomPerClick,
|
||||
this.viewport.pointFromPixel( event.position, true )
|
||||
);
|
||||
this.viewport.applyConstraints();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Raised when a mouse press/release or touch/remove occurs on the {@link OpenSeadragon.Viewer#canvas} element.
|
||||
@ -2239,19 +2268,18 @@ function onCanvasClick( event ) {
|
||||
}
|
||||
|
||||
function onCanvasDrag( event ) {
|
||||
var gestureSettings;
|
||||
|
||||
if ( !event.preventDefaultAction && this.viewport ) {
|
||||
gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
|
||||
if( !this.panHorizontal ){
|
||||
event.delta.x = 0;
|
||||
}
|
||||
if( !this.panVertical ){
|
||||
event.delta.y = 0;
|
||||
}
|
||||
this.viewport.panBy(
|
||||
this.viewport.deltaPointsFromPixels(
|
||||
event.delta.negate()
|
||||
)
|
||||
);
|
||||
if( this.constrainDuringPan ){
|
||||
this.viewport.panBy( this.viewport.deltaPointsFromPixels( event.delta.negate() ), gestureSettings.flickEnabled );
|
||||
if( this.constrainDuringPan && !gestureSettings.flickEnabled ){
|
||||
this.viewport.applyConstraints();
|
||||
}
|
||||
}
|
||||
@ -2265,6 +2293,8 @@ function onCanvasDrag( event ) {
|
||||
* @property {OpenSeadragon.MouseTracker} tracker - A reference to the MouseTracker which originated this event.
|
||||
* @property {OpenSeadragon.Point} position - The position of the event relative to the tracked element.
|
||||
* @property {OpenSeadragon.Point} delta - The x,y components of the difference between start drag and end drag.
|
||||
* @property {Number} speed - Current computed speed, in pixels per second.
|
||||
* @property {Number} direction - Current computed direction, expressed as an angle counterclockwise relative to the positive X axis (-pi to pi, in radians). Only valid if speed > 0.
|
||||
* @property {Boolean} shift - True if the shift key was pressed during this event.
|
||||
* @property {Object} originalEvent - The original DOM event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
@ -2273,14 +2303,61 @@ function onCanvasDrag( event ) {
|
||||
tracker: event.eventSource,
|
||||
position: event.position,
|
||||
delta: event.delta,
|
||||
speed: event.speed,
|
||||
direction: event.direction,
|
||||
shift: event.shift,
|
||||
originalEvent: event.originalEvent
|
||||
});
|
||||
}
|
||||
|
||||
function onCanvasDragEnd( event ) {
|
||||
var gestureSettings;
|
||||
|
||||
if ( !event.preventDefaultAction && this.viewport ) {
|
||||
gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
|
||||
if ( gestureSettings.flickEnabled && event.speed >= gestureSettings.flickMinSpeed && !event.preventDefaultAction && this.viewport ) {
|
||||
var amplitudeX = gestureSettings.flickMomentum * ( event.speed * Math.cos( event.direction ) ),
|
||||
amplitudeY = gestureSettings.flickMomentum * ( event.speed * Math.sin( event.direction ) ),
|
||||
center = this.viewport.pixelFromPoint( this.viewport.getCenter( true ) ),
|
||||
target = this.viewport.pointFromPixel( new $.Point( center.x - amplitudeX, center.y - amplitudeY ) );
|
||||
this.viewport.panTo( target, false );
|
||||
this.viewport.applyConstraints();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Raised when a mouse or touch drag operation ends on the {@link OpenSeadragon.Viewer#canvas} element.
|
||||
*
|
||||
* @event canvas-drag-end
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
||||
* @property {OpenSeadragon.MouseTracker} tracker - A reference to the MouseTracker which originated this event.
|
||||
* @property {OpenSeadragon.Point} position - The position of the event relative to the tracked element.
|
||||
* @property {Number} speed - Speed at the end of a drag gesture, in pixels per second.
|
||||
* @property {Number} direction - Direction at the end of a drag gesture, expressed as an angle counterclockwise relative to the positive X axis (-pi to pi, in radians). Only valid if speed > 0.
|
||||
* @property {Boolean} shift - True if the shift key was pressed during this event.
|
||||
* @property {Object} originalEvent - The original DOM event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.raiseEvent( 'canvas-drag-end', {
|
||||
tracker: event.eventSource,
|
||||
position: event.position,
|
||||
speed: event.speed,
|
||||
direction: event.direction,
|
||||
shift: event.shift,
|
||||
originalEvent: event.originalEvent
|
||||
});
|
||||
}
|
||||
|
||||
function onCanvasRelease( event ) {
|
||||
var gestureSettings;
|
||||
|
||||
if ( event.insideElementPressed && this.viewport ) {
|
||||
this.viewport.applyConstraints();
|
||||
gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
|
||||
|
||||
if ( !gestureSettings.flickEnabled ) {
|
||||
this.viewport.applyConstraints();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Raised when the mouse button is released or touch ends on the {@link OpenSeadragon.Viewer#canvas} element.
|
||||
@ -2305,18 +2382,67 @@ function onCanvasRelease( event ) {
|
||||
});
|
||||
}
|
||||
|
||||
function onCanvasScroll( event ) {
|
||||
var factor;
|
||||
function onCanvasPinch( event ) {
|
||||
var gestureSettings;
|
||||
|
||||
if ( !event.preventDefaultAction && this.viewport ) {
|
||||
factor = Math.pow( this.zoomPerScroll, event.scroll );
|
||||
this.viewport.zoomBy(
|
||||
factor,
|
||||
this.viewport.pointFromPixel( event.position, true )
|
||||
);
|
||||
this.viewport.applyConstraints();
|
||||
gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
|
||||
if ( gestureSettings.pinchToZoom ) {
|
||||
var centerPt = this.viewport.pointFromPixel( event.center, true ),
|
||||
lastCenterPt = this.viewport.pointFromPixel( event.lastCenter, true );
|
||||
this.viewport.zoomBy( event.distance / event.lastDistance, centerPt, true );
|
||||
this.viewport.panBy( lastCenterPt.minus( centerPt ), true );
|
||||
this.viewport.applyConstraints();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Raised when a scroll event occurs on the {@link OpenSeadragon.Viewer#canvas} element (mouse wheel, touch pinch, etc.).
|
||||
* Raised when a pinch event occurs on the {@link OpenSeadragon.Viewer#canvas} element.
|
||||
*
|
||||
* @event canvas-pinch
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
||||
* @property {OpenSeadragon.MouseTracker} tracker - A reference to the MouseTracker which originated this event.
|
||||
* @property {Array.<OpenSeadragon.MouseTracker.GesturePoint>} gesturePoints - Gesture points associated with the gesture. Velocity data can be found here.
|
||||
* @property {OpenSeadragon.Point} lastCenter - The previous center point of the two pinch contact points relative to the tracked element.
|
||||
* @property {OpenSeadragon.Point} center - The center point of the two pinch contact points relative to the tracked element.
|
||||
* @property {Number} lastDistance - The previous distance between the two pinch contact points in CSS pixels.
|
||||
* @property {Number} distance - The distance between the two pinch contact points in CSS pixels.
|
||||
* @property {Boolean} shift - True if the shift key was pressed during this event.
|
||||
* @property {Object} originalEvent - The original DOM event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.raiseEvent('canvas-pinch', {
|
||||
tracker: event.eventSource,
|
||||
gesturePoints: event.gesturePoints,
|
||||
lastCenter: event.lastCenter,
|
||||
center: event.center,
|
||||
lastDistance: event.lastDistance,
|
||||
distance: event.distance,
|
||||
shift: event.shift,
|
||||
originalEvent: event.originalEvent
|
||||
});
|
||||
//cancels event
|
||||
return false;
|
||||
}
|
||||
|
||||
function onCanvasScroll( event ) {
|
||||
var gestureSettings,
|
||||
factor;
|
||||
|
||||
if ( !event.preventDefaultAction && this.viewport ) {
|
||||
gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
|
||||
if ( gestureSettings.scrollToZoom ) {
|
||||
factor = Math.pow( this.zoomPerScroll, event.scroll );
|
||||
this.viewport.zoomBy(
|
||||
factor,
|
||||
this.viewport.pointFromPixel( event.position, true )
|
||||
);
|
||||
this.viewport.applyConstraints();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Raised when a scroll event occurs on the {@link OpenSeadragon.Viewer#canvas} element (mouse wheel).
|
||||
*
|
||||
* @event canvas-scroll
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
@ -2356,14 +2482,16 @@ function onContainerExit( event ) {
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
||||
* @property {OpenSeadragon.MouseTracker} tracker - A reference to the MouseTracker which originated this event.
|
||||
* @property {OpenSeadragon.Point} position - The position of the event relative to the tracked element.
|
||||
* @property {Number} buttons - Current buttons pressed. A combination of bit flags 0: none, 1: primary (or touch contact), 2: secondary, 4: aux (often middle), 8: X1 (often back), 16: X2 (often forward), 32: pen eraser.
|
||||
* @property {Boolean} insideElementPressed - True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false.
|
||||
* @property {Boolean} buttonDownAny - Was the button down anywhere in the screen during the event.
|
||||
* @property {Boolean} buttonDownAny - Was the button down anywhere in the screen during the event. <span style="color:red;">Deprecated. Use buttons instead.</span>
|
||||
* @property {Object} originalEvent - The original DOM event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.raiseEvent( 'container-exit', {
|
||||
tracker: event.eventSource,
|
||||
position: event.position,
|
||||
buttons: event.buttons,
|
||||
insideElementPressed: event.insideElementPressed,
|
||||
buttonDownAny: event.buttonDownAny,
|
||||
originalEvent: event.originalEvent
|
||||
@ -2412,14 +2540,16 @@ function onContainerEnter( event ) {
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
||||
* @property {OpenSeadragon.MouseTracker} tracker - A reference to the MouseTracker which originated this event.
|
||||
* @property {OpenSeadragon.Point} position - The position of the event relative to the tracked element.
|
||||
* @property {Number} buttons - Current buttons pressed. A combination of bit flags 0: none, 1: primary (or touch contact), 2: secondary, 4: aux (often middle), 8: X1 (often back), 16: X2 (often forward), 32: pen eraser.
|
||||
* @property {Boolean} insideElementPressed - True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false.
|
||||
* @property {Boolean} buttonDownAny - Was the button down anywhere in the screen during the event.
|
||||
* @property {Boolean} buttonDownAny - Was the button down anywhere in the screen during the event. <span style="color:red;">Deprecated. Use buttons instead.</span>
|
||||
* @property {Object} originalEvent - The original DOM event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.raiseEvent( 'container-enter', {
|
||||
tracker: event.eventSource,
|
||||
position: event.position,
|
||||
buttons: event.buttons,
|
||||
insideElementPressed: event.insideElementPressed,
|
||||
buttonDownAny: event.buttonDownAny,
|
||||
originalEvent: event.originalEvent
|
||||
|
734
test/events.js
734
test/events.js
@ -25,184 +25,380 @@
|
||||
} );
|
||||
|
||||
// ----------
|
||||
asyncTest( 'addHandler without userData', function () {
|
||||
var openHandler = function ( event ) {
|
||||
viewer.removeHandler( 'open', openHandler );
|
||||
ok( event, 'Event handler received event data' );
|
||||
if ( event ) {
|
||||
strictEqual( event.eventSource, viewer, 'eventSource sent, eventSource is viewer' );
|
||||
strictEqual( event.userData, null, 'User data defaulted to null' );
|
||||
}
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer.addHandler( 'open', openHandler );
|
||||
viewer.open( '/test/data/testpattern.dzi' );
|
||||
} );
|
||||
|
||||
// ----------
|
||||
asyncTest( 'addHandler with userData', function () {
|
||||
var userData = { item1: 'Test user data', item2: Math.random() },
|
||||
originalUserData = { item1: userData.item1, item2: userData.item2 };
|
||||
|
||||
var openHandler = function ( event ) {
|
||||
viewer.removeHandler( 'open', openHandler );
|
||||
ok( event, 'Event handler received event data' );
|
||||
ok( event && event.userData, 'Event handler received user data' );
|
||||
if ( event && event.userData ) {
|
||||
deepEqual( event.userData, originalUserData, 'User data was untouched' );
|
||||
}
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer.addHandler( 'open', openHandler, userData );
|
||||
viewer.open( '/test/data/testpattern.dzi' );
|
||||
} );
|
||||
|
||||
// ----------
|
||||
asyncTest( 'MouseTracker, EventSource canvas-drag canvas-release canvas-click', function () {
|
||||
asyncTest( 'MouseTracker: mouse gestures', function () {
|
||||
var $canvas = $( viewer.element ).find( '.openseadragon-canvas' ).not( '.navigator .openseadragon-canvas' ),
|
||||
mouseTracker = null,
|
||||
userData = { item1: 'Test user data', item2: Math.random() },
|
||||
originalUserData = { item1: userData.item1, item2: userData.item2 },
|
||||
dragCount = 10,
|
||||
dragsHandledEventSource = 0,
|
||||
releasesHandledEventSource = 0,
|
||||
clicksHandledEventSource = 0,
|
||||
eventsHandledMouseTracker = 0,
|
||||
eventSourcePassedMouseTracker = 0,
|
||||
originalEventsPassedMouseTracker = 0,
|
||||
eventsHandledViewer = 0,
|
||||
originalEventsPassedViewer = 0,
|
||||
releasesExpected = 1,
|
||||
clicksExpected = 1;
|
||||
simEvent = {},
|
||||
offset = $canvas.offset(),
|
||||
tracker = viewer.innerTracker,
|
||||
intervalId,
|
||||
origEnterHandler,
|
||||
origExitHandler,
|
||||
origPressHandler,
|
||||
origReleaseHandler,
|
||||
origMoveHandler,
|
||||
origClickHandler,
|
||||
origDragHandler,
|
||||
origDragEndHandler,
|
||||
enterCount,
|
||||
exitCount,
|
||||
pressCount,
|
||||
releaseCount,
|
||||
moveCount,
|
||||
clickCount,
|
||||
dragCount,
|
||||
dragEndCount,
|
||||
insideElementPressed,
|
||||
insideElementReleased,
|
||||
quickClick,
|
||||
speed,
|
||||
direction;
|
||||
|
||||
var hookViewerHandlers = function () {
|
||||
origEnterHandler = tracker.enterHandler;
|
||||
tracker.enterHandler = function ( event ) {
|
||||
enterCount++;
|
||||
if (origEnterHandler) {
|
||||
return origEnterHandler( event );
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
origExitHandler = tracker.exitHandler;
|
||||
tracker.exitHandler = function ( event ) {
|
||||
exitCount++;
|
||||
if (origExitHandler) {
|
||||
return origExitHandler( event );
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
origPressHandler = tracker.pressHandler;
|
||||
tracker.pressHandler = function ( event ) {
|
||||
pressCount++;
|
||||
if (origPressHandler) {
|
||||
return origPressHandler( event );
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
origReleaseHandler = tracker.releaseHandler;
|
||||
tracker.releaseHandler = function ( event ) {
|
||||
releaseCount++;
|
||||
insideElementPressed = event.insideElementPressed;
|
||||
insideElementReleased = event.insideElementReleased;
|
||||
if (origReleaseHandler) {
|
||||
return origReleaseHandler( event );
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
origMoveHandler = tracker.moveHandler;
|
||||
tracker.moveHandler = function ( event ) {
|
||||
moveCount++;
|
||||
if (origMoveHandler) {
|
||||
return origMoveHandler( event );
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
origClickHandler = tracker.clickHandler;
|
||||
tracker.clickHandler = function ( event ) {
|
||||
clickCount++;
|
||||
quickClick = event.quick;
|
||||
if (origClickHandler) {
|
||||
return origClickHandler( event );
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
origDragHandler = tracker.dragHandler;
|
||||
tracker.dragHandler = function ( event ) {
|
||||
dragCount++;
|
||||
if (origDragHandler) {
|
||||
return origDragHandler( event );
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
origDragEndHandler = tracker.dragEndHandler;
|
||||
tracker.dragEndHandler = function ( event ) {
|
||||
dragEndCount++;
|
||||
speed = event.speed;
|
||||
direction = event.direction;
|
||||
if (origDragEndHandler) {
|
||||
return origDragEndHandler( event );
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var unhookViewerHandlers = function () {
|
||||
tracker.enterHandler = origEnterHandler;
|
||||
tracker.exitHandler = origExitHandler;
|
||||
tracker.pressHandler = origPressHandler;
|
||||
tracker.releaseHandler = origReleaseHandler;
|
||||
tracker.moveHandler = origMoveHandler;
|
||||
tracker.clickHandler = origClickHandler;
|
||||
tracker.dragHandler = origDragHandler;
|
||||
tracker.dragEndHandler = origDragEndHandler;
|
||||
};
|
||||
|
||||
var simulateEnter = function (x, y) {
|
||||
simEvent.clientX = offset.left + x;
|
||||
simEvent.clientY = offset.top + y;
|
||||
$canvas.simulate( OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseenter' : 'mouseover', simEvent );
|
||||
};
|
||||
|
||||
var simulateLeave = function (x, y) {
|
||||
simEvent.clientX = offset.left + x;
|
||||
simEvent.clientY = offset.top + y;
|
||||
$canvas.simulate( OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseleave' : 'mouseout', simEvent );
|
||||
};
|
||||
|
||||
var simulateDown = function (x, y) {
|
||||
simEvent.clientX = offset.left + x;
|
||||
simEvent.clientY = offset.top + y;
|
||||
$canvas.simulate( 'mousedown', simEvent );
|
||||
};
|
||||
|
||||
var simulateUp = function (x, y) {
|
||||
simEvent.clientX = offset.left + x;
|
||||
simEvent.clientY = offset.top + y;
|
||||
$canvas.simulate( 'mouseup', simEvent );
|
||||
};
|
||||
|
||||
var simulateMove = function (dX, dY, count) {
|
||||
var i;
|
||||
for ( i = 0; i < count; i++ ) {
|
||||
simEvent.clientX += dX;
|
||||
simEvent.clientY += dY;
|
||||
$canvas.simulate( 'mousemove', simEvent );
|
||||
}
|
||||
};
|
||||
|
||||
var resetForAssessment = function () {
|
||||
simEvent = {
|
||||
clientX: offset.left,
|
||||
clientY: offset.top
|
||||
};
|
||||
enterCount = 0;
|
||||
exitCount = 0;
|
||||
pressCount = 0;
|
||||
releaseCount = 0;
|
||||
moveCount = 0;
|
||||
clickCount = 0;
|
||||
dragCount = 0;
|
||||
dragEndCount = 0;
|
||||
insideElementPressed = false;
|
||||
insideElementReleased = false;
|
||||
quickClick = false;
|
||||
speed = 0;
|
||||
direction = 2 * Math.PI;
|
||||
};
|
||||
|
||||
var assessGestureExpectations = function (expected) {
|
||||
var pointersList = tracker.getActivePointersListByType('mouse');
|
||||
if ('enterCount' in expected) {
|
||||
equal( enterCount, expected.enterCount, expected.description + 'enterHandler event count matches expected (' + expected.enterCount + ')' );
|
||||
}
|
||||
if ('exitCount' in expected) {
|
||||
equal( exitCount, expected.exitCount, expected.description + 'exitHandler event count matches expected (' + expected.exitCount + ')' );
|
||||
}
|
||||
if ('pressCount' in expected) {
|
||||
equal( pressCount, expected.pressCount, expected.description + 'pressHandler event count matches expected (' + expected.pressCount + ')' );
|
||||
}
|
||||
if ('releaseCount' in expected) {
|
||||
equal( releaseCount, expected.releaseCount, expected.description + 'releaseHandler event count matches expected (' + expected.releaseCount + ')' );
|
||||
}
|
||||
if ('moveCount' in expected) {
|
||||
equal( moveCount, expected.moveCount, expected.description + 'moveHandler event count matches expected (' + expected.moveCount + ')' );
|
||||
}
|
||||
if ('clickCount' in expected) {
|
||||
equal( clickCount, expected.clickCount, expected.description + 'clickHandler event count matches expected (' + expected.clickCount + ')' );
|
||||
}
|
||||
if ('dragCount' in expected) {
|
||||
equal( dragCount, expected.dragCount, expected.description + 'dragHandler event count matches expected (' + expected.dragCount + ')' );
|
||||
}
|
||||
if ('dragEndCount' in expected) {
|
||||
equal( dragEndCount, expected.dragEndCount, expected.description + 'dragEndHandler event count matches expected (' + expected.dragEndCount + ')' );
|
||||
}
|
||||
if ('insideElementPressed' in expected) {
|
||||
equal( insideElementPressed, expected.insideElementPressed, expected.description + 'releaseHandler event.insideElementPressed matches expected (' + expected.insideElementPressed + ')' );
|
||||
}
|
||||
if ('insideElementReleased' in expected) {
|
||||
equal( insideElementReleased, expected.insideElementReleased, expected.description + 'releaseHandler event.insideElementReleased matches expected (' + expected.insideElementReleased + ')' );
|
||||
}
|
||||
if ('contacts' in expected) {
|
||||
equal( pointersList.contacts, expected.contacts, expected.description + 'Remaining pointer contact count matches expected (' + expected.contacts + ')' );
|
||||
}
|
||||
if ('trackedPointers' in expected) {
|
||||
equal( pointersList.getLength(), expected.trackedPointers, expected.description + 'Remaining tracked pointer count matches expected (' + expected.trackedPointers + ')' );
|
||||
}
|
||||
if ('quickClick' in expected) {
|
||||
equal( quickClick, expected.quickClick, expected.description + 'clickHandler event.quick matches expected (' + expected.quickClick + ')' );
|
||||
}
|
||||
if ('speed' in expected) {
|
||||
Util.assessNumericValue(expected.speed, speed, 1.0, expected.description + 'Drag speed ');
|
||||
}
|
||||
if ('direction' in expected) {
|
||||
Util.assessNumericValue(expected.direction, direction, 0.2, expected.description + 'Drag direction ');
|
||||
}
|
||||
};
|
||||
|
||||
var onOpen = function ( event ) {
|
||||
var timeStart,
|
||||
timeElapsed;
|
||||
|
||||
viewer.removeHandler( 'open', onOpen );
|
||||
|
||||
viewer.addHandler( 'canvas-drag', onEventSourceDrag );
|
||||
viewer.addHandler( 'canvas-release', onEventSourceRelease );
|
||||
viewer.addHandler( 'canvas-click', onEventSourceClick );
|
||||
hookViewerHandlers();
|
||||
|
||||
mouseTracker = new OpenSeadragon.MouseTracker( {
|
||||
element: $canvas[0],
|
||||
userData: userData,
|
||||
clickTimeThreshold: OpenSeadragon.DEFAULT_SETTINGS.clickTimeThreshold,
|
||||
clickDistThreshold: OpenSeadragon.DEFAULT_SETTINGS.clickDistThreshold,
|
||||
focusHandler: onMouseTrackerFocus,
|
||||
blurHandler: onMouseTrackerBlur,
|
||||
enterHandler: onMouseTrackerEnter,
|
||||
pressHandler: onMouseTrackerPress,
|
||||
moveHandler: onMouseTrackerMove,
|
||||
dragHandler: onMouseTrackerDrag,
|
||||
releaseHandler: onMouseTrackerRelease,
|
||||
clickHandler: onMouseTrackerClick,
|
||||
exitHandler: onMouseTrackerExit
|
||||
} ).setTracking( true );
|
||||
// enter-move-release (release in tracked element, press in unknown element)
|
||||
// (Note we also test to see if the pointer is still being tracked by not simulating a leave event until after assessment)
|
||||
resetForAssessment();
|
||||
simulateEnter(0, 0);
|
||||
simulateMove(1, 1, 10);
|
||||
simulateMove(-1, -1, 10);
|
||||
simulateUp(0, 0);
|
||||
assessGestureExpectations({
|
||||
description: 'enter-move-release (release in tracked element, press in unknown element): ',
|
||||
enterCount: 1,
|
||||
exitCount: 0,
|
||||
pressCount: 0,
|
||||
releaseCount: 1,
|
||||
moveCount: 20,
|
||||
clickCount: 0,
|
||||
dragCount: 0,
|
||||
dragEndCount: 0,
|
||||
insideElementPressed: false,
|
||||
insideElementReleased: true,
|
||||
contacts: 0,
|
||||
trackedPointers: 1
|
||||
//quickClick: false
|
||||
});
|
||||
simulateLeave(-1, -1); // flush tracked pointer
|
||||
|
||||
var event = {
|
||||
clientX:1,
|
||||
clientY:1
|
||||
};
|
||||
// enter-move-exit (fly-over)
|
||||
resetForAssessment();
|
||||
simulateEnter(0, 0);
|
||||
simulateMove(1, 1, 10);
|
||||
simulateMove(-1, -1, 10);
|
||||
simulateLeave(-1, -1);
|
||||
assessGestureExpectations({
|
||||
description: 'enter-move-exit (fly-over): ',
|
||||
enterCount: 1,
|
||||
exitCount: 1,
|
||||
pressCount: 0,
|
||||
releaseCount: 0,
|
||||
moveCount: 20,
|
||||
clickCount: 0,
|
||||
dragCount: 0,
|
||||
dragEndCount: 0,
|
||||
//insideElementPressed: false,
|
||||
//insideElementReleased: false,
|
||||
contacts: 0,
|
||||
trackedPointers: 0
|
||||
//quickClick: false
|
||||
});
|
||||
|
||||
$canvas.simulate( 'focus', event );
|
||||
Util.simulateViewerClickWithDrag( {
|
||||
viewer: viewer,
|
||||
widthFactor: 0.25,
|
||||
heightFactor: 0.25,
|
||||
dragCount: dragCount,
|
||||
dragDx: 1,
|
||||
dragDy: 1
|
||||
} );
|
||||
$canvas.simulate( 'blur', event );
|
||||
};
|
||||
// move-exit (fly-over, no enter event)
|
||||
resetForAssessment();
|
||||
simulateMove(1, 1, 10);
|
||||
simulateMove(-1, -1, 10);
|
||||
simulateLeave(-1, -1);
|
||||
assessGestureExpectations({
|
||||
description: 'move-exit (fly-over, no enter event): ',
|
||||
enterCount: 0,
|
||||
exitCount: 1,
|
||||
pressCount: 0,
|
||||
releaseCount: 0,
|
||||
moveCount: 20,
|
||||
clickCount: 0,
|
||||
dragCount: 0,
|
||||
dragEndCount: 0,
|
||||
//insideElementPressed: false,
|
||||
//insideElementReleased: false,
|
||||
contacts: 0,
|
||||
trackedPointers: 0
|
||||
//quickClick: false
|
||||
});
|
||||
|
||||
var checkOriginalEventReceivedViewer = function ( event ) {
|
||||
eventsHandledViewer++;
|
||||
//TODO Provide a better check for the original event...simulate doesn't currently extend the object
|
||||
// with arbitrary user data.
|
||||
if ( event && event.originalEvent ) {
|
||||
originalEventsPassedViewer++;
|
||||
}
|
||||
};
|
||||
// enter-press-release-exit
|
||||
resetForAssessment();
|
||||
simulateEnter(0, 0);
|
||||
simulateDown(0, 0);
|
||||
simulateUp(0, 0);
|
||||
simulateLeave(-1, -1);
|
||||
assessGestureExpectations({
|
||||
description: 'enter-press-release-exit (click): ',
|
||||
enterCount: 1,
|
||||
exitCount: 1,
|
||||
pressCount: 1,
|
||||
releaseCount: 1,
|
||||
moveCount: 0,
|
||||
clickCount: 1,
|
||||
dragCount: 0,
|
||||
dragEndCount: 0,
|
||||
insideElementPressed: true,
|
||||
insideElementReleased: true,
|
||||
contacts: 0,
|
||||
trackedPointers: 0,
|
||||
quickClick: true
|
||||
});
|
||||
|
||||
var onEventSourceDrag = function ( event ) {
|
||||
checkOriginalEventReceivedViewer( event );
|
||||
dragsHandledEventSource++;
|
||||
};
|
||||
// enter-press-move-release-move-exit (drag, release in tracked element)
|
||||
resetForAssessment();
|
||||
simulateEnter(0, 0);
|
||||
simulateDown(0, 0);
|
||||
simulateMove(1, 1, 100);
|
||||
simulateUp(10, 10);
|
||||
simulateMove(-1, -1, 100);
|
||||
simulateLeave(-1, -1);
|
||||
assessGestureExpectations({
|
||||
description: 'enter-press-move-release-move-exit (drag, release in tracked element): ',
|
||||
enterCount: 1,
|
||||
exitCount: 1,
|
||||
pressCount: 1,
|
||||
releaseCount: 1,
|
||||
moveCount: 200,
|
||||
clickCount: 1,
|
||||
dragCount: 100,
|
||||
dragEndCount: 1,
|
||||
insideElementPressed: true,
|
||||
insideElementReleased: true,
|
||||
contacts: 0,
|
||||
trackedPointers: 0,
|
||||
quickClick: false
|
||||
});
|
||||
|
||||
var onEventSourceRelease = function ( event ) {
|
||||
checkOriginalEventReceivedViewer( event );
|
||||
releasesHandledEventSource++;
|
||||
};
|
||||
// enter-press-move-exit-move-release (drag, release outside tracked element)
|
||||
resetForAssessment();
|
||||
simulateEnter(0, 0);
|
||||
simulateDown(0, 0);
|
||||
simulateMove(1, 1, 5);
|
||||
simulateMove(-1, -1, 5);
|
||||
simulateLeave(-1, -1);
|
||||
simulateMove(-1, -1, 5);
|
||||
simulateUp(-5, -5);
|
||||
assessGestureExpectations({
|
||||
description: 'enter-press-move-exit-move-release (drag, release outside tracked element): ',
|
||||
enterCount: 1,
|
||||
exitCount: 1,
|
||||
pressCount: 1,
|
||||
releaseCount: 1,
|
||||
moveCount: 15,
|
||||
clickCount: 0,
|
||||
dragCount: 15,
|
||||
dragEndCount: 1,
|
||||
insideElementPressed: true,
|
||||
insideElementReleased: false,
|
||||
contacts: 0,
|
||||
trackedPointers: 0,
|
||||
quickClick: false
|
||||
});
|
||||
|
||||
var onEventSourceClick = function ( event ) {
|
||||
checkOriginalEventReceivedViewer( event );
|
||||
clicksHandledEventSource++;
|
||||
};
|
||||
|
||||
var checkOriginalEventReceived = function ( event ) {
|
||||
eventsHandledMouseTracker++;
|
||||
if ( event && event.eventSource === mouseTracker ) {
|
||||
eventSourcePassedMouseTracker++;
|
||||
}
|
||||
//TODO Provide a better check for the original event...simulate doesn't currently extend the object
|
||||
// with arbitrary user data.
|
||||
if ( event && event.originalEvent ) {
|
||||
originalEventsPassedMouseTracker++;
|
||||
}
|
||||
};
|
||||
|
||||
var onMouseTrackerFocus = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerBlur = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerEnter = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerPress = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerMove = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerDrag = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerRelease = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerClick = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerExit = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
|
||||
mouseTracker.destroy();
|
||||
viewer.removeHandler( 'canvas-drag', onEventSourceDrag );
|
||||
viewer.removeHandler( 'canvas-release', onEventSourceRelease );
|
||||
viewer.removeHandler( 'canvas-click', onEventSourceClick );
|
||||
|
||||
equal( dragsHandledEventSource, dragCount, "'canvas-drag' event count matches 'mousemove' event count (" + dragCount + ")" );
|
||||
equal( releasesHandledEventSource, releasesExpected, "'canvas-release' event count matches expected (" + releasesExpected + ")" );
|
||||
equal( clicksHandledEventSource, releasesExpected, "'canvas-click' event count matches expected (" + releasesExpected + ")" );
|
||||
equal( originalEventsPassedViewer, eventsHandledViewer, "Original event received count matches expected (" + eventsHandledViewer + ")" );
|
||||
|
||||
equal( eventSourcePassedMouseTracker, eventsHandledMouseTracker, "Event source received count matches expected (" + eventsHandledMouseTracker + ")" );
|
||||
equal( originalEventsPassedMouseTracker, eventsHandledMouseTracker, "Original event received count matches expected (" + eventsHandledMouseTracker + ")" );
|
||||
deepEqual( event.userData, originalUserData, 'MouseTracker userData was untouched' );
|
||||
unhookViewerHandlers();
|
||||
|
||||
viewer.close();
|
||||
start();
|
||||
@ -213,7 +409,7 @@
|
||||
} );
|
||||
|
||||
// ----------
|
||||
asyncTest( 'MouseTracker preventDefaultAction', function () {
|
||||
asyncTest( 'Viewer: preventDefaultAction', function () {
|
||||
var $canvas = $( viewer.element ).find( '.openseadragon-canvas' ).not( '.navigator .openseadragon-canvas' ),
|
||||
tracker = viewer.innerTracker,
|
||||
origClickHandler,
|
||||
@ -281,7 +477,209 @@
|
||||
} );
|
||||
|
||||
// ----------
|
||||
asyncTest( 'tile-drawing event', function () {
|
||||
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' ),
|
||||
mouseTracker = null,
|
||||
userData = { item1: 'Test user data', item2: Math.random() },
|
||||
originalUserData = { item1: userData.item1, item2: userData.item2 },
|
||||
dragCount = 10,
|
||||
dragsHandledEventSource = 0,
|
||||
dragEndsHandledEventSource = 0,
|
||||
releasesHandledEventSource = 0,
|
||||
clicksHandledEventSource = 0,
|
||||
eventsHandledMouseTracker = 0,
|
||||
eventSourcePassedMouseTracker = 0,
|
||||
originalEventsPassedMouseTracker = 0,
|
||||
eventsHandledViewer = 0,
|
||||
originalEventsPassedViewer = 0,
|
||||
dragEndsExpected = 1,
|
||||
releasesExpected = 1,
|
||||
clicksExpected = 1;
|
||||
|
||||
var onOpen = function ( event ) {
|
||||
viewer.removeHandler( 'open', onOpen );
|
||||
|
||||
viewer.addHandler( 'canvas-drag', onEventSourceDrag );
|
||||
viewer.addHandler( 'canvas-drag-end', onEventSourceDragEnd );
|
||||
viewer.addHandler( 'canvas-release', onEventSourceRelease );
|
||||
viewer.addHandler( 'canvas-click', onEventSourceClick );
|
||||
|
||||
mouseTracker = new OpenSeadragon.MouseTracker( {
|
||||
element: $canvas[0],
|
||||
userData: userData,
|
||||
clickTimeThreshold: OpenSeadragon.DEFAULT_SETTINGS.clickTimeThreshold,
|
||||
clickDistThreshold: OpenSeadragon.DEFAULT_SETTINGS.clickDistThreshold,
|
||||
focusHandler: onMouseTrackerFocus,
|
||||
blurHandler: onMouseTrackerBlur,
|
||||
enterHandler: onMouseTrackerEnter,
|
||||
pressHandler: onMouseTrackerPress,
|
||||
moveHandler: onMouseTrackerMove,
|
||||
dragHandler: onMouseTrackerDrag,
|
||||
dragEndHandler: onMouseTrackerDragEnd,
|
||||
releaseHandler: onMouseTrackerRelease,
|
||||
clickHandler: onMouseTrackerClick,
|
||||
exitHandler: onMouseTrackerExit
|
||||
} ).setTracking( true );
|
||||
|
||||
var event = {
|
||||
clientX:1,
|
||||
clientY:1
|
||||
};
|
||||
|
||||
$canvas.simulate( 'focus', event );
|
||||
Util.simulateViewerClickWithDrag( {
|
||||
viewer: viewer,
|
||||
widthFactor: 0.25,
|
||||
heightFactor: 0.25,
|
||||
dragCount: dragCount,
|
||||
dragDx: 1,
|
||||
dragDy: 1
|
||||
} );
|
||||
$canvas.simulate( 'blur', event );
|
||||
};
|
||||
|
||||
var checkOriginalEventReceivedViewer = function ( event ) {
|
||||
eventsHandledViewer++;
|
||||
//TODO Provide a better check for the original event...simulate doesn't currently extend the object
|
||||
// with arbitrary user data.
|
||||
if ( event && event.originalEvent ) {
|
||||
originalEventsPassedViewer++;
|
||||
}
|
||||
};
|
||||
|
||||
var onEventSourceDrag = function ( event ) {
|
||||
checkOriginalEventReceivedViewer( event );
|
||||
dragsHandledEventSource++;
|
||||
};
|
||||
|
||||
var onEventSourceDragEnd = function ( event ) {
|
||||
checkOriginalEventReceivedViewer( event );
|
||||
dragEndsHandledEventSource++;
|
||||
};
|
||||
|
||||
var onEventSourceRelease = function ( event ) {
|
||||
checkOriginalEventReceivedViewer( event );
|
||||
releasesHandledEventSource++;
|
||||
};
|
||||
|
||||
var onEventSourceClick = function ( event ) {
|
||||
checkOriginalEventReceivedViewer( event );
|
||||
clicksHandledEventSource++;
|
||||
};
|
||||
|
||||
var checkOriginalEventReceived = function ( event ) {
|
||||
eventsHandledMouseTracker++;
|
||||
if ( event && event.eventSource === mouseTracker ) {
|
||||
eventSourcePassedMouseTracker++;
|
||||
}
|
||||
//TODO Provide a better check for the original event...simulate doesn't currently extend the object
|
||||
// with arbitrary user data.
|
||||
if ( event && event.originalEvent ) {
|
||||
originalEventsPassedMouseTracker++;
|
||||
}
|
||||
};
|
||||
|
||||
var onMouseTrackerFocus = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerBlur = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerEnter = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerPress = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerMove = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerDrag = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerDragEnd = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerRelease = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerClick = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
};
|
||||
|
||||
var onMouseTrackerExit = function ( event ) {
|
||||
checkOriginalEventReceived( event );
|
||||
|
||||
mouseTracker.destroy();
|
||||
viewer.removeHandler( 'canvas-drag', onEventSourceDrag );
|
||||
viewer.removeHandler( 'canvas-release', onEventSourceRelease );
|
||||
viewer.removeHandler( 'canvas-click', onEventSourceClick );
|
||||
|
||||
equal( dragsHandledEventSource, dragCount, "'canvas-drag' event count matches 'mousemove' event count (" + dragCount + ")" );
|
||||
equal( dragEndsHandledEventSource, dragEndsExpected, "'canvas-drag-end' event count matches expected (" + dragEndsExpected + ")" );
|
||||
equal( releasesHandledEventSource, releasesExpected, "'canvas-release' event count matches expected (" + releasesExpected + ")" );
|
||||
equal( clicksHandledEventSource, releasesExpected, "'canvas-click' event count matches expected (" + releasesExpected + ")" );
|
||||
equal( originalEventsPassedViewer, eventsHandledViewer, "Original event received count matches expected (" + eventsHandledViewer + ")" );
|
||||
|
||||
equal( eventSourcePassedMouseTracker, eventsHandledMouseTracker, "Event source received count matches expected (" + eventsHandledMouseTracker + ")" );
|
||||
equal( originalEventsPassedMouseTracker, eventsHandledMouseTracker, "Original event received count matches expected (" + eventsHandledMouseTracker + ")" );
|
||||
deepEqual( event.userData, originalUserData, 'MouseTracker userData was untouched' );
|
||||
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer.addHandler( 'open', onOpen );
|
||||
viewer.open( '/test/data/testpattern.dzi' );
|
||||
} );
|
||||
|
||||
// ----------
|
||||
asyncTest( 'EventSource: addHandler without userData', function () {
|
||||
var openHandler = function ( event ) {
|
||||
viewer.removeHandler( 'open', openHandler );
|
||||
ok( event, 'Event handler received event data' );
|
||||
if ( event ) {
|
||||
strictEqual( event.eventSource, viewer, 'eventSource sent, eventSource is viewer' );
|
||||
strictEqual( event.userData, null, 'User data defaulted to null' );
|
||||
}
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer.addHandler( 'open', openHandler );
|
||||
viewer.open( '/test/data/testpattern.dzi' );
|
||||
} );
|
||||
|
||||
// ----------
|
||||
asyncTest( 'EventSource: addHandler with userData', function () {
|
||||
var userData = { item1: 'Test user data', item2: Math.random() },
|
||||
originalUserData = { item1: userData.item1, item2: userData.item2 };
|
||||
|
||||
var openHandler = function ( event ) {
|
||||
viewer.removeHandler( 'open', openHandler );
|
||||
ok( event, 'Event handler received event data' );
|
||||
ok( event && event.userData, 'Event handler received user data' );
|
||||
if ( event && event.userData ) {
|
||||
deepEqual( event.userData, originalUserData, 'User data was untouched' );
|
||||
}
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer.addHandler( 'open', openHandler, userData );
|
||||
viewer.open( '/test/data/testpattern.dzi' );
|
||||
} );
|
||||
|
||||
// ----------
|
||||
asyncTest( 'Viewer: tile-drawing event', function () {
|
||||
var tileDrawing = function ( event ) {
|
||||
viewer.removeHandler( 'tile-drawing', tileDrawing );
|
||||
ok( event, 'Event handler should be invoked' );
|
||||
|
42
test/legacy.mouse.shim.js
Normal file
42
test/legacy.mouse.shim.js
Normal file
@ -0,0 +1,42 @@
|
||||
(function($, undefined) {
|
||||
|
||||
/**
|
||||
* Plugin to force OpenSeadragon to use the legacy mouse pointer event model
|
||||
*/
|
||||
|
||||
$.MouseTracker.subscribeEvents = [ "click", "keypress", "focus", "blur", $.MouseTracker.wheelEventName ];
|
||||
|
||||
if( $.MouseTracker.wheelEventName == "DOMMouseScroll" ) {
|
||||
// Older Firefox
|
||||
$.MouseTracker.subscribeEvents.push( "MozMousePixelScroll" );
|
||||
}
|
||||
|
||||
$.MouseTracker.subscribeEvents.push( "mousedown", "mouseup", "mousemove" );
|
||||
if ( 'onmouseenter' in window ) {
|
||||
$.MouseTracker.subscribeEvents.push( "mouseenter", "mouseleave" );
|
||||
$.MouseTracker.haveMouseEnter = true;
|
||||
} else {
|
||||
$.MouseTracker.subscribeEvents.push( "mouseover", "mouseout" );
|
||||
$.MouseTracker.haveMouseEnter = false;
|
||||
}
|
||||
if ( 'ontouchstart' in window ) {
|
||||
// iOS, Android, and other W3c Touch Event implementations (see http://www.w3.org/TR/2011/WD-touch-events-20110505)
|
||||
$.MouseTracker.subscribeEvents.push( "touchstart", "touchend", "touchmove", "touchcancel" );
|
||||
if ( 'ontouchenter' in window ) {
|
||||
$.MouseTracker.subscribeEvents.push( "touchenter", "touchleave" );
|
||||
$.MouseTracker.haveTouchEnter = true;
|
||||
} else {
|
||||
$.MouseTracker.haveTouchEnter = false;
|
||||
}
|
||||
} else {
|
||||
$.MouseTracker.haveTouchEnter = false;
|
||||
}
|
||||
if ( 'ongesturestart' in window ) {
|
||||
// iOS (see https://developer.apple.com/library/safari/documentation/UserExperience/Reference/GestureEventClassReference/GestureEvent/GestureEvent.html)
|
||||
// Subscribe to these to prevent default gesture handling
|
||||
$.MouseTracker.subscribeEvents.push( "gesturestart", "gesturechange" );
|
||||
}
|
||||
$.MouseTracker.mousePointerId = "legacy-mouse";
|
||||
$.MouseTracker.maxTouchPoints = 10;
|
||||
|
||||
}(OpenSeadragon));
|
@ -189,7 +189,7 @@ QUnit.config.autostart = false;
|
||||
clientY:offset.top + locationY
|
||||
};
|
||||
$canvas
|
||||
.simulate('mouseover', event)
|
||||
.simulate(OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseenter' : 'mouseover', event)
|
||||
.simulate('mousedown', event)
|
||||
.simulate('mouseup', event);
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
@ -15,6 +15,7 @@
|
||||
<script src="/test/lib/jquery-ui-1.10.2/js/jquery-ui-1.10.2.min.js"></script>
|
||||
<script src="/test/lib/jquery.simulate.js"></script>
|
||||
<script src="/build/openseadragon/openseadragon.min.js"></script>
|
||||
<script src="/test/legacy.mouse.shim.js"></script>
|
||||
<script src="/test/test.js"></script>
|
||||
|
||||
<!-- Polyfill must be inserted first because it is testing functions
|
||||
|
@ -37,7 +37,7 @@
|
||||
};
|
||||
|
||||
$canvas
|
||||
.simulate( 'mouseover', event )
|
||||
.simulate( OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseenter' : 'mouseover', event )
|
||||
.simulate( 'mousedown', event );
|
||||
for ( var i = 0; i < args.dragCount; i++ ) {
|
||||
event.clientX += args.dragDx;
|
||||
@ -47,7 +47,7 @@
|
||||
}
|
||||
$canvas
|
||||
.simulate( 'mouseup', event )
|
||||
.simulate( 'mouseout', event );
|
||||
.simulate( OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseleave' : 'mouseout', event );
|
||||
},
|
||||
|
||||
initializeTestDOM: function () {
|
||||
|
Loading…
x
Reference in New Issue
Block a user