Keyboard navigation fixes

Removed textarea element from Viewer DOM. Viewer.canvas now handles keyboard navigation.
This commit is contained in:
Mark Salsbery 2015-01-17 11:18:55 -08:00
parent 1765e3c0c9
commit 412ebce94d
2 changed files with 100 additions and 127 deletions

View File

@ -18,6 +18,7 @@ OPENSEADRAGON CHANGELOG
* MouseTracker - added keydown and keyup handlers (#568) * MouseTracker - added keydown and keyup handlers (#568)
* Modifier keys ignored in keyboard navigation handlers (#503) * Modifier keys ignored in keyboard navigation handlers (#503)
* Arrow key navigation fixed across platforms (#565) * Arrow key navigation fixed across platforms (#565)
* Removed textarea element from viewer DOM. Viewer.canvas now handles keyboard navigation
1.2.0: 1.2.0:

View File

@ -108,14 +108,6 @@ $.Viewer = function( options ) {
* @memberof OpenSeadragon.Viewer# * @memberof OpenSeadragon.Viewer#
*/ */
container: null, container: null,
/**
* A &lt;textarea&gt; element, the element where keyboard events are handled.<br><br>
* Child element of {@link OpenSeadragon.Viewer#container},
* positioned below {@link OpenSeadragon.Viewer#canvas}.
* @member {Element} keyboardCommandArea
* @memberof OpenSeadragon.Viewer#
*/
keyboardCommandArea: null,
/** /**
* A &lt;div&gt; element, the element where user-input events are handled for panning and zooming.<br><br> * A &lt;div&gt; element, the element where user-input events are handled for panning and zooming.<br><br>
* Child element of {@link OpenSeadragon.Viewer#container}, * Child element of {@link OpenSeadragon.Viewer#container},
@ -263,7 +255,6 @@ $.Viewer = function( options ) {
this.element = this.element || document.getElementById( this.id ); this.element = this.element || document.getElementById( this.id );
this.canvas = $.makeNeutralElement( "div" ); this.canvas = $.makeNeutralElement( "div" );
this.keyboardCommandArea = $.makeNeutralElement( "textarea" );
this.drawersContainer = $.makeNeutralElement( "div" ); this.drawersContainer = $.makeNeutralElement( "div" );
this.overlaysContainer = $.makeNeutralElement( "div" ); this.overlaysContainer = $.makeNeutralElement( "div" );
@ -277,6 +268,7 @@ $.Viewer = function( options ) {
style.left = "0px"; style.left = "0px";
}(this.canvas.style)); }(this.canvas.style));
$.setElementTouchActionNone( this.canvas ); $.setElementTouchActionNone( this.canvas );
this.canvas.tabIndex = 0;
//the container is created through applying the ControlDock constructor above //the container is created through applying the ControlDock constructor above
this.container.className = "openseadragon-container"; this.container.className = "openseadragon-container";
@ -290,21 +282,7 @@ $.Viewer = function( options ) {
style.textAlign = "left"; // needed to protect against style.textAlign = "left"; // needed to protect against
}( this.container.style )); }( 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 ));
// Set read-only - hides keyboard on mobile devices, still allows input.
this.keyboardCommandArea.readOnly = true;
this.container.insertBefore( this.canvas, this.container.firstChild ); this.container.insertBefore( this.canvas, this.container.firstChild );
this.container.insertBefore( this.keyboardCommandArea, this.container.firstChild );
this.element.appendChild( this.container ); this.element.appendChild( this.container );
this.canvas.appendChild( this.drawersContainer ); this.canvas.appendChild( this.drawersContainer );
this.canvas.appendChild( this.overlaysContainer ); this.canvas.appendChild( this.overlaysContainer );
@ -317,110 +295,15 @@ $.Viewer = function( options ) {
this.bodyOverflow = document.body.style.overflow; this.bodyOverflow = document.body.style.overflow;
this.docOverflow = document.documentElement.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 );
}
},
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 ){
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;
}
}
}).setTracking( true ); // default state
this.innerTracker = new $.MouseTracker({ this.innerTracker = new $.MouseTracker({
element: this.canvas, element: this.canvas,
clickTimeThreshold: this.clickTimeThreshold, clickTimeThreshold: this.clickTimeThreshold,
clickDistThreshold: this.clickDistThreshold, clickDistThreshold: this.clickDistThreshold,
dblClickTimeThreshold: this.dblClickTimeThreshold, dblClickTimeThreshold: this.dblClickTimeThreshold,
dblClickDistThreshold: this.dblClickDistThreshold, dblClickDistThreshold: this.dblClickDistThreshold,
focusHandler: $.delegate( this, onCanvasFocus ),
keyDownHandler: $.delegate( this, onCanvasKeyDown ),
keyHandler: $.delegate( this, onCanvasKeyPress ),
clickHandler: $.delegate( this, onCanvasClick ), clickHandler: $.delegate( this, onCanvasClick ),
dblClickHandler: $.delegate( this, onCanvasDblClick ), dblClickHandler: $.delegate( this, onCanvasDblClick ),
dragHandler: $.delegate( this, onCanvasDrag ), dragHandler: $.delegate( this, onCanvasDrag ),
@ -648,9 +531,6 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
} }
// destroy the mouse trackers // destroy the mouse trackers
if (this.keyboardCommandArea){
this.keyboardCommandArea.innerTracker.destroy();
}
if (this.innerTracker){ if (this.innerTracker){
this.innerTracker.destroy(); this.innerTracker.destroy();
} }
@ -663,7 +543,6 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
// clear all our references to dom objects // clear all our references to dom objects
this.canvas = null; this.canvas = null;
this.keyboardCommandArea = null;
this.container = null; this.container = null;
// clear our reference to the main element - they will need to pass it in again, creating a new viewer // clear our reference to the main element - they will need to pass it in again, creating a new viewer
@ -2309,14 +2188,107 @@ 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 ) { function onCanvasClick( event ) {
var gestureSettings; var gestureSettings;
var haveKeyboardFocus = document.activeElement == this.keyboardCommandArea; var haveKeyboardFocus = document.activeElement == this.canvas;
// If we don't have keyboard focus, request it. // If we don't have keyboard focus, request it.
if ( !haveKeyboardFocus ) { if ( !haveKeyboardFocus ) {
this.keyboardCommandArea.focus(); this.canvas.focus();
} }
if ( !event.preventDefaultAction && this.viewport && event.quick ) { if ( !event.preventDefaultAction && this.viewport && event.quick ) {