diff --git a/Gruntfile.js b/Gruntfile.js
index e030188c..e3395308 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -202,7 +202,7 @@ module.exports = function(grunt) {
target: sources
},
"git-describe": {
- "options": {
+ options: {
failOnError: false
},
build: {}
diff --git a/changelog.txt b/changelog.txt
index 11ca2b6d..bae5de01 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -7,6 +7,16 @@ OPENSEADRAGON CHANGELOG
* Documentation fix (#1814 @kenanchristian)
* Better cleanup on destruction, to avoid memory leaks (#1832 @JoFrMueller)
* Miscellaneous code cleanup (#1840 @msalsbery)
+* Improved browser sniffing - detect EDGE and CHROMEEDGE browsers
+* Improved DOM event model feature detection
+* Added support for options parameter on addEvent()/removeEvent (to support passive option)
+* Added OpenSeadragon.eventIsCanceled() function for defaultPrevented detection on DOM events
+* MouseTracker: better PointerEvent model detection - removed use of deprecated window.navigator.pointerEnabled
+* MouseTracker: added overHandler/outHandler options for handling corresponding pointerover/pointerout events
+* MouseTracker: changed enterHandler/leaveHandler to use DOM pointerenter/pointerleave events instead of simulating using pointerover/pointerout
+* DEPRECATION: MouseTracker exitHandler deprecated for name change to leaveHandler for consistency with DOM event names
+* Added missing Button event object properties (were listed in documentation but not implemented)
+* Fixed bug in Button class where two MouseTracker event handlers used an invalid "this" causing issues in some browsers
2.4.2:
@@ -54,7 +64,7 @@ OPENSEADRAGON CHANGELOG
* You can now prevent canvas-click events on the navigator (#1416)
* The navigator can now be restricted to just horizontal or just vertical panning (#1416)
* Fixed DziTileSource so it doesn't load levels above maxLevel or below minLevel, if set (#1492)
-
+
2.3.1:
* Debug mode now uses different colors for different tiled images (customizable via debugGridColor) (#1271)
diff --git a/src/button.js b/src/button.js
index 7b00f9ee..9c3f2db0 100644
--- a/src/button.js
+++ b/src/button.js
@@ -77,6 +77,7 @@ $.ButtonState = {
* @param {OpenSeadragon.EventHandler} [options.onExit=null] Event handler callback for {@link OpenSeadragon.Button.event:exit}.
* @param {OpenSeadragon.EventHandler} [options.onFocus=null] Event handler callback for {@link OpenSeadragon.Button.event:focus}.
* @param {OpenSeadragon.EventHandler} [options.onBlur=null] Event handler callback for {@link OpenSeadragon.Button.event:blur}.
+ * @param {Object} [options.userData=null] Arbitrary object to be passed unchanged to any attached handler methods.
*/
$.Button = function( options ) {
@@ -111,7 +112,8 @@ $.Button = function( options ) {
onEnter: null,
onExit: null,
onFocus: null,
- onBlur: null
+ onBlur: null,
+ userData: null
}, options );
@@ -203,6 +205,7 @@ $.Button = function( options ) {
*/
this.tracker = new $.MouseTracker({
+ userData: 'Button.tracker',
element: this.element,
clickTimeThreshold: this.clickTimeThreshold,
clickDistThreshold: this.clickDistThreshold,
@@ -220,14 +223,18 @@ $.Button = function( options ) {
* @property {Object} originalEvent - The original DOM event.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
- _this.raiseEvent( "enter", { originalEvent: event.originalEvent } );
+ _this.raiseEvent( "enter", {
+ eventSource: _this,
+ originalEvent: event.originalEvent,
+ userData: _this.userData
+ } );
} else if ( !event.buttonDownAny ) {
inTo( _this, $.ButtonState.HOVER );
}
},
focusHandler: function ( event ) {
- this.enterHandler( event );
+ _this.tracker.enterHandler( event );
/**
* Raised when the Button element receives focus.
*
@@ -238,10 +245,14 @@ $.Button = function( options ) {
* @property {Object} originalEvent - The original DOM event.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
- _this.raiseEvent( "focus", { originalEvent: event.originalEvent } );
+ _this.raiseEvent( "focus", {
+ eventSource: _this,
+ originalEvent: event.originalEvent,
+ userData: _this.userData
+ } );
},
- exitHandler: function( event ) {
+ leaveHandler: function( event ) {
outTo( _this, $.ButtonState.GROUP );
if ( event.insideElementPressed ) {
/**
@@ -254,12 +265,16 @@ $.Button = function( options ) {
* @property {Object} originalEvent - The original DOM event.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
- _this.raiseEvent( "exit", { originalEvent: event.originalEvent } );
+ _this.raiseEvent( "exit", {
+ eventSource: _this,
+ originalEvent: event.originalEvent,
+ userData: _this.userData
+ } );
}
},
blurHandler: function ( event ) {
- this.exitHandler( event );
+ _this.tracker.leaveHandler( event );
/**
* Raised when the Button element loses focus.
*
@@ -270,7 +285,11 @@ $.Button = function( options ) {
* @property {Object} originalEvent - The original DOM event.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
- _this.raiseEvent( "blur", { originalEvent: event.originalEvent } );
+ _this.raiseEvent( "blur", {
+ eventSource: _this,
+ originalEvent: event.originalEvent,
+ userData: _this.userData
+ } );
},
pressHandler: function ( event ) {
@@ -285,7 +304,11 @@ $.Button = function( options ) {
* @property {Object} originalEvent - The original DOM event.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
- _this.raiseEvent( "press", { originalEvent: event.originalEvent } );
+ _this.raiseEvent( "press", {
+ eventSource: _this,
+ originalEvent: event.originalEvent,
+ userData: _this.userData
+ } );
},
releaseHandler: function( event ) {
@@ -301,7 +324,11 @@ $.Button = function( options ) {
* @property {Object} originalEvent - The original DOM event.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
- _this.raiseEvent( "release", { originalEvent: event.originalEvent } );
+ _this.raiseEvent( "release", {
+ eventSource: _this,
+ originalEvent: event.originalEvent,
+ userData: _this.userData
+ } );
} else if ( event.insideElementPressed ) {
outTo( _this, $.ButtonState.GROUP );
} else {
@@ -321,7 +348,11 @@ $.Button = function( options ) {
* @property {Object} originalEvent - The original DOM event.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
- _this.raiseEvent("click", { originalEvent: event.originalEvent });
+ _this.raiseEvent("click", {
+ eventSource: _this,
+ originalEvent: event.originalEvent,
+ userData: _this.userData
+ });
}
},
@@ -338,7 +369,11 @@ $.Button = function( options ) {
* @property {Object} originalEvent - The original DOM event.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
- _this.raiseEvent( "click", { originalEvent: event.originalEvent } );
+ _this.raiseEvent( "click", {
+ eventSource: _this,
+ originalEvent: event.originalEvent,
+ userData: _this.userData
+ } );
/***
* Raised when the mouse button is released or touch ends in the Button element.
*
@@ -349,7 +384,11 @@ $.Button = function( options ) {
* @property {Object} originalEvent - The original DOM event.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
- _this.raiseEvent( "release", { originalEvent: event.originalEvent } );
+ _this.raiseEvent( "release", {
+ eventSource: _this,
+ originalEvent: event.originalEvent,
+ userData: _this.userData
+ } );
return false;
}
return true;
@@ -363,8 +402,8 @@ $.Button = function( options ) {
$.extend( $.Button.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.Button.prototype */{
/**
- * TODO: Determine what this function is intended to do and if it's actually
- * useful as an API point.
+ * Used by a button container element (e.g. a ButtonGroup) to transition the button state
+ * to ButtonState.GROUP.
* @function
*/
notifyGroupEnter: function() {
@@ -372,8 +411,8 @@ $.extend( $.Button.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.
},
/**
- * TODO: Determine what this function is intended to do and if it's actually
- * useful as an API point.
+ * Used by a button container element (e.g. a ButtonGroup) to transition the button state
+ * to ButtonState.REST.
* @function
*/
notifyGroupExit: function() {
diff --git a/src/buttongroup.js b/src/buttongroup.js
index 995f90d3..5af71fea 100644
--- a/src/buttongroup.js
+++ b/src/buttongroup.js
@@ -88,6 +88,7 @@ $.ButtonGroup = function( options ) {
* @memberof OpenSeadragon.ButtonGroup#
*/
this.tracker = new $.MouseTracker({
+ userData: 'ButtonGroup.tracker',
element: this.element,
clickTimeThreshold: this.clickTimeThreshold,
clickDistThreshold: this.clickDistThreshold,
@@ -97,7 +98,7 @@ $.ButtonGroup = function( options ) {
_this.buttons[ i ].notifyGroupEnter();
}
},
- exitHandler: function ( event ) {
+ leaveHandler: function ( event ) {
var i;
if ( !event.insideElementPressed ) {
for ( i = 0; i < _this.buttons.length; i++ ) {
@@ -127,8 +128,8 @@ $.ButtonGroup.prototype = {
* @function
* @private
*/
- emulateExit: function() {
- this.tracker.exitHandler( { eventSource: this.tracker } );
+ emulateLeave: function() {
+ this.tracker.leaveHandler( { eventSource: this.tracker } );
},
destroy: function() {
diff --git a/src/mousetracker.js b/src/mousetracker.js
index d1b584ae..72658f2f 100644
--- a/src/mousetracker.js
+++ b/src/mousetracker.js
@@ -74,8 +74,14 @@
* event is fired.
* @param {OpenSeadragon.EventHandler} [options.enterHandler=null]
* An optional handler for pointer enter.
+ * @param {OpenSeadragon.EventHandler} [options.leaveHandler=null]
+ * An optional handler for pointer leave.
* @param {OpenSeadragon.EventHandler} [options.exitHandler=null]
- * An optional handler for pointer exit.
+ * An optional handler for pointer leave. Deprecated. Use leaveHandler instead.
+ * @param {OpenSeadragon.EventHandler} [options.overHandler=null]
+ * An optional handler for pointer over.
+ * @param {OpenSeadragon.EventHandler} [options.outHandler=null]
+ * An optional handler for pointer out.
* @param {OpenSeadragon.EventHandler} [options.pressHandler=null]
* An optional handler for pointer press.
* @param {OpenSeadragon.EventHandler} [options.nonPrimaryPressHandler=null]
@@ -165,7 +171,10 @@
this.stopDelay = options.stopDelay || 50;
this.enterHandler = options.enterHandler || null;
+ this.leaveHandler = options.leaveHandler || null;
this.exitHandler = options.exitHandler || null;
+ this.overHandler = options.overHandler || null;
+ this.outHandler = options.outHandler || null;
this.pressHandler = options.pressHandler || null;
this.nonPrimaryPressHandler = options.nonPrimaryPressHandler || null;
this.releaseHandler = options.releaseHandler || null;
@@ -207,10 +216,10 @@
DOMMouseScroll: function ( event ) { onMouseWheel( _this, event ); },
MozMousePixelScroll: function ( event ) { onMouseWheel( _this, event ); },
- mouseenter: function ( event ) { onMouseEnter( _this, event ); }, // Used on IE8 only
- mouseleave: function ( event ) { onMouseLeave( _this, event ); }, // Used on IE8 only
- mouseover: function ( event ) { onMouseOver( _this, event ); },
- mouseout: function ( event ) { onMouseOut( _this, event ); },
+ mouseover: function ( event ) { onMouseOver( _this, event ); }, // IE9+ only
+ mouseout: function ( event ) { onMouseOut( _this, event ); }, // IE9+ only
+ mouseenter: function ( event ) { onMouseEnter( _this, event ); },
+ mouseleave: function ( event ) { onMouseLeave( _this, event ); },
mousedown: function ( event ) { onMouseDown( _this, event ); },
mouseup: function ( event ) { onMouseUp( _this, event ); },
mouseupcaptured: function ( event ) { onMouseUpCaptured( _this, event ); },
@@ -231,6 +240,10 @@
MSPointerOver: function ( event ) { onPointerOver( _this, event ); },
pointerout: function ( event ) { onPointerOut( _this, event ); },
MSPointerOut: function ( event ) { onPointerOut( _this, event ); },
+ pointerenter: function ( event ) { onPointerEnter( _this, event ); },
+ MSPointerEnter: function ( event ) { onPointerEnter( _this, event ); },
+ pointerleave: function ( event ) { onPointerLeave( _this, event ); },
+ MSPointerLeave: function ( event ) { onPointerLeave( _this, event ); },
pointerdown: function ( event ) { onPointerDown( _this, event ); },
MSPointerDown: function ( event ) { onPointerDown( _this, event ); },
pointerup: function ( event ) { onPointerUp( _this, event ); },
@@ -403,12 +416,74 @@
* True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.
* @param {Object} event.originalEvent
* The original event object.
+ * @param {Object} event.userData
+ * Arbitrary user-defined object.
+ */
+ enterHandler: function () { },
+
+ /**
+ * Implement or assign implementation to these handlers during or after
+ * calling the constructor.
+ * @function
+ * @deprecated Use leaveHandler instead
+ * @param {Object} event
+ * @param {OpenSeadragon.MouseTracker} event.eventSource
+ * A reference to the tracker instance.
+ * @param {String} event.pointerType
+ * "mouse", "touch", "pen", etc.
+ * @param {OpenSeadragon.Point} event.position
+ * The position of the event relative to the tracked element.
+ * @param {Number} event.buttons
+ * Current buttons pressed.
+ * 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.
+ * @param {Number} event.pointers
+ * Number of pointers (all types) active in the tracked element.
+ * @param {Boolean} event.insideElementPressed
+ * True if the left mouse button is currently being pressed and was
+ * initiated inside the tracked element, otherwise false.
+ * @param {Boolean} event.buttonDownAny
+ * Was the button down anywhere in the screen during the event. Deprecated. Use buttons instead.
+ * @param {Boolean} event.isTouchEvent
+ * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.
+ * @param {Object} event.originalEvent
+ * The original event object.
+ * @param {Object} event.userData
+ * Arbitrary user-defined object.
+ */
+ leaveHandler: function () { },
+
+ /**
+ * Implement or assign implementation to these handlers during or after
+ * calling the constructor.
+ * @function
+ * @deprecated Use leaveHandler instead
+ * @param {Object} event
+ * @param {OpenSeadragon.MouseTracker} event.eventSource
+ * A reference to the tracker instance.
+ * @param {String} event.pointerType
+ * "mouse", "touch", "pen", etc.
+ * @param {OpenSeadragon.Point} event.position
+ * The position of the event relative to the tracked element.
+ * @param {Number} event.buttons
+ * Current buttons pressed.
+ * 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.
+ * @param {Number} event.pointers
+ * Number of pointers (all types) active in the tracked element.
+ * @param {Boolean} event.insideElementPressed
+ * True if the left mouse button is currently being pressed and was
+ * initiated inside the tracked element, otherwise false.
+ * @param {Boolean} event.buttonDownAny
+ * Was the button down anywhere in the screen during the event. Deprecated. Use buttons instead.
+ * @param {Boolean} event.isTouchEvent
+ * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.
+ * @param {Object} event.originalEvent
+ * The original event object.
* @param {Boolean} event.preventDefaultAction
* Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.
* @param {Object} event.userData
* Arbitrary user-defined object.
*/
- enterHandler: function () { },
+ exitHandler: function () { },
/**
* Implement or assign implementation to these handlers during or after
@@ -440,7 +515,39 @@
* @param {Object} event.userData
* Arbitrary user-defined object.
*/
- exitHandler: function () { },
+ overHandler: function () { },
+
+ /**
+ * Implement or assign implementation to these handlers during or after
+ * calling the constructor.
+ * @function
+ * @param {Object} event
+ * @param {OpenSeadragon.MouseTracker} event.eventSource
+ * A reference to the tracker instance.
+ * @param {String} event.pointerType
+ * "mouse", "touch", "pen", etc.
+ * @param {OpenSeadragon.Point} event.position
+ * The position of the event relative to the tracked element.
+ * @param {Number} event.buttons
+ * Current buttons pressed.
+ * 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.
+ * @param {Number} event.pointers
+ * Number of pointers (all types) active in the tracked element.
+ * @param {Boolean} event.insideElementPressed
+ * True if the left mouse button is currently being pressed and was
+ * initiated inside the tracked element, otherwise false.
+ * @param {Boolean} event.buttonDownAny
+ * Was the button down anywhere in the screen during the event. Deprecated. Use buttons instead.
+ * @param {Boolean} event.isTouchEvent
+ * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.
+ * @param {Object} event.originalEvent
+ * The original event object.
+ * @param {Boolean} event.preventDefaultAction
+ * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.
+ * @param {Object} event.userData
+ * Arbitrary user-defined object.
+ */
+ outHandler: function () { },
/**
* Implement or assign implementation to these handlers during or after
@@ -1020,38 +1127,37 @@
$.MouseTracker.subscribeEvents.push( "MozMousePixelScroll" );
}
- // Note: window.navigator.pointerEnable is deprecated on IE 11 and not part of W3C spec.
- if ( window.PointerEvent && ( window.navigator.pointerEnabled || $.Browser.vendor !== $.BROWSERS.IE ) ) {
+ if ( window.PointerEvent ) {
// IE11 and other W3C Pointer Event implementations (see http://www.w3.org/TR/pointerevents)
$.MouseTracker.havePointerEvents = true;
- $.MouseTracker.subscribeEvents.push( "pointerover", "pointerout", "pointerdown", "pointerup", "pointermove", "pointercancel" );
+ $.MouseTracker.subscribeEvents.push( "pointerenter", "pointerleave", "pointerover", "pointerout", "pointerdown", "pointerup", "pointermove", "pointercancel" );
$.MouseTracker.unprefixedPointerEvents = true;
if( navigator.maxTouchPoints ) {
$.MouseTracker.maxTouchPoints = navigator.maxTouchPoints;
} else {
$.MouseTracker.maxTouchPoints = 0;
}
- $.MouseTracker.haveMouseEnter = false;
+ $.MouseTracker.haveMouseOver = true;
} else if ( window.MSPointerEvent && window.navigator.msPointerEnabled ) {
// IE10
$.MouseTracker.havePointerEvents = true;
- $.MouseTracker.subscribeEvents.push( "MSPointerOver", "MSPointerOut", "MSPointerDown", "MSPointerUp", "MSPointerMove", "MSPointerCancel" );
+ $.MouseTracker.subscribeEvents.push( "MSPointerEnter", "MSPointerLeave", "MSPointerOver", "MSPointerOut", "MSPointerDown", "MSPointerUp", "MSPointerMove", "MSPointerCancel" );
$.MouseTracker.unprefixedPointerEvents = false;
if( navigator.msMaxTouchPoints ) {
$.MouseTracker.maxTouchPoints = navigator.msMaxTouchPoints;
} else {
$.MouseTracker.maxTouchPoints = 0;
}
- $.MouseTracker.haveMouseEnter = false;
+ $.MouseTracker.haveMouseOver = true;
} else {
// Legacy W3C mouse events
$.MouseTracker.havePointerEvents = false;
- if ( $.Browser.vendor === $.BROWSERS.IE && $.Browser.version < 9 ) {
- $.MouseTracker.subscribeEvents.push( "mouseenter", "mouseleave" );
- $.MouseTracker.haveMouseEnter = true;
- } else {
+ $.MouseTracker.subscribeEvents.push( "mouseenter", "mouseleave" );
+ if ( $.Browser.vendor !== $.BROWSERS.IE || $.Browser.version > 8 ) {
$.MouseTracker.subscribeEvents.push( "mouseover", "mouseout" );
- $.MouseTracker.haveMouseEnter = false;
+ $.MouseTracker.haveMouseOver = true;
+ } else {
+ $.MouseTracker.haveMouseOver = false;
}
$.MouseTracker.subscribeEvents.push( "mousedown", "mouseup", "mousemove" );
if ( 'ontouchstart' in window ) {
@@ -1832,38 +1938,12 @@
/**
- * Only used on IE 8
- *
* @private
* @inner
*/
function onMouseEnter( tracker, event ) {
event = $.getEvent( event );
- handleMouseEnter( tracker, event );
- }
-
-
- /**
- * @private
- * @inner
- */
- function onMouseOver( tracker, event ) {
- event = $.getEvent( event );
-
- if ( event.currentTarget === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
- return;
- }
-
- handleMouseEnter( tracker, event );
- }
-
-
- /**
- * @private
- * @inner
- */
- function handleMouseEnter( tracker, event ) {
var gPoint = {
id: $.MouseTracker.mousePointerId,
type: 'mouse',
@@ -1873,42 +1953,21 @@
};
updatePointersEnter( tracker, event, [ gPoint ] );
+
+ //TODO simulate mouseover on IE < 9?
+ // if ( $.Browser.vendor === $.BROWSERS.IE && $.Browser.version < 9 ) {
+ // handleMouseOver( tracker, event );
+ // }
}
/**
- * Only used on IE 8
- *
* @private
* @inner
*/
function onMouseLeave( tracker, event ) {
event = $.getEvent( event );
- handleMouseExit( tracker, event );
- }
-
-
- /**
- * @private
- * @inner
- */
- function onMouseOut( tracker, event ) {
- event = $.getEvent( event );
-
- if ( event.currentTarget === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
- return;
- }
-
- handleMouseExit( tracker, event );
- }
-
-
- /**
- * @private
- * @inner
- */
- function handleMouseExit( tracker, event ) {
var gPoint = {
id: $.MouseTracker.mousePointerId,
type: 'mouse',
@@ -1917,7 +1976,76 @@
currentTime: $.now()
};
- updatePointersExit( tracker, event, [ gPoint ] );
+ updatePointersLeave( tracker, event, [ gPoint ] );
+
+ //TODO simulate mouseoout on IE < 9?
+ // if ( $.Browser.vendor === $.BROWSERS.IE && $.Browser.version < 9 ) {
+ // handleMouseOut( tracker, event );
+ // }
+ }
+
+
+ /**
+ * IE9+ only
+ *
+ * @private
+ * @inner
+ */
+ function onMouseOver( tracker, event ) {
+ // if ( event.currentTarget === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
+ // return;
+ // }
+
+ handleMouseOver( tracker, event );
+ }
+
+
+ /**
+ * @private
+ * @inner
+ */
+ function handleMouseOver( tracker, event ) {
+ var gPoint = {
+ id: $.MouseTracker.mousePointerId,
+ type: 'mouse',
+ isPrimary: true,
+ currentPos: getMouseAbsolute( event ),
+ currentTime: $.now()
+ };
+
+ updatePointersOver( tracker, event, [ gPoint ] );
+ }
+
+
+ /**
+ * IE9+ only
+ *
+ * @private
+ * @inner
+ */
+ function onMouseOut( tracker, event ) {
+ // if ( event.currentTarget === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
+ // return;
+ // }
+
+ handleMouseOut( tracker, event );
+ }
+
+
+ /**
+ * @private
+ * @inner
+ */
+ function handleMouseOut( tracker, event ) {
+ var gPoint = {
+ id: $.MouseTracker.mousePointerId,
+ type: 'mouse',
+ isPrimary: true,
+ currentPos: getMouseAbsolute( event ),
+ currentTime: $.now()
+ };
+
+ updatePointersOut( tracker, event, [ gPoint ] );
}
@@ -2083,7 +2211,7 @@
pointsList.captureCount = 1;
releasePointer( tracker, pointsList.type );
// simulate touchleave/mouseout
- updatePointersExit( tracker, event, abortGPoints );
+ updatePointersLeave( tracker, event, abortGPoints );
}
}
}
@@ -2199,7 +2327,7 @@
}
// simulate touchleave on our tracked element
- updatePointersExit( tracker, event, gPoints );
+ updatePointersLeave( tracker, event, gPoints );
// simulate touchleave on our tracked element's tracked ancestor elements
for ( i = 0; i < MOUSETRACKERS.length; i++ ) {
@@ -2214,7 +2342,7 @@
currentTime: time
} );
}
- updatePointersExit( MOUSETRACKERS[ i ], event, parentGPoints );
+ updatePointersLeave( MOUSETRACKERS[ i ], event, parentGPoints );
}
}
@@ -2306,12 +2434,10 @@
* @private
* @inner
*/
- function onPointerOver( tracker, event ) {
+ function onPointerEnter( tracker, event ) {
var gPoint;
- if ( event.currentTarget === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
- return;
- }
+ //$.console.log('pointerenter ' + (tracker.userData ? tracker.userData.toString() : '') + ' ' + (event.target === tracker.element ? 'tracker.element' : ''));
gPoint = {
id: event.pointerId,
@@ -2322,6 +2448,52 @@
};
updatePointersEnter( tracker, event, [ gPoint ] );
+}
+
+
+ /**
+ * @private
+ * @inner
+ */
+ function onPointerLeave( tracker, event ) {
+ var gPoint;
+
+ //$.console.log('pointerleave ' + (tracker.userData ? tracker.userData.toString() : '') + ' ' + (event.target === tracker.element ? 'tracker.element' : ''));
+
+ gPoint = {
+ id: event.pointerId,
+ type: getPointerType( event ),
+ isPrimary: event.isPrimary,
+ currentPos: getMouseAbsolute( event ),
+ currentTime: $.now()
+ };
+
+ updatePointersLeave( tracker, event, [ gPoint ] );
+ }
+
+
+ /**
+ * @private
+ * @inner
+ */
+ function onPointerOver( tracker, event ) {
+ var gPoint;
+
+ $.console.log('pointerover ' + (tracker.userData ? tracker.userData.toString() : '') + ' ' + (event.target === tracker.element ? 'tracker.element' : ''));
+
+ //if ( event.currentTarget === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
+ // return;
+ //}
+
+ gPoint = {
+ id: event.pointerId,
+ type: getPointerType( event ),
+ isPrimary: event.isPrimary,
+ currentPos: getMouseAbsolute( event ),
+ currentTime: $.now()
+ };
+
+ updatePointersOver( tracker, event, [ gPoint ] );
}
@@ -2332,9 +2504,11 @@
function onPointerOut( tracker, event ) {
var gPoint;
- if ( event.currentTarget === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
- return;
- }
+ $.console.log('pointerout ' + (tracker.userData ? tracker.userData.toString() : '') + ' ' + (event.target === tracker.element ? 'tracker.element' : ''));
+
+ //if ( event.currentTarget === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
+ // return;
+ //}
gPoint = {
id: event.pointerId,
@@ -2344,7 +2518,7 @@
currentTime: $.now()
};
- updatePointersExit( tracker, event, [ gPoint ] );
+ updatePointersOut( tracker, event, [ gPoint ] );
}
@@ -2568,8 +2742,7 @@
i,
gPointCount = gPoints.length,
curGPoint,
- updateGPoint,
- propagate;
+ updateGPoint;
for ( i = 0; i < gPointCount; i++ ) {
curGPoint = gPoints[ i ];
@@ -2592,9 +2765,129 @@
startTrackingPointer( pointsList, curGPoint );
}
- // Enter
+ // Enter (doesn't bubble and not cancelable)
if ( tracker.enterHandler ) {
- propagate = tracker.enterHandler(
+ tracker.enterHandler(
+ {
+ eventSource: tracker,
+ pointerType: curGPoint.type,
+ position: getPointRelativeToAbsolute( curGPoint.currentPos, tracker.element ),
+ buttons: pointsList.buttons,
+ pointers: tracker.getActivePointerCount(),
+ insideElementPressed: curGPoint.insideElementPressed,
+ buttonDownAny: pointsList.buttons !== 0,
+ isTouchEvent: curGPoint.type === 'touch',
+ originalEvent: event,
+ userData: tracker.userData
+ }
+ );
+ }
+ }
+ }
+
+
+ /**
+ * @function
+ * @private
+ * @inner
+ * @param {OpenSeadragon.MouseTracker} tracker
+ * A reference to the MouseTracker instance.
+ * @param {Object} event
+ * A reference to the originating DOM event.
+ * @param {Array.} gPoints
+ * Gesture points associated with the event.
+ */
+ function updatePointersLeave( tracker, event, gPoints ) {
+ var pointsList = tracker.getActivePointersListByType(gPoints[0].type),
+ i,
+ gPointCount = gPoints.length,
+ curGPoint,
+ updateGPoint,
+ dispatchEventObj;
+
+ for ( i = 0; i < gPointCount; i++ ) {
+ curGPoint = gPoints[ i ];
+ updateGPoint = pointsList.getById( curGPoint.id );
+
+ if ( updateGPoint ) {
+ // Already tracking the pointer. If captured then update it, else stop tracking it
+ if ( updateGPoint.captured ) {
+ updateGPoint.insideElement = false;
+ updateGPoint.lastPos = updateGPoint.currentPos;
+ updateGPoint.lastTime = updateGPoint.currentTime;
+ updateGPoint.currentPos = curGPoint.currentPos;
+ updateGPoint.currentTime = curGPoint.currentTime;
+ } else {
+ stopTrackingPointer( pointsList, updateGPoint );
+ }
+
+ curGPoint = updateGPoint;
+ }
+
+ // Leave (doesn't bubble and not cancelable)
+ // Note: exitHandler is deprecated, replaced by leaveHandler
+ if ( tracker.leaveHandler || tracker.exitHandler ) {
+ dispatchEventObj = {
+ eventSource: tracker,
+ pointerType: curGPoint.type,
+ position: curGPoint.currentPos && getPointRelativeToAbsolute( curGPoint.currentPos, tracker.element ),
+ buttons: pointsList.buttons,
+ pointers: tracker.getActivePointerCount(),
+ insideElementPressed: updateGPoint ? updateGPoint.insideElementPressed : false,
+ buttonDownAny: pointsList.buttons !== 0,
+ isTouchEvent: curGPoint.type === 'touch',
+ originalEvent: event,
+ userData: tracker.userData
+ };
+
+ if ( tracker.leaveHandler ) {
+ tracker.leaveHandler( dispatchEventObj );
+ }
+ if ( tracker.exitHandler ) {
+ tracker.exitHandler( dispatchEventObj );
+ }
+ }
+ }
+ }
+
+
+ /**
+ * @function
+ * @private
+ * @inner
+ * @param {OpenSeadragon.MouseTracker} tracker
+ * A reference to the MouseTracker instance.
+ * @param {Object} event
+ * A reference to the originating DOM event.
+ * @param {Array.} gPoints
+ * Gesture points associated with the event.
+ */
+ function updatePointersOver( tracker, event, gPoints ) {
+ var pointsList,
+ i,
+ gPointCount,
+ curGPoint,
+ updateGPoint,
+ propagate;
+
+ if ( tracker.overHandler ) {
+ pointsList = tracker.getActivePointersListByType( gPoints[ 0 ].type );
+ gPointCount = gPoints.length;
+
+ for ( i = 0; i < gPointCount; i++ ) {
+ curGPoint = gPoints[ i ];
+ updateGPoint = pointsList.getById( curGPoint.id );
+
+ if ( updateGPoint ) {
+ curGPoint = updateGPoint;
+ } else {
+ //curGPoint.captured = false; // Tracked by updatePointersEnter
+ curGPoint.insideElementPressed = false;
+ //curGPoint.insideElement = true; // Tracked by updatePointersEnter
+ }
+
+ // Over
+ propagate = tracker.overHandler(
{
eventSource: tracker,
pointerType: curGPoint.type,
@@ -2616,7 +2909,6 @@
}
}
-
/**
* @function
* @private
@@ -2628,51 +2920,40 @@
* @param {Array.} gPoints
* Gesture points associated with the event.
*/
- function updatePointersExit( tracker, event, gPoints ) {
- var pointsList = tracker.getActivePointersListByType(gPoints[0].type),
+ function updatePointersOut( tracker, event, gPoints ) {
+ var pointsList,
i,
- gPointCount = gPoints.length,
+ gPointCount,
curGPoint,
updateGPoint,
propagate;
- for ( i = 0; i < gPointCount; i++ ) {
- curGPoint = gPoints[ i ];
- updateGPoint = pointsList.getById( curGPoint.id );
+ if ( tracker.outHandler ) {
+ pointsList = tracker.getActivePointersListByType(gPoints[0].type);
+ gPointCount = gPoints.length;
- if ( updateGPoint ) {
- // Already tracking the pointer. If captured then update it, else stop tracking it
- if ( updateGPoint.captured ) {
- updateGPoint.insideElement = false;
- updateGPoint.lastPos = updateGPoint.currentPos;
- updateGPoint.lastTime = updateGPoint.currentTime;
- updateGPoint.currentPos = curGPoint.currentPos;
- updateGPoint.currentTime = curGPoint.currentTime;
- } else {
- stopTrackingPointer( pointsList, updateGPoint );
+ for ( i = 0; i < gPointCount; i++ ) {
+ curGPoint = gPoints[ i ];
+ updateGPoint = pointsList.getById( curGPoint.id );
+
+ if ( updateGPoint ) {
+ curGPoint = updateGPoint;
}
- curGPoint = updateGPoint;
- }
-
- // Exit
- if ( tracker.exitHandler ) {
- propagate = tracker.exitHandler(
- {
- eventSource: tracker,
- pointerType: curGPoint.type,
- position: curGPoint.currentPos && getPointRelativeToAbsolute( curGPoint.currentPos, tracker.element ),
- buttons: pointsList.buttons,
- pointers: tracker.getActivePointerCount(),
- insideElementPressed: updateGPoint ? updateGPoint.insideElementPressed : false,
- buttonDownAny: pointsList.buttons !== 0,
- isTouchEvent: curGPoint.type === 'touch',
- originalEvent: event,
- preventDefaultAction: false,
- userData: tracker.userData
- }
- );
-
+ // Out
+ propagate = tracker.outHandler( {
+ eventSource: tracker,
+ pointerType: curGPoint.type,
+ position: curGPoint.currentPos && getPointRelativeToAbsolute( curGPoint.currentPos, tracker.element ),
+ buttons: pointsList.buttons,
+ pointers: tracker.getActivePointerCount(),
+ insideElementPressed: updateGPoint ? updateGPoint.insideElementPressed : false,
+ buttonDownAny: pointsList.buttons !== 0,
+ isTouchEvent: curGPoint.type === 'touch',
+ originalEvent: event,
+ preventDefaultAction: false,
+ userData: tracker.userData
+ } );
if ( propagate === false ) {
$.cancelEvent( event );
}
@@ -3326,7 +3607,7 @@
*/
function updatePointersCancel( tracker, event, gPoints ) {
updatePointersUp( tracker, event, gPoints, 0 );
- updatePointersExit( tracker, event, gPoints );
+ updatePointersLeave( tracker, event, gPoints );
}
@@ -3367,7 +3648,7 @@
* @function
* @private
* @inner
- * @returns {Boolean} True if the target has access rights to events, otherwise false.
+ * @returns {Boolean} True if the target supports DOM Level 2 event subscription methods, otherwise false.
*/
function canAccessEvents (target) {
try {
diff --git a/src/navigator.js b/src/navigator.js
index f0bdf452..4a8db20a 100644
--- a/src/navigator.js
+++ b/src/navigator.js
@@ -221,6 +221,7 @@ $.Navigator = function( options ){
// Remove the base class' (Viewer's) innerTracker and replace it with our own
this.innerTracker.destroy();
this.innerTracker = new $.MouseTracker({
+ userData: 'Navigator.innerTracker',
element: this.element,
dragHandler: $.delegate( this, onCanvasDrag ),
clickHandler: $.delegate( this, onCanvasClick ),
diff --git a/src/openseadragon.js b/src/openseadragon.js
index f035c436..d23291b8 100644
--- a/src/openseadragon.js
+++ b/src/openseadragon.js
@@ -917,6 +917,58 @@ function OpenSeadragon( options ){
return isTainted;
};
+ /**
+ * True if the browser supports the EventTarget.removeEventListener() method
+ * @member {Boolean} supportsAddEventListener
+ * @memberof OpenSeadragon
+ */
+ $.supportsAddEventListener = (function () {
+ return !!(document.documentElement.addEventListener && document.addEventListener);
+ }());
+
+ /**
+ * True if the browser supports the EventTarget.removeEventListener() method
+ * @member {Boolean} supportsRemoveEventListener
+ * @memberof OpenSeadragon
+ */
+ $.supportsRemoveEventListener = (function () {
+ return !!(document.documentElement.removeEventListener && document.removeEventListener);
+ }());
+
+ /**
+ * True if the browser supports the newer EventTarget.addEventListener options argument
+ * @member {Boolean} supportsEventListenerOptions
+ * @memberof OpenSeadragon
+ */
+ $.supportsEventListenerOptions = (function () {
+ var supported = 0;
+
+ if ( $.supportsAddEventListener ) {
+ try {
+ var options = {
+ get capture() {
+ supported++;
+ return false;
+ },
+ get once() {
+ supported++;
+ return false;
+ },
+ get passive() {
+ supported++;
+ return false;
+ }
+ };
+ window.addEventListener("test", null, options);
+ window.removeEventListener("test", null, options);
+ } catch ( e ) {
+ supported = 0;
+ }
+ }
+
+ return supported >= 3;
+ }());
+
/**
* A ratio comparing the device screen's pixel density to the canvas's backing store pixel density,
* clamped to a minimum of 1. Defaults to 1 if canvas isn't supported by the browser.
@@ -942,7 +994,7 @@ function OpenSeadragon( options ){
/**
* This closure defines all static methods available to the OpenSeadragon
- * namespace. Many, if not most, are taked directly from jQuery for use
+ * namespace. Many, if not most, are taken directly from jQuery for use
* to simplify and reduce common programming patterns. More static methods
* from jQuery may eventually make their way into this though we are
* attempting to avoid an explicit dependency on jQuery only because
@@ -1315,6 +1367,8 @@ function OpenSeadragon( options ){
* @property {Number} SAFARI
* @property {Number} CHROME
* @property {Number} OPERA
+ * @property {Number} EDGE
+ * @property {Number} CHROMEEDGE
*/
BROWSERS: {
UNKNOWN: 0,
@@ -1322,7 +1376,9 @@ function OpenSeadragon( options ){
FIREFOX: 2,
SAFARI: 3,
CHROME: 4,
- OPERA: 5
+ OPERA: 5,
+ EDGE: 6,
+ CHROMEEDGE: 7
},
@@ -1978,6 +2034,34 @@ function OpenSeadragon( options ){
element.className = newClasses.join(' ');
},
+ /**
+ * COnvert passed addEventListener() options to boolean or options object,
+ * depending on browser support.
+ * @function
+ * @param {Boolean|Object} [options] Boolean useCapture, or if [supportsEventListenerOptions]{@link OpenSeadragon.supportsEventListenerOptions}, can be an object
+ * @param {Boolean} [options.capture]
+ * @param {Boolean} [options.passive]
+ * @param {Boolean} [options.once]
+ * @return {String} The protocol (http:, https:, file:, ftp: ...)
+ */
+ normalizeEventListenerOptions: function (options) {
+ var opts;
+ if ( typeof options !== 'undefined' ) {
+ if ( typeof options === 'boolean' ) {
+ // Legacy Boolean useCapture
+ opts = $.supportsEventListenerOptions ? { capture: options } : options;
+ } else {
+ // Options object
+ opts = $.supportsEventListenerOptions ? options :
+ ( ( typeof options.capture !== 'undefined' ) ? options.capture : false );
+ }
+ } else {
+ // No options specified - Legacy optional useCapture argument
+ // (for IE, first supported on version 9, so we'll pass a Boolean)
+ opts = $.supportsEventListenerOptions ? { capture: false } : false;
+ }
+ return opts;
+ },
/**
* Adds an event listener for the given element, eventName and handler.
@@ -1985,16 +2069,23 @@ function OpenSeadragon( options ){
* @param {Element|String} element
* @param {String} eventName
* @param {Function} handler
- * @param {Boolean} [useCapture]
+ * @param {Boolean|Object} [options] Boolean useCapture, or if [supportsEventListenerOptions]{@link OpenSeadragon.supportsEventListenerOptions}, can be an object
+ * @param {Boolean} [options.capture]
+ * @param {Boolean} [options.passive]
+ * @param {Boolean} [options.once]
*/
+ // undefined - false or {capture: false}
+ // bool - bool or (capture: bool}
+ // obje - obje.capture or obje
addEvent: (function () {
- if ( window.addEventListener ) {
- return function ( element, eventName, handler, useCapture ) {
+ if ( $.supportsAddEventListener ) {
+ return function ( element, eventName, handler, options ) {
+ options = $.normalizeEventListenerOptions(options);
element = $.getElement( element );
- element.addEventListener( eventName, handler, useCapture );
+ element.addEventListener( eventName, handler, options );
};
- } else if ( window.attachEvent ) {
- return function ( element, eventName, handler, useCapture ) {
+ } else if ( document.documentElement.attachEvent && document.attachEvent ) {
+ return function ( element, eventName, handler ) {
element = $.getElement( element );
element.attachEvent( 'on' + eventName, handler );
};
@@ -2011,16 +2102,18 @@ function OpenSeadragon( options ){
* @param {Element|String} element
* @param {String} eventName
* @param {Function} handler
- * @param {Boolean} [useCapture]
+ * @param {Boolean|Object} [options] Boolean useCapture, or if [supportsEventListenerOptions]{@link OpenSeadragon.supportsEventListenerOptions}, can be an object
+ * @param {Boolean} [options.capture]
*/
removeEvent: (function () {
- if ( window.removeEventListener ) {
- return function ( element, eventName, handler, useCapture ) {
+ if ( $.supportsRemoveEventListener ) {
+ return function ( element, eventName, handler, options ) {
+ options = $.normalizeEventListenerOptions(options);
element = $.getElement( element );
- element.removeEventListener( eventName, handler, useCapture );
+ element.removeEventListener( eventName, handler, options );
};
- } else if ( window.detachEvent ) {
- return function( element, eventName, handler, useCapture ) {
+ } else if ( document.documentElement.detachEvent && document.detachEvent ) {
+ return function( element, eventName, handler ) {
element = $.getElement( element );
element.detachEvent( 'on' + eventName, handler );
};
@@ -2049,7 +2142,7 @@ function OpenSeadragon( options ){
event = $.getEvent( event );
// legacy for preventing default
event.cancel = true;
- // IE for preventing default
+ // IE < 9 for preventing default
event.returnValue = false;
};
}
@@ -2058,7 +2151,39 @@ function OpenSeadragon( options ){
/**
- * Stops the propagation of the event up the DOM.
+ * Returns true if {@link OpenSeadragon.cancelEvent|cancelEvent} has been called on
+ * the event, otherwise returns false.
+ * @function
+ * @param {Event} [event]
+ */
+ eventIsCanceled: function( event ) {
+ event = $.getEvent( event );
+
+ if ( event.preventDefault ) {
+ $.eventIsCanceled = function( event ){
+ // W3C
+ return event.defaultPrevented;
+ };
+ } else {
+ $.eventIsCanceled = function( event ){
+ event = $.getEvent( event );
+ if ( typeof event.returnValue !== 'undefined' ) {
+ // IE < 9
+ return !event.returnValue;
+ } else if ( typeof event.cancel !== 'undefined' ) {
+ // legacy
+ return event.cancel;
+ } else {
+ return false;
+ }
+ };
+ }
+ return $.eventIsCanceled( event );
+ },
+
+
+ /**
+ * Stops the propagation of the event through the DOM in the capturing and bubbling phases.
* @function
* @param {Event} [event]
*/
@@ -2071,7 +2196,7 @@ function OpenSeadragon( options ){
event.stopPropagation();
};
} else {
- // IE for stopping propagation
+ // IE < 9 for stopping propagation
$.stopEvent = function( event ){
event = $.getEvent( event );
event.cancelBubble = true;
@@ -2569,7 +2694,17 @@ function OpenSeadragon( options ){
break;
case "Netscape":
if (window.addEventListener) {
- if ( ua.indexOf( "Firefox" ) >= 0 ) {
+ if ( ua.indexOf( "Edge" ) >= 0 ) {
+ $.Browser.vendor = $.BROWSERS.EDGE;
+ $.Browser.version = parseFloat(
+ ua.substring( ua.indexOf( "Edge" ) + 5 )
+ );
+ } else if ( ua.indexOf( "Edg" ) >= 0 ) {
+ $.Browser.vendor = $.BROWSERS.CHROMEEDGE;
+ $.Browser.version = parseFloat(
+ ua.substring( ua.indexOf( "Edg" ) + 4 )
+ );
+ } else if ( ua.indexOf( "Firefox" ) >= 0 ) {
$.Browser.vendor = $.BROWSERS.FIREFOX;
$.Browser.version = parseFloat(
ua.substring( ua.indexOf( "Firefox" ) + 8 )
diff --git a/src/referencestrip.js b/src/referencestrip.js
index 31340e43..ede83662 100644
--- a/src/referencestrip.js
+++ b/src/referencestrip.js
@@ -120,11 +120,12 @@ $.ReferenceStrip = function ( options ) {
this.viewer = viewer;
this.innerTracker = new $.MouseTracker( {
+ userData: 'ReferenceStrip.innerTracker',
element: this.element,
dragHandler: $.delegate( this, onStripDrag ),
scrollHandler: $.delegate( this, onStripScroll ),
enterHandler: $.delegate( this, onStripEnter ),
- exitHandler: $.delegate( this, onStripExit ),
+ leaveHandler: $.delegate( this, onStripLeave ),
keyDownHandler: $.delegate( this, onKeyDown ),
keyHandler: $.delegate( this, onKeyPress )
} );
@@ -196,6 +197,7 @@ $.ReferenceStrip = function ( options ) {
$.setElementTouchActionNone( element );
element.innerTracker = new $.MouseTracker( {
+ userData: 'ReferenceStrip.TileSource.innerTracker',
element: element,
clickTimeThreshold: this.clickTimeThreshold,
clickDistThreshold: this.clickDistThreshold,
@@ -475,7 +477,8 @@ function loadPanels( strip, viewerSize, scroll ) {
// TODO: What is this for? Future keyboard navigation support?
miniViewer.displayRegion.innerTracker = new $.MouseTracker( {
- element: miniViewer.displayRegion,
+ userData: 'ReferenceStrip.miniViewer.innerTracker',
+ element: miniViewer.displayRegion,
startDisabled: true
} );
@@ -524,7 +527,7 @@ function onStripEnter( event ) {
* @inner
* @function
*/
-function onStripExit( event ) {
+function onStripLeave( event ) {
var element = event.eventSource.element;
if ( 'horizontal' === this.scroll ) {
diff --git a/src/viewer.js b/src/viewer.js
index b5b24318..7cb756a2 100644
--- a/src/viewer.js
+++ b/src/viewer.js
@@ -280,6 +280,7 @@ $.Viewer = function( options ) {
this.docOverflow = document.documentElement.style.overflow;
this.innerTracker = new $.MouseTracker({
+ userData: 'Viewer.innerTracker',
element: this.canvas,
startDisabled: !this.mouseNavEnabled,
clickTimeThreshold: this.clickTimeThreshold,
@@ -293,7 +294,7 @@ $.Viewer = function( options ) {
dragHandler: $.delegate( this, onCanvasDrag ),
dragEndHandler: $.delegate( this, onCanvasDragEnd ),
enterHandler: $.delegate( this, onCanvasEnter ),
- exitHandler: $.delegate( this, onCanvasExit ),
+ leaveHandler: $.delegate( this, onCanvasLeave ),
pressHandler: $.delegate( this, onCanvasPress ),
releaseHandler: $.delegate( this, onCanvasRelease ),
nonPrimaryPressHandler: $.delegate( this, onCanvasNonPrimaryPress ),
@@ -303,6 +304,7 @@ $.Viewer = function( options ) {
});
this.outerTracker = new $.MouseTracker({
+ userData: 'Viewer.outerTracker',
element: this.container,
startDisabled: !this.mouseNavEnabled,
clickTimeThreshold: this.clickTimeThreshold,
@@ -310,7 +312,7 @@ $.Viewer = function( options ) {
dblClickTimeThreshold: this.dblClickTimeThreshold,
dblClickDistThreshold: this.dblClickDistThreshold,
enterHandler: $.delegate( this, onContainerEnter ),
- exitHandler: $.delegate( this, onContainerExit )
+ leaveHandler: $.delegate( this, onContainerLeave )
});
if( this.toolbar ){
@@ -1099,7 +1101,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
THIS[ this.hash ].fullPage = false;
// mouse will likely be outside now
- $.delegate( this, onContainerExit )( { } );
+ $.delegate( this, onContainerLeave )( { } );
}
@@ -2925,7 +2927,7 @@ function onCanvasEnter( event ) {
});
}
-function onCanvasExit( event ) {
+function onCanvasLeave( event ) {
if (window.location !== window.parent.location){
$.MouseTracker.resetAllMouseTrackers();
@@ -3227,7 +3229,7 @@ function onContainerEnter( event ) {
});
}
-function onContainerExit( event ) {
+function onContainerLeave( event ) {
if ( event.pointers < 1 ) {
THIS[ this.hash ].mouseInside = false;
if ( !THIS[ this.hash ].animating ) {
@@ -3483,7 +3485,7 @@ function doSingleZoomOut() {
function lightUp() {
this.buttons.emulateEnter();
- this.buttons.emulateExit();
+ this.buttons.emulateLeave();
}
@@ -3503,7 +3505,7 @@ function onFullScreen() {
}
// correct for no mouseout event on change
if ( this.buttons ) {
- this.buttons.emulateExit();
+ this.buttons.emulateLeave();
}
this.fullPageButton.element.focus();
if ( this.viewport ) {
diff --git a/test/helpers/legacy.mouse.shim.js b/test/helpers/legacy.mouse.shim.js
index 3609ed85..e946c5f9 100644
--- a/test/helpers/legacy.mouse.shim.js
+++ b/test/helpers/legacy.mouse.shim.js
@@ -12,12 +12,12 @@
}
$.MouseTracker.havePointerEvents = false;
- if ( $.Browser.vendor === $.BROWSERS.IE && $.Browser.version < 9 ) {
- $.MouseTracker.subscribeEvents.push( "mouseenter", "mouseleave" );
- $.MouseTracker.haveMouseEnter = true;
- } else {
+ $.MouseTracker.subscribeEvents.push( "mouseenter", "mouseleave" );
+ if ( $.Browser.vendor !== $.BROWSERS.IE || $.Browser.version > 8 ) {
$.MouseTracker.subscribeEvents.push( "mouseover", "mouseout" );
- $.MouseTracker.haveMouseEnter = false;
+ $.MouseTracker.haveMouseOver = true;
+ } else {
+ $.MouseTracker.haveMouseOver = false;
}
$.MouseTracker.subscribeEvents.push( "mousedown", "mouseup", "mousemove" );
if ( 'ontouchstart' in window ) {
diff --git a/test/helpers/test.js b/test/helpers/test.js
index 8e7685d8..60931bba 100644
--- a/test/helpers/test.js
+++ b/test/helpers/test.js
@@ -37,7 +37,7 @@
};
$canvas
- .simulate( OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseenter' : 'mouseover', event )
+ .simulate( 'mouseenter', 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( OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseleave' : 'mouseout', event );
+ .simulate( 'mouseleave', event );
},
// ----------
diff --git a/test/modules/events.js b/test/modules/events.js
index 849e86f9..68e6232d 100644
--- a/test/modules/events.js
+++ b/test/modules/events.js
@@ -32,7 +32,7 @@
offset = $canvas.offset(),
tracker = viewer.innerTracker,
origEnterHandler,
- origExitHandler,
+ origLeaveHandler,
origPressHandler,
origReleaseHandler,
origNonPrimaryPressHandler,
@@ -43,7 +43,7 @@
origDragHandler,
origDragEndHandler,
enterCount,
- exitCount,
+ leaveCount,
pressCount,
releaseCount,
rightPressCount,
@@ -71,11 +71,11 @@
return true;
}
};
- origExitHandler = tracker.exitHandler;
- tracker.exitHandler = function ( event ) {
- exitCount++;
- if (origExitHandler) {
- return origExitHandler( event );
+ origLeaveHandler = tracker.leaveHandler;
+ tracker.leaveHandler = function ( event ) {
+ leaveCount++;
+ if (origLeaveHandler) {
+ return origLeaveHandler( event );
} else {
return true;
}
@@ -182,7 +182,7 @@
var unhookViewerHandlers = function () {
tracker.enterHandler = origEnterHandler;
- tracker.exitHandler = origExitHandler;
+ tracker.leaveHandler = origLeaveHandler;
tracker.pressHandler = origPressHandler;
tracker.releaseHandler = origReleaseHandler;
tracker.moveHandler = origMoveHandler;
@@ -195,21 +195,21 @@
var simulateEnter = function (x, y) {
simEvent.clientX = offset.left + x;
simEvent.clientY = offset.top + y;
- $canvas.simulate( OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseenter' : 'mouseover', simEvent );
+ $canvas.simulate( 'mouseenter', simEvent );
};
var simulateLeave = function (x, y) {
simEvent.clientX = offset.left + x;
simEvent.clientY = offset.top + y;
simEvent.relatedTarget = document.body;
- $canvas.simulate( OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseleave' : 'mouseout', simEvent );
+ $canvas.simulate( 'mouseleave', simEvent );
};
//var simulateLeaveFrame = function (x, y) {
// simEvent.clientX = offset.left + x;
// simEvent.clientY = offset.top + y;
// simEvent.relatedTarget = document.getElementsByTagName("html")[0];
- // $canvas.simulate( OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseleave' : 'mouseout', simEvent );
+ // $canvas.simulate( 'mouseleave', simEvent );
//};
var simulateDown = function (x, y) {
@@ -256,7 +256,7 @@
clientY: offset.top
};
enterCount = 0;
- exitCount = 0;
+ leaveCount = 0;
pressCount = 0;
releaseCount = 0;
rightPressCount = 0;
@@ -280,8 +280,8 @@
if ('enterCount' in expected) {
assert.equal( enterCount, expected.enterCount, expected.description + 'enterHandler event count matches expected (' + expected.enterCount + ')' );
}
- if ('exitCount' in expected) {
- assert.equal( exitCount, expected.exitCount, expected.description + 'exitHandler event count matches expected (' + expected.exitCount + ')' );
+ if ('leaveCount' in expected) {
+ assert.equal( leaveCount, expected.leaveCount, expected.description + 'leaveHandler event count matches expected (' + expected.leaveCount + ')' );
}
if ('pressCount' in expected) {
assert.equal( pressCount, expected.pressCount, expected.description + 'pressHandler event count matches expected (' + expected.pressCount + ')' );
@@ -355,7 +355,7 @@
assessGestureExpectations({
description: 'enter-move-release (release in tracked element, press in unknown element): ',
enterCount: 1,
- exitCount: 0,
+ leaveCount: 0,
pressCount: 0,
releaseCount: 1,
rightPressCount: 0,
@@ -375,16 +375,16 @@
});
simulateLeave(-1, -1); // flush tracked pointer
- // enter-move-exit (fly-over)
+ // enter-move-leave (fly-over)
resetForAssessment();
simulateEnter(0, 0);
simulateMove(1, 1, 10);
simulateMove(-1, -1, 10);
simulateLeave(-1, -1);
assessGestureExpectations({
- description: 'enter-move-exit (fly-over): ',
+ description: 'enter-move-leave (fly-over): ',
enterCount: 1,
- exitCount: 1,
+ leaveCount: 1,
pressCount: 0,
releaseCount: 0,
rightPressCount: 0,
@@ -403,15 +403,15 @@
//quickClick: false
});
- // move-exit (fly-over, no enter event)
+ // move-leave (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): ',
+ description: 'move-leave (fly-over, no enter event): ',
enterCount: 0,
- exitCount: 1,
+ leaveCount: 1,
pressCount: 0,
releaseCount: 0,
rightPressCount: 0,
@@ -430,7 +430,7 @@
//quickClick: false
});
- // enter-press-release-press-release-exit (primary/left double click)
+ // enter-press-release-press-release-leave (primary/left double click)
resetForAssessment();
simulateEnter(0, 0);
simulateDown(0, 0);
@@ -439,9 +439,9 @@
simulateUp(0, 0);
simulateLeave(-1, -1);
assessGestureExpectations({
- description: 'enter-press-release-press-release-exit (primary/left double click): ',
+ description: 'enter-press-release-press-release-leave (primary/left double click): ',
enterCount: 1,
- exitCount: 1,
+ leaveCount: 1,
pressCount: 2,
releaseCount: 2,
rightPressCount: 0,
@@ -460,16 +460,16 @@
//quickClick: true
});
- // enter-press-release-exit (primary/left click)
+ // enter-press-release-leave (primary/left click)
resetForAssessment();
simulateEnter(0, 0);
simulateDown(0, 0);
simulateUp(0, 0);
simulateLeave(-1, -1);
assessGestureExpectations({
- description: 'enter-press-release-exit (primary/left click): ',
+ description: 'enter-press-release-leave (primary/left click): ',
enterCount: 1,
- exitCount: 1,
+ leaveCount: 1,
pressCount: 1,
releaseCount: 1,
rightPressCount: 0,
@@ -488,16 +488,16 @@
quickClick: true
});
- // enter-nonprimarypress-nonprimaryrelease-exit (secondary/right click)
+ // enter-nonprimarypress-nonprimaryrelease-leave (secondary/right click)
resetForAssessment();
simulateEnter(0, 0);
simulateNonPrimaryDown(0, 0, 2);
simulateNonPrimaryUp(0, 0, 2);
simulateLeave(-1, -1);
assessGestureExpectations({
- description: 'enter-nonprimarypress-nonprimaryrelease-exit (secondary/right click): ',
+ description: 'enter-nonprimarypress-nonprimaryrelease-leave (secondary/right click): ',
enterCount: 1,
- exitCount: 1,
+ leaveCount: 1,
pressCount: 0,
releaseCount: 0,
rightPressCount: 1,
@@ -516,16 +516,16 @@
//quickClick: true
});
- // enter-nonprimarypress-nonprimaryrelease-exit (aux/middle click)
+ // enter-nonprimarypress-nonprimaryrelease-leave (aux/middle click)
resetForAssessment();
simulateEnter(0, 0);
simulateNonPrimaryDown(0, 0, 1);
simulateNonPrimaryUp(0, 0, 1);
simulateLeave(-1, -1);
assessGestureExpectations({
- description: 'enter-nonprimarypress-nonprimaryrelease-exit (aux/middle click): ',
+ description: 'enter-nonprimarypress-nonprimaryrelease-leave (aux/middle click): ',
enterCount: 1,
- exitCount: 1,
+ leaveCount: 1,
pressCount: 0,
releaseCount: 0,
rightPressCount: 0,
@@ -544,7 +544,7 @@
//quickClick: true
});
- // enter-nonprimarypress-move-nonprimaryrelease-move-exit (secondary/right button drag, release in tracked element)
+ // enter-nonprimarypress-move-nonprimaryrelease-move-leave (secondary/right button drag, release in tracked element)
resetForAssessment();
simulateEnter(0, 0);
simulateNonPrimaryDown(0, 0, 2);
@@ -553,9 +553,9 @@
simulateMove(-1, -1, 100);
simulateLeave(-1, -1);
assessGestureExpectations({
- description: 'enter-nonprimarypress-move-nonprimaryrelease-move-exit (secondary/right button drag, release in tracked element): ',
+ description: 'enter-nonprimarypress-move-nonprimaryrelease-move-leave (secondary/right button drag, release in tracked element): ',
enterCount: 1,
- exitCount: 1,
+ leaveCount: 1,
pressCount: 0,
releaseCount: 0,
rightPressCount: 1,
@@ -574,7 +574,7 @@
//quickClick: false
});
- // enter-press-move-release-move-exit (drag, release in tracked element)
+ // enter-press-move-release-move-leave (drag, release in tracked element)
resetForAssessment();
simulateEnter(0, 0);
simulateDown(0, 0);
@@ -583,9 +583,9 @@
simulateMove(-1, -1, 100);
simulateLeave(-1, -1);
assessGestureExpectations({
- description: 'enter-press-move-release-move-exit (drag, release in tracked element): ',
+ description: 'enter-press-move-release-move-leave (drag, release in tracked element): ',
enterCount: 1,
- exitCount: 1,
+ leaveCount: 1,
pressCount: 1,
releaseCount: 1,
rightPressCount: 0,
@@ -604,7 +604,7 @@
quickClick: false
});
- // enter-press-move-exit-move-release (drag, release outside tracked element)
+ // enter-press-move-leave-move-release (drag, release outside tracked element)
resetForAssessment();
simulateEnter(0, 0);
simulateDown(0, 0);
@@ -614,9 +614,9 @@
simulateMove(-1, -1, 5);
simulateUp(-5, -5);
assessGestureExpectations({
- description: 'enter-press-move-exit-move-release (drag, release outside tracked element): ',
+ description: 'enter-press-move-leave-move-release (drag, release outside tracked element): ',
enterCount: 1,
- exitCount: 1,
+ leaveCount: 1,
pressCount: 1,
releaseCount: 1,
rightPressCount: 0,
@@ -635,7 +635,7 @@
quickClick: false
});
- //// enter-press-move-exit-move-release-outside (drag, release outside iframe)
+ //// enter-press-move-leave-move-release-outside (drag, release outside iframe)
//resetForAssessment();
//simulateEnter(0, 0);
//simulateDown(0, 0);
@@ -644,9 +644,9 @@
//simulateLeaveFrame(-1, -1);
//// you don't actually receive the mouseup if you mouseup outside of the document
//assessGestureExpectations({
- // description: 'enter-press-move-exit-move-release-outside (drag, release outside iframe): ',
- // enterCount: 1,
- // exitCount: 1,
+ // description: 'enter-press-move-leave-move-release-outside (drag, release outside iframe): ',
+ // enterCount: 1,
+ // leaveCount: 1,
// pressCount: 1,
// releaseCount: 1,
// rightPressCount: 0,
@@ -953,7 +953,7 @@
dragEndHandler: onMouseTrackerDragEnd,
releaseHandler: onMouseTrackerRelease,
clickHandler: onMouseTrackerClick,
- exitHandler: onMouseTrackerExit
+ leaveHandler: onMouseTrackerLeave
} );
var event = {
@@ -1050,7 +1050,7 @@
checkOriginalEventReceived( event );
};
- var onMouseTrackerExit = function ( event ) {
+ var onMouseTrackerLeave = function ( event ) {
checkOriginalEventReceived( event );
mouseTracker.destroy();
diff --git a/test/modules/navigator.js b/test/modules/navigator.js
index e7f5f327..d1f98dea 100644
--- a/test/modules/navigator.js
+++ b/test/modules/navigator.js
@@ -216,7 +216,7 @@
clientY: offset.top + locationY
};
$canvas
- .simulate(OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseenter' : 'mouseover', event)
+ .simulate('mouseenter', event)
.simulate('mousedown', event)
.simulate('mouseup', event);
};