diff --git a/CITATION.cff b/CITATION.cff index bc1e4a8b..4704b183 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -35,5 +35,5 @@ keywords: - high-resolution - iiif license: BSD-3-Clause -version: 4.1.1 -date-released: 2024-04-01 +version: 5.0.0 +date-released: 2024-08-14 diff --git a/changelog.txt b/changelog.txt index d49699cb..08023eaa 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,19 +1,25 @@ OPENSEADRAGON CHANGELOG ======================= -5.0.0: (in progress...) +5.0.1: (in progress...) -* BREAKING CHANGE: Dropped support for IE11 (#2300, #2361 @AndrewADev) +5.0.0: + +* BREAKING CHANGE: Dropped support for IE11 (#2300, #2361, #2553 @AndrewADev, @msalsbery) * DEPRECATION: The OpenSeadragon.createCallback function is no longer recommended (#2367 @akansjain) -* The viewer now uses WebGL when available (#2310, #2462, #2466, #2468, #2469, #2472, #2478, #2488, #2492 @pearcetm, @Aiosa, @thec0keman) +* The viewer now uses WebGL when available (#2310, #2462, #2466, #2468, #2469, #2472, #2478, #2488, #2492, #2521, #2537, #2557, #2558 @pearcetm, @Aiosa, @thec0keman) * Added webp to supported image formats (#2455 @BeebBenjamin) +* Added avif to supported image formats (#2544 @msalsbery) * Introduced maxTilesPerFrame option to allow loading more tiles simultaneously (#2387 @jetic83) * Now when creating a viewer or navigator, we leave its position style alone if possible (#2393 @VIRAT9358) * Added getter & setter for Viewport.maxZoomPixelRatio (#2506 @eug-L) +* Overlays are now positioned properly when the viewport is flipped (#2546 @BeebBenjamin) +* Added overlayPreserveContentDirection option to keep overlays readable when viewport is flipped (#2546 @BeebBenjamin) * Test improvements (#2382 @AndrewADev) * MouseTracker options documentation fixes (#2389 @msalsbery) * Improved documentation and error message for Viewport.imageToViewportZoom (#2505 @eug-L) * Fixed documentation typos (#2507 @frameflare) +* Additional documentation fixes (#2563 @msalsbery) * Fixed: Sometimes if the viewport was flipped and the user zoomed in far enough, it would flip back (#2364 @SebDelile) * Fixed: Two-finger tap on a Mac trackpad would zoom you out (#2431 @cavenel) * Fixed: dragToPan gesture could not be disabled when flickEnabled was activated (#2464 @jonasengelmann) @@ -22,6 +28,7 @@ OPENSEADRAGON CHANGELOG * Fixed: The navigator wouldn't update its tracking rectangle when the navigator was resized (#2491 @pearcetm) * Fixed: The drawer would improperly crop when the viewport was flipped and a tiled image was rotated (#2511 @pearcetm, @eug-L) * Fixed: Flipped viewport caused image to be flipped again when going fullscreen or resizing (#2518 @pearcetm) +* Fixed: Viewer ajax options (loadTilesWithAjax, ajaxHeaders, and ajaxWithCredentials) weren't being propogated to the navigator. (#2539 @eug-L) 4.1.1: diff --git a/package-lock.json b/package-lock.json index f123990b..ed1e1e9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "openseadragon", - "version": "4.1.0", + "version": "4.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "openseadragon", - "version": "4.1.0", + "version": "4.1.1", "license": "BSD-3-Clause", "devDependencies": { "eslint-plugin-compat": "^4.1.2", @@ -571,6 +571,18 @@ "concat-map": "0.0.1" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/browserslist": { "version": "4.21.5", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", @@ -656,9 +668,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001456", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001456.tgz", - "integrity": "sha512-XFHJY5dUgmpMV25UqaD4kVq2LsiaU5rS8fb0f17pCoXQiQslzmFgnfOxfvo1bTpTqf7dwG/N/05CnLCnOEKmzA==", + "version": "1.0.30001636", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz", + "integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==", "dev": true, "funding": [ { @@ -668,8 +680,13 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "2.4.2", @@ -1735,6 +1752,18 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/finalhandler": { "version": "1.1.2", "dev": true, @@ -1767,39 +1796,6 @@ "node": ">= 10.13.0" } }, - "node_modules/findup-sync/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/findup-sync/node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/findup-sync/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/findup-sync/node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -1813,18 +1809,6 @@ "node": ">=8.6" } }, - "node_modules/findup-sync/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/fined": { "version": "1.2.0", "dev": true, @@ -3097,6 +3081,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-number-like": { "version": "1.0.8", "dev": true, @@ -3348,28 +3341,6 @@ "node": ">=10" } }, - "node_modules/liftup/node_modules/braces": { - "version": "3.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/liftup/node_modules/fill-range": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/liftup/node_modules/findup-sync": { "version": "4.0.0", "dev": true, @@ -3384,14 +3355,6 @@ "node": ">= 8" } }, - "node_modules/liftup/node_modules/is-number": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/liftup/node_modules/micromatch": { "version": "4.0.5", "dev": true, @@ -3404,17 +3367,6 @@ "node": ">=8.6" } }, - "node_modules/liftup/node_modules/to-regex-range": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -4765,6 +4717,18 @@ "dev": true, "license": "MIT" }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "dev": true, diff --git a/package.json b/package.json index 7654a199..728ee569 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openseadragon", - "version": "4.1.1", + "version": "5.0.0", "description": "Provides a smooth, zoomable user interface for HTML/Javascript.", "keywords": [ "image", @@ -48,4 +48,4 @@ "test": "grunt test", "prepare": "grunt build" } -} \ No newline at end of file +} diff --git a/src/button.js b/src/button.js index 34d1f27a..aeb9df92 100644 --- a/src/button.js +++ b/src/button.js @@ -167,13 +167,6 @@ $.Button = function( options ) { this.imgDown.style.visibility = "hidden"; - if ($.Browser.vendor === $.BROWSERS.FIREFOX && $.Browser.version < 3) { - this.imgGroup.style.top = - this.imgHover.style.top = - this.imgDown.style.top = - ""; - } - this.element.appendChild( this.imgRest ); this.element.appendChild( this.imgGroup ); this.element.appendChild( this.imgHover ); diff --git a/src/imagetilesource.js b/src/imagetilesource.js index aab005a2..7b02bc0e 100644 --- a/src/imagetilesource.js +++ b/src/imagetilesource.js @@ -249,10 +249,12 @@ $.ImageTileSource = class extends $.TileSource { return levels.reverse(); } + _createContext2D(data, w, h) { const canvas = document.createElement("canvas"), context = canvas.getContext("2d"); + canvas.width = w; canvas.height = h; context.drawImage(data, 0, 0, w, h); diff --git a/src/mousetracker.js b/src/mousetracker.js index 2a0b6a3c..e56cb609 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -1116,10 +1116,9 @@ /** * Detect available mouse wheel event name. */ - $.MouseTracker.wheelEventName = ( $.Browser.vendor === $.BROWSERS.IE && $.Browser.version > 8 ) || - ( 'onwheel' in document.createElement( 'div' ) ) ? 'wheel' : // Modern browsers support 'wheel' - document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least 'mousewheel' - 'DOMMouseScroll'; // Assume old Firefox + $.MouseTracker.wheelEventName = ( 'onwheel' in document.createElement( 'div' ) ) ? 'wheel' : // Modern browsers support 'wheel' + document.onmousewheel !== undefined ? 'mousewheel' : // Webkit (and unsupported IE) support at least 'mousewheel' + 'DOMMouseScroll'; // Assume old Firefox (deprecated) /** * Detect browser pointer device event model(s) and build appropriate list of events to subscribe to. @@ -1132,7 +1131,7 @@ } if ( window.PointerEvent ) { - // IE11 and other W3C Pointer Event implementations (see http://www.w3.org/TR/pointerevents) + // W3C Pointer Event implementations (see http://www.w3.org/TR/pointerevents) $.MouseTracker.havePointerEvents = true; $.MouseTracker.subscribeEvents.push( "pointerenter", "pointerleave", "pointerover", "pointerout", "pointerdown", "pointerup", "pointermove", "pointercancel" ); // Pointer events capture support @@ -1671,7 +1670,6 @@ /** * Gets a W3C Pointer Events model compatible pointer type string from a DOM pointer event. - * IE10 used a long integer value, but the W3C specification (and IE11+) use a string "mouse", "touch", "pen", etc. * * Note: Called for both pointer events and legacy mouse events * ($.MouseTracker.havePointerEvents determines which) @@ -1679,14 +1677,7 @@ * @inner */ function getPointerType( event ) { - if ( $.MouseTracker.havePointerEvents ) { - // Note: IE pointer events bug - sends invalid pointerType on lostpointercapture events - // and possibly other events. We rely on sane, valid property values in DOM events, so for - // IE, when the pointerType is missing, we'll default to 'mouse'...should be right most of the time - return event.pointerType || (( $.Browser.vendor === $.BROWSERS.IE ) ? 'mouse' : ''); - } else { - return 'mouse'; - } + return $.MouseTracker.havePointerEvents && event.pointerType ? event.pointerType : 'mouse'; } @@ -2554,15 +2545,14 @@ }; // Most browsers implicitly capture touch pointer events - // Note no IE versions have element.hasPointerCapture() so no implicit - // pointer capture possible + // Note no IE versions (unsupported) have element.hasPointerCapture() so + // no implicit pointer capture possible // var implicitlyCaptured = ($.MouseTracker.havePointerEvents && // event.target.hasPointerCapture && // $.Browser.vendor !== $.BROWSERS.IE) ? // event.target.hasPointerCapture(event.pointerId) : false; var implicitlyCaptured = $.MouseTracker.havePointerEvents && - gPoint.type === 'touch' && - $.Browser.vendor !== $.BROWSERS.IE; + gPoint.type === 'touch'; //$.console.log('pointerdown ' + (tracker.userData ? tracker.userData.toString() : '') + ' ' + (event.target === tracker.element ? 'tracker.element' : '')); diff --git a/src/navigator.js b/src/navigator.js index fb95e4b1..3329ed14 100644 --- a/src/navigator.js +++ b/src/navigator.js @@ -178,7 +178,6 @@ $.Navigator = function( options ){ style['float'] = 'left'; //Webkit style.cssFloat = 'left'; //Firefox - style.styleFloat = 'left'; //IE style.zIndex = 999999999; style.cursor = 'default'; style.boxSizing = 'content-box'; diff --git a/src/openseadragon.js b/src/openseadragon.js index 0326b28f..eb88d068 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -240,6 +240,11 @@ * @property {Boolean} [flipped=false] * Initial flip state. * + * @property {Boolean} [overlayPreserveContentDirection=true] + * When the viewport is flipped (by pressing 'f'), the overlay is flipped using ScaleX. + * Normally, this setting (default true) keeps the overlay's content readable by flipping it back. + * To make the content flip with the overlay, set overlayPreserveContentDirection to false. + * * @property {Number} [minZoomLevel=null] * * @property {Number} [maxZoomLevel=null] @@ -1078,8 +1083,9 @@ function OpenSeadragon( options ){ /** * A ratio comparing the device screen's pixel density to the canvas's backing store pixel density, * clamped to a minimum of 1. Defaults to 1 if canvas isn't supported by the browser. - * @member {Number} pixelDensityRatio + * @function getCurrentPixelDensityRatio * @memberof OpenSeadragon + * @returns {Number} */ $.getCurrentPixelDensityRatio = function() { if ( $.supportsCanvas ) { @@ -1097,6 +1103,8 @@ function OpenSeadragon( options ){ }; /** + * A ratio comparing the device screen's pixel density to the canvas's backing store pixel density, + * clamped to a minimum of 1. Defaults to 1 if canvas isn't supported by the browser. * @member {Number} pixelDensityRatio * @memberof OpenSeadragon */ @@ -1371,7 +1379,8 @@ function OpenSeadragon( options ){ degrees: 0, // INITIAL FLIP STATE - flipped: false, + flipped: false, + overlayPreserveContentDirection: true, // APPEARANCE opacity: 1, // to be passed into each TiledImage @@ -2335,43 +2344,18 @@ function OpenSeadragon( options ){ /** * Create an XHR object * @private - * @param {type} [local] If set to true, the XHR will be file: protocol - * compatible if possible (but may raise a warning in the browser). + * @param {type} [local] Deprecated. Ignored (IE/ActiveXObject file protocol no longer supported). * @returns {XMLHttpRequest} */ - createAjaxRequest: function( local ) { - // IE11 does not support window.ActiveXObject so we just try to - // create one to see if it is supported. - // See: http://msdn.microsoft.com/en-us/library/ie/dn423948%28v=vs.85%29.aspx - var supportActiveX; - try { - /* global ActiveXObject:true */ - supportActiveX = !!new ActiveXObject( "Microsoft.XMLHTTP" ); - } catch( e ) { - supportActiveX = false; - } - - if ( supportActiveX ) { - if ( window.XMLHttpRequest ) { - $.createAjaxRequest = function( local ) { - if ( local ) { - return new ActiveXObject( "Microsoft.XMLHTTP" ); - } - return new XMLHttpRequest(); - }; - } else { - $.createAjaxRequest = function() { - return new ActiveXObject( "Microsoft.XMLHTTP" ); - }; - } - } else if ( window.XMLHttpRequest ) { + createAjaxRequest: function() { + if ( window.XMLHttpRequest ) { $.createAjaxRequest = function() { return new XMLHttpRequest(); }; + return new XMLHttpRequest(); } else { throw new Error( "Browser doesn't support XMLHttpRequest." ); } - return $.createAjaxRequest( local ); }, /** @@ -2408,7 +2392,7 @@ function OpenSeadragon( options ){ } var protocol = $.getUrlProtocol( url ); - var request = $.createAjaxRequest( protocol === "file:" ); + var request = $.createAjaxRequest(); if ( !$.isFunction( onSuccess ) ) { throw new Error( "makeAjaxRequest requires a success callback" ); @@ -2577,17 +2561,6 @@ function OpenSeadragon( options ){ return xmlDoc; }; - } else if ( window.ActiveXObject ) { - - $.parseXml = function( string ) { - var xmlDoc = null; - - xmlDoc = new ActiveXObject( "Microsoft.XMLDOM" ); - xmlDoc.async = false; - xmlDoc.loadXML( string ); - return xmlDoc; - }; - } else { throw new Error( "Browser doesn't support XML DOM." ); } @@ -2624,6 +2597,7 @@ function OpenSeadragon( options ){ * Preexisting formats that are not being updated are left unchanged. * By default, the defined formats are *
{
+         *      avif: true,
          *      bmp:  false,
          *      jpeg: true,
          *      jpg:  true,
@@ -2757,6 +2731,7 @@ function OpenSeadragon( options ){
 
 
     var FILEFORMATS = {
+            avif: true,
             bmp:  false,
             jpeg: true,
             jpg:  true,
@@ -2778,6 +2753,10 @@ function OpenSeadragon( options ){
         //console.error( 'appVersion: ' + navigator.appVersion );
         //console.error( 'userAgent: ' + navigator.userAgent );
 
+        //TODO navigator.appName is deprecated. Should be 'Netscape' for all browsers
+        //  but could be dropped at any time
+        //  See https://developer.mozilla.org/en-US/docs/Web/API/Navigator/appName
+        //      https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent
         switch( navigator.appName ){
             case "Microsoft Internet Explorer":
                 if( !!window.attachEvent &&
@@ -2863,8 +2842,8 @@ function OpenSeadragon( options ){
         //determine if this browser supports element.style.opacity
         $.Browser.opacity = true;
 
-        if ( $.Browser.vendor === $.BROWSERS.IE && $.Browser.version < 11 ) {
-            $.console.error('Internet Explorer versions < 11 are not supported by OpenSeadragon');
+        if ( $.Browser.vendor === $.BROWSERS.IE ) {
+            $.console.error('Internet Explorer is not supported by OpenSeadragon');
         }
     })();
 
diff --git a/src/overlay.js b/src/overlay.js
index 7dec6a6b..7d485d42 100644
--- a/src/overlay.js
+++ b/src/overlay.js
@@ -129,6 +129,7 @@
         }
 
         this.element = options.element;
+        this.element.innerHTML = "
" + this.element.innerHTML + "
"; this.style = options.element.style; this._init(options); }; @@ -254,19 +255,23 @@ // least one direction when this.checkResize is set to false. this.size = $.getElementSize(element); } - var positionAndSize = this._getOverlayPositionAndSize(viewport); - var position = positionAndSize.position; var size = this.size = positionAndSize.size; - var rotate = positionAndSize.rotate; - + var outerScale = ""; + if (viewport.overlayPreserveContentDirection) { + outerScale = viewport.flipped ? " scaleX(-1)" : " scaleX(1)"; + } + var rotate = viewport.flipped ? -positionAndSize.rotate : positionAndSize.rotate; + var scale = viewport.flipped ? " scaleX(-1)" : ""; // call the onDraw callback if it exists to allow one to overwrite // the drawing/positioning/sizing of the overlay if (this.onDraw) { this.onDraw(position, size, this.element); } else { var style = this.style; + var innerElement = element.firstChild; + var innerStyle = innerElement.style; style.left = position.x + "px"; style.top = position.y + "px"; if (this.width !== null) { @@ -280,10 +285,20 @@ var transformProp = $.getCssPropertyWithVendorPrefix( 'transform'); if (transformOriginProp && transformProp) { - if (rotate) { + if (rotate && !viewport.flipped) { + innerStyle[transformProp] = ""; style[transformOriginProp] = this._getTransformOrigin(); style[transformProp] = "rotate(" + rotate + "deg)"; + } else if (!rotate && viewport.flipped) { + innerStyle[transformProp] = outerScale; + style[transformOriginProp] = this._getTransformOrigin(); + style[transformProp] = scale; + } else if (rotate && viewport.flipped){ + innerStyle[transformProp] = outerScale; + style[transformOriginProp] = this._getTransformOrigin(); + style[transformProp] = "rotate(" + rotate + "deg)" + scale; } else { + innerStyle[transformProp] = ""; style[transformOriginProp] = ""; style[transformProp] = ""; } @@ -314,6 +329,9 @@ } } + if (viewport.flipped) { + position.x = (viewport.getContainerSize().x - position.x); + } return { position: position, size: size, diff --git a/src/referencestrip.js b/src/referencestrip.js index 1f9bb35b..61bad43b 100644 --- a/src/referencestrip.js +++ b/src/referencestrip.js @@ -193,7 +193,6 @@ $.ReferenceStrip = function ( options ) { element.style.display = 'inline'; element.style['float'] = 'left'; //Webkit element.style.cssFloat = 'left'; //Firefox - element.style.styleFloat = 'left'; //IE element.style.padding = '2px'; $.setElementTouchActionNone( element ); $.setElementPointerEventsNone( element ); diff --git a/src/tiledimage.js b/src/tiledimage.js index e528be02..7cfb482f 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -72,8 +72,8 @@ * @param {Boolean} [options.iOSDevice] - See {@link OpenSeadragon.Options}. * @param {Number} [options.opacity=1] - Set to draw at proportional opacity. If zero, images will not draw. * @param {Boolean} [options.preload=false] - Set true to load even when the image is hidden by zero opacity. - * @param {String} [options.compositeOperation] - How the image is composited onto other images; see compositeOperation in {@link OpenSeadragon.Options} for possible - values. + * @param {String} [options.compositeOperation] - How the image is composited onto other images; + * see compositeOperation in {@link OpenSeadragon.Options} for possible values. * @param {Boolean} [options.debugMode] - See {@link OpenSeadragon.Options}. * @param {String|CanvasGradient|CanvasPattern|Function} [options.placeholderFillStyle] - See {@link OpenSeadragon.Options}. * @param {String|Boolean} [options.crossOriginPolicy] - See {@link OpenSeadragon.Options}. @@ -1108,7 +1108,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag // _tilesToDraw might have been updated by the update; refresh it tileArray = this._tilesToDraw.flat(); - // mark the tiles as being drawn, so that they won't be discarded from + // mark the tiles as being drawn, so that they won't be discarded from // the tileCache tileArray.forEach(tileInfo => { tileInfo.tile.beingDrawn = true; @@ -1351,10 +1351,9 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag // returns boolean flag of whether the image should be marked as fully loaded _updateLevelsForViewport: function(){ var levelsInterval = this._getLevelsInterval(); - var lowestLevel = levelsInterval.lowestLevel; - var highestLevel = levelsInterval.highestLevel; + var lowestLevel = levelsInterval.lowestLevel; // the lowest level we should draw at our current zoom + var highestLevel = levelsInterval.highestLevel; // the highest level we should draw at our current zoom var bestTiles = []; - var haveDrawn = false; var drawArea = this.getDrawArea(); var currentTime = $.now(); @@ -1378,6 +1377,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag for(let i = 0, level = highestLevel; level >= lowestLevel; level--, i++){ levelList[i] = level; } + // if a single-tile level is loaded, add that to the end of the list // as a fallback to use during zooming out, until a lower-res tile is // loaded @@ -1389,32 +1389,32 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag ); if(tile && tile.isBottomMost && tile.isRightMost && tile.loaded){ levelList.push(level); - levelList.hasHigherResolutionFallback = true; break; } } - // Update any level that will be drawn + // Update any level that will be drawn. + // We are iterating from highest resolution to lowest resolution + // Once a level fully covers the viewport the loop is halted and + // lower-resolution levels are skipped + let useLevel = false; for (let i = 0; i < levelList.length; i++) { let level = levelList[i]; - var drawLevel = false; - //Avoid calculations for draw if we have already drawn this var currentRenderPixelRatio = this.viewport.deltaPixelsFromPointsNoRotate( this.source.getPixelRatio(level), true ).x * this._scaleSpring.current.value; - if (i === levelList.length - 1 || - (!haveDrawn && currentRenderPixelRatio >= this.minPixelRatio) ) { - drawLevel = true; - haveDrawn = true; - } else if (!haveDrawn) { + // make sure we skip levels until currentRenderPixelRatio becomes >= minPixelRatio + // but always use the last level in the list so we draw something + if (i === levelList.length - 1 || currentRenderPixelRatio >= this.minPixelRatio ) { + useLevel = true; + } else if (!useLevel) { continue; } - //Perform calculations for draw if we haven't drawn this var targetRenderPixelRatio = this.viewport.deltaPixelsFromPointsNoRotate( this.source.getPixelRatio(level), false @@ -1437,10 +1437,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag ); // Update the level and keep track of 'best' tiles to load - // the bestTiles var result = this._updateLevel( - haveDrawn, - drawLevel, level, levelOpacity, levelVisibility, @@ -1593,8 +1590,6 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag /** * Updates all tiles at a given resolution level. * @private - * @param {Boolean} haveDrawn - * @param {Boolean} drawLevel * @param {Number} level * @param {Number} levelOpacity * @param {Number} levelVisibility @@ -1603,8 +1598,8 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag * @param {OpenSeadragon.Tile[]} best Array of the current best tiles * @returns {Object} Dictionary {bestTiles: OpenSeadragon.Tile - the current "best" tiles to draw, updatedTiles: OpenSeadragon.Tile) - the updated tiles}. */ - _updateLevel: function(haveDrawn, drawLevel, level, levelOpacity, - levelVisibility, drawArea, currentTime, best) { + _updateLevel: function(level, levelOpacity, + levelVisibility, drawArea, currentTime, best) { var topLeftBound = drawArea.getBoundingBox().getTopLeft(); var bottomRightBound = drawArea.getBoundingBox().getBottomRight(); @@ -1618,7 +1613,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag * @type {object} * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event. * @property {OpenSeadragon.TiledImage} tiledImage - Which TiledImage is being drawn. - * @property {Object} havedrawn + * @property {Object} havedrawn - deprecated, always true (kept for backwards compatibility) * @property {Object} level * @property {Object} opacity * @property {Object} visibility @@ -1631,7 +1626,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag */ this.viewer.raiseEvent('update-level', { tiledImage: this, - havedrawn: haveDrawn, + havedrawn: true, // deprecated, kept for backwards compatibility level: level, opacity: levelOpacity, visibility: levelVisibility, @@ -1686,8 +1681,6 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag } var result = this._updateTile( - drawLevel, - haveDrawn, flippedX, y, level, levelVisibility, @@ -1764,8 +1757,6 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag /** * Update a single tile at a particular resolution level. * @private - * @param {Boolean} haveDrawn - * @param {Boolean} drawLevel * @param {Number} x * @param {Number} y * @param {Number} level @@ -1776,8 +1767,8 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag * @param {OpenSeadragon.Tile} best - The current "best" tile to draw. * @returns {Object} Dictionary {bestTiles: OpenSeadragon.Tile[] - the current best tiles, tile: OpenSeadragon.Tile the current tile} */ - _updateTile: function( haveDrawn, drawLevel, x, y, level, - levelVisibility, viewportCenter, numberOfTiles, currentTime, best){ + _updateTile: function( x, y, level, + levelVisibility, viewportCenter, numberOfTiles, currentTime, best){ const tile = this._getTile( x, y, @@ -1785,7 +1776,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag currentTime, numberOfTiles ); - let drawTile = drawLevel; + if( this.viewer ){ /** @@ -1819,20 +1810,6 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag if (tile.loaded && tile.opacity === 1){ this._setCoverage( this.coverage, level, x, y, true ); } - if ( haveDrawn && !drawTile ) { - if ( this._isCovered( this.coverage, level, x, y ) ) { - this._setCoverage( this.coverage, level, x, y, true ); - } else { - drawTile = true; - } - } - - if ( !drawTile ) { - return { - bestTiles: best, - tile: tile - }; - } this._positionTile( tile, @@ -2278,9 +2255,11 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag return -1; } if (a.visibility === b.visibility) { + // sort by smallest squared distance return (a.squaredDistance - b.squaredDistance); } else { - return (a.visibility - b.visibility); + // sort by largest visibility value + return (b.visibility - a.visibility); } }); }, diff --git a/src/viewer.js b/src/viewer.js index 2af05c96..695182a4 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -399,24 +399,25 @@ $.Viewer = function( options ) { // Create the viewport this.viewport = new $.Viewport({ - containerSize: THIS[ this.hash ].prevContainerSize, - springStiffness: this.springStiffness, - animationTime: this.animationTime, - minZoomImageRatio: this.minZoomImageRatio, - maxZoomPixelRatio: this.maxZoomPixelRatio, - visibilityRatio: this.visibilityRatio, - wrapHorizontal: this.wrapHorizontal, - wrapVertical: this.wrapVertical, - defaultZoomLevel: this.defaultZoomLevel, - minZoomLevel: this.minZoomLevel, - maxZoomLevel: this.maxZoomLevel, - viewer: this, - degrees: this.degrees, - flipped: this.flipped, - navigatorRotate: this.navigatorRotate, - homeFillsViewer: this.homeFillsViewer, - margins: this.viewportMargins, - silenceMultiImageWarnings: this.silenceMultiImageWarnings + containerSize: THIS[ this.hash ].prevContainerSize, + springStiffness: this.springStiffness, + animationTime: this.animationTime, + minZoomImageRatio: this.minZoomImageRatio, + maxZoomPixelRatio: this.maxZoomPixelRatio, + visibilityRatio: this.visibilityRatio, + wrapHorizontal: this.wrapHorizontal, + wrapVertical: this.wrapVertical, + defaultZoomLevel: this.defaultZoomLevel, + minZoomLevel: this.minZoomLevel, + maxZoomLevel: this.maxZoomLevel, + viewer: this, + degrees: this.degrees, + flipped: this.flipped, + overlayPreserveContentDirection: this.overlayPreserveContentDirection, + navigatorRotate: this.navigatorRotate, + homeFillsViewer: this.homeFillsViewer, + margins: this.viewportMargins, + silenceMultiImageWarnings: this.silenceMultiImageWarnings }); this.viewport._setContentBounds(this.world.getHomeBounds(), this.world.getContentFactor()); @@ -516,6 +517,9 @@ $.Viewer = function( options ) { crossOriginPolicy: this.crossOriginPolicy, animationTime: this.animationTime, drawer: this.drawer.getType(), + loadTilesWithAjax: this.loadTilesWithAjax, + ajaxHeaders: this.ajaxHeaders, + ajaxWithCredentials: this.ajaxWithCredentials, }); } diff --git a/src/webgldrawer.js b/src/webgldrawer.js index c34de65b..e61a6ef8 100644 --- a/src/webgldrawer.js +++ b/src/webgldrawer.js @@ -191,7 +191,7 @@ let canvasElement = document.createElement( 'canvas' ); let webglContext = $.isFunction( canvasElement.getContext ) && canvasElement.getContext( 'webgl' ); - let ext = webglContext.getExtension('WEBGL_lose_context'); + let ext = webglContext && webglContext.getExtension('WEBGL_lose_context'); if(ext){ ext.loseContext(); } diff --git a/test/demo/overlay.html b/test/demo/overlay.html index 43c0f804..3e91a8cb 100644 --- a/test/demo/overlay.html +++ b/test/demo/overlay.html @@ -26,7 +26,8 @@ prefixUrl: "../../build/openseadragon/images/", tileSources: "../data/testpattern.dzi", minZoomImageRatio: 0, - maxZoomPixelRatio: 10 + maxZoomPixelRatio: 10, + overlayPreserveContentDirection: true // Change this to false to test overlay content flipping }); viewer.addHandler("open", function(event) { @@ -42,6 +43,19 @@ rotationMode: OpenSeadragon.OverlayRotationMode.BOUNDING_BOX }); + // test with image of letter B to see that images flip too + elt = document.createElement("div"); + elt.className = "runtime-overlay"; + elt.style.outline = "1px solid blue"; + elt.style.height = "100px"; + elt.innerHTML = "
" + viewer.addOverlay({ + element: elt, + location: new OpenSeadragon.Point(0.0, 0.0), + width: 0.1, + height: 0.1 + }); + elt = document.createElement("div"); elt.className = "runtime-overlay"; elt.style.background = "white"; diff --git a/test/helpers/legacy.mouse.shim.js b/test/helpers/legacy.mouse.shim.js index 19374147..938e8695 100644 --- a/test/helpers/legacy.mouse.shim.js +++ b/test/helpers/legacy.mouse.shim.js @@ -1,4 +1,4 @@ -(function($, undefined) { +(function($) { /** * Plugin to force OpenSeadragon to use the legacy mouse pointer event model