2013-05-01 08:46:16 +04:00
|
|
|
/*
|
|
|
|
* OpenSeadragon
|
|
|
|
*
|
|
|
|
* Copyright (C) 2009 CodePlex Foundation
|
2013-05-13 01:12:26 +04:00
|
|
|
* Copyright (C) 2011-2013 OpenSeadragon contributors
|
2013-05-01 08:46:16 +04:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
* met:
|
|
|
|
*
|
|
|
|
* - Redistributions of source code must retain the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer.
|
|
|
|
*
|
|
|
|
* - Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* - Neither the name of CodePlex Foundation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived from
|
|
|
|
* this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
|
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2012-03-07 07:20:00 +04:00
|
|
|
(function( $ ){
|
|
|
|
|
|
|
|
/**
|
2012-04-11 01:02:24 +04:00
|
|
|
* The Navigator provides a small view of the current image as fixed
|
|
|
|
* while representing the viewport as a moving box serving as a frame
|
|
|
|
* of reference in the larger viewport as to which portion of the image
|
2013-01-31 22:18:32 +04:00
|
|
|
* is currently being examined. The navigator's viewport can be interacted
|
2012-04-11 01:02:24 +04:00
|
|
|
* with using the keyboard or the mouse.
|
|
|
|
* @class
|
|
|
|
* @name OpenSeadragon.Navigator
|
|
|
|
* @extends OpenSeadragon.Viewer
|
|
|
|
* @extends OpenSeadragon.EventHandler
|
2012-03-07 07:20:00 +04:00
|
|
|
* @param {Object} options
|
|
|
|
* @param {String} options.viewerId
|
|
|
|
*/
|
|
|
|
$.Navigator = function( options ){
|
|
|
|
|
|
|
|
var _this = this,
|
2012-03-16 19:36:28 +04:00
|
|
|
viewer = options.viewer,
|
|
|
|
viewerSize = $.getElementSize( viewer.element );
|
2012-03-07 07:20:00 +04:00
|
|
|
|
|
|
|
//We may need to create a new element and id if they did not
|
|
|
|
//provide the id for the existing element
|
|
|
|
if( !options.id ){
|
2012-03-16 19:36:28 +04:00
|
|
|
options.id = 'navigator-' + (+new Date());
|
|
|
|
this.element = $.makeNeutralElement( "div" );
|
|
|
|
this.element.id = options.id;
|
|
|
|
this.element.className = 'navigator';
|
2012-03-07 07:20:00 +04:00
|
|
|
}
|
|
|
|
|
2012-03-09 20:04:28 +04:00
|
|
|
options = $.extend( true, {
|
2013-01-31 01:51:37 +04:00
|
|
|
sizeRatio: $.DEFAULT_SETTINGS.navigatorSizeRatio
|
2012-03-09 20:04:28 +04:00
|
|
|
}, options, {
|
2012-03-07 07:20:00 +04:00
|
|
|
element: this.element,
|
|
|
|
//These need to be overridden to prevent recursion since
|
|
|
|
//the navigator is a viewer and a viewer has a navigator
|
|
|
|
showNavigator: false,
|
|
|
|
mouseNavEnabled: false,
|
2012-04-11 01:02:24 +04:00
|
|
|
showNavigationControl: false,
|
2013-03-06 14:51:31 +04:00
|
|
|
showSequenceControl: false,
|
|
|
|
immediateRender: true,
|
|
|
|
blendTime: 0,
|
|
|
|
animationTime: 0
|
2012-03-07 07:20:00 +04:00
|
|
|
});
|
|
|
|
|
2012-09-07 16:55:19 +04:00
|
|
|
options.minPixelRatio = this.minPixelRatio = viewer.minPixelRatio;
|
2012-03-20 03:03:58 +04:00
|
|
|
|
2012-03-07 07:20:00 +04:00
|
|
|
(function( style ){
|
|
|
|
style.marginTop = '0px';
|
|
|
|
style.marginRight = '0px';
|
|
|
|
style.marginBottom = '0px';
|
|
|
|
style.marginLeft = '0px';
|
|
|
|
style.border = '2px solid #555';
|
|
|
|
style.background = '#000';
|
|
|
|
style.opacity = 0.8;
|
|
|
|
style.overflow = 'hidden';
|
|
|
|
}( this.element.style ));
|
|
|
|
|
2012-03-20 03:03:58 +04:00
|
|
|
this.displayRegion = $.makeNeutralElement( "textarea" );
|
|
|
|
this.displayRegion.id = this.element.id + '-displayregion';
|
|
|
|
this.displayRegion.className = 'displayregion';
|
2012-03-07 07:20:00 +04:00
|
|
|
|
|
|
|
(function( style ){
|
|
|
|
style.position = 'relative';
|
|
|
|
style.top = '0px';
|
|
|
|
style.left = '0px';
|
2012-03-21 05:58:23 +04:00
|
|
|
style.fontSize = '0px';
|
2012-09-11 20:31:42 +04:00
|
|
|
style.overflow = 'hidden';
|
2012-03-21 05:58:23 +04:00
|
|
|
style.border = '2px solid #900';
|
2013-01-29 22:06:39 +04:00
|
|
|
|
2012-03-20 23:00:25 +04:00
|
|
|
//TODO: IE doesnt like this property being set
|
2013-01-24 08:00:11 +04:00
|
|
|
//try{ style.outline = '2px auto #909'; }catch(e){/*ignore*/}
|
2013-01-29 22:06:39 +04:00
|
|
|
|
2012-03-07 07:20:00 +04:00
|
|
|
style.background = 'transparent';
|
2013-01-29 22:06:39 +04:00
|
|
|
|
|
|
|
// We use square bracket notation on the statement below, because float is a keyword.
|
2013-01-31 22:18:32 +04:00
|
|
|
// This is important for the Google Closure compiler, if nothing else.
|
2013-01-29 22:06:39 +04:00
|
|
|
/*jshint sub:true */
|
|
|
|
style['float'] = 'left'; //Webkit
|
|
|
|
|
2012-03-20 10:26:34 +04:00
|
|
|
style.cssFloat = 'left'; //Firefox
|
2012-03-20 23:30:29 +04:00
|
|
|
style.styleFloat = 'left'; //IE
|
2012-03-07 07:20:00 +04:00
|
|
|
style.zIndex = 999999999;
|
2012-04-03 11:08:27 +04:00
|
|
|
style.cursor = 'default';
|
2012-03-07 07:20:00 +04:00
|
|
|
}( this.displayRegion.style ));
|
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
this.element.innerTracker = new $.MouseTracker({
|
|
|
|
element: this.element,
|
|
|
|
scrollHandler: function(){
|
|
|
|
//dont scroll the page up and down if the user is scrolling
|
|
|
|
//in the navigator
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}).setTracking( true );
|
|
|
|
|
2012-03-20 03:03:58 +04:00
|
|
|
this.displayRegion.innerTracker = new $.MouseTracker({
|
|
|
|
element: this.displayRegion,
|
|
|
|
clickTimeThreshold: this.clickTimeThreshold,
|
|
|
|
clickDistThreshold: this.clickDistThreshold,
|
2012-04-03 11:08:27 +04:00
|
|
|
clickHandler: $.delegate( this, onCanvasClick ),
|
|
|
|
dragHandler: $.delegate( this, onCanvasDrag ),
|
|
|
|
releaseHandler: $.delegate( this, onCanvasRelease ),
|
|
|
|
scrollHandler: $.delegate( this, onCanvasScroll ),
|
2012-03-20 03:03:58 +04:00
|
|
|
focusHandler: function(){
|
2012-04-03 11:08:27 +04:00
|
|
|
var point = $.getElementPosition( _this.viewer.element );
|
|
|
|
|
|
|
|
window.scrollTo( 0, point.y );
|
|
|
|
|
2012-03-20 03:03:58 +04:00
|
|
|
_this.viewer.setControlsEnabled( true );
|
|
|
|
(function( style ){
|
2012-03-21 05:58:23 +04:00
|
|
|
style.border = '2px solid #437AB2';
|
2013-01-24 08:00:11 +04:00
|
|
|
//style.outline = '2px auto #437AB2';
|
2012-03-20 03:03:58 +04:00
|
|
|
}( this.element.style ));
|
|
|
|
|
|
|
|
},
|
|
|
|
blurHandler: function(){
|
|
|
|
_this.viewer.setControlsEnabled( false );
|
|
|
|
(function( style ){
|
2012-03-21 05:58:23 +04:00
|
|
|
style.border = '2px solid #900';
|
2013-01-24 08:00:11 +04:00
|
|
|
//style.outline = '2px auto #900';
|
2012-03-20 03:03:58 +04:00
|
|
|
}( this.element.style ));
|
|
|
|
},
|
2012-03-21 05:58:23 +04:00
|
|
|
keyHandler: function(tracker, keyCode, shiftKey){
|
2012-03-20 03:03:58 +04:00
|
|
|
//console.log( keyCode );
|
|
|
|
switch( keyCode ){
|
2012-03-21 05:58:23 +04:00
|
|
|
case 61://=|+
|
|
|
|
_this.viewer.viewport.zoomBy(1.1);
|
2012-04-03 11:08:27 +04:00
|
|
|
_this.viewer.viewport.applyConstraints();
|
2012-03-21 05:58:23 +04:00
|
|
|
return false;
|
|
|
|
case 45://-|_
|
|
|
|
_this.viewer.viewport.zoomBy(0.9);
|
2012-04-03 11:08:27 +04:00
|
|
|
_this.viewer.viewport.applyConstraints();
|
2012-03-21 05:58:23 +04:00
|
|
|
return false;
|
|
|
|
case 48://0|)
|
|
|
|
_this.viewer.viewport.goHome();
|
2012-04-03 11:08:27 +04:00
|
|
|
_this.viewer.viewport.applyConstraints();
|
2012-03-21 05:58:23 +04:00
|
|
|
return false;
|
2012-03-20 03:03:58 +04:00
|
|
|
case 119://w
|
2012-03-21 05:58:23 +04:00
|
|
|
case 87://W
|
2012-03-20 23:30:29 +04:00
|
|
|
case 38://up arrow
|
2013-01-29 21:32:58 +04:00
|
|
|
if (shiftKey)
|
|
|
|
_this.viewer.viewport.zoomBy(1.1);
|
|
|
|
else
|
2012-03-21 05:58:23 +04:00
|
|
|
_this.viewer.viewport.panBy(new $.Point(0, -0.05));
|
2012-04-03 11:08:27 +04:00
|
|
|
_this.viewer.viewport.applyConstraints();
|
2012-03-20 23:30:29 +04:00
|
|
|
return false;
|
2012-03-20 03:03:58 +04:00
|
|
|
case 115://s
|
2012-03-21 05:58:23 +04:00
|
|
|
case 83://S
|
2012-03-20 23:30:29 +04:00
|
|
|
case 40://down arrow
|
2013-01-29 21:32:58 +04:00
|
|
|
if (shiftKey)
|
|
|
|
_this.viewer.viewport.zoomBy(0.9);
|
|
|
|
else
|
2012-03-21 05:58:23 +04:00
|
|
|
_this.viewer.viewport.panBy(new $.Point(0, 0.05));
|
2012-04-03 11:08:27 +04:00
|
|
|
_this.viewer.viewport.applyConstraints();
|
2012-03-20 23:30:29 +04:00
|
|
|
return false;
|
2012-03-20 03:03:58 +04:00
|
|
|
case 97://a
|
2012-03-20 23:30:29 +04:00
|
|
|
case 37://left arrow
|
2012-03-20 23:00:25 +04:00
|
|
|
_this.viewer.viewport.panBy(new $.Point(-0.05, 0));
|
2012-04-03 11:08:27 +04:00
|
|
|
_this.viewer.viewport.applyConstraints();
|
2012-03-20 23:30:29 +04:00
|
|
|
return false;
|
2012-03-20 03:03:58 +04:00
|
|
|
case 100://d
|
2012-03-20 23:30:29 +04:00
|
|
|
case 39://right arrow
|
2012-03-20 23:00:25 +04:00
|
|
|
_this.viewer.viewport.panBy(new $.Point(0.05, 0));
|
2012-04-03 11:08:27 +04:00
|
|
|
_this.viewer.viewport.applyConstraints();
|
2012-03-20 23:30:29 +04:00
|
|
|
return false;
|
2012-03-20 03:03:58 +04:00
|
|
|
default:
|
|
|
|
//console.log( 'navigator keycode %s', keyCode );
|
2012-03-20 23:30:29 +04:00
|
|
|
return true;
|
2012-03-20 03:03:58 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}).setTracking( true ); // default state
|
|
|
|
|
|
|
|
/*this.displayRegion.outerTracker = new $.MouseTracker({
|
|
|
|
element: this.container,
|
|
|
|
clickTimeThreshold: this.clickTimeThreshold,
|
|
|
|
clickDistThreshold: this.clickDistThreshold,
|
|
|
|
enterHandler: $.delegate( this, onContainerEnter ),
|
|
|
|
exitHandler: $.delegate( this, onContainerExit ),
|
|
|
|
releaseHandler: $.delegate( this, onContainerRelease )
|
|
|
|
}).setTracking( this.mouseNavEnabled ? true : false ); // always tracking*/
|
|
|
|
|
2012-03-07 07:20:00 +04:00
|
|
|
|
2012-03-16 19:36:28 +04:00
|
|
|
viewer.addControl(
|
|
|
|
this.element,
|
|
|
|
$.ControlAnchor.TOP_RIGHT
|
|
|
|
);
|
2012-03-07 07:20:00 +04:00
|
|
|
|
2012-03-09 20:04:28 +04:00
|
|
|
if( options.width && options.height ){
|
|
|
|
this.element.style.width = options.width + 'px';
|
2012-03-07 07:20:00 +04:00
|
|
|
this.element.style.height = options.height + 'px';
|
|
|
|
} else {
|
2013-01-31 01:51:37 +04:00
|
|
|
this.element.style.width = ( viewerSize.x * options.sizeRatio ) + 'px';
|
|
|
|
this.element.style.height = ( viewerSize.y * options.sizeRatio ) + 'px';
|
2012-03-07 07:20:00 +04:00
|
|
|
}
|
|
|
|
|
2012-03-16 19:36:28 +04:00
|
|
|
$.Viewer.apply( this, [ options ] );
|
|
|
|
|
2012-08-29 22:46:34 +04:00
|
|
|
this.element.getElementsByTagName('form')[0].appendChild( this.displayRegion );
|
|
|
|
|
2012-03-07 07:20:00 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
$.extend( $.Navigator.prototype, $.EventHandler.prototype, $.Viewer.prototype, {
|
|
|
|
|
2012-04-11 01:02:24 +04:00
|
|
|
/**
|
|
|
|
* @function
|
|
|
|
* @name OpenSeadragon.Navigator.prototype.update
|
|
|
|
*/
|
2012-03-07 07:20:00 +04:00
|
|
|
update: function( viewport ){
|
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
var bounds,
|
|
|
|
topleft,
|
|
|
|
bottomright;
|
|
|
|
|
|
|
|
if( viewport && this.viewport ){
|
|
|
|
bounds = viewport.getBounds( true );
|
|
|
|
topleft = this.viewport.pixelFromPoint( bounds.getTopLeft() );
|
2012-03-07 07:20:00 +04:00
|
|
|
bottomright = this.viewport.pixelFromPoint( bounds.getBottomRight() );
|
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
//update style for navigator-box
|
|
|
|
(function(style){
|
2012-03-07 07:20:00 +04:00
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
style.top = topleft.y + 'px';
|
|
|
|
style.left = topleft.x + 'px';
|
2013-01-28 22:11:14 +04:00
|
|
|
|
2013-01-31 22:18:32 +04:00
|
|
|
var width = Math.abs( topleft.x - bottomright.x ) - 3; // TODO: What does this magic number mean?
|
2013-01-25 17:17:35 +04:00
|
|
|
var height = Math.abs( topleft.y - bottomright.y ) - 3;
|
|
|
|
// 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';
|
2012-03-07 07:20:00 +04:00
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
}( this.displayRegion.style ));
|
|
|
|
}
|
2012-03-07 07:20:00 +04:00
|
|
|
|
2013-03-06 14:51:31 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
open: function( source ){
|
|
|
|
var containerSize = this.viewer.viewport.containerSize.times( this.sizeRatio );
|
|
|
|
if( source.tileSize > containerSize.x ||
|
|
|
|
source.tileSize > containerSize.y ){
|
|
|
|
this.minPixelRatio = Math.min(
|
|
|
|
containerSize.x,
|
|
|
|
containerSize.y
|
|
|
|
) / source.tileSize;
|
|
|
|
} else {
|
2013-03-26 17:02:34 +04:00
|
|
|
this.minPixelRatio = this.viewer.minPixelRatio;
|
2013-03-06 14:51:31 +04:00
|
|
|
}
|
|
|
|
return $.Viewer.prototype.open.apply( this, [ source ] );
|
2012-03-07 07:20:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2012-04-11 01:02:24 +04:00
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
* @inner
|
|
|
|
* @function
|
|
|
|
*/
|
2012-04-03 11:08:27 +04:00
|
|
|
function onCanvasClick( tracker, position, quick, shift ) {
|
|
|
|
this.displayRegion.focus();
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2012-04-03 11:08:27 +04:00
|
|
|
|
|
|
|
|
2012-04-11 01:02:24 +04:00
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
* @inner
|
|
|
|
* @function
|
|
|
|
*/
|
2012-04-03 11:08:27 +04:00
|
|
|
function onCanvasDrag( tracker, position, delta, shift ) {
|
|
|
|
if ( this.viewer.viewport ) {
|
|
|
|
if( !this.panHorizontal ){
|
|
|
|
delta.x = 0;
|
|
|
|
}
|
|
|
|
if( !this.panVertical ){
|
|
|
|
delta.y = 0;
|
|
|
|
}
|
|
|
|
this.viewer.viewport.panBy(
|
|
|
|
this.viewport.deltaPointsFromPixels(
|
|
|
|
delta
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2012-04-03 11:08:27 +04:00
|
|
|
|
|
|
|
|
2012-04-11 01:02:24 +04:00
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
* @inner
|
|
|
|
* @function
|
|
|
|
*/
|
2012-04-03 11:08:27 +04:00
|
|
|
function onCanvasRelease( tracker, position, insideElementPress, insideElementRelease ) {
|
|
|
|
if ( insideElementPress && this.viewer.viewport ) {
|
|
|
|
this.viewer.viewport.applyConstraints();
|
|
|
|
}
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2012-04-11 01:02:24 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
* @inner
|
|
|
|
* @function
|
|
|
|
*/
|
2012-04-03 11:08:27 +04:00
|
|
|
function onCanvasScroll( tracker, position, scroll, shift ) {
|
|
|
|
var factor;
|
|
|
|
if ( this.viewer.viewport ) {
|
|
|
|
factor = Math.pow( this.zoomPerScroll, scroll );
|
|
|
|
this.viewer.viewport.zoomBy(
|
|
|
|
factor,
|
|
|
|
//this.viewport.pointFromPixel( position, true )
|
|
|
|
this.viewport.getCenter()
|
|
|
|
);
|
|
|
|
this.viewer.viewport.applyConstraints();
|
|
|
|
}
|
|
|
|
//cancels event
|
|
|
|
return false;
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2012-04-03 11:08:27 +04:00
|
|
|
|
|
|
|
|
2013-01-25 17:17:35 +04:00
|
|
|
}( OpenSeadragon ));
|