several bug fixes and enhancements. legacy tile source issue discovered and corrected for images with width greater than height. adding basic support for sequenced tile sources including previous and next buttons. added mouse drag and scroll interactions for viewport navigator.

This commit is contained in:
thatcher 2012-04-03 03:08:27 -04:00
parent 94247b7225
commit 05f3c1d811
20 changed files with 1162 additions and 471 deletions

View File

@ -6,7 +6,7 @@
PROJECT: openseadragon PROJECT: openseadragon
BUILD_MAJOR: 0 BUILD_MAJOR: 0
BUILD_MINOR: 9 BUILD_MINOR: 9
BUILD_ID: 37 BUILD_ID: 40
BUILD: ${PROJECT}.${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID} BUILD: ${PROJECT}.${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID}
VERSION: ${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID} VERSION: ${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID}

BIN
images/next_grouphover.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
images/next_hover.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
images/next_pressed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
images/next_rest.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
images/previous_hover.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
images/previous_pressed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
images/previous_rest.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

File diff suppressed because it is too large Load Diff

View File

@ -223,6 +223,18 @@ $.extend( $.Button.prototype, $.EventHandler.prototype, {
*/ */
notifyGroupExit: function() { notifyGroupExit: function() {
outTo( this, $.ButtonState.REST ); outTo( this, $.ButtonState.REST );
},
disable: function(){
this.notifyGroupExit();
this.element.disabled = true;
$.setElementOpacity( this.element, 0.2, true );
},
enable: function(){
this.element.disabled = false;
$.setElementOpacity( this.element, 1.0, true );
this.notifyGroupEnter();
} }
}); });
@ -268,6 +280,11 @@ function stopFading( button ) {
}; };
function inTo( button, newState ) { function inTo( button, newState ) {
if( button.element.disabled ){
return;
}
if ( newState >= $.ButtonState.GROUP && if ( newState >= $.ButtonState.GROUP &&
button.currentState == $.ButtonState.REST ) { button.currentState == $.ButtonState.REST ) {
stopFading( button ); stopFading( button );
@ -289,6 +306,11 @@ function inTo( button, newState ) {
function outTo( button, newState ) { function outTo( button, newState ) {
if( button.element.disabled ){
return;
}
if ( newState <= $.ButtonState.HOVER && if ( newState <= $.ButtonState.HOVER &&
button.currentState == $.ButtonState.DOWN ) { button.currentState == $.ButtonState.DOWN ) {
button.imgDown.style.visibility = "hidden"; button.imgDown.style.visibility = "hidden";

View File

@ -10,7 +10,8 @@ var TIMEOUT = 5000,
( BROWSER == $.BROWSERS.FIREFOX ) || ( BROWSER == $.BROWSERS.FIREFOX ) ||
( BROWSER == $.BROWSERS.OPERA ) || ( BROWSER == $.BROWSERS.OPERA ) ||
( BROWSER == $.BROWSERS.SAFARI && BROWSER_VERSION >= 4 ) || ( BROWSER == $.BROWSERS.SAFARI && BROWSER_VERSION >= 4 ) ||
( BROWSER == $.BROWSERS.CHROME && BROWSER_VERSION >= 2 ) ( BROWSER == $.BROWSERS.CHROME && BROWSER_VERSION >= 2 ) ||
( BROWSER == $.BROWSERS.IE && BROWSER_VERSION >= 9 )
) && ( !navigator.appVersion.match( 'Mobile' ) ), ) && ( !navigator.appVersion.match( 'Mobile' ) ),
USE_CANVAS = $.isFunction( document.createElement( "canvas" ).getContext ) && USE_CANVAS = $.isFunction( document.createElement( "canvas" ).getContext ) &&

View File

@ -49,8 +49,8 @@ $.LegacyTileSource.prototype = {
var levelScale = NaN; var levelScale = NaN;
if ( level >= this.minLevel && level <= this.maxLevel ){ if ( level >= this.minLevel && level <= this.maxLevel ){
levelScale = levelScale =
this.files[ level ].height / this.files[ level ].width /
this.files[ this.maxLevel ].height; this.files[ this.maxLevel ].width;
} }
return levelScale; return levelScale;
}, },
@ -101,9 +101,9 @@ $.LegacyTileSource.prototype = {
py = ( y === 0 ) ? 0 : this.files[ level ].height, py = ( y === 0 ) ? 0 : this.files[ level ].height,
sx = this.files[ level ].width, sx = this.files[ level ].width,
sy = this.files[ level ].height, sy = this.files[ level ].height,
scale = Math.max( scale = 1.0 / ( this.width >= this.height ?
1.0 / dimensionsScaled.x, dimensionsScaled.y :
1.0 / dimensionsScaled.y dimensionsScaled.x
); );
sx = Math.min( sx, dimensionsScaled.x - px ); sx = Math.min( sx, dimensionsScaled.x - px );

View File

@ -466,7 +466,7 @@
function triggerOthers( tracker, handler, event ) { function triggerOthers( tracker, handler, event ) {
var otherHash; var otherHash;
for ( otherHash in ACTIVE ) { for ( otherHash in ACTIVE ) {
if ( trackers.hasOwnProperty( otherHash ) && tracker.hash != otherHash ) { if ( ACTIVE.hasOwnProperty( otherHash ) && tracker.hash != otherHash ) {
handler( ACTIVE[ otherHash ], event ); handler( ACTIVE[ otherHash ], event );
} }
} }
@ -479,13 +479,16 @@
*/ */
function onFocus( tracker, event ){ function onFocus( tracker, event ){
//console.log( "focus %s", event ); //console.log( "focus %s", event );
var propagate;
if ( tracker.focusHandler ) { if ( tracker.focusHandler ) {
try { try {
tracker.focusHandler( propagate = tracker.focusHandler(
tracker, tracker,
event event
); );
$.cancelEvent( event ); if( propagate === false ){
$.cancelEvent( event );
}
} catch ( e ) { } catch ( e ) {
$.console.error( $.console.error(
"%s while executing key handler: %s", "%s while executing key handler: %s",
@ -504,13 +507,16 @@
*/ */
function onBlur( tracker, event ){ function onBlur( tracker, event ){
//console.log( "blur %s", event ); //console.log( "blur %s", event );
var propagate;
if ( tracker.blurHandler ) { if ( tracker.blurHandler ) {
try { try {
tracker.blurHandler( propagate = tracker.blurHandler(
tracker, tracker,
event event
); );
$.cancelEvent( event ); if( propagate === false ){
$.cancelEvent( event );
}
} catch ( e ) { } catch ( e ) {
$.console.error( $.console.error(
"%s while executing key handler: %s", "%s while executing key handler: %s",
@ -537,7 +543,7 @@
event.keyCode ? event.keyCode : event.charCode, event.keyCode ? event.keyCode : event.charCode,
event.shiftKey event.shiftKey
); );
if( !propagate ){ if( propagate === false ){
$.cancelEvent( event ); $.cancelEvent( event );
} }
} catch ( e ) { } catch ( e ) {
@ -559,7 +565,8 @@
function onMouseOver( tracker, event ) { function onMouseOver( tracker, event ) {
var event = $.getEvent( event ), var event = $.getEvent( event ),
delegate = THIS[ tracker.hash ]; delegate = THIS[ tracker.hash ],
propagate;
if ( $.Browser.vendor == $.BROWSERS.IE && if ( $.Browser.vendor == $.BROWSERS.IE &&
delegate.capturing && delegate.capturing &&
@ -585,12 +592,15 @@
if ( tracker.enterHandler ) { if ( tracker.enterHandler ) {
try { try {
tracker.enterHandler( propagate = tracker.enterHandler(
tracker, tracker,
getMouseRelative( event, tracker.element ), getMouseRelative( event, tracker.element ),
delegate.buttonDown, delegate.buttonDown,
IS_BUTTON_DOWN IS_BUTTON_DOWN
); );
if( propagate === false ){
$.cancelEvent( event );
}
} catch ( e ) { } catch ( e ) {
$.console.error( $.console.error(
"%s while executing enter handler: %s", "%s while executing enter handler: %s",
@ -609,7 +619,8 @@
*/ */
function onMouseOut( tracker, event ) { function onMouseOut( tracker, event ) {
var event = $.getEvent( event ), var event = $.getEvent( event ),
delegate = THIS[ tracker.hash ]; delegate = THIS[ tracker.hash ],
propagate;
if ( $.Browser.vendor == $.BROWSERS.IE && if ( $.Browser.vendor == $.BROWSERS.IE &&
delegate.capturing && delegate.capturing &&
@ -635,12 +646,16 @@
if ( tracker.exitHandler ) { if ( tracker.exitHandler ) {
try { try {
tracker.exitHandler( propagate = tracker.exitHandler(
tracker, tracker,
getMouseRelative( event, tracker.element ), getMouseRelative( event, tracker.element ),
delegate.buttonDown, delegate.buttonDown,
IS_BUTTON_DOWN IS_BUTTON_DOWN
); );
if( propagate === false ){
$.cancelEvent( event );
}
} catch ( e ) { } catch ( e ) {
$.console.error( $.console.error(
"%s while executing exit handler: %s", "%s while executing exit handler: %s",
@ -659,7 +674,8 @@
*/ */
function onMouseDown( tracker, event ) { function onMouseDown( tracker, event ) {
var event = $.getEvent( event ), var event = $.getEvent( event ),
delegate = THIS[ tracker.hash ]; delegate = THIS[ tracker.hash ],
propagate;
if ( event.button == 2 ) { if ( event.button == 2 ) {
return; return;
@ -673,10 +689,13 @@
if ( tracker.pressHandler ) { if ( tracker.pressHandler ) {
try { try {
tracker.pressHandler( propagate = tracker.pressHandler(
tracker, tracker,
getMouseRelative( event, tracker.element ) getMouseRelative( event, tracker.element )
); );
if( propagate === false ){
$.cancelEvent( event );
}
} catch (e) { } catch (e) {
$.console.error( $.console.error(
"%s while executing press handler: %s", "%s while executing press handler: %s",
@ -743,7 +762,8 @@
//were we inside the tracked element when we were pressed //were we inside the tracked element when we were pressed
insideElementPress = delegate.buttonDown, insideElementPress = delegate.buttonDown,
//are we still inside the tracked element when we released //are we still inside the tracked element when we released
insideElementRelease = delegate.insideElement; insideElementRelease = delegate.insideElement,
propagate;
if ( event.button == 2 ) { if ( event.button == 2 ) {
return; return;
@ -753,12 +773,15 @@
if ( tracker.releaseHandler ) { if ( tracker.releaseHandler ) {
try { try {
tracker.releaseHandler( propagate = tracker.releaseHandler(
tracker, tracker,
getMouseRelative( event, tracker.element ), getMouseRelative( event, tracker.element ),
insideElementPress, insideElementPress,
insideElementRelease insideElementRelease
); );
if( propagate === false ){
$.cancelEvent( event );
}
} catch (e) { } catch (e) {
$.console.error( $.console.error(
"%s while executing release handler: %s", "%s while executing release handler: %s",
@ -867,7 +890,8 @@
* @inner * @inner
*/ */
function onMouseWheelSpin( tracker, event ) { function onMouseWheelSpin( tracker, event ) {
var nDelta = 0; var nDelta = 0,
propagate;
if ( !event ) { // For IE, access the global (window) event object if ( !event ) { // For IE, access the global (window) event object
event = window.event; event = window.event;
@ -888,12 +912,15 @@
if ( tracker.scrollHandler ) { if ( tracker.scrollHandler ) {
try { try {
tracker.scrollHandler( propagate = tracker.scrollHandler(
tracker, tracker,
getMouseRelative( event, tracker.element ), getMouseRelative( event, tracker.element ),
nDelta, nDelta,
event.shiftKey event.shiftKey
); );
if( propagate === false ){
$.cancelEvent( event );
}
} catch (e) { } catch (e) {
$.console.error( $.console.error(
"%s while executing scroll handler: %s", "%s while executing scroll handler: %s",
@ -902,8 +929,6 @@
e e
); );
} }
$.cancelEvent( event );
} }
}; };
@ -914,7 +939,8 @@
*/ */
function handleMouseClick( tracker, event ) { function handleMouseClick( tracker, event ) {
var event = $.getEvent( event ), var event = $.getEvent( event ),
delegate = THIS[ tracker.hash ]; delegate = THIS[ tracker.hash ],
propagate;
if ( event.button == 2 ) { if ( event.button == 2 ) {
return; return;
@ -928,12 +954,15 @@
if ( tracker.clickHandler ) { if ( tracker.clickHandler ) {
try { try {
tracker.clickHandler( propagate = tracker.clickHandler(
tracker, tracker,
getMouseRelative( event, tracker.element ), getMouseRelative( event, tracker.element ),
quick, quick,
event.shiftKey event.shiftKey
); );
if( propagate === false ){
$.cancelEvent( event );
}
} catch ( e ) { } catch ( e ) {
$.console.error( $.console.error(
"%s while executing click handler: %s", "%s while executing click handler: %s",
@ -954,18 +983,22 @@
var event = $.getEvent( event ), var event = $.getEvent( event ),
delegate = THIS[ tracker.hash ], delegate = THIS[ tracker.hash ],
point = getMouseAbsolute( event ), point = getMouseAbsolute( event ),
delta = point.minus( delegate.lastPoint ); delta = point.minus( delegate.lastPoint ),
propagate;
delegate.lastPoint = point; delegate.lastPoint = point;
if ( tracker.dragHandler ) { if ( tracker.dragHandler ) {
try { try {
tracker.dragHandler( propagate = tracker.dragHandler(
tracker, tracker,
getMouseRelative( event, tracker.element ), getMouseRelative( event, tracker.element ),
delta, delta,
event.shiftKey event.shiftKey
); );
if( propagate === false ){
$.cancelEvent( event );
}
} catch (e) { } catch (e) {
$.console.error( $.console.error(
"%s while executing drag handler: %s", "%s while executing drag handler: %s",
@ -975,7 +1008,6 @@
); );
} }
$.cancelEvent( event );
} }
}; };

View File

@ -63,13 +63,31 @@ $.Navigator = function( options ){
style.cssFloat = 'left'; //Firefox style.cssFloat = 'left'; //Firefox
style.styleFloat = 'left'; //IE style.styleFloat = 'left'; //IE
style.zIndex = 999999999; style.zIndex = 999999999;
style.cursor = 'default';
}( this.displayRegion.style )); }( this.displayRegion.style ));
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 );
this.displayRegion.innerTracker = new $.MouseTracker({ this.displayRegion.innerTracker = new $.MouseTracker({
element: this.displayRegion, element: this.displayRegion,
clickTimeThreshold: this.clickTimeThreshold, clickTimeThreshold: this.clickTimeThreshold,
clickDistThreshold: this.clickDistThreshold, clickDistThreshold: this.clickDistThreshold,
clickHandler: $.delegate( this, onCanvasClick ),
dragHandler: $.delegate( this, onCanvasDrag ),
releaseHandler: $.delegate( this, onCanvasRelease ),
scrollHandler: $.delegate( this, onCanvasScroll ),
focusHandler: function(){ focusHandler: function(){
var point = $.getElementPosition( _this.viewer.element );
window.scrollTo( 0, point.y );
_this.viewer.setControlsEnabled( true ); _this.viewer.setControlsEnabled( true );
(function( style ){ (function( style ){
style.border = '2px solid #437AB2'; style.border = '2px solid #437AB2';
@ -89,12 +107,15 @@ $.Navigator = function( options ){
switch( keyCode ){ switch( keyCode ){
case 61://=|+ case 61://=|+
_this.viewer.viewport.zoomBy(1.1); _this.viewer.viewport.zoomBy(1.1);
_this.viewer.viewport.applyConstraints();
return false; return false;
case 45://-|_ case 45://-|_
_this.viewer.viewport.zoomBy(0.9); _this.viewer.viewport.zoomBy(0.9);
_this.viewer.viewport.applyConstraints();
return false; return false;
case 48://0|) case 48://0|)
_this.viewer.viewport.goHome(); _this.viewer.viewport.goHome();
_this.viewer.viewport.applyConstraints();
return false; return false;
case 119://w case 119://w
case 87://W case 87://W
@ -102,6 +123,7 @@ $.Navigator = function( options ){
shiftKey ? shiftKey ?
_this.viewer.viewport.zoomBy(1.1): _this.viewer.viewport.zoomBy(1.1):
_this.viewer.viewport.panBy(new $.Point(0, -0.05)); _this.viewer.viewport.panBy(new $.Point(0, -0.05));
_this.viewer.viewport.applyConstraints();
return false; return false;
case 115://s case 115://s
case 83://S case 83://S
@ -109,14 +131,17 @@ $.Navigator = function( options ){
shiftKey ? shiftKey ?
_this.viewer.viewport.zoomBy(0.9): _this.viewer.viewport.zoomBy(0.9):
_this.viewer.viewport.panBy(new $.Point(0, 0.05)); _this.viewer.viewport.panBy(new $.Point(0, 0.05));
_this.viewer.viewport.applyConstraints();
return false; return false;
case 97://a case 97://a
case 37://left arrow case 37://left arrow
_this.viewer.viewport.panBy(new $.Point(-0.05, 0)); _this.viewer.viewport.panBy(new $.Point(-0.05, 0));
_this.viewer.viewport.applyConstraints();
return false; return false;
case 100://d case 100://d
case 39://right arrow case 39://right arrow
_this.viewer.viewport.panBy(new $.Point(0.05, 0)); _this.viewer.viewport.panBy(new $.Point(0.05, 0));
_this.viewer.viewport.applyConstraints();
return false; return false;
default: default:
//console.log( 'navigator keycode %s', keyCode ); //console.log( 'navigator keycode %s', keyCode );
@ -157,23 +182,73 @@ $.extend( $.Navigator.prototype, $.EventHandler.prototype, $.Viewer.prototype, {
update: function( viewport ){ update: function( viewport ){
var bounds = viewport.getBounds( true ), var bounds,
topleft = this.viewport.pixelFromPoint( bounds.getTopLeft() ) topleft,
bottomright;
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() );
//update style for navigator-box //update style for navigator-box
(function(style){ (function(style){
style.top = topleft.y + 'px'; style.top = topleft.y + 'px';
style.left = topleft.x + 'px'; style.left = topleft.x + 'px';
style.width = ( Math.abs( topleft.x - bottomright.x ) - 3 ) + 'px'; style.width = ( Math.abs( topleft.x - bottomright.x ) - 3 ) + 'px';
style.height = ( Math.abs( topleft.y - bottomright.y ) - 3 ) + 'px'; style.height = ( Math.abs( topleft.y - bottomright.y ) - 3 ) + 'px';
}( this.displayRegion.style )); }( this.displayRegion.style ));
}
} }
}); });
function onCanvasClick( tracker, position, quick, shift ) {
this.displayRegion.focus();
};
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
)
);
}
};
function onCanvasRelease( tracker, position, insideElementPress, insideElementRelease ) {
if ( insideElementPress && this.viewer.viewport ) {
this.viewer.viewport.applyConstraints();
}
};
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;
};
}( OpenSeadragon )); }( OpenSeadragon ));

View File

@ -188,6 +188,12 @@
* interactions include draging the image in a plane, and zooming in toward * interactions include draging the image in a plane, and zooming in toward
* and away from the image. * and away from the image.
* *
* @param {Boolean} [options.preserveViewport=false]
* If the viewer has been configured with a sequence of tile sources, then
* normally navigating to through each image resets the viewport to 'home'
* position. If preserveViewport is set to true, then the viewport position
* is preserved when navigating between images in the sequence.
*
* @param {String} [options.prefixUrl=''] * @param {String} [options.prefixUrl='']
* Appends the prefixUrl to navImages paths, which is very useful * Appends the prefixUrl to navImages paths, which is very useful
* since the default paths are rarely useful for production * since the default paths are rarely useful for production
@ -428,43 +434,50 @@ OpenSeadragon = window.OpenSeadragon || function( options ){
* @static * @static
*/ */
DEFAULT_SETTINGS: { DEFAULT_SETTINGS: {
xmlPath: null, //DATA SOURCE DETAILS
tileSources: null, xmlPath: null,
debugMode: true, tileSources: null,
animationTime: 1.5, tileHost: null,
blendTime: 0.5,
alwaysBlend: false, //INTERFACE FEATURES
autoHideControls: true, debugMode: true,
immediateRender: false, animationTime: 1.5,
wrapHorizontal: false, blendTime: 0.5,
wrapVertical: false, alwaysBlend: false,
minZoomImageRatio: 0.8, autoHideControls: true,
maxZoomPixelRatio: 2, immediateRender: false,
visibilityRatio: 0.5, wrapHorizontal: false,
springStiffness: 5.0, wrapVertical: false,
imageLoaderLimit: 0, panHorizontal: true,
clickTimeThreshold: 200, panVertical: true,
clickDistThreshold: 5, visibilityRatio: 0.5,
zoomPerClick: 2.0, springStiffness: 5.0,
zoomPerScroll: 1.2, clickTimeThreshold: 200,
zoomPerSecond: 2.0, clickDistThreshold: 5,
showNavigationControl: true, zoomPerClick: 2.0,
zoomPerScroll: 1.2,
showNavigator: false, zoomPerSecond: 2.0,
navigatorElement: null, showNavigationControl: true,
navigatorHeight: null, controlsFadeDelay: 2000,
navigatorWidth: null, controlsFadeLength: 1500,
navigatorPosition: null, mouseNavEnabled: true,
navigatorSizeRatio: 0.25, showNavigator: false,
navigatorElement: null,
navigatorHeight: null,
navigatorWidth: null,
navigatorPosition: null,
navigatorSizeRatio: 0.25,
preserveViewport: false,
//These two were referenced but never defined //PERFORMANCE SETTINGS
controlsFadeDelay: 2000, minPixelRatio: 0.5,
controlsFadeLength: 1500, imageLoaderLimit: 0,
maxImageCacheCount: 200,
minZoomImageRatio: 0.9,
maxZoomPixelRatio: 2,
maxImageCacheCount: 200, //INTERFACE RESOURCE SETTINGS
minPixelRatio: 0.5, prefixUrl: null,
mouseNavEnabled: true,
prefixUrl: null,
navImages: { navImages: {
zoomIn: { zoomIn: {
REST: '/images/zoomin_rest.png', REST: '/images/zoomin_rest.png',
@ -489,6 +502,18 @@ OpenSeadragon = window.OpenSeadragon || function( options ){
GROUP: '/images/fullpage_grouphover.png', GROUP: '/images/fullpage_grouphover.png',
HOVER: '/images/fullpage_hover.png', HOVER: '/images/fullpage_hover.png',
DOWN: '/images/fullpage_pressed.png' DOWN: '/images/fullpage_pressed.png'
},
previous: {
REST: '/images/previous_rest.png',
GROUP: '/images/previous_grouphover.png',
HOVER: '/images/previous_hover.png',
DOWN: '/images/previous_pressed.png'
},
next: {
REST: '/images/next_rest.png',
GROUP: '/images/next_grouphover.png',
HOVER: '/images/next_hover.png',
DOWN: '/images/next_pressed.png'
} }
} }
}, },
@ -1192,7 +1217,7 @@ OpenSeadragon = window.OpenSeadragon || function( options ){
* @param {String} xmlString * @param {String} xmlString
* @param {Function} callback * @param {Function} callback
*/ */
createFromDZI: function( dzi, callback ) { createFromDZI: function( dzi, callback, tileHost ) {
var async = typeof ( callback ) == "function", var async = typeof ( callback ) == "function",
xmlUrl = dzi.substring(0,1) != '<' ? dzi : null, xmlUrl = dzi.substring(0,1) != '<' ? dzi : null,
xmlString = xmlUrl ? null : dzi, xmlString = xmlUrl ? null : dzi,
@ -1203,7 +1228,12 @@ OpenSeadragon = window.OpenSeadragon || function( options ){
tilesUrl; tilesUrl;
if( xmlUrl ){ if( tileHost ){
tilesUrl = tileHost + "/_files/";
} else if( xmlUrl ) {
urlParts = xmlUrl.split( '/' ); urlParts = xmlUrl.split( '/' );
filename = urlParts[ urlParts.length - 1 ]; filename = urlParts[ urlParts.length - 1 ];
lastDot = filename.lastIndexOf( '.' ); lastDot = filename.lastIndexOf( '.' );
@ -1213,6 +1243,7 @@ OpenSeadragon = window.OpenSeadragon || function( options ){
} }
tilesUrl = urlParts.join( '/' ) + "_files/"; tilesUrl = urlParts.join( '/' ) + "_files/";
} }
function finish( func, obj ) { function finish( func, obj ) {

View File

@ -6,28 +6,30 @@
// pythons gettext might be a reasonable approach. // pythons gettext might be a reasonable approach.
var I18N = { var I18N = {
Errors: { Errors: {
Failure: "Sorry, but Seadragon Ajax can't run on your browser!\n" + Failure: "Sorry, but Seadragon Ajax can't run on your browser!\n" +
"Please try using IE 7 or Firefox 3.\n", "Please try using IE 7 or Firefox 3.\n",
Dzc: "Sorry, we don't support Deep Zoom Collections!", Dzc: "Sorry, we don't support Deep Zoom Collections!",
Dzi: "Hmm, this doesn't appear to be a valid Deep Zoom Image.", Dzi: "Hmm, this doesn't appear to be a valid Deep Zoom Image.",
Xml: "Hmm, this doesn't appear to be a valid Deep Zoom Image.", Xml: "Hmm, this doesn't appear to be a valid Deep Zoom Image.",
Empty: "You asked us to open nothing, so we did just that.", Empty: "You asked us to open nothing, so we did just that.",
ImageFormat: "Sorry, we don't support {0}-based Deep Zoom Images.", ImageFormat: "Sorry, we don't support {0}-based Deep Zoom Images.",
Security: "It looks like a security restriction stopped us from " + Security: "It looks like a security restriction stopped us from " +
"loading this Deep Zoom Image.", "loading this Deep Zoom Image.",
Status: "This space unintentionally left blank ({0} {1}).", Status: "This space unintentionally left blank ({0} {1}).",
Unknown: "Whoops, something inexplicably went wrong. Sorry!" Unknown: "Whoops, something inexplicably went wrong. Sorry!"
}, },
Messages: { Messages: {
Loading: "Loading..." Loading: "Loading..."
}, },
Tooltips: { Tooltips: {
FullPage: "Toggle full page", FullPage: "Toggle full page",
Home: "Go home", Home: "Go home",
ZoomIn: "Zoom in", ZoomIn: "Zoom in",
ZoomOut: "Zoom out" ZoomOut: "Zoom out",
NextPage: "Next page",
PreviousPage: "Previous page"
} }
}; };
@ -41,12 +43,13 @@ $.extend( $, {
getString: function( prop ) { getString: function( prop ) {
var props = prop.split('.'), var props = prop.split('.'),
string = I18N, string = null,
args = arguments, args = arguments,
i; i;
for ( i = 0; i < props.length; i++ ) { for ( i = 0; i < props.length; i++ ) {
string = string[ props[ i ] ] || {}; // in case not a subproperty // in case not a subproperty
string = I18N[ props[ i ] ] || {};
} }
if ( typeof( string ) != "string" ) { if ( typeof( string ) != "string" ) {

View File

@ -45,7 +45,7 @@ $.Tile = function(level, x, y, bounds, exists, url) {
this.loading = false; this.loading = false;
this.element = null; this.element = null;
this.image = null; this.image = null;
this.style = null; this.style = null;
this.position = null; this.position = null;
@ -81,7 +81,7 @@ $.Tile.prototype = {
var position = this.position.apply( Math.floor ), var position = this.position.apply( Math.floor ),
size = this.size.apply( Math.ceil ); size = this.size.apply( Math.ceil );
if ( !this.loaded ) { if ( !this.loaded || !this.image ) {
$.console.warn( $.console.warn(
"Attempting to draw tile %s when it's not yet loaded.", "Attempting to draw tile %s when it's not yet loaded.",
this.toString() this.toString()
@ -90,9 +90,9 @@ $.Tile.prototype = {
} }
if ( !this.element ) { if ( !this.element ) {
this.element = $.makeNeutralElement("img"); this.element = $.makeNeutralElement("img");
this.element.src = this.url; this.element.src = this.url;
this.style = this.element.style; this.style = this.element.style;
this.style.position = "absolute"; this.style.position = "absolute";
this.style.msInterpolationMode = "nearest-neighbor"; this.style.msInterpolationMode = "nearest-neighbor";
@ -122,14 +122,13 @@ $.Tile.prototype = {
var position = this.position, var position = this.position,
size = this.size; size = this.size;
if ( !this.loaded ) { if ( !this.loaded || !this.image ) {
$.console.warn( $.console.warn(
"Attempting to draw tile %s when it's not yet loaded.", "Attempting to draw tile %s when it's not yet loaded.",
this.toString() this.toString()
); );
return; return;
} }
context.globalAlpha = this.opacity; context.globalAlpha = this.opacity;
context.drawImage( this.image, position.x, position.y, size.x, size.y ); context.drawImage( this.image, position.x, position.y, size.x, size.y );
}, },

View File

@ -59,16 +59,25 @@ $.Viewer = function( options ) {
delete options.config; delete options.config;
} }
//Public properties
//Allow the options object to override global defaults //Allow the options object to override global defaults
$.extend( true, this, { $.extend( true, this, {
id: options.id, //internal state and dom identifiers
hash: options.id, id: options.id,
overlays: [], hash: options.id,
overlayControls: [],
//dom nodes
element: null,
canvas: null,
container: null,
//TODO: not sure how to best describe these
overlays: [],
overlayControls:[],
//private state properties //private state properties
previousBody: [], previousBody: [],
//This was originally initialized in the constructor and so could never //This was originally initialized in the constructor and so could never
//have anything in it. now it can because we allow it to be specified //have anything in it. now it can because we allow it to be specified
@ -84,13 +93,76 @@ $.Viewer = function( options ) {
drawer: null, drawer: null,
viewport: null, viewport: null,
navigator: null, navigator: null,
//UI image resources
//TODO: rename navImages to uiImages
navImages: null,
//interface button controls
buttons: null,
//TODO: this is defunct so safely remove it
profiler: null profiler: null
}, $.DEFAULT_SETTINGS, options ); }, $.DEFAULT_SETTINGS, options );
//Private state properties
THIS[ this.hash ] = {
"fsBoundsDelta": new $.Point( 1, 1 ),
"prevContainerSize": null,
"lastOpenStartTime": 0,
"lastOpenEndTime": 0,
"animating": false,
"forceRedraw": false,
"mouseInside": false,
"group": null,
// whether we should be continuously zooming
"zooming": false,
// how much we should be continuously zooming by
"zoomFactor": null,
"lastZoomTime": null,
// did we decide this viewer has a sequence of tile sources
"sequenced": false,
"sequence": 0
};
//Inherit some behaviors and properties
$.EventHandler.call( this ); $.EventHandler.call( this );
$.ControlDock.call( this, options ); $.ControlDock.call( this, options );
//Deal with tile sources
var initialTileSource,
customTileSource;
if ( this.xmlPath ){
//Deprecated option. Now it is preferred to use the tileSources option
this.tileSources = [ this.xmlPath ];
}
if ( this.tileSources ){
//tileSources is a complex option...
//It can be a string, object, function, or an array of any of these.
// - A String implies a DZI
// - An Srray of Objects implies a simple image
// - A Function implies a custom tile source callback
// - An Array that is not an Array of simple Objects implies a sequence
// of tile sources which can be any of the above
if( $.isArray( this.tileSources ) ){
if( $.isPlainObject( this.tileSources[ 0 ] ) ){
//This is a non-sequenced legacy tile source
initialTileSource = this.tileSources;
} else {
//Sequenced tile source
initialTileSource = this.tileSources[ 0 ];
THIS[ this.hash ].sequenced = true;
}
} else {
initialTileSource = this.tileSources;
}
this.openTileSource( initialTileSource );
}
this.element = this.element || document.getElementById( this.id ); this.element = this.element || document.getElementById( this.id );
this.canvas = $.makeNeutralElement( "div" ); this.canvas = $.makeNeutralElement( "div" );
@ -112,7 +184,7 @@ $.Viewer = function( options ) {
container.textAlign = "left"; // needed to protect against container.textAlign = "left"; // needed to protect against
}( this.container.style )); }( this.container.style ));
this.container.insertBefore( this.canvas, this.container.firstChild); this.container.insertBefore( this.canvas, this.container.firstChild );
this.element.appendChild( this.container ); this.element.appendChild( this.container );
//Used for toggling between fullscreen and default container size //Used for toggling between fullscreen and default container size
@ -123,16 +195,6 @@ $.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[ this.hash ] = {
"fsBoundsDelta": new $.Point( 1, 1 ),
"prevContainerSize": null,
"lastOpenStartTime": 0,
"lastOpenEndTime": 0,
"animating": false,
"forceRedraw": false,
"mouseInside": false
};
this.innerTracker = new $.MouseTracker({ this.innerTracker = new $.MouseTracker({
element: this.canvas, element: this.canvas,
clickTimeThreshold: this.clickTimeThreshold, clickTimeThreshold: this.clickTimeThreshold,
@ -153,16 +215,6 @@ $.Viewer = function( options ) {
}).setTracking( this.mouseNavEnabled ? true : false ); // always tracking }).setTracking( this.mouseNavEnabled ? true : false ); // always tracking
//private state properties
$.extend( THIS[ this.hash ], {
"group": null,
// whether we should be continuously zooming
"zooming": false,
// how much we should be continuously zooming by
"zoomFactor": null,
"lastZoomTime": null
});
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Navigation Controls // Navigation Controls
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -175,16 +227,15 @@ $.Viewer = function( options ) {
onFullPageHandler = $.delegate( this, onFullPage ), onFullPageHandler = $.delegate( this, onFullPage ),
onFocusHandler = $.delegate( this, onFocus ), onFocusHandler = $.delegate( this, onFocus ),
onBlurHandler = $.delegate( this, onBlur ), onBlurHandler = $.delegate( this, onBlur ),
navImages = this.navImages; onNextHandler = $.delegate( this, onNext ),
onPreviousHandler = $.delegate( this, onPrevious ),
navImages = this.navImages,
buttons = [];
this.zoomInButton = null;
this.zoomOutButton = null;
this.goHomeButton = null;
this.fullPageButton = null;
if( this.showNavigationControl ){ if( this.showNavigationControl ){
this.zoomInButton = new $.Button({ buttons.push( this.zoomInButton = new $.Button({
clickTimeThreshold: this.clickTimeThreshold, clickTimeThreshold: this.clickTimeThreshold,
clickDistThreshold: this.clickDistThreshold, clickDistThreshold: this.clickDistThreshold,
tooltip: $.getString( "Tooltips.ZoomIn" ), tooltip: $.getString( "Tooltips.ZoomIn" ),
@ -199,9 +250,9 @@ $.Viewer = function( options ) {
onExit: endZoomingHandler, onExit: endZoomingHandler,
onFocus: onFocusHandler, onFocus: onFocusHandler,
onBlur: onBlurHandler onBlur: onBlurHandler
}); }));
this.zoomOutButton = new $.Button({ buttons.push( this.zoomOutButton = new $.Button({
clickTimeThreshold: this.clickTimeThreshold, clickTimeThreshold: this.clickTimeThreshold,
clickDistThreshold: this.clickDistThreshold, clickDistThreshold: this.clickDistThreshold,
tooltip: $.getString( "Tooltips.ZoomOut" ), tooltip: $.getString( "Tooltips.ZoomOut" ),
@ -216,9 +267,9 @@ $.Viewer = function( options ) {
onExit: endZoomingHandler, onExit: endZoomingHandler,
onFocus: onFocusHandler, onFocus: onFocusHandler,
onBlur: onBlurHandler onBlur: onBlurHandler
}); }));
this.goHomeButton = new $.Button({ buttons.push( this.homeButton = new $.Button({
clickTimeThreshold: this.clickTimeThreshold, clickTimeThreshold: this.clickTimeThreshold,
clickDistThreshold: this.clickDistThreshold, clickDistThreshold: this.clickDistThreshold,
tooltip: $.getString( "Tooltips.Home" ), tooltip: $.getString( "Tooltips.Home" ),
@ -229,9 +280,9 @@ $.Viewer = function( options ) {
onRelease: onHomeHandler, onRelease: onHomeHandler,
onFocus: onFocusHandler, onFocus: onFocusHandler,
onBlur: onBlurHandler onBlur: onBlurHandler
}); }));
this.fullPageButton = new $.Button({ buttons.push( this.fullPageButton = new $.Button({
clickTimeThreshold: this.clickTimeThreshold, clickTimeThreshold: this.clickTimeThreshold,
clickDistThreshold: this.clickDistThreshold, clickDistThreshold: this.clickDistThreshold,
tooltip: $.getString( "Tooltips.FullPage" ), tooltip: $.getString( "Tooltips.FullPage" ),
@ -242,17 +293,44 @@ $.Viewer = function( options ) {
onRelease: onFullPageHandler, onRelease: onFullPageHandler,
onFocus: onFocusHandler, onFocus: onFocusHandler,
onBlur: onBlurHandler onBlur: onBlurHandler
}); }));
this.buttons = new $.ButtonGroup({ if( THIS[ this.hash ].sequenced ){
buttons.push( this.previousButton = new $.Button({
clickTimeThreshold: this.clickTimeThreshold,
clickDistThreshold: this.clickDistThreshold,
tooltip: $.getString( "Tooltips.PreviousPage" ),
srcRest: resolveUrl( this.prefixUrl, navImages.previous.REST ),
srcGroup: resolveUrl( this.prefixUrl, navImages.previous.GROUP ),
srcHover: resolveUrl( this.prefixUrl, navImages.previous.HOVER ),
srcDown: resolveUrl( this.prefixUrl, navImages.previous.DOWN ),
onRelease: onPreviousHandler,
onFocus: onFocusHandler,
onBlur: onBlurHandler
}));
buttons.push( this.nextButton = new $.Button({
clickTimeThreshold: this.clickTimeThreshold,
clickDistThreshold: this.clickDistThreshold,
tooltip: $.getString( "Tooltips.NextPage" ),
srcRest: resolveUrl( this.prefixUrl, navImages.next.REST ),
srcGroup: resolveUrl( this.prefixUrl, navImages.next.GROUP ),
srcHover: resolveUrl( this.prefixUrl, navImages.next.HOVER ),
srcDown: resolveUrl( this.prefixUrl, navImages.next.DOWN ),
onRelease: onNextHandler,
onFocus: onFocusHandler,
onBlur: onBlurHandler
}));
this.previousButton.disable();
}
this.buttons = new $.ButtonGroup({
buttons: buttons,
clickTimeThreshold: this.clickTimeThreshold, clickTimeThreshold: this.clickTimeThreshold,
clickDistThreshold: this.clickDistThreshold, clickDistThreshold: this.clickDistThreshold
buttons: [
this.zoomInButton,
this.zoomOutButton,
this.goHomeButton,
this.fullPageButton
]
}); });
this.navControl = this.buttons.element; this.navControl = this.buttons.element;
@ -274,73 +352,10 @@ $.Viewer = function( options ) {
); );
} }
//Instantiate a navigator if configured
if ( this.showNavigator ){
this.navigator = new $.Navigator({
id: this.navigatorElement,
position: this.navigatorPosition,
sizeRatio: this.navigatorSizeRatio,
height: this.navigatorHeight,
width: this.navigatorWidth,
tileSources: this.tileSources,
prefixUrl: this.prefixUrl,
overlays: this.overlays,
viewer: this
});
}
window.setTimeout( function(){ window.setTimeout( function(){
beginControlsAutoHide( _this ); beginControlsAutoHide( _this );
}, 1 ); // initial fade out }, 1 ); // initial fade out
var initialTileSource,
customTileSource;
if ( this.xmlPath ){
//Deprecated option. Now it is preferred to use the tileSources option
this.tileSources = [ this.xmlPath ];
}
if ( this.tileSources ){
//tileSource is a complex option...
//It can be a string, object, function, or an array of any of these.
//A string implies a DZI
//An object implies a simple image
//A function implies a custom tile source callback
//An array implies a sequence of tile sources which can be any of the
//above
if( $.isArray( this.tileSources ) ){
if( $.isPlainObject( this.tileSources[ 0 ] ) ){
//This is a non-sequenced legacy tile source
initialTileSource = this.tileSources;
} else {
//Sequenced tile source
initialTileSource = this.tileSources[ 0 ];
}
} else {
initialTileSource = this.tileSources
}
if ( $.type( initialTileSource ) == 'string') {
//Standard DZI format
this.openDzi( initialTileSource );
} else if ( $.isArray( initialTileSource ) ){
//Legacy image pyramid
this.open( new $.LegacyTileSource( initialTileSource ) );
} else if ( $.isPlainObject( initialTileSource ) && $.isFunction( initialTileSource.getTileUrl ) ){
//Custom tile source
customTileSource = new $.TileSource(
initialTileSource.width,
initialTileSource.height,
initialTileSource.tileSize,
initialTileSource.tileOverlap,
initialTileSource.minLevel,
initialTileSource.maxLevel
);
customTileSource.getTileUrl = initialTileSource.getTileUrl;
this.open( customTileSource );
}
}
}; };
$.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype, { $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype, {
@ -370,7 +385,8 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
dzi, dzi,
function( source ){ function( source ){
_this.open( source ); _this.open( source );
} },
this.tileHost
); );
return this; return this;
}, },
@ -381,10 +397,34 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
* @return {OpenSeadragon.Viewer} Chainable. * @return {OpenSeadragon.Viewer} Chainable.
*/ */
openTileSource: function ( tileSource ) { openTileSource: function ( tileSource ) {
var _this = this; var _this = this,
window.setTimeout( function () { customTileSource;
_this.open( tileSource );
}, 1 ); setTimeout(function(){
if ( $.type( tileSource ) == 'string') {
//Standard DZI format
_this.openDzi( tileSource );
} else if ( $.isArray( tileSource ) ){
//Legacy image pyramid
_this.open( new $.LegacyTileSource( tileSource ) );
} else if ( $.isPlainObject( tileSource ) && $.isFunction( tileSource.getTileUrl ) ){
//Custom tile source
customTileSource = new $.TileSource(
tileSource.width,
tileSource.height,
tileSource.tileSize,
tileSource.tileOverlap,
tileSource.minLevel,
tileSource.maxLevel
);
customTileSource.getTileUrl = tileSource.getTileUrl;
_this.open( customTileSource );
} else {
//can assume it's already a tile source implementation
_this.open( tileSource );
}
}, 1);
return this; return this;
}, },
@ -399,7 +439,7 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
i; i;
if ( this.source ) { if ( this.source ) {
this.close(); this.close( );
} }
// to ignore earlier opens // to ignore earlier opens
@ -419,7 +459,7 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
this.source = source; this.source = source;
} }
this.viewport = new $.Viewport({ this.viewport = this.viewport ? this.viewport : new $.Viewport({
containerSize: THIS[ this.hash ].prevContainerSize, containerSize: THIS[ this.hash ].prevContainerSize,
contentSize: this.source.dimensions, contentSize: this.source.dimensions,
springStiffness: this.springStiffness, springStiffness: this.springStiffness,
@ -430,6 +470,9 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
wrapHorizontal: this.wrapHorizontal, wrapHorizontal: this.wrapHorizontal,
wrapVertical: this.wrapVertical wrapVertical: this.wrapVertical
}); });
if( this.preserveVewport ){
this.viewport.resetContentSize( this.source.dimensions );
}
this.drawer = new $.Drawer({ this.drawer = new $.Drawer({
source: this.source, source: this.source,
@ -447,6 +490,22 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
minPixelRatio: this.minPixelRatio minPixelRatio: this.minPixelRatio
}); });
//Instantiate a navigator if configured
if ( this.showNavigator && ! this.navigator ){
this.navigator = new $.Navigator({
id: this.navigatorElement,
position: this.navigatorPosition,
sizeRatio: this.navigatorSizeRatio,
height: this.navigatorHeight,
width: this.navigatorWidth,
tileSources: this.tileSources,
tileHost: this.tileHost,
prefixUrl: this.prefixUrl,
overlays: this.overlays,
viewer: this
});
}
//this.profiler = new $.Profiler(); //this.profiler = new $.Profiler();
THIS[ this.hash ].animating = false; THIS[ this.hash ].animating = false;
@ -487,6 +546,11 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
} }
VIEWERS[ this.hash ] = this; VIEWERS[ this.hash ] = this;
this.raiseEvent( "open" ); this.raiseEvent( "open" );
if( this.navigator ){
this.navigator.open( source );
}
return this; return this;
}, },
@ -495,10 +559,10 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
* @name OpenSeadragon.Viewer.prototype.close * @name OpenSeadragon.Viewer.prototype.close
* @return {OpenSeadragon.Viewer} Chainable. * @return {OpenSeadragon.Viewer} Chainable.
*/ */
close: function () { close: function ( ) {
this.source = null; this.source = null;
this.viewport = null;
this.drawer = null; this.drawer = null;
this.viewport = this.preserveViewport ? this.viewport : null;
//this.profiler = null; //this.profiler = null;
this.canvas.innerHTML = ""; this.canvas.innerHTML = "";
@ -722,6 +786,9 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
viewer = VIEWERS[ hash ]; viewer = VIEWERS[ hash ];
if( viewer !== this && viewer != this.navigator ){ if( viewer !== this && viewer != this.navigator ){
viewer.open( viewer.source ); viewer.open( viewer.source );
if( viewer.navigator ){
viewer.navigator.open( viewer.source );
}
} }
} }
} }
@ -757,10 +824,11 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
}); });
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Schedulers provide the general engine for animation // Schedulers provide the general engine for animation
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
function scheduleUpdate( viewer, updateFunc, prevUpdateTime ){ function scheduleUpdate( viewer, updateFunc, prevUpdateTime ){
var currentTime, var currentTime,
targetTime, targetTime,
@ -783,6 +851,7 @@ function scheduleUpdate( viewer, updateFunc, prevUpdateTime ){
}, deltaTime ); }, deltaTime );
}; };
//provides a sequence in the fade animation //provides a sequence in the fade animation
function scheduleControlsFade( viewer ) { function scheduleControlsFade( viewer ) {
window.setTimeout( function(){ window.setTimeout( function(){
@ -790,6 +859,7 @@ function scheduleControlsFade( viewer ) {
}, 20); }, 20);
}; };
//initiates an animation to hide the controls //initiates an animation to hide the controls
function beginControlsAutoHide( viewer ) { function beginControlsAutoHide( viewer ) {
if ( !viewer.autoHideControls ) { if ( !viewer.autoHideControls ) {
@ -831,6 +901,7 @@ function updateControlsFade( viewer ) {
} }
}; };
//stop the fade animation on the controls and show them //stop the fade animation on the controls and show them
function abortControlsAutoHide( viewer ) { function abortControlsAutoHide( viewer ) {
var i; var i;
@ -841,6 +912,7 @@ function abortControlsAutoHide( viewer ) {
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Default view event handlers. // Default view event handlers.
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -869,6 +941,12 @@ function onCanvasClick( tracker, position, quick, shift ) {
function onCanvasDrag( tracker, position, delta, shift ) { function onCanvasDrag( tracker, position, delta, shift ) {
if ( this.viewport ) { if ( this.viewport ) {
if( !this.panHorizontal ){
delta.x = 0;
}
if( !this.panVertical ){
delta.y = 0;
}
this.viewport.panBy( this.viewport.panBy(
this.viewport.deltaPointsFromPixels( this.viewport.deltaPointsFromPixels(
delta.negate() delta.negate()
@ -893,6 +971,8 @@ function onCanvasScroll( tracker, position, scroll, shift ) {
); );
this.viewport.applyConstraints(); this.viewport.applyConstraints();
} }
//cancels event
return false;
}; };
function onContainerExit( tracker, position, buttonDownElement, buttonDownAny ) { function onContainerExit( tracker, position, buttonDownElement, buttonDownAny ) {
@ -988,36 +1068,42 @@ function updateOnce( viewer ) {
//viewer.profiler.endUpdate(); //viewer.profiler.endUpdate();
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Navigation Controls // Navigation Controls
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
function resolveUrl( prefix, url ) { function resolveUrl( prefix, url ) {
return prefix ? prefix + url : url; return prefix ? prefix + url : url;
}; };
function beginZoomingIn() { function beginZoomingIn() {
THIS[ this.hash ].lastZoomTime = +new Date(); THIS[ this.hash ].lastZoomTime = +new Date();
THIS[ this.hash ].zoomFactor = this.zoomPerSecond; THIS[ this.hash ].zoomFactor = this.zoomPerSecond;
THIS[ this.hash ].zooming = true; THIS[ this.hash ].zooming = true;
scheduleZoom( this ); scheduleZoom( this );
} };
function beginZoomingOut() { function beginZoomingOut() {
THIS[ this.hash ].lastZoomTime = +new Date(); THIS[ this.hash ].lastZoomTime = +new Date();
THIS[ this.hash ].zoomFactor = 1.0 / this.zoomPerSecond; THIS[ this.hash ].zoomFactor = 1.0 / this.zoomPerSecond;
THIS[ this.hash ].zooming = true; THIS[ this.hash ].zooming = true;
scheduleZoom( this ); scheduleZoom( this );
} };
function endZooming() { function endZooming() {
THIS[ this.hash ].zooming = false; THIS[ this.hash ].zooming = false;
} };
function scheduleZoom( viewer ) { function scheduleZoom( viewer ) {
window.setTimeout( $.delegate( viewer, doZoom ), 10 ); window.setTimeout( $.delegate( viewer, doZoom ), 10 );
} };
function doZoom() { function doZoom() {
var currentTime, var currentTime,
@ -1036,6 +1122,7 @@ function doZoom() {
} }
}; };
function doSingleZoomIn() { function doSingleZoomIn() {
if ( this.viewport ) { if ( this.viewport ) {
THIS[ this.hash ].zooming = false; THIS[ this.hash ].zooming = false;
@ -1046,6 +1133,7 @@ function doSingleZoomIn() {
} }
}; };
function doSingleZoomOut() { function doSingleZoomOut() {
if ( this.viewport ) { if ( this.viewport ) {
THIS[ this.hash ].zooming = false; THIS[ this.hash ].zooming = false;
@ -1056,17 +1144,20 @@ function doSingleZoomOut() {
} }
}; };
function lightUp() { function lightUp() {
this.buttons.emulateEnter(); this.buttons.emulateEnter();
this.buttons.emulateExit(); this.buttons.emulateExit();
}; };
function onHome() { function onHome() {
if ( this.viewport ) { if ( this.viewport ) {
this.viewport.goHome(); this.viewport.goHome();
} }
}; };
function onFullPage() { function onFullPage() {
this.setFullPage( !this.isFullPage() ); this.setFullPage( !this.isFullPage() );
// correct for no mouseout event on change // correct for no mouseout event on change
@ -1077,4 +1168,47 @@ function onFullPage() {
} }
}; };
function onPrevious(){
var previous = THIS[ this.hash ].sequence - 1,
preserveVewport = true;
if( previous >= 0 ){
THIS[ this.hash ].sequence = previous;
if( 0 === previous ){
//Disable previous button
this.previousButton.disable();
}
if( this.tileSources.length > 0 ){
//Enable next button
this.nextButton.enable();
}
this.openTileSource( this.tileSources[ previous ] );
}
};
function onNext(){
var next = THIS[ this.hash ].sequence + 1,
preserveVewport = true;
if( this.tileSources.length > next ){
THIS[ this.hash ].sequence = next;
if( ( this.tileSources.length - 1 ) === next ){
//Disable next button
this.nextButton.disable();
}
if( next > 0 ){
//Enable previous button
this.previousButton.enable();
}
this.openTileSource( this.tileSources[ next ] );
}
};
}( OpenSeadragon )); }( OpenSeadragon ));

View File

@ -46,9 +46,6 @@ $.Viewport = function( options ) {
}, options ); }, options );
this.contentAspect = this.contentSize.x / this.contentSize.y;
this.contentHeight = this.contentSize.y / this.contentSize.x;
this.centerSpringX = new $.Spring({ this.centerSpringX = new $.Spring({
initial: 0, initial: 0,
springStiffness: this.springStiffness, springStiffness: this.springStiffness,
@ -64,19 +61,39 @@ $.Viewport = function( options ) {
springStiffness: this.springStiffness, springStiffness: this.springStiffness,
animationTime: this.animationTime animationTime: this.animationTime
}); });
this.homeBounds = new $.Rect( 0, 0, 1, this.contentHeight );
this.resetContentSize( this.contentSize );
this.goHome( true ); this.goHome( true );
//this.fitHorizontally( true );
this.update(); this.update();
}; };
$.Viewport.prototype = { $.Viewport.prototype = {
resetContentSize: function( contentSize ){
this.contentSize = contentSize;
this.contentAspectX = this.contentSize.x / this.contentSize.y;
this.contentAspectY = this.contentSize.y / this.contentSize.x;
this.homeBounds = new $.Rect(
0,
0,
1,
this.contentAspectY
);
this.fitWidthBounds = new $.Rect( 0, 0, 1, this.contentAspectX );
this.fitHeightBounds = new $.Rect( 0, 0, 1, this.contentAspectY );
},
/** /**
* @function * @function
*/ */
getHomeZoom: function() { getHomeZoom: function() {
var aspectFactor = this.contentAspect / this.getAspectRatio();
var aspectFactor = Math.min(
this.contentAspectX,
this.contentAspectY
) / this.getAspectRatio();
return ( aspectFactor >= 1 ) ? return ( aspectFactor >= 1 ) ?
1 : 1 :
aspectFactor; aspectFactor;
@ -229,7 +246,7 @@ $.Viewport.prototype = {
left = bounds.x + bounds.width; left = bounds.x + bounds.width;
right = 1 - bounds.x; right = 1 - bounds.x;
top = bounds.y + bounds.height; top = bounds.y + bounds.height;
bottom = this.contentHeight - bounds.y; bottom = this.contentAspectY - bounds.y;
if ( this.wrapHorizontal ) { if ( this.wrapHorizontal ) {
//do nothing //do nothing
@ -311,15 +328,22 @@ $.Viewport.prototype = {
this.containerSize.x / newBounds.width this.containerSize.x / newBounds.width
); );
this.zoomTo( newZoom, referencePoint, immediately ); this.zoomTo( newZoom, referencePoint, immediately );
}, },
/**
* @function
* @param {Boolean} immediately
*/
goHome: function( immediately ) {
return this.fitVertically( immediately );
},
/** /**
* @function * @function
* @param {Boolean} immediately * @param {Boolean} immediately
*/ */
goHome: function( immediately ) { fitVertically: function( immediately ) {
var center = this.getCenter(); var center = this.getCenter();
if ( this.wrapHorizontal ) { if ( this.wrapHorizontal ) {
@ -330,8 +354,8 @@ $.Viewport.prototype = {
if ( this.wrapVertical ) { if ( this.wrapVertical ) {
center.y = ( center.y = (
this.contentHeight + ( center.y % this.contentHeight ) this.contentAspectY + ( center.y % this.contentAspectY )
) % this.contentHeight; ) % this.contentAspectY;
this.centerSpringY.resetTo( center.y ); this.centerSpringY.resetTo( center.y );
this.centerSpringY.update(); this.centerSpringY.update();
} }
@ -339,6 +363,31 @@ $.Viewport.prototype = {
this.fitBounds( this.homeBounds, immediately ); this.fitBounds( this.homeBounds, immediately );
}, },
/**
* @function
* @param {Boolean} immediately
*/
fitHorizontally: function( immediately ) {
var center = this.getCenter();
if ( this.wrapHorizontal ) {
center.x = (
this.contentAspectX + ( center.x % this.contentAspectX )
) % this.contentAspectX;
this.centerSpringX.resetTo( center.x );
this.centerSpringX.update();
}
if ( this.wrapVertical ) {
center.y = ( 1 + ( center.y % 1 ) ) % 1;
this.centerSpringY.resetTo( center.y );
this.centerSpringY.update();
}
this.fitBounds( this.fitWidthBounds, immediately );
},
/** /**
* @function * @function
* @param {OpenSeadragon.Point} delta * @param {OpenSeadragon.Point} delta