Merge pull request #46 from houseofyin/issue37-navigator

Issue37 navigator
This commit is contained in:
iangilman 2013-05-20 09:38:49 -07:00
commit da86ca2e38
31 changed files with 792 additions and 140 deletions

View File

@ -109,6 +109,7 @@ module.exports = function(grunt) {
qunit: {
all: {
options: {
timeout: 10000,
urls: [ "http://localhost:8000/test/test.html" ]
}
}

View File

@ -66,9 +66,12 @@ $.ControlAnchor = {
* @property {Element} wrapper - a nuetral element surrounding the control
* element.
*/
$.Control = function ( element, anchor, container ) {
$.Control = function ( element, options, container ) {
var parent = element.parentNode;
options.attachToViewer = (typeof options.attachToViewer === 'undefined') ? true : options.attachToViewer;
this.autoFade = (typeof options.autoFade === 'undefined') ? true : options.autoFade;
this.element = element;
this.anchor = anchor;
this.anchor = options.anchor;
this.container = container;
this.wrapper = $.makeNeutralElement( "span" );
this.wrapper.style.display = "inline-block";
@ -79,6 +82,7 @@ $.Control = function ( element, anchor, container ) {
this.wrapper.style.width = this.wrapper.style.height = "100%";
}
if (options.attachToViewer ) {
if ( this.anchor == $.ControlAnchor.TOP_RIGHT ||
this.anchor == $.ControlAnchor.BOTTOM_RIGHT ) {
this.container.insertBefore(
@ -88,6 +92,9 @@ $.Control = function ( element, anchor, container ) {
} else {
this.container.appendChild( this.wrapper );
}
} else {
parent.appendChild( this.wrapper );
}
};
$.Control.prototype = {

View File

@ -88,7 +88,7 @@
/**
* @function
*/
addControl: function ( element, anchor ) {
addControl: function ( element, controlOptions ) {
element = $.getElement( element );
var div = null;
@ -96,7 +96,7 @@
return; // they're trying to add a duplicate control
}
switch ( anchor ) {
switch ( controlOptions.anchor ) {
case $.ControlAnchor.TOP_RIGHT:
div = this.controls.topright;
element.style.position = "relative";
@ -130,7 +130,7 @@
}
this.controls.push(
new $.Control( element, anchor, div )
new $.Control( element, controlOptions, div )
);
element.style.display = "inline-block";
},

View File

@ -82,7 +82,7 @@ $.EventHandler.prototype = {
if( $.isArray( events ) ){
for( i = 0; i < events.length; i++ ){
if( events[ i ] !== handler ){
handlers.push( handler );
handlers.push( events[ i ] );
}
}
this.events[ eventName ] = handlers;

View File

@ -51,16 +51,26 @@ $.Navigator = function( options ){
var _this = this,
viewer = options.viewer,
viewerSize = $.getElementSize( viewer.element );
viewerSize = $.getElementSize( viewer.element),
unneededElement;
//We may need to create a new element and id if they did not
//provide the id for the existing element
if( !options.id ){
options.id = 'navigator-' + (+new Date());
this.element = $.makeNeutralElement( "div" );
this.element.id = options.id;
this.element.className = 'navigator';
options.controlOptions = {anchor: $.ControlAnchor.TOP_RIGHT,
attachToViewer: true,
autoFade: true};
}
else {
this.element = document.getElementById( options.id );
options.controlOptions = {anchor: $.ControlAnchor.NONE,
attachToViewer: false,
autoFade: false};
}
this.element.id = options.id;
this.element.className += ' navigator';
options = $.extend( true, {
sizeRatio: $.DEFAULT_SETTINGS.navigatorSizeRatio
@ -79,29 +89,36 @@ $.Navigator = function( options ){
options.minPixelRatio = this.minPixelRatio = viewer.minPixelRatio;
(function( style ){
style.marginTop = '0px';
style.marginRight = '0px';
style.marginBottom = '0px';
style.marginLeft = '0px';
style.border = '2px solid #555';
this.viewerSizeInPoints = viewer.viewport.deltaPointsFromPixels(viewerSize);
this.borderWidth = 2;
//At some browser magnification levels the display regions lines up correctly, but at some there appears to
//be a one pixel gap.
this.fudge = new $.Point(1, 1);
this.totalBorderWidths = new $.Point(this.borderWidth*2, this.borderWidth*2).minus(this.fudge);
(function( style, borderWidth ){
style.margin = '0px';
style.border = borderWidth + 'px solid #555';
style.padding = '0px';
style.background = '#000';
style.opacity = 0.8;
style.overflow = 'hidden';
}( this.element.style ));
}( this.element.style, this.borderWidth));
this.displayRegion = $.makeNeutralElement( "textarea" );
this.displayRegion = $.makeNeutralElement( "div" );
this.displayRegion.id = this.element.id + '-displayregion';
this.displayRegion.className = 'displayregion';
(function( style ){
(function( style, borderWidth ){
style.position = 'relative';
style.top = '0px';
style.left = '0px';
style.fontSize = '0px';
style.overflow = 'hidden';
style.border = '2px solid #900';
style.border = borderWidth + 'px solid #900';
style.margin = '0px';
style.padding = '0px';
//TODO: IE doesnt like this property being set
//try{ style.outline = '2px auto #909'; }catch(e){/*ignore*/}
@ -116,10 +133,13 @@ $.Navigator = function( options ){
style.styleFloat = 'left'; //IE
style.zIndex = 999999999;
style.cursor = 'default';
}( this.displayRegion.style ));
}( this.displayRegion.style, this.borderWidth ));
this.element.innerTracker = new $.MouseTracker({
element: this.element,
clickHandler: $.delegate( this, onCanvasClick ),
releaseHandler: $.delegate( this, onCanvasRelease ),
scrollHandler: function(){
//dont scroll the page up and down if the user is scrolling
//in the navigator
@ -131,77 +151,10 @@ $.Navigator = function( options ){
element: this.displayRegion,
clickTimeThreshold: this.clickTimeThreshold,
clickDistThreshold: this.clickDistThreshold,
clickHandler: $.delegate( this, onCanvasClick ),
dragHandler: $.delegate( this, onCanvasDrag ),
releaseHandler: $.delegate( this, onCanvasRelease ),
scrollHandler: $.delegate( this, onCanvasScroll ),
focusHandler: function(){
var point = $.getElementPosition( _this.viewer.element );
window.scrollTo( 0, point.y );
_this.viewer.setControlsEnabled( true );
(function( style ){
style.border = '2px solid #437AB2';
//style.outline = '2px auto #437AB2';
}( this.element.style ));
},
blurHandler: function(){
_this.viewer.setControlsEnabled( false );
(function( style ){
style.border = '2px solid #900';
//style.outline = '2px auto #900';
}( this.element.style ));
},
keyHandler: function(tracker, keyCode, shiftKey){
//console.log( keyCode );
switch( keyCode ){
case 61://=|+
_this.viewer.viewport.zoomBy(1.1);
_this.viewer.viewport.applyConstraints();
return false;
case 45://-|_
_this.viewer.viewport.zoomBy(0.9);
_this.viewer.viewport.applyConstraints();
return false;
case 48://0|)
_this.viewer.viewport.goHome();
_this.viewer.viewport.applyConstraints();
return false;
case 119://w
case 87://W
case 38://up arrow
if (shiftKey)
_this.viewer.viewport.zoomBy(1.1);
else
_this.viewer.viewport.panBy(new $.Point(0, -0.05));
_this.viewer.viewport.applyConstraints();
return false;
case 115://s
case 83://S
case 40://down arrow
if (shiftKey)
_this.viewer.viewport.zoomBy(0.9);
else
_this.viewer.viewport.panBy(new $.Point(0, 0.05));
_this.viewer.viewport.applyConstraints();
return false;
case 97://a
case 37://left arrow
_this.viewer.viewport.panBy(new $.Point(-0.05, 0));
_this.viewer.viewport.applyConstraints();
return false;
case 100://d
case 39://right arrow
_this.viewer.viewport.panBy(new $.Point(0.05, 0));
_this.viewer.viewport.applyConstraints();
return false;
default:
//console.log( 'navigator keycode %s', keyCode );
return true;
}
}
scrollHandler: $.delegate( this, onCanvasScroll )
}).setTracking( true ); // default state
/*this.displayRegion.outerTracker = new $.MouseTracker({
@ -216,7 +169,7 @@ $.Navigator = function( options ){
viewer.addControl(
this.element,
$.ControlAnchor.TOP_RIGHT
options.controlOptions
);
if( options.width && options.height ){
@ -230,6 +183,10 @@ $.Navigator = function( options ){
$.Viewer.apply( this, [ options ] );
this.element.getElementsByTagName('form')[0].appendChild( this.displayRegion );
unneededElement = this.element.getElementsByTagName('textarea')[0];
if (unneededElement) {
unneededElement.parentNode.removeChild(unneededElement);
}
};
@ -248,21 +205,21 @@ $.extend( $.Navigator.prototype, $.EventHandler.prototype, $.Viewer.prototype, {
if( viewport && this.viewport ){
bounds = viewport.getBounds( true );
topleft = this.viewport.pixelFromPoint( bounds.getTopLeft());
bottomright = this.viewport.pixelFromPoint( bounds.getBottomRight() );
bottomright = this.viewport.pixelFromPoint( bounds.getBottomRight()).minus(this.totalBorderWidths);
//update style for navigator-box
(function(style){
(function(style, borderWidth){
style.top = topleft.y + 'px';
style.left = topleft.x + 'px';
var width = Math.abs( topleft.x - bottomright.x ) - 3; // TODO: What does this magic number mean?
var height = Math.abs( topleft.y - bottomright.y ) - 3;
var width = Math.abs( topleft.x - bottomright.x );
var height = Math.abs( topleft.y - bottomright.y );
// make sure width and height are non-negative so IE doesn't throw
style.width = Math.max( width, 0 ) + 'px';
style.height = Math.max( height, 0 ) + 'px';
}( this.displayRegion.style ));
}( this.displayRegion.style, this.borderWidth));
}
},
@ -283,16 +240,39 @@ $.extend( $.Navigator.prototype, $.EventHandler.prototype, $.Viewer.prototype, {
});
/**
* @private
* @inner
* @function
*/
function onCanvasClick( tracker, position, quick, shift ) {
this.displayRegion.focus();
var newBounds,
viewerPosition,
dimensions;
if (! this.drag) {
if ( this.viewer.viewport ) {
viewerPosition = this.viewport.deltaPointsFromPixels(position);
dimensions = this.viewer.viewport.getBounds().getSize();
newBounds = new $.Rect(
viewerPosition.x - dimensions.x/2,
viewerPosition.y - dimensions.y/2,
dimensions.x,
dimensions.y
);
if (this.viewer.source.aspectRatio > this.viewer.viewport.getAspectRatio()) {
newBounds.y = newBounds.y - ((this.viewerSizeInPoints.y - (1/this.viewer.source.aspectRatio)) /2 );
}
else {
newBounds.x = newBounds.x - ((this.viewerSizeInPoints.x -1) /2 );
}
this.viewer.viewport.fitBounds(newBounds);
this.viewer.viewport.applyConstraints();
}
}
else {
this.drag = false;
}
}
/**
* @private
@ -301,6 +281,7 @@ function onCanvasClick( tracker, position, quick, shift ) {
*/
function onCanvasDrag( tracker, position, delta, shift ) {
if ( this.viewer.viewport ) {
this.drag = true;
if( !this.panHorizontal ){
delta.x = 0;
}
@ -339,7 +320,6 @@ function onCanvasScroll( tracker, position, scroll, shift ) {
factor = Math.pow( this.zoomPerScroll, scroll );
this.viewer.viewport.zoomBy(
factor,
//this.viewport.pointFromPixel( position, true )
this.viewport.getCenter()
);
this.viewer.viewport.applyConstraints();

View File

@ -519,7 +519,7 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){
//VIEWPORT NAVIGATOR SETTINGS
showNavigator: true, //promoted to default in 0.9.64
navigatorElement: null,
navigatorId: null,
navigatorHeight: null,
navigatorWidth: null,
navigatorPosition: null,

View File

@ -130,7 +130,7 @@ $.ReferenceStrip = function( options ){
this.element.style.height = options.height + 'px';
viewer.addControl(
this.element,
$.ControlAnchor.BOTTOM_LEFT
{anchor: $.ControlAnchor.BOTTOM_LEFT}
);
} else {
if( "horizontal" == options.scroll ){
@ -147,7 +147,7 @@ $.ReferenceStrip = function( options ){
viewer.addControl(
this.element,
$.ControlAnchor.BOTTOM_LEFT
{anchor: $.ControlAnchor.BOTTOM_LEFT}
);
}else {
this.element.style.height = (
@ -163,7 +163,7 @@ $.ReferenceStrip = function( options ){
viewer.addControl(
this.element,
$.ControlAnchor.TOP_LEFT
{anchor: $.ControlAnchor.TOP_LEFT}
);
}

View File

@ -204,30 +204,42 @@ $.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( canvas ){
canvas.width = "100%";
canvas.height = "100%";
canvas.overflow = "hidden";
canvas.position = "absolute";
canvas.top = "0px";
canvas.left = "0px";
(function( style ){
style.width = "100%";
style.height = "100%";
style.overflow = "hidden";
style.position = "absolute";
style.top = "0px";
style.left = "0px";
}( this.canvas.style ));
//the container is created through applying the ControlDock constructor above
this.container.className = "openseadragon-container";
(function( container ){
container.width = "100%";
container.height = "100%";
container.position = "relative";
container.overflow = "hidden";
container.left = "0px";
container.top = "0px";
container.textAlign = "left"; // needed to protect against
(function( style ){
style.width = "100%";
style.height = "100%";
style.position = "relative";
style.overflow = "hidden";
style.left = "0px";
style.top = "0px";
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";
}( 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
@ -238,6 +250,64 @@ $.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(){
var point = $.getElementPosition( this.element );
window.scrollTo( 0, point.y );
},
keyHandler: function(tracker, keyCode, shiftKey){
switch( 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 (shiftKey)
_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 (shiftKey)
_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', keyCode );
return true;
}
}
}).setTracking( true ); // default state
this.innerTracker = new $.MouseTracker({
element: this.canvas,
clickTimeThreshold: this.clickTimeThreshold,
@ -267,7 +337,7 @@ $.Viewer = function( options ) {
for ( i = 0; i < this.customControls.length; i++ ) {
this.addControl(
this.customControls[ i ].id,
this.customControls[ i ].anchor
{anchor: this.customControls[ i ].anchor}
);
}
@ -794,12 +864,12 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
if( this.toolbar ){
this.toolbar.addControl(
this.pagingControl,
$.ControlAnchor.BOTTOM_RIGHT
{anchor: $.ControlAnchor.BOTTOM_RIGHT}
);
}else{
this.addControl(
this.pagingControl,
$.ControlAnchor.TOP_LEFT
{anchor: $.ControlAnchor.TOP_LEFT}
);
}
}
@ -916,12 +986,12 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
if( this.toolbar ){
this.toolbar.addControl(
this.navControl,
$.ControlAnchor.TOP_LEFT
{anchor: $.ControlAnchor.TOP_LEFT}
);
}else{
this.addControl(
this.navControl,
$.ControlAnchor.TOP_LEFT
{anchor: $.ControlAnchor.TOP_LEFT}
);
}
}
@ -1069,7 +1139,7 @@ function openTileSource( viewer, source ) {
//Instantiate a navigator if configured
if ( _this.showNavigator && ! _this.navigator && !_this.collectionMode ){
_this.navigator = new $.Navigator({
id: _this.navigatorElement,
id: _this.navigatorId,
position: _this.navigatorPosition,
sizeRatio: _this.navigatorSizeRatio,
height: _this.navigatorHeight,
@ -1216,8 +1286,10 @@ function updateControlsFade( viewer ) {
opacity = Math.max( 0.0, opacity );
for ( i = viewer.controls.length - 1; i >= 0; i--) {
if (viewer.controls[ i ].autoFade) {
viewer.controls[ i ].setOpacity( opacity );
}
}
if ( opacity > 0 ) {
// fade again

View File

@ -0,0 +1,48 @@
<html>
<head>
<title>OpenSeadragon Navigator in a custom location Demo</title>
<script type="text/javascript" src='../../build/openseadragon/openseadragon.js'></script>
<style type="text/css">
.openseadragon1
{
width: 800px;
height: 600px;
border: 1px solid black;
color: #333; /* text color for messages */
background-color: black;
}
</style>
</head>
<body>
<div>
Simple demo page to show how to put the navigator in a custom location
</div>
<div id="contentDiv" class="openseadragon1"></div>
<div id="navigatorDiv" class="findme"></div>
<script type="text/javascript">
var viewer = OpenSeadragon({
id:"contentDiv",
navigatorId: "navigatorDiv",
prefixUrl:"../../build/openseadragon/images/",
tileSources:{
Image:{
xmlns:"http://schemas.microsoft.com/deepzoom/2008",
Url:"../data/testpattern_files/",
Format:"jpg",
Overlap:"2",
TileSize:"256",
Size:{
Height:"1000",
Width:"1000"
}
}
}
});
</script>
</body>
</html>

View File

@ -0,0 +1,55 @@
<html>
<head>
<title>OpenSeadragon Navigator in a JQuery UI Dialog Demo</title>
<script type="text/javascript" src='../../build/openseadragon/openseadragon.js'></script>
<script type="text/javascript" src='../lib/jquery-1.9.1.min.js'></script>
<script type="text/javascript" src='../lib/jquery-ui-1.10.2/js/jquery-ui-1.10.2.min.js'></script>
<link rel="stylesheet" type="text/css" href="../lib/jquery-ui-1.10.2/css/smoothness/jquery-ui-1.10.2.min.css"/>
<style type="text/css">
.openseadragon
{
width: 800px;
height: 600px;
border: 1px solid black;
color: #333; /* text color for messages */
background-color: black;
}
</style>
</head>
<body>
<div>
Simple demo page to show how to put the navigator in a moveable JQuery UI dialog.
</div>
<div id="contentDiv" class="openseadragon"></div>
<div id="navigatorDialog">
<div id="navigatorDiv"></div>
</div>
<script type="text/javascript">
$('#navigatorDialog').dialog();
var viewer = OpenSeadragon({
id:"contentDiv",
navigatorId: "navigatorDiv",
prefixUrl:"../../build/openseadragon/images/",
tileSources:{
Image:{
xmlns:"http://schemas.microsoft.com/deepzoom/2008",
Url:"../data/testpattern_files/",
Format:"jpg",
Overlap:"2",
TileSize:"256",
Size:{
Height:"1000",
Width:"1000"
}
}
}
});
</script>
</body>
</html>

View File

@ -10,7 +10,7 @@
// ----------
var testOpen = function(name) {
$(document).ready(function() {
var timeWatcher = Util.timeWatcher();
var timeWatcher = Util.timeWatcher(7000);
viewer = OpenSeadragon({
id: 'example',

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

435
test/navigator.js Normal file
View File

@ -0,0 +1,435 @@
QUnit.config.autostart = false;
(function () {
var viewer,
displayRegion,
navigator,
navigatorAspectRatio,
leftScalingFactor,
maxHeightFactor,
contentStartFromLeft,
contentStartFromTop,
displayRegionWidth,
displayRegionHeight;
module("navigator", {
setup:function () {
Util.resetDom();
resetTestVariables();
}
});
$(document).ready(function () {
start();
});
var resetTestVariables = function () {
if (viewer != null) {
viewer.close();
}
displayRegion = null;
navigator = null;
navigatorAspectRatio = null;
leftScalingFactor = null;
maxHeightFactor = null;
contentStartFromLeft = null;
contentStartFromTop = null;
displayRegionWidth = null;
displayRegionHeight = null;
};
var assessNavigatorLocation = function (expectedX, expectedY) {
var navigator = $(".navigator");
Util.assessNumericValue(expectedX, navigator.offset().left, 4, ' Navigator x position');
Util.assessNumericValue(expectedY, navigator.offset().top, 4, ' Navigator y position');
};
var navigatorRegionBoundsInPoints = function () {
var regionBoundsInPoints,
expectedDisplayRegionWidth,
expectedDisplayRegionHeight,
expectedDisplayRegionXLocation,
expectedDisplayRegionYLocation;
if (navigator === null) {
maxHeightFactor = 1;
navigator = $(".navigator");
navigatorAspectRatio = navigator.height() / navigator.width();
leftScalingFactor = navigatorAspectRatio * viewer.source.aspectRatio;
if (viewer.source.aspectRatio < 1) {
if (viewer.source.aspectRatio < navigatorAspectRatio) {
maxHeightFactor = viewer.source.aspectRatio * navigatorAspectRatio;
}
else {
maxHeightFactor = viewer.source.aspectRatio;
}
contentStartFromLeft = ((1 / maxHeightFactor) - 1) / 2 * maxHeightFactor * navigator.width();
contentStartFromTop = 0;
}
else {
if (viewer.source.aspectRatio < navigatorAspectRatio) {
contentStartFromTop = (navigatorAspectRatio - (1 / viewer.source.aspectRatio)) / 2 / navigatorAspectRatio * navigator.height();
}
else {
contentStartFromTop = (navigatorAspectRatio - (1 / viewer.source.aspectRatio)) / 2 / navigatorAspectRatio * navigator.height();
leftScalingFactor = 1;
}
}
displayRegionWidth = navigator.width() - 2 * contentStartFromLeft;
displayRegionHeight = navigator.height() - 2 * contentStartFromTop;
}
expectedDisplayRegionWidth = navigator.width() / viewer.viewport.getZoom() * maxHeightFactor;
expectedDisplayRegionHeight = navigator.height() / viewer.viewport.getZoom() * maxHeightFactor;
expectedDisplayRegionXLocation = viewer.viewport.getBounds().x * maxHeightFactor * navigator.width() + contentStartFromLeft;
expectedDisplayRegionYLocation = viewer.viewport.getBounds().y * leftScalingFactor * navigator.width() + contentStartFromTop;
regionBoundsInPoints = new OpenSeadragon.Rect(expectedDisplayRegionXLocation, expectedDisplayRegionYLocation, expectedDisplayRegionWidth, expectedDisplayRegionHeight);
return regionBoundsInPoints;
};
var assessDisplayRegion = function (status) {
var expectedBounds = navigatorRegionBoundsInPoints();
Util.assessNumericValue(expectedBounds.width, displayRegion.width() + viewer.navigator.totalBorderWidths.x, 2, status + ' Width synchronization');
Util.assessNumericValue(expectedBounds.height, displayRegion.height() + viewer.navigator.totalBorderWidths.y, 2, status + ' Height synchronization');
Util.assessNumericValue(expectedBounds.x, displayRegion.position().left, 2, status + ' Left synchronization');
Util.assessNumericValue(expectedBounds.y, displayRegion.position().top, 2, status + ' Top synchronization');
};
var waitForViewer = function () {
return function (handler, count, lastDisplayRegionLeft, lastDisplayWidth) {
var viewerAndNavigatorDisplayReady = false,
currentDisplayRegionLeft,
currentDisplayWidth;
if (displayRegion === null) {
displayRegion = $(".displayregion");
}
if (typeof count !== "number") {
count = 0;
lastDisplayRegionLeft = null;
lastDisplayWidth = null;
}
try {
currentDisplayRegionLeft = displayRegion.position().left;
currentDisplayWidth = displayRegion.width();
viewerAndNavigatorDisplayReady = viewer.drawer !== null &&
!viewer.drawer.needsUpdate() &&
currentDisplayWidth > 0 &&
Util.equalsWithVariance(lastDisplayRegionLeft, currentDisplayRegionLeft, .0001) &&
Util.equalsWithVariance(lastDisplayWidth, currentDisplayWidth, .0001) &&
Util.equalsWithVariance(viewer.viewport.getBounds(true).x, viewer.viewport.getBounds().x, .0001) &&
Util.equalsWithVariance(viewer.viewport.getBounds(true).y, viewer.viewport.getBounds().y, .0001) &&
Util.equalsWithVariance(viewer.viewport.getBounds(true).width, viewer.viewport.getBounds().width, .0001);
}
catch (err) {
//Ignore. Subsequent code will try again shortly
}
if (( !viewerAndNavigatorDisplayReady) && count < 50) {
count++;
setTimeout(function () {
waitForViewer(handler, count, currentDisplayRegionLeft, currentDisplayWidth);
}, 100)
}
else {
if (count === 40) {
console.log("waitForViewer:" +
viewer.drawer + ":" + viewer.drawer.needsUpdate() + ":" +
viewerAndNavigatorDisplayReady + ":" +
lastDisplayRegionLeft + ":" + currentDisplayRegionLeft + ":" +
lastDisplayWidth + ":" + currentDisplayWidth + ":" +
viewer.viewport.getBounds(true).x + ":" + viewer.viewport.getBounds().x + ":" +
viewer.viewport.getBounds(true).y + ":" + viewer.viewport.getBounds().y + ":" +
viewer.viewport.getBounds(true).width + ":" + viewer.viewport.getBounds().width + ":" +
count);
}
handler();
}
};
}();
var simulateNavigatorClick = function (viewer, locationX, locationY) {
var $canvas = $(viewer.element).find('.openseadragon-canvas'),
offset = $canvas.offset(),
event = {
clientX:offset.left + locationX,
clientY:offset.top + locationY
};
$canvas
.simulate('mouseover', event)
.simulate('mousedown', event)
.simulate('mouseup', event);
};
var simulateNavigatorDrag = function (viewer, distanceX, distanceY) {
var $canvas = $(viewer.element).find('.displayregion'),
event = {
dx:Math.floor(distanceX),
dy:Math.floor(distanceY)
};
$canvas
.simulate('drag', event);
};
var assessViewerInCorner = function (theContentCorner) {
return function () {
var expectedXCoordinate, expecteYCoordinate;
if (theContentCorner === "TOPLEFT") {
expectedXCoordinate = 0;
expecteYCoordinate = 0;
}
else if (theContentCorner === "TOPRIGHT") {
expectedXCoordinate = 1 - viewer.viewport.getBounds().width;
expecteYCoordinate = 0;
}
else if (theContentCorner === "BOTTOMRIGHT") {
expectedXCoordinate = 1 - viewer.viewport.getBounds().width;
expecteYCoordinate = 1 / viewer.source.aspectRatio - viewer.viewport.getBounds().height;
}
else if (theContentCorner === "BOTTOMLEFT") {
expectedXCoordinate = 0;
expecteYCoordinate = 1 / viewer.source.aspectRatio - viewer.viewport.getBounds().height;
}
if (viewer.viewport.getBounds().width < 1) {
Util.assessNumericValue(expectedXCoordinate, viewer.viewport.getBounds().x, .04, ' Viewer at ' + theContentCorner + ', x coord');
}
if (viewer.viewport.getBounds().height < 1 / viewer.source.aspectRatio) {
Util.assessNumericValue(expecteYCoordinate, viewer.viewport.getBounds().y, .04, ' Viewer at ' + theContentCorner + ', y coord');
}
}
};
var assessViewerInCenter = function () {
var yPositionVariance = .04;
if (viewer.source.aspectRatio < 1) {
yPositionVariance = yPositionVariance / viewer.source.aspectRatio;
}
Util.assessNumericValue(1 / viewer.source.aspectRatio / 2, viewer.viewport.getCenter().y, yPositionVariance, ' Viewer at center, y coord');
Util.assessNumericValue(.5, viewer.viewport.getCenter().x, .4, ' Viewer at center, x coord');
};
var clickOnNavigator = function (theContentCorner) {
return function () {
var xPos,
yPos;
if (theContentCorner === "TOPLEFT") {
xPos = contentStartFromLeft;
yPos = contentStartFromTop;
}
else if (theContentCorner === "TOPRIGHT") {
xPos = contentStartFromLeft + displayRegionWidth;
yPos = contentStartFromTop;
}
else if (theContentCorner === "BOTTOMRIGHT") {
xPos = contentStartFromLeft + displayRegionWidth;
yPos = contentStartFromTop + displayRegionHeight;
}
else if (theContentCorner === "BOTTOMLEFT") {
xPos = contentStartFromLeft;
yPos = contentStartFromTop + displayRegionHeight;
}
simulateNavigatorClick(viewer.navigator, xPos, yPos);
}
};
var dragNavigatorBackToCenter = function () {
var start = viewer.viewport.getBounds().getTopLeft(),
target = new OpenSeadragon.Point(0.5 - viewer.viewport.getBounds().width / 2,
1 / viewer.source.aspectRatio / 2 - viewer.viewport.getBounds().height / 2),
delta = target.minus(start);
if (viewer.source.aspectRatio < 1) {
delta.y = delta.y * viewer.source.aspectRatio;
}
simulateNavigatorDrag(viewer.navigator, delta.x * displayRegionWidth, delta.y * displayRegionHeight);
};
var assessNavigatorViewerPlacement = function (seadragonProperties, testProperties) {
var navigatorOperationScenarios = [
{interactionOperation:clickOnNavigator("TOPRIGHT"),
assessmentOperation:assessViewerInCorner("TOPRIGHT"),
assessmentMessage:"After click on navigator on top right" },
{interactionOperation:dragNavigatorBackToCenter,
assessmentOperation:assessViewerInCenter,
assessmentMessage:"After drag on navigator from top right" },
{interactionOperation:clickOnNavigator("BOTTOMLEFT"),
assessmentOperation:assessViewerInCorner("BOTTOMLEFT"),
assessmentMessage:"After click on navigator on bottom left" },
{interactionOperation:dragNavigatorBackToCenter,
assessmentOperation:assessViewerInCenter,
assessmentMessage:"After drag on navigator from bottom left" },
{interactionOperation:clickOnNavigator("BOTTOMRIGHT"),
assessmentOperation:assessViewerInCorner("BOTTOMRIGHT"),
assessmentMessage:"After click on navigator on bottom right" },
{interactionOperation:dragNavigatorBackToCenter,
assessmentOperation:assessViewerInCenter,
assessmentMessage:"After drag on navigator from bottom right" },
{interactionOperation:clickOnNavigator("TOPLEFT"),
assessmentOperation:assessViewerInCorner("TOPLEFT"),
assessmentMessage:"After click on navigator on top left" },
{interactionOperation:dragNavigatorBackToCenter,
assessmentOperation:assessViewerInCenter,
assessmentMessage:"After drag on navigator from top left" }
],
autoHideWaitTime = 7500;
seadragonProperties.visibilityRatio = 1;
viewer = OpenSeadragon(seadragonProperties);
var assessNavigatorOperationAndTakeNextStep = function (step) {
return function () {
var nextStep = step + 1;
assessDisplayRegion(navigatorOperationScenarios[step].assessmentMessage);
navigatorOperationScenarios[step].assessmentOperation();
if (step === navigatorOperationScenarios.length - 1) {
start();
}
else {
navigatorOperationScenarios[nextStep].interactionOperation();
waitForViewer(assessNavigatorOperationAndTakeNextStep(nextStep));
}
};
};
var assessAfterDragOnViewer = function () {
assessDisplayRegion("After pan");
navigatorOperationScenarios[0].interactionOperation();
waitForViewer(assessNavigatorOperationAndTakeNextStep(0));
};
var assessAfterZoomOnViewer = function () {
var target = new OpenSeadragon.Point(0.4, 0.4);
assessDisplayRegion("After image zoom");
viewer.viewport.panTo(target);
waitForViewer(assessAfterDragOnViewer);
};
var captureInitialStateThenAct = function () {
assessDisplayRegion("After image load");
testProperties.determineExpectationsAndAssessNavigatorLocation(seadragonProperties, testProperties);
viewer.viewport.zoomTo(viewer.viewport.getZoom() * 2);
waitForViewer(assessAfterZoomOnViewer);
};
var assessAutohideTriggered = function () {
ok($(testProperties.navigatorLocator).parent().css("opacity") == 0, "Expecting navigator to be autohide when in the default location");
waitForViewer(captureInitialStateThenAct);
};
var assessAutohideDisabled = function () {
ok($(testProperties.navigatorLocator).parent().css("opacity") > 0, "Expecting navigator to be always visible when in a custom location");
waitForViewer(captureInitialStateThenAct);
};
var openHandler = function () {
viewer.removeHandler('open', openHandler);
if (!testProperties.testAutohide) {
waitForViewer(captureInitialStateThenAct);
}
else {
ok($(testProperties.navigatorLocator).parent().css("opacity") > 0, "Expecting navigator to be visible initially");
var event = {
clientX:1,
clientY:1
};
var body = $("body").simulate('mouseover', event);
if (testProperties.expectedAutoHide) {
setTimeout(assessAutohideTriggered,autoHideWaitTime);
}
else {
setTimeout(assessAutohideDisabled,autoHideWaitTime);
}
}
};
viewer.addHandler('open', openHandler);
};
asyncTest('DefaultNavigatorLocationWithWideImageTallViewer', function () {
assessNavigatorViewerPlacement({
id:'tallexample',
prefixUrl:'/build/openseadragon/images/',
tileSources:'/test/data/wide.dzi',
showNavigator:true
},
{
displayRegionLocator:'.navigator .displayregion',
navigatorLocator:'.navigator',
testAutohide: false,
expectedAutoHide: false,
determineExpectationsAndAssessNavigatorLocation:function (seadragonProperties, testProperties) {
var mainViewerElement = $("#" + seadragonProperties.id),
navigatorElement = $(testProperties.navigatorLocator);
assessNavigatorLocation(mainViewerElement.offset().left + mainViewerElement.width() - navigatorElement.width(),
mainViewerElement.offset().top);
}
});
});
asyncTest('CustomNavigatorLocationWithWideImageWideViewer', function () {
assessNavigatorViewerPlacement({
id:'wideexample',
navigatorId:'exampleNavigator',
prefixUrl:'/build/openseadragon/images/',
tileSources:'/test/data/wide.dzi',
showNavigator:true
},
{
displayRegionLocator:'#exampleNavigator .displayregion',
navigatorLocator:'#exampleNavigator',
testAutohide: false,
expectedAutoHide: true,
determineExpectationsAndAssessNavigatorLocation:function (seadragonProperties, testProperties) {
var mainViewerElement = $("#" + seadragonProperties.id),
navigatorViewerElement = $("#" + seadragonProperties.navigatorId);
assessNavigatorLocation(mainViewerElement.offset().left,
mainViewerElement.offset().top - navigatorViewerElement.parent().height());
}
});
});
asyncTest('CustomDialogNavigatorLocationWithTallImageTallViewer', function () {
$('#exampleNavigator').dialog();
assessNavigatorViewerPlacement({
id:'tallexample',
navigatorId:'exampleNavigator',
prefixUrl:'/build/openseadragon/images/',
tileSources:'/test/data/tall.dzi',
showNavigator:true
},
{
displayRegionLocator:'#exampleNavigator .displayregion',
navigatorLocator:'#exampleNavigator',
testAutohide: true,
expectedAutoHide: false,
determineExpectationsAndAssessNavigatorLocation:function (seadragonProperties, testProperties) {
var jqueryDialog = $(testProperties.navigatorLocator);
assessNavigatorLocation(jqueryDialog.offset().left,
jqueryDialog.offset().top);
}
});
});
asyncTest('DefaultNavigatorLocationWithTallImageWideViewer', function () {
assessNavigatorViewerPlacement({
id:'wideexample',
prefixUrl:'/build/openseadragon/images/',
tileSources:'/test/data/tall.dzi',
showNavigator:true
},
{
displayRegionLocator:'.navigator .displayregion',
navigatorLocator:'.navigator',
testAutohide: true,
expectedAutoHide: true,
determineExpectationsAndAssessNavigatorLocation:function (seadragonProperties, testProperties) {
var mainViewerElement = $("#" + seadragonProperties.id),
navigatorElement = $(testProperties.navigatorLocator);
assessNavigatorLocation(mainViewerElement.offset().left + mainViewerElement.width() - navigatorElement.width(),
mainViewerElement.offset().top);
}
});
});
})();

View File

@ -2,3 +2,14 @@
height: 500px;
width: 500px;
}
#wideexample {
height: 300px;
width: 700px;
}
#tallexample {
height: 700px;
width: 300px;
}

View File

@ -4,18 +4,26 @@
<meta charset="utf-8">
<title>OpenSeadragon QUnit</title>
<link rel="stylesheet" href="/node_modules/grunt-contrib-qunit/test/libs/qunit.css">
<link rel="stylesheet" href="/test/lib/jquery-ui-1.10.2/css/smoothness/jquery-ui-1.10.2.min.css">
<link rel="stylesheet" href="/test/test.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<div>
<div id="example"></div>
<div id="exampleNavigator"></div>
</div>
<div id="wideexample"></div>
<div id="tallexample"></div>
<script src="/node_modules/grunt-contrib-qunit/test/libs/qunit.js"></script>
<script src="/test/lib/jquery-1.9.1.min.js"></script>
<script src="/test/lib/jquery-ui-1.10.2/js/jquery-ui-1.10.2.min.js"></script>
<script src="/test/lib/jquery.simulate.js"></script>
<script src="/build/openseadragon/openseadragon.min.js"></script>
<script src="/test/test.js"></script>
<script src="/test/basic.js"></script>
<script src="/test/navigator.js"></script>
<script src="/test/strings.js"></script>
<script src="/test/formats.js"></script>
<script src="/test/utils.js"></script>

View File

@ -8,11 +8,13 @@
widthFactor = 0.5;
}
//TODO Redefine to be the middle by default
if (heightFactor === undefined) {
heightFactor = 0.5;
}
widthFactor = Math.min(1, Math.max(0, widthFactor));
//TODO Fix this. The max height should be 1/AR
heightFactor = Math.min(1, Math.max(0, heightFactor));
var $canvas = $(viewer.element).find('.openseadragon-canvas').not('.navigator .openseadragon-canvas');
@ -28,7 +30,26 @@
.simulate('mouseup', event);
},
// ----------
resetDom: function () {
if ($('#exampleNavigator').is(':ui-dialog')) {
$('#exampleNavigator').dialog('destroy');
}
$("#exampleNavigator").remove();
$(".navigator").remove();
$("#example").empty();
$("#tallexample").empty();
$("#wideexample").empty();
$("#example").parent().append('<div id="exampleNavigator"></div>');
},
equalsWithVariance: function (value1, value2, variance) {
return Math.abs(value1 - value2) <= variance;
},
assessNumericValue: function (value1, value2, variance, message) {
ok(Util.equalsWithVariance(value1, value2, variance), message + " Expected:" + value1 + " Found: " + value2 + " Variance: " + variance);
},
timeWatcher: function(time) {
time = time || 2000;
var finished = false;
@ -50,6 +71,8 @@
}
};
}
};
})();