MouseTracker - keyboard handling

1) MouseTracker - added keydown and keyup handlers
2) Modifier keys ignored in keyboard  navigation handlers (#503)
3) Arrow key navigation fixed across platforms (#565)
This commit is contained in:
Mark Salsbery 2015-01-16 16:26:30 -08:00
parent a8ac532ce1
commit 2831771af5
3 changed files with 231 additions and 36 deletions

View File

@ -95,6 +95,10 @@
* An optional handler for after a drag gesture. * An optional handler for after a drag gesture.
* @param {OpenSeadragon.EventHandler} [options.pinchHandler=null] * @param {OpenSeadragon.EventHandler} [options.pinchHandler=null]
* An optional handler for the pinch gesture. * 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] * @param {OpenSeadragon.EventHandler} [options.keyHandler=null]
* An optional handler for keypress. * An optional handler for keypress.
* @param {OpenSeadragon.EventHandler} [options.focusHandler=null] * @param {OpenSeadragon.EventHandler} [options.focusHandler=null]
@ -170,6 +174,8 @@
this.dragEndHandler = options.dragEndHandler || null; this.dragEndHandler = options.dragEndHandler || null;
this.pinchHandler = options.pinchHandler || null; this.pinchHandler = options.pinchHandler || null;
this.stopHandler = options.stopHandler || null; this.stopHandler = options.stopHandler || null;
this.keyDownHandler = options.keyDownHandler || null;
this.keyUpHandler = options.keyUpHandler || null;
this.keyHandler = options.keyHandler || null; this.keyHandler = options.keyHandler || null;
this.focusHandler = options.focusHandler || null; this.focusHandler = options.focusHandler || null;
this.blurHandler = options.blurHandler || null; this.blurHandler = options.blurHandler || null;
@ -185,6 +191,8 @@
THIS[ this.hash ] = { THIS[ this.hash ] = {
click: function ( event ) { onClick( _this, event ); }, click: function ( event ) { onClick( _this, event ); },
dblclick: function ( event ) { onDblClick( _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 ); }, keypress: function ( event ) { onKeyPress( _this, event ); },
focus: function ( event ) { onFocus( _this, event ); }, focus: function ( event ) { onFocus( _this, event ); },
blur: function ( event ) { onBlur( _this, event ); }, blur: function ( event ) { onBlur( _this, event ); },
@ -743,8 +751,66 @@
* A reference to the tracker instance. * A reference to the tracker instance.
* @param {Number} event.keyCode * @param {Number} event.keyCode
* The key code that was pressed. * The key code that was pressed.
* @param {Boolean} event.ctrl
* True if the ctrl key was pressed during this event.
* @param {Boolean} event.shift * @param {Boolean} event.shift
* True if the shift key was pressed during this event. * 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 * @param {Object} event.originalEvent
* The original event object. * The original event object.
* @param {Boolean} event.preventDefaultAction * @param {Boolean} event.preventDefaultAction
@ -904,7 +970,7 @@
/** /**
* Detect browser pointer device event model(s) and build appropriate list of events to subscribe to. * 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" ) { if( $.MouseTracker.wheelEventName == "DOMMouseScroll" ) {
// Older Firefox // Older Firefox
@ -1440,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 * @private
* @inner * @inner
*/ */
function onKeyPress( tracker, event ) { 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; var propagate;
if ( tracker.keyHandler ) { if ( tracker.keyHandler ) {
event = $.getEvent( event ); event = $.getEvent( event );
@ -1454,7 +1580,10 @@
eventSource: tracker, eventSource: tracker,
position: getMouseRelative( event, tracker.element ), position: getMouseRelative( event, tracker.element ),
keyCode: event.keyCode ? event.keyCode : event.charCode, keyCode: event.keyCode ? event.keyCode : event.charCode,
ctrl: event.ctrlKey,
shift: event.shiftKey, shift: event.shiftKey,
alt: event.altKey,
meta: event.metaKey,
originalEvent: event, originalEvent: event,
preventDefaultAction: false, preventDefaultAction: false,
userData: tracker.userData userData: tracker.userData

View File

@ -125,6 +125,7 @@ $.ReferenceStrip = function ( options ) {
scrollHandler: $.delegate( this, onStripScroll ), scrollHandler: $.delegate( this, onStripScroll ),
enterHandler: $.delegate( this, onStripEnter ), enterHandler: $.delegate( this, onStripEnter ),
exitHandler: $.delegate( this, onStripExit ), exitHandler: $.delegate( this, onStripExit ),
keyDownHandler: $.delegate( this, onKeyDown ),
keyHandler: $.delegate( this, onKeyPress ) keyHandler: $.delegate( this, onKeyPress )
} ).setTracking( true ); } ).setTracking( true );
@ -511,6 +512,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 * @private
@ -520,35 +552,35 @@ function onStripExit( event ) {
function onKeyPress( event ) { function onKeyPress( event ) {
//console.log( event.keyCode ); //console.log( event.keyCode );
switch ( event.keyCode ) { if ( !event.preventDefaultAction && !event.ctrl && !event.alt && !event.meta ) {
case 61: //=|+ switch ( event.keyCode ) {
onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } ); case 61: //=|+
return false; onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } );
case 45: //-|_ return false;
onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } ); case 45: //-|_
return false; onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } );
case 48: //0|) return false;
case 119: //w case 48: //0|)
case 87: //W case 119: //w
case 38: //up arrow case 87: //W
onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } ); onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } );
return false; return false;
case 115: //s case 115: //s
case 83: //S case 83: //S
case 40: //down arrow onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } );
onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } ); return false;
return false; case 97: //a
case 97: //a onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } );
case 37: //left arrow return false;
onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } ); case 100: //d
return false; onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } );
case 100: //d return false;
case 39: //right arrow default:
onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } ); //console.log( 'navigator keycode %s', event.keyCode );
return false; return true;
default: }
//console.log( 'navigator keycode %s', event.keyCode ); } else {
return true; return true;
} }
} }

