diff --git a/src/iipmooviewer-2.0.js b/src/iipmooviewer-2.0.js index 6a566e3..7d22888 100644 --- a/src/iipmooviewer-2.0.js +++ b/src/iipmooviewer-2.0.js @@ -169,6 +169,9 @@ var IIPMooViewer = new Class({ // Set up our protocol handler switch( options.protocol ){ + case 'openslide_deepzoom': + this.protocol = new Protocols.OpenSlide_DeepZoom(); + break; case 'zoomify': this.protocol = new Protocols.Zoomify(); break; @@ -486,28 +489,34 @@ var IIPMooViewer = new Class({ this.nudge(-d,0); if( IIPMooViewer.sync ) IIPMooViewer.windows(this).invoke( 'nudge', -d, 0 ); event.preventDefault(); // Prevent default only for navigational keys + this.fireEvent('viewUpdated'); break; case 38: // up this.nudge(0,-d); if( IIPMooViewer.sync ) IIPMooViewer.windows(this).invoke( 'nudge', 0, -d ); event.preventDefault(); + this.fireEvent('viewUpdated'); break; case 39: // right this.nudge(d,0); if( IIPMooViewer.sync ) IIPMooViewer.windows(this).invoke( 'nudge', d, 0 ); event.preventDefault(); + this.fireEvent('viewUpdated'); break; case 40: // down this.nudge(0,d); if( IIPMooViewer.sync ) IIPMooViewer.windows(this).invoke( 'nudge', 0, d ); event.preventDefault(); + this.fireEvent('viewUpdated'); break; case 107: // plus if(!e.control){ this.zoomIn(); if( IIPMooViewer.sync ) IIPMooViewer.windows(this).invoke('zoomIn'); event.preventDefault(); + this.fireEvent('viewUpdated'); } + this.fireEvent('viewUpdated'); break; case 109: // minus case 189: // minus @@ -515,7 +524,9 @@ var IIPMooViewer = new Class({ this.zoomOut(); if( IIPMooViewer.sync ) IIPMooViewer.windows(this).invoke('zoomOut'); event.preventDefault(); + this.fireEvent('viewUpdated'); } + this.fireEvent('viewUpdated'); break; case 72: // h if( this.navOptions&&this.navOptions.id ) break; @@ -673,6 +684,8 @@ var IIPMooViewer = new Class({ } if(IIPMooViewer.sync) IIPMooViewer.windows(this).invoke( 'moveTo', xmove, ymove ); + this.fireEvent('viewUpdated'); + }, @@ -712,6 +725,7 @@ var IIPMooViewer = new Class({ this.moveTo( xmove, ymove ); if( IIPMooViewer.sync ) IIPMooViewer.windows(this).invoke( 'moveTo', xmove, ymove ); + this.fireEvent('viewUpdated'); }, @@ -887,6 +901,8 @@ var IIPMooViewer = new Class({ else IIPMooViewer.windows(this).invoke('zoomIn'); } + this.fireEvent('viewUpdated'); + }, @@ -1254,14 +1270,17 @@ var IIPMooViewer = new Class({ 'zoomIn': function(){ _this.zoomIn(); if( IIPMooViewer.sync ) IIPMooViewer.windows(_this).invoke( 'zoomIn' ); + _this.fireEvent('viewUpdated'); }, 'zoomOut': function(){ _this.zoomOut(); if( IIPMooViewer.sync ) IIPMooViewer.windows(_this).invoke( 'zoomOut' ); + _this.fireEvent('viewUpdated'); }, 'reload': function(){ _this.reload(); if( IIPMooViewer.sync ) IIPMooViewer.windows(_this).invoke( 'reload' ); + _this.fireEvent('viewUpdated'); }, 'scroll': this.scrollNavigation.bind(this), 'zoom': this.zoom.bind(this) @@ -1465,6 +1484,7 @@ var IIPMooViewer = new Class({ if( this.scale ){ this.scale.update( this.wid/this.max_size.w, this.view.w ); this.scale.reflow(this.container); + this.fireEvent('viewUpdated'); } // Update images diff --git a/src/protocols/openslide_deepzoom.js b/src/protocols/openslide_deepzoom.js new file mode 100644 index 0000000..7791c31 --- /dev/null +++ b/src/protocols/openslide_deepzoom.js @@ -0,0 +1,52 @@ +/* DeepZoom Protocol Handler + */ + +Protocols.OpenSlide_DeepZoom = new Class({ + + /* Return metadata URL + */ + getMetaDataURL: function(server,image){ + return server + image; + }, + + /* Return an individual tile request URL + */ + getTileURL: function(t){ + // Strip off the .dzi or .xml suffix from the image name + var prefix = t.image.substr(0,t.image.lastIndexOf(".")); + return t.server+prefix+'_files/'+(t.resolution+1)+'/'+t.x+'_'+t.y+this.suffix; + }, + + /* Parse a Deepzoom protocol metadata request + */ + parseMetaData: function(response){ + this.suffix = "." + ( /Format="(\w+)/.exec(response)[1] ); + var ts = parseInt( /TileSize="(\d+)/.exec(response)[1] ); + var w = parseInt( /Width="(\d+)/.exec(response)[1] ); + var h = parseInt( /Height="(\d+)/.exec(response)[1] ); + // Number of resolutions is the ceiling of Log2(max) + var max = (w>h)? w : h; + var result = { + 'max_size': { w: w, h: h }, + 'tileSize': { w: ts, h: ts }, + 'num_resolutions': Math.ceil( Math.log(max)/Math.LN2 ) + }; + return result; + }, + + /* Return URL for a full view - not possible with Deepzoom + */ + getRegionURL: function(server,image,region,w){ + return null; + }, + + /* Return thumbnail URL + */ + getThumbnailURL: function(server,image,width){ + // Strip off the .dzi or .xml suffix from the image name + var prefix = image.substr(0,image.lastIndexOf(".")); + // this assumes a url for the image which ends in .thumb which returns the thumbnail image + return server+prefix+'.thumb'; + } + +}); diff --git a/src/touch.js b/src/touch.js index 70cbb23..4869db6 100644 --- a/src/touch.js +++ b/src/touch.js @@ -53,6 +53,7 @@ IIPMooViewer.implement({ _this.canvas.eliminate('taptime'); _this.zoomIn(); if(IIPMooViewer.sync) IIPMooViewer.windows(_this).invoke('zoomIn'); + _this.fireEvent('viewUpdated'); } else{ // Record our start position @@ -128,10 +129,12 @@ IIPMooViewer.implement({ if( scale > 0 ){ _this.zoomIn(); if(IIPMooViewer.sync) IIPMooViewer.windows(_this).invoke('zoomIn'); + _this.fireEvent('viewUpdated'); } else if( scale < 0 ){ _this.zoomOut(); if(IIPMooViewer.sync) IIPMooViewer.windows(_this).invoke('zoomOut'); + _this.fireEvent('viewUpdated'); } } @@ -146,6 +149,7 @@ IIPMooViewer.implement({ else r -= 90 % 360; _this.rotate(r); if(IIPMooViewer.sync) IIPMooViewer.windows(_this).invoke( 'rotate', r ); + _this.fireEvent('viewUpdated'); } } @@ -179,6 +183,7 @@ IIPMooViewer.implement({ _this.requestImages(); if( _this.navigation ) _this.navigation.update(_this.view.x/_this.wid,_this.view.y/_this.hei,_this.view.w/_this.wid,_this.view.h/_this.hei); if(IIPMooViewer.sync) IIPMooViewer.windows(_this).invoke( 'moveTo', _this.view.x, _this.view.y ); + _this.fireEvent('viewUpdated'); // This activates hardware acceleration _this.canvas.setStyle( _this.CSSprefix+'transform', 'translateZ(0)' );