From 2bef2e882fe53a655afb70aec5a45084d82649e5 Mon Sep 17 00:00:00 2001 From: gwills Date: Sat, 7 Sep 2013 17:08:39 +0100 Subject: [PATCH 01/31] IE 10 not reading DZI file correctly IE 10 is treating the data coming back from the JSONP request as a string and not as XML. I have confirmed this issue is happening on numerous IE10 machines but have not seen it on any other browser. The change simply checks the type of the data variable and if it is a string it parses the string as XML and updates the data object. --- src/tilesource.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tilesource.js b/src/tilesource.js index fce3cbb3..9055047b 100644 --- a/src/tilesource.js +++ b/src/tilesource.js @@ -299,6 +299,10 @@ $.TileSource.prototype = { } callback = function( data ){ + if( typeof(data) === "string" ) { + var tmp = new DOMParser(); + data = tmp.parseFromString( data , "text/xml" ); + } var $TileSource = $.TileSource.determineType( _this, data, url ); if ( !$TileSource ) { _this.raiseEvent( 'open-failed', { message: "Unable to load TileSource", source: url } ); From 8f2999da29e780952c732abe06df43dae99cd856 Mon Sep 17 00:00:00 2001 From: gwills Date: Tue, 24 Sep 2013 21:49:54 +0100 Subject: [PATCH 02/31] Use $.parseXml for parsing string as XML --- src/tilesource.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tilesource.js b/src/tilesource.js index 9055047b..8abe8cf0 100644 --- a/src/tilesource.js +++ b/src/tilesource.js @@ -300,8 +300,7 @@ $.TileSource.prototype = { callback = function( data ){ if( typeof(data) === "string" ) { - var tmp = new DOMParser(); - data = tmp.parseFromString( data , "text/xml" ); + data = $.parseXml( data ); } var $TileSource = $.TileSource.determineType( _this, data, url ); if ( !$TileSource ) { From f8a03157573dad376344f8c9155de3ce6aeacf8e Mon Sep 17 00:00:00 2001 From: gwills Date: Tue, 24 Sep 2013 21:54:54 +0100 Subject: [PATCH 03/31] Small formatting change Needed to change spacing to pass through jshint --- src/tilesource.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tilesource.js b/src/tilesource.js index 8abe8cf0..bc936b3b 100644 --- a/src/tilesource.js +++ b/src/tilesource.js @@ -300,7 +300,7 @@ $.TileSource.prototype = { callback = function( data ){ if( typeof(data) === "string" ) { - data = $.parseXml( data ); + data = $.parseXml( data ); } var $TileSource = $.TileSource.determineType( _this, data, url ); if ( !$TileSource ) { From 4cd98a5da9b66facb28ede00e4d86ae52705a0ff Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Sat, 12 Oct 2013 18:30:05 -0400 Subject: [PATCH 04/31] Check hash in viewer constructor. Fix #229 Fix #176 --- src/drawer.js | 1 + src/viewer.js | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/drawer.js b/src/drawer.js index 809d9176..0cc436d6 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -1160,6 +1160,7 @@ function drawTiles( drawer, lastDrawn ){ //$.console.log("Rendering collection tile %s | %s | %s", tile.y, tile.y, position); if( tileSource ){ drawer.collectionOverlays[ tileKey ] = viewer = new $.Viewer({ + hash: viewport.viewer.hash + "-" + tileKey, element: $.makeNeutralElement( "div" ), mouseNavEnabled: false, showNavigator: false, diff --git a/src/viewer.js b/src/viewer.js index e8ef88ac..eef46142 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -100,7 +100,7 @@ $.Viewer = function( options ) { //internal state and dom identifiers id: options.id, - hash: options.id, + hash: options.hash || options.id, //dom nodes element: null, @@ -147,6 +147,15 @@ $.Viewer = function( options ) { }, $.DEFAULT_SETTINGS, options ); + if ( typeof( this.hash) === "undefined" ) { + throw new Error("A hash must be defined, either by specifying options.id or options.hash."); + } + if ( typeof( THIS[ this.hash ] ) !== "undefined" ) { + // We don't want to throw an error here, as the user might have discarded + // the previous viewer with the same hash and now want to recreate it. + $.console.warn("Hash " + this.hash + " has already been used."); + } + //Private state properties THIS[ this.hash ] = { "fsBoundsDelta": new $.Point( 1, 1 ), From a70d082be3e9c3b961a217a712aca762f42ba653 Mon Sep 17 00:00:00 2001 From: gwills Date: Mon, 14 Oct 2013 10:59:20 +0100 Subject: [PATCH 05/31] Fix rotate on rectangular overalys Use size after rotate when positioning the overlay. Also removed check on this.scales - was there a reason these were not handled when rotating? If so we can add a option here maybe. --- src/overlay.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/overlay.js b/src/overlay.js index b828ac9e..f3df6cfb 100644 --- a/src/overlay.js +++ b/src/overlay.js @@ -211,13 +211,14 @@ // TODO replace the size rotation with CSS3 transforms // TODO add an option to overlays to not rotate with the image // Currently only rotates position and size - if( degrees !== 0 && this.scales ) { - overlayCenter = new $.Point( size.x / 2, size.y / 2 ); - + if( degrees !== 0 ) { + overlayCenter = new $.Point( size.x / 2, size.y / 2 ); + var overlayCenterAfterRotate = (degrees === 0 || degrees === 180) ? overlayCenter : new $.Point( size.y / 2, size.x / 2 ); + position = position.plus( overlayCenter ).rotate( degrees, drawerCenter - ).minus( overlayCenter ); + ).minus( overlayCenterAfterRotate ); size = size.rotate( degrees, new $.Point( 0, 0 ) ); size = new $.Point( Math.abs( size.x ), Math.abs( size.y ) ); From e06a5c73c77266daed5af1dee0bdc8223810ca51 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Mon, 14 Oct 2013 10:45:00 -0700 Subject: [PATCH 06/31] Changelog for #255 --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index 44c73777..348d3cfa 100644 --- a/changelog.txt +++ b/changelog.txt @@ -29,6 +29,7 @@ OPENSEADRAGON CHANGELOG * Check that zoom reference point is valid before using it in zoomTo and zoomBy (#247) * Added a number of easier coordinate conversion methods to viewport (#243) * Added the ability to create a viewer and start at a specified page (#252) +* Fixed image resolve issue with collection mode (#255) 0.9.131: From 984dd267b6252e941f06ee3537e65e73244452ca Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Tue, 15 Oct 2013 11:11:08 -0700 Subject: [PATCH 07/31] originalEvent Pass through to EventSource events --- changelog.txt | 3 +++ src/button.js | 18 +++++++++--------- src/viewer.js | 23 +++++++++++++++-------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/changelog.txt b/changelog.txt index 348d3cfa..9a78b48f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -30,6 +30,9 @@ OPENSEADRAGON CHANGELOG * Added a number of easier coordinate conversion methods to viewport (#243) * Added the ability to create a viewer and start at a specified page (#252) * Fixed image resolve issue with collection mode (#255) +* DOM events are now passed through as 'event.originalEvent' in viewer and button events where appropriate. Effects the following events: +* Viewer: 'canvas-release', 'canvas-click', 'canvas-drag', 'canvas-scroll', 'container-enter', 'container-exit', 'container-release' +* Button: 'enter', 'exit', 'press', 'release', 'focus', 'blur', 'click' 0.9.131: diff --git a/src/button.js b/src/button.js index e32ca35a..8a09cdb0 100644 --- a/src/button.js +++ b/src/button.js @@ -178,7 +178,7 @@ $.Button = function( options ) { enterHandler: function( event ) { if ( event.insideElementPressed ) { inTo( _this, $.ButtonState.DOWN ); - _this.raiseEvent( "enter", {} ); + _this.raiseEvent( "enter", { originalEvent: event.originalEvent } ); } else if ( !event.buttonDownAny ) { inTo( _this, $.ButtonState.HOVER ); } @@ -186,30 +186,30 @@ $.Button = function( options ) { focusHandler: function ( event ) { this.enterHandler( event ); - _this.raiseEvent( "focus", {} ); + _this.raiseEvent( "focus", { originalEvent: event.originalEvent } ); }, exitHandler: function( event ) { outTo( _this, $.ButtonState.GROUP ); if ( event.insideElementPressed ) { - _this.raiseEvent( "exit", {} ); + _this.raiseEvent( "exit", { originalEvent: event.originalEvent } ); } }, blurHandler: function ( event ) { this.exitHandler( event ); - _this.raiseEvent( "blur", {} ); + _this.raiseEvent( "blur", { originalEvent: event.originalEvent } ); }, pressHandler: function ( event ) { inTo( _this, $.ButtonState.DOWN ); - _this.raiseEvent( "press", {} ); + _this.raiseEvent( "press", { originalEvent: event.originalEvent } ); }, releaseHandler: function( event ) { if ( event.insideElementPressed && event.insideElementReleased ) { outTo( _this, $.ButtonState.HOVER ); - _this.raiseEvent( "release", {} ); + _this.raiseEvent( "release", { originalEvent: event.originalEvent } ); } else if ( event.insideElementPressed ) { outTo( _this, $.ButtonState.GROUP ); } else { @@ -219,15 +219,15 @@ $.Button = function( options ) { clickHandler: function( event ) { if ( event.quick ) { - _this.raiseEvent("click", {}); + _this.raiseEvent("click", { originalEvent: event.originalEvent }); } }, keyHandler: function( event ){ //console.log( "%s : handling key %s!", _this.tooltip, event.keyCode); if( 13 === event.keyCode ){ - _this.raiseEvent( "click", {} ); - _this.raiseEvent( "release", {} ); + _this.raiseEvent( "click", { originalEvent: event.originalEvent } ); + _this.raiseEvent( "release", { originalEvent: event.originalEvent } ); return false; } return true; diff --git a/src/viewer.js b/src/viewer.js index eef46142..d12c007f 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -530,7 +530,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, VIEWERS[ this.hash ] = null; delete VIEWERS[ this.hash ]; - this.raiseEvent( 'close', {} ); + this.raiseEvent( 'close' ); return this; }, @@ -1487,7 +1487,8 @@ function onCanvasClick( event ) { tracker: event.eventSource, position: event.position, quick: event.quick, - shift: event.shift + shift: event.shift, + originalEvent: event.originalEvent }); } @@ -1512,7 +1513,8 @@ function onCanvasDrag( event ) { tracker: event.eventSource, position: event.position, delta: event.delta, - shift: event.shift + shift: event.shift, + originalEvent: event.originalEvent }); } @@ -1524,7 +1526,8 @@ function onCanvasRelease( event ) { tracker: event.eventSource, position: event.position, insideElementPressed: event.insideElementPressed, - insideElementReleased: event.insideElementReleased + insideElementReleased: event.insideElementReleased, + originalEvent: event.originalEvent }); } @@ -1542,7 +1545,8 @@ function onCanvasScroll( event ) { tracker: event.eventSource, position: event.position, scroll: event.scroll, - shift: event.shift + shift: event.shift, + originalEvent: event.originalEvent }); //cancels event return false; @@ -1559,7 +1563,8 @@ function onContainerExit( event ) { tracker: event.eventSource, position: event.position, insideElementPressed: event.insideElementPressed, - buttonDownAny: event.buttonDownAny + buttonDownAny: event.buttonDownAny, + originalEvent: event.originalEvent }); } @@ -1574,7 +1579,8 @@ function onContainerRelease( event ) { tracker: event.eventSource, position: event.position, insideElementPressed: event.insideElementPressed, - insideElementReleased: event.insideElementReleased + insideElementReleased: event.insideElementReleased, + originalEvent: event.originalEvent }); } @@ -1585,7 +1591,8 @@ function onContainerEnter( event ) { tracker: event.eventSource, position: event.position, insideElementPressed: event.insideElementPressed, - buttonDownAny: event.buttonDownAny + buttonDownAny: event.buttonDownAny, + originalEvent: event.originalEvent }); } From a9d6a82c67f0ec24df72684070fb36afa6068970 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Tue, 15 Oct 2013 11:27:21 -0700 Subject: [PATCH 08/31] Unit test update for EventSource originalEvent --- test/events.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/events.js b/test/events.js index 9c8fefbb..f2f3018c 100644 --- a/test/events.js +++ b/test/events.js @@ -74,6 +74,8 @@ eventsHandledMouseTracker = 0, eventSourcePassedMouseTracker = 0, originalEventsPassedMouseTracker = 0, + eventsHandledViewer = 0, + originalEventsPassedViewer = 0, releasesExpected = 1, clicksExpected = 1; @@ -117,15 +119,27 @@ $canvas.simulate( 'blur', event ); }; + var checkOriginalEventReceivedViewer = function ( event ) { + eventsHandledViewer++; + //TODO Provide a better check for the original event...simulate doesn't currently extend the object + // with arbitrary user data. + if ( event && event.originalEvent ) { + originalEventsPassedViewer++; + } + }; + var onEventSourceDrag = function ( event ) { + checkOriginalEventReceivedViewer( event ); dragsHandledEventSource++; }; var onEventSourceRelease = function ( event ) { + checkOriginalEventReceivedViewer( event ); releasesHandledEventSource++; }; var onEventSourceClick = function ( event ) { + checkOriginalEventReceivedViewer( event ); clicksHandledEventSource++; }; @@ -184,6 +198,7 @@ equal( dragsHandledEventSource, dragCount, "'canvas-drag' event count matches 'mousemove' event count (" + dragCount + ")" ); equal( releasesHandledEventSource, releasesExpected, "'canvas-release' event count matches expected (" + releasesExpected + ")" ); equal( clicksHandledEventSource, releasesExpected, "'canvas-click' event count matches expected (" + releasesExpected + ")" ); + equal( originalEventsPassedViewer, eventsHandledViewer, "Original event received count matches expected (" + eventsHandledViewer + ")" ); equal( eventSourcePassedMouseTracker, eventsHandledMouseTracker, "Event source received count matches expected (" + eventsHandledMouseTracker + ")" ); equal( originalEventsPassedMouseTracker, eventsHandledMouseTracker, "Original event received count matches expected (" + eventsHandledMouseTracker + ")" ); From 54d02ada78ee4d99d69f61dd45a92afa6d3d061b Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Fri, 18 Oct 2013 15:16:49 -0400 Subject: [PATCH 09/31] Replace viewport.getImageZoomRatio by conversion methods between viewport zoom and image zoom --- src/viewport.js | 36 +++++++++++++++++++++++++++++------- test/units.js | 11 ++++++++--- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/viewport.js b/src/viewport.js index 6fa8931f..12fbd956 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -916,19 +916,41 @@ $.Viewport.prototype = { return viewerCoordinates.plus( OpenSeadragon.getElementPosition( this.viewer.element )); }, - + /** - * Get the zoom ratio of the image. 1 means original image size, 0.5 half size... + * Convert a viewport zoom to an image zoom. + * Image zoom: ratio of the original image size to displayed image size. + * 1 means original image size, 0.5 half size... + * Viewport zoom: ratio of the displayed image's width to viewport's width. + * 1 means identical width, 2 means image's width is twice the viewport's width... * @function - * @param {Boolean} current If true gives the current zoom otherwise gives the + * @param {Number} viewportZoom The viewport zoom * target zoom. - * @returns {Number} + * @returns {Number} imageZoom The image zoom */ - getImageZoomRatio: function( current ) { + viewportToImageZoom: function( viewportZoom ) { var imageWidth = this.viewer.source.dimensions.x; var containerWidth = this.getContainerSize().x; - var zoomToZoomLevelRatio = containerWidth / imageWidth; - return this.getZoom( current ) * zoomToZoomLevelRatio; + var viewportToImageZoomRatio = containerWidth / imageWidth; + return viewportZoom * viewportToImageZoomRatio; + }, + + /** + * Convert an image zoom to a viewport zoom. + * Image zoom: ratio of the original image size to displayed image size. + * 1 means original image size, 0.5 half size... + * Viewport zoom: ratio of the displayed image's width to viewport's width. + * 1 means identical width, 2 means image's width is twice the viewport's width... + * @function + * @param {Number} imageZoom The image zoom + * target zoom. + * @returns {Number} viewportZoom The viewport zoom + */ + imageToViewportZoom: function( imageZoom ) { + var imageWidth = this.viewer.source.dimensions.x; + var containerWidth = this.getContainerSize().x; + var viewportToImageZoomRatio = imageWidth / containerWidth; + return imageZoom * viewportToImageZoomRatio; } }; diff --git a/test/units.js b/test/units.js index 1417b801..348835b3 100644 --- a/test/units.js +++ b/test/units.js @@ -91,9 +91,14 @@ function checkZoom() { var currentImageWidth = getCurrentImageWidth(); - var expected = currentImageWidth / imageWidth; - var actual = viewport.getImageZoomRatio(true); - equal(actual, expected); + var expectedImageZoom = currentImageWidth / imageWidth; + var expectedViewportZoom = viewport.getZoom(true); + var actualImageZoom = viewport.viewportToImageZoom( + expectedViewportZoom); + equal(actualImageZoom, expectedImageZoom); + + var actualViewportZoom = viewport.imageToViewportZoom(actualImageZoom); + equal(actualViewportZoom, expectedViewportZoom); } checkZoom(); From 4fc9755906f02d4b715f89c8d54191dd5d700478 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Mon, 21 Oct 2013 17:16:25 -0700 Subject: [PATCH 10/31] changelog.txt update Grammar fix! --- changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 9a78b48f..dcbe8cae 100644 --- a/changelog.txt +++ b/changelog.txt @@ -30,7 +30,7 @@ OPENSEADRAGON CHANGELOG * Added a number of easier coordinate conversion methods to viewport (#243) * Added the ability to create a viewer and start at a specified page (#252) * Fixed image resolve issue with collection mode (#255) -* DOM events are now passed through as 'event.originalEvent' in viewer and button events where appropriate. Effects the following events: +* DOM events are now passed through as 'event.originalEvent' in viewer and button events where appropriate. Affects the following events: * Viewer: 'canvas-release', 'canvas-click', 'canvas-drag', 'canvas-scroll', 'container-enter', 'container-exit', 'container-release' * Button: 'enter', 'exit', 'press', 'release', 'focus', 'blur', 'click' From 3777b53507dd770c2de0b50dd6217ca07248c156 Mon Sep 17 00:00:00 2001 From: gwills Date: Tue, 22 Oct 2013 13:54:32 +0100 Subject: [PATCH 11/31] Revert "Fix rotate on rectangular overalys" This reverts commit a70d082be3e9c3b961a217a712aca762f42ba653. --- src/overlay.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/overlay.js b/src/overlay.js index f3df6cfb..b828ac9e 100644 --- a/src/overlay.js +++ b/src/overlay.js @@ -211,14 +211,13 @@ // TODO replace the size rotation with CSS3 transforms // TODO add an option to overlays to not rotate with the image // Currently only rotates position and size - if( degrees !== 0 ) { - overlayCenter = new $.Point( size.x / 2, size.y / 2 ); - var overlayCenterAfterRotate = (degrees === 0 || degrees === 180) ? overlayCenter : new $.Point( size.y / 2, size.x / 2 ); - + if( degrees !== 0 && this.scales ) { + overlayCenter = new $.Point( size.x / 2, size.y / 2 ); + position = position.plus( overlayCenter ).rotate( degrees, drawerCenter - ).minus( overlayCenterAfterRotate ); + ).minus( overlayCenter ); size = size.rotate( degrees, new $.Point( 0, 0 ) ); size = new $.Point( Math.abs( size.x ), Math.abs( size.y ) ); From 7e0c90c4a496ab009d6d48db9c4f26c49c261429 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Tue, 22 Oct 2013 10:45:54 -0700 Subject: [PATCH 12/31] Changelog for #218 --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index dcbe8cae..8d797229 100644 --- a/changelog.txt +++ b/changelog.txt @@ -33,6 +33,7 @@ OPENSEADRAGON CHANGELOG * DOM events are now passed through as 'event.originalEvent' in viewer and button events where appropriate. Affects the following events: * Viewer: 'canvas-release', 'canvas-click', 'canvas-drag', 'canvas-scroll', 'container-enter', 'container-exit', 'container-release' * Button: 'enter', 'exit', 'press', 'release', 'focus', 'blur', 'click' +* Fixed: IE 10 not reading DZI file correctly in certain circumstances (#218) 0.9.131: From 574aa0f4f1cb367be58aa69164e3e7edef3e6278 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Tue, 22 Oct 2013 10:46:15 -0700 Subject: [PATCH 13/31] Fixed indentation for breaking change lists --- changelog.txt | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/changelog.txt b/changelog.txt index 8d797229..86f1a0e7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -4,21 +4,21 @@ OPENSEADRAGON CHANGELOG 1.0.0: (in progress) * BREAKING CHANGE: All EventSource and MouseTracker event handler method signatures changed to 'handlerMethod(event)' where event == { eventSource, userData, ... } (#251) (Also fixes #23, #224, #239) -* The new eventSource property in the event object replaces the old eventSource parameter that was passed to handler methods. -* Where the event object duplicated the eventSource value, those properties have been removed. This effects the following events: -* All Button events - 'button' property removed -* All Viewer (Viewer, Drawer, Viewport) events - 'viewer' property removed + * The new eventSource property in the event object replaces the old eventSource parameter that was passed to handler methods. + * Where the event object duplicated the eventSource value, those properties have been removed. This effects the following events: + * All Button events - 'button' property removed + * All Viewer (Viewer, Drawer, Viewport) events - 'viewer' property removed * BREAKING CHANGE: Renamed EventHandler to EventSource (#225) * BREAKING CHANGE: Event names changed for consistency: changed to lower case, compound names hyphenated, and "on" prefixes removed (#226): -* Viewer "animationstart" changed to "animation-start" -* Viewer "animationfinish" changed to "animation-finish" -* Button "onPress" changed to "press" -* Button "onRelease" changed to "release" -* Button "onClick" changed to "click" -* Button "onEnter" changed to "enter" -* Button "onExit" changed to "exit" -* Button "onFocus" changed to "focus" -* Button "onBlur" changed to "blur" + * Viewer "animationstart" changed to "animation-start" + * Viewer "animationfinish" changed to "animation-finish" + * Button "onPress" changed to "press" + * Button "onRelease" changed to "release" + * Button "onClick" changed to "click" + * Button "onEnter" changed to "enter" + * Button "onExit" changed to "exit" + * Button "onFocus" changed to "focus" + * Button "onBlur" changed to "blur" * MouseTracker now passes the original event objects to its handler methods (#23) * MouseTracker now supports an optional 'moveHandler' method for tracking mousemove events (#215) * Fixed: Element-relative mouse coordinates now correct if the element and/or page is scrolled (using new OpenSeadragon.getElementOffset() method) (#131) @@ -31,8 +31,8 @@ OPENSEADRAGON CHANGELOG * Added the ability to create a viewer and start at a specified page (#252) * Fixed image resolve issue with collection mode (#255) * DOM events are now passed through as 'event.originalEvent' in viewer and button events where appropriate. Affects the following events: -* Viewer: 'canvas-release', 'canvas-click', 'canvas-drag', 'canvas-scroll', 'container-enter', 'container-exit', 'container-release' -* Button: 'enter', 'exit', 'press', 'release', 'focus', 'blur', 'click' + * Viewer: 'canvas-release', 'canvas-click', 'canvas-drag', 'canvas-scroll', 'container-enter', 'container-exit', 'container-release' + * Button: 'enter', 'exit', 'press', 'release', 'focus', 'blur', 'click' * Fixed: IE 10 not reading DZI file correctly in certain circumstances (#218) 0.9.131: From 8debb26d617065dd4aad816b1ee582471ffdf0c1 Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Tue, 22 Oct 2013 16:54:04 -0400 Subject: [PATCH 14/31] Add mouse stop event --- src/mousetracker.js | 51 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/mousetracker.js b/src/mousetracker.js index e0b9e931..8e19f34c 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -59,11 +59,14 @@ * A reference to an element or an element id for which the mouse * events will be monitored. * @param {Number} options.clickTimeThreshold - * The number of milliseconds within which mutliple mouse clicks + * The number of milliseconds within which multiple mouse clicks * will be treated as a single event. * @param {Number} options.clickDistThreshold * The distance between mouse click within multiple mouse clicks * will be treated as a single event. + * @param {Number} options.stopDelay + * The number of milliseconds without mouse move before the mouse stop + * event is fired. * @param {Function} options.enterHandler * An optional handler for mouse enter. * @param {Function} options.exitHandler @@ -116,6 +119,7 @@ this.clickTimeThreshold = options.clickTimeThreshold; this.clickDistThreshold = options.clickDistThreshold; this.userData = options.userData || null; + this.stopDelay = options.stopDelay || 50; this.enterHandler = options.enterHandler || null; this.exitHandler = options.exitHandler || null; @@ -125,6 +129,7 @@ this.scrollHandler = options.scrollHandler || null; this.clickHandler = options.clickHandler || null; this.dragHandler = options.dragHandler || null; + this.stopHandler = options.stopHandler || null; this.keyHandler = options.keyHandler || null; this.focusHandler = options.focusHandler || null; this.blurHandler = options.blurHandler || null; @@ -389,6 +394,24 @@ */ dragHandler: function () { }, + /** + * Implement or assign implementation to these handlers during or after + * calling the constructor. + * @function + * @param {Object} event + * @param {OpenSeadragon.MouseTracker} event.eventSource + * A reference to the tracker instance. + * @param {OpenSeadragon.Point} event.position + * The position of the event relative to the tracked element. + * @param {Boolean} event.isTouchEvent + * True if the original event is a touch event, otherwise false. + * @param {Object} event.originalEvent + * The original event object. + * @param {Object} event.userData + * Arbitrary user-defined object. + */ + stopHandler: function () { }, + /** * Implement or assign implmentation to these handlers during or after * calling the constructor. @@ -1053,8 +1076,34 @@ $.cancelEvent( event ); } } + if ( tracker.stopHandler ) { + clearTimeout( tracker.stopTimeOut ); + tracker.stopTimeOut = setTimeout( function() { + onMouseStop( tracker, event ); + }, tracker.stopDelay ); + } } + + /** + * @private + * @inner + */ + function onMouseStop( tracker, event ) { + if ( tracker.stopHandler ) { + event = $.getEvent( event ); + var propagate = tracker.stopHandler( { + eventSource: tracker, + position: getMouseRelative( event, tracker.element ), + isTouchEvent: false, + originalEvent: event, + userData: tracker.userData + } ); + if ( propagate === false ) { + $.cancelEvent( event ); + } + } + } /** * @private From e76c9e65ab90433f04b295ae525062b820703d44 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Wed, 23 Oct 2013 12:58:36 -0700 Subject: [PATCH 15/31] Added 'wheel' Event Support Also improved OpenSeadragon.addEvent()/OpenSeadragon.removeEvent() --- changelog.txt | 3 +- src/mousetracker.js | 135 +++++++++++++++++++++++++++++++------------ src/openseadragon.js | 96 +++++++++++++++--------------- 3 files changed, 147 insertions(+), 87 deletions(-) diff --git a/changelog.txt b/changelog.txt index 86f1a0e7..6c1eef95 100644 --- a/changelog.txt +++ b/changelog.txt @@ -5,7 +5,7 @@ OPENSEADRAGON CHANGELOG * BREAKING CHANGE: All EventSource and MouseTracker event handler method signatures changed to 'handlerMethod(event)' where event == { eventSource, userData, ... } (#251) (Also fixes #23, #224, #239) * The new eventSource property in the event object replaces the old eventSource parameter that was passed to handler methods. - * Where the event object duplicated the eventSource value, those properties have been removed. This effects the following events: + * Where the event object duplicated the eventSource value, those properties have been removed. This affects the following events: * All Button events - 'button' property removed * All Viewer (Viewer, Drawer, Viewport) events - 'viewer' property removed * BREAKING CHANGE: Renamed EventHandler to EventSource (#225) @@ -34,6 +34,7 @@ OPENSEADRAGON CHANGELOG * Viewer: 'canvas-release', 'canvas-click', 'canvas-drag', 'canvas-scroll', 'container-enter', 'container-exit', 'container-release' * Button: 'enter', 'exit', 'press', 'release', 'focus', 'blur', 'click' * Fixed: IE 10 not reading DZI file correctly in certain circumstances (#218) +* Added support for the 'wheel' DOM mousewheel event (#261) 0.9.131: diff --git a/src/mousetracker.js b/src/mousetracker.js index e0b9e931..d274fe8b 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -157,8 +157,9 @@ mouseup: function ( event ) { onMouseUp( _this, event, false ); }, mousemove: function ( event ) { onMouseMove( _this, event ); }, click: function ( event ) { onMouseClick( _this, event ); }, - DOMMouseScroll: function ( event ) { onMouseWheelSpin( _this, event, false ); }, - mousewheel: function ( event ) { onMouseWheelSpin( _this, event, false ); }, + wheel: function ( event ) { onWheel( _this, event ); }, + mousewheel: function ( event ) { onMouseWheel( _this, event ); }, + DOMMouseScroll: function ( event ) { onMouseWheel( _this, event ); }, mouseupie: function ( event ) { onMouseUpIE( _this, event ); }, mousemovecapturedie: function ( event ) { onMouseMoveCapturedIE( _this, event ); }, mouseupcaptured: function ( event ) { onMouseUpCaptured( _this, event ); }, @@ -436,6 +437,13 @@ blurHandler: function () { } }; + /** + * Detect available mouse wheel event. + */ + $.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 + /** * Starts tracking mouse events on this element. * @private @@ -445,7 +453,7 @@ var events = [ "mouseover", "mouseout", "mousedown", "mouseup", "mousemove", "click", - "DOMMouseScroll", "mousewheel", + $.MouseTracker.wheelEventName, "touchstart", "touchmove", "touchend", "keypress", "focus", "blur" @@ -478,7 +486,7 @@ var events = [ "mouseover", "mouseout", "mousedown", "mouseup", "mousemove", "click", - "DOMMouseScroll", "mousewheel", + $.MouseTracker.wheelEventName, "touchstart", "touchmove", "touchend", "keypress", "focus", "blur" @@ -1071,42 +1079,81 @@ * @private * @inner */ - function onMouseWheelSpin( tracker, event, isTouch ) { + function onWheel( tracker, event ) { + handleWheelEvent( tracker, event, event, false ); + } + + + /** + * @private + * @inner + */ + function onMouseWheel( tracker, originalEvent ) { + // For legacy IE, access the global (window) event object + originalEvent = originalEvent || window.event; + + // Simulate a 'wheel' event + var event = { + target: originalEvent.target || originalEvent.srcElement, + type: "wheel", + shiftKey: originalEvent.shiftKey || false, + clientX: originalEvent.clientX, + clientY: originalEvent.clientY, + pageX: originalEvent.pageX ? originalEvent.pageX : originalEvent.clientX, + pageY: originalEvent.pageY ? originalEvent.pageY : originalEvent.clientY, + deltaMode: originalEvent.type == "MozMousePixelScroll" ? 0 : 1, // 0=pixel, 1=line, 2=page + deltaX: 0, + deltaZ: 0, + preventDefault: function() { + if ( originalEvent.preventDefault ) { + originalEvent.preventDefault(); + } else { + originalEvent.returnValue = false; + } + } + }; + + // Calculate event.deltaY + if ( $.MouseTracker.wheelEventName == "mousewheel" ) { + event.deltaY = - 1 / $.DEFAULT_SETTINGS.pixelsPerWheelLine * originalEvent.wheelDelta; + } else { + event.deltaY = originalEvent.detail; + } + + handleWheelEvent( tracker, event, originalEvent, false ); + } + + + /** + * Handles 'wheel' events. + * The event may be simulated by the legacy mouse wheel event handler (onMouseWheel()) or onTouchMove(). + * + * @private + * @inner + */ + function handleWheelEvent( tracker, event, originalEvent, isTouch ) { var nDelta = 0, propagate; isTouch = isTouch || false; - if ( !event ) { // For IE, access the global (window) event object - event = window.event; - } - - if ( event.wheelDelta ) { // IE and Opera - nDelta = event.wheelDelta; - if ( window.opera ) { // Opera has the values reversed - nDelta = -nDelta; - } - } else if ( event.detail ) { // Mozilla FireFox - nDelta = -event.detail; - } - //The nDelta variable is gated to provide smooth z-index scrolling - //since the mouse wheel allows for substantial deltas meant for rapid - //y-index scrolling. - nDelta = nDelta > 0 ? 1 : -1; + // The nDelta variable is gated to provide smooth z-index scrolling + // since the mouse wheel allows for substantial deltas meant for rapid + // y-index scrolling. + // event.deltaMode: 0=pixel, 1=line, 2=page + // TODO: Deltas in pixel mode should be accumulated then a scroll value computed after $.DEFAULT_SETTINGS.pixelsPerWheelLine threshold reached + nDelta = event.deltaY < 0 ? 1 : -1; if ( tracker.scrollHandler ) { propagate = tracker.scrollHandler( { - eventSource: tracker, - // Note: Ok to call getMouseRelative on passed event for isTouch==true since - // event.pageX/event.pageY are added to the original touchmove event in - // onTouchMove(). - position: getMouseRelative( event, tracker.element ), - scroll: nDelta, - shift: event.shiftKey, - isTouchEvent: isTouch, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( event, tracker.element ), + scroll: nDelta, + shift: event.shiftKey, + isTouchEvent: isTouch, + originalEvent: originalEvent, + userData: tracker.userData } ); if ( propagate === false ) { @@ -1229,15 +1276,29 @@ if ( Math.abs( THIS[ tracker.hash ].lastPinchDelta - pinchDelta ) > 75 ) { //$.console.debug( "pinch delta : " + pinchDelta + " | previous : " + THIS[ tracker.hash ].lastPinchDelta); - // Simulate a mouse wheel scroll event + // Simulate a 'wheel' event var simulatedEvent = { - shiftKey: event.shiftKey || false, - pageX: THIS[ tracker.hash ].pinchMidpoint.x, - pageY: THIS[ tracker.hash ].pinchMidpoint.y, - detail: ( THIS[ tracker.hash ].lastPinchDelta > pinchDelta ) ? 1 : -1 + target: event.target || event.srcElement, + type: "wheel", + shiftKey: event.shiftKey || false, + clientX: event.clientX, + clientY: event.clientY, + pageX: event.pageX ? event.pageX : event.clientX, + pageY: event.pageY ? event.pageY : event.clientY, + deltaMode: 1, // 0=pixel, 1=line, 2=page + deltaX: 0, + deltaY: ( THIS[ tracker.hash ].lastPinchDelta > pinchDelta ) ? 1 : -1, + deltaZ: 0, + preventDefault: function() { + if ( event.preventDefault ) { + event.preventDefault(); + } else { + event.returnValue = false; + } + } }; - onMouseWheelSpin( tracker, simulatedEvent, true ); + handleWheelEvent( tracker, simulatedEvent, event, true ); THIS[ tracker.hash ].lastPinchDelta = pinchDelta; } diff --git a/src/openseadragon.js b/src/openseadragon.js index 0c0a01ca..34d275ca 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -386,6 +386,50 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ }; + /** + * Detect event model and create appropriate _addEvent/_removeEvent methods + */ + if ( window.addEventListener ) { + //$._addEventListener = 'addEventListener'; + //$._eventNamePrefix = ''; + $._addEvent = function ( element, eventName, handler, useCapture ) { + element = $.getElement( element ); + element.addEventListener( eventName, handler, useCapture ); + }; + } else if ( window.attachEvent ) { + //$._addEventListener = 'attachEvent'; + //$._eventNamePrefix = 'on'; + $._addEvent = function ( element, eventName, handler, useCapture ) { + element = $.getElement( element ); + element.attachEvent( 'on' + eventName, handler ); + if ( useCapture && element.setCapture ) { + element.setCapture(); + } + }; + } else { + throw new Error( "No known event model." ); + } + + if ( window.removeEventListener ) { + //$._removeEventListener = 'removeEventListener'; + $._removeEvent = function ( element, eventName, handler, useCapture ) { + element = $.getElement( element ); + element.removeEventListener( eventName, handler, useCapture ); + }; + } else if ( window.detachEvent ) { + //$._removeEventListener = 'detachEvent'; + $._removeEvent = function( element, eventName, handler, useCapture ) { + element = $.getElement( element ); + element.detachEvent( 'on' + eventName, handler ); + if ( useCapture && element.releaseCapture ) { + element.releaseCapture(); + } + }; + } else { + throw new Error( "No known event model." ); + } + + }( OpenSeadragon )); /** @@ -517,6 +561,7 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ immediateRender: false, minZoomImageRatio: 0.9, //-> closer to 0 allows zoom out to infinity maxZoomPixelRatio: 1.1, //-> higher allows 'over zoom' into pixels + pixelsPerWheelLine: 40, //DEFAULT CONTROL SETTINGS showSequenceControl: true, //SEQUENCE @@ -1142,33 +1187,9 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ * @param {String} eventName * @param {Function} handler * @param {Boolean} [useCapture] - * @throws {Error} */ addEvent: function( element, eventName, handler, useCapture ) { - element = $.getElement( element ); - - //TODO: Why do this if/else on every method call instead of just - // defining this function once based on the same logic - if ( element.addEventListener ) { - $.addEvent = function( element, eventName, handler, useCapture ){ - element = $.getElement( element ); - element.addEventListener( eventName, handler, useCapture ); - }; - } else if ( element.attachEvent ) { - $.addEvent = function( element, eventName, handler, useCapture ){ - element = $.getElement( element ); - element.attachEvent( "on" + eventName, handler ); - if ( useCapture && element.setCapture ) { - element.setCapture(); - } - }; - } else { - throw new Error( - "Unable to attach event handler, no known technique." - ); - } - - return $.addEvent( element, eventName, handler, useCapture ); + return $._addEvent( element, eventName, handler, useCapture ); }, @@ -1181,32 +1202,9 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ * @param {String} eventName * @param {Function} handler * @param {Boolean} [useCapture] - * @throws {Error} */ removeEvent: function( element, eventName, handler, useCapture ) { - element = $.getElement( element ); - - //TODO: Why do this if/else on every method call instead of just - // defining this function once based on the same logic - if ( element.removeEventListener ) { - $.removeEvent = function( element, eventName, handler, useCapture ) { - element = $.getElement( element ); - element.removeEventListener( eventName, handler, useCapture ); - }; - } else if ( element.detachEvent ) { - $.removeEvent = function( element, eventName, handler, useCapture ) { - element = $.getElement( element ); - element.detachEvent("on" + eventName, handler); - if ( useCapture && element.releaseCapture ) { - element.releaseCapture(); - } - }; - } else { - throw new Error( - "Unable to detach event handler, no known technique." - ); - } - return $.removeEvent( element, eventName, handler, useCapture ); + return $._removeEvent( element, eventName, handler, useCapture ); }, From 755c4752c099f4279abb338d086e5e20b2666e6e Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Wed, 23 Oct 2013 13:55:52 -0700 Subject: [PATCH 16/31] 'wheel' Event Support Fixes Whitespace, cancel handling --- src/mousetracker.js | 79 ++++++++++++++++++-------------------------- src/openseadragon.js | 6 ---- 2 files changed, 33 insertions(+), 52 deletions(-) diff --git a/src/mousetracker.js b/src/mousetracker.js index d274fe8b..2f337711 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -440,9 +440,10 @@ /** * Detect available mouse wheel event. */ - $.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 = ( $.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 /** * Starts tracking mouse events on this element. @@ -1088,39 +1089,32 @@ * @private * @inner */ - function onMouseWheel( tracker, originalEvent ) { + function onMouseWheel( tracker, event ) { // For legacy IE, access the global (window) event object - originalEvent = originalEvent || window.event; + event = event || window.event; // Simulate a 'wheel' event - var event = { - target: originalEvent.target || originalEvent.srcElement, - type: "wheel", - shiftKey: originalEvent.shiftKey || false, - clientX: originalEvent.clientX, - clientY: originalEvent.clientY, - pageX: originalEvent.pageX ? originalEvent.pageX : originalEvent.clientX, - pageY: originalEvent.pageY ? originalEvent.pageY : originalEvent.clientY, - deltaMode: originalEvent.type == "MozMousePixelScroll" ? 0 : 1, // 0=pixel, 1=line, 2=page - deltaX: 0, - deltaZ: 0, - preventDefault: function() { - if ( originalEvent.preventDefault ) { - originalEvent.preventDefault(); - } else { - originalEvent.returnValue = false; - } - } + var simulatedEvent = { + target: event.target || event.srcElement, + type: "wheel", + shiftKey: event.shiftKey || false, + clientX: event.clientX, + clientY: event.clientY, + pageX: event.pageX ? event.pageX : event.clientX, + pageY: event.pageY ? event.pageY : event.clientY, + deltaMode: event.type == "MozMousePixelScroll" ? 0 : 1, // 0=pixel, 1=line, 2=page + deltaX: 0, + deltaZ: 0 }; - // Calculate event.deltaY + // Calculate deltaY if ( $.MouseTracker.wheelEventName == "mousewheel" ) { - event.deltaY = - 1 / $.DEFAULT_SETTINGS.pixelsPerWheelLine * originalEvent.wheelDelta; + simulatedEvent.deltaY = - 1 / $.DEFAULT_SETTINGS.pixelsPerWheelLine * event.wheelDelta; } else { - event.deltaY = originalEvent.detail; + simulatedEvent.deltaY = event.detail; } - handleWheelEvent( tracker, event, originalEvent, false ); + handleWheelEvent( tracker, simulatedEvent, event, false ); } @@ -1157,7 +1151,7 @@ } ); if ( propagate === false ) { - $.cancelEvent( event ); + $.cancelEvent( originalEvent ); } } } @@ -1278,24 +1272,17 @@ // Simulate a 'wheel' event var simulatedEvent = { - target: event.target || event.srcElement, - type: "wheel", - shiftKey: event.shiftKey || false, - clientX: event.clientX, - clientY: event.clientY, - pageX: event.pageX ? event.pageX : event.clientX, - pageY: event.pageY ? event.pageY : event.clientY, - deltaMode: 1, // 0=pixel, 1=line, 2=page - deltaX: 0, - deltaY: ( THIS[ tracker.hash ].lastPinchDelta > pinchDelta ) ? 1 : -1, - deltaZ: 0, - preventDefault: function() { - if ( event.preventDefault ) { - event.preventDefault(); - } else { - event.returnValue = false; - } - } + target: event.target || event.srcElement, + type: "wheel", + shiftKey: event.shiftKey || false, + clientX: THIS[ tracker.hash ].pinchMidpoint.x, + clientY: THIS[ tracker.hash ].pinchMidpoint.y, + pageX: THIS[ tracker.hash ].pinchMidpoint.x, + pageY: THIS[ tracker.hash ].pinchMidpoint.y, + deltaMode: 1, // 0=pixel, 1=line, 2=page + deltaX: 0, + deltaY: ( THIS[ tracker.hash ].lastPinchDelta > pinchDelta ) ? 1 : -1, + deltaZ: 0 }; handleWheelEvent( tracker, simulatedEvent, event, true ); diff --git a/src/openseadragon.js b/src/openseadragon.js index 34d275ca..3d19f727 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -390,15 +390,11 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ * Detect event model and create appropriate _addEvent/_removeEvent methods */ if ( window.addEventListener ) { - //$._addEventListener = 'addEventListener'; - //$._eventNamePrefix = ''; $._addEvent = function ( element, eventName, handler, useCapture ) { element = $.getElement( element ); element.addEventListener( eventName, handler, useCapture ); }; } else if ( window.attachEvent ) { - //$._addEventListener = 'attachEvent'; - //$._eventNamePrefix = 'on'; $._addEvent = function ( element, eventName, handler, useCapture ) { element = $.getElement( element ); element.attachEvent( 'on' + eventName, handler ); @@ -411,13 +407,11 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ } if ( window.removeEventListener ) { - //$._removeEventListener = 'removeEventListener'; $._removeEvent = function ( element, eventName, handler, useCapture ) { element = $.getElement( element ); element.removeEventListener( eventName, handler, useCapture ); }; } else if ( window.detachEvent ) { - //$._removeEventListener = 'detachEvent'; $._removeEvent = function( element, eventName, handler, useCapture ) { element = $.getElement( element ); element.detachEvent( 'on' + eventName, handler ); From 0f8ac4cfab1e68adfcc56088ae1cd3663fe1c911 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Thu, 24 Oct 2013 13:39:00 -0700 Subject: [PATCH 17/31] Added 'MozMousePixelScroll' event handling For older Firefox versions --- src/mousetracker.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/mousetracker.js b/src/mousetracker.js index 2f337711..a12b3d50 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -160,6 +160,7 @@ wheel: function ( event ) { onWheel( _this, event ); }, mousewheel: function ( event ) { onMouseWheel( _this, event ); }, DOMMouseScroll: function ( event ) { onMouseWheel( _this, event ); }, + MozMousePixelScroll: function ( event ) { onMouseWheel( _this, event ); }, mouseupie: function ( event ) { onMouseUpIE( _this, event ); }, mousemovecapturedie: function ( event ) { onMouseMoveCapturedIE( _this, event ); }, mouseupcaptured: function ( event ) { onMouseUpCaptured( _this, event ); }, @@ -463,6 +464,11 @@ event, i; + // Add 'MozMousePixelScroll' event handler for older Firefox + if( $.MouseTracker.wheelEventName == "DOMMouseScroll" ) { + events.push( "MozMousePixelScroll" ); + } + if ( !delegate.tracking ) { for ( i = 0; i < events.length; i++ ) { event = events[ i ]; @@ -496,6 +502,11 @@ event, i; + // Remove 'MozMousePixelScroll' event handler for older Firefox + if( $.MouseTracker.wheelEventName == "DOMMouseScroll" ) { + events.push( "MozMousePixelScroll" ); + } + if ( delegate.tracking ) { for ( i = 0; i < events.length; i++ ) { event = events[ i ]; @@ -1077,6 +1088,8 @@ /** + * Handler for 'wheel' events + * * @private * @inner */ @@ -1086,6 +1099,8 @@ /** + * Handler for 'mousewheel', 'DOMMouseScroll', and 'MozMousePixelScroll' events + * * @private * @inner */ From d6b187eb0688fcfbc7b7745bb0bc0ba0f4f22221 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Mon, 28 Oct 2013 12:36:29 -0700 Subject: [PATCH 18/31] Fix for non-canvas tile rendering at large size In USE_CANVAS==false mode, wrapped tile img elements in div elements to allow them to be rendered larger than their containing element without being stretched. --- src/tile.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/tile.js b/src/tile.js index 3ba62636..f7b2464c 100644 --- a/src/tile.js +++ b/src/tile.js @@ -55,7 +55,8 @@ * @property {String} url The URL of this tile's image. * @property {Boolean} loaded Is this tile loaded? * @property {Boolean} loading Is this tile loading - * @property {Element} element The HTML element for this tile + * @property {Element} element The HTML div element for this tile + * @property {Element} imgElement The HTML img element for this tile * @property {Image} image The Image object for this tile * @property {String} style The alias of this.element.style. * @property {String} position This tile's position on screen, in pixels. @@ -78,6 +79,7 @@ $.Tile = function(level, x, y, bounds, exists, url) { this.loading = false; this.element = null; + this.imgElement = null; this.image = null; this.style = null; @@ -122,9 +124,12 @@ $.Tile.prototype = { // content during animation of the container size. if ( !this.element ) { - this.element = $.makeNeutralElement("img"); - this.element.src = this.url; - this.element.style.msInterpolationMode = "nearest-neighbor"; + this.element = $.makeNeutralElement( "div" ); + this.imgElement = $.makeNeutralElement( "img" ); + this.imgElement.src = this.url; + this.imgElement.style.msInterpolationMode = "nearest-neighbor"; + this.imgElement.style.width = "100%"; + this.imgElement.style.height = "100%"; this.style = this.element.style; this.style.position = "absolute"; @@ -132,6 +137,9 @@ $.Tile.prototype = { if ( this.element.parentNode != container ) { container.appendChild( this.element ); } + if ( this.imgElement.parentNode != this.element ) { + this.element.appendChild( this.imgElement ); + } this.style.top = this.position.y + "px"; this.style.left = this.position.x + "px"; @@ -216,6 +224,9 @@ $.Tile.prototype = { * @function */ unload: function() { + if ( this.imgElement && this.imgElement.parentNode ) { + this.imgElement.parentNode.removeChild( this.imgElement ); + } if ( this.element && this.element.parentNode ) { this.element.parentNode.removeChild( this.element ); } @@ -224,6 +235,7 @@ $.Tile.prototype = { } this.element = null; + this.imgElement = null; this.image = null; this.loaded = false; this.loading = false; From cfd76a6fd96df97e6e896e331719a1422a28cdd8 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Mon, 28 Oct 2013 12:38:17 -0700 Subject: [PATCH 19/31] Whitespace fix --- src/tile.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tile.js b/src/tile.js index f7b2464c..eb6f333c 100644 --- a/src/tile.js +++ b/src/tile.js @@ -234,11 +234,11 @@ $.Tile.prototype = { delete TILE_CACHE[ this.url ]; } - this.element = null; + this.element = null; this.imgElement = null; - this.image = null; - this.loaded = false; - this.loading = false; + this.image = null; + this.loaded = false; + this.loading = false; } }; From 9e5dcd766f7bd6d6ccaf0321addda900156fddcd Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Wed, 30 Oct 2013 13:35:39 -0700 Subject: [PATCH 20/31] Punctuation fix --- src/tile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tile.js b/src/tile.js index eb6f333c..fc985d1e 100644 --- a/src/tile.js +++ b/src/tile.js @@ -54,7 +54,7 @@ * this tile failed to load? * @property {String} url The URL of this tile's image. * @property {Boolean} loaded Is this tile loaded? - * @property {Boolean} loading Is this tile loading + * @property {Boolean} loading Is this tile loading? * @property {Element} element The HTML div element for this tile * @property {Element} imgElement The HTML img element for this tile * @property {Image} image The Image object for this tile From 542d5f5aebe950641162a88f720718d89ed8d128 Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Wed, 30 Oct 2013 21:28:10 -0400 Subject: [PATCH 21/31] Remove cancelEvent + fix typos --- src/mousetracker.js | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/mousetracker.js b/src/mousetracker.js index 8e19f34c..4ce7e82c 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -224,7 +224,7 @@ }, /** - * Implement or assign implmentation to these handlers during or after + * Implement or assign implementation to these handlers during or after * calling the constructor. * @function * @param {Object} event @@ -247,7 +247,7 @@ enterHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after + * Implement or assign implementation to these handlers during or after * calling the constructor. * @function * @param {Object} event @@ -270,7 +270,7 @@ exitHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after + * Implement or assign implementation to these handlers during or after * calling the constructor. * @function * @param {Object} event @@ -288,7 +288,7 @@ pressHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after + * Implement or assign implementation to these handlers during or after * calling the constructor. * @function * @param {Object} event @@ -311,7 +311,7 @@ releaseHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after + * Implement or assign implementation to these handlers during or after * calling the constructor. * @function * @param {Object} event @@ -329,7 +329,7 @@ moveHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after + * Implement or assign implementation to these handlers during or after * calling the constructor. * @function * @param {Object} event @@ -351,7 +351,7 @@ scrollHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after + * Implement or assign implementation to these handlers during or after * calling the constructor. * @function * @param {Object} event @@ -373,7 +373,7 @@ clickHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after + * Implement or assign implementation to these handlers during or after * calling the constructor. * @function * @param {Object} event @@ -413,7 +413,7 @@ stopHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after + * Implement or assign implementation to these handlers during or after * calling the constructor. * @function * @param {Object} event @@ -431,7 +431,7 @@ keyHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after + * Implement or assign implementation to these handlers during or after * calling the constructor. * @function * @param {Object} event @@ -445,7 +445,7 @@ focusHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after + * Implement or assign implementation to these handlers during or after * calling the constructor. * @function * @param {Object} event @@ -1092,16 +1092,13 @@ if ( tracker.stopHandler ) { event = $.getEvent( event ); - var propagate = tracker.stopHandler( { + tracker.stopHandler( { eventSource: tracker, position: getMouseRelative( event, tracker.element ), isTouchEvent: false, originalEvent: event, userData: tracker.userData } ); - if ( propagate === false ) { - $.cancelEvent( event ); - } } } From 667204096a40c0a421ec8a3ade7747dafc21e3e1 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Thu, 31 Oct 2013 10:17:08 -0700 Subject: [PATCH 22/31] Changelog for #264. --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index 86f1a0e7..8e30cacb 100644 --- a/changelog.txt +++ b/changelog.txt @@ -34,6 +34,7 @@ OPENSEADRAGON CHANGELOG * Viewer: 'canvas-release', 'canvas-click', 'canvas-drag', 'canvas-scroll', 'container-enter', 'container-exit', 'container-release' * Button: 'enter', 'exit', 'press', 'release', 'focus', 'blur', 'click' * Fixed: IE 10 not reading DZI file correctly in certain circumstances (#218) +* Fix for non-canvas tile rendering at large size (#264) 0.9.131: From 3f5db8f8de07047ade61a1f3de2680ab620d7255 Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Thu, 31 Oct 2013 16:16:08 -0400 Subject: [PATCH 23/31] Fix mousestop event on IE --- src/mousetracker.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/mousetracker.js b/src/mousetracker.js index 4ce7e82c..f0a91ff5 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -1088,15 +1088,13 @@ * @private * @inner */ - function onMouseStop( tracker, event ) { + function onMouseStop( tracker, originalMoveEvent ) { if ( tracker.stopHandler ) { - event = $.getEvent( event ); - tracker.stopHandler( { eventSource: tracker, - position: getMouseRelative( event, tracker.element ), + position: getMouseRelative( originalMoveEvent, tracker.element ), isTouchEvent: false, - originalEvent: event, + originalEvent: originalMoveEvent, userData: tracker.userData } ); } From e209846ac144282a9b4d7b4d78d6a36b0ad88bc9 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 1 Nov 2013 10:19:47 -0700 Subject: [PATCH 24/31] Use canvas whenever possible (#191) Drawer uses an HTML5 canvas element if it's available. Viewer.useCanvas can be used to override (default is true). --- changelog.txt | 1 + src/drawer.js | 9 +++++---- src/openseadragon.js | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index 8e30cacb..c1615913 100644 --- a/changelog.txt +++ b/changelog.txt @@ -35,6 +35,7 @@ OPENSEADRAGON CHANGELOG * Button: 'enter', 'exit', 'press', 'release', 'focus', 'blur', 'click' * Fixed: IE 10 not reading DZI file correctly in certain circumstances (#218) * Fix for non-canvas tile rendering at large size (#264) +* Drawer now uses an HTML5 canvas element if it's available. Can be overridden with Viewer.useCanvas option (#191) 0.9.131: diff --git a/src/drawer.js b/src/drawer.js index 0cc436d6..91771e5a 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -46,10 +46,7 @@ var DEVICE_SCREEN = $.getWindowSize(), ( BROWSER == $.BROWSERS.IE && BROWSER_VERSION >= 9 ) ), - USE_CANVAS = SUBPIXEL_RENDERING && - !( DEVICE_SCREEN.x <= 400 || DEVICE_SCREEN.y <= 400 ) && - !( navigator.appVersion.match( 'Mobile' ) ) && - $.isFunction( document.createElement( "canvas" ).getContext ); + USE_CANVAS = $.supportsCanvas; //console.error( 'USE_CANVAS ' + USE_CANVAS ); @@ -124,6 +121,10 @@ $.Drawer = function( options ) { }, options ); + if ( this.viewer ) { + USE_CANVAS = $.supportsCanvas && this.viewer.useCanvas; + } + this.container = $.getElement( this.element ); this.canvas = $.makeNeutralElement( USE_CANVAS ? "canvas" : "div" ); this.context = USE_CANVAS ? this.canvas.getContext( "2d" ) : null; diff --git a/src/openseadragon.js b/src/openseadragon.js index 0c0a01ca..0edb9b33 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -386,6 +386,19 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ }; + /* + * Detect canvas support + */ + var canvasElement = document.createElement( 'canvas' ); + /** + * True if the browser supports the HTML5 canvas element + * @name $.supportsCanvas + * @property + */ + $.supportsCanvas = !!( $.isFunction( canvasElement.getContext ) && + canvasElement.getContext( '2d' ) ); + + }( OpenSeadragon )); /** @@ -559,6 +572,7 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ imageLoaderLimit: 0, maxImageCacheCount: 200, timeout: 30000, + useCanvas: true, // Use canvas element for drawing if available //INTERFACE RESOURCE SETTINGS prefixUrl: "/images/", From 5d034b9ad20d8b2eee9c1930c46b4277a28c037f Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 1 Nov 2013 10:33:17 -0700 Subject: [PATCH 25/31] changelog.txt update --- changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index c1615913..16ae2c67 100644 --- a/changelog.txt +++ b/changelog.txt @@ -35,7 +35,7 @@ OPENSEADRAGON CHANGELOG * Button: 'enter', 'exit', 'press', 'release', 'focus', 'blur', 'click' * Fixed: IE 10 not reading DZI file correctly in certain circumstances (#218) * Fix for non-canvas tile rendering at large size (#264) -* Drawer now uses an HTML5 canvas element if it's available. Can be overridden with Viewer.useCanvas option (#191) +* Drawer now uses an HTML5 canvas element whenever it's available. Can be overridden with the Viewer.useCanvas option (#191) 0.9.131: From dbb7cee76a2cd7f97b767aefc86231cfeada3e70 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Fri, 1 Nov 2013 11:18:35 -0700 Subject: [PATCH 26/31] Changelog for #262 --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index 229032db..0b52e2b6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -21,6 +21,7 @@ OPENSEADRAGON CHANGELOG * Button "onBlur" changed to "blur" * MouseTracker now passes the original event objects to its handler methods (#23) * MouseTracker now supports an optional 'moveHandler' method for tracking mousemove events (#215) +* Added stopHandler to MouseTracker. (#262) * Fixed: Element-relative mouse coordinates now correct if the element and/or page is scrolled (using new OpenSeadragon.getElementOffset() method) (#131) * Fixed: Pinch zoom event issue, regressive issue from previous event system changes (#244) * Added IIIF Image API 1.1 Tile Source (#230) From 085c7f2ecb3be0426b1c96f67f921d3d4028dfc9 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 1 Nov 2013 13:02:28 -0700 Subject: [PATCH 27/31] Use canvas when available - Fixes Updated documentation doclet. Enclosed detection code in a function. Eliminated the Drawer USE_CANVAS global and replaced it with a Drawer.useCanvas instance variable. --- src/drawer.js | 23 +++++++++-------------- src/openseadragon.js | 30 +++++++++++++++++------------- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/drawer.js b/src/drawer.js index 91771e5a..696bb193 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -44,11 +44,8 @@ var DEVICE_SCREEN = $.getWindowSize(), ( BROWSER == $.BROWSERS.SAFARI && BROWSER_VERSION >= 4 ) || ( BROWSER == $.BROWSERS.CHROME && BROWSER_VERSION >= 2 ) || ( BROWSER == $.BROWSERS.IE && BROWSER_VERSION >= 9 ) - ), + ); - USE_CANVAS = $.supportsCanvas; - -//console.error( 'USE_CANVAS ' + USE_CANVAS ); /** * @class @@ -92,6 +89,7 @@ $.Drawer = function( options ) { //internal state properties viewer: null, + useCanvas: $.supportsCanvas, downloading: 0, tilesMatrix: {}, tilesLoaded: [], @@ -121,13 +119,10 @@ $.Drawer = function( options ) { }, options ); - if ( this.viewer ) { - USE_CANVAS = $.supportsCanvas && this.viewer.useCanvas; - } - + this.useCanvas = $.supportsCanvas && ( this.viewer ? this.viewer.useCanvas : true ); this.container = $.getElement( this.element ); - this.canvas = $.makeNeutralElement( USE_CANVAS ? "canvas" : "div" ); - this.context = USE_CANVAS ? this.canvas.getContext( "2d" ) : null; + this.canvas = $.makeNeutralElement( this.useCanvas ? "canvas" : "div" ); + this.context = this.useCanvas ? this.canvas.getContext( "2d" ) : null; this.normHeight = this.source.dimensions.y / this.source.dimensions.x; this.element = this.container; @@ -406,7 +401,7 @@ $.Drawer.prototype = { }, canRotate: function() { - return USE_CANVAS; + return this.useCanvas; } }; @@ -523,7 +518,7 @@ function updateViewport( drawer ) { //TODO drawer.canvas.innerHTML = ""; - if ( USE_CANVAS ) { + if ( drawer.useCanvas ) { if( drawer.canvas.width != viewportSize.x || drawer.canvas.height != viewportSize.y ){ drawer.canvas.width = viewportSize.x; @@ -1201,7 +1196,7 @@ function drawTiles( drawer, lastDrawn ){ } else { - if ( USE_CANVAS ) { + if ( drawer.useCanvas ) { // TODO do this in a more performant way // specifically, don't save,rotate,restore every time we draw a tile if( drawer.viewport.degrees !== 0 ) { @@ -1264,7 +1259,7 @@ function restoreRotationChanges( tile, canvas, context ){ function drawDebugInfo( drawer, tile, count, i ){ - if ( USE_CANVAS ) { + if ( drawer.useCanvas ) { drawer.context.save(); drawer.context.lineWidth = 2; drawer.context.font = 'small-caps bold 13px ariel'; diff --git a/src/openseadragon.js b/src/openseadragon.js index 67cceab5..3e7c7fd4 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -226,6 +226,9 @@ * @param {Number} [options.maxImageCacheCount=100] * The max number of images we should keep in memory (per drawer). * + * @param {Boolean} [options.useCanvas=true] + * Set to false to not use an HTML canvas element for image rendering even if canvas is supported. + * * @param {Number} [options.minPixelRatio=0.5] * The higher the minPixelRatio, the lower the quality of the image that * is considered sufficient to stop rendering a given zoom level. For @@ -293,6 +296,12 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ toString = Object.prototype.toString, hasOwn = Object.prototype.hasOwnProperty; + // Detects canvas support + function isCanvasSupported() { + var canvasElement = document.createElement( 'canvas' ); + return !!( $.isFunction( canvasElement.getContext ) && + canvasElement.getContext( '2d' ) ); + } /** * Taken from jQuery 1.6.1 @@ -386,6 +395,14 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ }; + /** + * True if the browser supports the HTML5 canvas element + * @name $.supportsCanvas + * @property + */ + $.supportsCanvas = isCanvasSupported(); + + /** * Detect event model and create appropriate _addEvent/_removeEvent methods */ @@ -424,19 +441,6 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ } - /* - * Detect canvas support - */ - var canvasElement = document.createElement( 'canvas' ); - /** - * True if the browser supports the HTML5 canvas element - * @name $.supportsCanvas - * @property - */ - $.supportsCanvas = !!( $.isFunction( canvasElement.getContext ) && - canvasElement.getContext( '2d' ) ); - - }( OpenSeadragon )); /** From 8e325a37482bed4c06ffe80b028a76a4bebc1816 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Mon, 4 Nov 2013 12:41:45 -0800 Subject: [PATCH 28/31] Added preventDefaultAction flag to MouseTracker Added a boolean preventDefaultAction property (default false) to the event object passed to MouseTracker handler methods. Implemented in the following MouseTracker subscribers: * Viewer.keyboardCommandArea.innerTracker.focusHandler: preventDefaultAction == true prevents scrolling viewer into view * Viewer.keyboardCommandArea.innerTracker.keyHandler: preventDefaultAction == true prevents viewer keyboard navigation * Viewer.innerTracker.clickHandler: preventDefaultAction == true prevents viewer zoom on click * Viewer.innerTracker.dragHandler: preventDefaultAction == true prevents viewer panning with mouse/touch * Viewer.innerTracker.scrollHandler: preventDefaultAction == true prevents viewer zooming on mousewheel/pinch --- changelog.txt | 6 ++ src/mousetracker.js | 168 +++++++++++++++++++++++++++----------------- src/viewer.js | 104 ++++++++++++++------------- 3 files changed, 162 insertions(+), 116 deletions(-) diff --git a/changelog.txt b/changelog.txt index 0b52e2b6..14d090d5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -37,6 +37,12 @@ OPENSEADRAGON CHANGELOG * Fixed: IE 10 not reading DZI file correctly in certain circumstances (#218) * Added support for the 'wheel' DOM mousewheel event (#261) * Fix for non-canvas tile rendering at large size (#264) +* Added a boolean preventDefaultAction property (default false) to the event object passed to MouseTracker handler methods. Implemented in the following MouseTracker subscribers: + * Viewer.keyboardCommandArea.innerTracker.focusHandler: preventDefaultAction == true prevents scrolling viewer into view + * Viewer.keyboardCommandArea.innerTracker.keyHandler: preventDefaultAction == true prevents viewer keyboard navigation + * Viewer.innerTracker.clickHandler: preventDefaultAction == true prevents viewer zoom on click + * Viewer.innerTracker.dragHandler: preventDefaultAction == true prevents viewer panning with mouse/touch + * Viewer.innerTracker.scrollHandler: preventDefaultAction == true prevents viewer zooming on mousewheel/pinch 0.9.131: diff --git a/src/mousetracker.js b/src/mousetracker.js index a7798b97..c2a7d446 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -243,6 +243,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -266,6 +268,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -284,6 +288,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -307,6 +313,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -325,6 +333,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -347,6 +357,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -369,6 +381,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -391,6 +405,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -409,6 +425,8 @@ * True if the original event is a touch event, otherwise false. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -427,6 +445,8 @@ * True if the shift key was pressed during this event. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -441,6 +461,8 @@ * A reference to the tracker instance. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -455,6 +477,8 @@ * A reference to the tracker instance. * @param {Object} event.originalEvent * The original event object. + * @param {Boolean} [event.preventDefaultAction=false] + * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). * @param {Object} event.userData * Arbitrary user-defined object. */ @@ -673,9 +697,10 @@ if ( tracker.focusHandler ) { propagate = tracker.focusHandler( { - eventSource: tracker, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -695,9 +720,10 @@ if ( tracker.blurHandler ) { propagate = tracker.blurHandler( { - eventSource: tracker, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -717,12 +743,13 @@ if ( tracker.keyHandler ) { propagate = tracker.keyHandler( { - eventSource: tracker, - position: getMouseRelative( event, tracker.element ), - keyCode: event.keyCode ? event.keyCode : event.charCode, - shift: event.shiftKey, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( event, tracker.element ), + keyCode: event.keyCode ? event.keyCode : event.charCode, + shift: event.shiftKey, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( !propagate ) { @@ -772,13 +799,14 @@ if ( tracker.enterHandler ) { propagate = tracker.enterHandler( { - eventSource: tracker, - position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), + eventSource: tracker, + position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), insideElementPressed: delegate.insideElementPressed, - buttonDownAny: IS_BUTTON_DOWN, - isTouchEvent: isTouch, - originalEvent: event, - userData: tracker.userData + buttonDownAny: IS_BUTTON_DOWN, + isTouchEvent: isTouch, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -828,13 +856,14 @@ if ( tracker.exitHandler ) { propagate = tracker.exitHandler( { - eventSource: tracker, - position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), + eventSource: tracker, + position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), insideElementPressed: delegate.insideElementPressed, - buttonDownAny: IS_BUTTON_DOWN, - isTouchEvent: isTouch, - originalEvent: event, - userData: tracker.userData + buttonDownAny: IS_BUTTON_DOWN, + isTouchEvent: isTouch, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); @@ -872,11 +901,12 @@ if ( tracker.pressHandler ) { propagate = tracker.pressHandler( { - eventSource: tracker, - position: getMouseRelative( eventOrTouchPoint, tracker.element ), - isTouchEvent: isTouch, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( eventOrTouchPoint, tracker.element ), + isTouchEvent: isTouch, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -967,13 +997,14 @@ if ( tracker.releaseHandler ) { propagate = tracker.releaseHandler( { - eventSource: tracker, - position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), - insideElementPressed: insideElementPressed, + eventSource: tracker, + position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), + insideElementPressed: insideElementPressed, insideElementReleased: insideElementReleased, - isTouchEvent: isTouch, - originalEvent: event, - userData: tracker.userData + isTouchEvent: isTouch, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -1085,11 +1116,12 @@ var propagate = tracker.moveHandler( { - eventSource: tracker, - position: getMouseRelative( event, tracker.element ), - isTouchEvent: false, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( event, tracker.element ), + isTouchEvent: false, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -1111,11 +1143,12 @@ function onMouseStop( tracker, originalMoveEvent ) { if ( tracker.stopHandler ) { tracker.stopHandler( { - eventSource: tracker, - position: getMouseRelative( originalMoveEvent, tracker.element ), - isTouchEvent: false, - originalEvent: originalMoveEvent, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( originalMoveEvent, tracker.element ), + isTouchEvent: false, + originalEvent: originalMoveEvent, + preventDefaultAction: false, + userData: tracker.userData } ); } } @@ -1200,13 +1233,14 @@ if ( tracker.scrollHandler ) { propagate = tracker.scrollHandler( { - eventSource: tracker, - position: getMouseRelative( event, tracker.element ), - scroll: nDelta, - shift: event.shiftKey, - isTouchEvent: isTouch, - originalEvent: originalEvent, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( event, tracker.element ), + scroll: nDelta, + shift: event.shiftKey, + isTouchEvent: isTouch, + originalEvent: originalEvent, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -1243,13 +1277,14 @@ if ( tracker.clickHandler ) { propagate = tracker.clickHandler( { - eventSource: tracker, - position: getMouseRelative( eventOrTouchPoint, tracker.element ), - quick: quick, - shift: event.shiftKey, - isTouchEvent: isTouch, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( eventOrTouchPoint, tracker.element ), + quick: quick, + shift: event.shiftKey, + isTouchEvent: isTouch, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { @@ -1281,13 +1316,14 @@ if ( tracker.dragHandler ) { propagate = tracker.dragHandler( { - eventSource: tracker, - position: getMouseRelative( eventOrTouchPoint, tracker.element ), - delta: delta, - shift: event.shiftKey, - isTouchEvent: isTouch, - originalEvent: event, - userData: tracker.userData + eventSource: tracker, + position: getMouseRelative( eventOrTouchPoint, tracker.element ), + delta: delta, + shift: event.shiftKey, + isTouchEvent: isTouch, + originalEvent: event, + preventDefaultAction: false, + userData: tracker.userData } ); if ( propagate === false ) { diff --git a/src/viewer.js b/src/viewer.js index d12c007f..9133afbb 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -276,58 +276,62 @@ $.Viewer = function( options ) { this.keyboardCommandArea.innerTracker = new $.MouseTracker({ _this : this, element: this.keyboardCommandArea, - focusHandler: function(){ - var point = $.getElementPosition( this.element ); - window.scrollTo( 0, point.y ); + focusHandler: function( event ){ + if ( !event.preventDefaultAction ) { + var point = $.getElementPosition( this.element ); + window.scrollTo( 0, point.y ); + } }, keyHandler: function( event ){ - switch( event.keyCode ){ - case 61://=|+ - _this.viewport.zoomBy(1.1); - _this.viewport.applyConstraints(); - return false; - case 45://-|_ - _this.viewport.zoomBy(0.9); - _this.viewport.applyConstraints(); - return false; - case 48://0|) - _this.viewport.goHome(); - _this.viewport.applyConstraints(); - return false; - case 119://w - case 87://W - case 38://up arrow - if ( event.shift ) { + if ( !event.preventDefaultAction ) { + switch( event.keyCode ){ + case 61://=|+ _this.viewport.zoomBy(1.1); - } else { - _this.viewport.panBy(new $.Point(0, -0.05)); - } - _this.viewport.applyConstraints(); - return false; - case 115://s - case 83://S - case 40://down arrow - if ( event.shift ) { + _this.viewport.applyConstraints(); + return false; + case 45://-|_ _this.viewport.zoomBy(0.9); - } else { - _this.viewport.panBy(new $.Point(0, 0.05)); - } - _this.viewport.applyConstraints(); - return false; - case 97://a - case 37://left arrow - _this.viewport.panBy(new $.Point(-0.05, 0)); - _this.viewport.applyConstraints(); - return false; - case 100://d - case 39://right arrow - _this.viewport.panBy(new $.Point(0.05, 0)); - _this.viewport.applyConstraints(); - return false; - default: - //console.log( 'navigator keycode %s', event.keyCode ); - return true; + _this.viewport.applyConstraints(); + return false; + case 48://0|) + _this.viewport.goHome(); + _this.viewport.applyConstraints(); + return false; + case 119://w + case 87://W + case 38://up arrow + if ( event.shift ) { + _this.viewport.zoomBy(1.1); + } else { + _this.viewport.panBy(new $.Point(0, -0.05)); + } + _this.viewport.applyConstraints(); + return false; + case 115://s + case 83://S + case 40://down arrow + if ( event.shift ) { + _this.viewport.zoomBy(0.9); + } else { + _this.viewport.panBy(new $.Point(0, 0.05)); + } + _this.viewport.applyConstraints(); + return false; + case 97://a + case 37://left arrow + _this.viewport.panBy(new $.Point(-0.05, 0)); + _this.viewport.applyConstraints(); + return false; + case 100://d + case 39://right arrow + _this.viewport.panBy(new $.Point(0.05, 0)); + _this.viewport.applyConstraints(); + return false; + default: + //console.log( 'navigator keycode %s', event.keyCode ); + return true; + } } } }).setTracking( true ); // default state @@ -1474,7 +1478,7 @@ function onBlur(){ function onCanvasClick( event ) { var zoomPerClick, factor; - if ( this.viewport && event.quick ) { // ignore clicks where mouse moved + if ( !event.preventDefaultAction && this.viewport && event.quick ) { // ignore clicks where mouse moved zoomPerClick = this.zoomPerClick; factor = event.shift ? 1.0 / zoomPerClick : zoomPerClick; this.viewport.zoomBy( @@ -1493,7 +1497,7 @@ function onCanvasClick( event ) { } function onCanvasDrag( event ) { - if ( this.viewport ) { + if ( !event.preventDefaultAction && this.viewport ) { if( !this.panHorizontal ){ event.delta.x = 0; } @@ -1533,7 +1537,7 @@ function onCanvasRelease( event ) { function onCanvasScroll( event ) { var factor; - if ( this.viewport ) { + if ( !event.preventDefaultAction && this.viewport ) { factor = Math.pow( this.zoomPerScroll, event.scroll ); this.viewport.zoomBy( factor, From 5c4131303a166aaf96b0c63fabc9a69478d99393 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Thu, 7 Nov 2013 11:48:01 -0800 Subject: [PATCH 29/31] Use canvas when available - Fixes Removed redundant useCanvas property from drawer --- src/drawer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/drawer.js b/src/drawer.js index 696bb193..5a049469 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -89,7 +89,6 @@ $.Drawer = function( options ) { //internal state properties viewer: null, - useCanvas: $.supportsCanvas, downloading: 0, tilesMatrix: {}, tilesLoaded: [], From 626f27771f85b6bbffeb2d29cb76211d3c8bbde2 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 8 Nov 2013 08:24:44 -0800 Subject: [PATCH 30/31] MouseTracker preventDefaultAction Unit Tests --- test/events.js | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/test/events.js b/test/events.js index f2f3018c..6fb7f23c 100644 --- a/test/events.js +++ b/test/events.js @@ -212,4 +212,72 @@ viewer.open( '/test/data/testpattern.dzi' ); } ); + // ---------- + asyncTest( 'MouseTracker preventDefaultAction', function () { + var $canvas = $( viewer.element ).find( '.openseadragon-canvas' ).not( '.navigator .openseadragon-canvas' ), + tracker = viewer.innerTracker, + origClickHandler, + origDragHandler, + dragCount = 10, + originalZoom = 0, + originalBounds = null; + + var onOpen = function ( event ) { + viewer.removeHandler( 'open', onOpen ); + + // Hook viewer events to set preventDefaultAction + origClickHandler = tracker.clickHandler; + tracker.clickHandler = function ( event ) { + event.preventDefaultAction = true; + return origClickHandler( event ); + }; + origDragHandler = tracker.dragHandler; + tracker.dragHandler = function ( event ) { + event.preventDefaultAction = true; + return origDragHandler( event ); + }; + + originalZoom = viewer.viewport.getZoom(); + originalBounds = viewer.viewport.getBounds(); + + var event = { + clientX:1, + clientY:1 + }; + + $canvas.simulate( 'focus', event ); + // Drag to pan + Util.simulateViewerClickWithDrag( { + viewer: viewer, + widthFactor: 0.25, + heightFactor: 0.25, + dragCount: dragCount, + dragDx: 1, + dragDy: 1 + } ); + // Click to zoom + Util.simulateViewerClickWithDrag( { + viewer: viewer, + widthFactor: 0.25, + heightFactor: 0.25, + dragCount: 0, + dragDx: 0, + dragDy: 0 + } ); + $canvas.simulate( 'blur', event ); + + var zoom = viewer.viewport.getZoom(), + bounds = viewer.viewport.getBounds(); + + equal( zoom, originalZoom, "Zoom prevented" ); + ok( bounds.x == originalBounds.x && bounds.y == originalBounds.y, 'Pan prevented' ); + + viewer.close(); + start(); + }; + + viewer.addHandler( 'open', onOpen ); + viewer.open( '/test/data/testpattern.dzi' ); + } ); + } )(); From 20d8f09011fd85bb13af09944f07568a67281154 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Fri, 8 Nov 2013 10:09:09 -0800 Subject: [PATCH 31/31] Changelog updates --- changelog.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index b8921cbd..7a03311c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -31,14 +31,14 @@ OPENSEADRAGON CHANGELOG * Added a number of easier coordinate conversion methods to viewport (#243) * Added the ability to create a viewer and start at a specified page (#252) * Fixed image resolve issue with collection mode (#255) -* DOM events are now passed through as 'event.originalEvent' in viewer and button events where appropriate. Affects the following events: +* DOM events are now passed through as 'event.originalEvent' in viewer and button events where appropriate. (#257) Affects the following events: * Viewer: 'canvas-release', 'canvas-click', 'canvas-drag', 'canvas-scroll', 'container-enter', 'container-exit', 'container-release' * Button: 'enter', 'exit', 'press', 'release', 'focus', 'blur', 'click' * Fixed: IE 10 not reading DZI file correctly in certain circumstances (#218) * Added support for the 'wheel' DOM mousewheel event (#261) * Fix for non-canvas tile rendering at large size (#264) * Drawer now uses an HTML5 canvas element whenever it's available. Can be overridden with the Viewer.useCanvas option (#191) -* Added a boolean preventDefaultAction property (default false) to the event object passed to MouseTracker handler methods. Implemented in the following MouseTracker subscribers: +* Added a boolean preventDefaultAction property (default false) to the event object passed to MouseTracker handler methods. (#270) Implemented in the following MouseTracker subscribers: * Viewer.keyboardCommandArea.innerTracker.focusHandler: preventDefaultAction == true prevents scrolling viewer into view * Viewer.keyboardCommandArea.innerTracker.keyHandler: preventDefaultAction == true prevents viewer keyboard navigation * Viewer.innerTracker.clickHandler: preventDefaultAction == true prevents viewer zoom on click