View File

@ -325,8 +325,44 @@ $.Viewer = function( options ) {
} }
}, },
keyDownHandler: function( 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;
}
},
keyHandler: function( event ){ keyHandler: function( event ){
if ( !event.preventDefaultAction ) { if ( !event.preventDefaultAction && !event.ctrl && !event.alt && !event.meta ) {
switch( event.keyCode ){ switch( event.keyCode ){
case 61://=|+ case 61://=|+
_this.viewport.zoomBy(1.1); _this.viewport.zoomBy(1.1);
@ -342,7 +378,6 @@ $.Viewer = function( options ) {
return false; return false;
case 119://w case 119://w
case 87://W case 87://W
case 38://up arrow
if ( event.shift ) { if ( event.shift ) {
_this.viewport.zoomBy(1.1); _this.viewport.zoomBy(1.1);
} else { } else {
@ -352,7 +387,6 @@ $.Viewer = function( options ) {
return false; return false;
case 115://s case 115://s
case 83://S case 83://S
case 40://down arrow
if ( event.shift ) { if ( event.shift ) {
_this.viewport.zoomBy(0.9); _this.viewport.zoomBy(0.9);
} else { } else {
@ -361,12 +395,10 @@ $.Viewer = function( options ) {
_this.viewport.applyConstraints(); _this.viewport.applyConstraints();
return false; return false;
case 97://a case 97://a
case 37://left arrow
_this.viewport.panBy(new $.Point(-0.05, 0)); _this.viewport.panBy(new $.Point(-0.05, 0));
_this.viewport.applyConstraints(); _this.viewport.applyConstraints();
return false; return false;
case 100://d case 100://d
case 39://right arrow
_this.viewport.panBy(new $.Point(0.05, 0)); _this.viewport.panBy(new $.Point(0.05, 0));
_this.viewport.applyConstraints(); _this.viewport.applyConstraints();
return false; return false;
@ -374,6 +406,8 @@ $.Viewer = function( options ) {
//console.log( 'navigator keycode %s', event.keyCode ); //console.log( 'navigator keycode %s', event.keyCode );
return true; return true;
} }
} else {
return true;
} }
} }
}).setTracking( true ); // default state }).setTracking( true ); // default state