From 47ae09467576f23b72292ba64694a9a4a36b221d Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Tue, 15 Apr 2014 12:55:32 -0400 Subject: [PATCH 01/10] Fix ajax call for file: and ftp: #73 --- src/openseadragon.js | 22 ++++++++++++++++++++-- test/basic.js | 2 +- test/utils.js | 24 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/openseadragon.js b/src/openseadragon.js index 3be339af..8b8c6a14 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -1725,6 +1725,21 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ return value ? value : null; }, + /** + * Retrieves the protocol used by the url. The url can either be absolute + * or relative. + * @function + * @param {String} url The url to retrieve the protocol from. + * @return {String} The protocol (http:, https:, file:, ftp: ...) + */ + getUrlProtocol: function( url ) { + var match = url.match(/^([a-z]+:)\/\//i); + if ( match === null ) { + // Relative URL, retrive the protocol from window.location + return window.location.protocol; + } + return match[1].toLowerCase(); + }, createAjaxRequest: function(){ var request; @@ -1778,10 +1793,13 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ if ( request.readyState == 4 ) { request.onreadystatechange = function(){}; - if ( request.status == 200 ) { + var protocol = $.getUrlProtocol( url ); + var successStatus = + protocol === "http:" || protocol === "https:" ? 200 : 0; + if ( request.status === successStatus ) { onSuccess( request ); } else { - $.console.log( "AJAX request returned %s: %s", request.status, url ); + $.console.log( "AJAX request returned %d: %s", request.status, url ); if ( $.isFunction( onError ) ) { onError( request ); diff --git a/test/basic.js b/test/basic.js index 946a8ff3..969f492f 100644 --- a/test/basic.js +++ b/test/basic.js @@ -56,7 +56,7 @@ equal($(".openseadragon-message").length, 1, "Open failures should display a message"); - ok(testLog.log.contains('["AJAX request returned %s: %s",404,"/test/data/not-a-real-file"]'), + ok(testLog.log.contains('["AJAX request returned %d: %s",404,"/test/data/not-a-real-file"]'), "AJAX failures should be logged to the console"); start(); diff --git a/test/utils.js b/test/utils.js index f46f9a84..92538375 100644 --- a/test/utils.js +++ b/test/utils.js @@ -87,6 +87,30 @@ ); }); + test("getUrlProtocol", function() { + + equal(OpenSeadragon.getUrlProtocol("test"), window.location.protocol, + "'test' url protocol should be window.location.protocol"); + + equal(OpenSeadragon.getUrlProtocol("/test"), window.location.protocol, + "'/test' url protocol should be window.location.protocol"); + + equal(OpenSeadragon.getUrlProtocol("//test"), window.location.protocol, + "'//test' url protocol should be window.location.protocol"); + + equal(OpenSeadragon.getUrlProtocol("http://test"), "http:", + "'http://test' url protocol should be http:"); + + equal(OpenSeadragon.getUrlProtocol("https://test"), "https:", + "'https://test' url protocol should be https:"); + + equal(OpenSeadragon.getUrlProtocol("file://test"), "file:", + "'file://test' url protocol should be file:"); + + equal(OpenSeadragon.getUrlProtocol("FTP://test"), "ftp:", + "'FTP://test' url protocol should be ftp:"); + }); + // ---------- asyncTest("requestAnimationFrame", function() { var timeWatcher = Util.timeWatcher(); From 3b4dca329db2480b1f7b09069a449d8eaa8453ec Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Thu, 17 Apr 2014 16:13:26 -0400 Subject: [PATCH 02/10] Use ActiveX on IE when requesting a file: URL with ajax. --- src/openseadragon.js | 54 ++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/openseadragon.js b/src/openseadragon.js index 8b8c6a14..b74bdb9e 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -1741,35 +1741,35 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ return match[1].toLowerCase(); }, - createAjaxRequest: function(){ - var request; - - if ( window.XMLHttpRequest ) { - $.createAjaxRequest = function( ){ + /** + * Create an XHR object + * @param {type} [local] If set to true, the XHR will be file: protocol + * compatible if possible (but may raise a warning in the browser). + * @returns {XMLHttpRequest} + */ + createAjaxRequest: function( local ) { + if ( window.ActiveXObject ) { + if ( window.XMLHttpRequest ) { + $.createAjaxRequest = function( local ) { + if ( local ) { + /* global ActiveXObject:true */ + return new ActiveXObject( "Microsoft.XMLHTTP" ); + } + return new XMLHttpRequest(); + }; + } else { + $.createAjaxRequest = function() { + return new ActiveXObject( "Microsoft.XMLHTTP" ); + }; + } + } else if ( window.XMLHttpRequest ) { + $.createAjaxRequest = function() { return new XMLHttpRequest(); }; - request = new XMLHttpRequest(); - } else if ( window.ActiveXObject ) { - /*jshint loopfunc:true*/ - /* global ActiveXObject:true */ - for ( var i = 0; i < ACTIVEX.length; i++ ) { - try { - request = new ActiveXObject( ACTIVEX[ i ] ); - $.createAjaxRequest = function( ){ - return new ActiveXObject( ACTIVEX[ i ] ); - }; - break; - } catch (e) { - continue; - } - } - } - - if ( !request ) { + } else { throw new Error( "Browser doesn't support XMLHttpRequest." ); } - - return request; + return $.createAjaxRequest( local ); }, @@ -1782,7 +1782,8 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ * @throws {Error} */ makeAjaxRequest: function( url, onSuccess, onError ) { - var request = $.createAjaxRequest(); + var protocol = $.getUrlProtocol( url ); + var request = $.createAjaxRequest( protocol === "file:" ); if ( !$.isFunction( onSuccess ) ) { throw new Error( "makeAjaxRequest requires a success callback" ); @@ -1793,7 +1794,6 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ if ( request.readyState == 4 ) { request.onreadystatechange = function(){}; - var protocol = $.getUrlProtocol( url ); var successStatus = protocol === "http:" || protocol === "https:" ? 200 : 0; if ( request.status === successStatus ) { From 116cf7449f64c60a4bee267ad3d152dc61f03983 Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Thu, 17 Apr 2014 17:20:04 -0400 Subject: [PATCH 03/10] Test if activex is available by trying to create one for ie11 compatibility. --- src/openseadragon.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/openseadragon.js b/src/openseadragon.js index b74bdb9e..8e0168ac 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -1748,11 +1748,21 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ * @returns {XMLHttpRequest} */ createAjaxRequest: function( local ) { - if ( window.ActiveXObject ) { + // IE11 does not support window.ActiveXObject so we just try to + // create one to see if it is supported. + // See: http://msdn.microsoft.com/en-us/library/ie/dn423948%28v=vs.85%29.aspx + var supportActiveX; + try { + /* global ActiveXObject:true */ + supportActiveX = !!new ActiveXObject( "Microsoft.XMLHTTP" ); + } catch( e ) { + supportActiveX = false; + } + + if ( supportActiveX ) { if ( window.XMLHttpRequest ) { $.createAjaxRequest = function( local ) { if ( local ) { - /* global ActiveXObject:true */ return new ActiveXObject( "Microsoft.XMLHTTP" ); } return new XMLHttpRequest(); @@ -2001,12 +2011,7 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ }; - var ACTIVEX = [ - "Msxml2.XMLHTTP", - "Msxml3.XMLHTTP", - "Microsoft.XMLHTTP" - ], - FILEFORMATS = { + var FILEFORMATS = { "bmp": false, "jpeg": true, "jpg": true, From 6a24af3743a01a4407debf9f6f0533c1806cfd0a Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Fri, 18 Apr 2014 16:59:47 -0400 Subject: [PATCH 04/10] Add @private to internal methods. --- src/openseadragon.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/openseadragon.js b/src/openseadragon.js index 8e0168ac..289652b6 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -1729,6 +1729,7 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ * Retrieves the protocol used by the url. The url can either be absolute * or relative. * @function + * @private * @param {String} url The url to retrieve the protocol from. * @return {String} The protocol (http:, https:, file:, ftp: ...) */ @@ -1743,6 +1744,7 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ /** * Create an XHR object + * @private * @param {type} [local] If set to true, the XHR will be file: protocol * compatible if possible (but may raise a warning in the browser). * @returns {XMLHttpRequest} @@ -1782,7 +1784,6 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ return $.createAjaxRequest( local ); }, - /** * Makes an AJAX request. * @function From 5860167d65ea4e5a9c2e4321565c2ea2c631c64c Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Sun, 20 Apr 2014 18:19:32 -0700 Subject: [PATCH 05/10] MouseTracker Touch Fixes - Flick Defaults and Bubbling Flick gesture settings defaults set to better values. Removed touch event model bubble cancelling so viewer controls show on touch contact. --- src/mousetracker.js | 3 --- src/openseadragon.js | 24 ++++++++++++------------ 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/mousetracker.js b/src/mousetracker.js index 4405e93e..ddca3dfb 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -1627,7 +1627,6 @@ // Touch event model start, end, and move events are always captured so we don't need to capture explicitly } - $.stopEvent( event ); $.cancelEvent( event ); } @@ -1663,7 +1662,6 @@ updatePointersExit( tracker, event, gPoints ); } - $.stopEvent( event ); $.cancelEvent( event ); } @@ -1689,7 +1687,6 @@ updatePointersMove( tracker, event, gPoints ); - $.stopEvent( event ); $.cancelEvent( event ); } diff --git a/src/openseadragon.js b/src/openseadragon.js index c7f69749..ccf4e630 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -286,8 +286,8 @@ * @property {Boolean} [gestureSettingsMouse.clickToZoom=true] - Zoom on click gesture * @property {Boolean} [gestureSettingsMouse.pinchToZoom=false] - Zoom on pinch gesture * @property {Boolean} [gestureSettingsMouse.flickEnabled=false] - Enable flick gesture - * @property {Number} [gestureSettingsMouse.flickMinSpeed=20] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second) - * @property {Number} [gestureSettingsMouse.flickMomentum=0.40] - If flickEnabled is true, the momentum factor for the flick gesture + * @property {Number} [gestureSettingsMouse.flickMinSpeed=120] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second) + * @property {Number} [gestureSettingsMouse.flickMomentum=0.25] - If flickEnabled is true, the momentum factor for the flick gesture * * @property {OpenSeadragon.GestureSettings} [gestureSettingsTouch] * Settings for gestures generated by a touch pointer device. (See {@link OpenSeadragon.GestureSettings}) @@ -295,8 +295,8 @@ * @property {Boolean} [gestureSettingsTouch.clickToZoom=false] - Zoom on click gesture * @property {Boolean} [gestureSettingsTouch.pinchToZoom=true] - Zoom on pinch gesture * @property {Boolean} [gestureSettingsTouch.flickEnabled=true] - Enable flick gesture - * @property {Number} [gestureSettingsTouch.flickMinSpeed=20] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second) - * @property {Number} [gestureSettingsTouch.flickMomentum=0.40] - If flickEnabled is true, the momentum factor for the flick gesture + * @property {Number} [gestureSettingsTouch.flickMinSpeed=120] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second) + * @property {Number} [gestureSettingsTouch.flickMomentum=0.25] - If flickEnabled is true, the momentum factor for the flick gesture * * @property {OpenSeadragon.GestureSettings} [gestureSettingsPen] * Settings for gestures generated by a pen pointer device. (See {@link OpenSeadragon.GestureSettings}) @@ -304,8 +304,8 @@ * @property {Boolean} [gestureSettingsPen.clickToZoom=true] - Zoom on click gesture * @property {Boolean} [gestureSettingsPen.pinchToZoom=false] - Zoom on pinch gesture * @property {Boolean} [gestureSettingsPen.flickEnabled=false] - Enable flick gesture - * @property {Number} [gestureSettingsPen.flickMinSpeed=20] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second) - * @property {Number} [gestureSettingsPen.flickMomentum=0.40] - If flickEnabled is true, the momentum factor for the flick gesture + * @property {Number} [gestureSettingsPen.flickMinSpeed=120] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second) + * @property {Number} [gestureSettingsPen.flickMomentum=0.25] - If flickEnabled is true, the momentum factor for the flick gesture * * @property {OpenSeadragon.GestureSettings} [gestureSettingsUnknown] * Settings for gestures generated by unknown pointer devices. (See {@link OpenSeadragon.GestureSettings}) @@ -313,8 +313,8 @@ * @property {Boolean} [gestureSettingsUnknown.clickToZoom=false] - Zoom on click gesture * @property {Boolean} [gestureSettingsUnknown.pinchToZoom=true] - Zoom on pinch gesture * @property {Boolean} [gestureSettingsUnknown.flickEnabled=true] - Enable flick gesture - * @property {Number} [gestureSettingsUnknown.flickMinSpeed=20] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second) - * @property {Number} [gestureSettingsUnknown.flickMomentum=0.40] - If flickEnabled is true, the momentum factor for the flick gesture + * @property {Number} [gestureSettingsUnknown.flickMinSpeed=120] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second) + * @property {Number} [gestureSettingsUnknown.flickMomentum=0.25] - If flickEnabled is true, the momentum factor for the flick gesture * * @property {Number} [zoomPerClick=2.0] * The "zoom distance" per mouse click or touch tap. Note: Setting this to 1.0 effectively disables the click-to-zoom feature (also see gestureSettings[Mouse|Touch|Pen].clickToZoom). @@ -893,10 +893,10 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ clickDistThreshold: 5, springStiffness: 5.0, animationTime: 1.2, - gestureSettingsMouse: { scrollToZoom: true, clickToZoom: true, pinchToZoom: false, flickEnabled: false, flickMinSpeed: 20, flickMomentum: 0.40 }, - gestureSettingsTouch: { scrollToZoom: false, clickToZoom: false, pinchToZoom: true, flickEnabled: true, flickMinSpeed: 20, flickMomentum: 0.40 }, - gestureSettingsPen: { scrollToZoom: false, clickToZoom: true, pinchToZoom: false, flickEnabled: false, flickMinSpeed: 20, flickMomentum: 0.40 }, - gestureSettingsUnknown: { scrollToZoom: false, clickToZoom: false, pinchToZoom: true, flickEnabled: true, flickMinSpeed: 20, flickMomentum: 0.40 }, + gestureSettingsMouse: { scrollToZoom: true, clickToZoom: true, pinchToZoom: false, flickEnabled: false, flickMinSpeed: 120, flickMomentum: 0.25 }, + gestureSettingsTouch: { scrollToZoom: false, clickToZoom: false, pinchToZoom: true, flickEnabled: true, flickMinSpeed: 120, flickMomentum: 0.25 }, + gestureSettingsPen: { scrollToZoom: false, clickToZoom: true, pinchToZoom: false, flickEnabled: false, flickMinSpeed: 120, flickMomentum: 0.25 }, + gestureSettingsUnknown: { scrollToZoom: false, clickToZoom: false, pinchToZoom: true, flickEnabled: true, flickMinSpeed: 120, flickMomentum: 0.25 }, zoomPerClick: 2, zoomPerScroll: 1.2, zoomPerSecond: 1.0, From 765df51bd3235f01c7f42a3ca30689de96a994b7 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Sun, 20 Apr 2014 21:25:29 -0700 Subject: [PATCH 06/10] Stiffened the spring --- src/openseadragon.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openseadragon.js b/src/openseadragon.js index ccf4e630..289201ff 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -274,7 +274,7 @@ * If a mouse or touch drag occurs and the distance to the starting drag * point is less than this many pixels, ignore the drag event. * - * @property {Number} [springStiffness=5.0] + * @property {Number} [springStiffness=6.5] * * @property {Number} [animationTime=1.2] * Specifies the animation duration per each {@link OpenSeadragon.Spring} @@ -891,7 +891,7 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ //UI RESPONSIVENESS AND FEEL clickTimeThreshold: 300, clickDistThreshold: 5, - springStiffness: 5.0, + springStiffness: 6.5, animationTime: 1.2, gestureSettingsMouse: { scrollToZoom: true, clickToZoom: true, pinchToZoom: false, flickEnabled: false, flickMinSpeed: 120, flickMomentum: 0.25 }, gestureSettingsTouch: { scrollToZoom: false, clickToZoom: false, pinchToZoom: true, flickEnabled: true, flickMinSpeed: 120, flickMomentum: 0.25 }, From e7ca7b1e95385988272cbe5db393f32ca56e1636 Mon Sep 17 00:00:00 2001 From: Antoine Vandecreme Date: Mon, 21 Apr 2014 09:23:17 -0400 Subject: [PATCH 07/10] Prefer DOMParser over ActiveX when both are availables. --- src/openseadragon.js | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/openseadragon.js b/src/openseadragon.js index 289652b6..628d128d 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -1947,23 +1947,9 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ * @returns {Document} */ parseXml: function( string ) { - //TODO: yet another example where we can determine the correct - // implementation once at start-up instead of everytime we use - // the function. DONE. - if ( window.ActiveXObject ) { + if ( window.DOMParser ) { - $.parseXml = function( string ){ - var xmlDoc = null; - - xmlDoc = new ActiveXObject( "Microsoft.XMLDOM" ); - xmlDoc.async = false; - xmlDoc.loadXML( string ); - return xmlDoc; - }; - - } else if ( window.DOMParser ) { - - $.parseXml = function( string ){ + $.parseXml = function( string ) { var xmlDoc = null, parser; @@ -1972,6 +1958,17 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ return xmlDoc; }; + } else if ( window.ActiveXObject ) { + + $.parseXml = function( string ) { + var xmlDoc = null; + + xmlDoc = new ActiveXObject( "Microsoft.XMLDOM" ); + xmlDoc.async = false; + xmlDoc.loadXML( string ); + return xmlDoc; + }; + } else { throw new Error( "Browser doesn't support XML DOM." ); } From d9dfd0a435ea93e3e01b76fac4e0f36c06a60fb8 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Wed, 23 Apr 2014 08:07:48 -0700 Subject: [PATCH 08/10] iOS touch enter/exit fix --- src/viewer.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/viewer.js b/src/viewer.js index bd01afe3..6bd8dad3 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -402,6 +402,7 @@ $.Viewer = function( options ) { clickDistThreshold: this.clickDistThreshold, enterHandler: $.delegate( this, onContainerEnter ), exitHandler: $.delegate( this, onContainerExit ), + pressHandler: $.delegate( this, onContainerPress ), releaseHandler: $.delegate( this, onContainerRelease ) }).setTracking( this.mouseNavEnabled ? true : false ); // always tracking @@ -2498,8 +2499,15 @@ function onContainerExit( event ) { }); } +function onContainerPress( event ) { + if ( event.pointerType === 'touch' && !$.MouseTracker.haveTouchEnter ) { + THIS[ this.hash ].mouseInside = true; + abortControlsAutoHide( this ); + } +} + function onContainerRelease( event ) { - if ( !event.insideElementReleased ) { + if ( !event.insideElementReleased || ( event.pointerType === 'touch' && !$.MouseTracker.haveTouchEnter ) ) { THIS[ this.hash ].mouseInside = false; if ( !THIS[ this.hash ].animating ) { beginControlsAutoHide( this ); From bd52f387883c0305c52f8aa4400273117db9bcd7 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Wed, 23 Apr 2014 08:38:55 -0700 Subject: [PATCH 09/10] iOS touch enter/exit fix for BUttonGroup --- src/buttongroup.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/buttongroup.js b/src/buttongroup.js index b8e92119..a05e9084 100644 --- a/src/buttongroup.js +++ b/src/buttongroup.js @@ -103,9 +103,17 @@ $.ButtonGroup = function( options ) { } } }, + pressHandler: function ( event ) { + if ( event.pointerType === 'touch' && !$.MouseTracker.haveTouchEnter ) { + var i; + for ( i = 0; i < _this.buttons.length; i++ ) { + _this.buttons[ i ].notifyGroupEnter(); + } + } + }, releaseHandler: function ( event ) { var i; - if ( !event.insideElementReleased ) { + if ( !event.insideElementReleased || ( event.pointerType === 'touch' && !$.MouseTracker.haveTouchEnter ) ) { for ( i = 0; i < _this.buttons.length; i++ ) { _this.buttons[ i ].notifyGroupExit(); } From 7a8a7b2221e61764846cd8c32801aedcbabc69ee Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Thu, 24 Apr 2014 10:06:03 -0700 Subject: [PATCH 10/10] Changelog for #379 --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index 3206e6f7..9da3552e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -48,6 +48,7 @@ OPENSEADRAGON CHANGELOG * Added a GestureSettings class for per-device gesture options. Currently has settings to enable/disable zoom-on-scroll, zoom-on-pinch, zoom-on-click, and flick gesture settings. * Added GestureSettings objects for mouse, touch, and pen devices to the Viewer options giving users the ability to customize gesture handling in the viewer * Added velocity (speed and direction) properties to the "canvas-drag" event +* Made it possible to run OpenSeadragon from local filesystem on some browsers (#379) 1.0.0: