Merge branch 'master' into ms-reference-strip

This commit is contained in:
Mark Salsbery 2023-08-10 15:20:31 -07:00
commit b4bb3a4afd
49 changed files with 1724 additions and 6827 deletions

1
.browserslistrc Normal file
View File

@ -0,0 +1 @@
defaults

View File

@ -1,14 +1,16 @@
{ {
"root": true, "root": true,
"plugins": ["compat"],
"extends": [ "extends": [
"eslint:recommended" "eslint:recommended",
"plugin:compat/recommended"
], ],
"env": { "env": {
"es6": false, "es6": true,
"browser": true "browser": true
}, },
"parserOptions": { "parserOptions": {
"ecmaVersion": 5, "ecmaVersion": 6,
"sourceType": "script", "sourceType": "script",
"ecmaFeatures": { "ecmaFeatures": {
"globalReturn": false, "globalReturn": false,

View File

@ -1,6 +1,10 @@
# Specify dist until Travis CI default Runner OS updates to one
# with glibc version required by newer Node versions
# See: https://github.com/nodejs/node/issues/42351#issuecomment-1068424442
dist: jammy
language: node_js language: node_js
sudo: false sudo: false
node_js: node_js:
- "16.14.2" - lts/*
before_install: before_install:
- npm install -g grunt-cli - npm install -g grunt-cli

View File

@ -161,9 +161,12 @@ module.exports = function(grunt) {
normal: { normal: {
options: { options: {
urls: [ "http://localhost:8000/test/test.html" ], urls: [ "http://localhost:8000/test/test.html" ],
timeout: 10000 timeout: 10000,
puppeteer: {
headless: 'new'
} }
}, },
},
coverage: { coverage: {
options: { options: {
urls: [ "http://localhost:8000/test/coverage.html" ], urls: [ "http://localhost:8000/test/coverage.html" ],

View File

@ -1,5 +1,5 @@
Copyright (C) 2009 CodePlex Foundation Copyright (C) 2009 CodePlex Foundation
Copyright (C) 2010-2022 OpenSeadragon contributors Copyright (C) 2010-2023 OpenSeadragon contributors
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:

View File

@ -1,18 +1,43 @@
OPENSEADRAGON CHANGELOG OPENSEADRAGON CHANGELOG
======================= =======================
4.0.1: (in progress...) 5.0.0: (in progress...)
* The viewer no longer emits canvas-key events for both keydown and keypress events; canvas-key is now just for keydown, and the new canvas-key-press is for keypress (#2270 @hrghauri) * BREAKING CHANGE: Dropped support for IE11 (#2300, #2361 @AndrewADev)
* DEPRECATION: The OpenSeadragon.createCallback function is no longer recommended (#2367 @akansjain)
* Introduced maxTilesPerFrame option to allow loading more tiles simultaneously (#2387 @jetic83)
* Test improvements (#2382 @AndrewADev)
* MouseTracker options documentation fixes (#2389 @msalsbery)
* Fixed: Sometimes if the viewport was flipped and the user zoomed in far enough, it would flip back (#2364 @SebDelile)
4.1.0:
* NEW BEHAVIOR: When `navigatorRotate` is false, while the navigator image doesn't rotate, the red outline now does (#2356 @lcl45)
* The viewer no longer emits `canvas-key` events for both keydown and keypress events; canvas-key is now just for keydown, and the new `canvas-key-press` is for keypress (#2270 @hrghauri)
* You can now specify a priority when calling addHandler, to control when your event handler gets called relative to others (#2273 @Aiosa) * You can now specify a priority when calling addHandler, to control when your event handler gets called relative to others (#2273 @Aiosa)
* Added tileRetryMax and tileRetryDelay options, so the viewer can retry loading failed tiles (#2238 @Ughuuu, @paaddyy) * Added tileRetryMax and tileRetryDelay options, so the viewer can retry loading failed tiles (#2238 @Ughuuu @paaddyy, #2334 @Ughuuu @Titan21)
* Fixed: Navigator display rectangle was off if the page had box-sizing: border-box (#2276 @ambujsahu81) * All of the viewers keyboard handling is now in response to keydown events (it used to be split between keydown and keypress) (#2291 @MohitBansal321)
* Added `canvas-focus` and `canvas-blur` events to Viewer (#2301 @MohitBansal321)
* You can now more easily add custom buttons to the viewer (#2306 @MohitBansal321)
* The fitBounds function now takes zoom constraints into account (#2293 @pearcetm)
* The viewer now has an `after-resize` event what happens after the viewport bounds have been updated, to complement the `resize` event which happens before (#2317 @pearcetm)
* IIIFTileSource now uses resolution level dimensions provided in the info.json "sizes" field for more accurate tile requests (#2337 @ruven)
* Added setAjaxHeaders method to Viewer and TiledImage (#2346 @uschmidt83)
* Improved documentation (#2297 @KevinBritten)
* Fixed: The `tile-loaded` event's completionCallback could be called more than once in some circumstances (#2282 @Aiosa, @pearcetm)
* Fixed: Navigator display rectangle was off if the page had `box-sizing: border-box` (#2276 @ambujsahu81)
* Fixed: Code that required identifying functions would fail for async functions (#2273 @Aiosa) * Fixed: Code that required identifying functions would fail for async functions (#2273 @Aiosa)
* Fixed: Reference strip click detection was not accurate for long reference strips (#2280 @damonsson) * Fixed: Reference strip click detection was not accurate for long reference strips (#2280 @damonsson)
* Fixed: Translation problems in some circumstances with cropping polygons enabled (#2316 @pearcetm)
* Fixed: The navigator area rectangle would grow larger when you zoom in very far (#2318 @donotloveshampo)
* Fixed: JSON with embedded XML was being incorrectly identified as XML (#2328 @craigberry)
* Fixed: Touch/pinch rotate was not working properly on some platforms (#2324 @rsimon, @pearcetm)
* Fixed: Navigator rotation didn't honor `immediately` parameter (#2333 @robertjcolley)
* Fixed: The navigator didn't update for its new size in certain circumstances (#2347 @pearcetm)
4.0.0: 4.0.0:
* NEW BEHAVIOR: Setting the viewport rotation now animates by default (pass false for the new `immediately` parameter to disable) (#2136 @jonasengelmann) * NEW BEHAVIOR: Setting the viewport rotation now animates by default (pass true for the new `immediately` parameter to disable) (#2136 @jonasengelmann)
* NEW BEHAVIOR: The auto resize now takes both width and height into account when scaling the contents proportionally to the viewer (#2256 @pearcetm) * NEW BEHAVIOR: The auto resize now takes both width and height into account when scaling the contents proportionally to the viewer (#2256 @pearcetm)
* DEPRECATION: Don't access the viewport's degrees property directly anymore; instead use setRotation and getRotation (#2136 @jonasengelmann) * DEPRECATION: Don't access the viewport's degrees property directly anymore; instead use setRotation and getRotation (#2136 @jonasengelmann)
* New gesture: Double-click and drag to zoom (on by default for touch) (#2225 @HamzaTatheer) * New gesture: Double-click and drag to zoom (on by default for touch) (#2225 @HamzaTatheer)

7470
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "openseadragon", "name": "openseadragon",
"version": "4.0.0", "version": "4.1.0",
"description": "Provides a smooth, zoomable user interface for HTML/Javascript.", "description": "Provides a smooth, zoomable user interface for HTML/Javascript.",
"keywords": [ "keywords": [
"image", "image",
@ -29,19 +29,20 @@
"url": "https://github.com/openseadragon/openseadragon.git" "url": "https://github.com/openseadragon/openseadragon.git"
}, },
"devDependencies": { "devDependencies": {
"grunt": "^1.4.1", "eslint-plugin-compat": "^4.1.2",
"grunt-contrib-clean": "^2.0.0", "grunt": "^1.6.1",
"grunt-contrib-clean": "^2.0.1",
"grunt-contrib-compress": "^2.0.0", "grunt-contrib-compress": "^2.0.0",
"grunt-contrib-concat": "^2.0.0", "grunt-contrib-concat": "^2.1.0",
"grunt-contrib-connect": "^3.0.0", "grunt-contrib-connect": "^3.0.0",
"grunt-contrib-qunit": "^6.2.0", "grunt-contrib-qunit": "^7.0.1",
"grunt-contrib-uglify": "^5.0.1", "grunt-contrib-uglify": "^5.0.1",
"grunt-contrib-watch": "^1.1.0", "grunt-contrib-watch": "^1.1.0",
"grunt-eslint": "^24.0.0", "grunt-eslint": "^24.0.1",
"grunt-git-describe": "^2.4.4", "grunt-git-describe": "^2.4.4",
"grunt-istanbul": "^0.8.0", "grunt-istanbul": "^0.8.0",
"grunt-text-replace": "^0.4.0", "grunt-text-replace": "^0.4.0",
"qunitjs": "2.4.1" "qunit": "^2.19.4"
}, },
"scripts": { "scripts": {
"test": "grunt test", "test": "grunt test",

View File

@ -2,7 +2,7 @@
* OpenSeadragon - Button * OpenSeadragon - Button
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - ButtonGroup * OpenSeadragon - ButtonGroup
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -112,6 +112,17 @@ $.ButtonGroup = function( options ) {
/** @lends OpenSeadragon.ButtonGroup.prototype */ /** @lends OpenSeadragon.ButtonGroup.prototype */
$.ButtonGroup.prototype = { $.ButtonGroup.prototype = {
/**
* Adds the given button to this button group.
*
* @function
* @param {OpenSeadragon.Button} button
*/
addButton: function( button ){
this.buttons.push(button);
this.element.appendChild(button.element);
},
/** /**
* TODO: Figure out why this is used on the public API and if a more useful * TODO: Figure out why this is used on the public API and if a more useful
* api can be created. * api can be created.

View File

@ -2,7 +2,7 @@
* OpenSeadragon - Control * OpenSeadragon - Control
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - ControlDock * OpenSeadragon - ControlDock
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - DisplayRect * OpenSeadragon - DisplayRect
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - Drawer * OpenSeadragon - Drawer
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - DziTileSource * OpenSeadragon - DziTileSource
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - EventSource * OpenSeadragon - EventSource
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - full-screen support functions * OpenSeadragon - full-screen support functions
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -67,10 +67,14 @@
return document.fullscreenElement; return document.fullscreenElement;
}; };
fullScreenApi.requestFullScreen = function( element ) { fullScreenApi.requestFullScreen = function( element ) {
return element.requestFullscreen(); return element.requestFullscreen().catch(function (msg) {
$.console.error('Fullscreen request failed: ', msg);
});
}; };
fullScreenApi.exitFullScreen = function() { fullScreenApi.exitFullScreen = function() {
document.exitFullscreen(); document.exitFullscreen().catch(function (msg) {
$.console.error('Error while exiting fullscreen: ', msg);
});
}; };
fullScreenApi.fullScreenEventName = "fullscreenchange"; fullScreenApi.fullScreenEventName = "fullscreenchange";
fullScreenApi.fullScreenErrorEventName = "fullscreenerror"; fullScreenApi.fullScreenErrorEventName = "fullscreenerror";

View File

@ -2,7 +2,7 @@
* OpenSeadragon - IIIFTileSource * OpenSeadragon - IIIFTileSource
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -141,6 +141,18 @@ $.IIIFTileSource = function( options ){
} }
} }
// Create an array with our exact resolution sizes if these have been supplied
if( this.sizes ) {
var sizeLength = this.sizes.length;
if ( (sizeLength === options.maxLevel) || (sizeLength === options.maxLevel + 1) ) {
this.levelSizes = this.sizes;
// Need to take into account that the list may or may not include the full resolution size
if( sizeLength === options.maxLevel ) {
this.levelSizes.push( {width: this.width, height: this.height} );
}
}
}
$.TileSource.apply( this, [ options ] ); $.TileSource.apply( this, [ options ] );
}; };
@ -333,7 +345,17 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
} }
} }
// Use supplied list of scaled resolution sizes if these exist
if( this.levelSizes ) {
var levelSize = this.levelSizes[level];
var x = Math.ceil( levelSize.width / this.getTileWidth(level) ),
y = Math.ceil( levelSize.height / this.getTileHeight(level) );
return new $.Point( x, y );
}
// Otherwise call default TileSource->getNumTiles() function
else {
return $.TileSource.prototype.getNumTiles.call(this, level); return $.TileSource.prototype.getNumTiles.call(this, level);
}
}, },
@ -348,6 +370,34 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
return new $.Point(0, 0); return new $.Point(0, 0);
} }
// Use supplied list of scaled resolution sizes if these exist
if( this.levelSizes ) {
var validPoint = point.x >= 0 && point.x <= 1 &&
point.y >= 0 && point.y <= 1 / this.aspectRatio;
$.console.assert(validPoint, "[TileSource.getTileAtPoint] must be called with a valid point.");
var widthScaled = this.levelSizes[level].width;
var pixelX = point.x * widthScaled;
var pixelY = point.y * widthScaled;
var x = Math.floor(pixelX / this.getTileWidth(level));
var y = Math.floor(pixelY / this.getTileHeight(level));
// When point.x == 1 or point.y == 1 / this.aspectRatio we want to
// return the last tile of the row/column
if (point.x >= 1) {
x = this.getNumTiles(level).x - 1;
}
var EPSILON = 1e-15;
if (point.y >= 1 / this.aspectRatio - EPSILON) {
y = this.getNumTiles(level).y - 1;
}
return new $.Point(x, y);
}
// Otherwise call default TileSource->getTileAtPoint() function
return $.TileSource.prototype.getTileAtPoint.call(this, level, point); return $.TileSource.prototype.getTileAtPoint.call(this, level, point);
}, },
@ -375,10 +425,9 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
var IIIF_ROTATION = '0', var IIIF_ROTATION = '0',
//## get the scale (level as a decimal) //## get the scale (level as a decimal)
scale = Math.pow( 0.5, this.maxLevel - level ), scale = Math.pow( 0.5, this.maxLevel - level ),
//# image dimensions at this level //# image dimensions at this level
levelWidth = Math.round( this.width * scale ), levelWidth,
levelHeight = Math.round( this.height * scale ), levelHeight,
//## iiif region //## iiif region
tileWidth, tileWidth,
@ -396,6 +445,17 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
iiifQuality, iiifQuality,
uri; uri;
// Use supplied list of scaled resolution sizes if these exist
if( this.levelSizes ) {
levelWidth = this.levelSizes[level].width;
levelHeight = this.levelSizes[level].height;
}
// Otherwise calculate the sizes ourselves
else {
levelWidth = Math.ceil( this.width * scale );
levelHeight = Math.ceil( this.height * scale );
}
tileWidth = this.getTileWidth(level); tileWidth = this.getTileWidth(level);
tileHeight = this.getTileHeight(level); tileHeight = this.getTileHeight(level);
iiifTileSizeWidth = Math.round( tileWidth / scale ); iiifTileSizeWidth = Math.round( tileWidth / scale );
@ -426,8 +486,8 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
} else { } else {
iiifRegion = [ iiifTileX, iiifTileY, iiifTileW, iiifTileH ].join( ',' ); iiifRegion = [ iiifTileX, iiifTileY, iiifTileW, iiifTileH ].join( ',' );
} }
iiifSizeW = Math.round( iiifTileW * scale ); iiifSizeW = Math.min( tileWidth, levelWidth - (x * tileWidth) );
iiifSizeH = Math.round( iiifTileH * scale ); iiifSizeH = Math.min( tileHeight, levelHeight - (y * tileHeight) );
if ( this.version === 2 && iiifSizeW === this.width ) { if ( this.version === 2 && iiifSizeW === this.width ) {
iiifSize = "full"; iiifSize = "full";
} else if ( this.version === 3 && iiifSizeW === this.width && iiifSizeH === this.height ) { } else if ( this.version === 3 && iiifSizeW === this.width && iiifSizeH === this.height ) {

View File

@ -2,7 +2,7 @@
* OpenSeadragon - ImageLoader * OpenSeadragon - ImageLoader
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -62,7 +62,7 @@ $.ImageJob = function(options) {
/** /**
* Data object which will contain downloaded image data. * Data object which will contain downloaded image data.
* @member {Image|*} image data object, by default an Image object (depends on TileSource) * @member {Image|*} data data object, by default an Image object (depends on TileSource)
* @memberof OpenSeadragon.ImageJob# * @memberof OpenSeadragon.ImageJob#
*/ */
this.data = null; this.data = null;
@ -234,7 +234,7 @@ $.ImageLoader.prototype = {
* @param callback - Called once cleanup is finished. * @param callback - Called once cleanup is finished.
*/ */
function completeJob(loader, job, callback) { function completeJob(loader, job, callback) {
if (job.errorMsg !== '' && (job.image === null || job.image === undefined) && job.tries < 1 + loader.tileRetryMax) { if (job.errorMsg !== '' && (job.data === null || job.data === undefined) && job.tries < 1 + loader.tileRetryMax) {
loader.failedTiles.push(job); loader.failedTiles.push(job);
} }
var nextJob; var nextJob;

View File

@ -2,7 +2,7 @@
* OpenSeadragon - ImageTileSource * OpenSeadragon - ImageTileSource
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - LegacyTileSource * OpenSeadragon - LegacyTileSource
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - MouseTracker * OpenSeadragon - MouseTracker
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -57,16 +57,16 @@
* @param {Boolean} [options.startDisabled=false] * @param {Boolean} [options.startDisabled=false]
* If true, event tracking on the element will not start until * If true, event tracking on the element will not start until
* {@link OpenSeadragon.MouseTracker.setTracking|setTracking} is called. * {@link OpenSeadragon.MouseTracker.setTracking|setTracking} is called.
* @param {Number} options.clickTimeThreshold * @param {Number} [options.clickTimeThreshold=300]
* The number of milliseconds within which a pointer down-up event combination * The number of milliseconds within which a pointer down-up event combination
* will be treated as a click gesture. * will be treated as a click gesture.
* @param {Number} options.clickDistThreshold * @param {Number} [options.clickDistThreshold=5]
* The maximum distance allowed between a pointer down event and a pointer up event * The maximum distance allowed between a pointer down event and a pointer up event
* to be treated as a click gesture. * to be treated as a click gesture.
* @param {Number} options.dblClickTimeThreshold * @param {Number} [options.dblClickTimeThreshold=300]
* The number of milliseconds within which two pointer down-up event combinations * The number of milliseconds within which two pointer down-up event combinations
* will be treated as a double-click gesture. * will be treated as a double-click gesture.
* @param {Number} options.dblClickDistThreshold * @param {Number} [options.dblClickDistThreshold=20]
* The maximum distance allowed between two pointer click events * The maximum distance allowed between two pointer click events
* to be treated as a click gesture. * to be treated as a click gesture.
* @param {Number} [options.stopDelay=50] * @param {Number} [options.stopDelay=50]

View File

@ -2,7 +2,7 @@
* OpenSeadragon - Navigator * OpenSeadragon - Navigator
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -224,19 +224,19 @@ $.Navigator = function( options ){
this.displayRegionContainer.appendChild(this.displayRegion); this.displayRegionContainer.appendChild(this.displayRegion);
this.element.getElementsByTagName('div')[0].appendChild(this.displayRegionContainer); this.element.getElementsByTagName('div')[0].appendChild(this.displayRegionContainer);
function rotate(degrees) { function rotate(degrees, immediately) {
_setTransformRotate(_this.displayRegionContainer, degrees); _setTransformRotate(_this.displayRegionContainer, degrees);
_setTransformRotate(_this.displayRegion, -degrees); _setTransformRotate(_this.displayRegion, -degrees);
_this.viewport.setRotation(degrees); _this.viewport.setRotation(degrees, immediately);
} }
if (options.navigatorRotate) { if (options.navigatorRotate) {
var degrees = options.viewer.viewport ? var degrees = options.viewer.viewport ?
options.viewer.viewport.getRotation() : options.viewer.viewport.getRotation() :
options.viewer.degrees || 0; options.viewer.degrees || 0;
rotate(degrees); rotate(degrees, true);
options.viewer.addHandler("rotate", function (args) { options.viewer.addHandler("rotate", function (args) {
rotate(args.degrees); rotate(args.degrees, args.immediately);
}); });
} }
@ -324,6 +324,7 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /*
this.width = width; this.width = width;
this.element.style.width = typeof (width) === "number" ? (width + 'px') : width; this.element.style.width = typeof (width) === "number" ? (width + 'px') : width;
this._resizeWithViewer = false; this._resizeWithViewer = false;
this.updateSize();
}, },
/** /**
@ -334,6 +335,7 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /*
this.height = height; this.height = height;
this.element.style.height = typeof (height) === "number" ? (height + 'px') : height; this.element.style.height = typeof (height) === "number" ? (height + 'px') : height;
this._resizeWithViewer = false; this._resizeWithViewer = false;
this.updateSize();
}, },
/** /**
@ -395,15 +397,20 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /*
bottomright = this.viewport.pixelFromPointNoRotate(bounds.getBottomRight(), false) bottomright = this.viewport.pixelFromPointNoRotate(bounds.getBottomRight(), false)
.minus( this.totalBorderWidths ); .minus( this.totalBorderWidths );
if (!this.navigatorRotate) {
var degrees = viewport.getRotation(true);
_setTransformRotate(this.displayRegion, -degrees);
}
//update style for navigator-box //update style for navigator-box
var style = this.displayRegion.style; var style = this.displayRegion.style;
style.display = this.world.getItemCount() ? 'block' : 'none'; style.display = this.world.getItemCount() ? 'block' : 'none';
style.top = Math.round( topleft.y ) + 'px'; style.top = topleft.y.toFixed(2) + "px";
style.left = Math.round( topleft.x ) + 'px'; style.left = topleft.x.toFixed(2) + "px";
var width = Math.abs( topleft.x - bottomright.x ); var width = bottomright.x - topleft.x;
var height = Math.abs( topleft.y - bottomright.y ); var height = bottomright.y - topleft.y;
// make sure width and height are non-negative so IE doesn't throw // make sure width and height are non-negative so IE doesn't throw
style.width = Math.round( Math.max( width, 0 ) ) + 'px'; style.width = Math.round( Math.max( width, 0 ) ) + 'px';
style.height = Math.round( Math.max( height, 0 ) ) + 'px'; style.height = Math.round( Math.max( height, 0 ) ) + 'px';

View File

@ -2,7 +2,7 @@
* OpenSeadragon * OpenSeadragon
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -60,7 +60,7 @@
/* /*
* Portions of this source file taken from mattsnider.com: * Portions of this source file taken from mattsnider.com:
* *
* Copyright (c) 2006-2022 Matt Snider * Copyright (c) 2006-2013 Matt Snider
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@ -290,6 +290,12 @@
* @property {Number} [rotationIncrement=90] * @property {Number} [rotationIncrement=90]
* The number of degrees to rotate right or left when the rotate buttons or keyboard shortcuts are activated. * The number of degrees to rotate right or left when the rotate buttons or keyboard shortcuts are activated.
* *
* @property {Number} [maxTilesPerFrame=1]
* The number of tiles loaded per frame. As the frame rate of the client's machine is usually high (e.g., 50 fps),
* one tile per frame should be a good choice. However, for large screens or lower frame rates, the number of
* loaded tiles per frame can be adjusted here. Reasonable values might be 2 or 3 tiles per frame.
* (Note that the actual frame rate is given by the client's browser and machine).
*
* @property {Number} [pixelsPerWheelLine=40] * @property {Number} [pixelsPerWheelLine=40]
* For pixel-resolution scrolling devices, the number of pixels equal to one scroll line. * For pixel-resolution scrolling devices, the number of pixels equal to one scroll line.
* *
@ -565,50 +571,50 @@
* viewing the first image and the 'next' button will wrap to the first * viewing the first image and the 'next' button will wrap to the first
* image when viewing the last image. * image when viewing the last image.
* *
* @property {String} zoomInButton *@property {String|Element} zoomInButton
* Set the id of the custom 'Zoom in' button to use. * Set the id or element of the custom 'Zoom in' button to use.
* This is useful to have a custom button anywhere in the web page.<br> * This is useful to have a custom button anywhere in the web page.<br>
* To only change the button images, consider using * To only change the button images, consider using
* {@link OpenSeadragon.Options.navImages} * {@link OpenSeadragon.Options.navImages}
* *
* @property {String} zoomOutButton * @property {String|Element} zoomOutButton
* Set the id of the custom 'Zoom out' button to use. * Set the id or element of the custom 'Zoom out' button to use.
* This is useful to have a custom button anywhere in the web page.<br> * This is useful to have a custom button anywhere in the web page.<br>
* To only change the button images, consider using * To only change the button images, consider using
* {@link OpenSeadragon.Options.navImages} * {@link OpenSeadragon.Options.navImages}
* *
* @property {String} homeButton * @property {String|Element} homeButton
* Set the id of the custom 'Go home' button to use. * Set the id or element of the custom 'Go home' button to use.
* This is useful to have a custom button anywhere in the web page.<br> * This is useful to have a custom button anywhere in the web page.<br>
* To only change the button images, consider using * To only change the button images, consider using
* {@link OpenSeadragon.Options.navImages} * {@link OpenSeadragon.Options.navImages}
* *
* @property {String} fullPageButton * @property {String|Element} fullPageButton
* Set the id of the custom 'Toggle full page' button to use. * Set the id or element of the custom 'Toggle full page' button to use.
* This is useful to have a custom button anywhere in the web page.<br> * This is useful to have a custom button anywhere in the web page.<br>
* To only change the button images, consider using * To only change the button images, consider using
* {@link OpenSeadragon.Options.navImages} * {@link OpenSeadragon.Options.navImages}
* *
* @property {String} rotateLeftButton * @property {String|Element} rotateLeftButton
* Set the id of the custom 'Rotate left' button to use. * Set the id or element of the custom 'Rotate left' button to use.
* This is useful to have a custom button anywhere in the web page.<br> * This is useful to have a custom button anywhere in the web page.<br>
* To only change the button images, consider using * To only change the button images, consider using
* {@link OpenSeadragon.Options.navImages} * {@link OpenSeadragon.Options.navImages}
* *
* @property {String} rotateRightButton * @property {String|Element} rotateRightButton
* Set the id of the custom 'Rotate right' button to use. * Set the id or element of the custom 'Rotate right' button to use.
* This is useful to have a custom button anywhere in the web page.<br> * This is useful to have a custom button anywhere in the web page.<br>
* To only change the button images, consider using * To only change the button images, consider using
* {@link OpenSeadragon.Options.navImages} * {@link OpenSeadragon.Options.navImages}
* *
* @property {String} previousButton * @property {String|Element} previousButton
* Set the id of the custom 'Previous page' button to use. * Set the id or element of the custom 'Previous page' button to use.
* This is useful to have a custom button anywhere in the web page.<br> * This is useful to have a custom button anywhere in the web page.<br>
* To only change the button images, consider using * To only change the button images, consider using
* {@link OpenSeadragon.Options.navImages} * {@link OpenSeadragon.Options.navImages}
* *
* @property {String} nextButton * @property {String|Element} nextButton
* Set the id of the custom 'Next page' button to use. * Set the id or element of the custom 'Next page' button to use.
* This is useful to have a custom button anywhere in the web page.<br> * This is useful to have a custom button anywhere in the web page.<br>
* To only change the button images, consider using * To only change the button images, consider using
* {@link OpenSeadragon.Options.navImages} * {@link OpenSeadragon.Options.navImages}
@ -1288,6 +1294,7 @@ function OpenSeadragon( options ){
preserveImageSizeOnResize: false, // requires autoResize=true preserveImageSizeOnResize: false, // requires autoResize=true
minScrollDeltaTime: 50, minScrollDeltaTime: 50,
rotationIncrement: 90, rotationIncrement: 90,
maxTilesPerFrame: 1,
//DEFAULT CONTROL SETTINGS //DEFAULT CONTROL SETTINGS
showSequenceControl: true, //SEQUENCE showSequenceControl: true, //SEQUENCE
@ -2251,25 +2258,12 @@ function OpenSeadragon( options ){
event.stopPropagation(); event.stopPropagation();
}, },
// Deprecated
/**
* Similar to OpenSeadragon.delegate, but it does not immediately call
* the method on the object, returning a function which can be called
* repeatedly to delegate the method. It also allows additional arguments
* to be passed during construction which will be added during each
* invocation, and each invocation can add additional arguments as well.
*
* @function
* @param {Object} object
* @param {Function} method
* @param [args] any additional arguments are passed as arguments to the
* created callback
* @returns {Function}
*/
createCallback: function( object, method ) { createCallback: function( object, method ) {
//TODO: This pattern is painful to use and debug. It's much cleaner //TODO: This pattern is painful to use and debug. It's much cleaner
// to use pinning plus anonymous functions. Get rid of this // to use pinning plus anonymous functions. Get rid of this
// pattern! // pattern!
console.error('The createCallback function is deprecated and will be removed in future versions. Please use alternativeFunction instead.');
var initialArgs = [], var initialArgs = [],
i; i;
for ( i = 2; i < arguments.length; i++ ) { for ( i = 2; i < arguments.length; i++ ) {

View File

@ -2,7 +2,7 @@
* OpenSeadragon - OsmTileSource * OpenSeadragon - OsmTileSource
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - Overlay * OpenSeadragon - Overlay
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - Point * OpenSeadragon - Point
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - Profiler * OpenSeadragon - Profiler
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - Rect * OpenSeadragon - Rect
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - ReferenceStrip * OpenSeadragon - ReferenceStrip
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - Spring * OpenSeadragon - Spring
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - getString/setString * OpenSeadragon - getString/setString
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - Tile * OpenSeadragon - Tile
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - TileCache * OpenSeadragon - TileCache
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - TiledImage * OpenSeadragon - TiledImage
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -147,6 +147,9 @@ $.TiledImage = function( options ) {
var degrees = options.degrees || 0; var degrees = options.degrees || 0;
delete options.degrees; delete options.degrees;
var ajaxHeaders = options.ajaxHeaders;
delete options.ajaxHeaders;
$.extend( true, this, { $.extend( true, this, {
//internal state properties //internal state properties
@ -179,7 +182,8 @@ $.TiledImage = function( options ) {
opacity: $.DEFAULT_SETTINGS.opacity, opacity: $.DEFAULT_SETTINGS.opacity,
preload: $.DEFAULT_SETTINGS.preload, preload: $.DEFAULT_SETTINGS.preload,
compositeOperation: $.DEFAULT_SETTINGS.compositeOperation, compositeOperation: $.DEFAULT_SETTINGS.compositeOperation,
subPixelRoundingForTransparency: $.DEFAULT_SETTINGS.subPixelRoundingForTransparency subPixelRoundingForTransparency: $.DEFAULT_SETTINGS.subPixelRoundingForTransparency,
maxTilesPerFrame: $.DEFAULT_SETTINGS.maxTilesPerFrame
}, options ); }, options );
this._preload = this.preload; this._preload = this.preload;
@ -238,6 +242,9 @@ $.TiledImage = function( options ) {
tiledImage: _this tiledImage: _this
}, args)); }, args));
}; };
this._ownAjaxHeaders = {};
this.setAjaxHeaders(ajaxHeaders, false);
}; };
$.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.TiledImage.prototype */{ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.TiledImage.prototype */{
@ -1003,6 +1010,90 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
}); });
}, },
/**
* Update headers to include when making AJAX requests.
*
* Unless `propagate` is set to false (which is likely only useful in rare circumstances),
* the updated headers are propagated to all tiles and queued image loader jobs.
*
* Note that the rules for merging headers still apply, i.e. headers returned by
* {@link OpenSeadragon.TileSource#getTileAjaxHeaders} take precedence over
* the headers here in the tiled image (`TiledImage.ajaxHeaders`).
*
* @function
* @param {Object} ajaxHeaders Updated AJAX headers, which will be merged over any headers specified in {@link OpenSeadragon.Options}.
* @param {Boolean} [propagate=true] Whether to propagate updated headers to existing tiles and queued image loader jobs.
*/
setAjaxHeaders: function(ajaxHeaders, propagate) {
if (ajaxHeaders === null) {
ajaxHeaders = {};
}
if (!$.isPlainObject(ajaxHeaders)) {
console.error('[TiledImage.setAjaxHeaders] Ignoring invalid headers, must be a plain object');
return;
}
this._ownAjaxHeaders = ajaxHeaders;
this._updateAjaxHeaders(propagate);
},
/**
* Update headers to include when making AJAX requests.
*
* This function has the same effect as calling {@link OpenSeadragon.TiledImage#setAjaxHeaders},
* except that the headers for this tiled image do not change. This is especially useful
* for propagating updated headers from {@link OpenSeadragon.TileSource#getTileAjaxHeaders}
* to existing tiles.
*
* @private
* @function
* @param {Boolean} [propagate=true] Whether to propagate updated headers to existing tiles and queued image loader jobs.
*/
_updateAjaxHeaders: function(propagate) {
if (propagate === undefined) {
propagate = true;
}
// merge with viewer's headers
if ($.isPlainObject(this.viewer.ajaxHeaders)) {
this.ajaxHeaders = $.extend({}, this.viewer.ajaxHeaders, this._ownAjaxHeaders);
} else {
this.ajaxHeaders = this._ownAjaxHeaders;
}
// propagate header updates to all tiles and queued image loader jobs
if (propagate) {
var numTiles, xMod, yMod, tile;
for (var level in this.tilesMatrix) {
numTiles = this.source.getNumTiles(level);
for (var x in this.tilesMatrix[level]) {
xMod = ( numTiles.x + ( x % numTiles.x ) ) % numTiles.x;
for (var y in this.tilesMatrix[level][x]) {
yMod = ( numTiles.y + ( y % numTiles.y ) ) % numTiles.y;
tile = this.tilesMatrix[level][x][y];
tile.loadWithAjax = this.loadTilesWithAjax;
if (tile.loadWithAjax) {
var tileAjaxHeaders = this.source.getTileAjaxHeaders( level, xMod, yMod );
tile.ajaxHeaders = $.extend({}, this.ajaxHeaders, tileAjaxHeaders);
} else {
tile.ajaxHeaders = null;
}
}
}
}
for (var i = 0; i < this._imageLoader.jobQueue.length; i++) {
var job = this._imageLoader.jobQueue[i];
job.loadWithAjax = job.tile.loadWithAjax;
job.ajaxHeaders = job.tile.loadWithAjax ? job.tile.ajaxHeaders : null;
}
}
},
// private // private
_setScale: function(scale, immediately) { _setScale: function(scale, immediately) {
var sameTarget = (this._scaleSpring.target.value === scale); var sameTarget = (this._scaleSpring.target.value === scale);
@ -1118,7 +1209,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
var levelsInterval = this._getLevelsInterval(); var levelsInterval = this._getLevelsInterval();
var lowestLevel = levelsInterval.lowestLevel; var lowestLevel = levelsInterval.lowestLevel;
var highestLevel = levelsInterval.highestLevel; var highestLevel = levelsInterval.highestLevel;
var bestTile = null; var bestTiles = [];
var haveDrawn = false; var haveDrawn = false;
var currentTime = $.now(); var currentTime = $.now();
@ -1163,7 +1254,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
); );
// Update the level and keep track of 'best' tile to load // Update the level and keep track of 'best' tile to load
bestTile = this._updateLevel( bestTiles = this._updateLevel(
haveDrawn, haveDrawn,
drawLevel, drawLevel,
level, level,
@ -1171,7 +1262,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
levelVisibility, levelVisibility,
drawArea, drawArea,
currentTime, currentTime,
bestTile bestTiles
); );
// Stop the loop if lower-res tiles would all be covered by // Stop the loop if lower-res tiles would all be covered by
@ -1184,9 +1275,13 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
// Perform the actual drawing // Perform the actual drawing
this._drawTiles(this.lastDrawn); this._drawTiles(this.lastDrawn);
// Load the new 'best' tile // Load the new 'best' n tiles
if (bestTile && !bestTile.context2D) { if (bestTiles && bestTiles.length > 0) {
this._loadTile(bestTile, currentTime); bestTiles.forEach(function (tile) {
if (tile && !tile.context2D) {
this._loadTile(tile, currentTime);
}
}, this);
this._needsDraw = true; this._needsDraw = true;
this._setFullyLoaded(false); this._setFullyLoaded(false);
} else { } else {
@ -1245,7 +1340,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
* @param {Number} levelVisibility * @param {Number} levelVisibility
* @param {OpenSeadragon.Rect} drawArea * @param {OpenSeadragon.Rect} drawArea
* @param {Number} currentTime * @param {Number} currentTime
* @param {OpenSeadragon.Tile} best - The current "best" tile to draw. * @param {OpenSeadragon.Tile[]} best - The current "best" n tiles to draw.
*/ */
_updateLevel: function(haveDrawn, drawLevel, level, levelOpacity, _updateLevel: function(haveDrawn, drawLevel, level, levelOpacity,
levelVisibility, drawArea, currentTime, best) { levelVisibility, drawArea, currentTime, best) {
@ -1270,7 +1365,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
* @property {Object} topleft deprecated, use drawArea instead * @property {Object} topleft deprecated, use drawArea instead
* @property {Object} bottomright deprecated, use drawArea instead * @property {Object} bottomright deprecated, use drawArea instead
* @property {Object} currenttime * @property {Object} currenttime
* @property {Object} best * @property {Object[]} best
* @property {?Object} userData - Arbitrary subscriber-defined object. * @property {?Object} userData - Arbitrary subscriber-defined object.
*/ */
this.viewer.raiseEvent('update-level', { this.viewer.raiseEvent('update-level', {
@ -1359,7 +1454,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
* @param {OpenSeadragon.Point} viewportCenter * @param {OpenSeadragon.Point} viewportCenter
* @param {Number} numberOfTiles * @param {Number} numberOfTiles
* @param {Number} currentTime * @param {Number} currentTime
* @param {OpenSeadragon.Tile} best - The current "best" tile to draw. * @param {OpenSeadragon.Tile[]} best - The current "best" tiles to draw.
*/ */
_updateTile: function( haveDrawn, drawLevel, x, y, level, levelOpacity, _updateTile: function( haveDrawn, drawLevel, x, y, level, levelOpacity,
levelVisibility, viewportCenter, numberOfTiles, currentTime, best){ levelVisibility, viewportCenter, numberOfTiles, currentTime, best){
@ -1448,7 +1543,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
// the tile is already in the download queue // the tile is already in the download queue
this._tilesLoading++; this._tilesLoading++;
} else if (!loadingCoverage) { } else if (!loadingCoverage) {
best = this._compareTiles( best, tile ); best = this._compareTiles( best, tile, this.maxTilesPerFrame );
} }
return best; return best;
@ -1621,6 +1716,8 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
tile.loading = false; tile.loading = false;
tile.exists = false; tile.exists = false;
return; return;
} else {
tile.exists = true;
} }
if ( time < this.lastResetTime ) { if ( time < this.lastResetTime ) {
@ -1656,9 +1753,14 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
*/ */
_setTileLoaded: function(tile, data, cutoff, tileRequest) { _setTileLoaded: function(tile, data, cutoff, tileRequest) {
var increment = 0, var increment = 0,
eventFinished = false,
_this = this; _this = this;
function getCompletionCallback() { function getCompletionCallback() {
if (eventFinished) {
$.console.error("Event 'tile-loaded' argument getCompletionCallback must be called synchronously. " +
"Its return value should be called asynchronously.");
}
increment++; increment++;
return completionCallback; return completionCallback;
} }
@ -1700,6 +1802,8 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
* marked as entirely loaded when the callback has been called once for each * marked as entirely loaded when the callback has been called once for each
* call to getCompletionCallback. * call to getCompletionCallback.
*/ */
var fallbackCompletion = getCompletionCallback();
this.viewer.raiseEvent("tile-loaded", { this.viewer.raiseEvent("tile-loaded", {
tile: tile, tile: tile,
tiledImage: this, tiledImage: this,
@ -1711,8 +1815,9 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
data: data, data: data,
getCompletionCallback: getCompletionCallback getCompletionCallback: getCompletionCallback
}); });
eventFinished = true;
// In case the completion callback is never called, we at least force it once. // In case the completion callback is never called, we at least force it once.
getCompletionCallback()(); fallbackCompletion();
}, },
/** /**
@ -1812,28 +1917,49 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
/** /**
* @private * @private
* @inner * @inner
* Determines whether the 'last best' tile for the area is better than the * Determines the 'best tiles' from the given 'last best' tiles and the
* tile in question. * tile in question.
* *
* @param {OpenSeadragon.Tile} previousBest * @param {OpenSeadragon.Tile[]} previousBest The best tiles so far.
* @param {OpenSeadragon.Tile} tile * @param {OpenSeadragon.Tile} tile The new tile to consider.
* @returns {OpenSeadragon.Tile} The new best tile. * @param {Number} maxNTiles The max number of best tiles.
* @returns {OpenSeadragon.Tile[]} The new best tiles.
*/ */
_compareTiles: function( previousBest, tile ) { _compareTiles: function( previousBest, tile, maxNTiles ) {
if ( !previousBest ) { if ( !previousBest ) {
return tile; return [tile];
}
if ( tile.visibility > previousBest.visibility ) {
return tile;
} else if ( tile.visibility === previousBest.visibility ) {
if ( tile.squaredDistance < previousBest.squaredDistance ) {
return tile;
} }
previousBest.push(tile);
this._sortTiles(previousBest);
if (previousBest.length > maxNTiles) {
previousBest.pop();
} }
return previousBest; return previousBest;
}, },
/**
* @private
* @inner
* Sorts tiles in an array according to distance and visibility.
*
* @param {OpenSeadragon.Tile[]} tiles The tiles.
*/
_sortTiles: function( tiles ) {
tiles.sort(function (a, b) {
if (a === null) {
return 1;
}
if (b === null) {
return -1;
}
if (a.visibility === b.visibility) {
return (a.squaredDistance - b.squaredDistance);
} else {
return (a.visibility - b.visibility);
}
});
},
/** /**
* @private * @private
* @inner * @inner
@ -1864,7 +1990,8 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
if (lastDrawn.length > 1 && if (lastDrawn.length > 1 &&
imageZoom > this.smoothTileEdgesMinZoom && imageZoom > this.smoothTileEdgesMinZoom &&
!this.iOSDevice && !this.iOSDevice &&
this.getRotation(true) % 360 === 0 && // TODO: support tile edge smoothing with tiled image rotation. this.getRotation(true) % 360 === 0 && // TODO: support tile edge smoothing with tiled image rotation (viewport rotation is not a problem).
this._drawer.viewer.viewport.getFlip() === false && // TODO: support tile edge smoothing with viewport flip (tiled image flip is not a problem).
$.supportsCanvas && this.viewer.useCanvas) { $.supportsCanvas && this.viewer.useCanvas) {
// When zoomed in a lot (>100%) the tile edges are visible. // When zoomed in a lot (>100%) the tile edges are visible.
// So we have to composite them at ~100% and scale them up together. // So we have to composite them at ~100% and scale them up together.
@ -1954,6 +2081,9 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
if (sketchScale) { if (sketchScale) {
clipPoint = clipPoint.times(sketchScale); clipPoint = clipPoint.times(sketchScale);
} }
if (sketchTranslate) {
clipPoint = clipPoint.plus(sketchTranslate);
}
return clipPoint; return clipPoint;
}); });
}); });

View File

@ -2,7 +2,7 @@
* OpenSeadragon - TileSource * OpenSeadragon - TileSource
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -663,6 +663,11 @@ $.TileSource.prototype = {
* The headers returned here will override headers specified at the Viewer or TiledImage level. * The headers returned here will override headers specified at the Viewer or TiledImage level.
* Specifying a falsy value for a header will clear its existing value set at the Viewer or * Specifying a falsy value for a header will clear its existing value set at the Viewer or
* TiledImage level (if any). * TiledImage level (if any).
*
* Note that the headers of existing tiles don't automatically change when this function
* returns updated headers. To do that, you need to call {@link OpenSeadragon.Viewer#setAjaxHeaders}
* and propagate the changes.
*
* @function * @function
* @param {Number} level * @param {Number} level
* @param {Number} x * @param {Number} x
@ -932,7 +937,7 @@ function processResponse( xhr ){
throw new Error( $.getString( "Errors.Status", status, statusText ) ); throw new Error( $.getString( "Errors.Status", status, statusText ) );
} }
if( responseText.match(/\s*<.*/) ){ if( responseText.match(/^\s*<.*/) ){
try{ try{
data = ( xhr.responseXML && xhr.responseXML.documentElement ) ? data = ( xhr.responseXML && xhr.responseXML.documentElement ) ?
xhr.responseXML : xhr.responseXML :

View File

@ -2,7 +2,7 @@
* OpenSeadragon - TileSourceCollection * OpenSeadragon - TileSourceCollection
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - TmsTileSource * OpenSeadragon - TmsTileSource
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -2,7 +2,7 @@
* OpenSeadragon - Viewer * OpenSeadragon - Viewer
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -307,7 +307,9 @@ $.Viewer = function( options ) {
nonPrimaryPressHandler: $.delegate( this, onCanvasNonPrimaryPress ), nonPrimaryPressHandler: $.delegate( this, onCanvasNonPrimaryPress ),
nonPrimaryReleaseHandler: $.delegate( this, onCanvasNonPrimaryRelease ), nonPrimaryReleaseHandler: $.delegate( this, onCanvasNonPrimaryRelease ),
scrollHandler: $.delegate( this, onCanvasScroll ), scrollHandler: $.delegate( this, onCanvasScroll ),
pinchHandler: $.delegate( this, onCanvasPinch ) pinchHandler: $.delegate( this, onCanvasPinch ),
focusHandler: $.delegate( this, onCanvasFocus ),
blurHandler: $.delegate( this, onCanvasBlur ),
}); });
this.outerTracker = new $.MouseTracker({ this.outerTracker = new $.MouseTracker({
@ -964,7 +966,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
* Turns debugging mode on or off for this viewer. * Turns debugging mode on or off for this viewer.
* *
* @function * @function
* @param {Boolean} true to turn debug on, false to turn debug off. * @param {Boolean} debugMode true to turn debug on, false to turn debug off.
*/ */
setDebugMode: function(debugMode){ setDebugMode: function(debugMode){
@ -976,6 +978,63 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
this.forceRedraw(); this.forceRedraw();
}, },
/**
* Update headers to include when making AJAX requests.
*
* Unless `propagate` is set to false (which is likely only useful in rare circumstances),
* the updated headers are propagated to all tiled images, each of which will subsequently
* propagate the changed headers to all their tiles.
* If applicable, the headers of the viewer's navigator and reference strip will also be updated.
*
* Note that the rules for merging headers still apply, i.e. headers returned by
* {@link OpenSeadragon.TileSource#getTileAjaxHeaders} take precedence over
* `TiledImage.ajaxHeaders`, which take precedence over the headers here in the viewer.
*
* @function
* @param {Object} ajaxHeaders Updated AJAX headers.
* @param {Boolean} [propagate=true] Whether to propagate updated headers to tiled images, etc.
*/
setAjaxHeaders: function(ajaxHeaders, propagate) {
if (ajaxHeaders === null) {
ajaxHeaders = {};
}
if (!$.isPlainObject(ajaxHeaders)) {
console.error('[Viewer.setAjaxHeaders] Ignoring invalid headers, must be a plain object');
return;
}
if (propagate === undefined) {
propagate = true;
}
this.ajaxHeaders = ajaxHeaders;
if (propagate) {
for (var i = 0; i < this.world.getItemCount(); i++) {
this.world.getItemAt(i)._updateAjaxHeaders(true);
}
if (this.navigator) {
this.navigator.setAjaxHeaders(this.ajaxHeaders, true);
}
if (this.referenceStrip && this.referenceStrip.miniViewers) {
for (var key in this.referenceStrip.miniViewers) {
this.referenceStrip.miniViewers[key].setAjaxHeaders(this.ajaxHeaders, true);
}
}
}
},
/**
* Adds the given button to this viewer.
*
* @function
* @param {OpenSeadragon.Button} button
*/
addButton: function( button ){
this.buttonGroup.addButton(button);
},
/** /**
* @function * @function
* @returns {Boolean} * @returns {Boolean}
@ -1390,7 +1449,6 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
* A set of headers to include when making tile AJAX requests. * A set of headers to include when making tile AJAX requests.
* Note that these headers will be merged over any headers specified in {@link OpenSeadragon.Options}. * Note that these headers will be merged over any headers specified in {@link OpenSeadragon.Options}.
* Specifying a falsy value for a header will clear its existing value set at the Viewer level (if any). * Specifying a falsy value for a header will clear its existing value set at the Viewer level (if any).
* requests.
* @param {Function} [options.success] A function that gets called when the image is * @param {Function} [options.success] A function that gets called when the image is
* successfully added. It's passed the event object which contains a single property: * successfully added. It's passed the event object which contains a single property:
* "item", which is the resulting instance of TiledImage. * "item", which is the resulting instance of TiledImage.
@ -1438,10 +1496,8 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
if (options.loadTilesWithAjax === undefined) { if (options.loadTilesWithAjax === undefined) {
options.loadTilesWithAjax = this.loadTilesWithAjax; options.loadTilesWithAjax = this.loadTilesWithAjax;
} }
if (options.ajaxHeaders === undefined || options.ajaxHeaders === null) { if (!$.isPlainObject(options.ajaxHeaders)) {
options.ajaxHeaders = this.ajaxHeaders; options.ajaxHeaders = {};
} else if ($.isPlainObject(options.ajaxHeaders) && $.isPlainObject(this.ajaxHeaders)) {
options.ajaxHeaders = $.extend({}, this.ajaxHeaders, options.ajaxHeaders);
} }
var myQueueItem = { var myQueueItem = {
@ -1548,6 +1604,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
minZoomImageRatio: _this.minZoomImageRatio, minZoomImageRatio: _this.minZoomImageRatio,
wrapHorizontal: _this.wrapHorizontal, wrapHorizontal: _this.wrapHorizontal,
wrapVertical: _this.wrapVertical, wrapVertical: _this.wrapVertical,
maxTilesPerFrame: _this.maxTilesPerFrame,
immediateRender: _this.immediateRender, immediateRender: _this.immediateRender,
blendTime: _this.blendTime, blendTime: _this.blendTime,
alwaysBlend: _this.alwaysBlend, alwaysBlend: _this.alwaysBlend,
@ -2757,7 +2814,7 @@ function onCanvasKeyDown( event ) {
if ( !canvasKeyDownEventArgs.preventDefaultAction && !event.ctrl && !event.alt && !event.meta ) { if ( !canvasKeyDownEventArgs.preventDefaultAction && !event.ctrl && !event.alt && !event.meta ) {
switch( event.keyCode ){ switch( event.keyCode ){
case 38://up arrow case 38://up arrow/shift uparrow
if (!canvasKeyDownEventArgs.preventVerticalPan) { if (!canvasKeyDownEventArgs.preventVerticalPan) {
if ( event.shift ) { if ( event.shift ) {
this.viewport.zoomBy(1.1); this.viewport.zoomBy(1.1);
@ -2768,7 +2825,7 @@ function onCanvasKeyDown( event ) {
} }
event.preventDefault = true; event.preventDefault = true;
break; break;
case 40://down arrow case 40://down arrow/shift downarrow
if (!canvasKeyDownEventArgs.preventVerticalPan) { if (!canvasKeyDownEventArgs.preventVerticalPan) {
if ( event.shift ) { if ( event.shift ) {
this.viewport.zoomBy(0.9); this.viewport.zoomBy(0.9);
@ -2793,6 +2850,84 @@ function onCanvasKeyDown( event ) {
} }
event.preventDefault = true; event.preventDefault = true;
break; break;
case 187://=|+
this.viewport.zoomBy(1.1);
this.viewport.applyConstraints();
event.preventDefault = true;
break;
case 189://-|_
this.viewport.zoomBy(0.9);
this.viewport.applyConstraints();
event.preventDefault = true;
break;
case 48://0|)
this.viewport.goHome();
this.viewport.applyConstraints();
event.preventDefault = true;
break;
case 87://W/w
if (!canvasKeyDownEventArgs.preventVerticalPan) {
if ( event.shift ) {
this.viewport.zoomBy(1.1);
} else {
this.viewport.panBy(this.viewport.deltaPointsFromPixels(new $.Point(0, -40)));
}
this.viewport.applyConstraints();
}
event.preventDefault = true;
break;
case 83://S/s
if (!canvasKeyDownEventArgs.preventVerticalPan) {
if ( event.shift ) {
this.viewport.zoomBy(0.9);
} else {
this.viewport.panBy(this.viewport.deltaPointsFromPixels(new $.Point(0, 40)));
}
this.viewport.applyConstraints();
}
event.preventDefault = true;
break;
case 65://a/A
if (!canvasKeyDownEventArgs.preventHorizontalPan) {
this.viewport.panBy(this.viewport.deltaPointsFromPixels(new $.Point(-40, 0)));
this.viewport.applyConstraints();
}
event.preventDefault = true;
break;
case 68://d/D
if (!canvasKeyDownEventArgs.preventHorizontalPan) {
this.viewport.panBy(this.viewport.deltaPointsFromPixels(new $.Point(40, 0)));
this.viewport.applyConstraints();
}
event.preventDefault = true;
break;
case 82: //r - clockwise rotation/R - counterclockwise rotation
if(event.shift){
if(this.viewport.flipped){
this.viewport.setRotation(this.viewport.getRotation() + this.rotationIncrement);
} else{
this.viewport.setRotation(this.viewport.getRotation() - this.rotationIncrement);
}
}else{
if(this.viewport.flipped){
this.viewport.setRotation(this.viewport.getRotation() - this.rotationIncrement);
} else{
this.viewport.setRotation(this.viewport.getRotation() + this.rotationIncrement);
}
}
this.viewport.applyConstraints();
event.preventDefault = true;
break;
case 70: //f/F
this.viewport.toggleFlip();
event.preventDefault = true;
break;
case 74: //j - previous image source
this.goToPreviousPage();
break;
case 75: //k - next image source
this.goToNextPage();
break;
default: default:
//console.log( 'navigator keycode %s', event.keyCode ); //console.log( 'navigator keycode %s', event.keyCode );
event.preventDefault = false; event.preventDefault = false;
@ -2802,12 +2937,10 @@ function onCanvasKeyDown( event ) {
event.preventDefault = false; event.preventDefault = false;
} }
} }
function onCanvasKeyPress( event ) { function onCanvasKeyPress( event ) {
var canvasKeyPressEventArgs = { var canvasKeyPressEventArgs = {
originalEvent: event.originalEvent, originalEvent: event.originalEvent,
preventDefaultAction: false,
preventVerticalPan: event.preventVerticalPan || !this.panVertical,
preventHorizontalPan: event.preventHorizontalPan || !this.panHorizontal
}; };
/** /**
@ -2818,109 +2951,12 @@ function onCanvasKeyPress( event ) {
* @type {object} * @type {object}
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event. * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
* @property {Object} originalEvent - The original DOM event. * @property {Object} originalEvent - The original DOM event.
* @property {Boolean} preventDefaultAction - Set to true to prevent default keyboard behaviour. Default: false.
* @property {Boolean} preventVerticalPan - Set to true to prevent keyboard vertical panning. Default: false.
* @property {Boolean} preventHorizontalPan - Set to true to prevent keyboard horizontal panning. Default: false.
* @property {?Object} userData - Arbitrary subscriber-defined object. * @property {?Object} userData - Arbitrary subscriber-defined object.
*/ */
this.raiseEvent('canvas-key-press', canvasKeyPressEventArgs); this.raiseEvent('canvas-key-press', canvasKeyPressEventArgs);
if ( !canvasKeyPressEventArgs.preventDefaultAction && !event.ctrl && !event.alt && !event.meta ) {
switch( event.keyCode ){
case 43://=|+
case 61://=|+
this.viewport.zoomBy(1.1);
this.viewport.applyConstraints();
event.preventDefault = true;
break;
case 45://-|_
this.viewport.zoomBy(0.9);
this.viewport.applyConstraints();
event.preventDefault = true;
break;
case 48://0|)
this.viewport.goHome();
this.viewport.applyConstraints();
event.preventDefault = true;
break;
case 119://w
case 87://W
if (!canvasKeyPressEventArgs.preventVerticalPan) {
if ( event.shift ) {
this.viewport.zoomBy(1.1);
} else {
this.viewport.panBy(this.viewport.deltaPointsFromPixels(new $.Point(0, -40)));
}
this.viewport.applyConstraints();
}
event.preventDefault = true;
break;
case 115://s
case 83://S
if (!canvasKeyPressEventArgs.preventVerticalPan) {
if ( event.shift ) {
this.viewport.zoomBy(0.9);
} else {
this.viewport.panBy(this.viewport.deltaPointsFromPixels(new $.Point(0, 40)));
}
this.viewport.applyConstraints();
}
event.preventDefault = true;
break;
case 97://a
if (!canvasKeyPressEventArgs.preventHorizontalPan) {
this.viewport.panBy(this.viewport.deltaPointsFromPixels(new $.Point(-40, 0)));
this.viewport.applyConstraints();
}
event.preventDefault = true;
break;
case 100://d
if (!canvasKeyPressEventArgs.preventHorizontalPan) {
this.viewport.panBy(this.viewport.deltaPointsFromPixels(new $.Point(40, 0)));
this.viewport.applyConstraints();
}
event.preventDefault = true;
break;
case 114: //r - clockwise rotation
if(this.viewport.flipped){
this.viewport.setRotation(this.viewport.getRotation() - this.rotationIncrement);
} else{
this.viewport.setRotation(this.viewport.getRotation() + this.rotationIncrement);
}
this.viewport.applyConstraints();
event.preventDefault = true;
break;
case 82: //R - counterclockwise rotation
if(this.viewport.flipped){
this.viewport.setRotation(this.viewport.getRotation() + this.rotationIncrement);
} else{
this.viewport.setRotation(this.viewport.getRotation() - this.rotationIncrement);
}
this.viewport.applyConstraints();
event.preventDefault = true;
break;
case 102: //f
this.viewport.toggleFlip();
event.preventDefault = true;
break;
case 106: //j - previous image source
this.goToPreviousPage();
break;
case 107: //k - next image source
this.goToNextPage();
break;
default:
// console.log( 'navigator keycode %s', event.keyCode );
event.preventDefault = false;
break;
}
} else {
event.preventDefault = false;
}
} }
function onCanvasClick( event ) { function onCanvasClick( event ) {
var gestureSettings; var gestureSettings;
@ -3431,11 +3467,49 @@ function onCanvasPinch( event ) {
event.gesturePoints[0].currentPos.x - event.gesturePoints[1].currentPos.x); event.gesturePoints[0].currentPos.x - event.gesturePoints[1].currentPos.x);
var angle2 = Math.atan2(event.gesturePoints[0].lastPos.y - event.gesturePoints[1].lastPos.y, var angle2 = Math.atan2(event.gesturePoints[0].lastPos.y - event.gesturePoints[1].lastPos.y,
event.gesturePoints[0].lastPos.x - event.gesturePoints[1].lastPos.x); event.gesturePoints[0].lastPos.x - event.gesturePoints[1].lastPos.x);
this.viewport.setRotation(this.viewport.getRotation() + ((angle1 - angle2) * (180 / Math.PI))); centerPt = this.viewport.pointFromPixel( event.center, true );
this.viewport.rotateTo(this.viewport.getRotation(true) + ((angle1 - angle2) * (180 / Math.PI)), centerPt, true);
} }
} }
} }
function onCanvasFocus( event ) {
/**
* Raised when the {@link OpenSeadragon.Viewer#canvas} element gets keyboard focus.
*
* @event canvas-focus
* @memberof OpenSeadragon.Viewer
* @type {object}
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
* @property {OpenSeadragon.MouseTracker} tracker - A reference to the MouseTracker which originated this event.
* @property {Object} originalEvent - The original DOM event.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
this.raiseEvent( 'canvas-focus', {
tracker: event.eventSource,
originalEvent: event.originalEvent
});
}
function onCanvasBlur( event ) {
/**
* Raised when the {@link OpenSeadragon.Viewer#canvas} element loses keyboard focus.
*
* @event canvas-blur
* @memberof OpenSeadragon.Viewer
* @type {object}
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
* @property {OpenSeadragon.MouseTracker} tracker - A reference to the MouseTracker which originated this event.
* @property {Object} originalEvent - The original DOM event.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
this.raiseEvent( 'canvas-blur', {
tracker: event.eventSource,
originalEvent: event.originalEvent
});
}
function onCanvasScroll( event ) { function onCanvasScroll( event ) {
var canvasScrollEventArgs, var canvasScrollEventArgs,
gestureSettings, gestureSettings,

View File

@ -2,7 +2,7 @@
* OpenSeadragon - Viewport * OpenSeadragon - Viewport
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -711,6 +711,8 @@ $.Viewport.prototype = {
if(constraints){ if(constraints){
this.panTo(center, false); this.panTo(center, false);
newZoom = this._applyZoomConstraints(newZoom);
this.zoomTo(newZoom, null, false); this.zoomTo(newZoom, null, false);
var constrainedBounds = this.getConstrainedBounds(); var constrainedBounds = this.getConstrainedBounds();
@ -1076,7 +1078,10 @@ $.Viewport.prototype = {
if( this.viewer ){ if( this.viewer ){
/** /**
* Raised when the viewer is resized (see {@link OpenSeadragon.Viewport#resize}). * Raised when a viewer resize operation is initiated (see {@link OpenSeadragon.Viewport#resize}).
* This event happens before the viewport bounds have been updated.
* See also {@link OpenSeadragon.Viewer#after-resize} which reflects
* the new viewport bounds following the resize action.
* *
* @event resize * @event resize
* @memberof OpenSeadragon.Viewer * @memberof OpenSeadragon.Viewer
@ -1092,7 +1097,29 @@ $.Viewport.prototype = {
}); });
} }
return this.fitBounds( newBounds, true ); var output = this.fitBounds( newBounds, true );
if( this.viewer ){
/**
* Raised after the viewer is resized (see {@link OpenSeadragon.Viewport#resize}).
* See also {@link OpenSeadragon.Viewer#resize} event which happens
* before the new bounds have been calculated and applied.
*
* @event after-resize
* @memberof OpenSeadragon.Viewer
* @type {object}
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
* @property {OpenSeadragon.Point} newContainerSize
* @property {Boolean} maintain
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
this.viewer.raiseEvent( 'after-resize', {
newContainerSize: newContainerSize,
maintain: maintain
});
}
return output;
}, },
// private // private

View File

@ -2,7 +2,7 @@
* OpenSeadragon - World * OpenSeadragon - World
* *
* Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2009 CodePlex Foundation
* Copyright (C) 2010-2022 OpenSeadragon contributors * Copyright (C) 2010-2023 OpenSeadragon contributors
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>OpenSeadragon QUnit</title> <title>OpenSeadragon QUnit</title>
<link rel="stylesheet" href="/node_modules/qunitjs/qunit/qunit.css"> <link rel="stylesheet" href="/node_modules/qunit/qunit/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/lib/jquery-ui-1.10.2/css/smoothness/jquery-ui-1.10.2.min.css">
<link rel="stylesheet" href="/test/helpers/test.css"> <link rel="stylesheet" href="/test/helpers/test.css">
</head> </head>
@ -15,7 +15,7 @@
var isCoverageTest = true; var isCoverageTest = true;
</script> </script>
<script src="/node_modules/qunitjs/qunit/qunit.js"></script> <script src="/node_modules/qunit/qunit/qunit.js"></script>
<script src="/test/lib/jquery-1.9.1.min.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-ui-1.10.2/js/jquery-ui-1.10.2.min.js"></script>
<script src="/test/lib/jquery.simulate.js"></script> <script src="/test/lib/jquery.simulate.js"></script>

View File

@ -20,5 +20,6 @@
"gif" "gif"
] ]
} }
] ],
"xmp": "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n <rdf:Description rdf:about=\"\"\n xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\"\n xmlns:aux=\"http://ns.adobe.com/exif/1.0/aux/\"\n xmlns:photoshop=\"http://ns.adobe.com/photoshop/1.0/\"\n xmlns:Iptc4xmpCore=\"http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/\"\n xmlns:tiff=\"http://ns.adobe.com/tiff/1.0/\"\n xmlns:exif=\"http://ns.adobe.com/exif/1.0/\"\n xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n xmp:CreatorTool=\"Capture One 11 Macintosh\"\n xmp:CreateDate=\"2019-08-21T20:54:20\"\n xmp:Rating=\"4\"\n aux:SerialNumber=\"GP001601\"\n aux:ImageNumber=\"30012\"\n aux:Firmware=\"IQ280, Factory Firmware: 8.05.36\"\n photoshop:CaptionWriter=\"\"\n photoshop:Headline=\"\"\n photoshop:City=\"\"\n photoshop:State=\"\"\n photoshop:Country=\"\"\n photoshop:Source=\"\"\n photoshop:Instructions=\"\"\n photoshop:AuthorsPosition=\"\"\n photoshop:TransmissionReference=\"\"\n photoshop:Credit=\"\"\n photoshop:LegacyIPTCDigest=\"B135BFFD6A4CFB049F834A3F370A9AE3\"\n photoshop:DateCreated=\"2019-08-21T20:54:20\"\n Iptc4xmpCore:Location=\"\"\n Iptc4xmpCore:IntellectualGenre=\"\"\n Iptc4xmpCore:CountryCode=\"\"\n tiff:ImageWidth=\"2088\"\n tiff:ImageLength=\"3000\"\n tiff:Compression=\"1\"\n tiff:PhotometricInterpretation=\"2\"\n tiff:Orientation=\"1\"\n tiff:SamplesPerPixel=\"3\"\n tiff:PlanarConfiguration=\"1\"\n tiff:XResolution=\"400/1\"\n tiff:YResolution=\"400/1\"\n tiff:ResolutionUnit=\"2\"\n tiff:Make=\"Phase One\"\n tiff:Model=\"IQ280\"\n tiff:Software=\"Capture One 11 Macintosh\"\n exif:ExifVersion=\"0230\"\n exif:PixelXDimension=\"2088\"\n exif:PixelYDimension=\"3000\"\n exif:ExposureTime=\"1/4\"\n exif:ExposureProgram=\"1\"\n exif:ShutterSpeedValue=\"2/1\"\n exif:MeteringMode=\"1\"\n exif:LightSource=\"255\"\n exif:FocalPlaneXResolution=\"63015385/32768\"\n exif:FocalPlaneYResolution=\"63015385/32768\"\n exif:FocalPlaneResolutionUnit=\"3\"\n exif:FileSource=\"3\"\n exif:SceneType=\"1\"\n exif:WhiteBalance=\"5\"\n exif:ImageUniqueID=\"00E058000075000004019E064100753C\">\n <Iptc4xmpCore:CreatorContactInfo\n Iptc4xmpCore:CiEmailWork=\"digicc@library.illinois.edu\"\n Iptc4xmpCore:CiTelWork=\"+1(217)2442062\"\n Iptc4xmpCore:CiAdrPcode=\"61801\"\n Iptc4xmpCore:CiUrlWork=\"http://www.library.illinois.edu/staff/preservation/digitization/\"\n Iptc4xmpCore:CiAdrExtadr=\"1408 W. Gregory Drive\"\n Iptc4xmpCore:CiAdrCity=\"Urbana\"\n Iptc4xmpCore:CiAdrCtry=\"United States\"\n Iptc4xmpCore:CiAdrRegion=\"Illinois\"/>\n <tiff:BitsPerSample>\n <rdf:Seq>\n <rdf:li>8 8 8</rdf:li>\n </rdf:Seq>\n </tiff:BitsPerSample>\n <exif:ISOSpeedRatings>\n <rdf:Seq>\n <rdf:li>50</rdf:li>\n </rdf:Seq>\n </exif:ISOSpeedRatings>\n <dc:creator>\n <rdf:Seq>\n <rdf:li>University of Illinois Library</rdf:li>\n </rdf:Seq>\n </dc:creator>\n </rdf:Description>\n </rdf:RDF>"
} }

View File

@ -25,7 +25,7 @@
id: "contentDiv", id: "contentDiv",
prefixUrl: "../../build/openseadragon/images/", prefixUrl: "../../build/openseadragon/images/",
tileSources: "../data/testpattern.dzi", tileSources: "../data/testpattern.dzi",
showNavigator:true showNavigator: true
}); });
</script> </script>
</body> </body>

View File

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<title>OpenSeadragon maxTilesPerFrame 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>
<style type="text/css">
.openseadragon1 {
width: 100vw;
height: 100vh;
}
</style>
</head>
<body>
<div>
Simple demo page to show an OpenSeadragon viewer with a higher maxTilesPerFrame.
</div>
<div id="contentDiv" class="openseadragon1"></div>
<script type="text/javascript">
var viewer = OpenSeadragon({
debugMode: true,
id: "contentDiv",
prefixUrl: "../../build/openseadragon/images/",
tileSources: "https://openseadragon.github.io/example-images/duomo/duomo.dzi",
showNavigator:true,
debugMode:true,
maxTilesPerFrame:3,
});
</script>
</body>
</html>

View File

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<title>OpenSeadragon Basic 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>
<style type="text/css">
.openseadragon1 {
width: 800px;
height: 600px;
}
</style>
</head>
<body>
<div>
Simple demo page. The navigator region is expected to rotate when the image is rotated.
The default behaviour is to keep the region still as the image below it rotates.
</div>
<div id="contentDiv" class="openseadragon1"></div>
<script type="text/javascript">
var viewer = OpenSeadragon({
// debugMode: true,
id: "contentDiv",
prefixUrl: "../../build/openseadragon/images/",
tileSources: "../data/testpattern.dzi",
showNavigator: true,
navigatorRotate: false
});
viewer.viewport.setRotation(45)
</script>
</body>
</html>

View File

@ -245,4 +245,130 @@
tileSource: staticHeaderTileSource tileSource: staticHeaderTileSource
}); });
}); });
QUnit.test('Viewer headers can be updated', function(assert) {
var done = assert.async();
var newHeaders = {
'X-Viewer-Header': 'ViewerHeaderValue-Updated',
'X-Viewer-Header2': 'ViewerHeaderValue2'
}
var newHeaders2 = {
Range: 'test',
}
var tileLoaded = function tileLoaded(evt) {
viewer.removeHandler('tile-loaded', tileLoaded);
// set new Viewer headers and propagate to TiledImage and Tile
viewer.setAjaxHeaders(newHeaders);
viewer.addHandler('tile-loaded', tileLoaded2);
};
var tileLoaded2 = function tileLoaded(evt) {
viewer.removeHandler('tile-loaded', tileLoaded2);
assert.deepEqual(viewer.ajaxHeaders, newHeaders);
assert.deepEqual(evt.tiledImage.ajaxHeaders, newHeaders);
assert.deepEqual(
evt.tile.ajaxHeaders,
OpenSeadragon.extend(
{}, viewer.ajaxHeaders, evt.tiledImage.ajaxHeaders,
{ Range: getTileRangeHeader(evt.tile.level, evt.tile.x, evt.tile.y) }
)
);
// set new Viewer headers and propagate to TiledImage and Tile
viewer.setAjaxHeaders(newHeaders2, true);
viewer.addHandler('tile-loaded', tileLoaded3);
};
var tileLoaded3 = function tileLoaded(evt) {
viewer.removeHandler('tile-loaded', tileLoaded3);
assert.deepEqual(viewer.ajaxHeaders, newHeaders2);
assert.deepEqual(evt.tiledImage.ajaxHeaders, newHeaders2);
assert.equal(evt.tile.ajaxHeaders['X-Viewer-Header'], undefined);
assert.equal(evt.tile.ajaxHeaders['X-Viewer-Header2'], undefined);
// 'Range' header entry set per tile and must not be overwritten by Viewer header
assert.equal(evt.tile.ajaxHeaders.Range, getTileRangeHeader(evt.tile.level, evt.tile.x, evt.tile.y));
// set new Viewer headers but do not propagate to TiledImage and Tile
viewer.setAjaxHeaders(newHeaders, false);
viewer.addHandler('tile-loaded', tileLoaded4);
};
var tileLoaded4 = function tileLoaded(evt) {
viewer.removeHandler('tile-loaded', tileLoaded4);
assert.deepEqual(viewer.ajaxHeaders, newHeaders);
assert.deepEqual(evt.tiledImage.ajaxHeaders, newHeaders2);
assert.equal(evt.tile.ajaxHeaders['X-Viewer-Header'], undefined);
assert.equal(evt.tile.ajaxHeaders['X-Viewer-Header2'], undefined);
done();
};
viewer.addHandler('tile-loaded', tileLoaded);
viewer.open(customTileSource);
});
QUnit.test('TiledImage headers can be updated', function(assert) {
var done = assert.async();
var tileSourceHeaders = {
'X-Tile-Header': 'TileHeaderValue'
}
var newHeaders = {
'X-TiledImage-Header': 'TiledImageHeaderValue-Updated',
'X-TiledImage-Header2': 'TiledImageHeaderValue2'
}
var newHeaders2 = {
'X-Viewer-Header': 'ViewerHeaderValue-Updated',
'X-Tile-Header': 'TileHeaderValue-Updated'
}
var tileLoaded = function tileLoaded(evt) {
viewer.removeHandler('tile-loaded', tileLoaded);
// set new TiledImage headers and propagate to Tile
evt.tiledImage.setAjaxHeaders(newHeaders);
viewer.addHandler('tile-loaded', tileLoaded2);
};
var tileLoaded2 = function tileLoaded(evt) {
viewer.removeHandler('tile-loaded', tileLoaded2);
assert.deepEqual(viewer.ajaxHeaders, { 'X-Viewer-Header': 'ViewerHeaderValue' });
assert.deepEqual(evt.tiledImage._ownAjaxHeaders, newHeaders);
assert.deepEqual(evt.tiledImage.ajaxHeaders, OpenSeadragon.extend({}, viewer.ajaxHeaders, newHeaders));
assert.deepEqual(evt.tile.ajaxHeaders, OpenSeadragon.extend({}, viewer.ajaxHeaders, newHeaders, tileSourceHeaders));
// set new TiledImage headers (that overwrite header entries of Viewer and Tile) and propagate to Tile
evt.tiledImage.setAjaxHeaders(newHeaders2, true);
viewer.addHandler('tile-loaded', tileLoaded3);
};
var tileLoaded3 = function tileLoaded(evt) {
viewer.removeHandler('tile-loaded', tileLoaded3);
assert.deepEqual(viewer.ajaxHeaders, { 'X-Viewer-Header': 'ViewerHeaderValue' });
assert.deepEqual(evt.tiledImage._ownAjaxHeaders, newHeaders2);
assert.deepEqual(evt.tiledImage.ajaxHeaders, OpenSeadragon.extend({}, viewer.ajaxHeaders, newHeaders2));
assert.deepEqual(evt.tile.ajaxHeaders, OpenSeadragon.extend({}, viewer.ajaxHeaders, newHeaders2, tileSourceHeaders));
// set new TiledImage headers but do not propagate to Tile
evt.tiledImage.setAjaxHeaders(null, false);
viewer.addHandler('tile-loaded', tileLoaded4);
};
var tileLoaded4 = function tileLoaded(evt) {
viewer.removeHandler('tile-loaded', tileLoaded4);
assert.deepEqual(viewer.ajaxHeaders, { 'X-Viewer-Header': 'ViewerHeaderValue' });
assert.deepEqual(evt.tiledImage._ownAjaxHeaders, {});
assert.deepEqual(evt.tiledImage.ajaxHeaders, viewer.ajaxHeaders);
assert.deepEqual(evt.tile.ajaxHeaders, OpenSeadragon.extend({}, viewer.ajaxHeaders, newHeaders2, tileSourceHeaders));
done();
};
viewer.addHandler('tile-loaded', tileLoaded);
viewer.addTiledImage({
ajaxHeaders: {
'X-TiledImage-Header': 'TiledImageHeaderValue'
},
tileSource: OpenSeadragon.extend({}, customTileSource, {
getTileAjaxHeaders: function() {
return tileSourceHeaders;
}
}),
});
});
})(); })();

View File

@ -224,32 +224,43 @@
}); });
QUnit.test('FullScreen', function(assert) { QUnit.test('FullScreen', function(assert) {
var done = assert.async(); const done = assert.async();
if (!OpenSeadragon.supportsFullScreen) { if (!OpenSeadragon.supportsFullScreen) {
assert.expect(0); assert.expect(0);
done(); done();
return; return;
} }
viewer.addHandler("open", function () { viewer.addHandler('open', function () {
assert.ok(!OpenSeadragon.isFullScreen(), 'Started out not fullscreen'); assert.ok(!OpenSeadragon.isFullScreen(), 'Started out not fullscreen');
var checkEnteringPreFullScreen = function(event) { const checkEnteringPreFullScreen = (event) => {
viewer.removeHandler('pre-full-screen', checkEnteringPreFullScreen); viewer.removeHandler('pre-full-screen', checkEnteringPreFullScreen);
assert.ok(event.fullScreen, 'Switching to fullscreen'); assert.ok(event.fullScreen, 'Switching to fullscreen');
assert.ok(!OpenSeadragon.isFullScreen(), 'Not yet fullscreen'); assert.ok(!OpenSeadragon.isFullScreen(), 'Not yet fullscreen');
}; };
// The fullscreen mode is always denied during tests so we are const checkExitingFullScreen = (event) => {
// exiting directly.
var checkExitingFullScreen = function(event) {
viewer.removeHandler('full-screen', checkExitingFullScreen); viewer.removeHandler('full-screen', checkExitingFullScreen);
assert.ok(!event.fullScreen, 'Exiting fullscreen'); assert.ok(!event.fullScreen, 'Disabling fullscreen');
assert.ok(!OpenSeadragon.isFullScreen(), 'Disabled fullscreen'); assert.ok(!OpenSeadragon.isFullScreen(), 'Fullscreen disabled');
done(); done();
}
// The 'new' headless mode allows us to enter fullscreen, so verify
// that we see the correct values returned. We will then close out
// of fullscreen to check the same values when exiting.
const checkAcquiredFullScreen = (event) => {
viewer.removeHandler('full-screen', checkAcquiredFullScreen);
viewer.addHandler('full-screen', checkExitingFullScreen);
assert.ok(event.fullScreen, 'Acquired fullscreen');
assert.ok(OpenSeadragon.isFullScreen(), 'Fullscreen enabled');
viewer.setFullScreen(false);
}; };
viewer.addHandler("pre-full-screen", checkEnteringPreFullScreen);
viewer.addHandler("full-screen", checkExitingFullScreen);
viewer.addHandler('pre-full-screen', checkEnteringPreFullScreen);
viewer.addHandler('full-screen', checkAcquiredFullScreen);
viewer.setFullScreen(true); viewer.setFullScreen(true);
}); });

View File

@ -3,14 +3,14 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>OpenSeadragon QUnit</title> <title>OpenSeadragon QUnit</title>
<link rel="stylesheet" href="/node_modules/qunitjs/qunit/qunit.css"> <link rel="stylesheet" href="/node_modules/qunit/qunit/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/lib/jquery-ui-1.10.2/css/smoothness/jquery-ui-1.10.2.min.css">
<link rel="stylesheet" href="/test/helpers/test.css"> <link rel="stylesheet" href="/test/helpers/test.css">
</head> </head>
<body> <body>
<div id="qunit"></div> <div id="qunit"></div>
<div id="qunit-fixture"></div> <div id="qunit-fixture"></div>
<script src="/node_modules/qunitjs/qunit/qunit.js"></script> <script src="/node_modules/qunit/qunit/qunit.js"></script>
<script src="/test/lib/jquery-1.9.1.min.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-ui-1.10.2/js/jquery-ui-1.10.2.min.js"></script>
<script src="/test/lib/jquery.simulate.js"></script> <script src="/test/lib/jquery.simulate.js"></script>