diff --git a/changelog.txt b/changelog.txt
index d7211b15..42227a91 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -47,6 +47,19 @@ OPENSEADRAGON CHANGELOG
* Fixed: DZI tilesource was broken on IE8/IE9 (#563)
* Exposed secondary pointer button (middle, right, etc.) events from MouseTracker and through viewer (#479)
* MouseTracker - Improved IE 8 compatibility (#562)
+* MouseTracker - Improved IE 9+ compatibility (#564)
+* MouseTracker - Simulated touchenter/touchleave events now bubble to parent element MouseTrackers (#566)
+* MouseTracker - Improved multitouch support in enter/exit event handlers (#566)
+* MouseTracker - orphaned tracked touch pointers removed (fix for #539)
+* MouseTracker - removed touchenter/touchleave event support since the events don't exist on any known platform and have been removed from the W3C specification (#566)
+* Removed Viewer onContainerPress/onContainerRelease handlers (and the associated 'container-release' event ) that were never fired due to the canvas (child) element capturing the DOM events (#566)
+* Added 'canvas-enter', 'canvas-exit', and 'canvas-press' events to Viewer (#566)
+* ButtonGroup - removed obsolete MouseTracker event handlers (#566)
+* MouseTracker - added keydown and keyup handlers (#568)
+* Modifier keys ignored in keyboard navigation handlers (#503)
+* Requesting keyboard focus when viewer is clicked (#537)
+* Arrow key navigation fixed across platforms (#565)
+* Removed textarea element from viewer DOM. Viewer.canvas now handles keyboard navigation (#569)
1.2.0:
diff --git a/src/buttongroup.js b/src/buttongroup.js
index 2837805a..7505af0a 100644
--- a/src/buttongroup.js
+++ b/src/buttongroup.js
@@ -105,22 +105,6 @@ $.ButtonGroup = function( options ) {
}
}
},
- pressHandler: function ( event ) {
- if ( event.pointerType === 'touch' && !$.MouseTracker.haveTouchEnter ) {
- var i;
- for ( i = 0; i < _this.buttons.length; i++ ) {
- _this.buttons[ i ].notifyGroupEnter();
- }
- }
- },
- releaseHandler: function ( event ) {
- var i;
- if ( !event.insideElementReleased || ( event.pointerType === 'touch' && !$.MouseTracker.haveTouchEnter ) ) {
- for ( i = 0; i < _this.buttons.length; i++ ) {
- _this.buttons[ i ].notifyGroupExit();
- }
- }
- }
}).setTracking( true );
};
diff --git a/src/mousetracker.js b/src/mousetracker.js
index 09b3c751..9e8f25ef 100644
--- a/src/mousetracker.js
+++ b/src/mousetracker.js
@@ -34,7 +34,10 @@
(function ( $ ) {
- // dictionary from hash to private properties
+ // All MouseTracker instances
+ var MOUSETRACKERS = [];
+
+ // dictionary from hash to private properties
var THIS = {};
@@ -92,6 +95,10 @@
* An optional handler for after a drag gesture.
* @param {OpenSeadragon.EventHandler} [options.pinchHandler=null]
* An optional handler for the pinch gesture.
+ * @param {OpenSeadragon.EventHandler} [options.keyDownHandler=null]
+ * An optional handler for keydown.
+ * @param {OpenSeadragon.EventHandler} [options.keyUpHandler=null]
+ * An optional handler for keyup.
* @param {OpenSeadragon.EventHandler} [options.keyHandler=null]
* An optional handler for keypress.
* @param {OpenSeadragon.EventHandler} [options.focusHandler=null]
@@ -103,6 +110,8 @@
*/
$.MouseTracker = function ( options ) {
+ MOUSETRACKERS.push( this );
+
var args = arguments;
if ( !$.isPlainObject( options ) ) {
@@ -165,6 +174,8 @@
this.dragEndHandler = options.dragEndHandler || null;
this.pinchHandler = options.pinchHandler || null;
this.stopHandler = options.stopHandler || null;
+ this.keyDownHandler = options.keyDownHandler || null;
+ this.keyUpHandler = options.keyUpHandler || null;
this.keyHandler = options.keyHandler || null;
this.focusHandler = options.focusHandler || null;
this.blurHandler = options.blurHandler || null;
@@ -180,6 +191,8 @@
THIS[ this.hash ] = {
click: function ( event ) { onClick( _this, event ); },
dblclick: function ( event ) { onDblClick( _this, event ); },
+ keydown: function ( event ) { onKeyDown( _this, event ); },
+ keyup: function ( event ) { onKeyUp( _this, event ); },
keypress: function ( event ) { onKeyPress( _this, event ); },
focus: function ( event ) { onFocus( _this, event ); },
blur: function ( event ) { onBlur( _this, event ); },
@@ -199,8 +212,6 @@
mousemove: function ( event ) { onMouseMove( _this, event ); },
mousemovecaptured: function ( event ) { onMouseMoveCaptured( _this, event ); },
- touchenter: function ( event ) { onTouchEnter( _this, event ); },
- touchleave: function ( event ) { onTouchLeave( _this, event ); },
touchstart: function ( event ) { onTouchStart( _this, event ); },
touchend: function ( event ) { onTouchEnd( _this, event ); },
touchendcaptured: function ( event ) { onTouchEndCaptured( _this, event ); },
@@ -215,7 +226,6 @@
MSPointerOver: function ( event ) { onPointerOver( _this, event ); },
pointerout: function ( event ) { onPointerOut( _this, event ); },
MSPointerOut: function ( event ) { onPointerOut( _this, event ); },
-
pointerdown: function ( event ) { onPointerDown( _this, event ); },
MSPointerDown: function ( event ) { onPointerDown( _this, event ); },
pointerup: function ( event ) { onPointerUp( _this, event ); },
@@ -256,9 +266,18 @@
* @function
*/
destroy: function () {
+ var i;
+
stopTracking( this );
this.element = null;
+ for ( i = 0; i < MOUSETRACKERS.length; i++ ) {
+ if ( MOUSETRACKERS[ i ] === this ) {
+ MOUSETRACKERS.splice( i, 1 );
+ break;
+ }
+ }
+
THIS[ this.hash ] = null;
delete THIS[ this.hash ];
},
@@ -313,6 +332,24 @@
return list;
},
+ /**
+ * Returns the total number of pointers currently active on the tracked element.
+ * @function
+ * @returns {Number}
+ */
+ getActivePointerCount: function () {
+ var delegate = THIS[ this.hash ],
+ i,
+ len = delegate.activePointersLists.length,
+ count = 0;
+
+ for ( i = 0; i < len; i++ ) {
+ count += delegate.activePointersLists[ i ].getLength();
+ }
+
+ return count;
+ },
+
/**
* Implement or assign implementation to these handlers during or after
* calling the constructor.
@@ -327,6 +364,8 @@
* @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.
@@ -357,6 +396,8 @@
* @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.
@@ -710,8 +751,66 @@
* A reference to the tracker instance.
* @param {Number} event.keyCode
* The key code that was pressed.
+ * @param {Boolean} event.ctrl
+ * True if the ctrl key was pressed during this event.
* @param {Boolean} event.shift
* True if the shift key was pressed during this event.
+ * @param {Boolean} event.alt
+ * True if the alt key was pressed during this event.
+ * @param {Boolean} event.meta
+ * True if the meta key was pressed during this event.
+ * @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.
+ */
+ keyDownHandler: 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 {Number} event.keyCode
+ * The key code that was pressed.
+ * @param {Boolean} event.ctrl
+ * True if the ctrl key was pressed during this event.
+ * @param {Boolean} event.shift
+ * True if the shift key was pressed during this event.
+ * @param {Boolean} event.alt
+ * True if the alt key was pressed during this event.
+ * @param {Boolean} event.meta
+ * True if the meta key was pressed during this event.
+ * @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.
+ */
+ keyUpHandler: 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 {Number} event.keyCode
+ * The key code that was pressed.
+ * @param {Boolean} event.ctrl
+ * True if the ctrl key was pressed during this event.
+ * @param {Boolean} event.shift
+ * True if the shift key was pressed during this event.
+ * @param {Boolean} event.alt
+ * True if the alt key was pressed during this event.
+ * @param {Boolean} event.meta
+ * True if the meta key was pressed during this event.
* @param {Object} event.originalEvent
* The original event object.
* @param {Boolean} event.preventDefaultAction
@@ -871,7 +970,7 @@
/**
* Detect browser pointer device event model(s) and build appropriate list of events to subscribe to.
*/
- $.MouseTracker.subscribeEvents = [ "click", "dblclick", "keypress", "focus", "blur", $.MouseTracker.wheelEventName ];
+ $.MouseTracker.subscribeEvents = [ "click", "dblclick", "keydown", "keyup", "keypress", "focus", "blur", $.MouseTracker.wheelEventName ];
if( $.MouseTracker.wheelEventName == "DOMMouseScroll" ) {
// Older Firefox
@@ -888,7 +987,6 @@
} else {
$.MouseTracker.maxTouchPoints = 0;
}
- $.MouseTracker.haveTouchEnter = false;
$.MouseTracker.haveMouseEnter = false;
} else if ( window.MSPointerEvent ) {
// IE10
@@ -900,7 +998,6 @@
} else {
$.MouseTracker.maxTouchPoints = 0;
}
- $.MouseTracker.haveTouchEnter = false;
$.MouseTracker.haveMouseEnter = false;
} else {
// Legacy W3C mouse events
@@ -914,19 +1011,14 @@
}
$.MouseTracker.subscribeEvents.push( "mousedown", "mouseup", "mousemove" );
if ( 'ontouchstart' in window ) {
- // iOS, Android, and other W3c Touch Event implementations (see http://www.w3.org/TR/2011/WD-touch-events-20110505)
+ // iOS, Android, and other W3c Touch Event implementations
+ // (see http://www.w3.org/TR/touch-events/)
+ // (see https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html)
+ // (see https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html)
$.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)
+ // iOS (see https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html)
// Subscribe to these to prevent default gesture handling
$.MouseTracker.subscribeEvents.push( "gesturestart", "gesturechange" );
}
@@ -1414,12 +1506,72 @@
}
+ /**
+ * @private
+ * @inner
+ */
+ function onKeyDown( tracker, event ) {
+ //$.console.log( "keydown %s %s %s %s %s", event.keyCode, event.charCode, event.ctrlKey, event.shiftKey, event.altKey );
+ var propagate;
+ if ( tracker.keyDownHandler ) {
+ event = $.getEvent( event );
+ propagate = tracker.keyDownHandler(
+ {
+ eventSource: tracker,
+ position: getMouseRelative( event, tracker.element ),
+ keyCode: event.keyCode ? event.keyCode : event.charCode,
+ ctrl: event.ctrlKey,
+ shift: event.shiftKey,
+ alt: event.altKey,
+ meta: event.metaKey,
+ originalEvent: event,
+ preventDefaultAction: false,
+ userData: tracker.userData
+ }
+ );
+ if ( !propagate ) {
+ $.cancelEvent( event );
+ }
+ }
+ }
+
+
+ /**
+ * @private
+ * @inner
+ */
+ function onKeyUp( tracker, event ) {
+ //$.console.log( "keyup %s %s %s %s %s", event.keyCode, event.charCode, event.ctrlKey, event.shiftKey, event.altKey );
+ var propagate;
+ if ( tracker.keyUpHandler ) {
+ event = $.getEvent( event );
+ propagate = tracker.keyUpHandler(
+ {
+ eventSource: tracker,
+ position: getMouseRelative( event, tracker.element ),
+ keyCode: event.keyCode ? event.keyCode : event.charCode,
+ ctrl: event.ctrlKey,
+ shift: event.shiftKey,
+ alt: event.altKey,
+ meta: event.metaKey,
+ originalEvent: event,
+ preventDefaultAction: false,
+ userData: tracker.userData
+ }
+ );
+ if ( !propagate ) {
+ $.cancelEvent( event );
+ }
+ }
+ }
+
+
/**
* @private
* @inner
*/
function onKeyPress( tracker, event ) {
- //console.log( "keypress %s %s %s %s %s", event.keyCode, event.charCode, event.ctrlKey, event.shiftKey, event.altKey );
+ //$.console.log( "keypress %s %s %s %s %s", event.keyCode, event.charCode, event.ctrlKey, event.shiftKey, event.altKey );
var propagate;
if ( tracker.keyHandler ) {
event = $.getEvent( event );
@@ -1428,7 +1580,10 @@
eventSource: tracker,
position: getMouseRelative( event, tracker.element ),
keyCode: event.keyCode ? event.keyCode : event.charCode,
+ ctrl: event.ctrlKey,
shift: event.shiftKey,
+ alt: event.altKey,
+ meta: event.metaKey,
originalEvent: event,
preventDefaultAction: false,
userData: tracker.userData
@@ -1609,7 +1764,7 @@
function onMouseOver( tracker, event ) {
event = $.getEvent( event );
- if ( this === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
+ if ( event.currentTarget === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
return;
}
@@ -1654,7 +1809,7 @@
function onMouseOut( tracker, event ) {
event = $.getEvent( event );
- if ( this === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
+ if ( event.currentTarget === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
return;
}
@@ -1823,45 +1978,24 @@
* @private
* @inner
*/
- function onTouchEnter( tracker, event ) {
+ function abortTouchContacts( tracker, event, pointsList ) {
var i,
- touchCount = event.changedTouches.length,
- gPoints = [];
+ gPointCount = pointsList.getLength(),
+ abortGPoints = [];
- for ( i = 0; i < touchCount; i++ ) {
- gPoints.push( {
- id: event.changedTouches[ i ].identifier,
- type: 'touch',
- // isPrimary not set - let the updatePointers functions determine it
- currentPos: getMouseAbsolute( event.changedTouches[ i ] ),
- currentTime: $.now()
- } );
+ for ( i = 0; i < gPointCount; i++ ) {
+ abortGPoints.push( pointsList.getByIndex( i ) );
}
- updatePointersEnter( tracker, event, gPoints );
- }
-
-
- /**
- * @private
- * @inner
- */
- function onTouchLeave( tracker, event ) {
- var i,
- touchCount = event.changedTouches.length,
- gPoints = [];
-
- for ( i = 0; i < touchCount; i++ ) {
- gPoints.push( {
- id: event.changedTouches[ i ].identifier,
- type: 'touch',
- // isPrimary not set - let the updatePointers functions determine it
- currentPos: getMouseAbsolute( event.changedTouches[ i ] ),
- currentTime: $.now()
- } );
+ if ( abortGPoints.length > 0 ) {
+ // simulate touchend
+ updatePointersUp( tracker, event, abortGPoints, 0 ); // 0 means primary button press/release or touch contact
+ // release pointer capture
+ pointsList.captureCount = 1;
+ releasePointer( tracker, 'touch' );
+ // simulate touchleave
+ updatePointersExit( tracker, event, abortGPoints );
}
-
- updatePointersExit( tracker, event, gPoints );
}
@@ -1872,11 +2006,19 @@
function onTouchStart( tracker, event ) {
var time,
i,
+ j,
touchCount = event.changedTouches.length,
- gPoints = [];
+ gPoints = [],
+ parentGPoints,
+ pointsList = tracker.getActivePointersListByType( 'touch' );
time = $.now();
+ if ( pointsList.getLength() > event.touches.length - touchCount ) {
+ $.console.warn('Tracked touch contact count doesn\'t match event.touches.length. Removing all tracked touch pointers.');
+ abortTouchContacts( tracker, event, pointsList );
+ }
+
for ( i = 0; i < touchCount; i++ ) {
gPoints.push( {
id: event.changedTouches[ i ].identifier,
@@ -1887,9 +2029,24 @@
} );
}
- // simulate touchenter if not natively available
- if ( !$.MouseTracker.haveTouchEnter ) {
- updatePointersEnter( tracker, event, gPoints );
+ // simulate touchenter on our tracked element
+ updatePointersEnter( tracker, event, gPoints );
+
+ // simulate touchenter on our tracked element's tracked ancestor elements
+ for ( i = 0; i < MOUSETRACKERS.length; i++ ) {
+ if ( MOUSETRACKERS[ i ] !== tracker && MOUSETRACKERS[ i ].isTracking() && isParentChild( MOUSETRACKERS[ i ].element, tracker.element ) ) {
+ parentGPoints = [];
+ for ( j = 0; j < touchCount; j++ ) {
+ parentGPoints.push( {
+ id: event.changedTouches[ j ].identifier,
+ type: 'touch',
+ // isPrimary not set - let the updatePointers functions determine it
+ currentPos: getMouseAbsolute( event.changedTouches[ j ] ),
+ currentTime: time
+ } );
+ }
+ updatePointersEnter( MOUSETRACKERS[ i ], event, parentGPoints );
+ }
}
if ( updatePointersDown( tracker, event, gPoints, 0 ) ) { // 0 means primary button press/release or touch contact
@@ -1930,8 +2087,10 @@
function handleTouchEnd( tracker, event ) {
var time,
i,
+ j,
touchCount = event.changedTouches.length,
- gPoints = [];
+ gPoints = [],
+ parentGPoints;
time = $.now();
@@ -1949,9 +2108,24 @@
releasePointer( tracker, 'touch' );
}
- // simulate touchleave if not natively available
- if ( !$.MouseTracker.haveTouchEnter && touchCount > 0 ) {
- updatePointersExit( tracker, event, gPoints );
+ // simulate touchleave on our tracked element
+ updatePointersExit( tracker, event, gPoints );
+
+ // simulate touchleave on our tracked element's tracked ancestor elements
+ for ( i = 0; i < MOUSETRACKERS.length; i++ ) {
+ if ( MOUSETRACKERS[ i ] !== tracker && MOUSETRACKERS[ i ].isTracking() && isParentChild( MOUSETRACKERS[ i ].element, tracker.element ) ) {
+ parentGPoints = [];
+ for ( j = 0; j < touchCount; j++ ) {
+ parentGPoints.push( {
+ id: event.changedTouches[ j ].identifier,
+ type: 'touch',
+ // isPrimary not set - let the updatePointers functions determine it
+ currentPos: getMouseAbsolute( event.changedTouches[ j ] ),
+ currentTime: time
+ } );
+ }
+ updatePointersExit( MOUSETRACKERS[ i ], event, parentGPoints );
+ }
}
$.cancelEvent( event );
@@ -2054,7 +2228,7 @@
function onPointerOver( tracker, event ) {
var gPoint;
- if ( this === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
+ if ( event.currentTarget === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
return;
}
@@ -2077,7 +2251,7 @@
function onPointerOut( tracker, event ) {
var gPoint;
- if ( this === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
+ if ( event.currentTarget === event.relatedTarget || isParentChild( event.currentTarget, event.relatedTarget ) ) {
return;
}
@@ -2092,6 +2266,7 @@
updatePointersExit( tracker, event, [ gPoint ] );
}
+
/**
* @private
* @inner
@@ -2344,6 +2519,7 @@
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',
@@ -2407,6 +2583,7 @@
pointerType: curGPoint.type,
position: getPointRelativeToAbsolute( curGPoint.currentPos, tracker.element ),
buttons: pointsList.buttons,
+ pointers: tracker.getActivePointerCount(),
insideElementPressed: updateGPoint ? updateGPoint.insideElementPressed : false,
buttonDownAny: pointsList.buttons !== 0,
isTouchEvent: curGPoint.type === 'touch',
diff --git a/src/referencestrip.js b/src/referencestrip.js
index 0c0fdf61..668e11eb 100644
--- a/src/referencestrip.js
+++ b/src/referencestrip.js
@@ -125,6 +125,7 @@ $.ReferenceStrip = function ( options ) {
scrollHandler: $.delegate( this, onStripScroll ),
enterHandler: $.delegate( this, onStripEnter ),
exitHandler: $.delegate( this, onStripExit ),
+ keyDownHandler: $.delegate( this, onKeyDown ),
keyHandler: $.delegate( this, onKeyPress )
} ).setTracking( true );
@@ -518,6 +519,37 @@ function onStripExit( event ) {
}
+/**
+ * @private
+ * @inner
+ * @function
+ */
+function onKeyDown( event ) {
+ //console.log( event.keyCode );
+
+ if ( !event.preventDefaultAction && !event.ctrl && !event.alt && !event.meta ) {
+ switch ( event.keyCode ) {
+ case 38: //up arrow
+ onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } );
+ return false;
+ case 40: //down arrow
+ onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } );
+ return false;
+ case 37: //left arrow
+ onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } );
+ return false;
+ case 39: //right arrow
+ onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } );
+ return false;
+ default:
+ //console.log( 'navigator keycode %s', event.keyCode );
+ return true;
+ }
+ } else {
+ return true;
+ }
+}
+
/**
* @private
@@ -527,35 +559,35 @@ function onStripExit( event ) {
function onKeyPress( event ) {
//console.log( event.keyCode );
- switch ( event.keyCode ) {
- case 61: //=|+
- onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } );
- return false;
- case 45: //-|_
- onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } );
- return false;
- case 48: //0|)
- case 119: //w
- case 87: //W
- case 38: //up arrow
- onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } );
- return false;
- case 115: //s
- case 83: //S
- case 40: //down arrow
- onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } );
- return false;
- case 97: //a
- case 37: //left arrow
- onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } );
- return false;
- case 100: //d
- case 39: //right arrow
- onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } );
- return false;
- default:
- //console.log( 'navigator keycode %s', event.keyCode );
- return true;
+ if ( !event.preventDefaultAction && !event.ctrl && !event.alt && !event.meta ) {
+ switch ( event.keyCode ) {
+ case 61: //=|+
+ onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } );
+ return false;
+ case 45: //-|_
+ onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } );
+ return false;
+ case 48: //0|)
+ case 119: //w
+ case 87: //W
+ onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } );
+ return false;
+ case 115: //s
+ case 83: //S
+ onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } );
+ return false;
+ case 97: //a
+ onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } );
+ return false;
+ case 100: //d
+ onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } );
+ return false;
+ default:
+ //console.log( 'navigator keycode %s', event.keyCode );
+ return true;
+ }
+ } else {
+ return true;
}
}
diff --git a/src/viewer.js b/src/viewer.js
index 4fee330a..b2b0b5a0 100644
--- a/src/viewer.js
+++ b/src/viewer.js
@@ -106,14 +106,6 @@ $.Viewer = function( options ) {
* @memberof OpenSeadragon.Viewer#
*/
container: null,
- /**
- * A <textarea> element, the element where keyboard events are handled.
- * Child element of {@link OpenSeadragon.Viewer#container},
- * positioned below {@link OpenSeadragon.Viewer#canvas}.
- * @member {Element} keyboardCommandArea
- * @memberof OpenSeadragon.Viewer#
- */
- keyboardCommandArea: null,
/**
* A <div> element, the element where user-input events are handled for panning and zooming.
* Child element of {@link OpenSeadragon.Viewer#container},
@@ -229,7 +221,6 @@ $.Viewer = function( options ) {
this.element = this.element || document.getElementById( this.id );
this.canvas = $.makeNeutralElement( "div" );
- this.keyboardCommandArea = $.makeNeutralElement( "textarea" );
this.canvas.className = "openseadragon-canvas";
(function( style ){
@@ -241,6 +232,7 @@ $.Viewer = function( options ) {
style.left = "0px";
}(this.canvas.style));
$.setElementTouchActionNone( this.canvas );
+ this.canvas.tabIndex = 0;
//the container is created through applying the ControlDock constructor above
this.container.className = "openseadragon-container";
@@ -254,19 +246,7 @@ $.Viewer = function( options ) {
style.textAlign = "left"; // needed to protect against
}( this.container.style ));
- this.keyboardCommandArea.className = "keyboard-command-area";
- (function( style ){
- style.width = "100%";
- style.height = "100%";
- style.overflow = "hidden";
- style.position = "absolute";
- style.top = "0px";
- style.left = "0px";
- style.resize = "none";
- }( this.keyboardCommandArea.style ));
-
this.container.insertBefore( this.canvas, this.container.firstChild );
- this.container.insertBefore( this.keyboardCommandArea, this.container.firstChild );
this.element.appendChild( this.container );
//Used for toggling between fullscreen and default container size
@@ -277,80 +257,22 @@ $.Viewer = function( options ) {
this.bodyOverflow = document.body.style.overflow;
this.docOverflow = document.documentElement.style.overflow;
- this.keyboardCommandArea.innerTracker = new $.MouseTracker({
- _this : this,
- element: this.keyboardCommandArea,
- focusHandler: function( event ){
- if ( !event.preventDefaultAction ) {
- var point = $.getElementPosition( this.element );
- window.scrollTo( 0, point.y );
- }
- },
-
- keyHandler: function( event ){
- if ( !event.preventDefaultAction ) {
- switch( event.keyCode ){
- case 61://=|+
- _this.viewport.zoomBy(1.1);
- _this.viewport.applyConstraints();
- return false;
- case 45://-|_
- _this.viewport.zoomBy(0.9);
- _this.viewport.applyConstraints();
- return false;
- case 48://0|)
- _this.viewport.goHome();
- _this.viewport.applyConstraints();
- return false;
- case 119://w
- case 87://W
- case 38://up arrow
- if ( event.shift ) {
- _this.viewport.zoomBy(1.1);
- } else {
- _this.viewport.panBy(new $.Point(0, -0.05));
- }
- _this.viewport.applyConstraints();
- return false;
- case 115://s
- case 83://S
- case 40://down arrow
- if ( event.shift ) {
- _this.viewport.zoomBy(0.9);
- } else {
- _this.viewport.panBy(new $.Point(0, 0.05));
- }
- _this.viewport.applyConstraints();
- return false;
- case 97://a
- case 37://left arrow
- _this.viewport.panBy(new $.Point(-0.05, 0));
- _this.viewport.applyConstraints();
- return false;
- case 100://d
- case 39://right arrow
- _this.viewport.panBy(new $.Point(0.05, 0));
- _this.viewport.applyConstraints();
- return false;
- default:
- //console.log( 'navigator keycode %s', event.keyCode );
- return true;
- }
- }
- }
- }).setTracking( true ); // default state
-
-
this.innerTracker = new $.MouseTracker({
element: this.canvas,
clickTimeThreshold: this.clickTimeThreshold,
clickDistThreshold: this.clickDistThreshold,
dblClickTimeThreshold: this.dblClickTimeThreshold,
dblClickDistThreshold: this.dblClickDistThreshold,
+ focusHandler: $.delegate( this, onCanvasFocus ),
+ keyDownHandler: $.delegate( this, onCanvasKeyDown ),
+ keyHandler: $.delegate( this, onCanvasKeyPress ),
clickHandler: $.delegate( this, onCanvasClick ),
dblClickHandler: $.delegate( this, onCanvasDblClick ),
dragHandler: $.delegate( this, onCanvasDrag ),
dragEndHandler: $.delegate( this, onCanvasDragEnd ),
+ enterHandler: $.delegate( this, onCanvasEnter ),
+ exitHandler: $.delegate( this, onCanvasExit ),
+ pressHandler: $.delegate( this, onCanvasPress ),
releaseHandler: $.delegate( this, onCanvasRelease ),
nonPrimaryPressHandler: $.delegate( this, onCanvasNonPrimaryPress ),
nonPrimaryReleaseHandler: $.delegate( this, onCanvasNonPrimaryRelease ),
@@ -365,9 +287,7 @@ $.Viewer = function( options ) {
dblClickTimeThreshold: this.dblClickTimeThreshold,
dblClickDistThreshold: this.dblClickDistThreshold,
enterHandler: $.delegate( this, onContainerEnter ),
- exitHandler: $.delegate( this, onContainerExit ),
- pressHandler: $.delegate( this, onContainerPress ),
- releaseHandler: $.delegate( this, onContainerRelease )
+ exitHandler: $.delegate( this, onContainerExit )
}).setTracking( this.mouseNavEnabled ? true : false ); // always tracking
if( this.toolbar ){
@@ -814,9 +734,6 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
}
// destroy the mouse trackers
- if (this.keyboardCommandArea){
- this.keyboardCommandArea.innerTracker.destroy();
- }
if (this.innerTracker){
this.innerTracker.destroy();
}
@@ -829,7 +746,6 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
// clear all our references to dom objects
this.canvas = null;
- this.keyboardCommandArea = null;
this.container = null;
// clear our reference to the main element - they will need to pass it in again, creating a new viewer
@@ -2269,9 +2185,109 @@ function onBlur(){
}
+function onCanvasFocus( event ) {
+ if ( !event.preventDefaultAction ) {
+ var point = $.getElementPosition( this.element );
+ window.scrollTo( 0, point.y );
+ }
+}
+
+function onCanvasKeyDown( event ) {
+ if ( !event.preventDefaultAction && !event.ctrl && !event.alt && !event.meta ) {
+ switch( event.keyCode ){
+ case 38://up arrow
+ if ( event.shift ) {
+ this.viewport.zoomBy(1.1);
+ } else {
+ this.viewport.panBy(new $.Point(0, -0.05));
+ }
+ this.viewport.applyConstraints();
+ return false;
+ case 40://down arrow
+ if ( event.shift ) {
+ this.viewport.zoomBy(0.9);
+ } else {
+ this.viewport.panBy(new $.Point(0, 0.05));
+ }
+ this.viewport.applyConstraints();
+ return false;
+ case 37://left arrow
+ this.viewport.panBy(new $.Point(-0.05, 0));
+ this.viewport.applyConstraints();
+ return false;
+ case 39://right arrow
+ this.viewport.panBy(new $.Point(0.05, 0));
+ this.viewport.applyConstraints();
+ return false;
+ default:
+ //console.log( 'navigator keycode %s', event.keyCode );
+ return true;
+ }
+ } else {
+ return true;
+ }
+}
+
+function onCanvasKeyPress( event ) {
+ if ( !event.preventDefaultAction && !event.ctrl && !event.alt && !event.meta ) {
+ switch( event.keyCode ){
+ case 61://=|+
+ this.viewport.zoomBy(1.1);
+ this.viewport.applyConstraints();
+ return false;
+ case 45://-|_
+ this.viewport.zoomBy(0.9);
+ this.viewport.applyConstraints();
+ return false;
+ case 48://0|)
+ this.viewport.goHome();
+ this.viewport.applyConstraints();
+ return false;
+ case 119://w
+ case 87://W
+ if ( event.shift ) {
+ this.viewport.zoomBy(1.1);
+ } else {
+ this.viewport.panBy(new $.Point(0, -0.05));
+ }
+ this.viewport.applyConstraints();
+ return false;
+ case 115://s
+ case 83://S
+ if ( event.shift ) {
+ this.viewport.zoomBy(0.9);
+ } else {
+ this.viewport.panBy(new $.Point(0, 0.05));
+ }
+ this.viewport.applyConstraints();
+ return false;
+ case 97://a
+ this.viewport.panBy(new $.Point(-0.05, 0));
+ this.viewport.applyConstraints();
+ return false;
+ case 100://d
+ this.viewport.panBy(new $.Point(0.05, 0));
+ this.viewport.applyConstraints();
+ return false;
+ default:
+ //console.log( 'navigator keycode %s', event.keyCode );
+ return true;
+ }
+ } else {
+ return true;
+ }
+}
+
function onCanvasClick( event ) {
var gestureSettings;
+ var haveKeyboardFocus = document.activeElement == this.canvas;
+
+ // If we don't have keyboard focus, request it.
+ if ( !haveKeyboardFocus ) {
+ this.canvas.focus();
+ }
+
if ( !event.preventDefaultAction && this.viewport && event.quick ) {
gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
if ( gestureSettings.clickToZoom ) {
@@ -2427,6 +2443,92 @@ function onCanvasDragEnd( event ) {
});
}
+function onCanvasEnter( event ) {
+ /**
+ * Raised when a pointer enters the {@link OpenSeadragon.Viewer#canvas} element.
+ *
+ * @event canvas-enter
+ * @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 {String} pointerType - "mouse", "touch", "pen", etc.
+ * @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 {Number} pointers - Number of pointers (all types) active in the tracked element.
+ * @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. Deprecated. Use buttons instead.
+ * @property {Object} originalEvent - The original DOM event.
+ * @property {?Object} userData - Arbitrary subscriber-defined object.
+ */
+ this.raiseEvent( 'canvas-enter', {
+ tracker: event.eventSource,
+ pointerType: event.pointerType,
+ position: event.position,
+ buttons: event.buttons,
+ pointers: event.pointers,
+ insideElementPressed: event.insideElementPressed,
+ buttonDownAny: event.buttonDownAny,
+ originalEvent: event.originalEvent
+ });
+}
+
+function onCanvasExit( event ) {
+ /**
+ * Raised when a pointer leaves the {@link OpenSeadragon.Viewer#canvas} element.
+ *
+ * @event canvas-exit
+ * @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 {String} pointerType - "mouse", "touch", "pen", etc.
+ * @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 {Number} pointers - Number of pointers (all types) active in the tracked element.
+ * @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. Deprecated. Use buttons instead.
+ * @property {Object} originalEvent - The original DOM event.
+ * @property {?Object} userData - Arbitrary subscriber-defined object.
+ */
+ this.raiseEvent( 'canvas-exit', {
+ tracker: event.eventSource,
+ pointerType: event.pointerType,
+ position: event.position,
+ buttons: event.buttons,
+ pointers: event.pointers,
+ insideElementPressed: event.insideElementPressed,
+ buttonDownAny: event.buttonDownAny,
+ originalEvent: event.originalEvent
+ });
+}
+
+function onCanvasPress( event ) {
+ /**
+ * Raised when the primary mouse button is pressed or touch starts on the {@link OpenSeadragon.Viewer#canvas} element.
+ *
+ * @event canvas-press
+ * @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 {String} pointerType - "mouse", "touch", "pen", etc.
+ * @property {OpenSeadragon.Point} position - The position of the event relative to the tracked element.
+ * @property {Boolean} insideElementPressed - True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false.
+ * @property {Boolean} insideElementReleased - True if the cursor still inside the tracked element when the button was released.
+ * @property {Object} originalEvent - The original DOM event.
+ * @property {?Object} userData - Arbitrary subscriber-defined object.
+ */
+ this.raiseEvent( 'canvas-press', {
+ tracker: event.eventSource,
+ pointerType: event.pointerType,
+ position: event.position,
+ insideElementPressed: event.insideElementPressed,
+ insideElementReleased: event.insideElementReleased,
+ originalEvent: event.originalEvent
+ });
+}
+
function onCanvasRelease( event ) {
/**
* Raised when the primary mouse button is released or touch ends on the {@link OpenSeadragon.Viewer#canvas} element.
@@ -2436,6 +2538,7 @@ function onCanvasRelease( event ) {
* @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 {String} pointerType - "mouse", "touch", "pen", etc.
* @property {OpenSeadragon.Point} position - The position of the event relative to the tracked element.
* @property {Boolean} insideElementPressed - True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false.
* @property {Boolean} insideElementReleased - True if the cursor still inside the tracked element when the button was released.
@@ -2444,6 +2547,7 @@ function onCanvasRelease( event ) {
*/
this.raiseEvent( 'canvas-release', {
tracker: event.eventSource,
+ pointerType: event.pointerType,
position: event.position,
insideElementPressed: event.insideElementPressed,
insideElementReleased: event.insideElementReleased,
@@ -2609,8 +2713,38 @@ function onCanvasScroll( event ) {
return false;
}
+function onContainerEnter( event ) {
+ THIS[ this.hash ].mouseInside = true;
+ abortControlsAutoHide( this );
+ /**
+ * Raised when the cursor enters the {@link OpenSeadragon.Viewer#container} element.
+ *
+ * @event container-enter
+ * @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} 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 {Number} pointers - Number of pointers (all types) active in the tracked element.
+ * @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. Deprecated. Use buttons instead.
+ * @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,
+ pointers: event.pointers,
+ insideElementPressed: event.insideElementPressed,
+ buttonDownAny: event.buttonDownAny,
+ originalEvent: event.originalEvent
+ });
+}
+
function onContainerExit( event ) {
- if ( !event.insideElementPressed ) {
+ if ( event.pointers < 1 ) {
THIS[ this.hash ].mouseInside = false;
if ( !THIS[ this.hash ].animating ) {
beginControlsAutoHide( this );
@@ -2626,6 +2760,7 @@ function onContainerExit( 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 {Number} pointers - Number of pointers (all types) active in the tracked element.
* @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. Deprecated. Use buttons instead.
* @property {Object} originalEvent - The original DOM event.
@@ -2635,71 +2770,7 @@ function onContainerExit( event ) {
tracker: event.eventSource,
position: event.position,
buttons: event.buttons,
- insideElementPressed: event.insideElementPressed,
- buttonDownAny: event.buttonDownAny,
- originalEvent: event.originalEvent
- });
-}
-
-function onContainerPress( event ) {
- if ( event.pointerType === 'touch' && !$.MouseTracker.haveTouchEnter ) {
- THIS[ this.hash ].mouseInside = true;
- abortControlsAutoHide( this );
- }
-}
-
-function onContainerRelease( event ) {
- if ( !event.insideElementReleased || ( event.pointerType === 'touch' && !$.MouseTracker.haveTouchEnter ) ) {
- THIS[ this.hash ].mouseInside = false;
- if ( !THIS[ this.hash ].animating ) {
- beginControlsAutoHide( this );
- }
- }
- /**
- * Raised when the primary mouse button is released or touch ends on the {@link OpenSeadragon.Viewer#container} element.
- *
- * @event container-release
- * @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 {Boolean} insideElementPressed - True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false.
- * @property {Boolean} insideElementReleased - True if the cursor still inside the tracked element when the button was released.
- * @property {Object} originalEvent - The original DOM event.
- * @property {?Object} userData - Arbitrary subscriber-defined object.
- */
- this.raiseEvent( 'container-release', {
- tracker: event.eventSource,
- position: event.position,
- insideElementPressed: event.insideElementPressed,
- insideElementReleased: event.insideElementReleased,
- originalEvent: event.originalEvent
- });
-}
-
-function onContainerEnter( event ) {
- THIS[ this.hash ].mouseInside = true;
- abortControlsAutoHide( this );
- /**
- * Raised when the cursor enters the {@link OpenSeadragon.Viewer#container} element.
- *
- * @event container-enter
- * @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} 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. Deprecated. Use buttons instead.
- * @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,
+ pointers: event.pointers,
insideElementPressed: event.insideElementPressed,
buttonDownAny: event.buttonDownAny,
originalEvent: event.originalEvent
diff --git a/test/helpers/legacy.mouse.shim.js b/test/helpers/legacy.mouse.shim.js
index 535f8815..3609ed85 100644
--- a/test/helpers/legacy.mouse.shim.js
+++ b/test/helpers/legacy.mouse.shim.js
@@ -21,19 +21,14 @@
}
$.MouseTracker.subscribeEvents.push( "mousedown", "mouseup", "mousemove" );
if ( 'ontouchstart' in window ) {
- // iOS, Android, and other W3c Touch Event implementations (see http://www.w3.org/TR/2011/WD-touch-events-20110505)
+ // iOS, Android, and other W3c Touch Event implementations
+ // (see http://www.w3.org/TR/touch-events/)
+ // (see https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html)
+ // (see https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html)
$.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)
+ // iOS (see https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html)
// Subscribe to these to prevent default gesture handling
$.MouseTracker.subscribeEvents.push( "gesturestart", "gesturechange" );
}