From f712e15793ddd85c7fba684b1a9a4858aeac90a9 Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Mon, 14 Oct 2013 18:01:58 -0400 Subject: [PATCH 1/7] Recenter the image after switching fullscreen mode. #62 and #170 --- src/viewer.js | 74 +++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 41 deletions(-) diff --git a/src/viewer.js b/src/viewer.js index e8ef88ac..27f9cc79 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -648,9 +648,6 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, docStyle = document.documentElement.style, canvasStyle = this.canvas.style, _this = this, - oldBounds, - newBounds, - viewer, hash, nodes, i; @@ -659,7 +656,39 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, if ( fullPage == this.isFullPage() ) { return; } - + + if ( this.viewport ) { + var oldBounds = this.viewport.getBounds(); + var oldCenter = this.viewport.getCenter(); + + // This function recenter the image as it was before switching mode. + // TODO: better adjust width and height. The new width and height + // should depend on the image dimensions and on the dimensions + // of the viewport before and after switching mode. + var resizeAfterFullscreenHandler = function() { + _this.removeHandler( "animation-finish", resizeAfterFullscreenHandler ); + + var viewport = _this.viewport; + if ( !viewport ) { + return; + } + + // We try to remove blanks as much as possible + var imageHeight = 1 / _this.source.aspectRatio; + var newWidth = oldBounds.width <= 1 ? oldBounds.width : 1; + var newHeight = oldBounds.height <= imageHeight ? + oldBounds.height : imageHeight; + + var newBounds = new $.Rect( + oldCenter.x - ( newWidth / 2.0 ), + oldCenter.y - ( newHeight / 2.0 ), + newWidth, + newHeight + ); + viewport.fitBounds( newBounds, true ); + }; + this.addHandler( "animation-finish", resizeAfterFullscreenHandler ); + } if ( fullPage ) { @@ -811,43 +840,6 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, } this.raiseEvent( 'fullpage', { fullpage: fullPage } ); - if ( this.viewport ) { - oldBounds = this.viewport.getBounds(); - this.viewport.resize( THIS[ this.hash ].prevContainerSize ); - newBounds = this.viewport.getBounds(); - - if ( fullPage ) { - THIS[ this.hash ].fsBoundsDelta = new $.Point( - newBounds.width / oldBounds.width, - newBounds.height / oldBounds.height - ); - } else { - this.viewport.update(); - this.viewport.zoomBy( - Math.max( - THIS[ this.hash ].fsBoundsDelta.x, - THIS[ this.hash ].fsBoundsDelta.y - ), - null, - true - ); - //Ensures that if multiple viewers are on a page, the viewers that - //were hidden during fullpage are 'reopened' - for( hash in VIEWERS ){ - viewer = VIEWERS[ hash ]; - if( viewer !== this && viewer != this.navigator ){ - viewer.open( viewer.source ); - if( viewer.navigator ){ - viewer.navigator.open( viewer.source ); - } - } - } - } - - THIS[ this.hash ].forceRedraw = true; - updateOnce( this ); - - } return this; }, From d4a4276bbc813ab5fd4dd406c971e046957a1027 Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Wed, 23 Oct 2013 10:00:08 -0400 Subject: [PATCH 2/7] Fix margin bug with legacy fullscreen mode --- src/viewer.js | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/viewer.js b/src/viewer.js index 27f9cc79..8f0ccea5 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -692,10 +692,15 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, if ( fullPage ) { - this.bodyOverflow = bodyStyle.overflow; - this.docOverflow = docStyle.overflow; - bodyStyle.overflow = "hidden"; - docStyle.overflow = "hidden"; + this.bodyMargin = bodyStyle.margin; + this.docMargin = docStyle.margin; + bodyStyle.margin = "0"; + docStyle.margin = "0"; + + this.bodyPadding = bodyStyle.padding; + this.docPadding = docStyle.padding; + bodyStyle.padding = "0"; + docStyle.padding = "0"; this.bodyWidth = bodyStyle.width; this.bodyHeight = bodyStyle.height; @@ -761,7 +766,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, ); this.element.style.height = '100%'; this.element.style.width = '100%'; - }else{ + } else { this.element.style.height = $.getWindowSize().y + 'px'; this.element.style.width = $.getWindowSize().x + 'px'; } @@ -788,8 +793,11 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, $.cancelFullScreen( document ); } - bodyStyle.overflow = this.bodyOverflow; - docStyle.overflow = this.docOverflow; + bodyStyle.margin = this.bodyMargin; + docStyle.margin = this.docMargin; + + bodyStyle.padding = this.bodyPadding; + docStyle.padding = this.docPadding; bodyStyle.width = this.bodyWidth; bodyStyle.height = this.bodyHeight; From 7375ba924148715ac212a75e3db10e18fa784362 Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Thu, 31 Oct 2013 22:19:22 -0400 Subject: [PATCH 3/7] Fix scrolling when exiting full-screen mode. Rename fullpage event to full-page and it's fullpage property to fullPage. Add pre-full-page event. --- src/openseadragon.js | 58 ++++++++++++- src/viewer.js | 197 +++++++++++++++++++++++-------------------- 2 files changed, 160 insertions(+), 95 deletions(-) diff --git a/src/openseadragon.js b/src/openseadragon.js index 0c0a01ca..fa12a2f2 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -843,7 +843,7 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ /** - * Determines the pages current scroll position. + * Determines the page current scroll position. * @function * @name OpenSeadragon.getPageScroll * @returns {Point} @@ -874,14 +874,64 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ ); }; } else { - $.getPageScroll = function(){ - return new $.Point(0,0); - }; + // We can't reassign the function yet, as there was no scroll. + return new $.Point(0,0); } return $.getPageScroll(); }, + /** + * Set the page scroll position. + * @function + * @name OpenSeadragon.getPageScroll + * @returns {Point} + */ + setPageScroll: function( scroll ) { + if ( typeof ( window.scrollTo ) !== "undefined" ) { + $.setPageScroll = function( scroll ) { + window.scrollTo( scroll.x, scroll.y ); + }; + } else { + var currentScroll = $.getPageScroll(); + if ( currentScroll.x === scroll.x && + currentScroll.y === scroll.y ) { + // We are already correctly positioned and there + // is no way to detect the correct method. + return; + } + + document.body.scrollLeft = scroll.x; + document.body.scrollTop = scroll.y; + currentScroll = $.getPageScroll(); + if ( currentScroll.x === scroll.x && + currentScroll.y === scroll.y ) { + $.setPageScroll = function( scroll ) { + document.body.scrollLeft = scroll.x; + document.body.scrollTop = scroll.y; + }; + return; + } + + document.documentElement.scrollLeft = scroll.x; + document.documentElement.scrollTop = scroll.y; + currentScroll = $.getPageScroll(); + if ( currentScroll.x === scroll.x && + currentScroll.y === scroll.y ) { + $.setPageScroll = function( scroll ) { + document.documentElement.scrollLeft = scroll.x; + document.documentElement.scrollTop = scroll.y; + }; + return; + } + + // We can't find anything working, so we do nothing. + $.setPageScroll = function( scroll ) { + }; + } + + return $.setPageScroll( scroll ); + }, /** * Determines the size of the browsers window. diff --git a/src/viewer.js b/src/viewer.js index 8f0ccea5..784675ca 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -646,7 +646,6 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, var body = document.body, bodyStyle = body.style, docStyle = document.documentElement.style, - canvasStyle = this.canvas.style, _this = this, hash, nodes, @@ -657,40 +656,106 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, return; } - if ( this.viewport ) { - var oldBounds = this.viewport.getBounds(); - var oldCenter = this.viewport.getCenter(); + var recenterAfterFullPage = function() { + if ( _this.viewport ) { + var oldBounds = _this.viewport.getBounds(); + var oldCenter = _this.viewport.getCenter(); + + // This function recenter the image as it was before switching mode. + // TODO: better adjust width and height. The new width and height + // should depend on the image dimensions and on the dimensions + // of the viewport before and after switching mode. + var resizeAfterFullscreenHandler = function() { + _this.removeHandler( "animation-finish", resizeAfterFullscreenHandler ); + + var viewport = _this.viewport; + if ( !viewport ) { + return; + } + + // We try to remove blanks as much as possible + var imageHeight = 1 / _this.source.aspectRatio; + var newWidth = oldBounds.width <= 1 ? oldBounds.width : 1; + var newHeight = oldBounds.height <= imageHeight ? + oldBounds.height : imageHeight; + + var newBounds = new $.Rect( + oldCenter.x - ( newWidth / 2.0 ), + oldCenter.y - ( newHeight / 2.0 ), + newWidth, + newHeight + ); + viewport.fitBounds( newBounds, true ); + }; + _this.addHandler( "animation-finish", resizeAfterFullscreenHandler ); + } + }; + + // On chrome, we need to restore the DOM after $.fullScreenEventName + // has been raised otherwise it won't restore the scroll position. + var exitFullPage = function() { + _this.raiseEvent( 'pre-full-page', { fullPage: false } ); - // This function recenter the image as it was before switching mode. - // TODO: better adjust width and height. The new width and height - // should depend on the image dimensions and on the dimensions - // of the viewport before and after switching mode. - var resizeAfterFullscreenHandler = function() { - _this.removeHandler( "animation-finish", resizeAfterFullscreenHandler ); - - var viewport = _this.viewport; - if ( !viewport ) { - return; - } - - // We try to remove blanks as much as possible - var imageHeight = 1 / _this.source.aspectRatio; - var newWidth = oldBounds.width <= 1 ? oldBounds.width : 1; - var newHeight = oldBounds.height <= imageHeight ? - oldBounds.height : imageHeight; - - var newBounds = new $.Rect( - oldCenter.x - ( newWidth / 2.0 ), - oldCenter.y - ( newHeight / 2.0 ), - newWidth, - newHeight - ); - viewport.fitBounds( newBounds, true ); - }; - this.addHandler( "animation-finish", resizeAfterFullscreenHandler ); - } + recenterAfterFullPage(); + + bodyStyle.margin = _this.bodyMargin; + docStyle.margin = _this.docMargin; + + bodyStyle.padding = _this.bodyPadding; + docStyle.padding = _this.docPadding; + + bodyStyle.width = _this.bodyWidth; + bodyStyle.height = _this.bodyHeight; + + body.removeChild( _this.element ); + nodes = _this.previousBody.length; + for ( i = 0; i < nodes; i++ ){ + body.appendChild( _this.previousBody.shift() ); + } + + $.removeClass( _this.element, 'fullpage' ); + THIS[ _this.hash ].prevElementParent.insertBefore( + _this.element, + THIS[ _this.hash ].prevNextSibling + ); + + //If we've got a toolbar, we need to enable the user to use css to + //reset it to its original state + if( _this.toolbar && _this.toolbar.element ){ + body.removeChild( _this.toolbar.element ); + + //Make sure the user has some ability to style the toolbar based + //on the mode + $.removeClass( _this.toolbar.element, 'fullpage' ); + + _this.toolbar.parentNode.insertBefore( + _this.toolbar.element, + _this.toolbar.nextSibling + ); + delete _this.toolbar.parentNode; + delete _this.toolbar.nextSibling; + } + + _this.element.style.width = THIS[ _this.hash ].prevElementWidth; + _this.element.style.height = THIS[ _this.hash ].prevElementHeight; + + $.setPageScroll(_this.pageScroll); + + THIS[ _this.hash ].fullPage = false; + + // mouse will likely be outside now + $.delegate( _this, onContainerExit )( {} ); + + + _this.raiseEvent( 'full-page', { fullPage: false } ); + }; if ( fullPage ) { + this.raiseEvent( 'pre-full-page', { fullPage: true } ); + + recenterAfterFullPage(); + + this.pageScroll = $.getPageScroll(); this.bodyMargin = bodyStyle.margin; this.docMargin = docStyle.margin; @@ -751,7 +816,11 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, if( $.isFullScreen() ){ _this.setFullPage( true ); } else { - _this.setFullPage( false ); + document.removeEventListener( + $.fullScreenEventName, + THIS[ _this.hash ].onfullscreenchange + ); + exitFullPage(); } }; @@ -782,71 +851,17 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, // mouse will be inside container now $.delegate( this, onContainerEnter )( {} ); + this.raiseEvent( 'full-page', { fullPage: true } ); } else { if( $.supportsFullScreen ){ - document.removeEventListener( - $.fullScreenEventName, - THIS[ this.hash ].onfullscreenchange - ); - $.cancelFullScreen( document ); + $.cancelFullScreen(); + } else { + exitFullPage(); } - bodyStyle.margin = this.bodyMargin; - docStyle.margin = this.docMargin; - - bodyStyle.padding = this.bodyPadding; - docStyle.padding = this.docPadding; - - bodyStyle.width = this.bodyWidth; - bodyStyle.height = this.bodyHeight; - - canvasStyle.backgroundColor = ""; - canvasStyle.color = ""; - - body.removeChild( this.element ); - nodes = this.previousBody.length; - for ( i = 0; i < nodes; i++ ){ - body.appendChild( this.previousBody.shift() ); - } - - $.removeClass( this.element, 'fullpage' ); - THIS[ this.hash ].prevElementParent.insertBefore( - this.element, - THIS[ this.hash ].prevNextSibling - ); - - //If we've got a toolbar, we need to enable the user to use css to - //reset it to its original state - if( this.toolbar && this.toolbar.element ){ - body.removeChild( this.toolbar.element ); - - //Make sure the user has some ability to style the toolbar based - //on the mode - $.removeClass( this.toolbar.element, 'fullpage' ); - //this.toolbar.element.style.position = 'relative'; - this.toolbar.parentNode.insertBefore( - this.toolbar.element, - this.toolbar.nextSibling - ); - delete this.toolbar.parentNode; - delete this.toolbar.nextSibling; - - //this.container.style.top = 'auto'; - } - - this.element.style.width = THIS[ this.hash ].prevElementWidth; - this.element.style.height = THIS[ this.hash ].prevElementHeight; - - THIS[ this.hash ].fullPage = false; - - // mouse will likely be outside now - $.delegate( this, onContainerExit )( {} ); - - } - this.raiseEvent( 'fullpage', { fullpage: fullPage } ); return this; }, From d853224c15e97ab4a09a781fd74bebf9d9c41055 Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Fri, 1 Nov 2013 17:37:19 -0400 Subject: [PATCH 4/7] Add units tests for scroll --- src/openseadragon.js | 18 +++--- src/viewer.js | 6 +- test/basic.js | 48 +++++++++++++--- test/polyfills.js | 130 +++++++++++++++++++++++++++++++++++++++++++ test/test.html | 4 ++ 5 files changed, 185 insertions(+), 21 deletions(-) create mode 100644 test/polyfills.js diff --git a/src/openseadragon.js b/src/openseadragon.js index fa12a2f2..8d12d897 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -843,7 +843,7 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ /** - * Determines the page current scroll position. + * Determines the page's current scroll position. * @function * @name OpenSeadragon.getPageScroll * @returns {Point} @@ -893,9 +893,9 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ window.scrollTo( scroll.x, scroll.y ); }; } else { - var currentScroll = $.getPageScroll(); - if ( currentScroll.x === scroll.x && - currentScroll.y === scroll.y ) { + var originalScroll = $.getPageScroll(); + if ( originalScroll.x === scroll.x && + originalScroll.y === scroll.y ) { // We are already correctly positioned and there // is no way to detect the correct method. return; @@ -903,9 +903,9 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ document.body.scrollLeft = scroll.x; document.body.scrollTop = scroll.y; - currentScroll = $.getPageScroll(); - if ( currentScroll.x === scroll.x && - currentScroll.y === scroll.y ) { + var currentScroll = $.getPageScroll(); + if ( currentScroll.x !== originalScroll.x && + currentScroll.y !== originalScroll.y ) { $.setPageScroll = function( scroll ) { document.body.scrollLeft = scroll.x; document.body.scrollTop = scroll.y; @@ -916,8 +916,8 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ document.documentElement.scrollLeft = scroll.x; document.documentElement.scrollTop = scroll.y; currentScroll = $.getPageScroll(); - if ( currentScroll.x === scroll.x && - currentScroll.y === scroll.y ) { + if ( currentScroll.x !== originalScroll.x && + currentScroll.y !== originalScroll.y ) { $.setPageScroll = function( scroll ) { document.documentElement.scrollLeft = scroll.x; document.documentElement.scrollTop = scroll.y; diff --git a/src/viewer.js b/src/viewer.js index 784675ca..54977599 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -656,7 +656,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, return; } - var recenterAfterFullPage = function() { + var registerRecenterAfterFullPageChange = function() { if ( _this.viewport ) { var oldBounds = _this.viewport.getBounds(); var oldCenter = _this.viewport.getCenter(); @@ -696,7 +696,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, var exitFullPage = function() { _this.raiseEvent( 'pre-full-page', { fullPage: false } ); - recenterAfterFullPage(); + registerRecenterAfterFullPageChange(); bodyStyle.margin = _this.bodyMargin; docStyle.margin = _this.docMargin; @@ -753,7 +753,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, if ( fullPage ) { this.raiseEvent( 'pre-full-page', { fullPage: true } ); - recenterAfterFullPage(); + registerRecenterAfterFullPageChange(); this.pageScroll = $.getPageScroll(); diff --git a/test/basic.js b/test/basic.js index 3ab694f1..6bffd5d9 100644 --- a/test/basic.js +++ b/test/basic.js @@ -180,16 +180,46 @@ ok(!$(viewer.element).hasClass('fullpage'), 'No fullpage class on div'); - viewer.setFullPage(true); - ok(viewer.isFullPage(), 'Enabled fullpage'); - ok($(viewer.element).hasClass('fullpage'), - 'Fullpage class added to div'); + var checkEnteringPreFullPage = function(event) { + viewer.removeHandler('pre-full-page', checkEnteringPreFullPage); + ok(event.fullPage, 'Switching to fullpage'); + ok(!viewer.isFullPage(), 'Not yet fullpage'); + }; - viewer.setFullPage(false); - ok(!viewer.isFullPage(), 'Disabled fullpage'); - ok(!$(viewer.element).hasClass('fullpage'), - 'Fullpage class removed from div'); - start(); + var checkEnteringFullPage = function(event) { + viewer.removeHandler('full-page', checkEnteringFullPage); + ok(event.fullPage, 'Switched to fullpage'); + ok(viewer.isFullPage(), 'Enabled fullpage'); + ok($(viewer.element).hasClass('fullpage'), + 'Fullpage class added to div'); + + var checkExitingPreFullPage = function(event) { + viewer.removeHandler('pre-full-page', checkExitingPreFullPage); + ok(!event.fullPage, 'Exiting fullpage'); + ok(viewer.isFullPage(), 'Still fullpage'); + }; + + var checkExitingFullPage = function(event) { + viewer.removeHandler('full-page', checkExitingFullPage); + ok(!event.fullPage, 'Exiting fullpage'); + ok(!viewer.isFullPage(), 'Disabled fullpage'); + ok(!$(viewer.element).hasClass('fullpage'), + 'Fullpage class removed from div'); + start(); + }; + + viewer.addHandler("pre-full-page", checkExitingPreFullPage); + viewer.addHandler("full-page", checkExitingFullPage); + + // Workaround: for some reason inside tests, the fullscreen + // mode is never activated, so disable it so that we can + // continue the tests. + OpenSeadragon.supportsFullScreen = false; + viewer.setFullPage(false); + }; + viewer.addHandler("pre-full-page", checkEnteringPreFullPage); + viewer.addHandler("full-page", checkEnteringFullPage); + viewer.setFullPage(true); }); viewer.open('/test/data/testpattern.dzi'); diff --git a/test/polyfills.js b/test/polyfills.js new file mode 100644 index 00000000..6811d19a --- /dev/null +++ b/test/polyfills.js @@ -0,0 +1,130 @@ +/* global module, asyncTest, $, ok, equal, notEqual, start, test, Util, testLog */ + +( function() { + + var origWidth, origHeight; + + module( 'Polyfills', { + setup: function() { + + origWidth = $( "body" ).width(); + origHeight = $( "body" ).height(); + $( "body" ).width( origWidth + 10000 ); + $( "body" ).height( origHeight + 10000 ); + + $( document ).scrollLeft( 0 ); + $( document ).scrollTop( 0 ); + testLog.reset(); + }, + teardown: function() { + $( "body" ).width( origWidth ); + $( "body" ).height( origHeight ); + $( document ).scrollLeft( 0 ); + $( document ).scrollTop( 0 ); + } + } ); + + // ---------- + test( 'pageScroll', function() { + + // Test get + var originalGetPageScroll = OpenSeadragon.getPageScroll; + + var scroll = OpenSeadragon.getPageScroll(); + equal( scroll.x, 0, "Scroll should be 0 at beginning." ); + equal( scroll.y, 0, "Scroll should be 0 at beginning." ); + + // If window.pageXOffset is not supported, the getPageScroll method should + // not have been redefined + if ( typeof ( window.pageXOffset ) != "number" ) { + equal( originalGetPageScroll, OpenSeadragon.getPageScroll, + "OpenSeadragon.getPageScroll must not be redefined when on 0,0" + + " and window API is not supported." ); + } else { + notEqual( originalGetPageScroll, OpenSeadragon.getPageScroll, + "OpenSeadragon.getPageScroll must be redefined when window API " + + "is supported." ); + } + + $( document ).scrollLeft( 200 ); + $( document ).scrollTop( 100 ); + scroll = originalGetPageScroll(); + equal( scroll.x, 200, "First call to getScroll." ); + equal( scroll.y, 100, "First call to getScroll." ); + + $( document ).scrollLeft( 500 ); + $( document ).scrollTop( 600 ); + scroll = OpenSeadragon.getPageScroll(); + equal( scroll.x, 500, "Second call to getScroll." ); + equal( scroll.y, 600, "Second call to getScroll." ); + + + + // Test set, must be imperatively be done after tests for get to not + // break them. + var originalSetPageScroll = OpenSeadragon.setPageScroll; + + $( document ).scrollLeft( 0 ); + $( document ).scrollTop( 0 ); + var scroll = new OpenSeadragon.Point( 0, 0 ); + OpenSeadragon.setPageScroll( scroll ); + equal( $( document ).scrollLeft(), 0, "First call to 0,0 while already on 0,0." ); + equal( $( document ).scrollTop(), 0, "First call to 0,0 while already on 0,0." ); + + // If window.pageXOffset is not supported, the getPageScroll method should + // not have been redefined + if ( typeof ( window.scrollTo ) === "undefined" ) { + equal( originalSetPageScroll, OpenSeadragon.setPageScroll, + "OpenSeadragon.setPageScroll must not be redefined when not moving." ); + } else { + notEqual( originalSetPageScroll, OpenSeadragon.setPageScroll, + "OpenSeadragon.setPageScroll must be redefined when window API is supported." ); + } + + + OpenSeadragon.setPageScroll = originalSetPageScroll; + $( document ).scrollLeft( 100 ); + $( document ).scrollTop( 200 ); + var scroll = new OpenSeadragon.Point( 100, 200 ); + OpenSeadragon.setPageScroll( scroll ); + equal( $( document ).scrollLeft(), 100, "First call to 100,200 while already on 100,200." ); + equal( $( document ).scrollTop(), 200, "First call to 100,200 while already on 100,200." ); + + // If window.pageXOffset is not supported, the getPageScroll method should + // not have been redefined + if ( typeof ( window.scrollTo ) === "undefined" ) { + equal( originalSetPageScroll, OpenSeadragon.setPageScroll, + "OpenSeadragon.setPageScroll must not be redefined when not moving." ); + } else { + notEqual( originalSetPageScroll, OpenSeadragon.setPageScroll, + "OpenSeadragon.setPageScroll must be redefined when window API is supported." ); + } + + + OpenSeadragon.setPageScroll = originalSetPageScroll; + $( document ).scrollLeft( 20000 ); + $( document ).scrollTop( 20000 ); + var actualScrollLeft = $( document ).scrollLeft(); + var actualScrollTop = $( document ).scrollTop(); + $( document ).scrollLeft( 0 ); + $( document ).scrollTop( 0 ); + var scroll = new OpenSeadragon.Point( 20000, 20000 ); + OpenSeadragon.setPageScroll( scroll ); + equal( $( document ).scrollLeft(), actualScrollLeft, "First call to position above limits." ); + equal( $( document ).scrollTop(), actualScrollTop, "First call to position above limits." ); + notEqual( originalSetPageScroll, OpenSeadragon.setPageScroll, + "Even if outside scroll limits, OpenSeadragon.setPageScroll can be " + + "reassigned on first call." ); + + + var currentSetPageScroll = OpenSeadragon.setPageScroll; + var scroll = new OpenSeadragon.Point( 200, 200 ); + OpenSeadragon.setPageScroll( scroll ); + equal( $( document ).scrollLeft(), 200, "Second call." ); + equal( $( document ).scrollTop(), 200, "Second call." ); + equal( currentSetPageScroll, OpenSeadragon.setPageScroll, + "OpenSeadragon.setPageScroll must not be reassigned after first call." ); + + } ); + +} )(); diff --git a/test/test.html b/test/test.html index 3bd6f919..0f46fa30 100644 --- a/test/test.html +++ b/test/test.html @@ -16,6 +16,10 @@ + + + From d70845d7ebc0ec3a38e6c468d3aa25a3164b44a3 Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Sat, 2 Nov 2013 21:01:04 -0400 Subject: [PATCH 5/7] Separate fullscreen and fullpage methods (#91) Fix scroll issue. Handle fullscreen denial by the browser --- src/fullscreen.js | 2 + src/viewer.js | 327 +++++++++++++++++++++++----------------------- test/basic.js | 40 +++++- 3 files changed, 201 insertions(+), 168 deletions(-) diff --git a/src/fullscreen.js b/src/fullscreen.js index feeab0b5..2935923f 100644 --- a/src/fullscreen.js +++ b/src/fullscreen.js @@ -72,6 +72,7 @@ requestFullScreen: function() {}, cancelFullScreen: function() {}, fullScreenEventName: '', + fullScreenErrorEventName: '', prefix: '' }, browserPrefixes = 'webkit moz o ms khtml'.split(' '); @@ -95,6 +96,7 @@ // update methods to do something useful if (fullScreenApi.supportsFullScreen) { fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; + fullScreenApi.fullScreenErrorEventName = fullScreenApi.prefix + 'fullscreenerror'; fullScreenApi.isFullScreen = function() { switch (this.prefix) { diff --git a/src/viewer.js b/src/viewer.js index 54977599..11c1cbfa 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -643,134 +643,40 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, */ setFullPage: function( fullPage ) { - var body = document.body, - bodyStyle = body.style, - docStyle = document.documentElement.style, - _this = this, + var body = document.body, + bodyStyle = body.style, + docStyle = document.documentElement.style, + _this = this, hash, nodes, i; //dont bother modifying the DOM if we are already in full page mode. if ( fullPage == this.isFullPage() ) { - return; + return this; } - - var registerRecenterAfterFullPageChange = function() { - if ( _this.viewport ) { - var oldBounds = _this.viewport.getBounds(); - var oldCenter = _this.viewport.getCenter(); - // This function recenter the image as it was before switching mode. - // TODO: better adjust width and height. The new width and height - // should depend on the image dimensions and on the dimensions - // of the viewport before and after switching mode. - var resizeAfterFullscreenHandler = function() { - _this.removeHandler( "animation-finish", resizeAfterFullscreenHandler ); - - var viewport = _this.viewport; - if ( !viewport ) { - return; - } - - // We try to remove blanks as much as possible - var imageHeight = 1 / _this.source.aspectRatio; - var newWidth = oldBounds.width <= 1 ? oldBounds.width : 1; - var newHeight = oldBounds.height <= imageHeight ? - oldBounds.height : imageHeight; - - var newBounds = new $.Rect( - oldCenter.x - ( newWidth / 2.0 ), - oldCenter.y - ( newHeight / 2.0 ), - newWidth, - newHeight - ); - viewport.fitBounds( newBounds, true ); - }; - _this.addHandler( "animation-finish", resizeAfterFullscreenHandler ); - } - }; - - // On chrome, we need to restore the DOM after $.fullScreenEventName - // has been raised otherwise it won't restore the scroll position. - var exitFullPage = function() { - _this.raiseEvent( 'pre-full-page', { fullPage: false } ); - - registerRecenterAfterFullPageChange(); - - bodyStyle.margin = _this.bodyMargin; - docStyle.margin = _this.docMargin; - - bodyStyle.padding = _this.bodyPadding; - docStyle.padding = _this.docPadding; - - bodyStyle.width = _this.bodyWidth; - bodyStyle.height = _this.bodyHeight; - - body.removeChild( _this.element ); - nodes = _this.previousBody.length; - for ( i = 0; i < nodes; i++ ){ - body.appendChild( _this.previousBody.shift() ); - } - - $.removeClass( _this.element, 'fullpage' ); - THIS[ _this.hash ].prevElementParent.insertBefore( - _this.element, - THIS[ _this.hash ].prevNextSibling - ); - - //If we've got a toolbar, we need to enable the user to use css to - //reset it to its original state - if( _this.toolbar && _this.toolbar.element ){ - body.removeChild( _this.toolbar.element ); - - //Make sure the user has some ability to style the toolbar based - //on the mode - $.removeClass( _this.toolbar.element, 'fullpage' ); - - _this.toolbar.parentNode.insertBefore( - _this.toolbar.element, - _this.toolbar.nextSibling - ); - delete _this.toolbar.parentNode; - delete _this.toolbar.nextSibling; - } - - _this.element.style.width = THIS[ _this.hash ].prevElementWidth; - _this.element.style.height = THIS[ _this.hash ].prevElementHeight; - - $.setPageScroll(_this.pageScroll); - - THIS[ _this.hash ].fullPage = false; - - // mouse will likely be outside now - $.delegate( _this, onContainerExit )( {} ); - - - _this.raiseEvent( 'full-page', { fullPage: false } ); - }; + this.raiseEvent( 'pre-full-page', { fullPage: fullPage } ); if ( fullPage ) { - this.raiseEvent( 'pre-full-page', { fullPage: true } ); - registerRecenterAfterFullPageChange(); + this.elementSize = $.getElementSize( this.element ); + this.pageScroll = $.getPageScroll(); - this.pageScroll = $.getPageScroll(); + this.bodyMargin = bodyStyle.margin; + this.docMargin = docStyle.margin; + bodyStyle.margin = "0"; + docStyle.margin = "0"; - this.bodyMargin = bodyStyle.margin; - this.docMargin = docStyle.margin; - bodyStyle.margin = "0"; - docStyle.margin = "0"; + this.bodyPadding = bodyStyle.padding; + this.docPadding = docStyle.padding; + bodyStyle.padding = "0"; + docStyle.padding = "0"; - this.bodyPadding = bodyStyle.padding; - this.docPadding = docStyle.padding; - bodyStyle.padding = "0"; - docStyle.padding = "0"; - - this.bodyWidth = bodyStyle.width; - this.bodyHeight = bodyStyle.height; - bodyStyle.width = "100%"; - bodyStyle.height = "100%"; + this.bodyWidth = bodyStyle.width; + this.bodyHeight = bodyStyle.height; + bodyStyle.width = "100%"; + bodyStyle.height = "100%"; //when entering full screen on the ipad it wasnt sufficient to leave //the body intact as only only the top half of the screen would @@ -783,14 +689,14 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, THIS[ this.hash ].prevElementWidth = this.element.style.width; THIS[ this.hash ].prevElementHeight = this.element.style.height; nodes = body.childNodes.length; - for ( i = 0; i < nodes; i ++ ){ + for ( i = 0; i < nodes; i++ ) { this.previousBody.push( body.childNodes[ 0 ] ); body.removeChild( body.childNodes[ 0 ] ); } //If we've got a toolbar, we need to enable the user to use css to //preserve it in fullpage mode - if( this.toolbar && this.toolbar.element ){ + if ( this.toolbar && this.toolbar.element ) { //save a reference to the parent so we can put it back //in the long run we need a better strategy this.toolbar.parentNode = this.toolbar.element.parentNode; @@ -805,42 +711,10 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, $.addClass( this.element, 'fullpage' ); body.appendChild( this.element ); - if( $.supportsFullScreen ){ - THIS[ this.hash ].onfullscreenchange = function() { - /* - fullscreenchange events don't include the new fullscreen status so we need to - retrieve the current status from the fullscreen API. See: - https://developer.mozilla.org/en-US/docs/Web/Reference/Events/fullscreenchange - */ + this.element.style.height = $.getWindowSize().y + 'px'; + this.element.style.width = $.getWindowSize().x + 'px'; - if( $.isFullScreen() ){ - _this.setFullPage( true ); - } else { - document.removeEventListener( - $.fullScreenEventName, - THIS[ _this.hash ].onfullscreenchange - ); - exitFullPage(); - } - }; - - $.requestFullScreen( document.body ); - - // The target of the event is always the document, - // but it is possible to retrieve the fullscreen element through the API - // Note that the API is still vendor-prefixed in browsers implementing it - document.addEventListener( - $.fullScreenEventName, - THIS[ this.hash ].onfullscreenchange - ); - this.element.style.height = '100%'; - this.element.style.width = '100%'; - } else { - this.element.style.height = $.getWindowSize().y + 'px'; - this.element.style.width = $.getWindowSize().x + 'px'; - } - - if( this.toolbar && this.toolbar.element ){ + if ( this.toolbar && this.toolbar.element ) { this.element.style.height = ( $.getElementSize( this.element ).y - $.getElementSize( this.toolbar.element ).y ) + 'px'; @@ -851,21 +725,119 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, // mouse will be inside container now $.delegate( this, onContainerEnter )( {} ); - this.raiseEvent( 'full-page', { fullPage: true } ); - } else { - if( $.supportsFullScreen ){ - $.cancelFullScreen(); - } else { - exitFullPage(); + bodyStyle.margin = this.bodyMargin; + docStyle.margin = this.docMargin; + + bodyStyle.padding = this.bodyPadding; + docStyle.padding = this.docPadding; + + bodyStyle.width = this.bodyWidth; + bodyStyle.height = this.bodyHeight; + + body.removeChild( this.element ); + nodes = this.previousBody.length; + for ( i = 0; i < nodes; i++ ) { + body.appendChild( this.previousBody.shift() ); } + $.removeClass( this.element, 'fullpage' ); + THIS[ this.hash ].prevElementParent.insertBefore( + this.element, + THIS[ this.hash ].prevNextSibling + ); + + //If we've got a toolbar, we need to enable the user to use css to + //reset it to its original state + if ( this.toolbar && this.toolbar.element ) { + body.removeChild( this.toolbar.element ); + + //Make sure the user has some ability to style the toolbar based + //on the mode + $.removeClass( this.toolbar.element, 'fullpage' ); + + this.toolbar.parentNode.insertBefore( + this.toolbar.element, + this.toolbar.nextSibling + ); + delete this.toolbar.parentNode; + delete this.toolbar.nextSibling; + } + + this.element.style.width = THIS[ this.hash ].prevElementWidth; + this.element.style.height = THIS[ this.hash ].prevElementHeight; + + // After exiting fullPage or fullScreen, it can take some time + // before the browser can actually set the scroll. + var restoreScroll = function() { + $.setPageScroll( _this.pageScroll ); + var pageScroll = $.getPageScroll(); + if ( pageScroll.x !== _this.pageScroll.x || + pageScroll.y !== _this.pageScroll.y ) { + $.requestAnimationFrame( restoreScroll ); + } + }; + $.requestAnimationFrame( restoreScroll ); + + THIS[ this.hash ].fullPage = false; + + // mouse will likely be outside now + $.delegate( this, onContainerExit )( { } ); + } + this.raiseEvent( 'full-page', { fullPage: fullPage } ); + return this; }, + /** + * Toggle full screen mode if supported. Toggle full page mode otherwise. + * @function + * @name OpenSeadragon.Viewer.prototype.setFullScreen + * @param {Boolean} fullScreen + * If true, enter full screen mode. If false, exit full screen mode. + * @return {OpenSeadragon.Viewer} Chainable. + */ + setFullScreen: function( fullScreen ) { + var _this = this; + + if ( !$.supportsFullScreen ) { + return this.setFullPage( fullScreen ); + } + + if ( $.isFullScreen() === fullScreen ) { + return this; + } + + this.raiseEvent( 'pre-full-screen', { fullScreen: fullScreen } ); + if ( fullScreen ) { + + this.setFullPage( true ); + + var onFullScreenChange = function() { + var isFullScreen = $.isFullScreen(); + if ( !isFullScreen ) { + $.removeEvent( document, $.fullScreenEventName, onFullScreenChange ); + $.removeEvent( document, $.fullScreenErrorEventName, onFullScreenChange ); + + _this.setFullPage( false ); + } + _this.raiseEvent( 'full-screen', { fullScreen: isFullScreen } ); + }; + $.addEvent( document, $.fullScreenEventName, onFullScreenChange ); + $.addEvent( document, $.fullScreenErrorEventName, onFullScreenChange ); + + $.requestFullScreen( document.body ); + + this.element.style.width = '100%'; + this.element.style.height = '100%'; + } else { + $.cancelFullScreen(); + } + return this; + }, /** * @function @@ -990,7 +962,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, beginZoomingOutHandler = $.delegate( this, beginZoomingOut ), doSingleZoomOutHandler = $.delegate( this, doSingleZoomOut ), onHomeHandler = $.delegate( this, onHome ), - onFullPageHandler = $.delegate( this, onFullPage ), + onFullPageHandler = $.delegate( this, onFullScreen ), onFocusHandler = $.delegate( this, onFocus ), onBlurHandler = $.delegate( this, onBlur ), navImages = this.navImages, @@ -1628,8 +1600,11 @@ function updateOnce( viewer ) { containerSize = _getSafeElemSize( viewer.container ); if ( !containerSize.equals( THIS[ viewer.hash ].prevContainerSize ) ) { // maintain image position - viewer.viewport.resize( containerSize, true ); + var oldBounds = viewer.viewport.getBounds(); + var oldCenter = viewer.viewport.getCenter(); + resizeViewportAndRecenter(viewer, containerSize, oldBounds, oldCenter); THIS[ viewer.hash ].prevContainerSize = containerSize; + THIS[ viewer.hash ].forceRedraw = true; } animated = viewer.viewport.update(); @@ -1670,7 +1645,30 @@ function updateOnce( viewer ) { //viewer.profiler.endUpdate(); } +// This function resize the viewport and recenter the image +// as it was before resizing. +// TODO: better adjust width and height. The new width and height +// should depend on the image dimensions and on the dimensions +// of the viewport before and after switching mode. +function resizeViewportAndRecenter( viewer, containerSize, oldBounds, oldCenter ) { + var viewport = viewer.viewport; + viewport.resize( containerSize, true ); + + // We try to remove blanks as much as possible + var imageHeight = 1 / viewer.source.aspectRatio; + var newWidth = oldBounds.width <= 1 ? oldBounds.width : 1; + var newHeight = oldBounds.height <= imageHeight ? + oldBounds.height : imageHeight; + + var newBounds = new $.Rect( + oldCenter.x - ( newWidth / 2.0 ), + oldCenter.y - ( newHeight / 2.0 ), + newWidth, + newHeight + ); + viewport.fitBounds( newBounds, true ); +} /////////////////////////////////////////////////////////////////////////////// // Navigation Controls @@ -1760,10 +1758,15 @@ function onHome() { } -function onFullPage() { - this.setFullPage( !this.isFullPage() ); +function onFullScreen() { + if ( this.isFullPage() && !$.isFullScreen() ) { + // Is fullPage but not fullScreen + this.setFullPage( false ); + } else { + this.setFullScreen( !this.isFullPage() ); + } // correct for no mouseout event on change - if( this.buttons ){ + if ( this.buttons ) { this.buttons.emulateExit(); } this.fullPageButton.element.focus(); diff --git a/test/basic.js b/test/basic.js index 6bffd5d9..946a8ff3 100644 --- a/test/basic.js +++ b/test/basic.js @@ -174,7 +174,7 @@ }); // ---------- - asyncTest('Fullscreen', function() { + asyncTest('FullPage', function() { viewer.addHandler("open", function () { ok(!viewer.isFullPage(), 'Started out not fullpage'); ok(!$(viewer.element).hasClass('fullpage'), @@ -210,11 +210,6 @@ viewer.addHandler("pre-full-page", checkExitingPreFullPage); viewer.addHandler("full-page", checkExitingFullPage); - - // Workaround: for some reason inside tests, the fullscreen - // mode is never activated, so disable it so that we can - // continue the tests. - OpenSeadragon.supportsFullScreen = false; viewer.setFullPage(false); }; viewer.addHandler("pre-full-page", checkEnteringPreFullPage); @@ -225,6 +220,39 @@ viewer.open('/test/data/testpattern.dzi'); }); + asyncTest('FullScreen', function() { + + if (!OpenSeadragon.supportsFullScreen) { + expect(0); + start(); + return; + } + + viewer.addHandler("open", function () { + ok(!OpenSeadragon.isFullScreen(), 'Started out not fullscreen'); + + var checkEnteringPreFullScreen = function(event) { + viewer.removeHandler('pre-full-screen', checkEnteringPreFullScreen); + ok(event.fullScreen, 'Switching to fullscreen'); + ok(!OpenSeadragon.isFullScreen(), 'Not yet fullscreen'); + }; + + // The fullscreen mode is always denied during tests so we are + // exiting directly. + var checkExitingFullScreen = function(event) { + viewer.removeHandler('full-screen', checkExitingFullScreen); + ok(!event.fullScreen, 'Exiting fullscreen'); + ok(!OpenSeadragon.isFullScreen(), 'Disabled fullscreen'); + start(); + }; + viewer.addHandler("pre-full-screen", checkEnteringPreFullScreen); + viewer.addHandler("full-screen", checkExitingFullScreen); + viewer.setFullScreen(true); + }); + + viewer.open('/test/data/testpattern.dzi'); + }); + // ---------- asyncTest('Close', function() { viewer.addHandler("open", function () { From 6aca0c0886c6bbd34c4a5cfdea16280d268fb6ce Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Fri, 8 Nov 2013 13:56:13 -0500 Subject: [PATCH 6/7] Add counter to avoid trying to set scroll indefinitly Style and spelling fixes Set scrolls tests setup inside own function --- src/viewer.js | 15 +++++++++------ test/polyfills.js | 30 ++++++++++++++---------------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/viewer.js b/src/viewer.js index 9e608f28..3f371737 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -759,7 +759,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, THIS[ this.hash ].prevElementParent.insertBefore( this.element, THIS[ this.hash ].prevNextSibling - ); + ); //If we've got a toolbar, we need to enable the user to use css to //reset it to its original state @@ -773,7 +773,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, this.toolbar.parentNode.insertBefore( this.toolbar.element, this.toolbar.nextSibling - ); + ); delete this.toolbar.parentNode; delete this.toolbar.nextSibling; } @@ -783,10 +783,13 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, // After exiting fullPage or fullScreen, it can take some time // before the browser can actually set the scroll. + var restoreScrollCounter = 0; var restoreScroll = function() { $.setPageScroll( _this.pageScroll ); var pageScroll = $.getPageScroll(); - if ( pageScroll.x !== _this.pageScroll.x || + restoreScrollCounter++; + if ( restoreScrollCounter < 10 && + pageScroll.x !== _this.pageScroll.x || pageScroll.y !== _this.pageScroll.y ) { $.requestAnimationFrame( restoreScroll ); } @@ -975,7 +978,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, beginZoomingOutHandler = $.delegate( this, beginZoomingOut ), doSingleZoomOutHandler = $.delegate( this, doSingleZoomOut ), onHomeHandler = $.delegate( this, onHome ), - onFullPageHandler = $.delegate( this, onFullScreen ), + onFullScreenHandler = $.delegate( this, onFullScreen ), onFocusHandler = $.delegate( this, onFocus ), onBlurHandler = $.delegate( this, onBlur ), navImages = this.navImages, @@ -1050,7 +1053,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, srcGroup: resolveUrl( this.prefixUrl, navImages.fullpage.GROUP ), srcHover: resolveUrl( this.prefixUrl, navImages.fullpage.HOVER ), srcDown: resolveUrl( this.prefixUrl, navImages.fullpage.DOWN ), - onRelease: onFullPageHandler, + onRelease: onFullScreenHandler, onFocus: onFocusHandler, onBlur: onBlurHandler })); @@ -1665,7 +1668,7 @@ function updateOnce( viewer ) { //viewer.profiler.endUpdate(); } -// This function resize the viewport and recenter the image +// This function resizes the viewport and recenters the image // as it was before resizing. // TODO: better adjust width and height. The new width and height // should depend on the image dimensions and on the dimensions diff --git a/test/polyfills.js b/test/polyfills.js index 6811d19a..5e93b1b8 100644 --- a/test/polyfills.js +++ b/test/polyfills.js @@ -2,30 +2,22 @@ ( function() { - var origWidth, origHeight; - module( 'Polyfills', { setup: function() { - - origWidth = $( "body" ).width(); - origHeight = $( "body" ).height(); - $( "body" ).width( origWidth + 10000 ); - $( "body" ).height( origHeight + 10000 ); - - $( document ).scrollLeft( 0 ); - $( document ).scrollTop( 0 ); testLog.reset(); - }, - teardown: function() { - $( "body" ).width( origWidth ); - $( "body" ).height( origHeight ); - $( document ).scrollLeft( 0 ); - $( document ).scrollTop( 0 ); } } ); // ---------- test( 'pageScroll', function() { + // Setup + var origWidth = $( "body" ).width(), + origHeight = $( "body" ).height(); + $( "body" ).width( origWidth + 10000 ); + $( "body" ).height( origHeight + 10000 ); + $( document ).scrollLeft( 0 ); + $( document ).scrollTop( 0 ); + // End setup // Test get var originalGetPageScroll = OpenSeadragon.getPageScroll; @@ -125,6 +117,12 @@ equal( currentSetPageScroll, OpenSeadragon.setPageScroll, "OpenSeadragon.setPageScroll must not be reassigned after first call." ); + + // Teardown + $( "body" ).width( origWidth ); + $( "body" ).height( origHeight ); + $( document ).scrollLeft( 0 ); + $( document ).scrollTop( 0 ); } ); } )(); From 03f25cef5f8b439bfecc598a5acceef90cc198ac Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Fri, 8 Nov 2013 15:03:54 -0500 Subject: [PATCH 7/7] Add support to cancel full screen and full page events. Fix fullpage when element has margin or padding. --- src/viewer.js | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/viewer.js b/src/viewer.js index 3f371737..3de2671c 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -669,13 +669,25 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, return this; } - this.raiseEvent( 'pre-full-page', { fullPage: fullPage } ); + var fullPageEventArgs = { + fullPage: fullPage, + preventDefaultAction: false + }; + this.raiseEvent( 'pre-full-page', fullPageEventArgs ); + if ( fullPageEventArgs.preventDefaultAction ) { + return this; + } if ( fullPage ) { this.elementSize = $.getElementSize( this.element ); this.pageScroll = $.getPageScroll(); + this.elementMargin = this.element.style.margin; + this.element.style.margin = "0"; + this.elementPadding = this.element.style.padding; + this.element.style.padding = "0"; + this.bodyMargin = bodyStyle.margin; this.docMargin = docStyle.margin; bodyStyle.margin = "0"; @@ -740,6 +752,9 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, } else { + this.element.style.margin = this.elementMargin; + this.element.style.padding = this.elementPadding; + bodyStyle.margin = this.bodyMargin; docStyle.margin = this.docMargin; @@ -827,10 +842,28 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, return this; } - this.raiseEvent( 'pre-full-screen', { fullScreen: fullScreen } ); + var fullScreeEventArgs = { + fullScreen: fullScreen, + preventDefaultAction: false + }; + this.raiseEvent( 'pre-full-screen', fullScreeEventArgs ); + if ( fullScreeEventArgs.preventDefaultAction ) { + return this; + } + if ( fullScreen ) { this.setFullPage( true ); + // If the full page mode is not actually entered, we need to prevent + // the full screen mode. + if ( !this.isFullPage() ) { + return this; + } + + this.fullPageStyleWidth = this.element.style.width; + this.fullPageStyleHeight = this.element.style.height; + this.element.style.width = '100%'; + this.element.style.height = '100%'; var onFullScreenChange = function() { var isFullScreen = $.isFullScreen(); @@ -839,6 +872,10 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, $.removeEvent( document, $.fullScreenErrorEventName, onFullScreenChange ); _this.setFullPage( false ); + if ( _this.isFullPage() ) { + _this.element.style.width = _this.fullPageStyleWidth; + _this.element.style.height = _this.fullPageStyleHeight; + } } _this.raiseEvent( 'full-screen', { fullScreen: isFullScreen } ); }; @@ -847,8 +884,6 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, $.requestFullScreen( document.body ); - this.element.style.width = '100%'; - this.element.style.height = '100%'; } else { $.cancelFullScreen(); }