2013-05-01 08:46:16 +04:00
|
|
|
/*
|
2013-05-14 08:00:24 +04:00
|
|
|
* OpenSeadragon - Viewer
|
2013-05-01 08:46:16 +04:00
|
|
|
*
|
|
|
|
* Copyright (C) 2009 CodePlex Foundation
|
2013-05-14 07:32:09 +04:00
|
|
|
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
2013-05-01 08:46:16 +04:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
* met:
|
|
|
|
*
|
|
|
|
* - Redistributions of source code must retain the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer.
|
|
|
|
*
|
2013-10-10 02:31:33 +04:00
|
|
|
* - Redistributions in binary form must reproduce the above copyright
|
2013-05-01 08:46:16 +04:00
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* - Neither the name of CodePlex Foundation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived from
|
|
|
|
* this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
|
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2011-12-06 07:50:25 +04:00
|
|
|
(function( $ ){
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2012-02-27 15:56:29 +04:00
|
|
|
// dictionary from hash to private properties
|
2012-03-20 10:44:31 +04:00
|
|
|
var THIS = {},
|
|
|
|
// We keep a list of viewers so we can 'wake-up' each viewer on
|
|
|
|
// a page after toggling between fullpage modes
|
2013-06-19 21:33:25 +04:00
|
|
|
VIEWERS = {};
|
2012-02-27 15:56:29 +04:00
|
|
|
|
2011-12-07 05:26:06 +04:00
|
|
|
/**
|
|
|
|
*
|
2012-02-01 00:59:09 +04:00
|
|
|
* The main point of entry into creating a zoomable image on the page.
|
2011-12-07 05:26:06 +04:00
|
|
|
*
|
2012-02-01 00:59:09 +04:00
|
|
|
* We have provided an idiomatic javascript constructor which takes
|
|
|
|
* a single object, but still support the legacy positional arguments.
|
2011-12-07 05:26:06 +04:00
|
|
|
*
|
2012-02-01 00:59:09 +04:00
|
|
|
* The options below are given in order that they appeared in the constructor
|
|
|
|
* as arguments and we translate a positional call into an idiomatic call.
|
2011-12-07 05:26:06 +04:00
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @class Viewer
|
2013-11-25 20:48:44 +04:00
|
|
|
* @classdesc The main OpenSeadragon viewer class.
|
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @memberof OpenSeadragon
|
2013-09-25 00:36:13 +04:00
|
|
|
* @extends OpenSeadragon.EventSource
|
2012-03-09 20:04:28 +04:00
|
|
|
* @extends OpenSeadragon.ControlDock
|
2013-11-19 23:20:45 +04:00
|
|
|
* @param {OpenSeadragon.Options} options - Viewer options.
|
2011-12-07 05:26:06 +04:00
|
|
|
*
|
2013-06-19 21:33:25 +04:00
|
|
|
**/
|
2011-12-07 05:26:06 +04:00
|
|
|
$.Viewer = function( options ) {
|
|
|
|
|
2012-01-24 17:03:50 +04:00
|
|
|
var args = arguments,
|
2011-12-08 06:10:13 +04:00
|
|
|
_this = this,
|
|
|
|
i;
|
2011-12-07 05:26:06 +04:00
|
|
|
|
2011-12-15 03:22:02 +04:00
|
|
|
|
2013-06-19 21:33:25 +04:00
|
|
|
//backward compatibility for positional args while prefering more
|
2012-03-01 17:38:15 +04:00
|
|
|
//idiomatic javascript options object as the only argument
|
2012-02-28 03:29:00 +04:00
|
|
|
if( !$.isPlainObject( options ) ){
|
2011-12-07 05:26:06 +04:00
|
|
|
options = {
|
|
|
|
id: args[ 0 ],
|
|
|
|
xmlPath: args.length > 1 ? args[ 1 ] : undefined,
|
|
|
|
prefixUrl: args.length > 2 ? args[ 2 ] : undefined,
|
|
|
|
controls: args.length > 3 ? args[ 3 ] : undefined,
|
2014-01-30 01:31:13 +04:00
|
|
|
overlays: args.length > 4 ? args[ 4 ] : undefined
|
2011-12-07 05:26:06 +04:00
|
|
|
};
|
|
|
|
}
|
2012-03-01 17:38:15 +04:00
|
|
|
|
|
|
|
//options.config and the general config argument are deprecated
|
|
|
|
//in favor of the more direct specification of optional settings
|
|
|
|
//being pass directly on the options object
|
|
|
|
if ( options.config ){
|
|
|
|
$.extend( true, options, options.config );
|
|
|
|
delete options.config;
|
|
|
|
}
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
//Public properties
|
2011-12-07 05:26:06 +04:00
|
|
|
//Allow the options object to override global defaults
|
2013-06-19 21:33:25 +04:00
|
|
|
$.extend( true, this, {
|
2012-03-01 17:38:15 +04:00
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
//internal state and dom identifiers
|
|
|
|
id: options.id,
|
2013-10-13 02:30:05 +04:00
|
|
|
hash: options.hash || options.id,
|
2012-04-03 11:08:27 +04:00
|
|
|
|
|
|
|
//dom nodes
|
2013-11-25 20:48:44 +04:00
|
|
|
/**
|
|
|
|
* The parent element of this Viewer instance, passed in when the Viewer was created.
|
|
|
|
* @member {Element} element
|
|
|
|
* @memberof OpenSeadragon.Viewer#
|
|
|
|
*/
|
2012-04-03 11:08:27 +04:00
|
|
|
element: null,
|
2013-11-25 20:48:44 +04:00
|
|
|
/**
|
|
|
|
* A <form> element (provided by {@link OpenSeadragon.ControlDock}), the base element of this Viewer instance.<br><br>
|
|
|
|
* Child element of {@link OpenSeadragon.Viewer#element}.
|
|
|
|
* @member {Element} container
|
|
|
|
* @memberof OpenSeadragon.Viewer#
|
|
|
|
*/
|
2012-04-03 11:08:27 +04:00
|
|
|
container: null,
|
2013-11-25 20:48:44 +04:00
|
|
|
/**
|
|
|
|
* A <textarea> element, the element where keyboard events are handled.<br><br>
|
|
|
|
* Child element of {@link OpenSeadragon.Viewer#container},
|
|
|
|
* positioned below {@link OpenSeadragon.Viewer#canvas}.
|
|
|
|
* @member {Element} keyboardCommandArea
|
|
|
|
* @memberof OpenSeadragon.Viewer#
|
|
|
|
*/
|
|
|
|
keyboardCommandArea: null,
|
|
|
|
/**
|
|
|
|
* A <div> element, the element where user-input events are handled for panning and zooming.<br><br>
|
|
|
|
* Child element of {@link OpenSeadragon.Viewer#container},
|
|
|
|
* positioned on top of {@link OpenSeadragon.Viewer#keyboardCommandArea}.<br><br>
|
|
|
|
* The parent of {@link OpenSeadragon.Drawer#canvas} instances.
|
|
|
|
* @member {Element} canvas
|
|
|
|
* @memberof OpenSeadragon.Viewer#
|
|
|
|
*/
|
|
|
|
canvas: null,
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2014-01-31 00:38:37 +04:00
|
|
|
// Overlays list. An overlay allows to add html on top of the viewer.
|
2014-01-31 20:49:44 +04:00
|
|
|
overlays: [],
|
2014-03-20 17:56:12 +04:00
|
|
|
// Container inside the canvas where overlays are drawn.
|
|
|
|
overlaysContainer: null,
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2012-03-01 17:38:15 +04:00
|
|
|
//private state properties
|
2012-04-03 11:08:27 +04:00
|
|
|
previousBody: [],
|
2011-12-08 06:10:13 +04:00
|
|
|
|
|
|
|
//This was originally initialized in the constructor and so could never
|
|
|
|
//have anything in it. now it can because we allow it to be specified
|
|
|
|
//in the options and is only empty by default if not specified. Also
|
|
|
|
//this array was returned from get_controls which I find confusing
|
|
|
|
//since this object has a controls property which is treated in other
|
|
|
|
//functions like clearControls. I'm removing the accessors.
|
2012-03-01 17:38:15 +04:00
|
|
|
customControls: [],
|
2011-12-06 07:50:25 +04:00
|
|
|
|
2012-03-01 17:38:15 +04:00
|
|
|
//These are originally not part options but declared as members
|
2013-11-19 23:20:45 +04:00
|
|
|
//in initialize. It's still considered idiomatic to put them here
|
2012-03-01 17:38:15 +04:00
|
|
|
source: null,
|
2013-11-19 22:08:04 +04:00
|
|
|
/**
|
2013-11-25 20:48:44 +04:00
|
|
|
* Handles rendering of tiles in the viewer. Created for each TileSource opened.
|
2013-11-19 22:08:04 +04:00
|
|
|
* @member {OpenSeadragon.Drawer} drawer
|
|
|
|
* @memberof OpenSeadragon.Viewer#
|
|
|
|
*/
|
2014-03-20 17:56:12 +04:00
|
|
|
drawer: null,
|
|
|
|
drawers: [],
|
|
|
|
// Container inside the canvas where drawers (layers) are drawn.
|
|
|
|
drawersContainer: null,
|
2013-11-19 22:08:04 +04:00
|
|
|
/**
|
2013-11-25 20:48:44 +04:00
|
|
|
* Handles coordinate-related functionality - zoom, pan, rotation, etc. Created for each TileSource opened.
|
2013-11-19 22:08:04 +04:00
|
|
|
* @member {OpenSeadragon.Viewport} viewport
|
|
|
|
* @memberof OpenSeadragon.Viewer#
|
|
|
|
*/
|
2012-03-01 17:38:15 +04:00
|
|
|
viewport: null,
|
2013-11-19 22:08:04 +04:00
|
|
|
/**
|
|
|
|
* @member {OpenSeadragon.Navigator} navigator
|
|
|
|
* @memberof OpenSeadragon.Viewer#
|
|
|
|
*/
|
2013-06-19 21:33:25 +04:00
|
|
|
navigator: null,
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2013-11-19 22:08:04 +04:00
|
|
|
//A collection viewport is a separate viewport used to provide
|
2013-11-19 23:20:45 +04:00
|
|
|
//simultaneous rendering of sets of tiles
|
2013-01-24 08:00:11 +04:00
|
|
|
collectionViewport: null,
|
|
|
|
collectionDrawer: null,
|
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
//UI image resources
|
|
|
|
//TODO: rename navImages to uiImages
|
|
|
|
navImages: null,
|
|
|
|
|
|
|
|
//interface button controls
|
2013-06-19 21:33:25 +04:00
|
|
|
buttons: null,
|
2012-04-03 11:08:27 +04:00
|
|
|
|
|
|
|
//TODO: this is defunct so safely remove it
|
2012-03-01 17:38:15 +04:00
|
|
|
profiler: null
|
2011-12-07 05:26:06 +04:00
|
|
|
|
2012-03-01 17:38:15 +04:00
|
|
|
}, $.DEFAULT_SETTINGS, options );
|
|
|
|
|
2013-10-13 02:30:05 +04:00
|
|
|
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.");
|
|
|
|
}
|
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
//Private state properties
|
|
|
|
THIS[ this.hash ] = {
|
|
|
|
"fsBoundsDelta": new $.Point( 1, 1 ),
|
|
|
|
"prevContainerSize": null,
|
|
|
|
"animating": false,
|
|
|
|
"forceRedraw": false,
|
|
|
|
"mouseInside": false,
|
|
|
|
"group": null,
|
|
|
|
// whether we should be continuously zooming
|
|
|
|
"zooming": false,
|
|
|
|
// how much we should be continuously zooming by
|
2013-06-19 21:33:25 +04:00
|
|
|
"zoomFactor": null,
|
2012-04-03 11:08:27 +04:00
|
|
|
"lastZoomTime": null,
|
|
|
|
// did we decide this viewer has a sequence of tile sources
|
|
|
|
"sequenced": false,
|
2013-02-28 23:28:05 +04:00
|
|
|
"sequence": 0,
|
2013-06-19 21:33:25 +04:00
|
|
|
"fullPage": false,
|
2013-02-28 23:28:05 +04:00
|
|
|
"onfullscreenchange": null
|
2012-04-03 11:08:27 +04:00
|
|
|
};
|
|
|
|
|
2013-06-18 22:06:43 +04:00
|
|
|
this._updateRequestId = null;
|
2014-03-15 19:20:33 +04:00
|
|
|
this.currentOverlays = [];
|
2013-06-18 22:06:43 +04:00
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
//Inherit some behaviors and properties
|
2013-09-25 00:36:13 +04:00
|
|
|
$.EventSource.call( this );
|
2013-06-28 02:10:23 +04:00
|
|
|
|
2013-10-11 04:00:15 +04:00
|
|
|
this.addHandler( 'open-failed', function ( event ) {
|
|
|
|
var msg = $.getString( "Errors.OpenFailed", event.eventSource, event.message);
|
2013-07-01 21:43:48 +04:00
|
|
|
_this._showMessage( msg );
|
2013-06-28 02:10:23 +04:00
|
|
|
});
|
|
|
|
|
2012-03-09 20:04:28 +04:00
|
|
|
$.ControlDock.call( this, options );
|
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
//Deal with tile sources
|
2013-06-19 01:55:19 +04:00
|
|
|
var initialTileSource;
|
2012-04-03 11:08:27 +04:00
|
|
|
|
|
|
|
if ( this.xmlPath ){
|
|
|
|
//Deprecated option. Now it is preferred to use the tileSources option
|
|
|
|
this.tileSources = [ this.xmlPath ];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( this.tileSources ){
|
2012-06-05 15:52:00 +04:00
|
|
|
// tileSources is a complex option...
|
2013-06-19 21:33:25 +04:00
|
|
|
//
|
2012-06-05 15:52:00 +04:00
|
|
|
// It can be a string, object, or an array of any of strings and objects.
|
2013-06-19 21:33:25 +04:00
|
|
|
// At this point we only care about if it is an Array or not.
|
2012-06-05 15:52:00 +04:00
|
|
|
//
|
2012-04-03 11:08:27 +04:00
|
|
|
if( $.isArray( this.tileSources ) ){
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2012-06-05 15:52:00 +04:00
|
|
|
//must be a sequence of tileSource since the first item
|
|
|
|
//is a legacy tile source
|
2013-06-19 21:33:25 +04:00
|
|
|
if( this.tileSources.length > 1 ){
|
2012-04-03 11:08:27 +04:00
|
|
|
THIS[ this.hash ].sequenced = true;
|
2013-06-19 21:33:25 +04:00
|
|
|
}
|
2013-10-10 23:25:11 +04:00
|
|
|
|
2013-10-09 04:07:49 +04:00
|
|
|
//Keeps the initial page within bounds
|
2013-10-10 02:27:43 +04:00
|
|
|
if ( this.initialPage > this.tileSources.length - 1 ){
|
|
|
|
this.initialPage = this.tileSources.length - 1;
|
2013-10-09 08:45:26 +04:00
|
|
|
}
|
|
|
|
|
2013-10-09 02:01:28 +04:00
|
|
|
initialTileSource = this.tileSources[ this.initialPage ];
|
2013-10-09 04:10:26 +04:00
|
|
|
|
|
|
|
//Update the sequence (aka currrent page) property
|
2013-10-10 02:36:21 +04:00
|
|
|
THIS[ this.hash ].sequence = this.initialPage;
|
2012-04-03 11:08:27 +04:00
|
|
|
} else {
|
|
|
|
initialTileSource = this.tileSources;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-05 06:30:59 +04:00
|
|
|
this.element = this.element || document.getElementById( this.id );
|
|
|
|
this.canvas = $.makeNeutralElement( "div" );
|
|
|
|
this.keyboardCommandArea = $.makeNeutralElement( "textarea" );
|
2014-03-20 17:56:12 +04:00
|
|
|
this.drawersContainer = $.makeNeutralElement( "div" );
|
|
|
|
this.overlaysContainer = $.makeNeutralElement( "div" );
|
2012-01-24 17:03:50 +04:00
|
|
|
|
2013-02-14 01:50:23 +04:00
|
|
|
this.canvas.className = "openseadragon-canvas";
|
2013-03-17 00:35:33 +04:00
|
|
|
(function( style ){
|
|
|
|
style.width = "100%";
|
|
|
|
style.height = "100%";
|
|
|
|
style.overflow = "hidden";
|
|
|
|
style.position = "absolute";
|
|
|
|
style.top = "0px";
|
|
|
|
style.left = "0px";
|
2012-03-09 20:04:28 +04:00
|
|
|
}( this.canvas.style ));
|
|
|
|
|
2013-02-14 01:50:23 +04:00
|
|
|
//the container is created through applying the ControlDock constructor above
|
|
|
|
this.container.className = "openseadragon-container";
|
2013-03-17 00:35:33 +04:00
|
|
|
(function( style ){
|
|
|
|
style.width = "100%";
|
|
|
|
style.height = "100%";
|
|
|
|
style.position = "relative";
|
|
|
|
style.overflow = "hidden";
|
|
|
|
style.left = "0px";
|
|
|
|
style.top = "0px";
|
|
|
|
style.textAlign = "left"; // needed to protect against
|
2012-03-09 20:04:28 +04:00
|
|
|
}( this.container.style ));
|
|
|
|
|
2013-04-05 06:30:59 +04:00
|
|
|
this.keyboardCommandArea.className = "keyboard-command-area";
|
|
|
|
(function( style ){
|
|
|
|
style.width = "100%";
|
|
|
|
style.height = "100%";
|
|
|
|
style.overflow = "hidden";
|
|
|
|
style.position = "absolute";
|
|
|
|
style.top = "0px";
|
|
|
|
style.left = "0px";
|
2013-06-01 22:11:56 +04:00
|
|
|
style.resize = "none";
|
2013-04-05 06:30:59 +04:00
|
|
|
}( this.keyboardCommandArea.style ));
|
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
this.container.insertBefore( this.canvas, this.container.firstChild );
|
2013-04-05 06:30:59 +04:00
|
|
|
this.container.insertBefore( this.keyboardCommandArea, this.container.firstChild );
|
2012-03-09 20:04:28 +04:00
|
|
|
this.element.appendChild( this.container );
|
2014-03-20 17:56:12 +04:00
|
|
|
this.canvas.appendChild( this.drawersContainer );
|
|
|
|
this.canvas.appendChild( this.overlaysContainer );
|
2012-03-09 20:04:28 +04:00
|
|
|
|
2012-01-24 17:03:50 +04:00
|
|
|
//Used for toggling between fullscreen and default container size
|
2012-02-27 15:56:29 +04:00
|
|
|
//TODO: these can be closure private and shared across Viewer
|
|
|
|
// instances.
|
2012-01-24 17:03:50 +04:00
|
|
|
this.bodyWidth = document.body.style.width;
|
|
|
|
this.bodyHeight = document.body.style.height;
|
|
|
|
this.bodyOverflow = document.body.style.overflow;
|
|
|
|
this.docOverflow = document.documentElement.style.overflow;
|
2012-02-27 15:56:29 +04:00
|
|
|
|
2013-04-05 06:30:59 +04:00
|
|
|
this.keyboardCommandArea.innerTracker = new $.MouseTracker({
|
|
|
|
_this : this,
|
|
|
|
element: this.keyboardCommandArea,
|
2013-11-05 00:41:45 +04:00
|
|
|
focusHandler: function( event ){
|
|
|
|
if ( !event.preventDefaultAction ) {
|
|
|
|
var point = $.getElementPosition( this.element );
|
|
|
|
window.scrollTo( 0, point.y );
|
|
|
|
}
|
2013-04-05 06:30:59 +04:00
|
|
|
},
|
|
|
|
|
2013-10-11 04:00:15 +04:00
|
|
|
keyHandler: function( event ){
|
2013-11-05 00:41:45 +04:00
|
|
|
if ( !event.preventDefaultAction ) {
|
|
|
|
switch( event.keyCode ){
|
|
|
|
case 61://=|+
|
2013-04-05 06:30:59 +04:00
|
|
|
_this.viewport.zoomBy(1.1);
|
2013-11-05 00:41:45 +04:00
|
|
|
_this.viewport.applyConstraints();
|
|
|
|
return false;
|
|
|
|
case 45://-|_
|
2013-04-05 06:30:59 +04:00
|
|
|
_this.viewport.zoomBy(0.9);
|
2013-11-05 00:41:45 +04:00
|
|
|
_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;
|
|
|
|
}
|
2013-04-05 06:30:59 +04:00
|
|
|
}
|
2013-03-17 00:35:33 +04:00
|
|
|
}
|
2013-04-05 06:30:59 +04:00
|
|
|
}).setTracking( true ); // default state
|
|
|
|
|
2013-03-17 00:35:33 +04:00
|
|
|
|
2012-02-03 04:12:45 +04:00
|
|
|
this.innerTracker = new $.MouseTracker({
|
2013-06-19 21:33:25 +04:00
|
|
|
element: this.canvas,
|
|
|
|
clickTimeThreshold: this.clickTimeThreshold,
|
2012-03-01 17:38:15 +04:00
|
|
|
clickDistThreshold: this.clickDistThreshold,
|
2012-02-03 04:12:45 +04:00
|
|
|
clickHandler: $.delegate( this, onCanvasClick ),
|
|
|
|
dragHandler: $.delegate( this, onCanvasDrag ),
|
|
|
|
releaseHandler: $.delegate( this, onCanvasRelease ),
|
|
|
|
scrollHandler: $.delegate( this, onCanvasScroll )
|
2012-03-07 07:20:00 +04:00
|
|
|
}).setTracking( this.mouseNavEnabled ? true : false ); // default state
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2012-02-03 04:12:45 +04:00
|
|
|
this.outerTracker = new $.MouseTracker({
|
2013-06-19 21:33:25 +04:00
|
|
|
element: this.container,
|
|
|
|
clickTimeThreshold: this.clickTimeThreshold,
|
2012-03-01 17:38:15 +04:00
|
|
|
clickDistThreshold: this.clickDistThreshold,
|
2012-02-03 04:12:45 +04:00
|
|
|
enterHandler: $.delegate( this, onContainerEnter ),
|
|
|
|
exitHandler: $.delegate( this, onContainerExit ),
|
|
|
|
releaseHandler: $.delegate( this, onContainerRelease )
|
2012-03-07 07:20:00 +04:00
|
|
|
}).setTracking( this.mouseNavEnabled ? true : false ); // always tracking
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2012-04-11 01:02:24 +04:00
|
|
|
if( this.toolbar ){
|
|
|
|
this.toolbar = new $.ControlDock({ element: this.toolbar });
|
2011-12-07 05:26:06 +04:00
|
|
|
}
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2012-04-11 01:02:24 +04:00
|
|
|
this.bindStandardControls();
|
|
|
|
this.bindSequenceControls();
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2013-10-10 23:25:11 +04:00
|
|
|
if ( initialTileSource ) {
|
|
|
|
this.open( initialTileSource );
|
2013-10-10 23:57:02 +04:00
|
|
|
|
|
|
|
if ( this.tileSources.length > 1 ) {
|
|
|
|
this._updateSequenceButtons( this.initialPage );
|
|
|
|
}
|
2013-10-10 23:25:11 +04:00
|
|
|
}
|
2013-10-10 23:57:02 +04:00
|
|
|
|
2012-03-16 19:36:28 +04:00
|
|
|
for ( i = 0; i < this.customControls.length; i++ ) {
|
|
|
|
this.addControl(
|
2013-06-19 21:33:25 +04:00
|
|
|
this.customControls[ i ].id,
|
2013-03-15 18:59:47 +04:00
|
|
|
{anchor: this.customControls[ i ].anchor}
|
2012-03-16 19:36:28 +04:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2013-02-26 19:19:48 +04:00
|
|
|
$.requestAnimationFrame( function(){
|
2011-12-08 06:10:13 +04:00
|
|
|
beginControlsAutoHide( _this );
|
2013-02-26 19:19:48 +04:00
|
|
|
} ); // initial fade out
|
2011-12-07 05:26:06 +04:00
|
|
|
|
2011-12-06 07:50:25 +04:00
|
|
|
};
|
|
|
|
|
2013-11-16 10:19:53 +04:00
|
|
|
$.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, /** @lends OpenSeadragon.Viewer.prototype */{
|
2011-12-06 07:50:25 +04:00
|
|
|
|
2011-12-23 05:47:21 +04:00
|
|
|
|
2012-02-01 00:59:09 +04:00
|
|
|
/**
|
|
|
|
* @function
|
2012-02-18 22:13:05 +04:00
|
|
|
* @return {Boolean}
|
2012-02-01 00:59:09 +04:00
|
|
|
*/
|
2011-12-06 07:50:25 +04:00
|
|
|
isOpen: function () {
|
|
|
|
return !!this.source;
|
|
|
|
},
|
2011-12-23 05:47:21 +04:00
|
|
|
|
2012-02-01 00:59:09 +04:00
|
|
|
/**
|
2013-06-19 21:33:25 +04:00
|
|
|
* A deprecated function, renamed to 'open' to match event name and
|
|
|
|
* match current 'close' method.
|
2012-02-01 00:59:09 +04:00
|
|
|
* @function
|
2013-03-26 17:02:34 +04:00
|
|
|
* @param {String} dzi xml string or the url to a DZI xml document.
|
2012-02-18 22:13:05 +04:00
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
2012-08-29 22:46:34 +04:00
|
|
|
*
|
2013-11-22 00:19:07 +04:00
|
|
|
* @deprecated - use {@link OpenSeadragon.Viewer#open} instead.
|
2012-02-01 00:59:09 +04:00
|
|
|
*/
|
|
|
|
openDzi: function ( dzi ) {
|
2013-03-26 17:02:34 +04:00
|
|
|
return this.open( dzi );
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-06-19 21:33:25 +04:00
|
|
|
* A deprecated function, renamed to 'open' to match event name and
|
2013-03-26 17:02:34 +04:00
|
|
|
* match current 'close' method.
|
|
|
|
* @function
|
|
|
|
* @param {String|Object|Function} See OpenSeadragon.Viewer.prototype.open
|
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
|
|
|
*
|
2013-11-22 00:19:07 +04:00
|
|
|
* @deprecated - use {@link OpenSeadragon.Viewer#open} instead.
|
2013-03-26 17:02:34 +04:00
|
|
|
*/
|
|
|
|
openTileSource: function ( tileSource ) {
|
|
|
|
return this.open( tileSource );
|
2011-12-06 07:50:25 +04:00
|
|
|
},
|
2011-12-23 05:47:21 +04:00
|
|
|
|
2012-02-01 00:59:09 +04:00
|
|
|
/**
|
2013-03-26 17:02:34 +04:00
|
|
|
* Open a TileSource object into the viewer.
|
|
|
|
*
|
2012-06-05 15:52:00 +04:00
|
|
|
* tileSources is a complex option...
|
2013-06-19 21:33:25 +04:00
|
|
|
*
|
2012-06-05 15:52:00 +04:00
|
|
|
* It can be a string, object, function, or an array of any of these:
|
|
|
|
*
|
|
|
|
* - A String implies a url used to determine the tileSource implementation
|
|
|
|
* based on the file extension of url. JSONP is implied by *.js,
|
|
|
|
* otherwise the url is retrieved as text and the resulting text is
|
2013-06-19 21:33:25 +04:00
|
|
|
* introspected to determine if its json, xml, or text and parsed.
|
|
|
|
* - An Object implies an inline configuration which has a single
|
|
|
|
* property sufficient for being able to determine tileSource
|
2012-06-05 15:52:00 +04:00
|
|
|
* implementation. If the object has a property which is a function
|
|
|
|
* named 'getTileUrl', it is treated as a custom TileSource.
|
2012-02-01 00:59:09 +04:00
|
|
|
* @function
|
2013-03-26 17:02:34 +04:00
|
|
|
* @param {String|Object|Function}
|
2012-02-18 22:13:05 +04:00
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
2013-11-22 00:19:07 +04:00
|
|
|
* @fires OpenSeadragon.Viewer.event:open
|
|
|
|
* @fires OpenSeadragon.Viewer.event:open-failed
|
2012-02-01 00:59:09 +04:00
|
|
|
*/
|
2013-03-26 17:02:34 +04:00
|
|
|
open: function ( tileSource ) {
|
2013-12-09 18:26:36 +04:00
|
|
|
var _this = this;
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2013-07-01 21:43:48 +04:00
|
|
|
_this._hideMessage();
|
2013-06-28 22:32:57 +04:00
|
|
|
|
2013-12-09 18:26:36 +04:00
|
|
|
getTileSourceImplementation( _this, tileSource, function( tileSource ) {
|
|
|
|
openTileSource( _this, tileSource );
|
|
|
|
}, function( event ) {
|
|
|
|
/**
|
|
|
|
* Raised when an error occurs loading a TileSource.
|
|
|
|
*
|
|
|
|
* @event open-failed
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {String} message
|
|
|
|
* @property {String} source
|
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
|
|
|
*/
|
|
|
|
_this.raiseEvent( 'open-failed', event );
|
|
|
|
});
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2012-02-18 22:13:05 +04:00
|
|
|
return this;
|
2011-12-06 07:50:25 +04:00
|
|
|
},
|
2011-12-23 05:47:21 +04:00
|
|
|
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2012-02-01 00:59:09 +04:00
|
|
|
/**
|
|
|
|
* @function
|
2012-02-18 22:13:05 +04:00
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
2013-11-22 00:19:07 +04:00
|
|
|
* @fires OpenSeadragon.Viewer.event:close
|
2012-02-01 00:59:09 +04:00
|
|
|
*/
|
2012-04-03 11:08:27 +04:00
|
|
|
close: function ( ) {
|
2013-06-18 22:06:43 +04:00
|
|
|
if ( this._updateRequestId !== null ) {
|
|
|
|
$.cancelAnimationFrame( this._updateRequestId );
|
|
|
|
this._updateRequestId = null;
|
2013-04-27 06:32:51 +04:00
|
|
|
}
|
|
|
|
|
2013-06-17 22:31:41 +04:00
|
|
|
if ( this.navigator ) {
|
|
|
|
this.navigator.close();
|
|
|
|
}
|
|
|
|
|
2014-01-31 00:38:37 +04:00
|
|
|
this.clearOverlays();
|
2014-03-20 17:56:12 +04:00
|
|
|
this.drawersContainer.innerHTML = "";
|
|
|
|
this.overlaysContainer.innerHTML = "";
|
2013-02-13 07:40:08 +04:00
|
|
|
|
2012-01-24 17:03:50 +04:00
|
|
|
this.source = null;
|
|
|
|
this.drawer = null;
|
2013-12-01 02:28:17 +04:00
|
|
|
this.drawers = [];
|
2013-02-11 07:53:51 +04:00
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
this.viewport = this.preserveViewport ? this.viewport : null;
|
2014-03-20 17:56:12 +04:00
|
|
|
|
2012-03-16 19:36:28 +04:00
|
|
|
|
|
|
|
VIEWERS[ this.hash ] = null;
|
|
|
|
delete VIEWERS[ this.hash ];
|
2013-02-14 04:44:23 +04:00
|
|
|
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-22 00:19:07 +04:00
|
|
|
* Raised when the viewer is closed (see {@link OpenSeadragon.Viewer#close}).
|
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event close
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-10-15 22:11:08 +04:00
|
|
|
this.raiseEvent( 'close' );
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2012-02-18 22:13:05 +04:00
|
|
|
return this;
|
2011-12-06 07:50:25 +04:00
|
|
|
},
|
2012-01-24 17:03:50 +04:00
|
|
|
|
2013-09-12 17:41:51 +04:00
|
|
|
|
2013-08-07 04:54:20 +04:00
|
|
|
/**
|
2013-08-12 10:38:37 +04:00
|
|
|
* Function to destroy the viewer and clean up everything created by
|
|
|
|
* OpenSeadragon.
|
2013-08-07 04:54:20 +04:00
|
|
|
* @function
|
|
|
|
*/
|
|
|
|
destroy: function( ) {
|
|
|
|
this.close();
|
|
|
|
|
2013-08-08 11:49:24 +04:00
|
|
|
this.removeAllHandlers();
|
2013-08-07 04:54:20 +04:00
|
|
|
|
|
|
|
// Go through top element (passed to us) and remove all children
|
|
|
|
// Use removeChild to make sure it handles SVG or any non-html
|
|
|
|
// also it performs better - http://jsperf.com/innerhtml-vs-removechild/15
|
2013-08-08 11:49:24 +04:00
|
|
|
if (this.element){
|
|
|
|
while (this.element.firstChild) {
|
|
|
|
this.element.removeChild(this.element.firstChild);
|
|
|
|
}
|
2013-08-07 04:54:20 +04:00
|
|
|
}
|
|
|
|
|
2013-08-08 11:49:24 +04:00
|
|
|
// destroy the mouse trackers
|
|
|
|
if (this.keyboardCommandArea){
|
|
|
|
this.keyboardCommandArea.innerTracker.destroy();
|
|
|
|
}
|
|
|
|
if (this.innerTracker){
|
|
|
|
this.innerTracker.destroy();
|
|
|
|
}
|
|
|
|
if (this.outerTracker){
|
|
|
|
this.outerTracker.destroy();
|
|
|
|
}
|
2013-08-07 04:54:20 +04:00
|
|
|
|
|
|
|
// clear all our references to dom objects
|
|
|
|
this.canvas = null;
|
|
|
|
this.keyboardCommandArea = null;
|
|
|
|
this.container = null;
|
|
|
|
|
|
|
|
// clear our reference to the main element - they will need to pass it in again, creating a new viewer
|
|
|
|
this.element = null;
|
|
|
|
},
|
|
|
|
|
2012-03-09 20:04:28 +04:00
|
|
|
|
2012-02-01 00:59:09 +04:00
|
|
|
/**
|
|
|
|
* @function
|
2012-03-09 20:04:28 +04:00
|
|
|
* @return {Boolean}
|
2012-02-01 00:59:09 +04:00
|
|
|
*/
|
2012-03-09 20:04:28 +04:00
|
|
|
isMouseNavEnabled: function () {
|
|
|
|
return this.innerTracker.isTracking();
|
2011-12-06 07:50:25 +04:00
|
|
|
},
|
2012-01-24 17:03:50 +04:00
|
|
|
|
2012-02-01 00:59:09 +04:00
|
|
|
/**
|
|
|
|
* @function
|
2013-11-16 10:19:53 +04:00
|
|
|
* @param {Boolean} enabled - true to enable, false to disable
|
2012-02-18 22:13:05 +04:00
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
2013-11-22 00:19:07 +04:00
|
|
|
* @fires OpenSeadragon.Viewer.event:mouse-enabled
|
2012-02-01 00:59:09 +04:00
|
|
|
*/
|
2012-03-09 20:04:28 +04:00
|
|
|
setMouseNavEnabled: function( enabled ){
|
|
|
|
this.innerTracker.setTracking( enabled );
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-22 00:19:07 +04:00
|
|
|
* Raised when mouse/touch navigation is enabled or disabled (see {@link OpenSeadragon.Viewer#setMouseNavEnabled}).
|
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event mouse-enabled
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {Boolean} enabled
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-10-11 04:00:15 +04:00
|
|
|
this.raiseEvent( 'mouse-enabled', { enabled: enabled } );
|
2012-02-18 22:13:05 +04:00
|
|
|
return this;
|
2011-12-06 07:50:25 +04:00
|
|
|
},
|
2012-01-24 17:03:50 +04:00
|
|
|
|
2012-03-09 20:04:28 +04:00
|
|
|
|
2012-02-01 00:59:09 +04:00
|
|
|
/**
|
|
|
|
* @function
|
2012-02-18 22:13:05 +04:00
|
|
|
* @return {Boolean}
|
2012-02-01 00:59:09 +04:00
|
|
|
*/
|
2012-03-20 03:03:58 +04:00
|
|
|
areControlsEnabled: function () {
|
2012-08-29 22:46:34 +04:00
|
|
|
var enabled = this.controls.length,
|
|
|
|
i;
|
|
|
|
for( i = 0; i < this.controls.length; i++ ){
|
|
|
|
enabled = enabled && this.controls[ i ].isVisibile();
|
|
|
|
}
|
|
|
|
return enabled;
|
2011-12-06 07:50:25 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
|
2012-02-01 00:59:09 +04:00
|
|
|
/**
|
2013-05-29 00:54:13 +04:00
|
|
|
* Shows or hides the controls (e.g. the default navigation buttons).
|
2013-06-19 21:33:25 +04:00
|
|
|
*
|
2012-02-01 00:59:09 +04:00
|
|
|
* @function
|
2013-05-29 00:54:13 +04:00
|
|
|
* @param {Boolean} true to show, false to hide.
|
2012-03-09 20:04:28 +04:00
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
2013-11-22 00:19:07 +04:00
|
|
|
* @fires OpenSeadragon.Viewer.event:controls-enabled
|
2012-02-01 00:59:09 +04:00
|
|
|
*/
|
2012-03-20 03:03:58 +04:00
|
|
|
setControlsEnabled: function( enabled ) {
|
|
|
|
if( enabled ){
|
|
|
|
abortControlsAutoHide( this );
|
|
|
|
} else {
|
|
|
|
beginControlsAutoHide( this );
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-22 00:19:07 +04:00
|
|
|
* Raised when the navigation controls are shown or hidden (see {@link OpenSeadragon.Viewer#setControlsEnabled}).
|
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event controls-enabled
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {Boolean} enabled
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-10-11 04:00:15 +04:00
|
|
|
this.raiseEvent( 'controls-enabled', { enabled: enabled } );
|
2013-02-14 04:44:23 +04:00
|
|
|
return this;
|
2011-12-06 07:50:25 +04:00
|
|
|
},
|
|
|
|
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2012-02-01 00:59:09 +04:00
|
|
|
/**
|
|
|
|
* @function
|
2012-02-18 22:13:05 +04:00
|
|
|
* @return {Boolean}
|
2012-02-01 00:59:09 +04:00
|
|
|
*/
|
2012-03-09 20:04:28 +04:00
|
|
|
isFullPage: function () {
|
2013-03-26 17:02:34 +04:00
|
|
|
return THIS[ this.hash ].fullPage;
|
2011-12-06 07:50:25 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
|
2012-02-01 00:59:09 +04:00
|
|
|
/**
|
2012-02-10 07:16:09 +04:00
|
|
|
* Toggle full page mode.
|
2012-02-01 00:59:09 +04:00
|
|
|
* @function
|
2012-02-10 07:16:09 +04:00
|
|
|
* @param {Boolean} fullPage
|
|
|
|
* If true, enter full page mode. If false, exit full page mode.
|
2012-02-18 22:13:05 +04:00
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
2013-11-22 00:19:07 +04:00
|
|
|
* @fires OpenSeadragon.Viewer.event:pre-full-page
|
|
|
|
* @fires OpenSeadragon.Viewer.event:full-page
|
2012-02-01 00:59:09 +04:00
|
|
|
*/
|
2011-12-08 06:10:13 +04:00
|
|
|
setFullPage: function( fullPage ) {
|
2011-12-06 07:50:25 +04:00
|
|
|
|
2013-11-03 05:01:04 +04:00
|
|
|
var body = document.body,
|
|
|
|
bodyStyle = body.style,
|
|
|
|
docStyle = document.documentElement.style,
|
|
|
|
_this = this,
|
2012-03-16 19:36:28 +04:00
|
|
|
hash,
|
2012-02-10 07:16:09 +04:00
|
|
|
nodes,
|
|
|
|
i;
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2012-02-10 07:16:09 +04:00
|
|
|
//dont bother modifying the DOM if we are already in full page mode.
|
2012-01-24 17:03:50 +04:00
|
|
|
if ( fullPage == this.isFullPage() ) {
|
2013-11-03 05:01:04 +04:00
|
|
|
return this;
|
2012-01-24 17:03:50 +04:00
|
|
|
}
|
2013-11-01 06:19:22 +04:00
|
|
|
|
2013-11-09 00:03:54 +04:00
|
|
|
var fullPageEventArgs = {
|
|
|
|
fullPage: fullPage,
|
|
|
|
preventDefaultAction: false
|
|
|
|
};
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-22 00:19:07 +04:00
|
|
|
* Raised when the viewer is about to change to/from full-page mode (see {@link OpenSeadragon.Viewer#setFullPage}).
|
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event pre-full-page
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {Boolean} fullPage - True if entering full-page mode, false if exiting full-page mode.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {Boolean} preventDefaultAction - Set to true to prevent full-page mode change. Default: false.
|
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-11-09 00:03:54 +04:00
|
|
|
this.raiseEvent( 'pre-full-page', fullPageEventArgs );
|
|
|
|
if ( fullPageEventArgs.preventDefaultAction ) {
|
|
|
|
return this;
|
|
|
|
}
|
2013-02-27 07:34:44 +04:00
|
|
|
|
2011-12-08 06:10:13 +04:00
|
|
|
if ( fullPage ) {
|
2013-11-01 06:19:22 +04:00
|
|
|
|
2013-11-03 05:01:04 +04:00
|
|
|
this.elementSize = $.getElementSize( this.element );
|
|
|
|
this.pageScroll = $.getPageScroll();
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2013-11-09 00:03:54 +04:00
|
|
|
this.elementMargin = this.element.style.margin;
|
|
|
|
this.element.style.margin = "0";
|
|
|
|
this.elementPadding = this.element.style.padding;
|
|
|
|
this.element.style.padding = "0";
|
|
|
|
|
2013-11-03 05:01:04 +04:00
|
|
|
this.bodyMargin = bodyStyle.margin;
|
|
|
|
this.docMargin = docStyle.margin;
|
|
|
|
bodyStyle.margin = "0";
|
|
|
|
docStyle.margin = "0";
|
2013-10-23 18:00:08 +04:00
|
|
|
|
2013-11-03 05:01:04 +04:00
|
|
|
this.bodyPadding = bodyStyle.padding;
|
|
|
|
this.docPadding = docStyle.padding;
|
|
|
|
bodyStyle.padding = "0";
|
|
|
|
docStyle.padding = "0";
|
2011-12-06 07:50:25 +04:00
|
|
|
|
2013-11-03 05:01:04 +04:00
|
|
|
this.bodyWidth = bodyStyle.width;
|
|
|
|
this.bodyHeight = bodyStyle.height;
|
|
|
|
bodyStyle.width = "100%";
|
|
|
|
bodyStyle.height = "100%";
|
2011-12-06 07:50:25 +04:00
|
|
|
|
2012-02-10 07:16:09 +04:00
|
|
|
//when entering full screen on the ipad it wasnt sufficient to leave
|
2013-06-19 21:33:25 +04:00
|
|
|
//the body intact as only only the top half of the screen would
|
2012-02-10 07:16:09 +04:00
|
|
|
//respond to touch events on the canvas, while the bottom half treated
|
|
|
|
//them as touch events on the document body. Thus we remove and store
|
|
|
|
//the bodies elements and replace them when we leave full screen.
|
|
|
|
this.previousBody = [];
|
2012-10-13 07:40:59 +04:00
|
|
|
THIS[ this.hash ].prevElementParent = this.element.parentNode;
|
2013-03-26 17:02:34 +04:00
|
|
|
THIS[ this.hash ].prevNextSibling = this.element.nextSibling;
|
2013-09-12 17:41:51 +04:00
|
|
|
THIS[ this.hash ].prevElementWidth = this.element.style.width;
|
|
|
|
THIS[ this.hash ].prevElementHeight = this.element.style.height;
|
2012-03-09 20:04:28 +04:00
|
|
|
nodes = body.childNodes.length;
|
2013-11-03 05:01:04 +04:00
|
|
|
for ( i = 0; i < nodes; i++ ) {
|
2012-03-09 20:04:28 +04:00
|
|
|
this.previousBody.push( body.childNodes[ 0 ] );
|
|
|
|
body.removeChild( body.childNodes[ 0 ] );
|
|
|
|
}
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2012-03-09 20:04:28 +04:00
|
|
|
//If we've got a toolbar, we need to enable the user to use css to
|
|
|
|
//preserve it in fullpage mode
|
2013-11-03 05:01:04 +04:00
|
|
|
if ( this.toolbar && this.toolbar.element ) {
|
2012-03-09 20:04:28 +04:00
|
|
|
//save a reference to the parent so we can put it back
|
|
|
|
//in the long run we need a better strategy
|
|
|
|
this.toolbar.parentNode = this.toolbar.element.parentNode;
|
2012-03-16 19:36:28 +04:00
|
|
|
this.toolbar.nextSibling = this.toolbar.element.nextSibling;
|
2012-03-09 20:04:28 +04:00
|
|
|
body.appendChild( this.toolbar.element );
|
|
|
|
|
|
|
|
//Make sure the user has some ability to style the toolbar based
|
|
|
|
//on the mode
|
2013-05-13 06:53:41 +04:00
|
|
|
$.addClass( this.toolbar.element, 'fullpage' );
|
2012-03-16 19:36:28 +04:00
|
|
|
}
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2013-05-13 07:02:18 +04:00
|
|
|
$.addClass( this.element, 'fullpage' );
|
2012-10-13 07:40:59 +04:00
|
|
|
body.appendChild( this.element );
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2013-11-03 05:01:04 +04:00
|
|
|
this.element.style.height = $.getWindowSize().y + 'px';
|
|
|
|
this.element.style.width = $.getWindowSize().x + 'px';
|
2013-02-28 23:28:05 +04:00
|
|
|
|
2013-11-03 05:01:04 +04:00
|
|
|
if ( this.toolbar && this.toolbar.element ) {
|
2012-10-13 07:40:59 +04:00
|
|
|
this.element.style.height = (
|
2013-02-28 23:28:05 +04:00
|
|
|
$.getElementSize( this.element ).y - $.getElementSize( this.toolbar.element ).y
|
2012-10-13 07:40:59 +04:00
|
|
|
) + 'px';
|
|
|
|
}
|
2011-12-06 07:50:25 +04:00
|
|
|
|
2013-03-26 17:02:34 +04:00
|
|
|
THIS[ this.hash ].fullPage = true;
|
|
|
|
|
2011-12-08 06:10:13 +04:00
|
|
|
// mouse will be inside container now
|
2013-10-11 04:00:15 +04:00
|
|
|
$.delegate( this, onContainerEnter )( {} );
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2011-12-06 07:50:25 +04:00
|
|
|
} else {
|
2013-02-27 02:31:47 +04:00
|
|
|
|
2013-11-09 00:03:54 +04:00
|
|
|
this.element.style.margin = this.elementMargin;
|
|
|
|
this.element.style.padding = this.elementPadding;
|
|
|
|
|
2013-11-03 05:01:04 +04:00
|
|
|
bodyStyle.margin = this.bodyMargin;
|
|
|
|
docStyle.margin = this.docMargin;
|
|
|
|
|
|
|
|
bodyStyle.padding = this.bodyPadding;
|
|
|
|
docStyle.padding = this.docPadding;
|
|
|
|
|
|
|
|
bodyStyle.width = this.bodyWidth;
|
|
|
|
bodyStyle.height = this.bodyHeight;
|
|
|
|
|
|
|
|
body.removeChild( this.element );
|
|
|
|
nodes = this.previousBody.length;
|
|
|
|
for ( i = 0; i < nodes; i++ ) {
|
|
|
|
body.appendChild( this.previousBody.shift() );
|
2012-03-09 20:04:28 +04:00
|
|
|
}
|
|
|
|
|
2013-11-03 05:01:04 +04:00
|
|
|
$.removeClass( this.element, 'fullpage' );
|
|
|
|
THIS[ this.hash ].prevElementParent.insertBefore(
|
|
|
|
this.element,
|
|
|
|
THIS[ this.hash ].prevNextSibling
|
2013-11-08 22:56:13 +04:00
|
|
|
);
|
2013-11-03 05:01:04 +04:00
|
|
|
|
|
|
|
//If we've got a toolbar, we need to enable the user to use css to
|
|
|
|
//reset it to its original state
|
|
|
|
if ( this.toolbar && this.toolbar.element ) {
|
|
|
|
body.removeChild( this.toolbar.element );
|
|
|
|
|
|
|
|
//Make sure the user has some ability to style the toolbar based
|
|
|
|
//on the mode
|
|
|
|
$.removeClass( this.toolbar.element, 'fullpage' );
|
|
|
|
|
|
|
|
this.toolbar.parentNode.insertBefore(
|
|
|
|
this.toolbar.element,
|
|
|
|
this.toolbar.nextSibling
|
2013-11-08 22:56:13 +04:00
|
|
|
);
|
2013-11-03 05:01:04 +04:00
|
|
|
delete this.toolbar.parentNode;
|
|
|
|
delete this.toolbar.nextSibling;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.element.style.width = THIS[ this.hash ].prevElementWidth;
|
|
|
|
this.element.style.height = THIS[ this.hash ].prevElementHeight;
|
|
|
|
|
|
|
|
// After exiting fullPage or fullScreen, it can take some time
|
|
|
|
// before the browser can actually set the scroll.
|
2013-11-08 22:56:13 +04:00
|
|
|
var restoreScrollCounter = 0;
|
2013-11-03 05:01:04 +04:00
|
|
|
var restoreScroll = function() {
|
|
|
|
$.setPageScroll( _this.pageScroll );
|
|
|
|
var pageScroll = $.getPageScroll();
|
2013-11-08 22:56:13 +04:00
|
|
|
restoreScrollCounter++;
|
|
|
|
if ( restoreScrollCounter < 10 &&
|
|
|
|
pageScroll.x !== _this.pageScroll.x ||
|
2013-11-03 05:01:04 +04:00
|
|
|
pageScroll.y !== _this.pageScroll.y ) {
|
|
|
|
$.requestAnimationFrame( restoreScroll );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
$.requestAnimationFrame( restoreScroll );
|
|
|
|
|
|
|
|
THIS[ this.hash ].fullPage = false;
|
|
|
|
|
|
|
|
// mouse will likely be outside now
|
|
|
|
$.delegate( this, onContainerExit )( { } );
|
|
|
|
|
2011-12-06 07:50:25 +04:00
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2013-12-14 21:11:14 +04:00
|
|
|
if ( this.navigator && this.viewport ) {
|
|
|
|
this.navigator.update( this.viewport );
|
|
|
|
}
|
|
|
|
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-22 00:19:07 +04:00
|
|
|
* Raised when the viewer has changed to/from full-page mode (see {@link OpenSeadragon.Viewer#setFullPage}).
|
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event full-page
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {Boolean} fullPage - True if changed to full-page mode, false if exited full-page mode.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-11-03 05:01:04 +04:00
|
|
|
this.raiseEvent( 'full-page', { fullPage: fullPage } );
|
|
|
|
|
2012-02-18 22:13:05 +04:00
|
|
|
return this;
|
2011-12-06 07:50:25 +04:00
|
|
|
},
|
|
|
|
|
2013-11-03 05:01:04 +04:00
|
|
|
/**
|
|
|
|
* Toggle full screen mode if supported. Toggle full page mode otherwise.
|
|
|
|
* @function
|
|
|
|
* @param {Boolean} fullScreen
|
|
|
|
* If true, enter full screen mode. If false, exit full screen mode.
|
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
2013-11-22 00:19:07 +04:00
|
|
|
* @fires OpenSeadragon.Viewer.event:pre-full-screen
|
|
|
|
* @fires OpenSeadragon.Viewer.event:full-screen
|
2013-11-03 05:01:04 +04:00
|
|
|
*/
|
|
|
|
setFullScreen: function( fullScreen ) {
|
|
|
|
var _this = this;
|
|
|
|
|
|
|
|
if ( !$.supportsFullScreen ) {
|
|
|
|
return this.setFullPage( fullScreen );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( $.isFullScreen() === fullScreen ) {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2013-11-09 00:03:54 +04:00
|
|
|
var fullScreeEventArgs = {
|
|
|
|
fullScreen: fullScreen,
|
|
|
|
preventDefaultAction: false
|
|
|
|
};
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-22 00:19:07 +04:00
|
|
|
* Raised when the viewer is about to change to/from full-screen mode (see {@link OpenSeadragon.Viewer#setFullScreen}).
|
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event pre-full-screen
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {Boolean} fullScreen - True if entering full-screen mode, false if exiting full-screen mode.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {Boolean} preventDefaultAction - Set to true to prevent full-screen mode change. Default: false.
|
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-11-09 00:03:54 +04:00
|
|
|
this.raiseEvent( 'pre-full-screen', fullScreeEventArgs );
|
|
|
|
if ( fullScreeEventArgs.preventDefaultAction ) {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2013-11-03 05:01:04 +04:00
|
|
|
if ( fullScreen ) {
|
|
|
|
|
|
|
|
this.setFullPage( true );
|
2013-11-09 00:03:54 +04:00
|
|
|
// If the full page mode is not actually entered, we need to prevent
|
|
|
|
// the full screen mode.
|
|
|
|
if ( !this.isFullPage() ) {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.fullPageStyleWidth = this.element.style.width;
|
|
|
|
this.fullPageStyleHeight = this.element.style.height;
|
|
|
|
this.element.style.width = '100%';
|
|
|
|
this.element.style.height = '100%';
|
2013-11-03 05:01:04 +04:00
|
|
|
|
|
|
|
var onFullScreenChange = function() {
|
|
|
|
var isFullScreen = $.isFullScreen();
|
|
|
|
if ( !isFullScreen ) {
|
|
|
|
$.removeEvent( document, $.fullScreenEventName, onFullScreenChange );
|
|
|
|
$.removeEvent( document, $.fullScreenErrorEventName, onFullScreenChange );
|
|
|
|
|
|
|
|
_this.setFullPage( false );
|
2013-11-09 00:03:54 +04:00
|
|
|
if ( _this.isFullPage() ) {
|
|
|
|
_this.element.style.width = _this.fullPageStyleWidth;
|
|
|
|
_this.element.style.height = _this.fullPageStyleHeight;
|
|
|
|
}
|
2013-11-03 05:01:04 +04:00
|
|
|
}
|
2013-12-14 21:11:14 +04:00
|
|
|
if ( _this.navigator && _this.viewport ) {
|
|
|
|
_this.navigator.update( _this.viewport );
|
|
|
|
}
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-22 00:19:07 +04:00
|
|
|
* Raised when the viewer has changed to/from full-screen mode (see {@link OpenSeadragon.Viewer#setFullScreen}).
|
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event full-screen
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {Boolean} fullScreen - True if changed to full-screen mode, false if exited full-screen mode.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-11-03 05:01:04 +04:00
|
|
|
_this.raiseEvent( 'full-screen', { fullScreen: isFullScreen } );
|
|
|
|
};
|
|
|
|
$.addEvent( document, $.fullScreenEventName, onFullScreenChange );
|
|
|
|
$.addEvent( document, $.fullScreenErrorEventName, onFullScreenChange );
|
|
|
|
|
|
|
|
$.requestFullScreen( document.body );
|
|
|
|
|
|
|
|
} else {
|
2014-03-18 01:01:36 +04:00
|
|
|
$.exitFullScreen();
|
2013-11-03 05:01:04 +04:00
|
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2012-02-01 00:59:09 +04:00
|
|
|
/**
|
|
|
|
* @function
|
2012-03-09 20:04:28 +04:00
|
|
|
* @return {Boolean}
|
2012-02-01 00:59:09 +04:00
|
|
|
*/
|
2012-03-09 20:04:28 +04:00
|
|
|
isVisible: function () {
|
|
|
|
return this.container.style.visibility != "hidden";
|
2011-12-06 07:50:25 +04:00
|
|
|
},
|
|
|
|
|
2012-03-09 20:04:28 +04:00
|
|
|
|
2012-02-01 00:59:09 +04:00
|
|
|
/**
|
|
|
|
* @function
|
2013-11-16 10:19:53 +04:00
|
|
|
* @param {Boolean} visible
|
2012-02-18 22:13:05 +04:00
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
2013-11-22 00:19:07 +04:00
|
|
|
* @fires OpenSeadragon.Viewer.event:visible
|
2012-02-01 00:59:09 +04:00
|
|
|
*/
|
2011-12-08 06:10:13 +04:00
|
|
|
setVisible: function( visible ){
|
|
|
|
this.container.style.visibility = visible ? "" : "hidden";
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-22 00:19:07 +04:00
|
|
|
* Raised when the viewer is shown or hidden (see {@link OpenSeadragon.Viewer#setVisible}).
|
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event visible
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {Boolean} visible
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-10-11 04:00:15 +04:00
|
|
|
this.raiseEvent( 'visible', { visible: visible } );
|
2012-02-18 22:13:05 +04:00
|
|
|
return this;
|
2012-04-11 01:02:24 +04:00
|
|
|
},
|
|
|
|
|
2013-12-01 02:28:17 +04:00
|
|
|
/**
|
2013-12-09 18:26:36 +04:00
|
|
|
* Add a layer.
|
|
|
|
* options.tileSource can be anything that {@link OpenSeadragon.Viewer#open}
|
2014-01-22 04:24:47 +04:00
|
|
|
* supports except arrays of images as layers cannot be sequences.
|
2013-12-01 02:28:17 +04:00
|
|
|
* @function
|
2013-12-09 18:26:36 +04:00
|
|
|
* @param {Object} options
|
2014-03-20 17:56:12 +04:00
|
|
|
* @param {String|Object|Function} options.tileSource The TileSource of the layer.
|
2013-12-09 18:26:36 +04:00
|
|
|
* @param {Number} [options.opacity=1] The opacity of the layer.
|
2014-03-20 17:56:12 +04:00
|
|
|
* @param {Number} [options.level] The level of the layer. Added on top of
|
|
|
|
* all other layers if not specified.
|
2013-12-09 18:26:36 +04:00
|
|
|
* @returns {OpenSeadragon.Viewer} Chainable.
|
|
|
|
* @fires OpenSeadragon.Viewer.event:add-layer
|
|
|
|
* @fires OpenSeadragon.Viewer.event:add-layer-failed
|
2013-12-01 02:28:17 +04:00
|
|
|
*/
|
2013-12-09 18:26:36 +04:00
|
|
|
addLayer: function( options ) {
|
|
|
|
var _this = this,
|
|
|
|
tileSource = options.tileSource;
|
|
|
|
|
2014-01-22 04:24:47 +04:00
|
|
|
if ( !this.isOpen() ) {
|
|
|
|
throw new Error( "An image must be loaded before adding layers." );
|
|
|
|
}
|
2013-12-09 18:26:36 +04:00
|
|
|
if ( !tileSource ) {
|
|
|
|
throw new Error( "No tile source provided as new layer." );
|
|
|
|
}
|
2014-01-12 04:25:27 +04:00
|
|
|
if ( this.collectionMode ) {
|
|
|
|
throw new Error( "Layers not supported in collection mode." );
|
|
|
|
}
|
2013-12-09 18:26:36 +04:00
|
|
|
|
2014-01-12 04:15:28 +04:00
|
|
|
function raiseAddLayerFailed( event ) {
|
|
|
|
/**
|
|
|
|
* Raised when an error occurs while adding a layer.
|
|
|
|
* @event add-layer-failed
|
|
|
|
* @memberOf OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {String} message
|
|
|
|
* @property {String} source
|
|
|
|
* @property {Object} options The options passed to the addLayer method.
|
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
|
|
|
*/
|
|
|
|
_this.raiseEvent( 'add-layer-failed', event );
|
|
|
|
}
|
|
|
|
|
2013-12-09 18:26:36 +04:00
|
|
|
getTileSourceImplementation( this, tileSource, function( tileSource ) {
|
2014-01-12 04:15:28 +04:00
|
|
|
|
|
|
|
if ( tileSource instanceof Array ) {
|
|
|
|
raiseAddLayerFailed({
|
2014-01-22 04:24:47 +04:00
|
|
|
message: "Sequences can not be added as layers.",
|
2014-01-12 04:15:28 +04:00
|
|
|
source: tileSource,
|
|
|
|
options: options
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-31 01:43:35 +04:00
|
|
|
for ( var i = 0; i < _this.drawers.length; i++ ) {
|
|
|
|
var otherAspectRatio = _this.drawers[ i ].source.aspectRatio;
|
|
|
|
var diff = otherAspectRatio - tileSource.aspectRatio;
|
|
|
|
if ( Math.abs( diff ) > _this.layersAspectRatioEpsilon ) {
|
|
|
|
raiseAddLayerFailed({
|
|
|
|
message: "Aspect ratio mismatch with layer " + i + ".",
|
|
|
|
source: tileSource,
|
|
|
|
options: options
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-09 18:26:36 +04:00
|
|
|
var drawer = new $.Drawer({
|
|
|
|
viewer: _this,
|
|
|
|
source: tileSource,
|
|
|
|
viewport: _this.viewport,
|
2014-03-20 17:56:12 +04:00
|
|
|
element: _this.drawersContainer,
|
2013-12-09 18:26:36 +04:00
|
|
|
opacity: options.opacity !== undefined ?
|
|
|
|
options.opacity : _this.opacity,
|
|
|
|
maxImageCacheCount: _this.maxImageCacheCount,
|
|
|
|
imageLoaderLimit: _this.imageLoaderLimit,
|
|
|
|
minZoomImageRatio: _this.minZoomImageRatio,
|
|
|
|
wrapHorizontal: _this.wrapHorizontal,
|
|
|
|
wrapVertical: _this.wrapVertical,
|
|
|
|
immediateRender: _this.immediateRender,
|
|
|
|
blendTime: _this.blendTime,
|
|
|
|
alwaysBlend: _this.alwaysBlend,
|
|
|
|
minPixelRatio: _this.minPixelRatio,
|
|
|
|
timeout: _this.timeout,
|
|
|
|
debugMode: _this.debugMode,
|
|
|
|
debugGridColor: _this.debugGridColor
|
|
|
|
});
|
|
|
|
_this.drawers.push( drawer );
|
2014-01-22 04:24:47 +04:00
|
|
|
if ( options.level !== undefined ) {
|
2013-12-09 18:26:36 +04:00
|
|
|
_this.setLayerLevel( drawer, options.level );
|
|
|
|
}
|
|
|
|
THIS[ _this.hash ].forceRedraw = true;
|
|
|
|
/**
|
|
|
|
* Raised when a layer is successfully added.
|
|
|
|
* @event add-layer
|
|
|
|
* @memberOf OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
2014-01-06 04:20:45 +04:00
|
|
|
* @property {Object} options The options passed to the addLayer method.
|
2013-12-09 18:26:36 +04:00
|
|
|
* @property {OpenSeadragon.Drawer} drawer The layer's underlying drawer.
|
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
|
|
|
*/
|
2014-01-06 04:20:45 +04:00
|
|
|
_this.raiseEvent( 'add-layer', {
|
|
|
|
options: options,
|
|
|
|
drawer: drawer
|
|
|
|
});
|
2013-12-09 18:26:36 +04:00
|
|
|
}, function( event ) {
|
2014-01-06 04:20:45 +04:00
|
|
|
event.options = options;
|
2014-01-12 04:15:28 +04:00
|
|
|
raiseAddLayerFailed(event);
|
2013-12-09 18:26:36 +04:00
|
|
|
} );
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
2014-01-12 03:08:04 +04:00
|
|
|
/**
|
|
|
|
* Get the layer at the specified level.
|
|
|
|
* @param {Number} level The layer to retrieve level.
|
|
|
|
* @returns {OpenSeadragon.Drawer} The layer at the specified level.
|
|
|
|
*/
|
|
|
|
getLayerAtLevel: function( level ) {
|
|
|
|
if ( level >= this.drawers.length ) {
|
|
|
|
throw new Error( "Level bigger than number of layers." );
|
|
|
|
}
|
|
|
|
return this.drawers[ level ];
|
|
|
|
},
|
|
|
|
|
2013-12-09 18:26:36 +04:00
|
|
|
/**
|
|
|
|
* Get the level of the layer associated with the given drawer or -1 if not
|
|
|
|
* present.
|
|
|
|
* @param {OpenSeadragon.Drawer} drawer The underlying drawer of the layer.
|
|
|
|
* @returns {Number} The level of the layer or -1 if not present.
|
|
|
|
*/
|
2014-01-12 03:08:04 +04:00
|
|
|
getLevelOfLayer: function( drawer ) {
|
2013-12-11 04:22:15 +04:00
|
|
|
return $.indexOf( this.drawers, drawer );
|
2013-12-09 18:26:36 +04:00
|
|
|
},
|
|
|
|
|
2014-01-11 21:52:44 +04:00
|
|
|
/**
|
|
|
|
* Get the number of layers used.
|
|
|
|
* @returns {Number} The number of layers used.
|
|
|
|
*/
|
2014-01-22 04:24:47 +04:00
|
|
|
getLayersCount: function() {
|
|
|
|
return this.drawers.length;
|
2014-01-11 21:52:44 +04:00
|
|
|
},
|
|
|
|
|
2013-12-09 18:26:36 +04:00
|
|
|
/**
|
|
|
|
* Change the level of a layer so that it appears over or under others.
|
|
|
|
* @param {OpenSeadragon.Drawer} drawer The underlying drawer of the changing
|
|
|
|
* level layer.
|
|
|
|
* @param {Number} level The new level
|
|
|
|
* @returns {OpenSeadragon.Viewer} Chainable.
|
2013-12-11 04:22:15 +04:00
|
|
|
* @fires OpenSeadragon.Viewer.event:layer-level-changed
|
2013-12-09 18:26:36 +04:00
|
|
|
*/
|
|
|
|
setLayerLevel: function( drawer, level ) {
|
2014-01-12 03:08:04 +04:00
|
|
|
var oldLevel = this.getLevelOfLayer( drawer );
|
2014-01-22 04:24:47 +04:00
|
|
|
|
2013-12-11 04:22:15 +04:00
|
|
|
if ( level >= this.drawers.length ) {
|
2013-12-09 18:26:36 +04:00
|
|
|
throw new Error( "Level bigger than number of layers." );
|
|
|
|
}
|
|
|
|
if ( level === oldLevel || oldLevel === -1 ) {
|
|
|
|
return this;
|
|
|
|
}
|
2014-01-22 04:24:47 +04:00
|
|
|
if ( level === 0 || oldLevel === 0 ) {
|
|
|
|
if ( THIS[ this.hash ].sequenced ) {
|
|
|
|
throw new Error( "Cannot reassign base level when in sequence mode." );
|
|
|
|
}
|
2014-01-31 01:59:51 +04:00
|
|
|
// We need to re-assign the base drawer and the source
|
2014-01-22 04:24:47 +04:00
|
|
|
this.drawer = level === 0 ? drawer : this.getLayerAtLevel( level );
|
2014-01-31 01:59:51 +04:00
|
|
|
this.source = this.drawer.source;
|
2014-01-22 04:24:47 +04:00
|
|
|
}
|
2013-12-09 18:26:36 +04:00
|
|
|
this.drawers.splice( oldLevel, 1 );
|
|
|
|
this.drawers.splice( level, 0, drawer );
|
2014-03-20 17:56:12 +04:00
|
|
|
this.drawersContainer.removeChild( drawer.canvas );
|
2014-01-22 04:24:47 +04:00
|
|
|
if ( level === 0 ) {
|
|
|
|
var nextLevelCanvas = this.drawers[ 1 ].canvas;
|
|
|
|
nextLevelCanvas.parentNode.insertBefore( drawer.canvas,
|
|
|
|
nextLevelCanvas );
|
|
|
|
} else {
|
|
|
|
// Insert right after layer at level - 1
|
|
|
|
var prevLevelCanvas = this.drawers[level - 1].canvas;
|
|
|
|
prevLevelCanvas.parentNode.insertBefore( drawer.canvas,
|
|
|
|
prevLevelCanvas.nextSibling );
|
|
|
|
}
|
2013-12-11 04:22:15 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Raised when the order of the layers has been changed.
|
|
|
|
* @event layer-level-changed
|
|
|
|
* @memberOf OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {OpenSeadragon.Drawer} drawer - The drawer which level has
|
|
|
|
* been changed
|
|
|
|
* @property {Number} previousLevel - The previous level of the drawer
|
|
|
|
* @property {Number} newLevel - The new level of the drawer
|
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
|
|
|
*/
|
|
|
|
this.raiseEvent( 'layer-level-changed', {
|
|
|
|
drawer: drawer,
|
|
|
|
previousLevel: oldLevel,
|
|
|
|
newLevel: level
|
|
|
|
} );
|
|
|
|
|
2013-12-09 18:26:36 +04:00
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2014-01-22 20:33:59 +04:00
|
|
|
* Remove a layer. If there is only one layer, close the viewer.
|
2013-12-09 18:26:36 +04:00
|
|
|
* @function
|
|
|
|
* @param {OpenSeadragon.Drawer} drawer The underlying drawer of the layer
|
|
|
|
* to remove
|
|
|
|
* @returns {OpenSeadragon.Viewer} Chainable.
|
|
|
|
* @fires OpenSeadragon.Viewer.event:remove-layer
|
|
|
|
*/
|
|
|
|
removeLayer: function( drawer ) {
|
|
|
|
var index = this.drawers.indexOf( drawer );
|
|
|
|
if ( index === -1 ) {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
if ( index === 0 ) {
|
2014-01-22 20:33:59 +04:00
|
|
|
if ( THIS[ this.hash ].sequenced ) {
|
|
|
|
throw new Error( "Cannot remove base layer when in sequence mode." );
|
|
|
|
}
|
|
|
|
if ( this.drawers.length === 1 ) {
|
|
|
|
this.close();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
this.drawer = this.drawers[ 1 ];
|
2013-12-09 18:26:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
this.drawers.splice( index, 1 );
|
2014-03-20 17:56:12 +04:00
|
|
|
this.drawersContainer.removeChild( drawer.canvas );
|
2013-12-09 18:26:36 +04:00
|
|
|
/**
|
|
|
|
* Raised when a layer is removed.
|
|
|
|
* @event remove-layer
|
|
|
|
* @memberOf OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {OpenSeadragon.Drawer} drawer The layer's underlying drawer.
|
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
|
|
|
*/
|
|
|
|
this.raiseEvent( 'remove-layer', { drawer: drawer } );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Force the viewer to redraw its drawers.
|
|
|
|
* @returns {OpenSeadragon.Viewer} Chainable.
|
|
|
|
*/
|
|
|
|
forceRedraw: function() {
|
|
|
|
THIS[ this.hash ].forceRedraw = true;
|
|
|
|
return this;
|
2013-12-01 02:28:17 +04:00
|
|
|
},
|
2013-02-14 04:44:23 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @function
|
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
|
|
|
*/
|
2012-04-11 01:02:24 +04:00
|
|
|
bindSequenceControls: function(){
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2012-04-11 01:02:24 +04:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Image Sequence Controls
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
var onFocusHandler = $.delegate( this, onFocus ),
|
|
|
|
onBlurHandler = $.delegate( this, onBlur ),
|
|
|
|
onNextHandler = $.delegate( this, onNext ),
|
|
|
|
onPreviousHandler = $.delegate( this, onPrevious ),
|
|
|
|
navImages = this.navImages,
|
|
|
|
useGroup = true ;
|
|
|
|
|
|
|
|
if( this.showSequenceControl && THIS[ this.hash ].sequenced ){
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2012-04-11 01:02:24 +04:00
|
|
|
if( this.previousButton || this.nextButton ){
|
2013-06-19 21:33:25 +04:00
|
|
|
//if we are binding to custom buttons then layout and
|
2012-04-11 01:02:24 +04:00
|
|
|
//grouping is the responsibility of the page author
|
|
|
|
useGroup = false;
|
|
|
|
}
|
|
|
|
|
2013-06-19 21:33:25 +04:00
|
|
|
this.previousButton = new $.Button({
|
2012-04-11 01:02:24 +04:00
|
|
|
element: this.previousButton ? $.getElement( this.previousButton ) : null,
|
|
|
|
clickTimeThreshold: this.clickTimeThreshold,
|
|
|
|
clickDistThreshold: this.clickDistThreshold,
|
|
|
|
tooltip: $.getString( "Tooltips.PreviousPage" ),
|
|
|
|
srcRest: resolveUrl( this.prefixUrl, navImages.previous.REST ),
|
|
|
|
srcGroup: resolveUrl( this.prefixUrl, navImages.previous.GROUP ),
|
|
|
|
srcHover: resolveUrl( this.prefixUrl, navImages.previous.HOVER ),
|
|
|
|
srcDown: resolveUrl( this.prefixUrl, navImages.previous.DOWN ),
|
|
|
|
onRelease: onPreviousHandler,
|
|
|
|
onFocus: onFocusHandler,
|
|
|
|
onBlur: onBlurHandler
|
|
|
|
});
|
|
|
|
|
2013-06-19 21:33:25 +04:00
|
|
|
this.nextButton = new $.Button({
|
2012-04-11 01:02:24 +04:00
|
|
|
element: this.nextButton ? $.getElement( this.nextButton ) : null,
|
|
|
|
clickTimeThreshold: this.clickTimeThreshold,
|
|
|
|
clickDistThreshold: this.clickDistThreshold,
|
|
|
|
tooltip: $.getString( "Tooltips.NextPage" ),
|
|
|
|
srcRest: resolveUrl( this.prefixUrl, navImages.next.REST ),
|
|
|
|
srcGroup: resolveUrl( this.prefixUrl, navImages.next.GROUP ),
|
|
|
|
srcHover: resolveUrl( this.prefixUrl, navImages.next.HOVER ),
|
|
|
|
srcDown: resolveUrl( this.prefixUrl, navImages.next.DOWN ),
|
|
|
|
onRelease: onNextHandler,
|
|
|
|
onFocus: onFocusHandler,
|
|
|
|
onBlur: onBlurHandler
|
|
|
|
});
|
|
|
|
|
2013-06-19 01:19:09 +04:00
|
|
|
if( !this.navPrevNextWrap ){
|
|
|
|
this.previousButton.disable();
|
|
|
|
}
|
2012-04-11 01:02:24 +04:00
|
|
|
|
|
|
|
if( useGroup ){
|
|
|
|
this.paging = new $.ButtonGroup({
|
2013-06-19 21:33:25 +04:00
|
|
|
buttons: [
|
|
|
|
this.previousButton,
|
|
|
|
this.nextButton
|
2012-04-11 01:02:24 +04:00
|
|
|
],
|
|
|
|
clickTimeThreshold: this.clickTimeThreshold,
|
|
|
|
clickDistThreshold: this.clickDistThreshold
|
|
|
|
});
|
|
|
|
|
|
|
|
this.pagingControl = this.paging.element;
|
|
|
|
|
|
|
|
if( this.toolbar ){
|
2013-06-19 21:33:25 +04:00
|
|
|
this.toolbar.addControl(
|
|
|
|
this.pagingControl,
|
2013-03-15 18:59:47 +04:00
|
|
|
{anchor: $.ControlAnchor.BOTTOM_RIGHT}
|
2012-04-11 01:02:24 +04:00
|
|
|
);
|
|
|
|
}else{
|
2013-06-19 21:33:25 +04:00
|
|
|
this.addControl(
|
|
|
|
this.pagingControl,
|
2013-12-09 22:04:39 +04:00
|
|
|
{anchor: this.sequenceControlAnchor || $.ControlAnchor.TOP_LEFT}
|
2012-04-11 01:02:24 +04:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-02-14 04:44:23 +04:00
|
|
|
return this;
|
2012-04-11 01:02:24 +04:00
|
|
|
},
|
|
|
|
|
2013-02-14 04:44:23 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @function
|
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
|
|
|
*/
|
2012-04-11 01:02:24 +04:00
|
|
|
bindStandardControls: function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Navigation Controls
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
var beginZoomingInHandler = $.delegate( this, beginZoomingIn ),
|
|
|
|
endZoomingHandler = $.delegate( this, endZooming ),
|
|
|
|
doSingleZoomInHandler = $.delegate( this, doSingleZoomIn ),
|
|
|
|
beginZoomingOutHandler = $.delegate( this, beginZoomingOut ),
|
|
|
|
doSingleZoomOutHandler = $.delegate( this, doSingleZoomOut ),
|
|
|
|
onHomeHandler = $.delegate( this, onHome ),
|
2013-11-08 22:56:13 +04:00
|
|
|
onFullScreenHandler = $.delegate( this, onFullScreen ),
|
2014-02-21 00:57:39 +04:00
|
|
|
onRotateLeftHandler = $.delegate( this, onRotateLeft ),
|
|
|
|
onRotateRightHandler = $.delegate( this, onRotateRight ),
|
2012-04-11 01:02:24 +04:00
|
|
|
onFocusHandler = $.delegate( this, onFocus ),
|
|
|
|
onBlurHandler = $.delegate( this, onBlur ),
|
|
|
|
navImages = this.navImages,
|
|
|
|
buttons = [],
|
|
|
|
useGroup = true ;
|
|
|
|
|
|
|
|
|
2014-04-07 22:11:33 +04:00
|
|
|
if ( this.showNavigationControl ) {
|
2012-04-11 01:02:24 +04:00
|
|
|
|
2014-04-07 22:11:33 +04:00
|
|
|
if( this.zoomInButton || this.zoomOutButton ||
|
|
|
|
this.homeButton || this.fullPageButton ||
|
|
|
|
this.rotateLeftButton || this.rotateRightButton ) {
|
2013-06-19 21:33:25 +04:00
|
|
|
//if we are binding to custom buttons then layout and
|
2012-04-11 01:02:24 +04:00
|
|
|
//grouping is the responsibility of the page author
|
|
|
|
useGroup = false;
|
|
|
|
}
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2014-04-07 22:11:33 +04:00
|
|
|
if ( this.showZoomControl ) {
|
|
|
|
buttons.push( this.zoomInButton = new $.Button({
|
|
|
|
element: this.zoomInButton ? $.getElement( this.zoomInButton ) : null,
|
|
|
|
clickTimeThreshold: this.clickTimeThreshold,
|
|
|
|
clickDistThreshold: this.clickDistThreshold,
|
|
|
|
tooltip: $.getString( "Tooltips.ZoomIn" ),
|
|
|
|
srcRest: resolveUrl( this.prefixUrl, navImages.zoomIn.REST ),
|
|
|
|
srcGroup: resolveUrl( this.prefixUrl, navImages.zoomIn.GROUP ),
|
|
|
|
srcHover: resolveUrl( this.prefixUrl, navImages.zoomIn.HOVER ),
|
|
|
|
srcDown: resolveUrl( this.prefixUrl, navImages.zoomIn.DOWN ),
|
|
|
|
onPress: beginZoomingInHandler,
|
|
|
|
onRelease: endZoomingHandler,
|
|
|
|
onClick: doSingleZoomInHandler,
|
|
|
|
onEnter: beginZoomingInHandler,
|
|
|
|
onExit: endZoomingHandler,
|
|
|
|
onFocus: onFocusHandler,
|
|
|
|
onBlur: onBlurHandler
|
|
|
|
}));
|
2012-04-11 01:02:24 +04:00
|
|
|
|
2014-04-07 22:11:33 +04:00
|
|
|
buttons.push( this.zoomOutButton = new $.Button({
|
|
|
|
element: this.zoomOutButton ? $.getElement( this.zoomOutButton ) : null,
|
|
|
|
clickTimeThreshold: this.clickTimeThreshold,
|
|
|
|
clickDistThreshold: this.clickDistThreshold,
|
|
|
|
tooltip: $.getString( "Tooltips.ZoomOut" ),
|
|
|
|
srcRest: resolveUrl( this.prefixUrl, navImages.zoomOut.REST ),
|
|
|
|
srcGroup: resolveUrl( this.prefixUrl, navImages.zoomOut.GROUP ),
|
|
|
|
srcHover: resolveUrl( this.prefixUrl, navImages.zoomOut.HOVER ),
|
|
|
|
srcDown: resolveUrl( this.prefixUrl, navImages.zoomOut.DOWN ),
|
|
|
|
onPress: beginZoomingOutHandler,
|
|
|
|
onRelease: endZoomingHandler,
|
|
|
|
onClick: doSingleZoomOutHandler,
|
|
|
|
onEnter: beginZoomingOutHandler,
|
|
|
|
onExit: endZoomingHandler,
|
|
|
|
onFocus: onFocusHandler,
|
|
|
|
onBlur: onBlurHandler
|
|
|
|
}));
|
|
|
|
}
|
2012-04-11 01:02:24 +04:00
|
|
|
|
2014-04-07 22:11:33 +04:00
|
|
|
if ( this.showHomeControl ) {
|
|
|
|
buttons.push( this.homeButton = new $.Button({
|
|
|
|
element: this.homeButton ? $.getElement( this.homeButton ) : null,
|
|
|
|
clickTimeThreshold: this.clickTimeThreshold,
|
|
|
|
clickDistThreshold: this.clickDistThreshold,
|
|
|
|
tooltip: $.getString( "Tooltips.Home" ),
|
|
|
|
srcRest: resolveUrl( this.prefixUrl, navImages.home.REST ),
|
|
|
|
srcGroup: resolveUrl( this.prefixUrl, navImages.home.GROUP ),
|
|
|
|
srcHover: resolveUrl( this.prefixUrl, navImages.home.HOVER ),
|
|
|
|
srcDown: resolveUrl( this.prefixUrl, navImages.home.DOWN ),
|
|
|
|
onRelease: onHomeHandler,
|
|
|
|
onFocus: onFocusHandler,
|
|
|
|
onBlur: onBlurHandler
|
|
|
|
}));
|
|
|
|
}
|
2012-04-11 01:02:24 +04:00
|
|
|
|
2014-04-07 22:11:33 +04:00
|
|
|
if ( this.showFullPageControl ) {
|
|
|
|
buttons.push( this.fullPageButton = new $.Button({
|
|
|
|
element: this.fullPageButton ? $.getElement( this.fullPageButton ) : null,
|
|
|
|
clickTimeThreshold: this.clickTimeThreshold,
|
|
|
|
clickDistThreshold: this.clickDistThreshold,
|
|
|
|
tooltip: $.getString( "Tooltips.FullPage" ),
|
|
|
|
srcRest: resolveUrl( this.prefixUrl, navImages.fullpage.REST ),
|
|
|
|
srcGroup: resolveUrl( this.prefixUrl, navImages.fullpage.GROUP ),
|
|
|
|
srcHover: resolveUrl( this.prefixUrl, navImages.fullpage.HOVER ),
|
|
|
|
srcDown: resolveUrl( this.prefixUrl, navImages.fullpage.DOWN ),
|
|
|
|
onRelease: onFullScreenHandler,
|
|
|
|
onFocus: onFocusHandler,
|
|
|
|
onBlur: onBlurHandler
|
|
|
|
}));
|
|
|
|
}
|
2012-04-11 01:02:24 +04:00
|
|
|
|
2014-04-07 22:11:33 +04:00
|
|
|
if ( this.showRotationControl ) {
|
|
|
|
buttons.push( this.rotateLeftButton = new $.Button({
|
2014-03-03 20:28:28 +04:00
|
|
|
element: this.rotateLeftButton ? $.getElement( this.rotateLeftButton ) : null,
|
|
|
|
clickTimeThreshold: this.clickTimeThreshold,
|
|
|
|
clickDistThreshold: this.clickDistThreshold,
|
|
|
|
tooltip: $.getString( "Tooltips.RotateLeft" ),
|
|
|
|
srcRest: resolveUrl( this.prefixUrl, navImages.rotateleft.REST ),
|
|
|
|
srcGroup: resolveUrl( this.prefixUrl, navImages.rotateleft.GROUP ),
|
|
|
|
srcHover: resolveUrl( this.prefixUrl, navImages.rotateleft.HOVER ),
|
|
|
|
srcDown: resolveUrl( this.prefixUrl, navImages.rotateleft.DOWN ),
|
|
|
|
onRelease: onRotateLeftHandler,
|
|
|
|
onFocus: onFocusHandler,
|
|
|
|
onBlur: onBlurHandler
|
|
|
|
}));
|
|
|
|
|
2014-04-07 22:11:33 +04:00
|
|
|
buttons.push( this.rotateRightButton = new $.Button({
|
2014-03-03 20:28:28 +04:00
|
|
|
element: this.rotateRightButton ? $.getElement( this.rotateRightButton ) : null,
|
|
|
|
clickTimeThreshold: this.clickTimeThreshold,
|
|
|
|
clickDistThreshold: this.clickDistThreshold,
|
|
|
|
tooltip: $.getString( "Tooltips.RotateRight" ),
|
|
|
|
srcRest: resolveUrl( this.prefixUrl, navImages.rotateright.REST ),
|
|
|
|
srcGroup: resolveUrl( this.prefixUrl, navImages.rotateright.GROUP ),
|
|
|
|
srcHover: resolveUrl( this.prefixUrl, navImages.rotateright.HOVER ),
|
|
|
|
srcDown: resolveUrl( this.prefixUrl, navImages.rotateright.DOWN ),
|
|
|
|
onRelease: onRotateRightHandler,
|
|
|
|
onFocus: onFocusHandler,
|
|
|
|
onBlur: onBlurHandler
|
|
|
|
}));
|
2014-02-21 00:57:39 +04:00
|
|
|
|
2014-03-03 20:28:28 +04:00
|
|
|
}
|
2014-02-21 00:57:39 +04:00
|
|
|
|
2014-04-07 22:11:33 +04:00
|
|
|
if ( useGroup ) {
|
2012-04-11 01:02:24 +04:00
|
|
|
this.buttons = new $.ButtonGroup({
|
|
|
|
buttons: buttons,
|
|
|
|
clickTimeThreshold: this.clickTimeThreshold,
|
|
|
|
clickDistThreshold: this.clickDistThreshold
|
|
|
|
});
|
|
|
|
|
|
|
|
this.navControl = this.buttons.element;
|
|
|
|
this.addHandler( 'open', $.delegate( this, lightUp ) );
|
|
|
|
|
|
|
|
if( this.toolbar ){
|
2013-06-19 21:33:25 +04:00
|
|
|
this.toolbar.addControl(
|
|
|
|
this.navControl,
|
2013-03-15 18:59:47 +04:00
|
|
|
{anchor: $.ControlAnchor.TOP_LEFT}
|
2012-04-11 01:02:24 +04:00
|
|
|
);
|
2014-04-07 22:11:33 +04:00
|
|
|
} else {
|
2013-06-19 21:33:25 +04:00
|
|
|
this.addControl(
|
|
|
|
this.navControl,
|
2013-12-09 22:04:39 +04:00
|
|
|
{anchor: this.navigationControlAnchor || $.ControlAnchor.TOP_LEFT}
|
2012-04-11 01:02:24 +04:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2012-06-05 15:52:00 +04:00
|
|
|
}
|
2013-02-14 04:44:23 +04:00
|
|
|
return this;
|
2012-06-05 15:52:00 +04:00
|
|
|
},
|
2013-10-09 02:01:28 +04:00
|
|
|
|
2013-10-10 23:25:11 +04:00
|
|
|
/**
|
2013-10-10 23:27:49 +04:00
|
|
|
* Gets the active page of a sequence
|
2013-10-10 23:25:11 +04:00
|
|
|
* @function
|
|
|
|
* @return {Number}
|
|
|
|
*/
|
2014-04-07 22:11:33 +04:00
|
|
|
currentPage: function() {
|
2013-10-10 02:36:21 +04:00
|
|
|
return THIS[ this.hash ].sequence;
|
2014-04-07 22:11:33 +04:00
|
|
|
},
|
2013-10-09 04:07:49 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @function
|
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
2013-11-22 00:19:07 +04:00
|
|
|
* @fires OpenSeadragon.Viewer.event:page
|
2013-10-09 04:07:49 +04:00
|
|
|
*/
|
|
|
|
goToPage: function( page ){
|
2013-11-20 00:13:38 +04:00
|
|
|
if( page >= 0 && page < this.tileSources.length ){
|
|
|
|
/**
|
2013-11-22 00:19:07 +04:00
|
|
|
* Raised when the page is changed on a viewer configured with multiple image sources (see {@link OpenSeadragon.Viewer#goToPage}).
|
2013-11-20 00:13:38 +04:00
|
|
|
*
|
|
|
|
* @event page
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {Object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {Number} page - The page index.
|
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
|
|
|
*/
|
|
|
|
this.raiseEvent( 'page', { page: page } );
|
2013-10-09 04:07:49 +04:00
|
|
|
|
|
|
|
THIS[ this.hash ].sequence = page;
|
|
|
|
|
2013-10-10 23:25:11 +04:00
|
|
|
this._updateSequenceButtons( page );
|
2012-06-05 15:52:00 +04:00
|
|
|
|
2013-03-26 17:02:34 +04:00
|
|
|
this.open( this.tileSources[ page ] );
|
2013-02-14 04:44:23 +04:00
|
|
|
|
2013-11-20 00:13:38 +04:00
|
|
|
if( this.referenceStrip ){
|
|
|
|
this.referenceStrip.setFocus( page );
|
|
|
|
}
|
2012-10-13 07:40:59 +04:00
|
|
|
}
|
2013-11-20 00:13:38 +04:00
|
|
|
|
2013-02-14 04:44:23 +04:00
|
|
|
return this;
|
2013-06-28 23:46:31 +04:00
|
|
|
},
|
2011-12-06 07:50:25 +04:00
|
|
|
|
2014-01-31 00:38:37 +04:00
|
|
|
/**
|
|
|
|
* Adds an html element as an overlay to the current viewport. Useful for
|
|
|
|
* highlighting words or areas of interest on an image or other zoomable
|
2014-03-15 19:20:33 +04:00
|
|
|
* interface. The overlays added via this method are removed when the viewport
|
|
|
|
* is closed which include when changing page.
|
2014-01-31 00:38:37 +04:00
|
|
|
* @method
|
|
|
|
* @param {Element|String|Object} element - A reference to an element or an id for
|
|
|
|
* the element which will overlayed. Or an Object specifying the configuration for the overlay
|
|
|
|
* @param {OpenSeadragon.Point|OpenSeadragon.Rect} location - The point or
|
|
|
|
* rectangle which will be overlayed.
|
|
|
|
* @param {OpenSeadragon.OverlayPlacement} placement - The position of the
|
|
|
|
* viewport which the location coordinates will be treated as relative
|
|
|
|
* to.
|
|
|
|
* @param {function} onDraw - If supplied the callback is called when the overlay
|
|
|
|
* needs to be drawn. It it the responsibility of the callback to do any drawing/positioning.
|
|
|
|
* It is passed position, size and element.
|
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
|
|
|
* @fires OpenSeadragon.Viewer.event:add-overlay
|
|
|
|
*/
|
|
|
|
addOverlay: function( element, location, placement, onDraw ) {
|
|
|
|
var options;
|
|
|
|
if( $.isPlainObject( element ) ){
|
|
|
|
options = element;
|
|
|
|
} else {
|
|
|
|
options = {
|
|
|
|
element: element,
|
|
|
|
location: location,
|
|
|
|
placement: placement,
|
|
|
|
onDraw: onDraw
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2014-03-15 19:20:33 +04:00
|
|
|
element = $.getElement( options.element );
|
2014-01-31 00:38:37 +04:00
|
|
|
|
|
|
|
if ( getOverlayIndex( this.currentOverlays, element ) >= 0 ) {
|
|
|
|
// they're trying to add a duplicate overlay
|
|
|
|
return this;
|
|
|
|
}
|
2014-03-15 19:20:33 +04:00
|
|
|
this.currentOverlays.push( getOverlayObject( this, options ) );
|
2014-01-31 00:38:37 +04:00
|
|
|
THIS[ this.hash ].forceRedraw = true;
|
|
|
|
/**
|
|
|
|
* Raised when an overlay is added to the viewer (see {@link OpenSeadragon.Viewer#addOverlay}).
|
|
|
|
*
|
|
|
|
* @event add-overlay
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {Element} element - The overlay element.
|
|
|
|
* @property {OpenSeadragon.Point|OpenSeadragon.Rect} location
|
|
|
|
* @property {OpenSeadragon.OverlayPlacement} placement
|
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
|
|
|
*/
|
|
|
|
this.raiseEvent( 'add-overlay', {
|
|
|
|
element: element,
|
|
|
|
location: options.location,
|
|
|
|
placement: options.placement
|
|
|
|
});
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the overlay represented by the reference to the element or
|
|
|
|
* element id moving it to the new location, relative to the new placement.
|
|
|
|
* @method
|
|
|
|
* @param {OpenSeadragon.Point|OpenSeadragon.Rect} location - The point or
|
|
|
|
* rectangle which will be overlayed.
|
|
|
|
* @param {OpenSeadragon.OverlayPlacement} placement - The position of the
|
|
|
|
* viewport which the location coordinates will be treated as relative
|
|
|
|
* to.
|
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
|
|
|
* @fires OpenSeadragon.Viewer.event:update-overlay
|
|
|
|
*/
|
|
|
|
updateOverlay: function( element, location, placement ) {
|
|
|
|
var i;
|
|
|
|
|
|
|
|
element = $.getElement( element );
|
|
|
|
i = getOverlayIndex( this.currentOverlays, element );
|
|
|
|
|
|
|
|
if ( i >= 0 ) {
|
|
|
|
this.currentOverlays[ i ].update( location, placement );
|
|
|
|
THIS[ this.hash ].forceRedraw = true;
|
|
|
|
/**
|
|
|
|
* Raised when an overlay's location or placement changes
|
|
|
|
* (see {@link OpenSeadragon.Viewer#updateOverlay}).
|
|
|
|
*
|
|
|
|
* @event update-overlay
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the
|
|
|
|
* Viewer which raised the event.
|
|
|
|
* @property {Element} element
|
|
|
|
* @property {OpenSeadragon.Point|OpenSeadragon.Rect} location
|
|
|
|
* @property {OpenSeadragon.OverlayPlacement} placement
|
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
|
|
|
*/
|
|
|
|
this.raiseEvent( 'update-overlay', {
|
|
|
|
element: element,
|
|
|
|
location: location,
|
|
|
|
placement: placement
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes an overlay identified by the reference element or element id
|
|
|
|
* and schedules an update.
|
|
|
|
* @method
|
|
|
|
* @param {Element|String} element - A reference to the element or an
|
|
|
|
* element id which represent the ovelay content to be removed.
|
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
|
|
|
* @fires OpenSeadragon.Viewer.event:remove-overlay
|
|
|
|
*/
|
|
|
|
removeOverlay: function( element ) {
|
|
|
|
var i;
|
|
|
|
|
|
|
|
element = $.getElement( element );
|
|
|
|
i = getOverlayIndex( this.currentOverlays, element );
|
|
|
|
|
|
|
|
if ( i >= 0 ) {
|
|
|
|
this.currentOverlays[ i ].destroy();
|
|
|
|
this.currentOverlays.splice( i, 1 );
|
|
|
|
THIS[ this.hash ].forceRedraw = true;
|
|
|
|
/**
|
|
|
|
* Raised when an overlay is removed from the viewer
|
|
|
|
* (see {@link OpenSeadragon.Viewer#removeOverlay}).
|
|
|
|
*
|
|
|
|
* @event remove-overlay
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the
|
|
|
|
* Viewer which raised the event.
|
|
|
|
* @property {Element} element - The overlay element.
|
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
|
|
|
*/
|
|
|
|
this.raiseEvent( 'remove-overlay', {
|
|
|
|
element: element
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes all currently configured Overlays from this Viewer and schedules
|
|
|
|
* an update.
|
|
|
|
* @method
|
|
|
|
* @return {OpenSeadragon.Viewer} Chainable.
|
|
|
|
* @fires OpenSeadragon.Viewer.event:clear-overlay
|
|
|
|
*/
|
|
|
|
clearOverlays: function() {
|
|
|
|
while ( this.currentOverlays.length > 0 ) {
|
|
|
|
this.currentOverlays.pop().destroy();
|
|
|
|
}
|
|
|
|
THIS[ this.hash ].forceRedraw = true;
|
|
|
|
/**
|
|
|
|
* Raised when all overlays are removed from the viewer (see {@link OpenSeadragon.Drawer#clearOverlays}).
|
|
|
|
*
|
|
|
|
* @event clear-overlay
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
|
|
|
*/
|
|
|
|
this.raiseEvent( 'clear-overlay', {} );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
2013-10-10 23:27:49 +04:00
|
|
|
/**
|
|
|
|
* Updates the sequence buttons.
|
2013-11-16 10:19:53 +04:00
|
|
|
* @function OpenSeadragon.Viewer.prototype._updateSequenceButtons
|
2013-10-10 23:27:49 +04:00
|
|
|
* @private
|
|
|
|
* @param {Number} Sequence Value
|
2013-10-10 23:35:49 +04:00
|
|
|
*/
|
2014-04-07 22:11:33 +04:00
|
|
|
_updateSequenceButtons: function( page ) {
|
2013-10-10 23:27:49 +04:00
|
|
|
|
2014-04-07 22:11:33 +04:00
|
|
|
if ( this.nextButton ) {
|
|
|
|
if( ( this.tileSources.length - 1 ) === page ) {
|
2013-10-10 23:27:49 +04:00
|
|
|
//Disable next button
|
2014-04-07 22:11:33 +04:00
|
|
|
if ( !this.navPrevNextWrap ) {
|
2013-10-10 23:27:49 +04:00
|
|
|
this.nextButton.disable();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this.nextButton.enable();
|
|
|
|
}
|
|
|
|
}
|
2014-04-07 22:11:33 +04:00
|
|
|
if ( this.previousButton ) {
|
|
|
|
if ( page > 0 ) {
|
2013-10-10 23:27:49 +04:00
|
|
|
//Enable previous button
|
|
|
|
this.previousButton.enable();
|
|
|
|
} else {
|
2014-04-07 22:11:33 +04:00
|
|
|
if ( !this.navPrevNextWrap ) {
|
2013-10-10 23:27:49 +04:00
|
|
|
this.previousButton.disable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2013-06-28 23:46:31 +04:00
|
|
|
/**
|
|
|
|
* Display a message in the viewport
|
2013-11-16 10:19:53 +04:00
|
|
|
* @function OpenSeadragon.Viewer.prototype._showMessage
|
2013-07-01 21:43:48 +04:00
|
|
|
* @private
|
2013-06-28 23:46:31 +04:00
|
|
|
* @param {String} text message
|
|
|
|
*/
|
2013-07-01 21:43:48 +04:00
|
|
|
_showMessage: function ( message ) {
|
|
|
|
this._hideMessage();
|
2013-07-01 20:58:22 +04:00
|
|
|
|
2013-07-01 21:43:48 +04:00
|
|
|
var div = $.makeNeutralElement( "div" );
|
2013-06-28 23:46:31 +04:00
|
|
|
div.appendChild( document.createTextNode( message ) );
|
|
|
|
|
2013-07-01 21:43:48 +04:00
|
|
|
this.messageDiv = $.makeCenteredNode( div );
|
|
|
|
|
2013-07-02 02:26:33 +04:00
|
|
|
$.addClass(this.messageDiv, "openseadragon-message");
|
|
|
|
|
2013-07-01 21:43:48 +04:00
|
|
|
this.container.appendChild( this.messageDiv );
|
2013-06-28 23:46:31 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hide any currently displayed viewport message
|
2013-11-16 10:19:53 +04:00
|
|
|
* @function OpenSeadragon.Viewer.prototype._hideMessage
|
2013-07-01 21:43:48 +04:00
|
|
|
* @private
|
2013-06-28 23:46:31 +04:00
|
|
|
*/
|
2013-07-01 21:43:48 +04:00
|
|
|
_hideMessage: function () {
|
2013-06-28 23:46:31 +04:00
|
|
|
var div = this.messageDiv;
|
|
|
|
if (div) {
|
2013-07-01 21:43:48 +04:00
|
|
|
div.parentNode.removeChild(div);
|
2013-06-28 23:46:31 +04:00
|
|
|
delete this.messageDiv;
|
|
|
|
}
|
|
|
|
}
|
2011-12-15 03:22:02 +04:00
|
|
|
});
|
2011-12-06 07:50:25 +04:00
|
|
|
|
2013-07-31 22:00:16 +04:00
|
|
|
|
|
|
|
/**
|
2013-08-02 20:40:55 +04:00
|
|
|
* _getSafeElemSize is like getElementSize(), but refuses to return 0 for x or y,
|
|
|
|
* which was causing some calling operations in updateOnce and openTileSource to
|
2013-08-01 21:11:33 +04:00
|
|
|
* return NaN.
|
2013-08-02 20:40:55 +04:00
|
|
|
* @returns {Point}
|
2013-07-31 22:00:16 +04:00
|
|
|
* @private
|
|
|
|
*/
|
2013-07-31 23:01:46 +04:00
|
|
|
function _getSafeElemSize (oElement) {
|
2013-08-01 21:11:33 +04:00
|
|
|
oElement = $.getElement( oElement );
|
2013-07-31 23:01:46 +04:00
|
|
|
|
2013-08-01 21:11:33 +04:00
|
|
|
return new $.Point(
|
|
|
|
(oElement.clientWidth === 0 ? 1 : oElement.clientWidth),
|
|
|
|
(oElement.clientHeight === 0 ? 1 : oElement.clientHeight)
|
|
|
|
);
|
2013-07-31 22:00:16 +04:00
|
|
|
}
|
|
|
|
|
2013-12-09 18:26:36 +04:00
|
|
|
/**
|
|
|
|
* @function
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
function getTileSourceImplementation( viewer, tileSource, successCallback,
|
2014-01-06 04:20:45 +04:00
|
|
|
failCallback ) {
|
2013-12-09 18:26:36 +04:00
|
|
|
var _this = viewer;
|
|
|
|
|
|
|
|
//allow plain xml strings or json strings to be parsed here
|
|
|
|
if ( $.type( tileSource ) == 'string' ) {
|
|
|
|
if ( tileSource.match( /\s*<.*/ ) ) {
|
|
|
|
tileSource = $.parseXml( tileSource );
|
|
|
|
} else if ( tileSource.match( /\s*[\{\[].*/ ) ) {
|
|
|
|
/*jshint evil:true*/
|
|
|
|
tileSource = eval( '(' + tileSource + ')' );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setTimeout( function() {
|
|
|
|
if ( $.type( tileSource ) == 'string' ) {
|
|
|
|
//If its still a string it means it must be a url at this point
|
|
|
|
tileSource = new $.TileSource( tileSource, function( event ) {
|
|
|
|
successCallback( event.tileSource );
|
|
|
|
});
|
|
|
|
tileSource.addHandler( 'open-failed', function( event ) {
|
|
|
|
failCallback( event );
|
|
|
|
} );
|
|
|
|
|
|
|
|
} else if ( $.isPlainObject( tileSource ) || tileSource.nodeType ) {
|
|
|
|
if ( $.isFunction( tileSource.getTileUrl ) ) {
|
|
|
|
//Custom tile source
|
|
|
|
var customTileSource = new $.TileSource( tileSource );
|
|
|
|
customTileSource.getTileUrl = tileSource.getTileUrl;
|
|
|
|
successCallback( customTileSource );
|
|
|
|
} else {
|
|
|
|
//inline configuration
|
|
|
|
var $TileSource = $.TileSource.determineType( _this, tileSource );
|
|
|
|
if ( !$TileSource ) {
|
|
|
|
failCallback( {
|
|
|
|
message: "Unable to load TileSource",
|
|
|
|
source: tileSource
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var options = $TileSource.prototype.configure.apply( _this, [ tileSource ] );
|
|
|
|
var readySource = new $TileSource( options );
|
|
|
|
successCallback( readySource );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//can assume it's already a tile source implementation
|
|
|
|
successCallback( tileSource );
|
|
|
|
}
|
|
|
|
}, 1 );
|
|
|
|
}
|
|
|
|
|
2013-03-26 17:02:34 +04:00
|
|
|
/**
|
|
|
|
* @function
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
function openTileSource( viewer, source ) {
|
2014-03-18 21:17:43 +04:00
|
|
|
var i,
|
|
|
|
_this = viewer;
|
2013-03-26 17:02:34 +04:00
|
|
|
|
|
|
|
if ( _this.source ) {
|
|
|
|
_this.close( );
|
|
|
|
}
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2013-07-31 22:28:38 +04:00
|
|
|
THIS[ _this.hash ].prevContainerSize = _getSafeElemSize( _this.container );
|
2013-03-26 17:02:34 +04:00
|
|
|
|
|
|
|
|
|
|
|
if( _this.collectionMode ){
|
|
|
|
_this.source = new $.TileSourceCollection({
|
|
|
|
rows: _this.collectionRows,
|
|
|
|
layout: _this.collectionLayout,
|
|
|
|
tileSize: _this.collectionTileSize,
|
|
|
|
tileSources: _this.tileSources,
|
|
|
|
tileMargin: _this.collectionTileMargin
|
|
|
|
});
|
|
|
|
_this.viewport = _this.viewport ? _this.viewport : new $.Viewport({
|
|
|
|
collectionMode: true,
|
|
|
|
collectionTileSource: _this.source,
|
2013-06-19 21:33:25 +04:00
|
|
|
containerSize: THIS[ _this.hash ].prevContainerSize,
|
|
|
|
contentSize: _this.source.dimensions,
|
2013-03-26 17:02:34 +04:00
|
|
|
springStiffness: _this.springStiffness,
|
|
|
|
animationTime: _this.animationTime,
|
|
|
|
showNavigator: false,
|
|
|
|
minZoomImageRatio: 1,
|
|
|
|
maxZoomPixelRatio: 1,
|
2014-02-06 00:52:31 +04:00
|
|
|
viewer: _this,
|
|
|
|
degrees: _this.degrees //,
|
2013-03-26 17:02:34 +04:00
|
|
|
//TODO: figure out how to support these in a way that makes sense
|
|
|
|
//minZoomLevel: this.minZoomLevel,
|
|
|
|
//maxZoomLevel: this.maxZoomLevel
|
|
|
|
});
|
2014-01-31 00:38:37 +04:00
|
|
|
} else {
|
2013-03-26 17:02:34 +04:00
|
|
|
if( source ){
|
|
|
|
_this.source = source;
|
|
|
|
}
|
|
|
|
_this.viewport = _this.viewport ? _this.viewport : new $.Viewport({
|
2013-06-19 21:33:25 +04:00
|
|
|
containerSize: THIS[ _this.hash ].prevContainerSize,
|
|
|
|
contentSize: _this.source.dimensions,
|
2013-03-26 17:02:34 +04:00
|
|
|
springStiffness: _this.springStiffness,
|
|
|
|
animationTime: _this.animationTime,
|
|
|
|
minZoomImageRatio: _this.minZoomImageRatio,
|
|
|
|
maxZoomPixelRatio: _this.maxZoomPixelRatio,
|
|
|
|
visibilityRatio: _this.visibilityRatio,
|
|
|
|
wrapHorizontal: _this.wrapHorizontal,
|
|
|
|
wrapVertical: _this.wrapVertical,
|
|
|
|
defaultZoomLevel: _this.defaultZoomLevel,
|
|
|
|
minZoomLevel: _this.minZoomLevel,
|
|
|
|
maxZoomLevel: _this.maxZoomLevel,
|
2014-02-06 00:52:31 +04:00
|
|
|
viewer: _this,
|
|
|
|
degrees: _this.degrees
|
2013-03-26 17:02:34 +04:00
|
|
|
});
|
|
|
|
}
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2013-04-24 07:58:58 +04:00
|
|
|
if( _this.preserveViewport ){
|
2013-03-26 17:02:34 +04:00
|
|
|
_this.viewport.resetContentSize( _this.source.dimensions );
|
2013-06-19 21:33:25 +04:00
|
|
|
}
|
2013-03-26 17:02:34 +04:00
|
|
|
|
|
|
|
_this.source.overlays = _this.source.overlays || [];
|
|
|
|
|
|
|
|
_this.drawer = new $.Drawer({
|
2013-05-16 10:49:29 +04:00
|
|
|
viewer: _this,
|
2013-06-19 21:33:25 +04:00
|
|
|
source: _this.source,
|
|
|
|
viewport: _this.viewport,
|
2014-03-20 17:56:12 +04:00
|
|
|
element: _this.drawersContainer,
|
2013-12-09 18:26:36 +04:00
|
|
|
opacity: _this.opacity,
|
2013-03-26 17:02:34 +04:00
|
|
|
maxImageCacheCount: _this.maxImageCacheCount,
|
|
|
|
imageLoaderLimit: _this.imageLoaderLimit,
|
|
|
|
minZoomImageRatio: _this.minZoomImageRatio,
|
|
|
|
wrapHorizontal: _this.wrapHorizontal,
|
|
|
|
wrapVertical: _this.wrapVertical,
|
|
|
|
immediateRender: _this.immediateRender,
|
|
|
|
blendTime: _this.blendTime,
|
|
|
|
alwaysBlend: _this.alwaysBlend,
|
|
|
|
minPixelRatio: _this.collectionMode ? 0 : _this.minPixelRatio,
|
|
|
|
timeout: _this.timeout,
|
|
|
|
debugMode: _this.debugMode,
|
2014-03-20 21:30:46 +04:00
|
|
|
debugGridColor: _this.debugGridColor,
|
|
|
|
crossOriginPolicy: _this.crossOriginPolicy
|
2013-03-26 17:02:34 +04:00
|
|
|
});
|
2013-12-09 18:26:36 +04:00
|
|
|
_this.drawers = [_this.drawer];
|
2013-03-26 17:02:34 +04:00
|
|
|
|
2014-03-03 22:14:09 +04:00
|
|
|
// Now that we have a drawer, see if it supports rotate. If not we need to remove the rotate buttons
|
|
|
|
if (!_this.drawer.canRotate()) {
|
|
|
|
// Disable/remove the rotate left/right buttons since they aren't supported
|
|
|
|
if (_this.rotateLeft) {
|
|
|
|
i = _this.buttons.buttons.indexOf(_this.rotateLeft);
|
|
|
|
_this.buttons.buttons.splice(i, 1);
|
|
|
|
_this.buttons.element.removeChild(_this.rotateLeft.element);
|
|
|
|
}
|
|
|
|
if (_this.rotateRight) {
|
|
|
|
i = _this.buttons.buttons.indexOf(_this.rotateRight);
|
|
|
|
_this.buttons.buttons.splice(i, 1);
|
|
|
|
_this.buttons.element.removeChild(_this.rotateRight.element);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-26 17:02:34 +04:00
|
|
|
//Instantiate a navigator if configured
|
2013-06-17 22:51:02 +04:00
|
|
|
if ( _this.showNavigator && !_this.collectionMode ){
|
|
|
|
// Note: By passing the fully parsed source, the navigator doesn't
|
|
|
|
// have to load it again.
|
|
|
|
if ( _this.navigator ) {
|
|
|
|
_this.navigator.open( source );
|
|
|
|
} else {
|
|
|
|
_this.navigator = new $.Navigator({
|
Enhanced Navigator Resizability (#280, #296)
New navigator options:
* @property {Boolean} [showNavigator=false]
* Set to true to make the navigator minimap appear.
*
* @property {Boolean} [navigatorId=navigator-GENERATED DATE]
* The ID of a div to hold the navigator minimap.
* If an ID is specified, the navigatorPosition, navigatorSizeRatio,
navigatorMaintainSizeRatio, and navigatorTop|Left|Height|Width options
will be ignored.
* If an ID is not specified, a div element will be generated and
placed on top of the main image.
*
* @property {String} [navigatorPosition='TOP_RIGHT']
* Valid values are 'TOP_LEFT', 'TOP_RIGHT', 'BOTTOM_LEFT',
'BOTTOM_RIGHT', or 'ABSOLUTE'.<br>
* If 'ABSOLUTE' is specified, then navigatorTop|Left|Height|Width
determines the size and position of the navigator minimap in the viewer,
and navigatorSizeRatio and navigatorMaintainSizeRatio are ignored.<br>
* For 'TOP_LEFT', 'TOP_RIGHT', 'BOTTOM_LEFT', and 'BOTTOM_RIGHT',
the navigatorSizeRatio or navigatorHeight|Width values determine the
size of the navigator minimap.
*
* @property {Number} [navigatorSizeRatio=0.2]
* Ratio of navigator size to viewer size. Ignored if
navigatorHeight|Width are specified.
*
* @property {Boolean} [navigatorMaintainSizeRatio=false]
* If true, the navigator minimap is resized (using
navigatorSizeRatio) when the viewer size changes.
*
* @property {Number|String} [navigatorTop=null]
* Specifies the location of the navigator minimap (see
navigatorPosition).
*
* @property {Number|String} [navigatorLeft=null]
* Specifies the location of the navigator minimap (see
navigatorPosition).
*
* @property {Number|String} [navigatorHeight=null]
* Specifies the size of the navigator minimap (see
navigatorPosition).
* If specified, navigatorSizeRatio and navigatorMaintainSizeRatio
are ignored.
*
* @property {Number|String} [navigatorWidth=null]
* Specifies the size of the navigator minimap (see
navigatorPosition).
* If specified, navigatorSizeRatio and navigatorMaintainSizeRatio
are ignored.
Fixes #280 and #296
2013-12-13 21:23:56 +04:00
|
|
|
id: _this.navigatorId,
|
|
|
|
position: _this.navigatorPosition,
|
|
|
|
sizeRatio: _this.navigatorSizeRatio,
|
|
|
|
maintainSizeRatio: _this.navigatorMaintainSizeRatio,
|
|
|
|
top: _this.navigatorTop,
|
|
|
|
left: _this.navigatorLeft,
|
|
|
|
width: _this.navigatorWidth,
|
|
|
|
height: _this.navigatorHeight,
|
2013-12-15 02:45:11 +04:00
|
|
|
autoResize: _this.navigatorAutoResize,
|
Enhanced Navigator Resizability (#280, #296)
New navigator options:
* @property {Boolean} [showNavigator=false]
* Set to true to make the navigator minimap appear.
*
* @property {Boolean} [navigatorId=navigator-GENERATED DATE]
* The ID of a div to hold the navigator minimap.
* If an ID is specified, the navigatorPosition, navigatorSizeRatio,
navigatorMaintainSizeRatio, and navigatorTop|Left|Height|Width options
will be ignored.
* If an ID is not specified, a div element will be generated and
placed on top of the main image.
*
* @property {String} [navigatorPosition='TOP_RIGHT']
* Valid values are 'TOP_LEFT', 'TOP_RIGHT', 'BOTTOM_LEFT',
'BOTTOM_RIGHT', or 'ABSOLUTE'.<br>
* If 'ABSOLUTE' is specified, then navigatorTop|Left|Height|Width
determines the size and position of the navigator minimap in the viewer,
and navigatorSizeRatio and navigatorMaintainSizeRatio are ignored.<br>
* For 'TOP_LEFT', 'TOP_RIGHT', 'BOTTOM_LEFT', and 'BOTTOM_RIGHT',
the navigatorSizeRatio or navigatorHeight|Width values determine the
size of the navigator minimap.
*
* @property {Number} [navigatorSizeRatio=0.2]
* Ratio of navigator size to viewer size. Ignored if
navigatorHeight|Width are specified.
*
* @property {Boolean} [navigatorMaintainSizeRatio=false]
* If true, the navigator minimap is resized (using
navigatorSizeRatio) when the viewer size changes.
*
* @property {Number|String} [navigatorTop=null]
* Specifies the location of the navigator minimap (see
navigatorPosition).
*
* @property {Number|String} [navigatorLeft=null]
* Specifies the location of the navigator minimap (see
navigatorPosition).
*
* @property {Number|String} [navigatorHeight=null]
* Specifies the size of the navigator minimap (see
navigatorPosition).
* If specified, navigatorSizeRatio and navigatorMaintainSizeRatio
are ignored.
*
* @property {Number|String} [navigatorWidth=null]
* Specifies the size of the navigator minimap (see
navigatorPosition).
* If specified, navigatorSizeRatio and navigatorMaintainSizeRatio
are ignored.
Fixes #280 and #296
2013-12-13 21:23:56 +04:00
|
|
|
tileSources: source,
|
|
|
|
tileHost: _this.tileHost,
|
|
|
|
prefixUrl: _this.prefixUrl,
|
|
|
|
viewer: _this
|
2013-06-17 22:51:02 +04:00
|
|
|
});
|
|
|
|
}
|
2013-03-26 17:02:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
//Instantiate a referencestrip if configured
|
|
|
|
if ( _this.showReferenceStrip && !_this.referenceStrip ){
|
|
|
|
_this.referenceStrip = new $.ReferenceStrip({
|
|
|
|
id: _this.referenceStripElement,
|
|
|
|
position: _this.referenceStripPosition,
|
|
|
|
sizeRatio: _this.referenceStripSizeRatio,
|
|
|
|
scroll: _this.referenceStripScroll,
|
|
|
|
height: _this.referenceStripHeight,
|
|
|
|
width: _this.referenceStripWidth,
|
|
|
|
tileSources: _this.tileSources,
|
|
|
|
tileHost: _this.tileHost,
|
|
|
|
prefixUrl: _this.prefixUrl,
|
|
|
|
viewer: _this
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
//this.profiler = new $.Profiler();
|
|
|
|
|
|
|
|
THIS[ _this.hash ].animating = false;
|
|
|
|
THIS[ _this.hash ].forceRedraw = true;
|
2013-06-18 22:06:43 +04:00
|
|
|
_this._updateRequestId = scheduleUpdate( _this, updateMulti );
|
2013-03-26 17:02:34 +04:00
|
|
|
|
|
|
|
VIEWERS[ _this.hash ] = _this;
|
|
|
|
|
2014-03-15 19:20:33 +04:00
|
|
|
loadOverlays( _this );
|
2014-01-31 00:38:37 +04:00
|
|
|
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-22 00:19:07 +04:00
|
|
|
* Raised when the viewer has opened and loaded one or more TileSources.
|
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event open
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
|
|
|
* @property {OpenSeadragon.TileSource} source
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-10-11 04:00:15 +04:00
|
|
|
_this.raiseEvent( 'open', { source: source } );
|
2013-03-26 17:02:34 +04:00
|
|
|
|
|
|
|
return _this;
|
|
|
|
}
|
|
|
|
|
2014-03-15 19:20:33 +04:00
|
|
|
function loadOverlays( _this ) {
|
|
|
|
_this.currentOverlays = [];
|
|
|
|
for ( var i = 0; i < _this.overlays.length; i++ ) {
|
|
|
|
_this.currentOverlays[ i ] = getOverlayObject( _this, _this.overlays[ i ] );
|
|
|
|
}
|
|
|
|
for ( var j = 0; j < _this.source.overlays.length; j++ ) {
|
|
|
|
_this.currentOverlays[ i + j ] =
|
|
|
|
getOverlayObject( _this, _this.source.overlays[ j ] );
|
|
|
|
}
|
|
|
|
}
|
2013-03-26 17:02:34 +04:00
|
|
|
|
2014-01-31 00:38:37 +04:00
|
|
|
function getOverlayObject( viewer, overlay ) {
|
2014-03-15 19:20:33 +04:00
|
|
|
if ( overlay instanceof $.Overlay ) {
|
2014-01-31 00:38:37 +04:00
|
|
|
return overlay;
|
|
|
|
}
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2014-03-15 19:20:33 +04:00
|
|
|
var element = null;
|
|
|
|
if ( overlay.element ) {
|
|
|
|
element = $.getElement( overlay.element );
|
|
|
|
} else {
|
|
|
|
var id = overlay.id ?
|
|
|
|
overlay.id :
|
|
|
|
"openseadragon-overlay-" + Math.floor( Math.random() * 10000000 );
|
|
|
|
|
|
|
|
element = $.getElement( overlay.id );
|
|
|
|
if ( !element ) {
|
|
|
|
element = document.createElement( "a" );
|
|
|
|
element.href = "#/overlay/" + id;
|
|
|
|
}
|
|
|
|
element.id = id;
|
|
|
|
$.addClass( element, overlay.className ?
|
|
|
|
overlay.className :
|
|
|
|
"openseadragon-overlay"
|
|
|
|
);
|
2014-01-31 00:38:37 +04:00
|
|
|
}
|
|
|
|
|
2014-03-15 19:20:33 +04:00
|
|
|
var location = overlay.location;
|
|
|
|
if ( !location ) {
|
2014-03-21 23:55:04 +04:00
|
|
|
if ( overlay.width && overlay.height ) {
|
|
|
|
location = overlay.px !== undefined ?
|
|
|
|
viewer.viewport.imageToViewportRectangle( new $.Rect(
|
|
|
|
overlay.px,
|
|
|
|
overlay.py,
|
|
|
|
overlay.width,
|
|
|
|
overlay.height
|
|
|
|
) ) :
|
|
|
|
new $.Rect(
|
|
|
|
overlay.x,
|
|
|
|
overlay.y,
|
|
|
|
overlay.width,
|
|
|
|
overlay.height
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
location = overlay.px !== undefined ?
|
|
|
|
viewer.viewport.imageToViewportCoordinates( new $.Point(
|
|
|
|
overlay.px,
|
|
|
|
overlay.py
|
|
|
|
) ) :
|
|
|
|
new $.Point(
|
|
|
|
overlay.x,
|
|
|
|
overlay.y
|
|
|
|
);
|
2014-03-15 19:20:33 +04:00
|
|
|
}
|
2014-01-31 00:38:37 +04:00
|
|
|
}
|
|
|
|
|
2014-03-15 19:20:33 +04:00
|
|
|
var placement = overlay.placement;
|
|
|
|
if ( placement && ( $.type( placement ) === "string" ) ) {
|
|
|
|
placement = $.OverlayPlacement[ overlay.placement.toUpperCase() ];
|
2014-01-31 00:38:37 +04:00
|
|
|
}
|
2014-03-15 19:20:33 +04:00
|
|
|
|
|
|
|
return new $.Overlay({
|
|
|
|
element: element,
|
|
|
|
location: location,
|
|
|
|
placement: placement,
|
2014-03-20 23:39:31 +04:00
|
|
|
onDraw: overlay.onDraw,
|
|
|
|
checkResize: overlay.checkResize
|
2014-03-15 19:20:33 +04:00
|
|
|
});
|
2014-01-31 00:38:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
* @inner
|
2014-03-15 19:20:33 +04:00
|
|
|
* Determines the index of the given overlay in the given overlays array.
|
2014-01-31 00:38:37 +04:00
|
|
|
*/
|
|
|
|
function getOverlayIndex( overlays, element ) {
|
|
|
|
var i;
|
|
|
|
for ( i = overlays.length - 1; i >= 0; i-- ) {
|
2014-03-15 19:20:33 +04:00
|
|
|
if ( overlays[ i ].element === element ) {
|
2014-01-31 00:38:37 +04:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
2013-03-26 17:02:34 +04:00
|
|
|
|
2014-01-31 00:38:37 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2014-03-15 19:20:33 +04:00
|
|
|
function drawOverlays( viewport, overlays, container ) {
|
2014-01-31 00:38:37 +04:00
|
|
|
var i,
|
|
|
|
length = overlays.length;
|
|
|
|
for ( i = 0; i < length; i++ ) {
|
|
|
|
overlays[ i ].drawHTML( container, viewport );
|
|
|
|
}
|
|
|
|
}
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2011-12-08 06:10:13 +04:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Schedulers provide the general engine for animation
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2013-06-19 20:58:09 +04:00
|
|
|
function scheduleUpdate( viewer, updateFunc ){
|
2013-04-27 05:48:48 +04:00
|
|
|
return $.requestAnimationFrame( function(){
|
|
|
|
updateFunc( viewer );
|
|
|
|
} );
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2011-12-08 06:10:13 +04:00
|
|
|
//provides a sequence in the fade animation
|
|
|
|
function scheduleControlsFade( viewer ) {
|
2013-02-26 19:19:48 +04:00
|
|
|
$.requestAnimationFrame( function(){
|
2011-12-08 06:10:13 +04:00
|
|
|
updateControlsFade( viewer );
|
2013-02-26 19:19:48 +04:00
|
|
|
});
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2011-12-08 06:10:13 +04:00
|
|
|
//initiates an animation to hide the controls
|
|
|
|
function beginControlsAutoHide( viewer ) {
|
2012-03-01 17:38:15 +04:00
|
|
|
if ( !viewer.autoHideControls ) {
|
2011-12-08 06:10:13 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
viewer.controlsShouldFade = true;
|
2013-06-19 21:33:25 +04:00
|
|
|
viewer.controlsFadeBeginTime =
|
2013-06-21 00:15:04 +04:00
|
|
|
$.now() +
|
2012-03-01 17:38:15 +04:00
|
|
|
viewer.controlsFadeDelay;
|
2011-12-08 06:10:13 +04:00
|
|
|
|
|
|
|
window.setTimeout( function(){
|
|
|
|
scheduleControlsFade( viewer );
|
2012-03-01 17:38:15 +04:00
|
|
|
}, viewer.controlsFadeDelay );
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
|
|
|
|
|
|
|
|
//determines if fade animation is done or continues the animation
|
|
|
|
function updateControlsFade( viewer ) {
|
|
|
|
var currentTime,
|
|
|
|
deltaTime,
|
|
|
|
opacity,
|
|
|
|
i;
|
|
|
|
if ( viewer.controlsShouldFade ) {
|
2013-06-21 00:15:04 +04:00
|
|
|
currentTime = $.now();
|
2011-12-08 06:10:13 +04:00
|
|
|
deltaTime = currentTime - viewer.controlsFadeBeginTime;
|
2012-03-01 17:38:15 +04:00
|
|
|
opacity = 1.0 - deltaTime / viewer.controlsFadeLength;
|
2011-12-08 06:10:13 +04:00
|
|
|
|
|
|
|
opacity = Math.min( 1.0, opacity );
|
|
|
|
opacity = Math.max( 0.0, opacity );
|
|
|
|
|
2011-12-13 02:22:01 +04:00
|
|
|
for ( i = viewer.controls.length - 1; i >= 0; i--) {
|
2013-03-15 18:59:47 +04:00
|
|
|
if (viewer.controls[ i ].autoFade) {
|
|
|
|
viewer.controls[ i ].setOpacity( opacity );
|
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( opacity > 0 ) {
|
|
|
|
// fade again
|
2013-06-19 21:33:25 +04:00
|
|
|
scheduleControlsFade( viewer );
|
2011-12-08 06:10:13 +04:00
|
|
|
}
|
|
|
|
}
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2011-12-08 06:10:13 +04:00
|
|
|
//stop the fade animation on the controls and show them
|
|
|
|
function abortControlsAutoHide( viewer ) {
|
|
|
|
var i;
|
|
|
|
viewer.controlsShouldFade = false;
|
|
|
|
for ( i = viewer.controls.length - 1; i >= 0; i-- ) {
|
|
|
|
viewer.controls[ i ].setOpacity( 1.0 );
|
|
|
|
}
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
|
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2011-12-08 06:10:13 +04:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Default view event handlers.
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2012-03-16 19:36:28 +04:00
|
|
|
function onFocus(){
|
|
|
|
abortControlsAutoHide( this );
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2012-03-16 19:36:28 +04:00
|
|
|
|
|
|
|
function onBlur(){
|
|
|
|
beginControlsAutoHide( this );
|
2013-06-19 21:33:25 +04:00
|
|
|
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2012-03-16 19:36:28 +04:00
|
|
|
|
2013-10-11 04:00:15 +04:00
|
|
|
function onCanvasClick( event ) {
|
2013-06-19 01:56:13 +04:00
|
|
|
var zoomPerClick,
|
2011-12-08 06:10:13 +04:00
|
|
|
factor;
|
2013-11-05 00:41:45 +04:00
|
|
|
if ( !event.preventDefaultAction && this.viewport && event.quick ) { // ignore clicks where mouse moved
|
2012-03-01 17:38:15 +04:00
|
|
|
zoomPerClick = this.zoomPerClick;
|
2013-10-11 04:00:15 +04:00
|
|
|
factor = event.shift ? 1.0 / zoomPerClick : zoomPerClick;
|
2012-01-24 17:03:50 +04:00
|
|
|
this.viewport.zoomBy(
|
2013-06-19 21:33:25 +04:00
|
|
|
factor,
|
2013-10-11 04:00:15 +04:00
|
|
|
this.viewport.pointFromPixel( event.position, true )
|
2012-01-24 17:03:50 +04:00
|
|
|
);
|
2011-12-08 06:10:13 +04:00
|
|
|
this.viewport.applyConstraints();
|
|
|
|
}
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-25 20:48:44 +04:00
|
|
|
* Raised when a mouse press/release or touch/remove occurs on the {@link OpenSeadragon.Viewer#canvas} element.
|
2013-11-22 00:19:07 +04:00
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event canvas-click
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
|
|
|
* @property {OpenSeadragon.MouseTracker} tracker - A reference to the MouseTracker which originated this event.
|
|
|
|
* @property {OpenSeadragon.Point} position - The position of the event relative to the tracked element.
|
|
|
|
* @property {Boolean} quick - True only if the clickDistThreshold and clickDeltaThreshold are both passed. Useful for differentiating between clicks and drags.
|
|
|
|
* @property {Boolean} shift - True if the shift key was pressed during this event.
|
|
|
|
* @property {Object} originalEvent - The original DOM event.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-09-30 21:22:06 +04:00
|
|
|
this.raiseEvent( 'canvas-click', {
|
2013-10-11 04:00:15 +04:00
|
|
|
tracker: event.eventSource,
|
|
|
|
position: event.position,
|
|
|
|
quick: event.quick,
|
2013-10-15 22:11:08 +04:00
|
|
|
shift: event.shift,
|
|
|
|
originalEvent: event.originalEvent
|
2013-02-14 04:44:23 +04:00
|
|
|
});
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2013-10-11 04:00:15 +04:00
|
|
|
function onCanvasDrag( event ) {
|
2013-11-05 00:41:45 +04:00
|
|
|
if ( !event.preventDefaultAction && this.viewport ) {
|
2012-04-03 11:08:27 +04:00
|
|
|
if( !this.panHorizontal ){
|
2013-10-11 04:00:15 +04:00
|
|
|
event.delta.x = 0;
|
2012-04-03 11:08:27 +04:00
|
|
|
}
|
|
|
|
if( !this.panVertical ){
|
2013-10-11 04:00:15 +04:00
|
|
|
event.delta.y = 0;
|
2012-04-03 11:08:27 +04:00
|
|
|
}
|
2013-06-19 21:33:25 +04:00
|
|
|
this.viewport.panBy(
|
|
|
|
this.viewport.deltaPointsFromPixels(
|
2013-10-11 04:00:15 +04:00
|
|
|
event.delta.negate()
|
2013-06-19 21:33:25 +04:00
|
|
|
)
|
2012-01-24 17:03:50 +04:00
|
|
|
);
|
2013-02-13 07:40:08 +04:00
|
|
|
if( this.constrainDuringPan ){
|
|
|
|
this.viewport.applyConstraints();
|
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
}
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-25 20:48:44 +04:00
|
|
|
* Raised when a mouse or touch drag operation occurs on the {@link OpenSeadragon.Viewer#canvas} element.
|
2013-11-22 00:19:07 +04:00
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event canvas-drag
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
|
|
|
* @property {OpenSeadragon.MouseTracker} tracker - A reference to the MouseTracker which originated this event.
|
|
|
|
* @property {OpenSeadragon.Point} position - The position of the event relative to the tracked element.
|
|
|
|
* @property {OpenSeadragon.Point} delta - The x,y components of the difference between start drag and end drag.
|
|
|
|
* @property {Boolean} shift - True if the shift key was pressed during this event.
|
|
|
|
* @property {Object} originalEvent - The original DOM event.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-09-30 21:22:06 +04:00
|
|
|
this.raiseEvent( 'canvas-drag', {
|
2013-10-11 04:00:15 +04:00
|
|
|
tracker: event.eventSource,
|
|
|
|
position: event.position,
|
|
|
|
delta: event.delta,
|
2013-10-15 22:11:08 +04:00
|
|
|
shift: event.shift,
|
|
|
|
originalEvent: event.originalEvent
|
2013-02-14 04:44:23 +04:00
|
|
|
});
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2013-10-11 04:00:15 +04:00
|
|
|
function onCanvasRelease( event ) {
|
|
|
|
if ( event.insideElementPressed && this.viewport ) {
|
2011-12-08 06:10:13 +04:00
|
|
|
this.viewport.applyConstraints();
|
|
|
|
}
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-25 20:48:44 +04:00
|
|
|
* Raised when the mouse button is released or touch ends on the {@link OpenSeadragon.Viewer#canvas} element.
|
2013-11-22 00:19:07 +04:00
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event canvas-release
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
|
|
|
* @property {OpenSeadragon.MouseTracker} tracker - A reference to the MouseTracker which originated this event.
|
|
|
|
* @property {OpenSeadragon.Point} position - The position of the event relative to the tracked element.
|
|
|
|
* @property {Boolean} insideElementPressed - True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false.
|
|
|
|
* @property {Boolean} insideElementReleased - True if the cursor still inside the tracked element when the button was released.
|
|
|
|
* @property {Object} originalEvent - The original DOM event.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-09-30 21:22:06 +04:00
|
|
|
this.raiseEvent( 'canvas-release', {
|
2013-10-11 04:00:15 +04:00
|
|
|
tracker: event.eventSource,
|
|
|
|
position: event.position,
|
|
|
|
insideElementPressed: event.insideElementPressed,
|
2013-10-15 22:11:08 +04:00
|
|
|
insideElementReleased: event.insideElementReleased,
|
|
|
|
originalEvent: event.originalEvent
|
2013-02-14 04:44:23 +04:00
|
|
|
});
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2013-10-11 04:00:15 +04:00
|
|
|
function onCanvasScroll( event ) {
|
2011-12-08 06:10:13 +04:00
|
|
|
var factor;
|
2013-11-05 00:41:45 +04:00
|
|
|
if ( !event.preventDefaultAction && this.viewport ) {
|
2013-10-11 04:00:15 +04:00
|
|
|
factor = Math.pow( this.zoomPerScroll, event.scroll );
|
2013-06-19 21:33:25 +04:00
|
|
|
this.viewport.zoomBy(
|
|
|
|
factor,
|
2013-10-11 04:00:15 +04:00
|
|
|
this.viewport.pointFromPixel( event.position, true )
|
2012-01-24 17:03:50 +04:00
|
|
|
);
|
2011-12-08 06:10:13 +04:00
|
|
|
this.viewport.applyConstraints();
|
|
|
|
}
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-25 20:48:44 +04:00
|
|
|
* Raised when a scroll event occurs on the {@link OpenSeadragon.Viewer#canvas} element (mouse wheel, touch pinch, etc.).
|
2013-11-22 00:19:07 +04:00
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event canvas-scroll
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
|
|
|
* @property {OpenSeadragon.MouseTracker} tracker - A reference to the MouseTracker which originated this event.
|
|
|
|
* @property {OpenSeadragon.Point} position - The position of the event relative to the tracked element.
|
|
|
|
* @property {Number} scroll - The scroll delta for the event.
|
|
|
|
* @property {Boolean} shift - True if the shift key was pressed during this event.
|
|
|
|
* @property {Object} originalEvent - The original DOM event.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-09-30 21:22:06 +04:00
|
|
|
this.raiseEvent( 'canvas-scroll', {
|
2013-10-11 04:00:15 +04:00
|
|
|
tracker: event.eventSource,
|
|
|
|
position: event.position,
|
|
|
|
scroll: event.scroll,
|
2013-10-15 22:11:08 +04:00
|
|
|
shift: event.shift,
|
|
|
|
originalEvent: event.originalEvent
|
2013-02-14 04:44:23 +04:00
|
|
|
});
|
2012-04-03 11:08:27 +04:00
|
|
|
//cancels event
|
|
|
|
return false;
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2013-10-11 04:00:15 +04:00
|
|
|
function onContainerExit( event ) {
|
|
|
|
if ( !event.insideElementPressed ) {
|
2012-02-27 15:56:29 +04:00
|
|
|
THIS[ this.hash ].mouseInside = false;
|
|
|
|
if ( !THIS[ this.hash ].animating ) {
|
2011-12-08 06:10:13 +04:00
|
|
|
beginControlsAutoHide( this );
|
|
|
|
}
|
|
|
|
}
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-25 20:48:44 +04:00
|
|
|
* Raised when the cursor leaves the {@link OpenSeadragon.Viewer#container} element.
|
2013-11-22 00:19:07 +04:00
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event container-exit
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
|
|
|
* @property {OpenSeadragon.MouseTracker} tracker - A reference to the MouseTracker which originated this event.
|
|
|
|
* @property {OpenSeadragon.Point} position - The position of the event relative to the tracked element.
|
|
|
|
* @property {Boolean} insideElementPressed - True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false.
|
|
|
|
* @property {Boolean} buttonDownAny - Was the button down anywhere in the screen during the event.
|
|
|
|
* @property {Object} originalEvent - The original DOM event.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-09-30 21:22:06 +04:00
|
|
|
this.raiseEvent( 'container-exit', {
|
2013-10-11 04:00:15 +04:00
|
|
|
tracker: event.eventSource,
|
|
|
|
position: event.position,
|
|
|
|
insideElementPressed: event.insideElementPressed,
|
2013-10-15 22:11:08 +04:00
|
|
|
buttonDownAny: event.buttonDownAny,
|
|
|
|
originalEvent: event.originalEvent
|
2013-02-14 04:44:23 +04:00
|
|
|
});
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2013-10-11 04:00:15 +04:00
|
|
|
function onContainerRelease( event ) {
|
|
|
|
if ( !event.insideElementReleased ) {
|
2012-02-27 15:56:29 +04:00
|
|
|
THIS[ this.hash ].mouseInside = false;
|
|
|
|
if ( !THIS[ this.hash ].animating ) {
|
2011-12-08 06:10:13 +04:00
|
|
|
beginControlsAutoHide( this );
|
|
|
|
}
|
|
|
|
}
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-25 20:48:44 +04:00
|
|
|
* Raised when the mouse button is released or touch ends on the {@link OpenSeadragon.Viewer#container} element.
|
2013-11-22 00:19:07 +04:00
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event container-release
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
|
|
|
* @property {OpenSeadragon.MouseTracker} tracker - A reference to the MouseTracker which originated this event.
|
|
|
|
* @property {OpenSeadragon.Point} position - The position of the event relative to the tracked element.
|
|
|
|
* @property {Boolean} insideElementPressed - True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false.
|
|
|
|
* @property {Boolean} insideElementReleased - True if the cursor still inside the tracked element when the button was released.
|
|
|
|
* @property {Object} originalEvent - The original DOM event.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-09-30 21:22:06 +04:00
|
|
|
this.raiseEvent( 'container-release', {
|
2013-10-11 04:00:15 +04:00
|
|
|
tracker: event.eventSource,
|
|
|
|
position: event.position,
|
|
|
|
insideElementPressed: event.insideElementPressed,
|
2013-10-15 22:11:08 +04:00
|
|
|
insideElementReleased: event.insideElementReleased,
|
|
|
|
originalEvent: event.originalEvent
|
2013-02-14 04:44:23 +04:00
|
|
|
});
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2013-10-11 04:00:15 +04:00
|
|
|
function onContainerEnter( event ) {
|
2012-02-27 15:56:29 +04:00
|
|
|
THIS[ this.hash ].mouseInside = true;
|
2011-12-08 06:10:13 +04:00
|
|
|
abortControlsAutoHide( this );
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-25 20:48:44 +04:00
|
|
|
* Raised when the cursor enters the {@link OpenSeadragon.Viewer#container} element.
|
2013-11-22 00:19:07 +04:00
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event container-enter
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
|
|
|
* @property {OpenSeadragon.MouseTracker} tracker - A reference to the MouseTracker which originated this event.
|
|
|
|
* @property {OpenSeadragon.Point} position - The position of the event relative to the tracked element.
|
|
|
|
* @property {Boolean} insideElementPressed - True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false.
|
|
|
|
* @property {Boolean} buttonDownAny - Was the button down anywhere in the screen during the event.
|
|
|
|
* @property {Object} originalEvent - The original DOM event.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-09-30 21:22:06 +04:00
|
|
|
this.raiseEvent( 'container-enter', {
|
2013-10-11 04:00:15 +04:00
|
|
|
tracker: event.eventSource,
|
|
|
|
position: event.position,
|
|
|
|
insideElementPressed: event.insideElementPressed,
|
2013-10-15 22:11:08 +04:00
|
|
|
buttonDownAny: event.buttonDownAny,
|
|
|
|
originalEvent: event.originalEvent
|
2013-02-14 04:44:23 +04:00
|
|
|
});
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Page update routines ( aka Views - for future reference )
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2011-12-23 05:47:21 +04:00
|
|
|
|
2013-04-27 05:48:48 +04:00
|
|
|
function updateMulti( viewer ) {
|
2013-04-29 21:17:37 +04:00
|
|
|
if ( !viewer.source ) {
|
2013-06-18 22:06:43 +04:00
|
|
|
viewer._updateRequestId = null;
|
2013-04-29 21:17:37 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-12-23 05:47:21 +04:00
|
|
|
updateOnce( viewer );
|
2013-04-27 06:32:51 +04:00
|
|
|
|
2013-06-17 22:30:31 +04:00
|
|
|
// Request the next frame, unless we've been closed during the updateOnce()
|
|
|
|
if ( viewer.source ) {
|
2013-06-19 20:58:09 +04:00
|
|
|
viewer._updateRequestId = scheduleUpdate( viewer, updateMulti );
|
2013-06-17 22:30:31 +04:00
|
|
|
}
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-23 05:47:21 +04:00
|
|
|
|
2011-12-23 05:36:17 +04:00
|
|
|
function updateOnce( viewer ) {
|
2012-01-24 17:03:50 +04:00
|
|
|
|
|
|
|
var containerSize,
|
|
|
|
animated;
|
|
|
|
|
2011-12-23 05:36:17 +04:00
|
|
|
if ( !viewer.source ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-12-30 02:14:42 +04:00
|
|
|
//viewer.profiler.beginUpdate();
|
2011-12-23 05:36:17 +04:00
|
|
|
|
2013-11-25 22:27:03 +04:00
|
|
|
if ( viewer.autoResize ) {
|
2013-11-23 05:07:44 +04:00
|
|
|
containerSize = _getSafeElemSize( viewer.container );
|
|
|
|
if ( !containerSize.equals( THIS[ viewer.hash ].prevContainerSize ) ) {
|
|
|
|
// maintain image position
|
|
|
|
var oldBounds = viewer.viewport.getBounds();
|
|
|
|
var oldCenter = viewer.viewport.getCenter();
|
|
|
|
resizeViewportAndRecenter(viewer, containerSize, oldBounds, oldCenter);
|
|
|
|
THIS[ viewer.hash ].prevContainerSize = containerSize;
|
|
|
|
THIS[ viewer.hash ].forceRedraw = true;
|
|
|
|
}
|
2011-12-23 05:36:17 +04:00
|
|
|
}
|
|
|
|
|
2012-01-24 17:03:50 +04:00
|
|
|
animated = viewer.viewport.update();
|
2012-09-05 18:52:57 +04:00
|
|
|
|
|
|
|
if( viewer.referenceStrip ){
|
|
|
|
animated = viewer.referenceStrip.update( viewer.viewport ) || animated;
|
|
|
|
}
|
2012-10-13 07:40:59 +04:00
|
|
|
|
2012-02-27 15:56:29 +04:00
|
|
|
if ( !THIS[ viewer.hash ].animating && animated ) {
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-22 00:19:07 +04:00
|
|
|
* Raised when any spring animation starts (zoom, pan, etc.).
|
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event animation-start
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-09-30 21:22:06 +04:00
|
|
|
viewer.raiseEvent( "animation-start" );
|
2011-12-23 05:36:17 +04:00
|
|
|
abortControlsAutoHide( viewer );
|
|
|
|
}
|
2011-12-08 06:10:13 +04:00
|
|
|
|
2011-12-23 05:36:17 +04:00
|
|
|
if ( animated ) {
|
2013-12-01 02:28:17 +04:00
|
|
|
updateDrawers( viewer );
|
2014-03-20 17:56:12 +04:00
|
|
|
drawOverlays( viewer.viewport, viewer.currentOverlays, viewer.overlaysContainer );
|
2012-03-07 07:20:00 +04:00
|
|
|
if( viewer.navigator ){
|
|
|
|
viewer.navigator.update( viewer.viewport );
|
|
|
|
}
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-22 00:19:07 +04:00
|
|
|
* Raised when any spring animation update occurs (zoom, pan, etc.).
|
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event animation
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2011-12-23 05:36:17 +04:00
|
|
|
viewer.raiseEvent( "animation" );
|
2013-12-01 02:28:17 +04:00
|
|
|
} else if ( THIS[ viewer.hash ].forceRedraw || drawersNeedUpdate( viewer ) ) {
|
|
|
|
updateDrawers( viewer );
|
2014-03-20 17:56:12 +04:00
|
|
|
drawOverlays( viewer.viewport, viewer.currentOverlays, viewer.overlaysContainer );
|
2012-03-07 07:20:00 +04:00
|
|
|
if( viewer.navigator ){
|
|
|
|
viewer.navigator.update( viewer.viewport );
|
|
|
|
}
|
2012-02-27 15:56:29 +04:00
|
|
|
THIS[ viewer.hash ].forceRedraw = false;
|
2013-06-19 21:33:25 +04:00
|
|
|
}
|
2011-12-23 05:36:17 +04:00
|
|
|
|
2012-02-27 15:56:29 +04:00
|
|
|
if ( THIS[ viewer.hash ].animating && !animated ) {
|
2013-11-16 10:19:53 +04:00
|
|
|
/**
|
2013-11-22 00:19:07 +04:00
|
|
|
* Raised when any spring animation ends (zoom, pan, etc.).
|
|
|
|
*
|
2013-11-16 10:19:53 +04:00
|
|
|
* @event animation-finish
|
|
|
|
* @memberof OpenSeadragon.Viewer
|
|
|
|
* @type {object}
|
|
|
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
2013-11-18 18:56:32 +04:00
|
|
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
2013-11-16 10:19:53 +04:00
|
|
|
*/
|
2013-09-30 21:22:06 +04:00
|
|
|
viewer.raiseEvent( "animation-finish" );
|
2011-12-23 05:36:17 +04:00
|
|
|
|
2012-02-27 15:56:29 +04:00
|
|
|
if ( !THIS[ viewer.hash ].mouseInside ) {
|
2011-12-23 05:36:17 +04:00
|
|
|
beginControlsAutoHide( viewer );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-27 15:56:29 +04:00
|
|
|
THIS[ viewer.hash ].animating = animated;
|
2011-12-23 05:36:17 +04:00
|
|
|
|
2011-12-30 02:14:42 +04:00
|
|
|
//viewer.profiler.endUpdate();
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-13 07:40:02 +04:00
|
|
|
|
2013-11-08 22:56:13 +04:00
|
|
|
// This function resizes the viewport and recenters the image
|
2013-11-03 05:01:04 +04:00
|
|
|
// as it was before resizing.
|
|
|
|
// TODO: better adjust width and height. The new width and height
|
|
|
|
// should depend on the image dimensions and on the dimensions
|
|
|
|
// of the viewport before and after switching mode.
|
|
|
|
function resizeViewportAndRecenter( viewer, containerSize, oldBounds, oldCenter ) {
|
|
|
|
var viewport = viewer.viewport;
|
|
|
|
|
|
|
|
viewport.resize( containerSize, true );
|
|
|
|
|
|
|
|
// We try to remove blanks as much as possible
|
|
|
|
var imageHeight = 1 / viewer.source.aspectRatio;
|
|
|
|
var newWidth = oldBounds.width <= 1 ? oldBounds.width : 1;
|
|
|
|
var newHeight = oldBounds.height <= imageHeight ?
|
|
|
|
oldBounds.height : imageHeight;
|
|
|
|
|
|
|
|
var newBounds = new $.Rect(
|
|
|
|
oldCenter.x - ( newWidth / 2.0 ),
|
|
|
|
oldCenter.y - ( newHeight / 2.0 ),
|
|
|
|
newWidth,
|
|
|
|
newHeight
|
|
|
|
);
|
|
|
|
viewport.fitBounds( newBounds, true );
|
|
|
|
}
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2013-12-01 02:28:17 +04:00
|
|
|
function updateDrawers( viewer ) {
|
2013-12-09 18:26:36 +04:00
|
|
|
for (var i = 0; i < viewer.drawers.length; i++ ) {
|
|
|
|
viewer.drawers[i].update();
|
|
|
|
}
|
2013-12-01 02:28:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
function drawersNeedUpdate( viewer ) {
|
2013-12-09 18:26:36 +04:00
|
|
|
for (var i = 0; i < viewer.drawers.length; i++ ) {
|
|
|
|
if (viewer.drawers[i].needsUpdate()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2013-12-01 02:28:17 +04:00
|
|
|
}
|
|
|
|
|
2011-12-23 05:08:06 +04:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Navigation Controls
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
function resolveUrl( prefix, url ) {
|
|
|
|
return prefix ? prefix + url : url;
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-23 05:08:06 +04:00
|
|
|
|
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2011-12-23 05:08:06 +04:00
|
|
|
function beginZoomingIn() {
|
2013-06-21 00:15:04 +04:00
|
|
|
THIS[ this.hash ].lastZoomTime = $.now();
|
2012-03-01 17:38:15 +04:00
|
|
|
THIS[ this.hash ].zoomFactor = this.zoomPerSecond;
|
2012-02-27 15:56:29 +04:00
|
|
|
THIS[ this.hash ].zooming = true;
|
2011-12-23 05:08:06 +04:00
|
|
|
scheduleZoom( this );
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2011-12-23 05:08:06 +04:00
|
|
|
|
|
|
|
function beginZoomingOut() {
|
2013-06-21 00:15:04 +04:00
|
|
|
THIS[ this.hash ].lastZoomTime = $.now();
|
2012-03-01 17:38:15 +04:00
|
|
|
THIS[ this.hash ].zoomFactor = 1.0 / this.zoomPerSecond;
|
2012-02-27 15:56:29 +04:00
|
|
|
THIS[ this.hash ].zooming = true;
|
2011-12-23 05:08:06 +04:00
|
|
|
scheduleZoom( this );
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2011-12-23 05:08:06 +04:00
|
|
|
|
|
|
|
function endZooming() {
|
2012-02-27 15:56:29 +04:00
|
|
|
THIS[ this.hash ].zooming = false;
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2011-12-23 05:08:06 +04:00
|
|
|
|
|
|
|
function scheduleZoom( viewer ) {
|
2013-02-26 19:19:48 +04:00
|
|
|
$.requestAnimationFrame( $.delegate( viewer, doZoom ) );
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2011-12-23 05:08:06 +04:00
|
|
|
|
|
|
|
function doZoom() {
|
2012-01-24 17:03:50 +04:00
|
|
|
var currentTime,
|
|
|
|
deltaTime,
|
2013-06-19 01:56:13 +04:00
|
|
|
adjustedFactor;
|
2012-01-24 17:03:50 +04:00
|
|
|
|
2012-02-27 15:56:29 +04:00
|
|
|
if ( THIS[ this.hash ].zooming && this.viewport) {
|
2013-06-21 00:15:04 +04:00
|
|
|
currentTime = $.now();
|
2012-02-27 15:56:29 +04:00
|
|
|
deltaTime = currentTime - THIS[ this.hash ].lastZoomTime;
|
|
|
|
adjustedFactor = Math.pow( THIS[ this.hash ].zoomFactor, deltaTime / 1000 );
|
2011-12-23 05:08:06 +04:00
|
|
|
|
2012-01-24 17:03:50 +04:00
|
|
|
this.viewport.zoomBy( adjustedFactor );
|
2011-12-23 05:08:06 +04:00
|
|
|
this.viewport.applyConstraints();
|
2012-02-27 15:56:29 +04:00
|
|
|
THIS[ this.hash ].lastZoomTime = currentTime;
|
2011-12-23 05:08:06 +04:00
|
|
|
scheduleZoom( this );
|
|
|
|
}
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-23 05:08:06 +04:00
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2011-12-23 05:08:06 +04:00
|
|
|
function doSingleZoomIn() {
|
2012-01-24 17:03:50 +04:00
|
|
|
if ( this.viewport ) {
|
2012-02-27 15:56:29 +04:00
|
|
|
THIS[ this.hash ].zooming = false;
|
2013-06-19 21:33:25 +04:00
|
|
|
this.viewport.zoomBy(
|
|
|
|
this.zoomPerClick / 1.0
|
2011-12-23 05:08:06 +04:00
|
|
|
);
|
|
|
|
this.viewport.applyConstraints();
|
|
|
|
}
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-23 05:08:06 +04:00
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2011-12-23 05:08:06 +04:00
|
|
|
function doSingleZoomOut() {
|
2012-01-24 17:03:50 +04:00
|
|
|
if ( this.viewport ) {
|
2012-02-27 15:56:29 +04:00
|
|
|
THIS[ this.hash ].zooming = false;
|
2011-12-23 05:08:06 +04:00
|
|
|
this.viewport.zoomBy(
|
2012-03-01 17:38:15 +04:00
|
|
|
1.0 / this.zoomPerClick
|
2011-12-23 05:08:06 +04:00
|
|
|
);
|
|
|
|
this.viewport.applyConstraints();
|
|
|
|
}
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-23 05:08:06 +04:00
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2011-12-23 05:08:06 +04:00
|
|
|
function lightUp() {
|
2012-01-24 17:03:50 +04:00
|
|
|
this.buttons.emulateEnter();
|
|
|
|
this.buttons.emulateExit();
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-23 05:08:06 +04:00
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2011-12-23 05:08:06 +04:00
|
|
|
function onHome() {
|
2012-01-24 17:03:50 +04:00
|
|
|
if ( this.viewport ) {
|
2011-12-23 05:08:06 +04:00
|
|
|
this.viewport.goHome();
|
|
|
|
}
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-23 05:08:06 +04:00
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
|
2013-11-03 05:01:04 +04:00
|
|
|
function onFullScreen() {
|
|
|
|
if ( this.isFullPage() && !$.isFullScreen() ) {
|
|
|
|
// Is fullPage but not fullScreen
|
|
|
|
this.setFullPage( false );
|
|
|
|
} else {
|
|
|
|
this.setFullScreen( !this.isFullPage() );
|
|
|
|
}
|
2012-01-24 17:03:50 +04:00
|
|
|
// correct for no mouseout event on change
|
2013-11-03 05:01:04 +04:00
|
|
|
if ( this.buttons ) {
|
2012-04-11 01:02:24 +04:00
|
|
|
this.buttons.emulateExit();
|
|
|
|
}
|
2012-03-20 03:03:58 +04:00
|
|
|
this.fullPageButton.element.focus();
|
2012-01-24 17:03:50 +04:00
|
|
|
if ( this.viewport ) {
|
2011-12-23 05:08:06 +04:00
|
|
|
this.viewport.applyConstraints();
|
|
|
|
}
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2011-12-13 07:40:02 +04:00
|
|
|
|
2014-02-21 00:57:39 +04:00
|
|
|
/**
|
|
|
|
* Note: The current rotation feature is limited to 90 degree turns.
|
|
|
|
*/
|
|
|
|
function onRotateLeft() {
|
|
|
|
if ( this.viewport ) {
|
|
|
|
var currRotation = this.viewport.getRotation();
|
2014-02-21 01:04:26 +04:00
|
|
|
if (currRotation === 0) {
|
2014-02-21 00:57:39 +04:00
|
|
|
currRotation = 270;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
currRotation -= 90;
|
|
|
|
}
|
|
|
|
this.viewport.setRotation(currRotation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Note: The current rotation feature is limited to 90 degree turns.
|
|
|
|
*/
|
|
|
|
function onRotateRight() {
|
|
|
|
if ( this.viewport ) {
|
|
|
|
var currRotation = this.viewport.getRotation();
|
2014-02-21 01:04:26 +04:00
|
|
|
if (currRotation === 270) {
|
2014-02-21 00:57:39 +04:00
|
|
|
currRotation = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
currRotation += 90;
|
|
|
|
}
|
|
|
|
this.viewport.setRotation(currRotation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-03 11:08:27 +04:00
|
|
|
|
|
|
|
function onPrevious(){
|
2012-06-05 15:52:00 +04:00
|
|
|
var previous = THIS[ this.hash ].sequence - 1;
|
2013-05-30 03:10:45 +04:00
|
|
|
if(this.navPrevNextWrap && previous < 0){
|
|
|
|
previous += this.tileSources.length;
|
|
|
|
}
|
2012-06-05 15:52:00 +04:00
|
|
|
this.goToPage( previous );
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2012-04-03 11:08:27 +04:00
|
|
|
|
|
|
|
|
|
|
|
function onNext(){
|
2012-06-05 15:52:00 +04:00
|
|
|
var next = THIS[ this.hash ].sequence + 1;
|
2013-05-30 03:10:45 +04:00
|
|
|
if(this.navPrevNextWrap && next >= this.tileSources.length){
|
|
|
|
next = 0;
|
|
|
|
}
|
2012-06-05 15:52:00 +04:00
|
|
|
this.goToPage( next );
|
2013-01-29 21:32:58 +04:00
|
|
|
}
|
2012-04-03 11:08:27 +04:00
|
|
|
|
|
|
|
|
2011-12-06 07:50:25 +04:00
|
|
|
}( OpenSeadragon ));
|