Merge remote branch 'upstream/master'
2
.gitignore
vendored
@ -1,5 +1,3 @@
|
||||
*.sublime-workspace
|
||||
node_modules
|
||||
build/
|
||||
openseadragon.zip
|
||||
openseadragon.tar
|
||||
|
14
.jshintrc
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"browser": true,
|
||||
"curly": true,
|
||||
"eqeqeq": false,
|
||||
"loopfunc": false,
|
||||
"noarg": true,
|
||||
"trailing": true,
|
||||
"undef": true,
|
||||
"unused": false,
|
||||
|
||||
"globals": {
|
||||
"OpenSeadragon": true
|
||||
}
|
||||
}
|
84
Gruntfile.js
@ -10,15 +10,19 @@ module.exports = function(grunt) {
|
||||
grunt.loadNpmTasks("grunt-contrib-watch");
|
||||
grunt.loadNpmTasks("grunt-contrib-clean");
|
||||
grunt.loadNpmTasks("grunt-git-describe");
|
||||
grunt.loadNpmTasks('grunt-text-replace');
|
||||
|
||||
// ----------
|
||||
var distribution = "build/openseadragon/openseadragon.js",
|
||||
var packageJson = grunt.file.readJSON("package.json"),
|
||||
distribution = "build/openseadragon/openseadragon.js",
|
||||
minified = "build/openseadragon/openseadragon.min.js",
|
||||
packageDirName = "openseadragon-bin-" + packageJson.version,
|
||||
packageDir = "build/" + packageDirName + "/",
|
||||
releaseRoot = "../site-build/built-openseadragon/",
|
||||
sources = [
|
||||
"src/openseadragon.js",
|
||||
"src/fullscreen.js",
|
||||
"src/eventhandler.js",
|
||||
"src/eventsource.js",
|
||||
"src/mousetracker.js",
|
||||
"src/control.js",
|
||||
"src/controldock.js",
|
||||
@ -30,6 +34,7 @@ module.exports = function(grunt) {
|
||||
"src/tilesource.js",
|
||||
"src/dzitilesource.js",
|
||||
"src/iiiftilesource.js",
|
||||
"src/iiif1_1tilesource.js",
|
||||
"src/osmtilesource.js",
|
||||
"src/tmstilesource.js",
|
||||
"src/legacytilesource.js",
|
||||
@ -49,9 +54,16 @@ module.exports = function(grunt) {
|
||||
// ----------
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON("package.json"),
|
||||
pkg: packageJson,
|
||||
osdVersion: {
|
||||
versionStr: packageJson.version,
|
||||
major: parseInt(packageJson.version.split('.')[0], 10),
|
||||
minor: parseInt(packageJson.version.split('.')[1], 10),
|
||||
revision: parseInt(packageJson.version.split('.')[2], 10)
|
||||
},
|
||||
clean: {
|
||||
build: ["build"],
|
||||
package: [packageDir],
|
||||
release: {
|
||||
src: [releaseRoot],
|
||||
options: {
|
||||
@ -64,7 +76,8 @@ module.exports = function(grunt) {
|
||||
banner: "//! <%= pkg.name %> <%= pkg.version %>\n"
|
||||
+ "//! Built on <%= grunt.template.today('yyyy-mm-dd') %>\n"
|
||||
+ "//! Git commit: <%= gitInfo %>\n"
|
||||
+ "//! http://openseadragon.github.io\n\n",
|
||||
+ "//! http://openseadragon.github.io\n"
|
||||
+ "//! License: http://openseadragon.github.io/license/\n\n",
|
||||
process: true
|
||||
},
|
||||
dist: {
|
||||
@ -72,9 +85,27 @@ module.exports = function(grunt) {
|
||||
dest: distribution
|
||||
}
|
||||
},
|
||||
replace: {
|
||||
cleanPaths: {
|
||||
src: ['build/openseadragon/*.map'],
|
||||
overwrite: true,
|
||||
replacements: [
|
||||
{
|
||||
from: /build\/openseadragon\//g,
|
||||
to: ''
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
uglify: {
|
||||
options: {
|
||||
preserveComments: "some"
|
||||
preserveComments: "some",
|
||||
sourceMap: function (filename) {
|
||||
return filename.replace(/\.js$/, '.js.map');
|
||||
},
|
||||
sourceMappingURL: function (filename) {
|
||||
return filename.replace(/\.js$/, '.js.map').replace('build/openseadragon/', '');
|
||||
},
|
||||
},
|
||||
openseadragon: {
|
||||
src: [ distribution ],
|
||||
@ -84,24 +115,27 @@ module.exports = function(grunt) {
|
||||
compress: {
|
||||
zip: {
|
||||
options: {
|
||||
archive: "build/openseadragon.zip"
|
||||
archive: "build/releases/" + packageDirName + ".zip",
|
||||
level: 9
|
||||
},
|
||||
files: [
|
||||
{ expand: true, cwd: "build/", src: ["openseadragon/**"] }
|
||||
{ expand: true, cwd: "build/", src: [ packageDirName + "/**" ] }
|
||||
]
|
||||
},
|
||||
tar: {
|
||||
options: {
|
||||
archive: "build/openseadragon.tar"
|
||||
archive: "build/releases/" + packageDirName + ".tar.gz",
|
||||
level: 9
|
||||
},
|
||||
files: [
|
||||
{ expand: true, cwd: "build/", src: [ "openseadragon/**" ] }
|
||||
{ expand: true, cwd: "build/", src: [ packageDirName + "/**" ] }
|
||||
]
|
||||
}
|
||||
},
|
||||
qunit: {
|
||||
all: {
|
||||
options: {
|
||||
timeout: 10000,
|
||||
urls: [ "http://localhost:8000/test/test.html" ]
|
||||
}
|
||||
}
|
||||
@ -120,12 +154,7 @@ module.exports = function(grunt) {
|
||||
},
|
||||
jshint: {
|
||||
options: {
|
||||
browser: true,
|
||||
eqeqeq: false,
|
||||
loopfunc: false,
|
||||
globals: {
|
||||
OpenSeadragon: true
|
||||
}
|
||||
jshintrc: '.jshintrc'
|
||||
},
|
||||
beforeconcat: sources,
|
||||
afterconcat: [ distribution ]
|
||||
@ -146,8 +175,20 @@ module.exports = function(grunt) {
|
||||
grunt.file.recurse("images", function(abspath, rootdir, subdir, filename) {
|
||||
grunt.file.copy(abspath, "build/openseadragon/images/" + (subdir || "") + filename);
|
||||
});
|
||||
});
|
||||
|
||||
grunt.file.copy("changelog.txt", "build/changelog.txt");
|
||||
// ----------
|
||||
// Copy:package task.
|
||||
// Creates a directory tree to be compressed into a package.
|
||||
grunt.registerTask("copy:package", function() {
|
||||
grunt.file.recurse("build/openseadragon", function(abspath, rootdir, subdir, filename) {
|
||||
var dest = packageDir
|
||||
+ (subdir ? subdir + "/" : '/')
|
||||
+ filename;
|
||||
grunt.file.copy(abspath, dest);
|
||||
});
|
||||
grunt.file.copy("changelog.txt", packageDir + "changelog.txt");
|
||||
grunt.file.copy("LICENSE.txt", packageDir + "LICENSE.txt");
|
||||
});
|
||||
|
||||
// ----------
|
||||
@ -155,6 +196,10 @@ module.exports = function(grunt) {
|
||||
// Copies the contents of the build folder into the release folder.
|
||||
grunt.registerTask("copy:release", function() {
|
||||
grunt.file.recurse("build", function(abspath, rootdir, subdir, filename) {
|
||||
if (subdir === 'releases') {
|
||||
return;
|
||||
}
|
||||
|
||||
var dest = releaseRoot
|
||||
+ (subdir ? subdir + "/" : '/')
|
||||
+ filename;
|
||||
@ -167,7 +212,8 @@ module.exports = function(grunt) {
|
||||
// Build task.
|
||||
// Cleans out the build folder and builds the code and images into it, checking lint.
|
||||
grunt.registerTask("build", [
|
||||
"clean:build", "jshint:beforeconcat", "git-describe", "concat", "jshint:afterconcat", "uglify", "copy:build"
|
||||
"clean:build", "jshint:beforeconcat", "git-describe", "concat", "jshint:afterconcat",
|
||||
"uglify", "replace:cleanPaths", "copy:build"
|
||||
]);
|
||||
|
||||
// ----------
|
||||
@ -177,8 +223,8 @@ module.exports = function(grunt) {
|
||||
|
||||
// ----------
|
||||
// Package task.
|
||||
// Builds and creates the .zip and .tar files.
|
||||
grunt.registerTask("package", ["build", "compress"]);
|
||||
// Builds and creates the .zip and .tar.gz files.
|
||||
grunt.registerTask("package", ["build", "copy:package", "compress", "clean:package"]);
|
||||
|
||||
// ----------
|
||||
// Publish task.
|
||||
|
28
LICENSE.txt
Normal file
@ -0,0 +1,28 @@
|
||||
Copyright (C) 2009 CodePlex Foundation
|
||||
Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
|
||||
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.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright 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.
|
75
README.md
@ -1,14 +1,20 @@
|
||||
# OpenSeadragon
|
||||
|
||||
This project is a fork of the OpenSeadragon project at http://openseadragon.codeplex.com/
|
||||
An open-source, web-based viewer for zoomable images, implemented in pure JavaScript.
|
||||
|
||||
## On the Web
|
||||
See it in action and get started using it at http://openseadragon.github.io/.
|
||||
|
||||
http://openseadragon.github.io/
|
||||
## Stable Builds
|
||||
|
||||
## First Time Setup
|
||||
See the [GitHub releases page](https://github.com/openseadragon/openseadragon/releases).
|
||||
|
||||
All command-line operations are scripted using [Grunt](http://gruntjs.com/) which is based on [Node.js](http://nodejs.org/). To get set up:
|
||||
## Development
|
||||
|
||||
If you want to use OpenSeadragon in your own projects, you can find the latest stable build, API documentation, and example code at http://openseadragon.github.io/. If you want to modify OpenSeadragon and/or contribute to its development, read on.
|
||||
|
||||
### First Time Setup
|
||||
|
||||
All command-line operations for building and testing OpenSeadragon are scripted using [Grunt](http://gruntjs.com/) which is based on [Node.js](http://nodejs.org/). To get set up:
|
||||
|
||||
1. Install Node, if you haven't already (available at the link above)
|
||||
1. Install the Grunt command line runner (if you haven't already); on the command line, run `npm install -g grunt-cli`
|
||||
@ -18,7 +24,7 @@ All command-line operations are scripted using [Grunt](http://gruntjs.com/) whic
|
||||
|
||||
You're set... continue reading for build and test instructions.
|
||||
|
||||
## Building from Source
|
||||
### Building from Source
|
||||
|
||||
To build, just run (on the command line, in the openseadragon folder):
|
||||
|
||||
@ -40,9 +46,9 @@ You can also publish the built version to the site-build repository. This assume
|
||||
|
||||
grunt publish
|
||||
|
||||
... which will delete the existing openseadragon folder, along with the .zip and .tar files, out of the site-build folder and replace them with newly built ones from the source in this repository; you'll then need to commit the changes to site-build.
|
||||
... which will delete the existing openseadragon folder, along with the .zip and .tar.gz files, out of the site-build folder and replace them with newly built ones from the source in this repository; you'll then need to commit the changes to site-build.
|
||||
|
||||
## Testing
|
||||
### Testing
|
||||
|
||||
Our tests are based on [QUnit](http://qunitjs.com/) and [PhantomJS](http://phantomjs.org/); they're both installed when you run `npm install`. At the moment we don't have much in the way of tests, but we're working to fix that. To run on the command line:
|
||||
|
||||
@ -52,58 +58,27 @@ If you wish to work interactively with the tests or test your changes:
|
||||
|
||||
grunt connect watch
|
||||
|
||||
and open `http://localhost:8000/` in your browser
|
||||
and open `http://localhost:8000/test/test.html` in your browser.
|
||||
|
||||
## Contributing
|
||||
Another good page, if you want to interactively test out your changes, is `http://localhost:8000/test/demo/basic.html`.
|
||||
|
||||
### Contributing
|
||||
|
||||
OpenSeadragon is truly a community project; we welcome your involvement!
|
||||
|
||||
When contributing, please attempt to match the code style already in the codebase. Note that we use four spaces per indentation stop. For more thoughts on code style, see https://github.com/rwldrn/idiomatic.js/.
|
||||
|
||||
## Licenses
|
||||
When fixing bugs and adding features, when appropriate please also:
|
||||
|
||||
OpenSeadragon was initially released with a New BSD License ( preserved below ), while work done by Chris Thatcher is additionally licensed under the MIT License.
|
||||
* Update related doc comments (we use [JSDoc 3](http://usejsdoc.org/))
|
||||
* Add/update related unit tests
|
||||
|
||||
### Original license preserved below
|
||||
If you're new to the project, check out our [good first bug](https://github.com/openseadragon/openseadragon/issues?labels=good+first+bug&page=1&state=open) issues for some places to dip your toe in the water.
|
||||
|
||||
-------------------------------------
|
||||
License: New BSD License (BSD)
|
||||
Copyright (c) 2010, OpenSeadragon
|
||||
All rights reserved.
|
||||
If you're new to open source in general, check out [GitHub's open source intro guide](https://guides.github.com/overviews/os-contributing/).
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
## License
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of OpenSeadragon 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.
|
||||
|
||||
### MIT License
|
||||
|
||||
--------------------------------------
|
||||
(c) Christopher Thatcher 2011, 2012. All rights reserved.
|
||||
|
||||
Licensed with the MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
OpenSeadragon is released under the New BSD license. For details, see the file LICENSE.txt.
|
||||
|
||||
[![Build Status](https://secure.travis-ci.org/openseadragon/openseadragon.png?branch=master)](http://travis-ci.org/openseadragon/openseadragon)
|
||||
|
161
changelog.txt
@ -1,12 +1,171 @@
|
||||
OPENSEADRAGON CHANGELOG
|
||||
=======================
|
||||
|
||||
0.9.125: In Progress
|
||||
1.1.0: (in progress)
|
||||
|
||||
* BREAKING CHANGE: the openseadragon-canvas element now has two child divs. This means: (#298)
|
||||
* The drawer element is no longer accessible via viewer.canvas.firstChild but via viewer.drawersContainer.firstChild or viewer.drawer.canvas.
|
||||
* The overlays elements are no longer accessible via viewer.canvas.childNodes but via viewer.overlaysContainer.childNodes or viewer.currentOverlays[i].element.
|
||||
* BREAKING CHANGE: Pseudo full screen mode on IE<11 using activex has been dropped. OpenSeadragon will run in full page if full screen mode is requested.
|
||||
* DEPRECATION: overlay functions have been moved from Drawer to Viewer (#331)
|
||||
* DEPRECATION: OpenSeadragon.cancelFullScreen has been renamed OpenSeadragon.exitFullScreen (#358)
|
||||
* Added layers support. Multiple images can now been displayed on top of each other with transparency via the Viewer.addLayer method (#298)
|
||||
* Improved overlay functions (#331)
|
||||
* Fixed: Nav button highlight states aren't quite aligned on Firefox (#303)
|
||||
* Added ControlAnchor options for default controls (#304)
|
||||
* Enabled basic cross-domain tile loading without tainting canvas (works in Chrome and Firefox) (#308)
|
||||
* Added crossOriginPolicy drawer configuration to enable or disable CORS image requests (#364)
|
||||
* Disabled CORS by default (#377)
|
||||
* Added a ControlAnchor.ABSOLUTE enumeration. Enables absolute positioning of control elements in the viewer (#310)
|
||||
* Added a 'navigator-scroll' event to Navigator. Fired when mousewheel/pinch events occur in the navigator (#310)
|
||||
* Added a navigatorMaintainSizeRatio option. If set to true, the navigator minimap resizes when the viewer element is resized (#310)
|
||||
* Added 'ABSOLUTE' as a navigatorPosition option, along with corresponding navigatorTop, navigatorLeft options. Allows the navigator minimap to be placed anywhere in the viewer (#310)
|
||||
* Enhanced the navigatorTop, navigatorLeft, navigatorHeight, and navigatorWidth options to allow a number for pixel units or a string for other element units (%, em, etc.) (#310)
|
||||
* Additional enhancements for IIIF support (#315)
|
||||
* Fixed: Setting degrees in Viewer constructor has no effect (#336)
|
||||
* Added pre-draw event for tiles to allow applications to alter the image (#348)
|
||||
* Added optional Rotate Left/Right buttons to standard controls (#341)
|
||||
* Added optimization for large numbers of overlays: `checkResize = false` option for OpenSeadragon.Overlay (#365)
|
||||
* Updated full screen API, adding support for Opera and IE11 and allowing keyboard input in Chrome (#358)
|
||||
* Various fixes to bring OpenSeadragon into W3C compliance (#375)
|
||||
* Added separate flags for turning off each of the nav buttons (#376)
|
||||
|
||||
1.0.0:
|
||||
|
||||
NOTE: This version has a number of breaking changes to the API, mostly in event handling. See below.
|
||||
|
||||
* BREAKING CHANGE: All EventSource and MouseTracker event handler method signatures changed to 'handlerMethod(event)' where event == { eventSource, userData, ... } (#251) (Also fixes #23, #224, #239)
|
||||
* The new eventSource property in the event object replaces the old eventSource parameter that was passed to handler methods.
|
||||
* Where the event object duplicated the eventSource value, those properties have been removed. This affects the following events:
|
||||
* All Button events - 'button' property removed
|
||||
* All Viewer (Viewer, Drawer, Viewport) events - 'viewer' property removed
|
||||
* BREAKING CHANGE: Renamed EventHandler to EventSource (#225)
|
||||
* BREAKING CHANGE: Event names changed for consistency: changed to lower case, compound names hyphenated, and "on" prefixes removed (#226):
|
||||
* Viewer "animationstart" changed to "animation-start"
|
||||
* Viewer "animationfinish" changed to "animation-finish"
|
||||
* Button "onPress" changed to "press"
|
||||
* Button "onRelease" changed to "release"
|
||||
* Button "onClick" changed to "click"
|
||||
* Button "onEnter" changed to "enter"
|
||||
* Button "onExit" changed to "exit"
|
||||
* Button "onFocus" changed to "focus"
|
||||
* Button "onBlur" changed to "blur"
|
||||
* BREAKING CHANGE: Numerous improvements to fullPage/fullScreen (#256):
|
||||
* Retains zoom/pan position better when switching into and out of fullPage.
|
||||
* Retains scroll position when switching back out.
|
||||
* More resilient to styling variations on the page.
|
||||
* setFullPage no longer automatically engages fullScreen; there's now a separate setFullScreen.
|
||||
* 'fullpage' event is now 'full-page'.
|
||||
* The `fullpage` property of the 'full-page' event is now `fullPage`.
|
||||
* There is now a 'full-screen' event with a `fullScreen` property (true if it has gone to full screen).
|
||||
* There are now 'pre-full-page' and 'pre-full-screen' events that include a `preventDefaultAction` property you can set in your handler to cancel. They also have `fullPage` and `fullScreen` properties respectively, to indicate if they are going into or out of the mode.
|
||||
* BREAKING CHANGE: Removed the 'onPageChange' callback from the viewer options. Viewer.goToPage() now raises the 'page' event only (#285)
|
||||
* Major documentation improvements (#281)
|
||||
* MouseTracker now passes the original event objects to its handler methods (#23)
|
||||
* MouseTracker now supports an optional 'moveHandler' method for tracking mousemove events (#215)
|
||||
* Added stopHandler to MouseTracker. (#262)
|
||||
* Fixed: Element-relative mouse coordinates now correct if the element and/or page is scrolled (using new OpenSeadragon.getElementOffset() method) (#131)
|
||||
* Fixed: Pinch zoom event issue, regressive issue from previous event system changes (#244)
|
||||
* Added IIIF Image API 1.1 Tile Source (#230)
|
||||
* IIIF 1.0 now uses pixel based syntax (#249)
|
||||
* Fixed: Touch event issue where no canvas-click events were being raised (#240)
|
||||
* Check that zoom reference point is valid before using it in zoomTo and zoomBy (#247)
|
||||
* Added a number of easier coordinate conversion methods to viewport (#243)
|
||||
* Added the ability to create a viewer and start at a specified page (#252)
|
||||
* Fixed image resolve issue with collection mode (#255)
|
||||
* DOM events are now passed through as 'event.originalEvent' in viewer and button events where appropriate. (#257) Affects the following events:
|
||||
* Viewer: 'canvas-release', 'canvas-click', 'canvas-drag', 'canvas-scroll', 'container-enter', 'container-exit', 'container-release'
|
||||
* Button: 'enter', 'exit', 'press', 'release', 'focus', 'blur', 'click'
|
||||
* Fixed: IE 10 not reading DZI file correctly in certain circumstances (#218)
|
||||
* Added support for the 'wheel' DOM mousewheel event (#261)
|
||||
* Fix for non-canvas tile rendering at large size (#264)
|
||||
* Drawer now uses an HTML5 canvas element whenever it's available. Can be overridden with the Viewer.useCanvas option (#191)
|
||||
* Added a boolean preventDefaultAction property (default false) to the event object passed to MouseTracker handler methods. (#270) Implemented in the following MouseTracker subscribers:
|
||||
* Viewer.keyboardCommandArea.innerTracker.focusHandler: preventDefaultAction == true prevents scrolling viewer into view
|
||||
* Viewer.keyboardCommandArea.innerTracker.keyHandler: preventDefaultAction == true prevents viewer keyboard navigation
|
||||
* Viewer.innerTracker.clickHandler: preventDefaultAction == true prevents viewer zoom on click
|
||||
* Viewer.innerTracker.dragHandler: preventDefaultAction == true prevents viewer panning with mouse/touch
|
||||
* Viewer.innerTracker.scrollHandler: preventDefaultAction == true prevents viewer zooming on mousewheel/pinch
|
||||
* Fixed: IE8 error with custom buttons - "Object doesn't support this action" (#279)
|
||||
* Support IIIF servers that don't report tile dimensions (#286)
|
||||
* Added an autoResize option. Default is true. When set to false, the viewer takes no action when its container element is resized. (#291)
|
||||
* Added a static 'version' property to OpenSeadragon. Useful for plugins that require specific OpenSeadragon versions. (#292)
|
||||
|
||||
0.9.131:
|
||||
|
||||
* Fixed: canvas-click event shouldn't fire as you drag (#198)
|
||||
* Fixed: LegacyTileSource doesn't fail gracefully when no supported file formats are found (#202)
|
||||
* Added an optional userData argument to EventHandler.addHandler() which is passed unchanged to the handler method (#203)
|
||||
* Fixed AJAX error reporting on IE8 (#208)
|
||||
* Added viewportToImageRectangle method, and updated imageToViewportRectangle, imageToViewportCoordinates, and viewportToImageCoordinates to be more flexible with params (#212)
|
||||
* Fixed: Viewer is not responsive (css) after returning from full screen (#222)
|
||||
|
||||
0.9.130:
|
||||
|
||||
* Added partial support for rotation (just 90 degree increments for now). (#185)
|
||||
* Hiding and restoring broke the viewer; fixed (#177)
|
||||
* You can now provide an onDraw function for overlays to do custom overlay manipulation (#160)
|
||||
* Added a destroy function on the viewer to clean up and remove elements (#179)
|
||||
* Fixed: navigatorPosition option corrected. (#163)
|
||||
* OpenSeadragon.now() returned undefined the first time; fixed
|
||||
* onTouchEnd did not call the correct mouse up handler; fixed (#159)
|
||||
* Touch events no longer capture mouse (was causing issues on devices that support both) (#168)
|
||||
* Clicking on a button control no longer refreshes page (#184)
|
||||
* Drawer now works when the page is rtl (#187)
|
||||
* Fixed a situation that could throw errors in touch handling (#188)
|
||||
|
||||
0.9.129:
|
||||
|
||||
* Fixed: navigator image not updating when base zoom image is changed (#147)
|
||||
* Fixed tile rendering issue at lower zoom levels with the IIIF TileSource (#55)
|
||||
* On IE, ajax errors would cause an exception to be thrown; fixed (#144)
|
||||
* Faster and more consistent millisecond getter (#138)
|
||||
* Fixed an error when using navPrevNextWrap on single images (#135)
|
||||
* Various fixes to our timer handling (#133)
|
||||
* Now generating source map for openseadragon.min.js (#51)
|
||||
* Fix for calculating overlay width / height (#142)
|
||||
* JSHint tidying (#136)
|
||||
* Improved Ajax method (#149)
|
||||
* Overhauled AJAX error reporting (#151)
|
||||
|
||||
0.9.128:
|
||||
|
||||
* The navigator is now off by default (#102)
|
||||
* Reverted minPixelRatio to 0.5 for better quality (#116)
|
||||
* Sometimes tiles wouldn't resolve if you used the blendTime option; fixed. (#95)
|
||||
* You can now choose to have previous and next buttons wrap using the config.navPrevNextWrap. (#114)
|
||||
* You can now specify an ID for a div to hold the navigator (#46)
|
||||
* You can now click in the navigator to go to a new location (#46)
|
||||
* Keyboard handling is now done in the viewer rather than navigator (#46)
|
||||
* Additional navigator fixes (#46)
|
||||
* Drawer events now fire properly (#94)
|
||||
* Fixed an error in EventHandler.removeHandler() (#48)
|
||||
* Better requestAnimationFrame detection on older Firefox (#103)
|
||||
* More efficient navigator loading (#115)
|
||||
* Simplified element opacity setting implementation (#123)
|
||||
|
||||
0.9.127:
|
||||
|
||||
* Fixed a problem with getString when the string property is a sub-property. (#64)
|
||||
* Fixed: Tooltips for Navigation Controls not displaying (#63)
|
||||
* Cleaned up some diagnostic code that was broken.
|
||||
* Added fullpage class to viewer element when in fullpage mode (#61)
|
||||
* Reverted to original New BSD license; cleaned up license declarations (#89)
|
||||
|
||||
0.9.126:
|
||||
|
||||
* DZI JSONp was broken; fixed.
|
||||
|
||||
0.9.125:
|
||||
|
||||
* Fully deprecated OpenSeadragon.createFromDZI, safely deprecated Viewer.openTileSource and
|
||||
Viewer.openDZI to use Viewer.open internally. (#53 & #54).
|
||||
* Full page bug fix for when viewer is child of document body (#43).
|
||||
* Overlays for DZI bug fix (#45).
|
||||
* DziTileSource: avoid changing relative paths (#56).
|
||||
* Fix typo in preserveViewport handling (#77).
|
||||
* Fix updateMulti timer leak after multiple Viewer.open() calls (#76).
|
||||
* Minor documentation fixes.
|
||||
|
||||
0.9.124:
|
||||
|
||||
|
0
images/fullpage_grouphover.png
Executable file → Normal file
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
0
images/fullpage_hover.png
Executable file → Normal file
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
0
images/fullpage_pressed.png
Executable file → Normal file
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
0
images/fullpage_rest.png
Executable file → Normal file
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
0
images/home_grouphover.png
Executable file → Normal file
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
0
images/home_hover.png
Executable file → Normal file
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
0
images/home_pressed.png
Executable file → Normal file
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
0
images/home_rest.png
Executable file → Normal file
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
BIN
images/rotateleft_grouphover.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
images/rotateleft_hover.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
images/rotateleft_pressed.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
images/rotateleft_rest.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
images/rotateright_grouphover.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
images/rotateright_hover.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
images/rotateright_pressed.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
images/rotateright_rest.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
0
images/zoomin_grouphover.png
Executable file → Normal file
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
0
images/zoomin_hover.png
Executable file → Normal file
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
0
images/zoomin_pressed.png
Executable file → Normal file
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
0
images/zoomin_rest.png
Executable file → Normal file
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
0
images/zoomout_grouphover.png
Executable file → Normal file
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
0
images/zoomout_hover.png
Executable file → Normal file
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
0
images/zoomout_pressed.png
Executable file → Normal file
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
0
images/zoomout_rest.png
Executable file → Normal file
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
@ -1,21 +0,0 @@
|
||||
(c) Christopher Thatcher 2011, 2012. All rights reserved.
|
||||
|
||||
Licensed with the MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
@ -1,36 +0,0 @@
|
||||
This license is preserved from the OpenSeadragon project at
|
||||
http://openseadragon.codeplex.com/ as per the text below.
|
||||
|
||||
-------------------------------------
|
||||
|
||||
License: New BSD License (BSD)
|
||||
Copyright (c) 2010, OpenSeadragon
|
||||
All rights reserved.
|
||||
|
||||
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.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of OpenSeadragon 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.
|
||||
|
||||
-------------------------------------
|
@ -3,12 +3,19 @@
|
||||
[
|
||||
{
|
||||
"path": ".",
|
||||
"file_exclude_patterns": ["*.sublime-project", "*.sublime-workspace"]
|
||||
"file_exclude_patterns": [
|
||||
"*.sublime-project",
|
||||
"*.sublime-workspace"
|
||||
],
|
||||
"folder_exclude_patterns": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
],
|
||||
"settings":
|
||||
{
|
||||
"tab_size": 4,
|
||||
"translate_tabs_to_spaces": true
|
||||
"translate_tabs_to_spaces": true,
|
||||
"trim_trailing_white_space_on_save": true
|
||||
}
|
||||
}
|
||||
|
23
package.json
@ -1,18 +1,19 @@
|
||||
{
|
||||
"name": "OpenSeadragon",
|
||||
"version": "0.9.124",
|
||||
"version": "1.0.0",
|
||||
"description": "Provides a smooth, zoomable user interface for HTML/Javascript.",
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.0",
|
||||
"grunt-contrib-compress": "~0.4.0",
|
||||
"grunt-contrib-concat": "~0.1.2",
|
||||
"grunt-contrib-jshint": "~0.1.1",
|
||||
"grunt-contrib-uglify": "~0.1.1",
|
||||
"grunt-contrib-qunit": "~0.2.0",
|
||||
"grunt-contrib-connect": "~0.1.2",
|
||||
"grunt-contrib-watch": "~0.2.0",
|
||||
"grunt-contrib-clean": "~0.4.0",
|
||||
"grunt-git-describe": "~2.0.0"
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-contrib-compress": "~0.5.2",
|
||||
"grunt-contrib-concat": "~0.3.0",
|
||||
"grunt-contrib-jshint": "~0.7.2",
|
||||
"grunt-contrib-uglify": "~0.2.7",
|
||||
"grunt-contrib-qunit": "~0.3.0",
|
||||
"grunt-contrib-connect": "~0.5.0",
|
||||
"grunt-contrib-watch": "~0.5.3",
|
||||
"grunt-contrib-clean": "~0.5.0",
|
||||
"grunt-git-describe": "~2.0.0",
|
||||
"grunt-text-replace": "~0.3.9"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "grunt test"
|
||||
|
317
src/button.js
@ -1,8 +1,49 @@
|
||||
/*
|
||||
* OpenSeadragon - Button
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* An enumeration of button states including, REST, GROUP, HOVER, and DOWN
|
||||
* An enumeration of button states
|
||||
* @member ButtonState
|
||||
* @memberof OpenSeadragon
|
||||
* @static
|
||||
* @type {Object}
|
||||
* @property {Number} REST
|
||||
* @property {Number} GROUP
|
||||
* @property {Number} HOVER
|
||||
* @property {Number} DOWN
|
||||
*/
|
||||
$.ButtonState = {
|
||||
REST: 0,
|
||||
@ -12,44 +53,36 @@ $.ButtonState = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Manages events, hover states for individual buttons, tool-tips, as well
|
||||
* as fading the bottons out when the user has not interacted with them
|
||||
* @class Button
|
||||
* @classdesc Manages events, hover states for individual buttons, tool-tips, as well
|
||||
* as fading the buttons out when the user has not interacted with them
|
||||
* for a specified period.
|
||||
* @class
|
||||
* @extends OpenSeadragon.EventHandler
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
* @extends OpenSeadragon.EventSource
|
||||
* @param {Object} options
|
||||
* @param {String} options.tooltip Provides context help for the button we the
|
||||
* @param {Element} [options.element=null] Element to use as the button. If not specified, an HTML <button> element is created.
|
||||
* @param {String} [options.tooltip=null] Provides context help for the button when the
|
||||
* user hovers over it.
|
||||
* @param {String} options.srcRest URL of image to use in 'rest' state
|
||||
* @param {String} options.srcGroup URL of image to use in 'up' state
|
||||
* @param {String} options.srcHover URL of image to use in 'hover' state
|
||||
* @param {String} options.srcDown URL of image to use in 'domn' state
|
||||
* @param {Element} [options.element] Element to use as a container for the
|
||||
* button.
|
||||
* @property {String} tooltip Provides context help for the button we the
|
||||
* user hovers over it.
|
||||
* @property {String} srcRest URL of image to use in 'rest' state
|
||||
* @property {String} srcGroup URL of image to use in 'up' state
|
||||
* @property {String} srcHover URL of image to use in 'hover' state
|
||||
* @property {String} srcDown URL of image to use in 'domn' state
|
||||
* @property {Object} config Configurable settings for this button. DEPRECATED.
|
||||
* @property {Element} [element] Element to use as a container for the
|
||||
* button.
|
||||
* @property {Number} fadeDelay How long to wait before fading
|
||||
* @property {Number} fadeLength How long should it take to fade the button.
|
||||
* @property {Number} fadeBeginTime When the button last began to fade.
|
||||
* @property {Boolean} shouldFade Whether this button should fade after user
|
||||
* stops interacting with the viewport.
|
||||
this.fadeDelay = 0; // begin fading immediately
|
||||
this.fadeLength = 2000; // fade over a period of 2 seconds
|
||||
this.fadeBeginTime = null;
|
||||
this.shouldFade = false;
|
||||
* @param {String} [options.srcRest=null] URL of image to use in 'rest' state.
|
||||
* @param {String} [options.srcGroup=null] URL of image to use in 'up' state.
|
||||
* @param {String} [options.srcHover=null] URL of image to use in 'hover' state.
|
||||
* @param {String} [options.srcDown=null] URL of image to use in 'down' state.
|
||||
* @param {Number} [options.fadeDelay=0] How long to wait before fading.
|
||||
* @param {Number} [options.fadeLength=2000] How long should it take to fade the button.
|
||||
* @param {OpenSeadragon.EventHandler} [options.onPress=null] Event handler callback for {@link OpenSeadragon.Button.event:press}.
|
||||
* @param {OpenSeadragon.EventHandler} [options.onRelease=null] Event handler callback for {@link OpenSeadragon.Button.event:release}.
|
||||
* @param {OpenSeadragon.EventHandler} [options.onClick=null] Event handler callback for {@link OpenSeadragon.Button.event:click}.
|
||||
* @param {OpenSeadragon.EventHandler} [options.onEnter=null] Event handler callback for {@link OpenSeadragon.Button.event:enter}.
|
||||
* @param {OpenSeadragon.EventHandler} [options.onExit=null] Event handler callback for {@link OpenSeadragon.Button.event:exit}.
|
||||
* @param {OpenSeadragon.EventHandler} [options.onFocus=null] Event handler callback for {@link OpenSeadragon.Button.event:focus}.
|
||||
* @param {OpenSeadragon.EventHandler} [options.onBlur=null] Event handler callback for {@link OpenSeadragon.Button.event:blur}.
|
||||
*/
|
||||
$.Button = function( options ) {
|
||||
|
||||
var _this = this;
|
||||
|
||||
$.EventHandler.call( this );
|
||||
$.EventSource.call( this );
|
||||
|
||||
$.extend( true, this, {
|
||||
|
||||
@ -60,9 +93,17 @@ $.Button = function( options ) {
|
||||
srcDown: null,
|
||||
clickTimeThreshold: $.DEFAULT_SETTINGS.clickTimeThreshold,
|
||||
clickDistThreshold: $.DEFAULT_SETTINGS.clickDistThreshold,
|
||||
// begin fading immediately
|
||||
/**
|
||||
* How long to wait before fading.
|
||||
* @member {Number} fadeDelay
|
||||
* @memberof OpenSeadragon.Button#
|
||||
*/
|
||||
fadeDelay: 0,
|
||||
// fade over a period of 2 seconds
|
||||
/**
|
||||
* How long should it take to fade the button.
|
||||
* @member {Number} fadeLength
|
||||
* @memberof OpenSeadragon.Button#
|
||||
*/
|
||||
fadeLength: 2000,
|
||||
onPress: null,
|
||||
onRelease: null,
|
||||
@ -74,21 +115,28 @@ $.Button = function( options ) {
|
||||
|
||||
}, options );
|
||||
|
||||
this.element = options.element || $.makeNeutralElement( "button" );
|
||||
this.element.href = this.element.href || '#';
|
||||
/**
|
||||
* The button element.
|
||||
* @member {Element} element
|
||||
* @memberof OpenSeadragon.Button#
|
||||
*/
|
||||
this.element = options.element || $.makeNeutralElement( "div" );
|
||||
|
||||
//if the user has specified the element to bind the control to explicitly
|
||||
//then do not add the default control images
|
||||
if( !options.element ){
|
||||
if ( !options.element ) {
|
||||
this.imgRest = $.makeTransparentImage( this.srcRest );
|
||||
this.imgGroup = $.makeTransparentImage( this.srcGroup );
|
||||
this.imgHover = $.makeTransparentImage( this.srcHover );
|
||||
this.imgDown = $.makeTransparentImage( this.srcDown );
|
||||
|
||||
this.element.appendChild( this.imgRest );
|
||||
this.element.appendChild( this.imgGroup );
|
||||
this.element.appendChild( this.imgHover );
|
||||
this.element.appendChild( this.imgDown );
|
||||
this.imgRest.alt =
|
||||
this.imgGroup.alt =
|
||||
this.imgHover.alt =
|
||||
this.imgDown.alt =
|
||||
this.tooltip;
|
||||
|
||||
this.element.style.position = "relative";
|
||||
|
||||
this.imgGroup.style.position =
|
||||
this.imgHover.style.position =
|
||||
@ -115,85 +163,192 @@ $.Button = function( options ) {
|
||||
this.imgDown.style.top =
|
||||
"";
|
||||
}
|
||||
|
||||
this.element.appendChild( this.imgRest );
|
||||
this.element.appendChild( this.imgGroup );
|
||||
this.element.appendChild( this.imgHover );
|
||||
this.element.appendChild( this.imgDown );
|
||||
}
|
||||
|
||||
|
||||
this.addHandler( "onPress", this.onPress );
|
||||
this.addHandler( "onRelease", this.onRelease );
|
||||
this.addHandler( "onClick", this.onClick );
|
||||
this.addHandler( "onEnter", this.onEnter );
|
||||
this.addHandler( "onExit", this.onExit );
|
||||
this.addHandler( "onFocus", this.onFocus );
|
||||
this.addHandler( "onBlur", this.onBlur );
|
||||
this.addHandler( "press", this.onPress );
|
||||
this.addHandler( "release", this.onRelease );
|
||||
this.addHandler( "click", this.onClick );
|
||||
this.addHandler( "enter", this.onEnter );
|
||||
this.addHandler( "exit", this.onExit );
|
||||
this.addHandler( "focus", this.onFocus );
|
||||
this.addHandler( "blur", this.onBlur );
|
||||
|
||||
/**
|
||||
* The button's current state.
|
||||
* @member {OpenSeadragon.ButtonState} currentState
|
||||
* @memberof OpenSeadragon.Button#
|
||||
*/
|
||||
this.currentState = $.ButtonState.GROUP;
|
||||
|
||||
// When the button last began to fade.
|
||||
this.fadeBeginTime = null;
|
||||
// Whether this button should fade after user stops interacting with the viewport.
|
||||
this.shouldFade = false;
|
||||
|
||||
this.element.style.display = "inline-block";
|
||||
this.element.style.position = "relative";
|
||||
this.element.title = this.tooltip;
|
||||
|
||||
/**
|
||||
* Tracks mouse/touch/key events on the button.
|
||||
* @member {OpenSeadragon.MouseTracker} tracker
|
||||
* @memberof OpenSeadragon.Button#
|
||||
*/
|
||||
this.tracker = new $.MouseTracker({
|
||||
|
||||
element: this.element,
|
||||
clickTimeThreshold: this.clickTimeThreshold,
|
||||
clickDistThreshold: this.clickDistThreshold,
|
||||
|
||||
enterHandler: function( tracker, position, buttonDownElement, buttonDownAny ) {
|
||||
if ( buttonDownElement ) {
|
||||
enterHandler: function( event ) {
|
||||
if ( event.insideElementPressed ) {
|
||||
inTo( _this, $.ButtonState.DOWN );
|
||||
_this.raiseEvent( "onEnter", _this );
|
||||
} else if ( !buttonDownAny ) {
|
||||
/**
|
||||
* Raised when the cursor enters the Button element.
|
||||
*
|
||||
* @event enter
|
||||
* @memberof OpenSeadragon.Button
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Button} eventSource - A reference to the Button which raised the event.
|
||||
* @property {Object} originalEvent - The original DOM event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( "enter", { originalEvent: event.originalEvent } );
|
||||
} else if ( !event.buttonDownAny ) {
|
||||
inTo( _this, $.ButtonState.HOVER );
|
||||
}
|
||||
},
|
||||
|
||||
focusHandler: function( tracker, position, buttonDownElement, buttonDownAny ) {
|
||||
this.enterHandler( tracker, position, buttonDownElement, buttonDownAny );
|
||||
_this.raiseEvent( "onFocus", _this );
|
||||
focusHandler: function ( event ) {
|
||||
this.enterHandler( event );
|
||||
/**
|
||||
* Raised when the Button element receives focus.
|
||||
*
|
||||
* @event focus
|
||||
* @memberof OpenSeadragon.Button
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Button} eventSource - A reference to the Button which raised the event.
|
||||
* @property {Object} originalEvent - The original DOM event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( "focus", { originalEvent: event.originalEvent } );
|
||||
},
|
||||
|
||||
exitHandler: function( tracker, position, buttonDownElement, buttonDownAny ) {
|
||||
exitHandler: function( event ) {
|
||||
outTo( _this, $.ButtonState.GROUP );
|
||||
if ( buttonDownElement ) {
|
||||
_this.raiseEvent( "onExit", _this );
|
||||
if ( event.insideElementPressed ) {
|
||||
/**
|
||||
* Raised when the cursor leaves the Button element.
|
||||
*
|
||||
* @event exit
|
||||
* @memberof OpenSeadragon.Button
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Button} eventSource - A reference to the Button which raised the event.
|
||||
* @property {Object} originalEvent - The original DOM event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( "exit", { originalEvent: event.originalEvent } );
|
||||
}
|
||||
},
|
||||
|
||||
blurHandler: function( tracker, position, buttonDownElement, buttonDownAny ) {
|
||||
this.exitHandler( tracker, position, buttonDownElement, buttonDownAny );
|
||||
_this.raiseEvent( "onBlur", _this );
|
||||
blurHandler: function ( event ) {
|
||||
this.exitHandler( event );
|
||||
/**
|
||||
* Raised when the Button element loses focus.
|
||||
*
|
||||
* @event blur
|
||||
* @memberof OpenSeadragon.Button
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Button} eventSource - A reference to the Button which raised the event.
|
||||
* @property {Object} originalEvent - The original DOM event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( "blur", { originalEvent: event.originalEvent } );
|
||||
},
|
||||
|
||||
pressHandler: function( tracker, position ) {
|
||||
pressHandler: function ( event ) {
|
||||
inTo( _this, $.ButtonState.DOWN );
|
||||
_this.raiseEvent( "onPress", _this );
|
||||
/**
|
||||
* Raised when a mouse button is pressed or touch occurs in the Button element.
|
||||
*
|
||||
* @event press
|
||||
* @memberof OpenSeadragon.Button
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Button} eventSource - A reference to the Button which raised the event.
|
||||
* @property {Object} originalEvent - The original DOM event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( "press", { originalEvent: event.originalEvent } );
|
||||
},
|
||||
|
||||
releaseHandler: function( tracker, position, insideElementPress, insideElementRelease ) {
|
||||
if ( insideElementPress && insideElementRelease ) {
|
||||
releaseHandler: function( event ) {
|
||||
if ( event.insideElementPressed && event.insideElementReleased ) {
|
||||
outTo( _this, $.ButtonState.HOVER );
|
||||
_this.raiseEvent( "onRelease", _this );
|
||||
} else if ( insideElementPress ) {
|
||||
/**
|
||||
* Raised when the mouse button is released or touch ends in the Button element.
|
||||
*
|
||||
* @event release
|
||||
* @memberof OpenSeadragon.Button
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Button} eventSource - A reference to the Button which raised the event.
|
||||
* @property {Object} originalEvent - The original DOM event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( "release", { originalEvent: event.originalEvent } );
|
||||
} else if ( event.insideElementPressed ) {
|
||||
outTo( _this, $.ButtonState.GROUP );
|
||||
} else {
|
||||
inTo( _this, $.ButtonState.HOVER );
|
||||
}
|
||||
},
|
||||
|
||||
clickHandler: function( tracker, position, quick, shift ) {
|
||||
if ( quick ) {
|
||||
_this.raiseEvent("onClick", _this);
|
||||
clickHandler: function( event ) {
|
||||
if ( event.quick ) {
|
||||
/**
|
||||
* Raised when a mouse button is pressed and released or touch is initiated and ended in the Button element within the time and distance threshold.
|
||||
*
|
||||
* @event click
|
||||
* @memberof OpenSeadragon.Button
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Button} eventSource - A reference to the Button which raised the event.
|
||||
* @property {Object} originalEvent - The original DOM event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent("click", { originalEvent: event.originalEvent });
|
||||
}
|
||||
},
|
||||
|
||||
keyHandler: function( tracker, key ){
|
||||
//console.log( "%s : handling key %s!", _this.tooltip, key);
|
||||
if( 13 === key ){
|
||||
_this.raiseEvent( "onClick", _this );
|
||||
_this.raiseEvent( "onRelease", _this );
|
||||
keyHandler: function( event ){
|
||||
//console.log( "%s : handling key %s!", _this.tooltip, event.keyCode);
|
||||
if( 13 === event.keyCode ){
|
||||
/***
|
||||
* Raised when a mouse button is pressed and released or touch is initiated and ended in the Button element within the time and distance threshold.
|
||||
*
|
||||
* @event click
|
||||
* @memberof OpenSeadragon.Button
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Button} eventSource - A reference to the Button which raised the event.
|
||||
* @property {Object} originalEvent - The original DOM event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( "click", { originalEvent: event.originalEvent } );
|
||||
/***
|
||||
* Raised when the mouse button is released or touch ends in the Button element.
|
||||
*
|
||||
* @event release
|
||||
* @memberof OpenSeadragon.Button
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Button} eventSource - A reference to the Button which raised the event.
|
||||
* @property {Object} originalEvent - The original DOM event.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( "release", { originalEvent: event.originalEvent } );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -204,13 +359,12 @@ $.Button = function( options ) {
|
||||
outTo( this, $.ButtonState.REST );
|
||||
};
|
||||
|
||||
$.extend( $.Button.prototype, $.EventHandler.prototype, {
|
||||
$.extend( $.Button.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.Button.prototype */{
|
||||
|
||||
/**
|
||||
* TODO: Determine what this function is intended to do and if it's actually
|
||||
* useful as an API point.
|
||||
* @function
|
||||
* @name OpenSeadragon.Button.prototype.notifyGroupEnter
|
||||
*/
|
||||
notifyGroupEnter: function() {
|
||||
inTo( this, $.ButtonState.GROUP );
|
||||
@ -220,18 +374,23 @@ $.extend( $.Button.prototype, $.EventHandler.prototype, {
|
||||
* TODO: Determine what this function is intended to do and if it's actually
|
||||
* useful as an API point.
|
||||
* @function
|
||||
* @name OpenSeadragon.Button.prototype.notifyGroupExit
|
||||
*/
|
||||
notifyGroupExit: function() {
|
||||
outTo( this, $.ButtonState.REST );
|
||||
},
|
||||
|
||||
/**
|
||||
* @function
|
||||
*/
|
||||
disable: function(){
|
||||
this.notifyGroupExit();
|
||||
this.element.disabled = true;
|
||||
$.setElementOpacity( this.element, 0.2, true );
|
||||
},
|
||||
|
||||
/**
|
||||
* @function
|
||||
*/
|
||||
enable: function(){
|
||||
this.element.disabled = false;
|
||||
$.setElementOpacity( this.element, 1.0, true );
|
||||
@ -253,7 +412,7 @@ function updateFade( button ) {
|
||||
opacity;
|
||||
|
||||
if ( button.shouldFade ) {
|
||||
currentTime = +new Date();
|
||||
currentTime = $.now();
|
||||
deltaTime = currentTime - button.fadeBeginTime;
|
||||
opacity = 1.0 - deltaTime / button.fadeLength;
|
||||
opacity = Math.min( 1.0, opacity );
|
||||
@ -271,7 +430,7 @@ function updateFade( button ) {
|
||||
|
||||
function beginFading( button ) {
|
||||
button.shouldFade = true;
|
||||
button.fadeBeginTime = +new Date() + button.fadeDelay;
|
||||
button.fadeBeginTime = $.now() + button.fadeDelay;
|
||||
window.setTimeout( function(){
|
||||
scheduleFade( button );
|
||||
}, button.fadeDelay );
|
||||
|
@ -1,41 +1,74 @@
|
||||
/*
|
||||
* OpenSeadragon - ButtonGroup
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
/**
|
||||
* Manages events on groups of buttons.
|
||||
* @class
|
||||
* @param {Object} options - a dictionary of settings applied against the entire
|
||||
* group of buttons
|
||||
* @param {Array} options.buttons Array of buttons
|
||||
* @param {Element} [options.group] Element to use as the container,
|
||||
* @param {Object} options.config Object with Viewer settings ( TODO: is
|
||||
* this actually used anywhere? )
|
||||
* @param {Function} [options.enter] Function callback for when the mouse
|
||||
* enters group
|
||||
* @param {Function} [options.exit] Function callback for when mouse leaves
|
||||
* the group
|
||||
* @param {Function} [options.release] Function callback for when mouse is
|
||||
* released
|
||||
* @property {Array} buttons - An array containing the buttons themselves.
|
||||
* @property {Element} element - The shared container for the buttons.
|
||||
* @property {Object} config - Configurable settings for the group of buttons.
|
||||
* @property {OpenSeadragon.MouseTracker} tracker - Tracks mouse events accross
|
||||
* the group of buttons.
|
||||
* @class ButtonGroup
|
||||
* @classdesc Manages events on groups of buttons.
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
* @param {Object} options - A dictionary of settings applied against the entire group of buttons.
|
||||
* @param {Array} options.buttons Array of buttons
|
||||
* @param {Element} [options.element] Element to use as the container
|
||||
**/
|
||||
$.ButtonGroup = function( options ) {
|
||||
|
||||
$.extend( true, this, {
|
||||
/**
|
||||
* An array containing the buttons themselves.
|
||||
* @member {Array} buttons
|
||||
* @memberof OpenSeadragon.ButtonGroup#
|
||||
*/
|
||||
buttons: [],
|
||||
clickTimeThreshold: $.DEFAULT_SETTINGS.clickTimeThreshold,
|
||||
clickDistThreshold: $.DEFAULT_SETTINGS.clickDistThreshold,
|
||||
labelText: ""
|
||||
}, options );
|
||||
|
||||
// copy the botton elements
|
||||
// copy the button elements TODO: Why?
|
||||
var buttons = this.buttons.concat([]),
|
||||
_this = this,
|
||||
i;
|
||||
|
||||
this.element = options.element || $.makeNeutralElement( "fieldgroup" );
|
||||
/**
|
||||
* The shared container for the buttons.
|
||||
* @member {Element} element
|
||||
* @memberof OpenSeadragon.ButtonGroup#
|
||||
*/
|
||||
this.element = options.element || $.makeNeutralElement( "div" );
|
||||
|
||||
// TODO What if there IS an options.group specified?
|
||||
if( !options.group ){
|
||||
this.label = $.makeNeutralElement( "label" );
|
||||
//TODO: support labels for ButtonGroups
|
||||
@ -47,33 +80,32 @@ $.ButtonGroup = function( options ) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks mouse/touch/key events accross the group of buttons.
|
||||
* @member {OpenSeadragon.MouseTracker} tracker
|
||||
* @memberof OpenSeadragon.ButtonGroup#
|
||||
*/
|
||||
this.tracker = new $.MouseTracker({
|
||||
element: this.element,
|
||||
clickTimeThreshold: this.clickTimeThreshold,
|
||||
clickDistThreshold: this.clickDistThreshold,
|
||||
enterHandler: function() {
|
||||
enterHandler: function ( event ) {
|
||||
var i;
|
||||
for ( i = 0; i < _this.buttons.length; i++ ) {
|
||||
_this.buttons[ i ].notifyGroupEnter();
|
||||
}
|
||||
},
|
||||
exitHandler: function() {
|
||||
var i,
|
||||
buttonDownElement = arguments.length > 2 ?
|
||||
arguments[ 2 ] :
|
||||
null;
|
||||
if ( !buttonDownElement ) {
|
||||
exitHandler: function ( event ) {
|
||||
var i;
|
||||
if ( !event.insideElementPressed ) {
|
||||
for ( i = 0; i < _this.buttons.length; i++ ) {
|
||||
_this.buttons[ i ].notifyGroupExit();
|
||||
}
|
||||
}
|
||||
},
|
||||
releaseHandler: function() {
|
||||
var i,
|
||||
insideElementRelease = arguments.length > 3 ?
|
||||
arguments[ 3 ] :
|
||||
null;
|
||||
if ( !insideElementRelease ) {
|
||||
releaseHandler: function ( event ) {
|
||||
var i;
|
||||
if ( !event.insideElementReleased ) {
|
||||
for ( i = 0; i < _this.buttons.length; i++ ) {
|
||||
_this.buttons[ i ].notifyGroupExit();
|
||||
}
|
||||
@ -82,26 +114,26 @@ $.ButtonGroup = function( options ) {
|
||||
}).setTracking( true );
|
||||
};
|
||||
|
||||
$.ButtonGroup.prototype = {
|
||||
$.ButtonGroup.prototype = /** @lends OpenSeadragon.ButtonGroup.prototype */{
|
||||
|
||||
/**
|
||||
* TODO: Figure out why this is used on the public API and if a more useful
|
||||
* api can be created.
|
||||
* @function
|
||||
* @name OpenSeadragon.ButtonGroup.prototype.emulateEnter
|
||||
* @private
|
||||
*/
|
||||
emulateEnter: function() {
|
||||
this.tracker.enterHandler();
|
||||
this.tracker.enterHandler( { eventSource: this.tracker } );
|
||||
},
|
||||
|
||||
/**
|
||||
* TODO: Figure out why this is used on the public API and if a more useful
|
||||
* api can be created.
|
||||
* @function
|
||||
* @name OpenSeadragon.ButtonGroup.prototype.emulateExit
|
||||
* @private
|
||||
*/
|
||||
emulateExit: function() {
|
||||
this.tracker.exitHandler();
|
||||
this.tracker.exitHandler( { eventSource: this.tracker } );
|
||||
}
|
||||
};
|
||||
|
||||
|
164
src/control.js
@ -1,62 +1,158 @@
|
||||
/*
|
||||
* OpenSeadragon - Control
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* An enumeration of supported locations where controls can be anchored,
|
||||
* including NONE, TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT, and BOTTOM_LEFT.
|
||||
* The anchoring is always relative to the container
|
||||
* An enumeration of supported locations where controls can be anchored.
|
||||
* The anchoring is always relative to the container.
|
||||
* @member ControlAnchor
|
||||
* @memberof OpenSeadragon
|
||||
* @static
|
||||
* @type {Object}
|
||||
* @property {Number} NONE
|
||||
* @property {Number} TOP_LEFT
|
||||
* @property {Number} TOP_RIGHT
|
||||
* @property {Number} BOTTOM_LEFT
|
||||
* @property {Number} BOTTOM_RIGHT
|
||||
* @property {Number} ABSOLUTE
|
||||
*/
|
||||
$.ControlAnchor = {
|
||||
NONE: 0,
|
||||
TOP_LEFT: 1,
|
||||
TOP_RIGHT: 2,
|
||||
BOTTOM_RIGHT: 3,
|
||||
BOTTOM_LEFT: 4
|
||||
BOTTOM_LEFT: 4,
|
||||
ABSOLUTE: 5
|
||||
};
|
||||
|
||||
/**
|
||||
* A Control represents any interface element which is meant to allow the user
|
||||
* @class Control
|
||||
* @classdesc A Control represents any interface element which is meant to allow the user
|
||||
* to interact with the zoomable interface. Any control can be anchored to any
|
||||
* element.
|
||||
* @class
|
||||
* @param {Element} element - the contol element to be anchored in the container.
|
||||
* @param {OpenSeadragon.ControlAnchor} anchor - the location to anchor at.
|
||||
* @param {Element} container - the element to control will be anchored too.
|
||||
*
|
||||
* @property {Element} element - the element providing the user interface with
|
||||
* some type of control. Eg a zoom-in button
|
||||
* @property {OpenSeadragon.ControlAnchor} anchor - the position of the control
|
||||
* @memberof OpenSeadragon
|
||||
* @param {Element} element - the control element to be anchored in the container.
|
||||
* @param {Object } options - All required and optional settings for configuring a control element.
|
||||
* @param {OpenSeadragon.ControlAnchor} [options.anchor=OpenSeadragon.ControlAnchor.NONE] - the position of the control
|
||||
* relative to the container.
|
||||
* @property {Element} container - the element within with the control is
|
||||
* positioned.
|
||||
* @property {Element} wrapper - a nuetral element surrounding the control
|
||||
* element.
|
||||
* @param {Boolean} [options.attachToViewer=true] - Whether the control should be added directly to the viewer, or
|
||||
* directly to the container
|
||||
* @param {Boolean} [options.autoFade=true] - Whether the control should have the autofade behavior
|
||||
* @param {Element} container - the element to control will be anchored too.
|
||||
*/
|
||||
$.Control = function ( element, anchor, container ) {
|
||||
$.Control = function ( element, options, container ) {
|
||||
var parent = element.parentNode;
|
||||
if (typeof options === 'number')
|
||||
{
|
||||
$.console.error("Passing an anchor directly into the OpenSeadragon.Control constructor is deprecated; " +
|
||||
"please use an options object instead. " +
|
||||
"Support for this deprecated variant is scheduled for removal in December 2013");
|
||||
options = {anchor: options};
|
||||
}
|
||||
options.attachToViewer = (typeof options.attachToViewer === 'undefined') ? true : options.attachToViewer;
|
||||
/**
|
||||
* True if the control should have autofade behavior.
|
||||
* @member {Boolean} autoFade
|
||||
* @memberof OpenSeadragon.Control#
|
||||
*/
|
||||
this.autoFade = (typeof options.autoFade === 'undefined') ? true : options.autoFade;
|
||||
/**
|
||||
* The element providing the user interface with some type of control (e.g. a zoom-in button).
|
||||
* @member {Element} element
|
||||
* @memberof OpenSeadragon.Control#
|
||||
*/
|
||||
this.element = element;
|
||||
this.anchor = anchor;
|
||||
/**
|
||||
* The position of the Control relative to its container.
|
||||
* @member {OpenSeadragon.ControlAnchor} anchor
|
||||
* @memberof OpenSeadragon.Control#
|
||||
*/
|
||||
this.anchor = options.anchor;
|
||||
/**
|
||||
* The Control's containing element.
|
||||
* @member {Element} container
|
||||
* @memberof OpenSeadragon.Control#
|
||||
*/
|
||||
this.container = container;
|
||||
this.wrapper = $.makeNeutralElement( "span" );
|
||||
this.wrapper.style.display = "inline-block";
|
||||
/**
|
||||
* A neutral element surrounding the control element.
|
||||
* @member {Element} wrapper
|
||||
* @memberof OpenSeadragon.Control#
|
||||
*/
|
||||
if ( this.anchor == $.ControlAnchor.ABSOLUTE ) {
|
||||
this.wrapper = $.makeNeutralElement( "div" );
|
||||
this.wrapper.style.position = "absolute";
|
||||
this.wrapper.style.top = typeof ( options.top ) == "number" ? ( options.top + 'px' ) : options.top;
|
||||
this.wrapper.style.left = typeof ( options.left ) == "number" ? (options.left + 'px' ) : options.left;
|
||||
this.wrapper.style.height = typeof ( options.height ) == "number" ? ( options.height + 'px' ) : options.height;
|
||||
this.wrapper.style.width = typeof ( options.width ) == "number" ? ( options.width + 'px' ) : options.width;
|
||||
this.wrapper.style.margin = "0px";
|
||||
this.wrapper.style.padding = "0px";
|
||||
|
||||
this.element.style.position = "relative";
|
||||
this.element.style.top = "0px";
|
||||
this.element.style.left = "0px";
|
||||
this.element.style.height = "100%";
|
||||
this.element.style.width = "100%";
|
||||
} else {
|
||||
this.wrapper = $.makeNeutralElement( "div" );
|
||||
this.wrapper.style.display = "inline-block";
|
||||
if ( this.anchor == $.ControlAnchor.NONE ) {
|
||||
// IE6 fix
|
||||
this.wrapper.style.width = this.wrapper.style.height = "100%";
|
||||
}
|
||||
}
|
||||
this.wrapper.appendChild( this.element );
|
||||
|
||||
if ( this.anchor == $.ControlAnchor.NONE ) {
|
||||
// IE6 fix
|
||||
this.wrapper.style.width = this.wrapper.style.height = "100%";
|
||||
}
|
||||
|
||||
if ( this.anchor == $.ControlAnchor.TOP_RIGHT ||
|
||||
this.anchor == $.ControlAnchor.BOTTOM_RIGHT ) {
|
||||
this.container.insertBefore(
|
||||
this.wrapper,
|
||||
this.container.firstChild
|
||||
);
|
||||
if (options.attachToViewer ) {
|
||||
if ( this.anchor == $.ControlAnchor.TOP_RIGHT ||
|
||||
this.anchor == $.ControlAnchor.BOTTOM_RIGHT ) {
|
||||
this.container.insertBefore(
|
||||
this.wrapper,
|
||||
this.container.firstChild
|
||||
);
|
||||
} else {
|
||||
this.container.appendChild( this.wrapper );
|
||||
}
|
||||
} else {
|
||||
this.container.appendChild( this.wrapper );
|
||||
parent.appendChild( this.wrapper );
|
||||
}
|
||||
};
|
||||
|
||||
$.Control.prototype = {
|
||||
$.Control.prototype = /** @lends OpenSeadragon.Control.prototype */{
|
||||
|
||||
/**
|
||||
* Removes the control from the container.
|
||||
@ -83,7 +179,7 @@ $.Control.prototype = {
|
||||
*/
|
||||
setVisible: function( visible ) {
|
||||
this.wrapper.style.display = visible ?
|
||||
"inline-block" :
|
||||
( this.anchor == $.ControlAnchor.ABSOLUTE ? 'block' : 'inline-block' ) :
|
||||
"none";
|
||||
},
|
||||
|
||||
|
@ -1,10 +1,43 @@
|
||||
/*
|
||||
* OpenSeadragon - ControlDock
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
//id hash for private properties;
|
||||
var THIS = {};
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @class ControlDock
|
||||
* @classdesc Provides a container element (a <form> element) with support for the layout of control elements.
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
*/
|
||||
$.ControlDock = function( options ){
|
||||
var layouts = [ 'topleft', 'topright', 'bottomright', 'bottomleft'],
|
||||
@ -12,11 +45,17 @@
|
||||
i;
|
||||
|
||||
$.extend( true, this, {
|
||||
id: 'controldock-'+(+new Date())+'-'+Math.floor(Math.random()*1000000),
|
||||
container: $.makeNeutralElement('form'),
|
||||
id: 'controldock-'+$.now()+'-'+Math.floor(Math.random()*1000000),
|
||||
container: $.makeNeutralElement( 'div' ),
|
||||
controls: []
|
||||
}, options );
|
||||
|
||||
// Disable the form's submit; otherwise button clicks and return keys
|
||||
// can trigger it.
|
||||
this.container.onsubmit = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
if( this.element ){
|
||||
this.element = $.getElement( this.element );
|
||||
this.element.appendChild( this.container );
|
||||
@ -49,12 +88,12 @@
|
||||
this.container.appendChild( this.controls.bottomleft );
|
||||
};
|
||||
|
||||
$.ControlDock.prototype = {
|
||||
$.ControlDock.prototype = /** @lends OpenSeadragon.ControlDock.prototype */{
|
||||
|
||||
/**
|
||||
* @function
|
||||
*/
|
||||
addControl: function ( element, anchor ) {
|
||||
addControl: function ( element, controlOptions ) {
|
||||
element = $.getElement( element );
|
||||
var div = null;
|
||||
|
||||
@ -62,7 +101,7 @@
|
||||
return; // they're trying to add a duplicate control
|
||||
}
|
||||
|
||||
switch ( anchor ) {
|
||||
switch ( controlOptions.anchor ) {
|
||||
case $.ControlAnchor.TOP_RIGHT:
|
||||
div = this.controls.topright;
|
||||
element.style.position = "relative";
|
||||
@ -87,6 +126,11 @@
|
||||
element.style.paddingLeft = "0px";
|
||||
element.style.paddingTop = "0px";
|
||||
break;
|
||||
case $.ControlAnchor.ABSOLUTE:
|
||||
div = this.container;
|
||||
element.style.margin = "0px";
|
||||
element.style.padding = "0px";
|
||||
break;
|
||||
default:
|
||||
case $.ControlAnchor.NONE:
|
||||
div = this.container;
|
||||
@ -96,7 +140,7 @@
|
||||
}
|
||||
|
||||
this.controls.push(
|
||||
new $.Control( element, anchor, div )
|
||||
new $.Control( element, controlOptions, div )
|
||||
);
|
||||
element.style.display = "inline-block";
|
||||
},
|
||||
|
@ -1,10 +1,46 @@
|
||||
/*
|
||||
* OpenSeadragon - DisplayRect
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* A display rectanlge is very similar to the OpenSeadragon.Rect but adds two
|
||||
* @class DisplayRect
|
||||
* @classdesc A display rectangle is very similar to {@link OpenSeadragon.Rect} but adds two
|
||||
* fields, 'minLevel' and 'maxLevel' which denote the supported zoom levels
|
||||
* for this rectangle.
|
||||
* @class
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
* @extends OpenSeadragon.Rect
|
||||
* @param {Number} x The vector component 'x'.
|
||||
* @param {Number} y The vector component 'y'.
|
||||
@ -12,13 +48,21 @@
|
||||
* @param {Number} height The vector component 'width'.
|
||||
* @param {Number} minLevel The lowest zoom level supported.
|
||||
* @param {Number} maxLevel The highest zoom level supported.
|
||||
* @property {Number} minLevel The lowest zoom level supported.
|
||||
* @property {Number} maxLevel The highest zoom level supported.
|
||||
*/
|
||||
$.DisplayRect = function( x, y, width, height, minLevel, maxLevel ) {
|
||||
$.Rect.apply( this, [ x, y, width, height ] );
|
||||
|
||||
/**
|
||||
* The lowest zoom level supported.
|
||||
* @member {Number} minLevel
|
||||
* @memberof OpenSeadragon.DisplayRect#
|
||||
*/
|
||||
this.minLevel = minLevel;
|
||||
/**
|
||||
* The highest zoom level supported.
|
||||
* @member {Number} maxLevel
|
||||
* @memberof OpenSeadragon.DisplayRect#
|
||||
*/
|
||||
this.maxLevel = maxLevel;
|
||||
};
|
||||
|
||||
|
513
src/drawer.js
@ -1,3 +1,37 @@
|
||||
/*
|
||||
* OpenSeadragon - Drawer
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
var DEVICE_SCREEN = $.getWindowSize(),
|
||||
@ -10,37 +44,18 @@ var DEVICE_SCREEN = $.getWindowSize(),
|
||||
( BROWSER == $.BROWSERS.SAFARI && BROWSER_VERSION >= 4 ) ||
|
||||
( BROWSER == $.BROWSERS.CHROME && BROWSER_VERSION >= 2 ) ||
|
||||
( BROWSER == $.BROWSERS.IE && BROWSER_VERSION >= 9 )
|
||||
),
|
||||
);
|
||||
|
||||
USE_CANVAS = SUBPIXEL_RENDERING &&
|
||||
!( DEVICE_SCREEN.x <= 400 || DEVICE_SCREEN.y <= 400 ) &&
|
||||
!( navigator.appVersion.match( 'Mobile' ) ) &&
|
||||
$.isFunction( document.createElement( "canvas" ).getContext );
|
||||
|
||||
//console.error( 'USE_CANVAS ' + USE_CANVAS );
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @class Drawer
|
||||
* @classdesc Handles rendering of tiles for an {@link OpenSeadragon.Viewer}.
|
||||
* A new instance is created for each TileSource opened (see {@link OpenSeadragon.Viewer#drawer}).
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
* @param {OpenSeadragon.TileSource} source - Reference to Viewer tile source.
|
||||
* @param {OpenSeadragon.Viewport} viewport - Reference to Viewer viewport.
|
||||
* @param {Element} element - Reference to Viewer 'canvas'.
|
||||
* @property {OpenSeadragon.TileSource} source - Reference to Viewer tile source.
|
||||
* @property {OpenSeadragon.Viewport} viewport - Reference to Viewer viewport.
|
||||
* @property {Element} container - Reference to Viewer 'canvas'.
|
||||
* @property {Element|Canvas} canvas - TODO
|
||||
* @property {CanvasContext} context - TODO
|
||||
* @property {Object} config - Reference to Viewer config.
|
||||
* @property {Number} downloading - How many images are currently being loaded in parallel.
|
||||
* @property {Number} normHeight - Ratio of zoomable image height to width.
|
||||
* @property {Object} tilesMatrix - A '3d' dictionary [level][x][y] --> Tile.
|
||||
* @property {Array} tilesLoaded - An unordered list of Tiles with loaded images.
|
||||
* @property {Object} coverage - A '3d' dictionary [level][x][y] --> Boolean.
|
||||
* @property {Array} overlays - An unordered list of Overlays added.
|
||||
* @property {Array} lastDrawn - An unordered list of Tiles drawn last frame.
|
||||
* @property {Number} lastResetTime - Last time for which the drawer was reset.
|
||||
* @property {Boolean} midUpdate - Is the drawer currently updating the viewport?
|
||||
* @property {Boolean} updateAgain - Does the drawer need to update the viewort again?
|
||||
* @property {Element} element - DEPRECATED Alias for container.
|
||||
* @param {Element} element - Parent element.
|
||||
*/
|
||||
$.Drawer = function( options ) {
|
||||
|
||||
@ -51,30 +66,31 @@ $.Drawer = function( options ) {
|
||||
|
||||
if( !$.isPlainObject( options ) ){
|
||||
options = {
|
||||
source: args[ 0 ],
|
||||
viewport: args[ 1 ],
|
||||
element: args[ 2 ]
|
||||
source: args[ 0 ], // Reference to Viewer tile source.
|
||||
viewport: args[ 1 ], // Reference to Viewer viewport.
|
||||
element: args[ 2 ] // Parent element.
|
||||
};
|
||||
}
|
||||
|
||||
$.extend( true, this, {
|
||||
|
||||
//internal state properties
|
||||
downloading: 0,
|
||||
tilesMatrix: {},
|
||||
tilesLoaded: [],
|
||||
coverage: {},
|
||||
lastDrawn: [],
|
||||
lastResetTime: 0,
|
||||
midUpdate: false,
|
||||
updateAgain: true,
|
||||
viewer: null,
|
||||
downloading: 0, // How many images are currently being loaded in parallel.
|
||||
tilesMatrix: {}, // A '3d' dictionary [level][x][y] --> Tile.
|
||||
tilesLoaded: [], // An unordered list of Tiles with loaded images.
|
||||
coverage: {}, // A '3d' dictionary [level][x][y] --> Boolean.
|
||||
lastDrawn: [], // An unordered list of Tiles drawn last frame.
|
||||
lastResetTime: 0, // Last time for which the drawer was reset.
|
||||
midUpdate: false, // Is the drawer currently updating the viewport?
|
||||
updateAgain: true, // Does the drawer need to update the viewort again?
|
||||
|
||||
|
||||
//internal state / configurable settings
|
||||
overlays: [],
|
||||
collectionOverlays: {},
|
||||
collectionOverlays: {}, // For collection mode. Here an overlay is actually a viewer.
|
||||
|
||||
//configurable settings
|
||||
opacity: $.DEFAULT_SETTINGS.opacity,
|
||||
maxImageCacheCount: $.DEFAULT_SETTINGS.maxImageCacheCount,
|
||||
imageLoaderLimit: $.DEFAULT_SETTINGS.imageLoaderLimit,
|
||||
minZoomImageRatio: $.DEFAULT_SETTINGS.minZoomImageRatio,
|
||||
@ -85,73 +101,81 @@ $.Drawer = function( options ) {
|
||||
alwaysBlend: $.DEFAULT_SETTINGS.alwaysBlend,
|
||||
minPixelRatio: $.DEFAULT_SETTINGS.minPixelRatio,
|
||||
debugMode: $.DEFAULT_SETTINGS.debugMode,
|
||||
timeout: $.DEFAULT_SETTINGS.timeout
|
||||
timeout: $.DEFAULT_SETTINGS.timeout,
|
||||
crossOriginPolicy: $.DEFAULT_SETTINGS.crossOriginPolicy
|
||||
|
||||
}, options );
|
||||
|
||||
this.useCanvas = $.supportsCanvas && ( this.viewer ? this.viewer.useCanvas : true );
|
||||
/**
|
||||
* The parent element of this Drawer instance, passed in when the Drawer was created.
|
||||
* The parent of {@link OpenSeadragon.Drawer#canvas}.
|
||||
* @member {Element} container
|
||||
* @memberof OpenSeadragon.Drawer#
|
||||
*/
|
||||
this.container = $.getElement( this.element );
|
||||
this.canvas = $.makeNeutralElement( USE_CANVAS ? "canvas" : "div" );
|
||||
this.context = USE_CANVAS ? this.canvas.getContext( "2d" ) : null;
|
||||
/**
|
||||
* A <canvas> element if the browser supports them, otherwise a <div> element.
|
||||
* Child element of {@link OpenSeadragon.Drawer#container}.
|
||||
* @member {Element} canvas
|
||||
* @memberof OpenSeadragon.Drawer#
|
||||
*/
|
||||
this.canvas = $.makeNeutralElement( this.useCanvas ? "canvas" : "div" );
|
||||
/**
|
||||
* 2d drawing context for {@link OpenSeadragon.Drawer#canvas} if it's a <canvas> element, otherwise null.
|
||||
* @member {Object} context
|
||||
* @memberof OpenSeadragon.Drawer#
|
||||
*/
|
||||
this.context = this.useCanvas ? this.canvas.getContext( "2d" ) : null;
|
||||
// Ratio of zoomable image height to width.
|
||||
this.normHeight = this.source.dimensions.y / this.source.dimensions.x;
|
||||
/**
|
||||
* @member {Element} element
|
||||
* @memberof OpenSeadragon.Drawer#
|
||||
* @deprecated Alias for {@link OpenSeadragon.Drawer#container}.
|
||||
*/
|
||||
this.element = this.container;
|
||||
|
||||
// We force our container to ltr because our drawing math doesn't work in rtl.
|
||||
// This issue only affects our canvas renderer, but we do it always for consistency.
|
||||
// Note that this means overlays you want to be rtl need to be explicitly set to rtl.
|
||||
this.container.dir = 'ltr';
|
||||
|
||||
this.canvas.style.width = "100%";
|
||||
this.canvas.style.height = "100%";
|
||||
this.canvas.style.position = "absolute";
|
||||
$.setElementOpacity( this.canvas, this.opacity, true );
|
||||
|
||||
// explicit left-align
|
||||
this.container.style.textAlign = "left";
|
||||
this.container.appendChild( this.canvas );
|
||||
|
||||
//create the correct type of overlay by convention if the overlays
|
||||
//are not already OpenSeadragon.Overlays
|
||||
for( i = 0; i < this.overlays.length; i++ ){
|
||||
if( $.isPlainObject( this.overlays[ i ] ) ){
|
||||
|
||||
this.overlays[ i ] = addOverlayFromConfiguration( this, this.overlays[ i ]);
|
||||
|
||||
} else if ( $.isFunction( this.overlays[ i ] ) ){
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
||||
//this.profiler = new $.Profiler();
|
||||
};
|
||||
|
||||
$.Drawer.prototype = {
|
||||
$.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{
|
||||
|
||||
/**
|
||||
* 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
|
||||
* interface.
|
||||
* @method
|
||||
* @param {Element|String} element - A reference to an element or an id for
|
||||
* the element which will overlayed.
|
||||
* @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.
|
||||
* @fires OpenSeadragon.Viewer.event:add-overlay
|
||||
* @deprecated - use {@link OpenSeadragon.Viewer#addOverlay} instead.
|
||||
*/
|
||||
addOverlay: function( element, location, placement ) {
|
||||
element = $.getElement( element );
|
||||
|
||||
if ( getOverlayIndex( this.overlays, element ) >= 0 ) {
|
||||
// they're trying to add a duplicate overlay
|
||||
return;
|
||||
}
|
||||
|
||||
this.overlays.push( new $.Overlay( element, location, placement ) );
|
||||
this.updateAgain = true;
|
||||
if( this.viewer ){
|
||||
this.viewer.raiseEvent( 'add-overlay', {
|
||||
viewer: this.viewer,
|
||||
element: element,
|
||||
location: location,
|
||||
placement: placement
|
||||
});
|
||||
}
|
||||
addOverlay: function( element, location, placement, onDraw ) {
|
||||
$.console.error("drawer.addOverlay is deprecated. Use viewer.addOverlay instead.");
|
||||
this.viewer.addOverlay( element, location, placement, onDraw );
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -165,25 +189,12 @@ $.Drawer.prototype = {
|
||||
* viewport which the location coordinates will be treated as relative
|
||||
* to.
|
||||
* @return {OpenSeadragon.Drawer} Chainable.
|
||||
* @fires OpenSeadragon.Viewer.event:update-overlay
|
||||
* @deprecated - use {@link OpenSeadragon.Viewer#updateOverlay} instead.
|
||||
*/
|
||||
updateOverlay: function( element, location, placement ) {
|
||||
var i;
|
||||
|
||||
element = $.getElement( element );
|
||||
i = getOverlayIndex( this.overlays, element );
|
||||
|
||||
if ( i >= 0 ) {
|
||||
this.overlays[ i ].update( location, placement );
|
||||
this.updateAgain = true;
|
||||
}
|
||||
if( this.viewer ){
|
||||
this.viewer.raiseEvent( 'update-overlay', {
|
||||
viewer: this.viewer,
|
||||
element: element,
|
||||
location: location,
|
||||
placement: placement
|
||||
});
|
||||
}
|
||||
$.console.error("drawer.updateOverlay is deprecated. Use viewer.updateOverlay instead.");
|
||||
this.viewer.updateOverlay( element, location, placement );
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -194,24 +205,12 @@ $.Drawer.prototype = {
|
||||
* @param {Element|String} element - A reference to the element or an
|
||||
* element id which represent the ovelay content to be removed.
|
||||
* @return {OpenSeadragon.Drawer} Chainable.
|
||||
* @fires OpenSeadragon.Viewer.event:remove-overlay
|
||||
* @deprecated - use {@link OpenSeadragon.Viewer#removeOverlay} instead.
|
||||
*/
|
||||
removeOverlay: function( element ) {
|
||||
var i;
|
||||
|
||||
element = $.getElement( element );
|
||||
i = getOverlayIndex( this.overlays, element );
|
||||
|
||||
if ( i >= 0 ) {
|
||||
this.overlays[ i ].destroy();
|
||||
this.overlays.splice( i, 1 );
|
||||
this.updateAgain = true;
|
||||
}
|
||||
if( this.viewer ){
|
||||
this.viewer.raiseEvent( 'remove-overlay', {
|
||||
viewer: this.viewer,
|
||||
element: element
|
||||
});
|
||||
}
|
||||
$.console.error("drawer.removeOverlay is deprecated. Use viewer.removeOverlay instead.");
|
||||
this.viewer.removeOverlay( element );
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -220,22 +219,35 @@ $.Drawer.prototype = {
|
||||
* and update.
|
||||
* @method
|
||||
* @return {OpenSeadragon.Drawer} Chainable.
|
||||
* @fires OpenSeadragon.Viewer.event:clear-overlay
|
||||
* @deprecated - use {@link OpenSeadragon.Viewer#clearOverlays} instead.
|
||||
*/
|
||||
clearOverlays: function() {
|
||||
while ( this.overlays.length > 0 ) {
|
||||
this.overlays.pop().destroy();
|
||||
this.updateAgain = true;
|
||||
}
|
||||
if( this.viewer ){
|
||||
this.viewer.raiseEvent( 'clear-overlay', {
|
||||
viewer: this.viewer,
|
||||
element: element
|
||||
});
|
||||
}
|
||||
$.console.error("drawer.clearOverlays is deprecated. Use viewer.clearOverlays instead.");
|
||||
this.viewer.clearOverlays();
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the opacity of the drawer.
|
||||
* @method
|
||||
* @param {Number} opacity
|
||||
* @return {OpenSeadragon.Drawer} Chainable.
|
||||
*/
|
||||
setOpacity: function( opacity ) {
|
||||
this.opacity = opacity;
|
||||
$.setElementOpacity( this.canvas, this.opacity, true );
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the opacity of the drawer.
|
||||
* @method
|
||||
* @returns {Number}
|
||||
*/
|
||||
getOpacity: function() {
|
||||
return this.opacity;
|
||||
},
|
||||
/**
|
||||
* Returns whether the Drawer is scheduled for an update at the
|
||||
* soonest possible opportunity.
|
||||
@ -265,7 +277,7 @@ $.Drawer.prototype = {
|
||||
*/
|
||||
reset: function() {
|
||||
clearTiles( this );
|
||||
this.lastResetTime = +new Date();
|
||||
this.lastResetTime = $.now();
|
||||
this.updateAgain = true;
|
||||
return this;
|
||||
},
|
||||
@ -315,6 +327,10 @@ $.Drawer.prototype = {
|
||||
|
||||
image = new Image();
|
||||
|
||||
if ( _this.crossOriginPolicy !== false ) {
|
||||
image.crossOrigin = _this.crossOriginPolicy;
|
||||
}
|
||||
|
||||
complete = function( imagesrc, resultingImage ){
|
||||
_this.downloading--;
|
||||
if (typeof ( callback ) == "function") {
|
||||
@ -349,62 +365,22 @@ $.Drawer.prototype = {
|
||||
}
|
||||
|
||||
return loading;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether rotation is supported or not.
|
||||
* @method
|
||||
* @return {Boolean} True if rotation is supported.
|
||||
*/
|
||||
canRotate: function() {
|
||||
return this.useCanvas;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @inner
|
||||
*/
|
||||
function addOverlayFromConfiguration( drawer, overlay ){
|
||||
|
||||
var element = null,
|
||||
rect = ( overlay.height && overlay.width ) ? new $.Rect(
|
||||
overlay.x || overlay.px,
|
||||
overlay.y || overlay.py,
|
||||
overlay.width,
|
||||
overlay.height
|
||||
) : new $.Point(
|
||||
overlay.x || overlay.px,
|
||||
overlay.y || overlay.py
|
||||
),
|
||||
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;
|
||||
element.className = element.className + " " + ( overlay.className ?
|
||||
overlay.className :
|
||||
"openseadragon-overlay"
|
||||
);
|
||||
|
||||
|
||||
if(overlay.px !== undefined){
|
||||
//if they specified 'px' so its in pixel coordinates so
|
||||
//we need to translate to viewport coordinates
|
||||
rect = drawer.viewport.imageToViewportRectangle( rect );
|
||||
}
|
||||
if( overlay.placement ){
|
||||
return new $.Overlay(
|
||||
element,
|
||||
drawer.viewport.pointFromPixel(rect),
|
||||
$.OverlayPlacement[overlay.placement.toUpperCase()]
|
||||
);
|
||||
}else{
|
||||
return new $.Overlay( element, rect );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @inner
|
||||
* Pretty much every other line in this needs to be documented so its clear
|
||||
* Pretty much every other line in this needs to be documented so it's clear
|
||||
* how each piece of this routine contributes to the drawing process. That's
|
||||
* why there are so many TODO's inside this function.
|
||||
*/
|
||||
@ -413,16 +389,23 @@ function updateViewport( drawer ) {
|
||||
drawer.updateAgain = false;
|
||||
|
||||
if( drawer.viewer ){
|
||||
drawer.viewer.raiseEvent( 'update-viewport', {
|
||||
viewer: drawer.viewer
|
||||
});
|
||||
/**
|
||||
* <em>- Needs documentation -</em>
|
||||
*
|
||||
* @event update-viewport
|
||||
* @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.
|
||||
*/
|
||||
drawer.viewer.raiseEvent( 'update-viewport', {} );
|
||||
}
|
||||
|
||||
var tile,
|
||||
level,
|
||||
best = null,
|
||||
haveDrawn = false,
|
||||
currentTime = +new Date(),
|
||||
currentTime = $.now(),
|
||||
viewportSize = drawer.viewport.getContainerSize(),
|
||||
viewportBounds = drawer.viewport.getBounds( true ),
|
||||
viewportTL = viewportBounds.getTopLeft(),
|
||||
@ -445,6 +428,7 @@ function updateViewport( drawer ) {
|
||||
Math.log( 2 )
|
||||
))
|
||||
),
|
||||
degrees = drawer.viewport.degrees,
|
||||
renderPixelRatioC,
|
||||
renderPixelRatioT,
|
||||
zeroRatioT,
|
||||
@ -460,7 +444,7 @@ function updateViewport( drawer ) {
|
||||
|
||||
//TODO
|
||||
drawer.canvas.innerHTML = "";
|
||||
if ( USE_CANVAS ) {
|
||||
if ( drawer.useCanvas ) {
|
||||
if( drawer.canvas.width != viewportSize.x ||
|
||||
drawer.canvas.height != viewportSize.y ){
|
||||
drawer.canvas.width = viewportSize.x;
|
||||
@ -469,7 +453,14 @@ function updateViewport( drawer ) {
|
||||
drawer.context.clearRect( 0, 0, viewportSize.x, viewportSize.y );
|
||||
}
|
||||
|
||||
//TODO
|
||||
//Change bounds for rotation
|
||||
if (degrees === 90 || degrees === 270) {
|
||||
var rotatedBounds = viewportBounds.rotate( degrees );
|
||||
viewportTL = rotatedBounds.getTopLeft();
|
||||
viewportBR = rotatedBounds.getBottomRight();
|
||||
}
|
||||
|
||||
//Don't draw if completely outside of the viewport
|
||||
if ( !drawer.wrapHorizontal &&
|
||||
( viewportBR.x < 0 || viewportTL.x > 1 ) ) {
|
||||
return;
|
||||
@ -493,7 +484,9 @@ function updateViewport( drawer ) {
|
||||
lowestLevel = Math.min( lowestLevel, highestLevel );
|
||||
|
||||
//TODO
|
||||
var drawLevel; // FIXME: drawLevel should have a more explanatory name
|
||||
for ( level = highestLevel; level >= lowestLevel; level-- ) {
|
||||
drawLevel = false;
|
||||
|
||||
//Avoid calculations for draw if we have already drawn this
|
||||
renderPixelRatioC = drawer.viewport.deltaPixelsFromPoints(
|
||||
@ -509,6 +502,7 @@ function updateViewport( drawer ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//Perform calculations for draw if we haven't drawn this
|
||||
renderPixelRatioT = drawer.viewport.deltaPixelsFromPoints(
|
||||
drawer.source.getPixelRatio( level ),
|
||||
false
|
||||
@ -538,6 +532,7 @@ function updateViewport( drawer ) {
|
||||
best = updateLevel(
|
||||
drawer,
|
||||
haveDrawn,
|
||||
drawLevel,
|
||||
level,
|
||||
levelOpacity,
|
||||
levelVisibility,
|
||||
@ -555,7 +550,6 @@ function updateViewport( drawer ) {
|
||||
|
||||
//TODO
|
||||
drawTiles( drawer, drawer.lastDrawn );
|
||||
drawOverlays( drawer.viewport, drawer.overlays, drawer.container );
|
||||
|
||||
//TODO
|
||||
if ( best ) {
|
||||
@ -567,7 +561,7 @@ function updateViewport( drawer ) {
|
||||
}
|
||||
|
||||
|
||||
function updateLevel( drawer, haveDrawn, level, levelOpacity, levelVisibility, viewportTL, viewportBR, currentTime, best ){
|
||||
function updateLevel( drawer, haveDrawn, drawLevel, level, levelOpacity, levelVisibility, viewportTL, viewportBR, currentTime, best ){
|
||||
|
||||
var x, y,
|
||||
tileTL,
|
||||
@ -577,14 +571,30 @@ function updateLevel( drawer, haveDrawn, level, levelOpacity, levelVisibility, v
|
||||
|
||||
|
||||
if( drawer.viewer ){
|
||||
/**
|
||||
* <em>- Needs documentation -</em>
|
||||
*
|
||||
* @event update-level
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
||||
* @property {Object} havedrawn
|
||||
* @property {Object} level
|
||||
* @property {Object} opacity
|
||||
* @property {Object} visibility
|
||||
* @property {Object} topleft
|
||||
* @property {Object} bottomright
|
||||
* @property {Object} currenttime
|
||||
* @property {Object} best
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
drawer.viewer.raiseEvent( 'update-level', {
|
||||
viewer: drawer.viewer,
|
||||
havedrawn: haveDrawn,
|
||||
level: level,
|
||||
opacity: levelOpacity,
|
||||
visibility: levelVisibility,
|
||||
topleft: viewportTopLeft,
|
||||
bottomright: viewportBottomRight,
|
||||
topleft: viewportTL,
|
||||
bottomright: viewportBR,
|
||||
currenttime: currentTime,
|
||||
best: best
|
||||
});
|
||||
@ -638,12 +648,20 @@ function updateTile( drawer, drawLevel, haveDrawn, x, y, level, levelOpacity, le
|
||||
numberOfTiles,
|
||||
drawer.normHeight
|
||||
),
|
||||
drawTile = drawLevel,
|
||||
newbest;
|
||||
drawTile = drawLevel;
|
||||
|
||||
if( drawer.viewer ){
|
||||
/**
|
||||
* <em>- Needs documentation -</em>
|
||||
*
|
||||
* @event update-tile
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
||||
* @property {OpenSeadragon.Tile} tile
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
drawer.viewer.raiseEvent( 'update-tile', {
|
||||
viewer: drawer.viewer,
|
||||
tile: tile
|
||||
});
|
||||
}
|
||||
@ -675,8 +693,7 @@ function updateTile( drawer, drawLevel, haveDrawn, x, y, level, levelOpacity, le
|
||||
);
|
||||
|
||||
if ( tile.loaded ) {
|
||||
|
||||
drawer.updateAgain = blendTile(
|
||||
var needsUpdate = blendTile(
|
||||
drawer,
|
||||
tile,
|
||||
x, y,
|
||||
@ -684,6 +701,10 @@ function updateTile( drawer, drawLevel, haveDrawn, x, y, level, levelOpacity, le
|
||||
levelOpacity,
|
||||
currentTime
|
||||
);
|
||||
|
||||
if ( needsUpdate ) {
|
||||
drawer.updateAgain = true;
|
||||
}
|
||||
} else if ( tile.loading ) {
|
||||
// the tile is already in the download queue
|
||||
// thanks josh1093 for finally translating this typo
|
||||
@ -975,23 +996,6 @@ function resetCoverage( coverage, level ) {
|
||||
coverage[ level ] = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @inner
|
||||
* Determines the 'z-index' of the given overlay. Overlays are ordered in
|
||||
* a z-index based on the order they are added to the Drawer.
|
||||
*/
|
||||
function getOverlayIndex( overlays, element ) {
|
||||
var i;
|
||||
for ( i = overlays.length - 1; i >= 0; i-- ) {
|
||||
if ( overlays[ i ].element == element ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @inner
|
||||
@ -1029,28 +1033,6 @@ function finishLoadingImage( image, callback, successful, jobid ){
|
||||
|
||||
}
|
||||
|
||||
|
||||
function drawOverlays( viewport, overlays, container ){
|
||||
var i,
|
||||
length = overlays.length;
|
||||
for ( i = 0; i < length; i++ ) {
|
||||
drawOverlay( viewport, overlays[ i ], container );
|
||||
}
|
||||
}
|
||||
|
||||
function drawOverlay( viewport, overlay, container ){
|
||||
|
||||
overlay.position = viewport.pixelFromPoint(
|
||||
overlay.bounds.getTopLeft(),
|
||||
true
|
||||
);
|
||||
overlay.size = viewport.deltaPixelsFromPoints(
|
||||
overlay.bounds.getSize(),
|
||||
true
|
||||
);
|
||||
overlay.drawHTML( container );
|
||||
}
|
||||
|
||||
function drawTiles( drawer, lastDrawn ){
|
||||
var i,
|
||||
tile,
|
||||
@ -1061,6 +1043,25 @@ function drawTiles( drawer, lastDrawn ){
|
||||
tileSource,
|
||||
collectionTileSource;
|
||||
|
||||
// We need a callback to give image manipulation a chance to happen
|
||||
var drawingHandler = function(args) {
|
||||
if (drawer.viewer) {
|
||||
/**
|
||||
* This event is fired just before the tile is drawn giving the application a chance to alter the image.
|
||||
*
|
||||
* NOTE: This event is only fired when the drawer is using a <canvas>.
|
||||
*
|
||||
* @event tile-drawing
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
||||
* @property {OpenSeadragon.Tile} tile
|
||||
* @property {?Object} userData - 'context', 'tile' and 'rendered'.
|
||||
*/
|
||||
drawer.viewer.raiseEvent('tile-drawing', args);
|
||||
}
|
||||
};
|
||||
|
||||
for ( i = lastDrawn.length - 1; i >= 0; i-- ) {
|
||||
tile = lastDrawn[ i ];
|
||||
|
||||
@ -1076,15 +1077,18 @@ function drawTiles( drawer, lastDrawn ){
|
||||
|
||||
position = collectionTileSource.layout == 'horizontal' ?
|
||||
tile.y + ( tile.x * collectionTileSource.rows ) :
|
||||
tile.x + ( tile.y * collectionTileSource.rows ),
|
||||
tile.x + ( tile.y * collectionTileSource.rows );
|
||||
|
||||
tileSource = position < collectionTileSource.tileSources.length ?
|
||||
collectionTileSource.tileSources[ position ] :
|
||||
null;
|
||||
if (position < collectionTileSource.tileSources.length) {
|
||||
tileSource = collectionTileSource.tileSources[ position ];
|
||||
} else {
|
||||
tileSource = null;
|
||||
}
|
||||
|
||||
//$.console.log("Rendering collection tile %s | %s | %s", tile.y, tile.y, position);
|
||||
if( tileSource ){
|
||||
drawer.collectionOverlays[ tileKey ] = viewer = new $.Viewer({
|
||||
hash: viewport.viewer.hash + "-" + tileKey,
|
||||
element: $.makeNeutralElement( "div" ),
|
||||
mouseNavEnabled: false,
|
||||
showNavigator: false,
|
||||
@ -1108,7 +1112,7 @@ function drawTiles( drawer, lastDrawn ){
|
||||
')';
|
||||
}
|
||||
|
||||
drawer.addOverlay(
|
||||
drawer.viewer.addOverlay(
|
||||
viewer.element,
|
||||
tile.bounds
|
||||
);
|
||||
@ -1124,8 +1128,16 @@ function drawTiles( drawer, lastDrawn ){
|
||||
|
||||
} else {
|
||||
|
||||
if ( USE_CANVAS ) {
|
||||
tile.drawCanvas( drawer.context );
|
||||
if ( drawer.useCanvas ) {
|
||||
// TODO do this in a more performant way
|
||||
// specifically, don't save,rotate,restore every time we draw a tile
|
||||
if( drawer.viewport.degrees !== 0 ) {
|
||||
offsetForRotation( tile, drawer.canvas, drawer.context, drawer.viewport.degrees );
|
||||
tile.drawCanvas( drawer.context, drawingHandler );
|
||||
restoreRotationChanges( tile, drawer.canvas, drawer.context );
|
||||
} else {
|
||||
tile.drawCanvas( drawer.context, drawingHandler );
|
||||
}
|
||||
} else {
|
||||
tile.drawHTML( drawer.canvas );
|
||||
}
|
||||
@ -1143,18 +1155,53 @@ function drawTiles( drawer, lastDrawn ){
|
||||
}
|
||||
|
||||
if( drawer.viewer ){
|
||||
/**
|
||||
* <em>- Needs documentation -</em>
|
||||
*
|
||||
* @event tile-drawn
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
||||
* @property {OpenSeadragon.Tile} tile
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
drawer.viewer.raiseEvent( 'tile-drawn', {
|
||||
viewer: drawer.viewer,
|
||||
tile: tile
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function offsetForRotation( tile, canvas, context, degrees ){
|
||||
var cx = canvas.width / 2,
|
||||
cy = canvas.height / 2,
|
||||
px = tile.position.x - cx,
|
||||
py = tile.position.y - cy;
|
||||
|
||||
context.save();
|
||||
|
||||
context.translate(cx, cy);
|
||||
context.rotate( Math.PI / 180 * degrees);
|
||||
tile.position.x = px;
|
||||
tile.position.y = py;
|
||||
}
|
||||
|
||||
function restoreRotationChanges( tile, canvas, context ){
|
||||
var cx = canvas.width / 2,
|
||||
cy = canvas.height / 2,
|
||||
px = tile.position.x + cx,
|
||||
py = tile.position.y + cy;
|
||||
|
||||
tile.position.x = px;
|
||||
tile.position.y = py;
|
||||
|
||||
context.restore();
|
||||
}
|
||||
|
||||
|
||||
function drawDebugInfo( drawer, tile, count, i ){
|
||||
|
||||
if ( USE_CANVAS ) {
|
||||
if ( drawer.useCanvas ) {
|
||||
drawer.context.save();
|
||||
drawer.context.lineWidth = 2;
|
||||
drawer.context.font = 'small-caps bold 13px ariel';
|
||||
|
@ -1,8 +1,42 @@
|
||||
/*
|
||||
* OpenSeadragon - DziTileSource
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @class DziTileSource
|
||||
* @memberof OpenSeadragon
|
||||
* @extends OpenSeadragon.TileSource
|
||||
* @param {Number|Object} width - the pixel width of the image or the idiomatic
|
||||
* options object which is used instead of positional arguments.
|
||||
@ -59,14 +93,13 @@ $.DziTileSource = function( width, height, tileSize, tileOverlap, tilesUrl, file
|
||||
|
||||
};
|
||||
|
||||
$.extend( $.DziTileSource.prototype, $.TileSource.prototype, {
|
||||
$.extend( $.DziTileSource.prototype, $.TileSource.prototype, /** @lends OpenSeadragon.DziTileSource.prototype */{
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the data and/or url imply the image service is supported by
|
||||
* this tile source.
|
||||
* @function
|
||||
* @name OpenSeadragon.DziTileSource.prototype.supports
|
||||
* @param {Object|Array} data
|
||||
* @param {String} optional - url
|
||||
*/
|
||||
@ -85,7 +118,6 @@ $.extend( $.DziTileSource.prototype, $.TileSource.prototype, {
|
||||
/**
|
||||
*
|
||||
* @function
|
||||
* @name OpenSeadragon.DziTileSource.prototype.configure
|
||||
* @param {Object|XMLDocument} data - the raw configuration
|
||||
* @param {String} url - the url the data was retreived from if any.
|
||||
* @return {Object} options - A dictionary of keyword arguments sufficient
|
||||
@ -93,11 +125,7 @@ $.extend( $.DziTileSource.prototype, $.TileSource.prototype, {
|
||||
*/
|
||||
configure: function( data, url ){
|
||||
|
||||
var dziPath,
|
||||
dziName,
|
||||
tilesUrl,
|
||||
options,
|
||||
host;
|
||||
var options;
|
||||
|
||||
if( !$.isPlainObject(data) ){
|
||||
|
||||
@ -109,7 +137,7 @@ $.extend( $.DziTileSource.prototype, $.TileSource.prototype, {
|
||||
}
|
||||
|
||||
if (url && !options.tilesUrl) {
|
||||
options.tilesUrl = url.replace(/([^\/]+)\.dzi$/, '$1_files/');
|
||||
options.tilesUrl = url.replace(/([^\/]+)\.(dzi|xml|js)$/, '$1_files/');
|
||||
}
|
||||
|
||||
return options;
|
||||
@ -118,7 +146,6 @@ $.extend( $.DziTileSource.prototype, $.TileSource.prototype, {
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @name OpenSeadragon.DziTileSource.prototype.getTileUrl
|
||||
* @param {Number} level
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
@ -130,7 +157,6 @@ $.extend( $.DziTileSource.prototype, $.TileSource.prototype, {
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @name OpenSeadragon.DziTileSource.prototype.tileExists
|
||||
* @param {Number} level
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
@ -254,7 +280,7 @@ function configureFromXML( tileSource, xmlDoc ){
|
||||
} else if ( rootName == "Collection" ) {
|
||||
throw new Error( $.getString( "Errors.Dzc" ) );
|
||||
} else if ( rootName == "Error" ) {
|
||||
return processDZIError( root );
|
||||
return $._processDZIError( root );
|
||||
}
|
||||
|
||||
throw new Error( $.getString( "Errors.Dzi" ) );
|
||||
|
@ -1,114 +0,0 @@
|
||||
(function($){
|
||||
|
||||
/**
|
||||
* For use by classes which want to support custom, non-browser events.
|
||||
* TODO: This is an aweful name! This thing represents an "event source",
|
||||
* not an "event handler". PLEASE change the to EventSource. Also please
|
||||
* change 'addHandler', 'removeHandler' and 'raiseEvent' to 'bind',
|
||||
* 'unbind', and 'trigger' respectively. Finally add a method 'one' which
|
||||
* automatically unbinds a listener after the first triggered event that
|
||||
* matches.
|
||||
* @class
|
||||
*/
|
||||
$.EventHandler = function() {
|
||||
this.events = {};
|
||||
};
|
||||
|
||||
$.EventHandler.prototype = {
|
||||
|
||||
/**
|
||||
* Add an event handler for a given event.
|
||||
* @function
|
||||
* @param {String} eventName - Name of event to register.
|
||||
* @param {Function} handler - Function to call when event is triggered.
|
||||
*/
|
||||
addHandler: function( eventName, handler ) {
|
||||
var events = this.events[ eventName ];
|
||||
if( !events ){
|
||||
this.events[ eventName ] = events = [];
|
||||
}
|
||||
if( handler && $.isFunction( handler ) ){
|
||||
events[ events.length ] = handler;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a specific event handler for a given event.
|
||||
* @function
|
||||
* @param {String} eventName - Name of event for which the handler is to be removed.
|
||||
* @param {Function} handler - Function to be removed.
|
||||
*/
|
||||
removeHandler: function( eventName, handler ) {
|
||||
var events = this.events[ eventName ],
|
||||
handlers = [],
|
||||
i;
|
||||
if ( !events ){
|
||||
return;
|
||||
}
|
||||
if( $.isArray( events ) ){
|
||||
for( i = 0; i < events.length; i++ ){
|
||||
if( events[ i ] !== handler ){
|
||||
handlers.push( handler );
|
||||
}
|
||||
}
|
||||
this.events[ eventName ] = handlers;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Remove all event handler for a given event type.
|
||||
* @function
|
||||
* @param {String} eventName - Name of event for which all handlers are to be removed.
|
||||
*/
|
||||
removeAllHandlers: function( eventName ){
|
||||
this.events[ eventName ] = [];
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Retrive the list of all handlers registered for a given event.
|
||||
* @function
|
||||
* @param {String} eventName - Name of event to get handlers for.
|
||||
*/
|
||||
getHandler: function( eventName ) {
|
||||
var events = this.events[ eventName ];
|
||||
if ( !events || !events.length ){
|
||||
return null;
|
||||
}
|
||||
events = events.length === 1 ?
|
||||
[ events[ 0 ] ] :
|
||||
Array.apply( null, events );
|
||||
return function( source, args ) {
|
||||
var i,
|
||||
length = events.length;
|
||||
for ( i = 0; i < length; i++ ) {
|
||||
if( events[ i ] ){
|
||||
events[ i ]( source, args );
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Trigger an event, optionally passing additional information.
|
||||
* @function
|
||||
* @param {String} eventName - Name of event to register.
|
||||
* @param {Function} handler - Function to call when event is triggered.
|
||||
*/
|
||||
raiseEvent: function( eventName, eventArgs ) {
|
||||
//uncomment if you want to get a log og all events
|
||||
//$.console.log( eventName );
|
||||
var handler = this.getHandler( eventName );
|
||||
|
||||
if ( handler ) {
|
||||
if ( !eventArgs ) {
|
||||
eventArgs = {};
|
||||
}
|
||||
|
||||
handler( this, eventArgs );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}( OpenSeadragon ));
|
164
src/eventsource.js
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* OpenSeadragon - EventSource
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function($){
|
||||
|
||||
/**
|
||||
* Event handler method signature used by all OpenSeadragon events.
|
||||
*
|
||||
* @callback EventHandler
|
||||
* @memberof OpenSeadragon
|
||||
* @param {Object} event - See individual events for event-specific properties.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @class EventSource
|
||||
* @classdesc For use by classes which want to support custom, non-browser events.
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
*/
|
||||
$.EventSource = function() {
|
||||
this.events = {};
|
||||
};
|
||||
|
||||
$.EventSource.prototype = /** @lends OpenSeadragon.EventSource.prototype */{
|
||||
|
||||
// TODO: Add a method 'one' which automatically unbinds a listener after the first triggered event that matches.
|
||||
|
||||
/**
|
||||
* Add an event handler for a given event.
|
||||
* @function
|
||||
* @param {String} eventName - Name of event to register.
|
||||
* @param {OpenSeadragon.EventHandler} handler - Function to call when event is triggered.
|
||||
* @param {Object} [userData=null] - Arbitrary object to be passed unchanged to the handler.
|
||||
*/
|
||||
addHandler: function ( eventName, handler, userData ) {
|
||||
var events = this.events[ eventName ];
|
||||
if ( !events ) {
|
||||
this.events[ eventName ] = events = [];
|
||||
}
|
||||
if ( handler && $.isFunction( handler ) ) {
|
||||
events[ events.length ] = { handler: handler, userData: userData || null };
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a specific event handler for a given event.
|
||||
* @function
|
||||
* @param {String} eventName - Name of event for which the handler is to be removed.
|
||||
* @param {OpenSeadragon.EventHandler} handler - Function to be removed.
|
||||
*/
|
||||
removeHandler: function ( eventName, handler ) {
|
||||
var events = this.events[ eventName ],
|
||||
handlers = [],
|
||||
i;
|
||||
if ( !events ) {
|
||||
return;
|
||||
}
|
||||
if ( $.isArray( events ) ) {
|
||||
for ( i = 0; i < events.length; i++ ) {
|
||||
if ( events[i].handler !== handler ) {
|
||||
handlers.push( events[ i ] );
|
||||
}
|
||||
}
|
||||
this.events[ eventName ] = handlers;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Remove all event handlers for a given event type. If no type is given all
|
||||
* event handlers for every event type are removed.
|
||||
* @function
|
||||
* @param {String} eventName - Name of event for which all handlers are to be removed.
|
||||
*/
|
||||
removeAllHandlers: function( eventName ) {
|
||||
if ( eventName ){
|
||||
this.events[ eventName ] = [];
|
||||
} else{
|
||||
for ( var eventType in this.events ) {
|
||||
this.events[ eventType ] = [];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a function which iterates the list of all handlers registered for a given event, calling the handler for each.
|
||||
* @function
|
||||
* @param {String} eventName - Name of event to get handlers for.
|
||||
*/
|
||||
getHandler: function ( eventName ) {
|
||||
var events = this.events[ eventName ];
|
||||
if ( !events || !events.length ) {
|
||||
return null;
|
||||
}
|
||||
events = events.length === 1 ?
|
||||
[ events[ 0 ] ] :
|
||||
Array.apply( null, events );
|
||||
return function ( source, args ) {
|
||||
var i,
|
||||
length = events.length;
|
||||
for ( i = 0; i < length; i++ ) {
|
||||
if ( events[ i ] ) {
|
||||
args.eventSource = source;
|
||||
args.userData = events[ i ].userData;
|
||||
events[ i ].handler( args );
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Trigger an event, optionally passing additional information.
|
||||
* @function
|
||||
* @param {String} eventName - Name of event to register.
|
||||
* @param {Object} eventArgs - Event-specific data.
|
||||
*/
|
||||
raiseEvent: function( eventName, eventArgs ) {
|
||||
//uncomment if you want to get a log of all events
|
||||
//$.console.log( eventName );
|
||||
var handler = this.getHandler( eventName );
|
||||
|
||||
if ( handler ) {
|
||||
if ( !eventArgs ) {
|
||||
eventArgs = {};
|
||||
}
|
||||
|
||||
handler( this, eventArgs );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}( OpenSeadragon ));
|
@ -1,76 +1,143 @@
|
||||
/**
|
||||
* Determines the appropriate level of native full screen support we can get
|
||||
* from the browser.
|
||||
* Thanks to John Dyer for the implementation and research
|
||||
* http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugin/
|
||||
* Also includes older IE support based on
|
||||
* http://stackoverflow.com/questions/1125084/how-to-make-in-javascript-full-screen-windows-stretching-all-over-the-screen/7525760
|
||||
* @name $.supportsFullScreen
|
||||
/*
|
||||
* OpenSeadragon - full-screen support functions
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ) {
|
||||
/**
|
||||
* Determine native full screen support we can get from the browser.
|
||||
* @member fullScreenApi
|
||||
* @memberof OpenSeadragon
|
||||
* @type {object}
|
||||
* @property {Boolean} supportsFullScreen Return true if full screen API is supported.
|
||||
* @property {Function} isFullScreen Return true if currently in full screen mode.
|
||||
* @property {Function} getFullScreenElement Return the element currently in full screen mode.
|
||||
* @property {Function} requestFullScreen Make a request to go in full screen mode.
|
||||
* @property {Function} exitFullScreen Make a request to exit full screen mode.
|
||||
* @property {Function} cancelFullScreen Deprecated, use exitFullScreen instead.
|
||||
* @property {String} fullScreenEventName Event fired when the full screen mode change.
|
||||
* @property {String} fullScreenErrorEventName Event fired when a request to go
|
||||
* in full screen mode failed.
|
||||
*/
|
||||
var fullScreenApi = {
|
||||
supportsFullScreen: false,
|
||||
isFullScreen: function() { return false; },
|
||||
requestFullScreen: function() {},
|
||||
cancelFullScreen: function() {},
|
||||
fullScreenEventName: '',
|
||||
prefix: ''
|
||||
},
|
||||
browserPrefixes = 'webkit moz o ms khtml'.split(' ');
|
||||
supportsFullScreen: false,
|
||||
isFullScreen: function() { return false; },
|
||||
getFullScreenElement: function() { return null; },
|
||||
requestFullScreen: function() {},
|
||||
exitFullScreen: function() {},
|
||||
cancelFullScreen: function() {},
|
||||
fullScreenEventName: '',
|
||||
fullScreenErrorEventName: ''
|
||||
};
|
||||
|
||||
// check for native support
|
||||
if (typeof document.cancelFullScreen != 'undefined') {
|
||||
if ( document.exitFullscreen ) {
|
||||
// W3C standard
|
||||
fullScreenApi.supportsFullScreen = true;
|
||||
} else {
|
||||
// check for fullscreen support by vendor prefix
|
||||
for (var i = 0, il = browserPrefixes.length; i < il; i++ ) {
|
||||
fullScreenApi.prefix = browserPrefixes[i];
|
||||
|
||||
if (typeof document[fullScreenApi.prefix + 'CancelFullScreen' ] != 'undefined' ) {
|
||||
fullScreenApi.supportsFullScreen = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update methods to do something useful
|
||||
if (fullScreenApi.supportsFullScreen) {
|
||||
fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange';
|
||||
|
||||
fullScreenApi.isFullScreen = function() {
|
||||
switch (this.prefix) {
|
||||
case '':
|
||||
return document.fullScreen;
|
||||
case 'webkit':
|
||||
return document.webkitIsFullScreen;
|
||||
default:
|
||||
return document[this.prefix + 'FullScreen'];
|
||||
}
|
||||
fullScreenApi.getFullScreenElement = function() {
|
||||
return document.fullscreenElement;
|
||||
};
|
||||
fullScreenApi.requestFullScreen = function( element ) {
|
||||
return (this.prefix === '') ?
|
||||
element.requestFullScreen() :
|
||||
element[this.prefix + 'RequestFullScreen']();
|
||||
|
||||
return element.requestFullscreen();
|
||||
};
|
||||
fullScreenApi.cancelFullScreen = function( element ) {
|
||||
return (this.prefix === '') ?
|
||||
document.cancelFullScreen() :
|
||||
document[this.prefix + 'CancelFullScreen']();
|
||||
fullScreenApi.exitFullScreen = function() {
|
||||
document.exitFullscreen();
|
||||
};
|
||||
} else if ( typeof window.ActiveXObject !== "undefined" ){
|
||||
// Older IE.
|
||||
fullScreenApi.requestFullScreen = function(){
|
||||
var wscript = new ActiveXObject("WScript.Shell");
|
||||
if ( wscript !== null ) {
|
||||
wscript.SendKeys("{F11}");
|
||||
}
|
||||
return false;
|
||||
fullScreenApi.fullScreenEventName = "fullscreenchange";
|
||||
fullScreenApi.fullScreenErrorEventName = "fullscreenerror";
|
||||
} else if ( document.msExitFullscreen ) {
|
||||
// IE 11
|
||||
fullScreenApi.supportsFullScreen = true;
|
||||
fullScreenApi.getFullScreenElement = function() {
|
||||
return document.msFullscreenElement;
|
||||
};
|
||||
fullScreenApi.cancelFullScreen = fullScreenApi.requestFullScreen;
|
||||
fullScreenApi.requestFullScreen = function( element ) {
|
||||
return element.msRequestFullscreen();
|
||||
};
|
||||
fullScreenApi.exitFullScreen = function() {
|
||||
document.msExitFullscreen();
|
||||
};
|
||||
fullScreenApi.fullScreenEventName = "MSFullscreenChange";
|
||||
fullScreenApi.fullScreenErrorEventName = "MSFullscreenError";
|
||||
} else if ( document.webkitExitFullscreen ) {
|
||||
// Recent webkit
|
||||
fullScreenApi.supportsFullScreen = true;
|
||||
fullScreenApi.getFullScreenElement = function() {
|
||||
return document.webkitFullscreenElement;
|
||||
};
|
||||
fullScreenApi.requestFullScreen = function( element ) {
|
||||
return element.webkitRequestFullscreen();
|
||||
};
|
||||
fullScreenApi.exitFullScreen = function() {
|
||||
document.webkitExitFullscreen();
|
||||
};
|
||||
fullScreenApi.fullScreenEventName = "webkitfullscreenchange";
|
||||
fullScreenApi.fullScreenErrorEventName = "webkitfullscreenerror";
|
||||
} else if ( document.webkitCancelFullScreen ) {
|
||||
// Old webkit
|
||||
fullScreenApi.supportsFullScreen = true;
|
||||
fullScreenApi.getFullScreenElement = function() {
|
||||
return document.webkitCurrentFullScreenElement;
|
||||
};
|
||||
fullScreenApi.requestFullScreen = function( element ) {
|
||||
return element.webkitRequestFullScreen();
|
||||
};
|
||||
fullScreenApi.exitFullScreen = function() {
|
||||
document.webkitCancelFullScreen();
|
||||
};
|
||||
fullScreenApi.fullScreenEventName = "webkitfullscreenchange";
|
||||
fullScreenApi.fullScreenErrorEventName = "webkitfullscreenerror";
|
||||
} else if ( document.mozCancelFullScreen ) {
|
||||
// Firefox
|
||||
fullScreenApi.supportsFullScreen = true;
|
||||
fullScreenApi.getFullScreenElement = function() {
|
||||
return document.mozFullScreenElement;
|
||||
};
|
||||
fullScreenApi.requestFullScreen = function( element ) {
|
||||
return element.mozRequestFullScreen();
|
||||
};
|
||||
fullScreenApi.exitFullScreen = function() {
|
||||
document.mozCancelFullScreen();
|
||||
};
|
||||
fullScreenApi.fullScreenEventName = "mozfullscreenchange";
|
||||
fullScreenApi.fullScreenErrorEventName = "mozfullscreenerror";
|
||||
}
|
||||
|
||||
fullScreenApi.isFullScreen = function() {
|
||||
return fullScreenApi.getFullScreenElement() !== null;
|
||||
};
|
||||
fullScreenApi.cancelFullScreen = function() {
|
||||
$.console.error("cancelFullScreen is deprecated. Use exitFullScreen instead.");
|
||||
fullScreenApi.exitFullScreen();
|
||||
};
|
||||
|
||||
// export api
|
||||
$.extend( $, fullScreenApi );
|
||||
|
192
src/iiif1_1tilesource.js
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* OpenSeadragon - IIIF1_1TileSource
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* @class IIIF1_1TileSource
|
||||
* @classdesc A client implementation of the International Image Interoperability
|
||||
* Format: Image API 1.1
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
* @extends OpenSeadragon.TileSource
|
||||
* @see http://library.stanford.edu/iiif/image-api/
|
||||
*/
|
||||
$.IIIF1_1TileSource = function( options ){
|
||||
|
||||
|
||||
$.extend( true, this, options );
|
||||
|
||||
|
||||
if ( !( this.height && this.width && this['@id'] ) ){
|
||||
throw new Error( 'IIIF required parameters not provided.' );
|
||||
}
|
||||
|
||||
if ( ( this.profile &&
|
||||
this.profile == "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level0" ) ){
|
||||
// what if not reporting a profile?
|
||||
throw new Error( 'IIIF Image API 1.1 compliance level 1 or greater is required.' );
|
||||
}
|
||||
|
||||
if ( this.tile_width ) {
|
||||
options.tileSize = this.tile_width;
|
||||
} else if ( this.tile_height ) {
|
||||
options.tileSize = this.tile_height;
|
||||
} else {
|
||||
// use the largest of tileOptions that is smaller than the short
|
||||
// dimension
|
||||
|
||||
var shortDim = Math.min( this.height, this.width ),
|
||||
tileOptions = [256,512,1024],
|
||||
smallerTiles = [];
|
||||
|
||||
for ( var c = 0; c < tileOptions.length; c++ ) {
|
||||
if ( tileOptions[c] <= shortDim ) {
|
||||
smallerTiles.push( tileOptions[c] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( smallerTiles.length > 0 ) {
|
||||
options.tileSize = Math.max.apply( null, smallerTiles );
|
||||
} else {
|
||||
// If we're smaller than 256, just use the short side.
|
||||
options.tileSize = shortDim;
|
||||
}
|
||||
this.tile_width = options.tileSize; // So that 'full' gets used for
|
||||
this.tile_height = options.tileSize; // the region below
|
||||
}
|
||||
|
||||
if ( !options.maxLevel ) {
|
||||
var mf = -1;
|
||||
var scfs = this.scale_factors || this.scale_factor;
|
||||
if ( scfs instanceof Array ) {
|
||||
for ( var i = 0; i < scfs.length; i++ ) {
|
||||
var cf = Number( scfs[i] );
|
||||
if ( !isNaN( cf ) && cf > mf ) { mf = cf; }
|
||||
}
|
||||
}
|
||||
if ( mf < 0 ) { options.maxLevel = Number( Math.ceil( Math.log( Math.max( this.width, this.height ), 2 ) ) ); }
|
||||
else { options.maxLevel = mf; }
|
||||
}
|
||||
|
||||
$.TileSource.apply( this, [ options ] );
|
||||
};
|
||||
|
||||
$.extend( $.IIIF1_1TileSource.prototype, $.TileSource.prototype, /** @lends OpenSeadragon.IIIF1_1TileSource.prototype */{
|
||||
/**
|
||||
* Determine if the data and/or url imply the image service is supported by
|
||||
* this tile source.
|
||||
* @function
|
||||
* @param {Object|Array} data
|
||||
* @param {String} optional - url
|
||||
*/
|
||||
supports: function( data, url ) {
|
||||
return ( data['@context'] &&
|
||||
data['@context'] == "http://library.stanford.edu/iiif/image-api/1.1/context.json" );
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @function
|
||||
* @param {Object} data - the raw configuration
|
||||
* @example <caption>IIIF 1.1 Info Looks like this (XML syntax is no more)</caption>
|
||||
* {
|
||||
* "@context" : "http://library.stanford.edu/iiif/image-api/1.1/context.json",
|
||||
* "@id" : "http://iiif.example.com/prefix/1E34750D-38DB-4825-A38A-B60A345E591C",
|
||||
* "width" : 6000,
|
||||
* "height" : 4000,
|
||||
* "scale_factors" : [ 1, 2, 4 ],
|
||||
* "tile_width" : 1024,
|
||||
* "tile_height" : 1024,
|
||||
* "formats" : [ "jpg", "png" ],
|
||||
* "qualities" : [ "native", "grey" ],
|
||||
* "profile" : "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level0"
|
||||
* }
|
||||
*/
|
||||
configure: function( data ){
|
||||
return data;
|
||||
},
|
||||
/**
|
||||
* Responsible for retreiving the url which will return an image for the
|
||||
* region specified by the given x, y, and level components.
|
||||
* @function
|
||||
* @param {Number} level - z index
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
* @throws {Error}
|
||||
*/
|
||||
getTileUrl: function( level, x, y ){
|
||||
|
||||
//# constants
|
||||
|
||||
var IIIF_ROTATION = '0',
|
||||
IIIF_QUALITY = 'native.jpg',
|
||||
|
||||
//## get the scale (level as a decimal)
|
||||
scale = Math.pow( 0.5, this.maxLevel - level ),
|
||||
|
||||
//# image dimensions at this level
|
||||
levelWidth = Math.ceil( this.width * scale ),
|
||||
levelHeight = Math.ceil( this.height * scale ),
|
||||
|
||||
//## iiif region
|
||||
iiifTileSizeWidth = Math.ceil( this.tileSize / scale ),
|
||||
iiifTileSizeHeight = Math.ceil( this.tileSize / scale ),
|
||||
iiifRegion,
|
||||
iiifTileX,
|
||||
iiifTileY,
|
||||
iiifTileW,
|
||||
iiifTileH,
|
||||
iiifSize,
|
||||
uri;
|
||||
|
||||
if ( levelWidth < this.tile_width && levelHeight < this.tile_height ){
|
||||
iiifSize = levelWidth + ",";
|
||||
iiifRegion = 'full';
|
||||
} else {
|
||||
iiifTileX = x * iiifTileSizeWidth;
|
||||
iiifTileY = y * iiifTileSizeHeight;
|
||||
iiifTileW = Math.min( iiifTileSizeWidth, this.width - iiifTileX );
|
||||
iiifTileH = Math.min( iiifTileSizeHeight, this.height - iiifTileY );
|
||||
|
||||
iiifSize = Math.ceil( iiifTileW * scale ) + ",";
|
||||
|
||||
iiifRegion = [ iiifTileX, iiifTileY, iiifTileW, iiifTileH ].join( ',' );
|
||||
}
|
||||
uri = [ this['@id'], iiifRegion, iiifSize, IIIF_ROTATION, IIIF_QUALITY ].join( '/' );
|
||||
return uri;
|
||||
}
|
||||
});
|
||||
|
||||
}( OpenSeadragon ));
|
@ -1,14 +1,52 @@
|
||||
/*
|
||||
* OpenSeadragon - IIIFTileSource
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The getTileUrl implementation is based on Jon Stroop's Python version,
|
||||
* which is released under the New BSD license:
|
||||
* https://gist.github.com/jpstroop/4624253
|
||||
*/
|
||||
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* A client implementation of the International Image Interoperability
|
||||
* Format: Image API Draft 0.2 - Please read more about the specification
|
||||
* at
|
||||
* @class IIIFTileSource
|
||||
* @classdesc A client implementation of the International Image Interoperability
|
||||
* Format: Image API Draft 0.2
|
||||
*
|
||||
* The getTileUrl implementation is based on the gist from:
|
||||
* https://gist.github.com/jpstroop/4624253
|
||||
*
|
||||
* @class
|
||||
* @memberof OpenSeadragon
|
||||
* @extends OpenSeadragon.TileSource
|
||||
* @see http://library.stanford.edu/iiif/image-api/
|
||||
*/
|
||||
@ -27,19 +65,27 @@ $.IIIFTileSource = function( options ){
|
||||
// to preserve backward compatibility.
|
||||
options.tileSize = this.tile_width;
|
||||
|
||||
options.maxLevel = options.maxLevel ? options.maxLevel : Number(
|
||||
Math.ceil( Math.log( Math.max( this.width, this.height ), 2 ) )
|
||||
);
|
||||
if (! options.maxLevel ) {
|
||||
var mf = -1;
|
||||
var scfs = this.scale_factors || this.scale_factor;
|
||||
if ( scfs instanceof Array ) {
|
||||
for ( var i = 0; i < scfs.length; i++ ) {
|
||||
var cf = Number( scfs[i] );
|
||||
if ( !isNaN( cf ) && cf > mf ) { mf = cf; }
|
||||
}
|
||||
}
|
||||
if ( mf < 0 ) { options.maxLevel = Number(Math.ceil(Math.log(Math.max(this.width, this.height), 2))); }
|
||||
else { options.maxLevel = mf; }
|
||||
}
|
||||
|
||||
$.TileSource.apply( this, [ options ] );
|
||||
};
|
||||
|
||||
$.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, {
|
||||
$.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSeadragon.IIIFTileSource.prototype */{
|
||||
/**
|
||||
* Determine if the data and/or url imply the image service is supported by
|
||||
* this tile source.
|
||||
* @function
|
||||
* @name OpenSeadragon.IIIFTileSource.prototype.supports
|
||||
* @method
|
||||
* @param {Object|Array} data
|
||||
* @param {String} optional - url
|
||||
*/
|
||||
@ -62,18 +108,16 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, {
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
/**
|
||||
*
|
||||
* @function
|
||||
* @name OpenSeadragon.IIIFTileSource.prototype.configure
|
||||
* @method
|
||||
* @param {Object|XMLDocument} data - the raw configuration
|
||||
* @param {String} url - the url the data was retreived from if any.
|
||||
* @return {Object} options - A dictionary of keyword arguments sufficient
|
||||
* to configure this tile source via it's constructor.
|
||||
* to configure this tile source via its constructor.
|
||||
*/
|
||||
configure: function( data, url ){
|
||||
var service,
|
||||
identifier,
|
||||
options,
|
||||
host;
|
||||
|
||||
@ -106,8 +150,7 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, {
|
||||
/**
|
||||
* Responsible for retreiving the url which will return an image for the
|
||||
* region speified by the given x, y, and level components.
|
||||
* @function
|
||||
* @name OpenSeadragon.IIIFTileSource.prototype.getTileUrl
|
||||
* @method
|
||||
* @param {Number} level - z index
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
@ -123,7 +166,7 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, {
|
||||
scale = Math.pow( 0.5, this.maxLevel - level ),
|
||||
|
||||
//## get iiif size
|
||||
iiif_size = 'pct:' + ( scale * 100 ),
|
||||
// iiif_size = 'pct:' + ( scale * 100 ),
|
||||
|
||||
//# image dimensions at this level
|
||||
level_width = Math.ceil( this.width * scale ),
|
||||
@ -136,16 +179,19 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, {
|
||||
iiif_tile_x,
|
||||
iiif_tile_y,
|
||||
iiif_tile_w,
|
||||
iiif_tile_h;
|
||||
iiif_tile_h,
|
||||
iiif_size;
|
||||
|
||||
|
||||
if ( level_width < this.tile_width || level_height < this.tile_height ){
|
||||
if ( level_width < this.tile_width && level_height < this.tile_height ){
|
||||
iiif_size = level_width + ","; // + level_height; only one dim. for IIIF level 1 compliance
|
||||
iiif_region = 'full';
|
||||
} else {
|
||||
iiif_tile_x = x * iiif_tile_size_width;
|
||||
iiif_tile_y = y * iiif_tile_size_height;
|
||||
iiif_tile_w = Math.min( iiif_tile_size_width, this.width - iiif_tile_x );
|
||||
iiif_tile_h = Math.min( iiif_tile_size_height, this.height - iiif_tile_y );
|
||||
iiif_size = Math.ceil(iiif_tile_w * scale) + ",";
|
||||
iiif_region = [ iiif_tile_x, iiif_tile_y, iiif_tile_w, iiif_tile_h ].join(',');
|
||||
}
|
||||
|
||||
@ -166,28 +212,28 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, {
|
||||
* @private
|
||||
* @inner
|
||||
* @function
|
||||
*
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<info xmlns="http://library.stanford.edu/iiif/image-api/ns/">
|
||||
<identifier>1E34750D-38DB-4825-A38A-B60A345E591C</identifier>
|
||||
<width>6000</width>
|
||||
<height>4000</height>
|
||||
<scale_factors>
|
||||
<scale_factor>1</scale_factor>
|
||||
<scale_factor>2</scale_factor>
|
||||
<scale_factor>4</scale_factor>
|
||||
</scale_factors>
|
||||
<tile_width>1024</tile_width>
|
||||
<tile_height>1024</tile_height>
|
||||
<formats>
|
||||
<format>jpg</format>
|
||||
<format>png</format>
|
||||
</formats>
|
||||
<qualities>
|
||||
<quality>native</quality>
|
||||
<quality>grey</quality>
|
||||
</qualities>
|
||||
</info>
|
||||
* @example
|
||||
* <?xml version="1.0" encoding="UTF-8"?>
|
||||
* <info xmlns="http://library.stanford.edu/iiif/image-api/ns/">
|
||||
* <identifier>1E34750D-38DB-4825-A38A-B60A345E591C</identifier>
|
||||
* <width>6000</width>
|
||||
* <height>4000</height>
|
||||
* <scale_factors>
|
||||
* <scale_factor>1</scale_factor>
|
||||
* <scale_factor>2</scale_factor>
|
||||
* <scale_factor>4</scale_factor>
|
||||
* </scale_factors>
|
||||
* <tile_width>1024</tile_width>
|
||||
* <tile_height>1024</tile_height>
|
||||
* <formats>
|
||||
* <format>jpg</format>
|
||||
* <format>png</format>
|
||||
* </formats>
|
||||
* <qualities>
|
||||
* <quality>native</quality>
|
||||
* <quality>grey</quality>
|
||||
* </qualities>
|
||||
* </info>
|
||||
*/
|
||||
function configureFromXml( tileSource, xmlDoc ){
|
||||
|
||||
@ -198,11 +244,7 @@ function configureFromXml( tileSource, xmlDoc ){
|
||||
|
||||
var root = xmlDoc.documentElement,
|
||||
rootName = root.tagName,
|
||||
configuration = null,
|
||||
scale_factors,
|
||||
formats,
|
||||
qualities,
|
||||
i;
|
||||
configuration = null;
|
||||
|
||||
if ( rootName == "info" ) {
|
||||
|
||||
@ -261,18 +303,18 @@ function parseXML( node, configuration, property ){
|
||||
* @private
|
||||
* @inner
|
||||
* @function
|
||||
*
|
||||
{
|
||||
"profile" : "http://library.stanford.edu/iiif/image-api/compliance.html#level1",
|
||||
"identifier" : "1E34750D-38DB-4825-A38A-B60A345E591C",
|
||||
"width" : 6000,
|
||||
"height" : 4000,
|
||||
"scale_factors" : [ 1, 2, 4 ],
|
||||
"tile_width" : 1024,
|
||||
"tile_height" : 1024,
|
||||
"formats" : [ "jpg", "png" ],
|
||||
"quality" : [ "native", "grey" ]
|
||||
}
|
||||
* @example
|
||||
* {
|
||||
* "profile" : "http://library.stanford.edu/iiif/image-api/compliance.html#level1",
|
||||
* "identifier" : "1E34750D-38DB-4825-A38A-B60A345E591C",
|
||||
* "width" : 6000,
|
||||
* "height" : 4000,
|
||||
* "scale_factors" : [ 1, 2, 4 ],
|
||||
* "tile_width" : 1024,
|
||||
* "tile_height" : 1024,
|
||||
* "formats" : [ "jpg", "png" ],
|
||||
* "quality" : [ "native", "grey" ]
|
||||
* }
|
||||
*/
|
||||
function configureFromObject( tileSource, configuration ){
|
||||
//the image_host property is not part of the iiif standard but is included here to
|
||||
|
@ -1,13 +1,49 @@
|
||||
/*
|
||||
* OpenSeadragon - LegacyTileSource
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* The LegacyTileSource allows simple, traditional image pyramids to be loaded
|
||||
* @class LegacyTileSource
|
||||
* @classdesc The LegacyTileSource allows simple, traditional image pyramids to be loaded
|
||||
* into an OpenSeadragon Viewer. Basically, this translates to the historically
|
||||
* common practice of starting with a 'master' image, maybe a tiff for example,
|
||||
* and generating a set of 'service' images like one or more thumbnails, a medium
|
||||
* resolution image and a high resolution image in standard web formats like
|
||||
* png or jpg.
|
||||
* @class
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
* @extends OpenSeadragon.TileSource
|
||||
* @param {Array} levels An array of file descriptions, each is an object with
|
||||
* a 'url', a 'width', and a 'height'. Overriding classes can expect more
|
||||
@ -37,29 +73,36 @@ $.LegacyTileSource = function( levels ) {
|
||||
|
||||
//clean up the levels to make sure we support all formats
|
||||
options.levels = filterFiles( options.levels );
|
||||
width = options.levels[ options.levels.length - 1 ].width;
|
||||
height = options.levels[ options.levels.length - 1 ].height;
|
||||
|
||||
$.extend( true, options, {
|
||||
width: width,
|
||||
height: height,
|
||||
tileSize: Math.max( height, width ),
|
||||
if ( options.levels.length > 0 ) {
|
||||
width = options.levels[ options.levels.length - 1 ].width;
|
||||
height = options.levels[ options.levels.length - 1 ].height;
|
||||
}
|
||||
else {
|
||||
width = 0;
|
||||
height = 0;
|
||||
$.console.error( "No supported image formats found" );
|
||||
}
|
||||
|
||||
$.extend( true, options, {
|
||||
width: width,
|
||||
height: height,
|
||||
tileSize: Math.max( height, width ),
|
||||
tileOverlap: 0,
|
||||
minLevel: 0,
|
||||
maxLevel: options.levels.length - 1
|
||||
});
|
||||
minLevel: 0,
|
||||
maxLevel: options.levels.length > 0 ? options.levels.length - 1 : 0
|
||||
} );
|
||||
|
||||
$.TileSource.apply( this, [ options ] );
|
||||
|
||||
this.levels = options.levels;
|
||||
};
|
||||
|
||||
$.extend( $.LegacyTileSource.prototype, $.TileSource.prototype, {
|
||||
$.extend( $.LegacyTileSource.prototype, $.TileSource.prototype, /** @lends OpenSeadragon.LegacyTileSource.prototype */{
|
||||
/**
|
||||
* Determine if the data and/or url imply the image service is supported by
|
||||
* this tile source.
|
||||
* @function
|
||||
* @name OpenSeadragon.LegacyTileSource.prototype.supports
|
||||
* @param {Object|Array} data
|
||||
* @param {String} optional - url
|
||||
*/
|
||||
@ -77,7 +120,6 @@ $.extend( $.LegacyTileSource.prototype, $.TileSource.prototype, {
|
||||
/**
|
||||
*
|
||||
* @function
|
||||
* @name OpenSeadragon.LegacyTileSource.prototype.configure
|
||||
* @param {Object|XMLDocument} configuration - the raw configuration
|
||||
* @param {String} dataUrl - the url the data was retreived from if any.
|
||||
* @return {Object} options - A dictionary of keyword arguments sufficient
|
||||
@ -102,12 +144,11 @@ $.extend( $.LegacyTileSource.prototype, $.TileSource.prototype, {
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @name OpenSeadragon.LegacyTileSource.prototype.getLevelScale
|
||||
* @param {Number} level
|
||||
*/
|
||||
getLevelScale: function( level ) {
|
||||
getLevelScale: function ( level ) {
|
||||
var levelScale = NaN;
|
||||
if ( level >= this.minLevel && level <= this.maxLevel ){
|
||||
if ( this.levels.length > 0 && level >= this.minLevel && level <= this.maxLevel ) {
|
||||
levelScale =
|
||||
this.levels[ level ].width /
|
||||
this.levels[ this.maxLevel ].width;
|
||||
@ -117,7 +158,6 @@ $.extend( $.LegacyTileSource.prototype, $.TileSource.prototype, {
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @name OpenSeadragon.LegacyTileSource.prototype.getNumTiles
|
||||
* @param {Number} level
|
||||
*/
|
||||
getNumTiles: function( level ) {
|
||||
@ -131,7 +171,6 @@ $.extend( $.LegacyTileSource.prototype, $.TileSource.prototype, {
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @name OpenSeadragon.LegacyTileSource.prototype.getTileAtPoint
|
||||
* @param {Number} level
|
||||
* @param {OpenSeadragon.Point} point
|
||||
*/
|
||||
@ -146,20 +185,19 @@ $.extend( $.LegacyTileSource.prototype, $.TileSource.prototype, {
|
||||
* server technologies, and various specifications for building image
|
||||
* pyramids, this method is here to allow easy integration.
|
||||
* @function
|
||||
* @name OpenSeadragon.LegacyTileSource.prototype.getTileUrl
|
||||
* @param {Number} level
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
* @throws {Error}
|
||||
*/
|
||||
getTileUrl: function( level, x, y ) {
|
||||
getTileUrl: function ( level, x, y ) {
|
||||
var url = null;
|
||||
if( level >= this.minLevel && level <= this.maxLevel ){
|
||||
if ( this.levels.length > 0 && level >= this.minLevel && level <= this.maxLevel ) {
|
||||
url = this.levels[ level ].url;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
});
|
||||
} );
|
||||
|
||||
/**
|
||||
* This method removes any files from the Array which dont conform to our
|
||||
@ -189,6 +227,9 @@ function filterFiles( files ){
|
||||
height: Number( file.height )
|
||||
});
|
||||
}
|
||||
else {
|
||||
$.console.error( 'Unsupported image format: %s', file.url ? file.url : '<no URL>' );
|
||||
}
|
||||
}
|
||||
|
||||
return filtered.sort(function(a,b){
|
||||
|
1022
src/mousetracker.js
388
src/navigator.js
@ -1,32 +1,98 @@
|
||||
/*
|
||||
* OpenSeadragon - Navigator
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* The Navigator provides a small view of the current image as fixed
|
||||
* @class Navigator
|
||||
* @classdesc The Navigator provides a small view of the current image as fixed
|
||||
* while representing the viewport as a moving box serving as a frame
|
||||
* of reference in the larger viewport as to which portion of the image
|
||||
* is currently being examined. The navigator's viewport can be interacted
|
||||
* with using the keyboard or the mouse.
|
||||
* @class
|
||||
* @name OpenSeadragon.Navigator
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
* @extends OpenSeadragon.Viewer
|
||||
* @extends OpenSeadragon.EventHandler
|
||||
* @extends OpenSeadragon.EventSource
|
||||
* @param {Object} options
|
||||
* @param {String} options.viewerId
|
||||
*/
|
||||
$.Navigator = function( options ){
|
||||
|
||||
var _this = this,
|
||||
viewer = options.viewer,
|
||||
viewerSize = $.getElementSize( viewer.element );
|
||||
var viewer = options.viewer,
|
||||
viewerSize,
|
||||
navigatorSize,
|
||||
unneededElement;
|
||||
|
||||
//We may need to create a new element and id if they did not
|
||||
//provide the id for the existing element
|
||||
if( !options.id ){
|
||||
options.id = 'navigator-' + (+new Date());
|
||||
options.id = 'navigator-' + $.now();
|
||||
this.element = $.makeNeutralElement( "div" );
|
||||
this.element.id = options.id;
|
||||
this.element.className = 'navigator';
|
||||
options.controlOptions = {
|
||||
anchor: $.ControlAnchor.TOP_RIGHT,
|
||||
attachToViewer: true,
|
||||
autoFade: true
|
||||
};
|
||||
|
||||
if( options.position ){
|
||||
if( 'BOTTOM_RIGHT' == options.position ){
|
||||
options.controlOptions.anchor = $.ControlAnchor.BOTTOM_RIGHT;
|
||||
} else if( 'BOTTOM_LEFT' == options.position ){
|
||||
options.controlOptions.anchor = $.ControlAnchor.BOTTOM_LEFT;
|
||||
} else if( 'TOP_RIGHT' == options.position ){
|
||||
options.controlOptions.anchor = $.ControlAnchor.TOP_RIGHT;
|
||||
} else if( 'TOP_LEFT' == options.position ){
|
||||
options.controlOptions.anchor = $.ControlAnchor.TOP_LEFT;
|
||||
} else if( 'ABSOLUTE' == options.position ){
|
||||
options.controlOptions.anchor = $.ControlAnchor.ABSOLUTE;
|
||||
options.controlOptions.top = options.top;
|
||||
options.controlOptions.left = options.left;
|
||||
options.controlOptions.height = options.height;
|
||||
options.controlOptions.width = options.width;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
this.element = document.getElementById( options.id );
|
||||
options.controlOptions = {
|
||||
anchor: $.ControlAnchor.NONE,
|
||||
attachToViewer: false,
|
||||
autoFade: false
|
||||
};
|
||||
}
|
||||
this.element.id = options.id;
|
||||
this.element.className += ' navigator';
|
||||
|
||||
options = $.extend( true, {
|
||||
sizeRatio: $.DEFAULT_SETTINGS.navigatorSizeRatio
|
||||
@ -40,34 +106,43 @@ $.Navigator = function( options ){
|
||||
showSequenceControl: false,
|
||||
immediateRender: true,
|
||||
blendTime: 0,
|
||||
animationTime: 0
|
||||
animationTime: 0,
|
||||
autoResize: options.autoResize
|
||||
});
|
||||
|
||||
options.minPixelRatio = this.minPixelRatio = viewer.minPixelRatio;
|
||||
|
||||
(function( style ){
|
||||
style.marginTop = '0px';
|
||||
style.marginRight = '0px';
|
||||
style.marginBottom = '0px';
|
||||
style.marginLeft = '0px';
|
||||
style.border = '2px solid #555';
|
||||
style.background = '#000';
|
||||
style.opacity = 0.8;
|
||||
style.overflow = 'hidden';
|
||||
}( this.element.style ));
|
||||
this.borderWidth = 2;
|
||||
//At some browser magnification levels the display regions lines up correctly, but at some there appears to
|
||||
//be a one pixel gap.
|
||||
this.fudge = new $.Point(1, 1);
|
||||
this.totalBorderWidths = new $.Point(this.borderWidth*2, this.borderWidth*2).minus(this.fudge);
|
||||
|
||||
this.displayRegion = $.makeNeutralElement( "textarea" );
|
||||
|
||||
if ( options.controlOptions.anchor != $.ControlAnchor.NONE ) {
|
||||
(function( style, borderWidth ){
|
||||
style.margin = '0px';
|
||||
style.border = borderWidth + 'px solid #555';
|
||||
style.padding = '0px';
|
||||
style.background = '#000';
|
||||
style.opacity = 0.8;
|
||||
style.overflow = 'hidden';
|
||||
}( this.element.style, this.borderWidth));
|
||||
}
|
||||
|
||||
this.displayRegion = $.makeNeutralElement( "div" );
|
||||
this.displayRegion.id = this.element.id + '-displayregion';
|
||||
this.displayRegion.className = 'displayregion';
|
||||
|
||||
(function( style ){
|
||||
(function( style, borderWidth ){
|
||||
style.position = 'relative';
|
||||
style.top = '0px';
|
||||
style.left = '0px';
|
||||
style.fontSize = '0px';
|
||||
style.overflow = 'hidden';
|
||||
style.border = '2px solid #900';
|
||||
|
||||
style.border = borderWidth + 'px solid #900';
|
||||
style.margin = '0px';
|
||||
style.padding = '0px';
|
||||
//TODO: IE doesnt like this property being set
|
||||
//try{ style.outline = '2px auto #909'; }catch(e){/*ignore*/}
|
||||
|
||||
@ -82,94 +157,17 @@ $.Navigator = function( options ){
|
||||
style.styleFloat = 'left'; //IE
|
||||
style.zIndex = 999999999;
|
||||
style.cursor = 'default';
|
||||
}( this.displayRegion.style ));
|
||||
}( this.displayRegion.style, this.borderWidth ));
|
||||
|
||||
|
||||
this.element.innerTracker = new $.MouseTracker({
|
||||
element: this.element,
|
||||
scrollHandler: function(){
|
||||
//dont scroll the page up and down if the user is scrolling
|
||||
//in the navigator
|
||||
return false;
|
||||
}
|
||||
element: this.element,
|
||||
dragHandler: $.delegate( this, onCanvasDrag ),
|
||||
clickHandler: $.delegate( this, onCanvasClick ),
|
||||
releaseHandler: $.delegate( this, onCanvasRelease ),
|
||||
scrollHandler: $.delegate( this, onCanvasScroll )
|
||||
}).setTracking( true );
|
||||
|
||||
this.displayRegion.innerTracker = new $.MouseTracker({
|
||||
element: this.displayRegion,
|
||||
clickTimeThreshold: this.clickTimeThreshold,
|
||||
clickDistThreshold: this.clickDistThreshold,
|
||||
clickHandler: $.delegate( this, onCanvasClick ),
|
||||
dragHandler: $.delegate( this, onCanvasDrag ),
|
||||
releaseHandler: $.delegate( this, onCanvasRelease ),
|
||||
scrollHandler: $.delegate( this, onCanvasScroll ),
|
||||
focusHandler: function(){
|
||||
var point = $.getElementPosition( _this.viewer.element );
|
||||
|
||||
window.scrollTo( 0, point.y );
|
||||
|
||||
_this.viewer.setControlsEnabled( true );
|
||||
(function( style ){
|
||||
style.border = '2px solid #437AB2';
|
||||
//style.outline = '2px auto #437AB2';
|
||||
}( this.element.style ));
|
||||
|
||||
},
|
||||
blurHandler: function(){
|
||||
_this.viewer.setControlsEnabled( false );
|
||||
(function( style ){
|
||||
style.border = '2px solid #900';
|
||||
//style.outline = '2px auto #900';
|
||||
}( this.element.style ));
|
||||
},
|
||||
keyHandler: function(tracker, keyCode, shiftKey){
|
||||
//console.log( keyCode );
|
||||
switch( keyCode ){
|
||||
case 61://=|+
|
||||
_this.viewer.viewport.zoomBy(1.1);
|
||||
_this.viewer.viewport.applyConstraints();
|
||||
return false;
|
||||
case 45://-|_
|
||||
_this.viewer.viewport.zoomBy(0.9);
|
||||
_this.viewer.viewport.applyConstraints();
|
||||
return false;
|
||||
case 48://0|)
|
||||
_this.viewer.viewport.goHome();
|
||||
_this.viewer.viewport.applyConstraints();
|
||||
return false;
|
||||
case 119://w
|
||||
case 87://W
|
||||
case 38://up arrow
|
||||
if (shiftKey)
|
||||
_this.viewer.viewport.zoomBy(1.1);
|
||||
else
|
||||
_this.viewer.viewport.panBy(new $.Point(0, -0.05));
|
||||
_this.viewer.viewport.applyConstraints();
|
||||
return false;
|
||||
case 115://s
|
||||
case 83://S
|
||||
case 40://down arrow
|
||||
if (shiftKey)
|
||||
_this.viewer.viewport.zoomBy(0.9);
|
||||
else
|
||||
_this.viewer.viewport.panBy(new $.Point(0, 0.05));
|
||||
_this.viewer.viewport.applyConstraints();
|
||||
return false;
|
||||
case 97://a
|
||||
case 37://left arrow
|
||||
_this.viewer.viewport.panBy(new $.Point(-0.05, 0));
|
||||
_this.viewer.viewport.applyConstraints();
|
||||
return false;
|
||||
case 100://d
|
||||
case 39://right arrow
|
||||
_this.viewer.viewport.panBy(new $.Point(0.05, 0));
|
||||
_this.viewer.viewport.applyConstraints();
|
||||
return false;
|
||||
default:
|
||||
//console.log( 'navigator keycode %s', keyCode );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}).setTracking( true ); // default state
|
||||
|
||||
/*this.displayRegion.outerTracker = new $.MouseTracker({
|
||||
element: this.container,
|
||||
clickTimeThreshold: this.clickTimeThreshold,
|
||||
@ -182,48 +180,112 @@ $.Navigator = function( options ){
|
||||
|
||||
viewer.addControl(
|
||||
this.element,
|
||||
$.ControlAnchor.TOP_RIGHT
|
||||
options.controlOptions
|
||||
);
|
||||
|
||||
if( options.width && options.height ){
|
||||
this.element.style.width = options.width + 'px';
|
||||
this.element.style.height = options.height + 'px';
|
||||
} else {
|
||||
this.element.style.width = ( viewerSize.x * options.sizeRatio ) + 'px';
|
||||
this.element.style.height = ( viewerSize.y * options.sizeRatio ) + 'px';
|
||||
if ( options.controlOptions.anchor != $.ControlAnchor.ABSOLUTE && options.controlOptions.anchor != $.ControlAnchor.NONE ) {
|
||||
if ( options.width && options.height ) {
|
||||
this.element.style.height = typeof ( options.height ) == "number" ? ( options.height + 'px' ) : options.height;
|
||||
this.element.style.width = typeof ( options.width ) == "number" ? ( options.width + 'px' ) : options.width;
|
||||
} else {
|
||||
viewerSize = $.getElementSize( viewer.element );
|
||||
this.element.style.height = ( viewerSize.y * options.sizeRatio ) + 'px';
|
||||
this.element.style.width = ( viewerSize.x * options.sizeRatio ) + 'px';
|
||||
this.oldViewerSize = viewerSize;
|
||||
}
|
||||
navigatorSize = $.getElementSize( this.element );
|
||||
this.elementArea = navigatorSize.x * navigatorSize.y;
|
||||
}
|
||||
|
||||
this.oldContainerSize = new $.Point( 0, 0 );
|
||||
|
||||
$.Viewer.apply( this, [ options ] );
|
||||
|
||||
this.element.getElementsByTagName('form')[0].appendChild( this.displayRegion );
|
||||
this.element.getElementsByTagName( 'div' )[0].appendChild( this.displayRegion );
|
||||
unneededElement = this.element.getElementsByTagName('textarea')[0];
|
||||
if (unneededElement) {
|
||||
unneededElement.parentNode.removeChild(unneededElement);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$.extend( $.Navigator.prototype, $.EventHandler.prototype, $.Viewer.prototype, {
|
||||
$.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /** @lends OpenSeadragon.Navigator.prototype */{
|
||||
|
||||
/**
|
||||
* Used to notify the navigator when its size has changed.
|
||||
* Especially useful when {@link OpenSeadragon.Options}.navigatorAutoResize is set to false and the navigator is resizable.
|
||||
* @function
|
||||
* @name OpenSeadragon.Navigator.prototype.update
|
||||
*/
|
||||
update: function( viewport ){
|
||||
updateSize: function () {
|
||||
if ( this.viewport ) {
|
||||
var containerSize = new $.Point(
|
||||
(this.container.clientWidth === 0 ? 1 : this.container.clientWidth),
|
||||
(this.container.clientHeight === 0 ? 1 : this.container.clientHeight)
|
||||
);
|
||||
if ( !containerSize.equals( this.oldContainerSize ) ) {
|
||||
var oldBounds = this.viewport.getBounds();
|
||||
var oldCenter = this.viewport.getCenter();
|
||||
this.viewport.resize( containerSize, true );
|
||||
var imageHeight = 1 / this.source.aspectRatio;
|
||||
var newWidth = oldBounds.width <= 1 ? oldBounds.width : 1;
|
||||
var newHeight = oldBounds.height <= imageHeight ?
|
||||
oldBounds.height : imageHeight;
|
||||
var newBounds = new $.Rect(
|
||||
oldCenter.x - ( newWidth / 2.0 ),
|
||||
oldCenter.y - ( newHeight / 2.0 ),
|
||||
newWidth,
|
||||
newHeight
|
||||
);
|
||||
this.viewport.fitBounds( newBounds, true );
|
||||
this.oldContainerSize = containerSize;
|
||||
this.drawer.update();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
var bounds,
|
||||
/**
|
||||
* Used to update the navigator minimap's viewport rectangle when a change in the viewer's viewport occurs.
|
||||
* @function
|
||||
* @param {OpenSeadragon.Viewport} The viewport this navigator is tracking.
|
||||
*/
|
||||
update: function( viewport ) {
|
||||
|
||||
var viewerSize,
|
||||
newWidth,
|
||||
newHeight,
|
||||
bounds,
|
||||
topleft,
|
||||
bottomright;
|
||||
|
||||
if( viewport && this.viewport ){
|
||||
viewerSize = $.getElementSize( this.viewer.element );
|
||||
if ( !viewerSize.equals( this.oldViewerSize ) ) {
|
||||
this.oldViewerSize = viewerSize;
|
||||
if ( this.maintainSizeRatio ) {
|
||||
newWidth = viewerSize.x * this.sizeRatio;
|
||||
newHeight = viewerSize.y * this.sizeRatio;
|
||||
}
|
||||
else {
|
||||
newWidth = Math.sqrt(this.elementArea * (viewerSize.x / viewerSize.y));
|
||||
newHeight = this.elementArea / newWidth;
|
||||
}
|
||||
this.element.style.width = newWidth + 'px';
|
||||
this.element.style.height = newHeight + 'px';
|
||||
this.updateSize();
|
||||
}
|
||||
|
||||
if( viewport && this.viewport ) {
|
||||
bounds = viewport.getBounds( true );
|
||||
topleft = this.viewport.pixelFromPoint( bounds.getTopLeft() );
|
||||
bottomright = this.viewport.pixelFromPoint( bounds.getBottomRight() );
|
||||
topleft = this.viewport.pixelFromPoint( bounds.getTopLeft(), false );
|
||||
bottomright = this.viewport.pixelFromPoint( bounds.getBottomRight(), false ).minus( this.totalBorderWidths );
|
||||
|
||||
//update style for navigator-box
|
||||
(function(style){
|
||||
(function(style) {
|
||||
|
||||
style.top = topleft.y + 'px';
|
||||
style.left = topleft.x + 'px';
|
||||
|
||||
var width = Math.abs( topleft.x - bottomright.x ) - 3; // TODO: What does this magic number mean?
|
||||
var height = Math.abs( topleft.y - bottomright.y ) - 3;
|
||||
var width = Math.abs( topleft.x - bottomright.x );
|
||||
var height = Math.abs( topleft.y - bottomright.y );
|
||||
// make sure width and height are non-negative so IE doesn't throw
|
||||
style.width = Math.max( width, 0 ) + 'px';
|
||||
style.height = Math.max( height, 0 ) + 'px';
|
||||
@ -233,7 +295,8 @@ $.extend( $.Navigator.prototype, $.EventHandler.prototype, $.Viewer.prototype, {
|
||||
|
||||
},
|
||||
|
||||
open: function( source ){
|
||||
open: function( source ) {
|
||||
this.updateSize();
|
||||
var containerSize = this.viewer.viewport.containerSize.times( this.sizeRatio );
|
||||
if( source.tileSize > containerSize.x ||
|
||||
source.tileSize > containerSize.y ){
|
||||
@ -249,33 +312,43 @@ $.extend( $.Navigator.prototype, $.EventHandler.prototype, $.Viewer.prototype, {
|
||||
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @inner
|
||||
* @function
|
||||
*/
|
||||
function onCanvasClick( tracker, position, quick, shift ) {
|
||||
this.displayRegion.focus();
|
||||
function onCanvasClick( event ) {
|
||||
var newBounds,
|
||||
viewerPosition,
|
||||
dimensions;
|
||||
if (! this.drag) {
|
||||
if ( this.viewer.viewport ) {
|
||||
this.viewer.viewport.panTo( this.viewport.pointFromPixel( event.position ) );
|
||||
this.viewer.viewport.applyConstraints();
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.drag = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @inner
|
||||
* @function
|
||||
*/
|
||||
function onCanvasDrag( tracker, position, delta, shift ) {
|
||||
function onCanvasDrag( event ) {
|
||||
if ( this.viewer.viewport ) {
|
||||
this.drag = true;
|
||||
if( !this.panHorizontal ){
|
||||
delta.x = 0;
|
||||
event.delta.x = 0;
|
||||
}
|
||||
if( !this.panVertical ){
|
||||
delta.y = 0;
|
||||
event.delta.y = 0;
|
||||
}
|
||||
this.viewer.viewport.panBy(
|
||||
this.viewport.deltaPointsFromPixels(
|
||||
delta
|
||||
event.delta
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -287,8 +360,8 @@ function onCanvasDrag( tracker, position, delta, shift ) {
|
||||
* @inner
|
||||
* @function
|
||||
*/
|
||||
function onCanvasRelease( tracker, position, insideElementPress, insideElementRelease ) {
|
||||
if ( insideElementPress && this.viewer.viewport ) {
|
||||
function onCanvasRelease( event ) {
|
||||
if ( event.insideElementPressed && this.viewer.viewport ) {
|
||||
this.viewer.viewport.applyConstraints();
|
||||
}
|
||||
}
|
||||
@ -299,18 +372,31 @@ function onCanvasRelease( tracker, position, insideElementPress, insideElementRe
|
||||
* @inner
|
||||
* @function
|
||||
*/
|
||||
function onCanvasScroll( tracker, position, scroll, shift ) {
|
||||
var factor;
|
||||
if ( this.viewer.viewport ) {
|
||||
factor = Math.pow( this.zoomPerScroll, scroll );
|
||||
this.viewer.viewport.zoomBy(
|
||||
factor,
|
||||
//this.viewport.pointFromPixel( position, true )
|
||||
this.viewport.getCenter()
|
||||
);
|
||||
this.viewer.viewport.applyConstraints();
|
||||
}
|
||||
//cancels event
|
||||
function onCanvasScroll( event ) {
|
||||
/**
|
||||
* Raised when a scroll event occurs on the {@link OpenSeadragon.Viewer#navigator} element (mouse wheel, touch pinch, etc.).
|
||||
*
|
||||
* @event navigator-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.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.viewer.raiseEvent( 'navigator-scroll', {
|
||||
tracker: event.eventSource,
|
||||
position: event.position,
|
||||
scroll: event.scroll,
|
||||
shift: event.shift,
|
||||
originalEvent: event.originalEvent
|
||||
});
|
||||
|
||||
//dont scroll the page up and down if the user is scrolling
|
||||
//in the navigator
|
||||
return false;
|
||||
}
|
||||
|
||||
|
1488
src/openseadragon.js
@ -1,13 +1,55 @@
|
||||
/*
|
||||
* OpenSeadragon - OsmTileSource
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Derived from the OSM tile source in Rainer Simon's seajax-utils project
|
||||
* <http://github.com/rsimon/seajax-utils>. Rainer Simon has contributed
|
||||
* the included code to the OpenSeadragon project under the New BSD license;
|
||||
* see <https://github.com/openseadragon/openseadragon/issues/58>.
|
||||
*/
|
||||
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* A tilesource implementation for OpenStreetMap. Adopted from Rainer Simon
|
||||
* project http://github.com/rsimon/seajax-utils.
|
||||
* @class OsmTileSource
|
||||
* @classdesc A tilesource implementation for OpenStreetMap.<br><br>
|
||||
*
|
||||
* Note 1. Zoomlevels. Deep Zoom and OSM define zoom levels differently. In Deep
|
||||
* Zoom, level 0 equals an image of 1x1 pixels. In OSM, level 0 equals an image of
|
||||
* 256x256 levels (see http://gasi.ch/blog/inside-deep-zoom-2). I.e. there is a
|
||||
* difference of log2(256)=8 levels.
|
||||
* difference of log2(256)=8 levels.<br><br>
|
||||
*
|
||||
* Note 2. Image dimension. According to the OSM Wiki
|
||||
* (http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Zoom_levels)
|
||||
@ -15,7 +57,7 @@
|
||||
* pixel size. I.e. the Deep Zoom image dimension is 65.572.864x65.572.864
|
||||
* pixels.
|
||||
*
|
||||
* @class
|
||||
* @memberof OpenSeadragon
|
||||
* @extends OpenSeadragon.TileSource
|
||||
* @param {Number|Object} width - the pixel width of the image or the idiomatic
|
||||
* options object which is used instead of positional arguments.
|
||||
@ -58,14 +100,13 @@ $.OsmTileSource = function( width, height, tileSize, tileOverlap, tilesUrl ) {
|
||||
|
||||
};
|
||||
|
||||
$.extend( $.OsmTileSource.prototype, $.TileSource.prototype, {
|
||||
$.extend( $.OsmTileSource.prototype, $.TileSource.prototype, /** @lends OpenSeadragon.OsmTileSource.prototype */{
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the data and/or url imply the image service is supported by
|
||||
* this tile source.
|
||||
* @function
|
||||
* @name OpenSeadragon.OsmTileSource.prototype.supports
|
||||
* @param {Object|Array} data
|
||||
* @param {String} optional - url
|
||||
*/
|
||||
@ -79,7 +120,6 @@ $.extend( $.OsmTileSource.prototype, $.TileSource.prototype, {
|
||||
/**
|
||||
*
|
||||
* @function
|
||||
* @name OpenSeadragon.OsmTileSource.prototype.configure
|
||||
* @param {Object} data - the raw configuration
|
||||
* @param {String} url - the url the data was retreived from if any.
|
||||
* @return {Object} options - A dictionary of keyword arguments sufficient
|
||||
@ -92,7 +132,6 @@ $.extend( $.OsmTileSource.prototype, $.TileSource.prototype, {
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @name OpenSeadragon.OsmTileSource.prototype.getTileUrl
|
||||
* @param {Number} level
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
|
200
src/overlay.js
@ -1,10 +1,55 @@
|
||||
/*
|
||||
* OpenSeadragon - Overlay
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* An enumeration of positions that an overlay may be assigned relative
|
||||
* to the viewport including CENTER, TOP_LEFT (default), TOP, TOP_RIGHT,
|
||||
* RIGHT, BOTTOM_RIGHT, BOTTOM, BOTTOM_LEFT, and LEFT.
|
||||
* An enumeration of positions that an overlay may be assigned relative to
|
||||
* the viewport.
|
||||
* @member OverlayPlacement
|
||||
* @memberof OpenSeadragon
|
||||
* @static
|
||||
* @type {Object}
|
||||
* @property {Number} CENTER
|
||||
* @property {Number} TOP_LEFT
|
||||
* @property {Number} TOP
|
||||
* @property {Number} TOP_RIGHT
|
||||
* @property {Number} RIGHT
|
||||
* @property {Number} BOTTOM_RIGHT
|
||||
* @property {Number} BOTTOM
|
||||
* @property {Number} BOTTOM_LEFT
|
||||
* @property {Number} LEFT
|
||||
*/
|
||||
$.OverlayPlacement = {
|
||||
CENTER: 0,
|
||||
@ -19,34 +64,76 @@
|
||||
};
|
||||
|
||||
/**
|
||||
* An Overlay provides a
|
||||
* @class
|
||||
* @class Overlay
|
||||
* @classdesc Provides a way to float an HTML element on top of the viewer element.
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
* @param {Object} options
|
||||
* @param {Element} options.element
|
||||
* @param {OpenSeadragon.Point|OpenSeadragon.Rect} options.location - The
|
||||
* location of the overlay on the image. If a {@link OpenSeadragon.Point}
|
||||
* is specified, the overlay will keep a constant size independently of the
|
||||
* zoom. If a {@link OpenSeadragon.Rect} is specified, the overlay size will
|
||||
* be adjusted when the zoom changes.
|
||||
* @param {OpenSeadragon.OverlayPlacement} [options.placement=OpenSeadragon.OverlayPlacement.TOP_LEFT]
|
||||
* Relative position to the viewport.
|
||||
* Only used if location is a {@link OpenSeadragon.Point}.
|
||||
* @param {OpenSeadragon.Overlay.OnDrawCallback} [options.onDraw]
|
||||
* @param {Boolean} [options.checkResize=true] Set to false to avoid to
|
||||
* check the size of the overlay everytime it is drawn when using a
|
||||
* {@link OpenSeadragon.Point} as options.location. It will improve
|
||||
* performances but will cause a misalignment if the overlay size changes.
|
||||
*/
|
||||
$.Overlay = function( element, location, placement ) {
|
||||
this.element = element;
|
||||
this.scales = location instanceof $.Rect;
|
||||
|
||||
/**
|
||||
* onDraw callback signature used by {@link OpenSeadragon.Overlay}.
|
||||
*
|
||||
* @callback OnDrawCallback
|
||||
* @memberof OpenSeadragon.Overlay
|
||||
* @param {OpenSeadragon.Point} position
|
||||
* @param {OpenSeadragon.Point} size
|
||||
* @param {Element} element
|
||||
*/
|
||||
|
||||
var options;
|
||||
if ( $.isPlainObject( element ) ) {
|
||||
options = element;
|
||||
} else {
|
||||
options = {
|
||||
element: element,
|
||||
location: location,
|
||||
placement: placement
|
||||
};
|
||||
}
|
||||
|
||||
this.element = options.element;
|
||||
this.scales = options.location instanceof $.Rect;
|
||||
this.bounds = new $.Rect(
|
||||
location.x,
|
||||
location.y,
|
||||
location.width,
|
||||
location.height
|
||||
options.location.x,
|
||||
options.location.y,
|
||||
options.location.width,
|
||||
options.location.height
|
||||
);
|
||||
this.position = new $.Point(
|
||||
location.x,
|
||||
location.y
|
||||
options.location.x,
|
||||
options.location.y
|
||||
);
|
||||
this.size = new $.Point(
|
||||
location.width,
|
||||
location.height
|
||||
options.location.width,
|
||||
options.location.height
|
||||
);
|
||||
this.style = element.style;
|
||||
this.style = options.element.style;
|
||||
// rects are always top-left
|
||||
this.placement = location instanceof $.Point ?
|
||||
placement :
|
||||
this.placement = options.location instanceof $.Point ?
|
||||
options.placement :
|
||||
$.OverlayPlacement.TOP_LEFT;
|
||||
this.onDraw = options.onDraw;
|
||||
this.checkResize = options.checkResize === undefined ?
|
||||
true : options.checkResize;
|
||||
};
|
||||
|
||||
$.Overlay.prototype = {
|
||||
$.Overlay.prototype = /** @lends OpenSeadragon.Overlay.prototype */{
|
||||
|
||||
/**
|
||||
* @function
|
||||
@ -100,7 +187,7 @@
|
||||
element.parentNode.removeChild( element );
|
||||
//this should allow us to preserve overlays when required between
|
||||
//pages
|
||||
if( element.prevElementParent ){
|
||||
if ( element.prevElementParent ) {
|
||||
style.display = 'none';
|
||||
//element.prevElementParent.insertBefore(
|
||||
// element,
|
||||
@ -110,6 +197,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
// clear the onDraw callback
|
||||
this.onDraw = null;
|
||||
|
||||
style.top = "";
|
||||
style.left = "";
|
||||
style.position = "";
|
||||
@ -124,40 +214,80 @@
|
||||
* @function
|
||||
* @param {Element} container
|
||||
*/
|
||||
drawHTML: function( container ) {
|
||||
drawHTML: function( container, viewport ) {
|
||||
var element = this.element,
|
||||
style = this.style,
|
||||
scales = this.scales,
|
||||
position,
|
||||
size;
|
||||
degrees = viewport.degrees,
|
||||
position = viewport.pixelFromPoint(
|
||||
this.bounds.getTopLeft(),
|
||||
true
|
||||
),
|
||||
size,
|
||||
overlayCenter;
|
||||
|
||||
if ( element.parentNode != container ) {
|
||||
//save the source parent for later if we need it
|
||||
element.prevElementParent = element.parentNode;
|
||||
element.prevNextSibling = element.nextSibling;
|
||||
container.appendChild( element );
|
||||
}
|
||||
|
||||
if ( !scales ) {
|
||||
this.size = $.getElementSize( element );
|
||||
}
|
||||
|
||||
position = this.position;
|
||||
size = this.size;
|
||||
if ( scales ) {
|
||||
size = viewport.deltaPixelsFromPoints(
|
||||
this.bounds.getSize(),
|
||||
true
|
||||
);
|
||||
} else if ( this.checkResize ) {
|
||||
size = $.getElementSize( element );
|
||||
} else {
|
||||
size = this.size;
|
||||
}
|
||||
|
||||
this.position = position;
|
||||
this.size = size;
|
||||
|
||||
this.adjust( position, size );
|
||||
|
||||
position = position.apply( Math.floor );
|
||||
size = size.apply( Math.ceil );
|
||||
|
||||
style.left = position.x + "px";
|
||||
style.top = position.y + "px";
|
||||
style.position = "absolute";
|
||||
style.display = 'block';
|
||||
// rotate the position of the overlay
|
||||
// TODO only rotate overlays if in canvas mode
|
||||
// TODO replace the size rotation with CSS3 transforms
|
||||
// TODO add an option to overlays to not rotate with the image
|
||||
// Currently only rotates position and size
|
||||
if( degrees !== 0 && this.scales ) {
|
||||
overlayCenter = new $.Point( size.x / 2, size.y / 2 );
|
||||
|
||||
if ( scales ) {
|
||||
style.width = size.x + "px";
|
||||
style.height = size.y + "px";
|
||||
var drawerCenter = new $.Point(
|
||||
viewport.viewer.drawer.canvas.width / 2,
|
||||
viewport.viewer.drawer.canvas.height / 2
|
||||
);
|
||||
position = position.plus( overlayCenter ).rotate(
|
||||
degrees,
|
||||
drawerCenter
|
||||
).minus( overlayCenter );
|
||||
|
||||
size = size.rotate( degrees, new $.Point( 0, 0 ) );
|
||||
size = new $.Point( Math.abs( size.x ), Math.abs( size.y ) );
|
||||
}
|
||||
|
||||
// call the onDraw callback if it exists to allow one to overwrite
|
||||
// the drawing/positioning/sizing of the overlay
|
||||
if ( this.onDraw ) {
|
||||
this.onDraw( position, size, element );
|
||||
} else {
|
||||
style.left = position.x + "px";
|
||||
style.top = position.y + "px";
|
||||
style.position = "absolute";
|
||||
style.display = 'block';
|
||||
|
||||
if ( scales ) {
|
||||
style.width = size.x + "px";
|
||||
style.height = size.y + "px";
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
125
src/point.js
@ -1,21 +1,65 @@
|
||||
/*
|
||||
* OpenSeadragon - Point
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* A Point is really used as a 2-dimensional vector, equally useful for
|
||||
* @class Point
|
||||
* @classdesc A Point is really used as a 2-dimensional vector, equally useful for
|
||||
* representing a point on a plane, or the height and width of a plane
|
||||
* not requiring any other frame of reference.
|
||||
* @class
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
* @param {Number} [x] The vector component 'x'. Defaults to the origin at 0.
|
||||
* @param {Number} [y] The vector component 'y'. Defaults to the origin at 0.
|
||||
* @property {Number} [x] The vector component 'x'.
|
||||
* @property {Number} [y] The vector component 'y'.
|
||||
*/
|
||||
$.Point = function( x, y ) {
|
||||
/**
|
||||
* The vector component 'x'.
|
||||
* @member {Number} x
|
||||
* @memberof OpenSeadragon.Point#
|
||||
*/
|
||||
this.x = typeof ( x ) == "number" ? x : 0;
|
||||
/**
|
||||
* The vector component 'y'.
|
||||
* @member {Number} y
|
||||
* @memberof OpenSeadragon.Point#
|
||||
*/
|
||||
this.y = typeof ( y ) == "number" ? y : 0;
|
||||
};
|
||||
|
||||
$.Point.prototype = {
|
||||
$.Point.prototype = /** @lends OpenSeadragon.Point.prototype */{
|
||||
|
||||
/**
|
||||
* Add another Point to this point and return a new Point.
|
||||
@ -32,10 +76,10 @@ $.Point.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Add another Point to this point and return a new Point.
|
||||
* Substract another Point to this point and return a new Point.
|
||||
* @function
|
||||
* @param {OpenSeadragon.Point} point The point to add vector components.
|
||||
* @returns {OpenSeadragon.Point} A new point representing the sum of the
|
||||
* @param {OpenSeadragon.Point} point The point to substract vector components.
|
||||
* @returns {OpenSeadragon.Point} A new point representing the substraction of the
|
||||
* vector components
|
||||
*/
|
||||
minus: function( point ) {
|
||||
@ -46,11 +90,11 @@ $.Point.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Add another Point to this point and return a new Point.
|
||||
* Multiply this point by a factor and return a new Point.
|
||||
* @function
|
||||
* @param {OpenSeadragon.Point} point The point to add vector components.
|
||||
* @returns {OpenSeadragon.Point} A new point representing the sum of the
|
||||
* vector components
|
||||
* @param {Number} factor The factor to multiply vector components.
|
||||
* @returns {OpenSeadragon.Point} A new point representing the multiplication
|
||||
* of the vector components by the factor
|
||||
*/
|
||||
times: function( factor ) {
|
||||
return new $.Point(
|
||||
@ -60,11 +104,11 @@ $.Point.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Add another Point to this point and return a new Point.
|
||||
* Divide this point by a factor and return a new Point.
|
||||
* @function
|
||||
* @param {OpenSeadragon.Point} point The point to add vector components.
|
||||
* @returns {OpenSeadragon.Point} A new point representing the sum of the
|
||||
* vector components
|
||||
* @param {Number} factor The factor to divide vector components.
|
||||
* @returns {OpenSeadragon.Point} A new point representing the division of the
|
||||
* vector components by the factor
|
||||
*/
|
||||
divide: function( factor ) {
|
||||
return new $.Point(
|
||||
@ -74,10 +118,9 @@ $.Point.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Add another Point to this point and return a new Point.
|
||||
* Compute the opposite of this point and return a new Point.
|
||||
* @function
|
||||
* @param {OpenSeadragon.Point} point The point to add vector components.
|
||||
* @returns {OpenSeadragon.Point} A new point representing the sum of the
|
||||
* @returns {OpenSeadragon.Point} A new point representing the opposite of the
|
||||
* vector components
|
||||
*/
|
||||
negate: function() {
|
||||
@ -85,11 +128,10 @@ $.Point.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Add another Point to this point and return a new Point.
|
||||
* Compute the distance between this point and another point.
|
||||
* @function
|
||||
* @param {OpenSeadragon.Point} point The point to add vector components.
|
||||
* @returns {OpenSeadragon.Point} A new point representing the sum of the
|
||||
* vector components
|
||||
* @param {OpenSeadragon.Point} point The point to compute the distance with.
|
||||
* @returns {Number} The distance between the 2 points
|
||||
*/
|
||||
distanceTo: function( point ) {
|
||||
return Math.sqrt(
|
||||
@ -99,22 +141,21 @@ $.Point.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Add another Point to this point and return a new Point.
|
||||
* Apply a function to each coordinate of this point and return a new point.
|
||||
* @function
|
||||
* @param {OpenSeadragon.Point} point The point to add vector components.
|
||||
* @returns {OpenSeadragon.Point} A new point representing the sum of the
|
||||
* vector components
|
||||
* @param {function} func The function to apply to each coordinate.
|
||||
* @returns {OpenSeadragon.Point} A new point with the coordinates computed
|
||||
* by the specified function
|
||||
*/
|
||||
apply: function( func ) {
|
||||
return new $.Point( func( this.x ), func( this.y ) );
|
||||
},
|
||||
|
||||
/**
|
||||
* Add another Point to this point and return a new Point.
|
||||
* Check if this point is equal to another one.
|
||||
* @function
|
||||
* @param {OpenSeadragon.Point} point The point to add vector components.
|
||||
* @returns {OpenSeadragon.Point} A new point representing the sum of the
|
||||
* vector components
|
||||
* @param {OpenSeadragon.Point} point The point to compare this point with.
|
||||
* @returns {Boolean} true if they are equal, false otherwise.
|
||||
*/
|
||||
equals: function( point ) {
|
||||
return (
|
||||
@ -127,11 +168,25 @@ $.Point.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Add another Point to this point and return a new Point.
|
||||
* Rotates the point around the specified pivot
|
||||
* From http://stackoverflow.com/questions/4465931/rotate-rectangle-around-a-point
|
||||
* @function
|
||||
* @param {OpenSeadragon.Point} point The point to add vector components.
|
||||
* @returns {OpenSeadragon.Point} A new point representing the sum of the
|
||||
* vector components
|
||||
* @param {Number} degress to rotate around the pivot.
|
||||
* @param {OpenSeadragon.Point} pivot Point about which to rotate.
|
||||
* @returns {OpenSeadragon.Point}. A new point representing the point rotated around the specified pivot
|
||||
*/
|
||||
rotate: function ( degrees, pivot ) {
|
||||
var angle = degrees * Math.PI / 180.0,
|
||||
x = Math.cos( angle ) * ( this.x - pivot.x ) - Math.sin( angle ) * ( this.y - pivot.y ) + pivot.x,
|
||||
y = Math.sin( angle ) * ( this.x - pivot.x ) + Math.cos( angle ) * ( this.y - pivot.y ) + pivot.y;
|
||||
return new $.Point( x, y );
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert this point to a string in the format (x,y) where x and y are
|
||||
* rounded to the nearest integer.
|
||||
* @function
|
||||
* @returns {String} A string representation of this point.
|
||||
*/
|
||||
toString: function() {
|
||||
return "(" + Math.round(this.x) + "," + Math.round(this.y) + ")";
|
||||
|
@ -1,9 +1,45 @@
|
||||
/*
|
||||
* OpenSeadragon - Profiler
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* A utility class useful for developers to establish baseline performance
|
||||
* @class Profiler
|
||||
* @classdesc A utility class useful for developers to establish baseline performance
|
||||
* metrics of rendering routines.
|
||||
* @class
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
* @property {Boolean} midUpdate
|
||||
* @property {Number} numUpdates
|
||||
* @property {Number} lastBeginTime
|
||||
@ -32,7 +68,7 @@ $.Profiler = function() {
|
||||
this.maxIdleTime = 0;
|
||||
};
|
||||
|
||||
$.Profiler.prototype = {
|
||||
$.Profiler.prototype = /** @lends OpenSeadragon.Profiler.prototype */{
|
||||
|
||||
/**
|
||||
* @function
|
||||
@ -43,7 +79,7 @@ $.Profiler.prototype = {
|
||||
}
|
||||
|
||||
this.midUpdate = true;
|
||||
this.lastBeginTime = new Date().getTime();
|
||||
this.lastBeginTime = $.now();
|
||||
|
||||
if (this.numUpdates < 1) {
|
||||
return; // this is the first update
|
||||
@ -69,7 +105,7 @@ $.Profiler.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastEndTime = new Date().getTime();
|
||||
this.lastEndTime = $.now();
|
||||
this.midUpdate = false;
|
||||
|
||||
var time = this.lastEndTime - this.lastBeginTime;
|
||||
|
163
src/rectangle.js
@ -1,29 +1,80 @@
|
||||
/*
|
||||
* OpenSeadragon - Rect
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* A Rectangle really represents a 2x2 matrix where each row represents a
|
||||
* @class Rect
|
||||
* @classdesc A Rectangle really represents a 2x2 matrix where each row represents a
|
||||
* 2 dimensional vector component, the first is (x,y) and the second is
|
||||
* (width, height). The latter component implies the equation of a simple
|
||||
* plane.
|
||||
*
|
||||
* @class
|
||||
* @memberof OpenSeadragon
|
||||
* @param {Number} x The vector component 'x'.
|
||||
* @param {Number} y The vector component 'y'.
|
||||
* @param {Number} width The vector component 'height'.
|
||||
* @param {Number} height The vector component 'width'.
|
||||
* @property {Number} x The vector component 'x'.
|
||||
* @property {Number} y The vector component 'y'.
|
||||
* @property {Number} width The vector component 'width'.
|
||||
* @property {Number} height The vector component 'height'.
|
||||
*/
|
||||
$.Rect = function( x, y, width, height ) {
|
||||
/**
|
||||
* The vector component 'x'.
|
||||
* @member {Number} x
|
||||
* @memberof OpenSeadragon.Rect#
|
||||
*/
|
||||
this.x = typeof ( x ) == "number" ? x : 0;
|
||||
/**
|
||||
* The vector component 'y'.
|
||||
* @member {Number} y
|
||||
* @memberof OpenSeadragon.Rect#
|
||||
*/
|
||||
this.y = typeof ( y ) == "number" ? y : 0;
|
||||
/**
|
||||
* The vector component 'width'.
|
||||
* @member {Number} width
|
||||
* @memberof OpenSeadragon.Rect#
|
||||
*/
|
||||
this.width = typeof ( width ) == "number" ? width : 0;
|
||||
/**
|
||||
* The vector component 'height'.
|
||||
* @member {Number} height
|
||||
* @memberof OpenSeadragon.Rect#
|
||||
*/
|
||||
this.height = typeof ( height ) == "number" ? height : 0;
|
||||
};
|
||||
|
||||
$.Rect.prototype = {
|
||||
$.Rect.prototype = /** @lends OpenSeadragon.Rect.prototype */{
|
||||
|
||||
/**
|
||||
* The aspect ratio is simply the ratio of width to height.
|
||||
@ -35,14 +86,17 @@ $.Rect.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Provides the coordinates of the upper-left corner of the rectanglea s a
|
||||
* Provides the coordinates of the upper-left corner of the rectangle as a
|
||||
* point.
|
||||
* @function
|
||||
* @returns {OpenSeadragon.Point} The coordinate of the upper-left corner of
|
||||
* the rectangle.
|
||||
*/
|
||||
getTopLeft: function() {
|
||||
return new $.Point( this.x, this.y );
|
||||
return new $.Point(
|
||||
this.x,
|
||||
this.y
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -59,10 +113,38 @@ $.Rect.prototype = {
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Provides the coordinates of the top-right corner of the rectangle as a
|
||||
* point.
|
||||
* @function
|
||||
* @returns {OpenSeadragon.Point} The coordinate of the top-right corner of
|
||||
* the rectangle.
|
||||
*/
|
||||
getTopRight: function() {
|
||||
return new $.Point(
|
||||
this.x + this.width,
|
||||
this.y
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Provides the coordinates of the bottom-left corner of the rectangle as a
|
||||
* point.
|
||||
* @function
|
||||
* @returns {OpenSeadragon.Point} The coordinate of the bottom-left corner of
|
||||
* the rectangle.
|
||||
*/
|
||||
getBottomLeft: function() {
|
||||
return new $.Point(
|
||||
this.x,
|
||||
this.y + this.height
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Computes the center of the rectangle.
|
||||
* @function
|
||||
* @returns {OpenSeadragon.Point} The center of the rectangle as represnted
|
||||
* @returns {OpenSeadragon.Point} The center of the rectangle as represented
|
||||
* as represented by a 2-dimensional vector (x,y)
|
||||
*/
|
||||
getCenter: function() {
|
||||
@ -75,7 +157,7 @@ $.Rect.prototype = {
|
||||
/**
|
||||
* Returns the width and height component as a vector OpenSeadragon.Point
|
||||
* @function
|
||||
* @returns {OpenSeadragon.Point} The 2 dimensional vector represnting the
|
||||
* @returns {OpenSeadragon.Point} The 2 dimensional vector representing the
|
||||
* the width and height of the rectangle.
|
||||
*/
|
||||
getSize: function() {
|
||||
@ -83,7 +165,7 @@ $.Rect.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines if two Rectanlges have equivalent components.
|
||||
* Determines if two Rectangles have equivalent components.
|
||||
* @function
|
||||
* @param {OpenSeadragon.Rect} rectangle The Rectangle to compare to.
|
||||
* @return {Boolean} 'true' if all components are equal, otherwise 'false'.
|
||||
@ -97,7 +179,62 @@ $.Rect.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Provides a string representation of the retangle which is useful for
|
||||
* Rotates a rectangle around a point. Currently only 90, 180, and 270
|
||||
* degrees are supported.
|
||||
* @function
|
||||
* @param {Number} degrees The angle in degrees to rotate.
|
||||
* @param {OpenSeadragon.Point} pivot The point about which to rotate.
|
||||
* Defaults to the center of the rectangle.
|
||||
* @return {OpenSeadragon.Rect}
|
||||
*/
|
||||
rotate: function( degrees, pivot ) {
|
||||
// TODO support arbitrary rotation
|
||||
var width = this.width,
|
||||
height = this.height,
|
||||
newTopLeft;
|
||||
|
||||
degrees = ( degrees + 360 ) % 360;
|
||||
if( degrees % 90 !== 0 ) {
|
||||
throw new Error('Currently only 0, 90, 180, and 270 degrees are supported.');
|
||||
}
|
||||
|
||||
if( degrees === 0 ){
|
||||
return new $.Rect(
|
||||
this.x,
|
||||
this.y,
|
||||
this.width,
|
||||
this.height
|
||||
);
|
||||
}
|
||||
|
||||
pivot = pivot || this.getCenter();
|
||||
|
||||
switch ( degrees ) {
|
||||
case 90:
|
||||
newTopLeft = this.getBottomLeft();
|
||||
width = this.height;
|
||||
height = this.width;
|
||||
break;
|
||||
case 180:
|
||||
newTopLeft = this.getBottomRight();
|
||||
break;
|
||||
case 270:
|
||||
newTopLeft = this.getTopRight();
|
||||
width = this.height;
|
||||
height = this.width;
|
||||
break;
|
||||
default:
|
||||
newTopLeft = this.getTopLeft();
|
||||
break;
|
||||
}
|
||||
|
||||
newTopLeft = newTopLeft.rotate(degrees, pivot);
|
||||
|
||||
return new $.Rect(newTopLeft.x, newTopLeft.y, width, height);
|
||||
},
|
||||
|
||||
/**
|
||||
* Provides a string representation of the rectangle which is useful for
|
||||
* debugging.
|
||||
* @function
|
||||
* @returns {String} A string representation of the rectangle.
|
||||
|
@ -1,5 +1,38 @@
|
||||
/*
|
||||
* OpenSeadragon - ReferenceStrip
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
(function ( $ ) {
|
||||
|
||||
// dictionary from id to private properties
|
||||
var THIS = {};
|
||||
@ -23,21 +56,24 @@ var THIS = {};
|
||||
* require better abstraction at those points in order to effeciently
|
||||
* reuse those paradigms.
|
||||
*/
|
||||
$.ReferenceStrip = function( options ){
|
||||
/**
|
||||
* @class ReferenceStrip
|
||||
* @memberof OpenSeadragon
|
||||
* @param {Object} options
|
||||
*/
|
||||
$.ReferenceStrip = function ( options ) {
|
||||
|
||||
var _this = this,
|
||||
viewer = options.viewer,
|
||||
viewerSize = $.getElementSize( viewer.element ),
|
||||
miniViewer,
|
||||
minPixelRatio,
|
||||
element,
|
||||
style,
|
||||
i;
|
||||
|
||||
//We may need to create a new element and id if they did not
|
||||
//provide the id for the existing element
|
||||
if( !options.id ){
|
||||
options.id = 'referencestrip-' + (+new Date());
|
||||
if ( !options.id ) {
|
||||
options.id = 'referencestrip-' + $.now();
|
||||
this.element = $.makeNeutralElement( "div" );
|
||||
this.element.id = options.id;
|
||||
this.element.className = 'referencestrip';
|
||||
@ -57,17 +93,17 @@ $.ReferenceStrip = function( options ){
|
||||
mouseNavEnabled: false,
|
||||
showNavigationControl: false,
|
||||
showSequenceControl: false
|
||||
});
|
||||
} );
|
||||
|
||||
$.extend( this, options );
|
||||
//Private state properties
|
||||
THIS[ this.id ] = {
|
||||
"animating": false
|
||||
THIS[this.id] = {
|
||||
"animating": false
|
||||
};
|
||||
|
||||
this.minPixelRatio = this.viewer.minPixelRatio;
|
||||
|
||||
style = this.element.style;
|
||||
style = this.element.style;
|
||||
style.marginTop = '0px';
|
||||
style.marginRight = '0px';
|
||||
style.marginBottom = '0px';
|
||||
@ -81,56 +117,56 @@ $.ReferenceStrip = function( options ){
|
||||
$.setElementOpacity( this.element, 0.8 );
|
||||
|
||||
this.viewer = viewer;
|
||||
this.innerTracker = new $.MouseTracker({
|
||||
this.innerTracker = new $.MouseTracker( {
|
||||
element: this.element,
|
||||
dragHandler: $.delegate( this, onStripDrag ),
|
||||
scrollHandler: $.delegate( this, onStripScroll ),
|
||||
enterHandler: $.delegate( this, onStripEnter ),
|
||||
exitHandler: $.delegate( this, onStripExit ),
|
||||
keyHandler: $.delegate( this, onKeyPress )
|
||||
}).setTracking( true );
|
||||
} ).setTracking( true );
|
||||
|
||||
//Controls the position and orientation of the reference strip and sets the
|
||||
//appropriate width and height
|
||||
if( options.width && options.height ){
|
||||
if ( options.width && options.height ) {
|
||||
this.element.style.width = options.width + 'px';
|
||||
this.element.style.height = options.height + 'px';
|
||||
viewer.addControl(
|
||||
this.element,
|
||||
$.ControlAnchor.BOTTOM_LEFT
|
||||
{ anchor: $.ControlAnchor.BOTTOM_LEFT }
|
||||
);
|
||||
} else {
|
||||
if( "horizontal" == options.scroll ){
|
||||
if ( "horizontal" == options.scroll ) {
|
||||
this.element.style.width = (
|
||||
viewerSize.x *
|
||||
options.sizeRatio *
|
||||
viewer.tileSources.length
|
||||
) + ( 12 * viewer.tileSources.length ) + 'px';
|
||||
|
||||
this.element.style.height = (
|
||||
this.element.style.height = (
|
||||
viewerSize.y *
|
||||
options.sizeRatio
|
||||
) + 'px';
|
||||
|
||||
viewer.addControl(
|
||||
this.element,
|
||||
$.ControlAnchor.BOTTOM_LEFT
|
||||
{ anchor: $.ControlAnchor.BOTTOM_LEFT }
|
||||
);
|
||||
}else {
|
||||
} else {
|
||||
this.element.style.height = (
|
||||
viewerSize.y *
|
||||
options.sizeRatio *
|
||||
viewer.tileSources.length
|
||||
) + ( 12 * viewer.tileSources.length ) + 'px';
|
||||
|
||||
this.element.style.width = (
|
||||
this.element.style.width = (
|
||||
viewerSize.x *
|
||||
options.sizeRatio
|
||||
) + 'px';
|
||||
|
||||
viewer.addControl(
|
||||
this.element,
|
||||
$.ControlAnchor.TOP_LEFT
|
||||
{ anchor: $.ControlAnchor.TOP_LEFT }
|
||||
);
|
||||
|
||||
}
|
||||
@ -141,9 +177,9 @@ $.ReferenceStrip = function( options ){
|
||||
this.panels = [];
|
||||
|
||||
/*jshint loopfunc:true*/
|
||||
for( i = 0; i < viewer.tileSources.length; i++ ){
|
||||
for ( i = 0; i < viewer.tileSources.length; i++ ) {
|
||||
|
||||
element = $.makeNeutralElement('div');
|
||||
element = $.makeNeutralElement( 'div' );
|
||||
element.id = this.element.id + "-" + i;
|
||||
|
||||
element.style.width = _this.panelWidth + 'px';
|
||||
@ -154,27 +190,28 @@ $.ReferenceStrip = function( options ){
|
||||
element.style.styleFloat = 'left'; //IE
|
||||
element.style.padding = '2px';
|
||||
|
||||
element.innerTracker = new $.MouseTracker({
|
||||
element.innerTracker = new $.MouseTracker( {
|
||||
element: element,
|
||||
clickTimeThreshold: this.clickTimeThreshold,
|
||||
clickDistThreshold: this.clickDistThreshold,
|
||||
pressHandler: function( tracker ){
|
||||
tracker.dragging = +new Date();
|
||||
pressHandler: function ( event ) {
|
||||
event.eventSource.dragging = $.now();
|
||||
},
|
||||
releaseHandler: function( tracker, position, insideElementPress, insideElementRelease ){
|
||||
var id = tracker.element.id,
|
||||
page = Number( id.split( '-' )[ 2 ] ),
|
||||
now = +new Date();
|
||||
releaseHandler: function ( event ) {
|
||||
var tracker = event.eventSource,
|
||||
id = tracker.element.id,
|
||||
page = Number( id.split( '-' )[2] ),
|
||||
now = $.now();
|
||||
|
||||
if ( insideElementPress &&
|
||||
insideElementRelease &&
|
||||
if ( event.insideElementPressed &&
|
||||
event.insideElementReleased &&
|
||||
tracker.dragging &&
|
||||
( now - tracker.dragging ) < tracker.clickTimeThreshold ){
|
||||
( now - tracker.dragging ) < tracker.clickTimeThreshold ) {
|
||||
tracker.dragging = null;
|
||||
viewer.goToPage( page );
|
||||
}
|
||||
}
|
||||
}).setTracking( true );
|
||||
} ).setTracking( true );
|
||||
|
||||
this.element.appendChild( element );
|
||||
|
||||
@ -183,49 +220,52 @@ $.ReferenceStrip = function( options ){
|
||||
this.panels.push( element );
|
||||
|
||||
}
|
||||
loadPanels( this, this.scroll == 'vertical' ? viewerSize.y : viewerSize.y, 0);
|
||||
loadPanels( this, this.scroll == 'vertical' ? viewerSize.y : viewerSize.y, 0 );
|
||||
this.setFocus( 0 );
|
||||
|
||||
};
|
||||
|
||||
$.extend( $.ReferenceStrip.prototype, $.EventHandler.prototype, $.Viewer.prototype, {
|
||||
$.extend( $.ReferenceStrip.prototype, $.EventSource.prototype, $.Viewer.prototype, /** @lends OpenSeadragon.ReferenceStrip.prototype */{
|
||||
|
||||
setFocus: function( page ){
|
||||
var element = $.getElement( this.element.id + '-' + page ),
|
||||
viewerSize = $.getElementSize( this.viewer.canvas ),
|
||||
scrollWidth = Number(this.element.style.width.replace('px','')),
|
||||
scrollHeight = Number(this.element.style.height.replace('px','')),
|
||||
offsetLeft = -Number(this.element.style.marginLeft.replace('px','')),
|
||||
offsetTop = -Number(this.element.style.marginTop.replace('px','')),
|
||||
/**
|
||||
* @function
|
||||
*/
|
||||
setFocus: function ( page ) {
|
||||
var element = $.getElement( this.element.id + '-' + page ),
|
||||
viewerSize = $.getElementSize( this.viewer.canvas ),
|
||||
scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ),
|
||||
scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ),
|
||||
offsetLeft = -Number( this.element.style.marginLeft.replace( 'px', '' ) ),
|
||||
offsetTop = -Number( this.element.style.marginTop.replace( 'px', '' ) ),
|
||||
offset;
|
||||
|
||||
if ( this.currentSelected !== element ){
|
||||
if( this.currentSelected ){
|
||||
if ( this.currentSelected !== element ) {
|
||||
if ( this.currentSelected ) {
|
||||
this.currentSelected.style.background = '#000';
|
||||
}
|
||||
this.currentSelected = element;
|
||||
this.currentSelected.style.background = '#999';
|
||||
|
||||
if( 'horizontal' == this.scroll ){
|
||||
if ( 'horizontal' == this.scroll ) {
|
||||
//right left
|
||||
offset = (Number(page)) * ( this.panelWidth + 3 );
|
||||
if( offset > offsetLeft + viewerSize.x - this.panelWidth){
|
||||
offset = Math.min(offset, (scrollWidth - viewerSize.x));
|
||||
offset = ( Number( page ) ) * ( this.panelWidth + 3 );
|
||||
if ( offset > offsetLeft + viewerSize.x - this.panelWidth ) {
|
||||
offset = Math.min( offset, ( scrollWidth - viewerSize.x ) );
|
||||
this.element.style.marginLeft = -offset + 'px';
|
||||
loadPanels( this, viewerSize.x, -offset );
|
||||
}else if( offset < offsetLeft ){
|
||||
offset = Math.max(0, offset - viewerSize.x / 2);
|
||||
} else if ( offset < offsetLeft ) {
|
||||
offset = Math.max( 0, offset - viewerSize.x / 2 );
|
||||
this.element.style.marginLeft = -offset + 'px';
|
||||
loadPanels( this, viewerSize.x, -offset );
|
||||
}
|
||||
}else{
|
||||
offset = (Number(page) ) * ( this.panelHeight + 3 );
|
||||
if( offset > offsetTop + viewerSize.y - this.panelHeight){
|
||||
offset = Math.min(offset, (scrollHeight - viewerSize.y));
|
||||
} else {
|
||||
offset = ( Number( page ) ) * ( this.panelHeight + 3 );
|
||||
if ( offset > offsetTop + viewerSize.y - this.panelHeight ) {
|
||||
offset = Math.min( offset, ( scrollHeight - viewerSize.y ) );
|
||||
this.element.style.marginTop = -offset + 'px';
|
||||
loadPanels( this, viewerSize.y, -offset );
|
||||
}else if( offset < offsetTop ){
|
||||
offset = Math.max(0, offset - viewerSize.y / 2);
|
||||
} else if ( offset < offsetTop ) {
|
||||
offset = Math.max( 0, offset - viewerSize.y / 2 );
|
||||
this.element.style.marginTop = -offset + 'px';
|
||||
loadPanels( this, viewerSize.y, -offset );
|
||||
}
|
||||
@ -233,24 +273,22 @@ $.extend( $.ReferenceStrip.prototype, $.EventHandler.prototype, $.Viewer.prototy
|
||||
|
||||
this.currentPage = page;
|
||||
$.getElement( element.id + '-displayregion' ).focus();
|
||||
onStripEnter.call( this, this.innerTracker );
|
||||
onStripEnter.call( this, { eventSource: this.innerTracker } );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @name OpenSeadragon.ReferenceStrip.prototype.update
|
||||
*/
|
||||
update: function( viewport ){
|
||||
|
||||
if( THIS[ this.id ].animating ){
|
||||
$.console.log('image reference strip update');
|
||||
update: function () {
|
||||
if ( THIS[this.id].animating ) {
|
||||
$.console.log( 'image reference strip update' );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
} );
|
||||
|
||||
|
||||
|
||||
@ -260,41 +298,41 @@ $.extend( $.ReferenceStrip.prototype, $.EventHandler.prototype, $.Viewer.prototy
|
||||
* @inner
|
||||
* @function
|
||||
*/
|
||||
function onStripDrag( tracker, position, delta, shift ) {
|
||||
function onStripDrag( event ) {
|
||||
|
||||
var offsetLeft = Number(this.element.style.marginLeft.replace('px','')),
|
||||
offsetTop = Number(this.element.style.marginTop.replace('px','')),
|
||||
scrollWidth = Number(this.element.style.width.replace('px','')),
|
||||
scrollHeight = Number(this.element.style.height.replace('px','')),
|
||||
viewerSize = $.getElementSize( this.viewer.canvas );
|
||||
var offsetLeft = Number( this.element.style.marginLeft.replace( 'px', '' ) ),
|
||||
offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ),
|
||||
scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ),
|
||||
scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ),
|
||||
viewerSize = $.getElementSize( this.viewer.canvas );
|
||||
this.dragging = true;
|
||||
if ( this.element ) {
|
||||
if( 'horizontal' == this.scroll ){
|
||||
if ( -delta.x > 0 ) {
|
||||
if ( 'horizontal' == this.scroll ) {
|
||||
if ( -event.delta.x > 0 ) {
|
||||
//forward
|
||||
if( offsetLeft > -(scrollWidth - viewerSize.x)){
|
||||
this.element.style.marginLeft = ( offsetLeft + (delta.x * 2) ) + 'px';
|
||||
loadPanels( this, viewerSize.x, offsetLeft + (delta.x * 2) );
|
||||
if ( offsetLeft > -( scrollWidth - viewerSize.x ) ) {
|
||||
this.element.style.marginLeft = ( offsetLeft + ( event.delta.x * 2 ) ) + 'px';
|
||||
loadPanels( this, viewerSize.x, offsetLeft + ( event.delta.x * 2 ) );
|
||||
}
|
||||
} else if ( -delta.x < 0 ) {
|
||||
} else if ( -event.delta.x < 0 ) {
|
||||
//reverse
|
||||
if( offsetLeft < 0 ){
|
||||
this.element.style.marginLeft = ( offsetLeft + (delta.x * 2) ) + 'px';
|
||||
loadPanels( this, viewerSize.x, offsetLeft + (delta.x * 2) );
|
||||
if ( offsetLeft < 0 ) {
|
||||
this.element.style.marginLeft = ( offsetLeft + ( event.delta.x * 2 ) ) + 'px';
|
||||
loadPanels( this, viewerSize.x, offsetLeft + ( event.delta.x * 2 ) );
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if ( -delta.y > 0 ) {
|
||||
} else {
|
||||
if ( -event.delta.y > 0 ) {
|
||||
//forward
|
||||
if( offsetTop > -(scrollHeight - viewerSize.y)){
|
||||
this.element.style.marginTop = ( offsetTop + (delta.y * 2) ) + 'px';
|
||||
loadPanels( this, viewerSize.y, offsetTop + (delta.y * 2) );
|
||||
if ( offsetTop > -( scrollHeight - viewerSize.y ) ) {
|
||||
this.element.style.marginTop = ( offsetTop + ( event.delta.y * 2 ) ) + 'px';
|
||||
loadPanels( this, viewerSize.y, offsetTop + ( event.delta.y * 2 ) );
|
||||
}
|
||||
} else if ( -delta.y < 0 ) {
|
||||
} else if ( -event.delta.y < 0 ) {
|
||||
//reverse
|
||||
if( offsetTop < 0 ){
|
||||
this.element.style.marginTop = ( offsetTop + (delta.y * 2) ) + 'px';
|
||||
loadPanels( this, viewerSize.y, offsetTop + (delta.y * 2) );
|
||||
if ( offsetTop < 0 ) {
|
||||
this.element.style.marginTop = ( offsetTop + ( event.delta.y * 2 ) ) + 'px';
|
||||
loadPanels( this, viewerSize.y, offsetTop + ( event.delta.y * 2 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -310,39 +348,39 @@ function onStripDrag( tracker, position, delta, shift ) {
|
||||
* @inner
|
||||
* @function
|
||||
*/
|
||||
function onStripScroll( tracker, position, scroll, shift ) {
|
||||
var offsetLeft = Number(this.element.style.marginLeft.replace('px','')),
|
||||
offsetTop = Number(this.element.style.marginTop.replace('px','')),
|
||||
scrollWidth = Number(this.element.style.width.replace('px','')),
|
||||
scrollHeight = Number(this.element.style.height.replace('px','')),
|
||||
viewerSize = $.getElementSize( this.viewer.canvas );
|
||||
function onStripScroll( event ) {
|
||||
var offsetLeft = Number( this.element.style.marginLeft.replace( 'px', '' ) ),
|
||||
offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ),
|
||||
scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ),
|
||||
scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ),
|
||||
viewerSize = $.getElementSize( this.viewer.canvas );
|
||||
if ( this.element ) {
|
||||
if( 'horizontal' == this.scroll ){
|
||||
if ( scroll > 0 ) {
|
||||
if ( 'horizontal' == this.scroll ) {
|
||||
if ( event.scroll > 0 ) {
|
||||
//forward
|
||||
if( offsetLeft > -(scrollWidth - viewerSize.x)){
|
||||
this.element.style.marginLeft = ( offsetLeft - (scroll * 60) ) + 'px';
|
||||
loadPanels( this, viewerSize.x, offsetLeft - (scroll * 60) );
|
||||
if ( offsetLeft > -( scrollWidth - viewerSize.x ) ) {
|
||||
this.element.style.marginLeft = ( offsetLeft - ( event.scroll * 60 ) ) + 'px';
|
||||
loadPanels( this, viewerSize.x, offsetLeft - ( event.scroll * 60 ) );
|
||||
}
|
||||
} else if ( scroll < 0 ) {
|
||||
} else if ( event.scroll < 0 ) {
|
||||
//reverse
|
||||
if( offsetLeft < 0 ){
|
||||
this.element.style.marginLeft = ( offsetLeft - (scroll * 60) ) + 'px';
|
||||
loadPanels( this, viewerSize.x, offsetLeft - (scroll * 60) );
|
||||
if ( offsetLeft < 0 ) {
|
||||
this.element.style.marginLeft = ( offsetLeft - ( event.scroll * 60 ) ) + 'px';
|
||||
loadPanels( this, viewerSize.x, offsetLeft - ( event.scroll * 60 ) );
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if ( scroll < 0 ) {
|
||||
} else {
|
||||
if ( event.scroll < 0 ) {
|
||||
//scroll up
|
||||
if( offsetTop > viewerSize.y - scrollHeight ){
|
||||
this.element.style.marginTop = ( offsetTop + (scroll * 60) ) + 'px';
|
||||
loadPanels( this, viewerSize.y, offsetTop + (scroll * 60) );
|
||||
if ( offsetTop > viewerSize.y - scrollHeight ) {
|
||||
this.element.style.marginTop = ( offsetTop + ( event.scroll * 60 ) ) + 'px';
|
||||
loadPanels( this, viewerSize.y, offsetTop + ( event.scroll * 60 ) );
|
||||
}
|
||||
} else if ( scroll > 0 ) {
|
||||
} else if ( event.scroll > 0 ) {
|
||||
//scroll dowm
|
||||
if( offsetTop < 0 ){
|
||||
this.element.style.marginTop = ( offsetTop + (scroll * 60) ) + 'px';
|
||||
loadPanels( this, viewerSize.y, offsetTop + (scroll * 60) );
|
||||
if ( offsetTop < 0 ) {
|
||||
this.element.style.marginTop = ( offsetTop + ( event.scroll * 60 ) ) + 'px';
|
||||
loadPanels( this, viewerSize.y, offsetTop + ( event.scroll * 60 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -352,29 +390,30 @@ function onStripScroll( tracker, position, scroll, shift ) {
|
||||
}
|
||||
|
||||
|
||||
function loadPanels(strip, viewerSize, scroll){
|
||||
function loadPanels( strip, viewerSize, scroll ) {
|
||||
var panelSize,
|
||||
activePanelsStart,
|
||||
activePanelsEnd,
|
||||
miniViewer,
|
||||
style,
|
||||
i;
|
||||
if( 'horizontal' == strip.scroll ){
|
||||
i,
|
||||
element;
|
||||
if ( 'horizontal' == strip.scroll ) {
|
||||
panelSize = strip.panelWidth;
|
||||
}else{
|
||||
} else {
|
||||
panelSize = strip.panelHeight;
|
||||
}
|
||||
activePanelsStart = Math.ceil( viewerSize / panelSize ) + 5;
|
||||
activePanelsEnd = Math.ceil( (Math.abs(scroll) + viewerSize ) / panelSize ) + 1;
|
||||
activePanelsEnd = Math.ceil( ( Math.abs( scroll ) + viewerSize ) / panelSize ) + 1;
|
||||
activePanelsStart = activePanelsEnd - activePanelsStart;
|
||||
activePanelsStart = activePanelsStart < 0 ? 0 : activePanelsStart;
|
||||
|
||||
for( i = activePanelsStart; i < activePanelsEnd && i < strip.panels.length; i++ ){
|
||||
element = strip.panels[ i ];
|
||||
if ( !element.activePanel ){
|
||||
for ( i = activePanelsStart; i < activePanelsEnd && i < strip.panels.length; i++ ) {
|
||||
element = strip.panels[i];
|
||||
if ( !element.activePanel ) {
|
||||
miniViewer = new $.Viewer( {
|
||||
id: element.id,
|
||||
tileSources: [ strip.viewer.tileSources[ i ] ],
|
||||
tileSources: [strip.viewer.tileSources[i]],
|
||||
element: element,
|
||||
navigatorSizeRatio: strip.sizeRatio,
|
||||
showNavigator: false,
|
||||
@ -390,7 +429,7 @@ function loadPanels(strip, viewerSize, scroll){
|
||||
miniViewer.displayRegion.id = element.id + '-displayregion';
|
||||
miniViewer.displayRegion.className = 'displayregion';
|
||||
|
||||
style = miniViewer.displayRegion.style;
|
||||
style = miniViewer.displayRegion.style;
|
||||
style.position = 'relative';
|
||||
style.top = '0px';
|
||||
style.left = '0px';
|
||||
@ -404,11 +443,11 @@ function loadPanels(strip, viewerSize, scroll){
|
||||
style.width = ( strip.panelWidth - 4 ) + 'px';
|
||||
style.height = ( strip.panelHeight - 4 ) + 'px';
|
||||
|
||||
miniViewer.displayRegion.innerTracker = new $.MouseTracker({
|
||||
element: miniViewer.displayRegion
|
||||
});
|
||||
miniViewer.displayRegion.innerTracker = new $.MouseTracker( {
|
||||
element: miniViewer.displayRegion
|
||||
} );
|
||||
|
||||
element.getElementsByTagName('form')[ 0 ].appendChild(
|
||||
element.getElementsByTagName( 'div' )[0].appendChild(
|
||||
miniViewer.displayRegion
|
||||
);
|
||||
|
||||
@ -423,22 +462,23 @@ function loadPanels(strip, viewerSize, scroll){
|
||||
* @inner
|
||||
* @function
|
||||
*/
|
||||
function onStripEnter( tracker ) {
|
||||
function onStripEnter( event ) {
|
||||
var element = event.eventSource.element;
|
||||
|
||||
//$.setElementOpacity(tracker.element, 0.8);
|
||||
//$.setElementOpacity(element, 0.8);
|
||||
|
||||
//tracker.element.style.border = '1px solid #555';
|
||||
//tracker.element.style.background = '#000';
|
||||
//element.style.border = '1px solid #555';
|
||||
//element.style.background = '#000';
|
||||
|
||||
if( 'horizontal' == this.scroll ){
|
||||
if ( 'horizontal' == this.scroll ) {
|
||||
|
||||
//tracker.element.style.paddingTop = "0px";
|
||||
tracker.element.style.marginBottom = "0px";
|
||||
//element.style.paddingTop = "0px";
|
||||
element.style.marginBottom = "0px";
|
||||
|
||||
} else {
|
||||
|
||||
//tracker.element.style.paddingRight = "0px";
|
||||
tracker.element.style.marginLeft = "0px";
|
||||
//element.style.paddingRight = "0px";
|
||||
element.style.marginLeft = "0px";
|
||||
|
||||
}
|
||||
return false;
|
||||
@ -450,24 +490,18 @@ function onStripEnter( tracker ) {
|
||||
* @inner
|
||||
* @function
|
||||
*/
|
||||
function onStripExit( tracker ) {
|
||||
function onStripExit( event ) {
|
||||
var element = event.eventSource.element;
|
||||
|
||||
var viewerSize = $.getElementSize( this.viewer.element );
|
||||
if ( 'horizontal' == this.scroll ) {
|
||||
|
||||
//$.setElementOpacity(tracker.element, 0.4);
|
||||
//tracker.element.style.border = 'none';
|
||||
//tracker.element.style.background = '#fff';
|
||||
|
||||
|
||||
if( 'horizontal' == this.scroll ){
|
||||
|
||||
//tracker.element.style.paddingTop = "10px";
|
||||
tracker.element.style.marginBottom = "-" + ( $.getElementSize( tracker.element ).y / 2 ) + "px";
|
||||
//element.style.paddingTop = "10px";
|
||||
element.style.marginBottom = "-" + ( $.getElementSize( element ).y / 2 ) + "px";
|
||||
|
||||
} else {
|
||||
|
||||
//tracker.element.style.paddingRight = "10px";
|
||||
tracker.element.style.marginLeft = "-" + ( $.getElementSize( tracker.element ).x / 2 )+ "px";
|
||||
//element.style.paddingRight = "10px";
|
||||
element.style.marginLeft = "-" + ( $.getElementSize( element ).x / 2 ) + "px";
|
||||
|
||||
}
|
||||
return false;
|
||||
@ -480,41 +514,41 @@ function onStripExit( tracker ) {
|
||||
* @inner
|
||||
* @function
|
||||
*/
|
||||
function onKeyPress( tracker, keyCode, shiftKey ){
|
||||
//console.log( keyCode );
|
||||
function onKeyPress( event ) {
|
||||
//console.log( event.keyCode );
|
||||
|
||||
switch( keyCode ){
|
||||
case 61://=|+
|
||||
onStripScroll.call(this, this.tracker, null, 1, null);
|
||||
switch ( event.keyCode ) {
|
||||
case 61: //=|+
|
||||
onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } );
|
||||
return false;
|
||||
case 45://-|_
|
||||
onStripScroll.call(this, this.tracker, null, -1, null);
|
||||
case 45: //-|_
|
||||
onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } );
|
||||
return false;
|
||||
case 48://0|)
|
||||
case 119://w
|
||||
case 87://W
|
||||
case 38://up arrow
|
||||
onStripScroll.call(this, this.tracker, null, 1, null);
|
||||
case 48: //0|)
|
||||
case 119: //w
|
||||
case 87: //W
|
||||
case 38: //up arrow
|
||||
onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } );
|
||||
return false;
|
||||
case 115://s
|
||||
case 83://S
|
||||
case 40://down arrow
|
||||
onStripScroll.call(this, this.tracker, null, -1, null);
|
||||
case 115: //s
|
||||
case 83: //S
|
||||
case 40: //down arrow
|
||||
onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } );
|
||||
return false;
|
||||
case 97://a
|
||||
case 37://left arrow
|
||||
onStripScroll.call(this, this.tracker, null, -1, null);
|
||||
case 97: //a
|
||||
case 37: //left arrow
|
||||
onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: -1, shift: null } );
|
||||
return false;
|
||||
case 100://d
|
||||
case 39://right arrow
|
||||
onStripScroll.call(this, this.tracker, null, 1, null);
|
||||
case 100: //d
|
||||
case 39: //right arrow
|
||||
onStripScroll.call( this, { eventSource: this.tracker, position: null, scroll: 1, shift: null } );
|
||||
return false;
|
||||
default:
|
||||
//console.log( 'navigator keycode %s', keyCode );
|
||||
//console.log( 'navigator keycode %s', event.keyCode );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}( OpenSeadragon ));
|
||||
} ( OpenSeadragon ) );
|
||||
|
@ -1,20 +1,47 @@
|
||||
/*
|
||||
* OpenSeadragon - Spring
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @class Spring
|
||||
* @memberof OpenSeadragon
|
||||
* @param {Object} options - Spring configuration settings.
|
||||
* @param {Number} options.initial - Initial value of spring, default to 0 so
|
||||
* spring is not in motion initally by default.
|
||||
* @param {Number} options.springStiffness - Spring stiffness.
|
||||
* @param {Number} options.animationTime - Animation duration per spring.
|
||||
*
|
||||
* @property {Number} initial - Initial value of spring, default to 0 so
|
||||
* spring is not in motion initally by default.
|
||||
* @property {Number} springStiffness - Spring stiffness.
|
||||
* @property {Number} animationTime - Animation duration per spring.
|
||||
* @property {Object} current
|
||||
* @property {Number} start
|
||||
* @property {Number} target
|
||||
*/
|
||||
$.Spring = function( options ) {
|
||||
var args = arguments;
|
||||
@ -26,9 +53,19 @@ $.Spring = function( options ) {
|
||||
initial: args.length && typeof ( args[ 0 ] ) == "number" ?
|
||||
args[ 0 ] :
|
||||
0,
|
||||
/**
|
||||
* Spring stiffness.
|
||||
* @member {Number} springStiffness
|
||||
* @memberof OpenSeadragon.Spring#
|
||||
*/
|
||||
springStiffness: args.length > 1 ?
|
||||
args[ 1 ].springStiffness :
|
||||
5.0,
|
||||
/**
|
||||
* Animation duration per spring.
|
||||
* @member {Number} animationTime
|
||||
* @memberof OpenSeadragon.Spring#
|
||||
*/
|
||||
animationTime: args.length > 1 ?
|
||||
args[ 1 ].animationTime :
|
||||
1.5
|
||||
@ -37,26 +74,43 @@ $.Spring = function( options ) {
|
||||
|
||||
$.extend( true, this, options);
|
||||
|
||||
|
||||
/**
|
||||
* @member {Object} current
|
||||
* @memberof OpenSeadragon.Spring#
|
||||
* @property {Number} value
|
||||
* @property {Number} time
|
||||
*/
|
||||
this.current = {
|
||||
value: typeof ( this.initial ) == "number" ?
|
||||
this.initial :
|
||||
0,
|
||||
time: new Date().getTime() // always work in milliseconds
|
||||
time: $.now() // always work in milliseconds
|
||||
};
|
||||
|
||||
/**
|
||||
* @member {Object} start
|
||||
* @memberof OpenSeadragon.Spring#
|
||||
* @property {Number} value
|
||||
* @property {Number} time
|
||||
*/
|
||||
this.start = {
|
||||
value: this.current.value,
|
||||
time: this.current.time
|
||||
};
|
||||
|
||||
/**
|
||||
* @member {Object} target
|
||||
* @memberof OpenSeadragon.Spring#
|
||||
* @property {Number} value
|
||||
* @property {Number} time
|
||||
*/
|
||||
this.target = {
|
||||
value: this.current.value,
|
||||
time: this.current.time
|
||||
};
|
||||
};
|
||||
|
||||
$.Spring.prototype = {
|
||||
$.Spring.prototype = /** @lends OpenSeadragon.Spring.prototype */{
|
||||
|
||||
/**
|
||||
* @function
|
||||
@ -93,7 +147,7 @@ $.Spring.prototype = {
|
||||
* @function
|
||||
*/
|
||||
update: function() {
|
||||
this.current.time = new Date().getTime();
|
||||
this.current.time = $.now();
|
||||
this.current.value = (this.current.time >= this.target.time) ?
|
||||
this.target.value :
|
||||
this.start.value +
|
||||
|
@ -1,3 +1,36 @@
|
||||
/*
|
||||
* OpenSeadragon - getString/setString
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
@ -6,21 +39,14 @@
|
||||
// pythons gettext might be a reasonable approach.
|
||||
var I18N = {
|
||||
Errors: {
|
||||
Failure: "Sorry, but Seadragon Ajax can't run on your browser!\n" +
|
||||
"Please try using IE 7 or Firefox 3.\n",
|
||||
Dzc: "Sorry, we don't support Deep Zoom Collections!",
|
||||
Dzi: "Hmm, this doesn't appear to be a valid Deep Zoom Image.",
|
||||
Xml: "Hmm, this doesn't appear to be a valid Deep Zoom Image.",
|
||||
Empty: "You asked us to open nothing, so we did just that.",
|
||||
ImageFormat: "Sorry, we don't support {0}-based Deep Zoom Images.",
|
||||
Security: "It looks like a security restriction stopped us from " +
|
||||
"loading this Deep Zoom Image.",
|
||||
Status: "This space unintentionally left blank ({0} {1}).",
|
||||
Unknown: "Whoops, something inexplicably went wrong. Sorry!"
|
||||
},
|
||||
|
||||
Messages: {
|
||||
Loading: "Loading..."
|
||||
OpenFailed: "Unable to open {0}: {1}"
|
||||
},
|
||||
|
||||
Tooltips: {
|
||||
@ -29,15 +55,16 @@ var I18N = {
|
||||
ZoomIn: "Zoom in",
|
||||
ZoomOut: "Zoom out",
|
||||
NextPage: "Next page",
|
||||
PreviousPage: "Previous page"
|
||||
PreviousPage: "Previous page",
|
||||
RotateLeft: "Rotate left",
|
||||
RotateRight: "Rotate right"
|
||||
}
|
||||
};
|
||||
|
||||
$.extend( $, {
|
||||
$.extend( $, /** @lends OpenSeadragon */{
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @name OpenSeadragon.getString
|
||||
* @param {String} property
|
||||
*/
|
||||
getString: function( prop ) {
|
||||
@ -55,7 +82,8 @@ $.extend( $, {
|
||||
string = container[ props[ i ] ];
|
||||
|
||||
if ( typeof( string ) != "string" ) {
|
||||
string = "";
|
||||
$.console.debug( "Untranslated source string:", prop );
|
||||
string = ""; // FIXME: this breaks gettext()-style convention, which would return source
|
||||
}
|
||||
|
||||
return string.replace(/\{\d+\}/g, function(capture) {
|
||||
@ -68,14 +96,13 @@ $.extend( $, {
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @name OpenSeadragon.setString
|
||||
* @param {String} property
|
||||
* @param {*} value
|
||||
*/
|
||||
setString: function( prop, value ) {
|
||||
|
||||
var props = prop.split('.'),
|
||||
container = $.Strings,
|
||||
container = I18N,
|
||||
i;
|
||||
|
||||
for ( i = 0; i < props.length - 1; i++ ) {
|
||||
|
228
src/tile.js
@ -1,7 +1,42 @@
|
||||
/*
|
||||
* OpenSeadragon - Tile
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
var TILE_CACHE = {};
|
||||
/**
|
||||
* @class
|
||||
* @class Tile
|
||||
* @memberof OpenSeadragon
|
||||
* @param {Number} level The zoom level this tile belongs to.
|
||||
* @param {Number} x The vector component 'x'.
|
||||
* @param {Number} y The vector component 'y'.
|
||||
@ -10,55 +45,134 @@
|
||||
* @param {Boolean} exists Is this tile a part of a sparse image? ( Also has
|
||||
* this tile failed to load? )
|
||||
* @param {String} url The URL of this tile's image.
|
||||
*
|
||||
* @property {Number} level The zoom level this tile belongs to.
|
||||
* @property {Number} x The vector component 'x'.
|
||||
* @property {Number} y The vector component 'y'.
|
||||
* @property {OpenSeadragon.Point} bounds Where this tile fits, in normalized
|
||||
* coordinates
|
||||
* @property {Boolean} exists Is this tile a part of a sparse image? ( Also has
|
||||
* this tile failed to load?
|
||||
* @property {String} url The URL of this tile's image.
|
||||
* @property {Boolean} loaded Is this tile loaded?
|
||||
* @property {Boolean} loading Is this tile loading
|
||||
* @property {Element} element The HTML element for this tile
|
||||
* @property {Image} image The Image object for this tile
|
||||
* @property {String} style The alias of this.element.style.
|
||||
* @property {String} position This tile's position on screen, in pixels.
|
||||
* @property {String} size This tile's size on screen, in pixels
|
||||
* @property {String} blendStart The start time of this tile's blending
|
||||
* @property {String} opacity The current opacity this tile should be.
|
||||
* @property {String} distance The distance of this tile to the viewport center
|
||||
* @property {String} visibility The visibility score of this tile.
|
||||
* @property {Boolean} beingDrawn Whether this tile is currently being drawn
|
||||
* @property {Number} lastTouchTime Timestamp the tile was last touched.
|
||||
*/
|
||||
$.Tile = function(level, x, y, bounds, exists, url) {
|
||||
/**
|
||||
* The zoom level this tile belongs to.
|
||||
* @member {Number} level
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.level = level;
|
||||
/**
|
||||
* The vector component 'x'.
|
||||
* @member {Number} x
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.x = x;
|
||||
/**
|
||||
* The vector component 'y'.
|
||||
* @member {Number} y
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.y = y;
|
||||
/**
|
||||
* Where this tile fits, in normalized coordinates
|
||||
* @member {OpenSeadragon.Point} bounds
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.bounds = bounds;
|
||||
/**
|
||||
* Is this tile a part of a sparse image? Also has this tile failed to load?
|
||||
* @member {Boolean} exists
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.exists = exists;
|
||||
/**
|
||||
* The URL of this tile's image.
|
||||
* @member {String} url
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.url = url;
|
||||
/**
|
||||
* Is this tile loaded?
|
||||
* @member {Boolean} loaded
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.loaded = false;
|
||||
/**
|
||||
* Is this tile loading?
|
||||
* @member {Boolean} loading
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.loading = false;
|
||||
|
||||
/**
|
||||
* The HTML div element for this tile
|
||||
* @member {Element} element
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.element = null;
|
||||
/**
|
||||
* The HTML img element for this tile.
|
||||
* @member {Element} imgElement
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.imgElement = null;
|
||||
/**
|
||||
* The Image object for this tile.
|
||||
* @member {Object} image
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.image = null;
|
||||
|
||||
/**
|
||||
* The alias of this.element.style.
|
||||
* @member {String} style
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.style = null;
|
||||
/**
|
||||
* This tile's position on screen, in pixels.
|
||||
* @member {OpenSeadragon.Point} position
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.position = null;
|
||||
/**
|
||||
* This tile's size on screen, in pixels.
|
||||
* @member {OpenSeadragon.Point} size
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.size = null;
|
||||
/**
|
||||
* The start time of this tile's blending.
|
||||
* @member {Number} blendStart
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.blendStart = null;
|
||||
/**
|
||||
* The current opacity this tile should be.
|
||||
* @member {Number} opacity
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.opacity = null;
|
||||
/**
|
||||
* The distance of this tile to the viewport center.
|
||||
* @member {Number} distance
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.distance = null;
|
||||
/**
|
||||
* The visibility score of this tile.
|
||||
* @member {Number} visibility
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.visibility = null;
|
||||
|
||||
/**
|
||||
* Whether this tile is currently being drawn.
|
||||
* @member {Boolean} beingDrawn
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.beingDrawn = false;
|
||||
/**
|
||||
* Timestamp the tile was last touched.
|
||||
* @member {Number} lastTouchTime
|
||||
* @memberof OpenSeadragon.Tile#
|
||||
*/
|
||||
this.lastTouchTime = 0;
|
||||
};
|
||||
|
||||
$.Tile.prototype = {
|
||||
$.Tile.prototype = /** @lends OpenSeadragon.Tile.prototype */{
|
||||
|
||||
/**
|
||||
* Provides a string representation of this tiles level and (x,y)
|
||||
@ -76,9 +190,6 @@ $.Tile.prototype = {
|
||||
* @param {Element} container
|
||||
*/
|
||||
drawHTML: function( container ) {
|
||||
|
||||
var containerSize = $.getElementSize( container );
|
||||
|
||||
if ( !this.loaded || !this.image ) {
|
||||
$.console.warn(
|
||||
"Attempting to draw tile %s when it's not yet loaded.",
|
||||
@ -87,33 +198,16 @@ $.Tile.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
/* EXISTING IMPLEMENTATION
|
||||
if ( !this.element ) {
|
||||
this.element = $.makeNeutralElement("img");
|
||||
this.element.src = this.url;
|
||||
|
||||
this.style = this.element.style;
|
||||
this.style.position = "absolute";
|
||||
this.style.msInterpolationMode = "nearest-neighbor";
|
||||
}
|
||||
|
||||
if ( this.element.parentNode != container ) {
|
||||
container.appendChild( this.element );
|
||||
}
|
||||
|
||||
this.style.top = position.y + "px";
|
||||
this.style.left = position.x + "px";
|
||||
this.style.height = size.y + "px";
|
||||
this.style.width = size.x + "px";
|
||||
*/
|
||||
|
||||
//EXPERIMENTAL - trying to figure out how to scale the container
|
||||
// content during animation of the container size.
|
||||
|
||||
if ( !this.element ) {
|
||||
this.element = $.makeNeutralElement("img");
|
||||
this.element.src = this.url;
|
||||
this.element.style.msInterpolationMode = "nearest-neighbor";
|
||||
this.element = $.makeNeutralElement( "div" );
|
||||
this.imgElement = $.makeNeutralElement( "img" );
|
||||
this.imgElement.src = this.url;
|
||||
this.imgElement.style.msInterpolationMode = "nearest-neighbor";
|
||||
this.imgElement.style.width = "100%";
|
||||
this.imgElement.style.height = "100%";
|
||||
|
||||
this.style = this.element.style;
|
||||
this.style.position = "absolute";
|
||||
@ -121,23 +215,26 @@ $.Tile.prototype = {
|
||||
if ( this.element.parentNode != container ) {
|
||||
container.appendChild( this.element );
|
||||
}
|
||||
if ( this.imgElement.parentNode != this.element ) {
|
||||
this.element.appendChild( this.imgElement );
|
||||
}
|
||||
|
||||
this.style.top = 100 * ( this.position.y / containerSize.y ) + "%";
|
||||
this.style.left = 100 * ( this.position.x / containerSize.x ) + "%";
|
||||
this.style.height = 100 * ( this.size.y / containerSize.y ) + "%";
|
||||
this.style.width = 100 * ( this.size.x / containerSize.x ) + "%";
|
||||
this.style.top = this.position.y + "px";
|
||||
this.style.left = this.position.x + "px";
|
||||
this.style.height = this.size.y + "px";
|
||||
this.style.width = this.size.x + "px";
|
||||
|
||||
$.setElementOpacity( this.element, this.opacity );
|
||||
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Renders the tile in a canvas-based context.
|
||||
* @function
|
||||
* @param {Canvas} context
|
||||
* @param {Function} method for firing the drawing event. drawingHandler({context, tile, rendered})
|
||||
* where <code>rendered</code> is the context with the pre-drawn image.
|
||||
*/
|
||||
drawCanvas: function( context ) {
|
||||
drawCanvas: function( context, drawingHandler ) {
|
||||
|
||||
var position = this.position,
|
||||
size = this.size,
|
||||
@ -185,6 +282,9 @@ $.Tile.prototype = {
|
||||
|
||||
rendered = TILE_CACHE[ this.url ];
|
||||
|
||||
// This gives the application a chance to make image manipulation changes as we are rendering the image
|
||||
drawingHandler({context: context, tile: this, rendered: rendered});
|
||||
|
||||
//rendered.save();
|
||||
context.drawImage(
|
||||
rendered.canvas,
|
||||
@ -203,10 +303,13 @@ $.Tile.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes tile from it's contianer.
|
||||
* Removes tile from its container.
|
||||
* @function
|
||||
*/
|
||||
unload: function() {
|
||||
if ( this.imgElement && this.imgElement.parentNode ) {
|
||||
this.imgElement.parentNode.removeChild( this.imgElement );
|
||||
}
|
||||
if ( this.element && this.element.parentNode ) {
|
||||
this.element.parentNode.removeChild( this.element );
|
||||
}
|
||||
@ -214,10 +317,11 @@ $.Tile.prototype = {
|
||||
delete TILE_CACHE[ this.url ];
|
||||
}
|
||||
|
||||
this.element = null;
|
||||
this.image = null;
|
||||
this.loaded = false;
|
||||
this.loading = false;
|
||||
this.element = null;
|
||||
this.imgElement = null;
|
||||
this.image = null;
|
||||
this.loaded = false;
|
||||
this.loading = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,8 +1,43 @@
|
||||
/*
|
||||
* OpenSeadragon - TileSource
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
|
||||
/**
|
||||
* The TileSource contains the most basic implementation required to create a
|
||||
* @class TileSource
|
||||
* @classdesc The TileSource contains the most basic implementation required to create a
|
||||
* smooth transition between layer in an image pyramid. It has only a single key
|
||||
* interface that must be implemented to complete it key functionality:
|
||||
* 'getTileUrl'. It also has several optional interfaces that can be
|
||||
@ -14,12 +49,13 @@
|
||||
* By default the image pyramid is split into N layers where the images longest
|
||||
* side in M (in pixels), where N is the smallest integer which satisfies
|
||||
* <strong>2^(N+1) >= M</strong>.
|
||||
* @class
|
||||
* @extends OpenSeadragon.EventHandler
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
* @extends OpenSeadragon.EventSource
|
||||
* @param {Number|Object|Array|String} width
|
||||
* If more than a single argument is supplied, the traditional use of
|
||||
* positional parameters is supplied and width is expected to be the width
|
||||
* source image at it's max resolution in pixels. If a single argument is supplied and
|
||||
* source image at its max resolution in pixels. If a single argument is supplied and
|
||||
* it is an Object or Array, the construction is assumed to occur through
|
||||
* the extending classes implementation of 'configure'. Finally if only a
|
||||
* single argument is supplied and it is a String, the extending class is
|
||||
@ -36,23 +72,9 @@
|
||||
* The minimum level to attempt to load.
|
||||
* @param {Number} maxLevel
|
||||
* The maximum level to attempt to load.
|
||||
* @property {Number} aspectRatio
|
||||
* Ratio of width to height
|
||||
* @property {OpenSeadragon.Point} dimensions
|
||||
* Vector storing x and y dimensions ( width and height respectively ).
|
||||
* @property {Number} tileSize
|
||||
* The size of the image tiles used to compose the image.
|
||||
* @property {Number} tileOverlap
|
||||
* The overlap in pixels each tile shares with it's adjacent neighbors.
|
||||
* @property {Number} minLevel
|
||||
* The minimum pyramid level this tile source supports or should attempt to load.
|
||||
* @property {Number} maxLevel
|
||||
* The maximum pyramid level this tile source supports or should attempt to load.
|
||||
*/
|
||||
$.TileSource = function( width, height, tileSize, tileOverlap, minLevel, maxLevel ) {
|
||||
var _this = this,
|
||||
callback = null,
|
||||
readyHandler = null,
|
||||
var callback = null,
|
||||
args = arguments,
|
||||
options,
|
||||
i;
|
||||
@ -71,8 +93,8 @@ $.TileSource = function( width, height, tileSize, tileOverlap, minLevel, maxLeve
|
||||
}
|
||||
|
||||
//Tile sources supply some events, namely 'ready' when they must be configured
|
||||
//by asyncronously fetching their configuration data.
|
||||
$.EventHandler.call( this );
|
||||
//by asynchronously fetching their configuration data.
|
||||
$.EventSource.call( this );
|
||||
|
||||
//we allow options to override anything we dont treat as
|
||||
//required via idiomatic options or which is functionally
|
||||
@ -82,17 +104,53 @@ $.TileSource = function( width, height, tileSize, tileOverlap, minLevel, maxLeve
|
||||
|
||||
//Any functions that are passed as arguments are bound to the ready callback
|
||||
/*jshint loopfunc:true*/
|
||||
for( i = 0; i < arguments.length; i++ ){
|
||||
if( $.isFunction( arguments[i] ) ){
|
||||
for ( i = 0; i < arguments.length; i++ ) {
|
||||
if ( $.isFunction( arguments[ i ] ) ) {
|
||||
callback = arguments[ i ];
|
||||
this.addHandler( 'ready', function( placeHolderSource, readySource ){
|
||||
callback( readySource );
|
||||
});
|
||||
this.addHandler( 'ready', function ( event ) {
|
||||
callback( event );
|
||||
} );
|
||||
//only one callback per constructor
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ratio of width to height
|
||||
* @member {Number} aspectRatio
|
||||
* @memberof OpenSeadragon.TileSource#
|
||||
*/
|
||||
/**
|
||||
* Vector storing x and y dimensions ( width and height respectively ).
|
||||
* @member {OpenSeadragon.Point} dimensions
|
||||
* @memberof OpenSeadragon.TileSource#
|
||||
*/
|
||||
/**
|
||||
* The size of the image tiles used to compose the image.
|
||||
* @member {Number} tileSize
|
||||
* @memberof OpenSeadragon.TileSource#
|
||||
*/
|
||||
/**
|
||||
* The overlap in pixels each tile shares with its adjacent neighbors.
|
||||
* @member {Number} tileOverlap
|
||||
* @memberof OpenSeadragon.TileSource#
|
||||
*/
|
||||
/**
|
||||
* The minimum pyramid level this tile source supports or should attempt to load.
|
||||
* @member {Number} minLevel
|
||||
* @memberof OpenSeadragon.TileSource#
|
||||
*/
|
||||
/**
|
||||
* The maximum pyramid level this tile source supports or should attempt to load.
|
||||
* @member {Number} maxLevel
|
||||
* @memberof OpenSeadragon.TileSource#
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* @member {Boolean} ready
|
||||
* @memberof OpenSeadragon.TileSource#
|
||||
*/
|
||||
|
||||
if( 'string' == $.type( arguments[ 0 ] ) ){
|
||||
//in case the getImageInfo method is overriden and/or implies an
|
||||
//async mechanism set some safe defaults first
|
||||
@ -134,7 +192,7 @@ $.TileSource = function( width, height, tileSize, tileOverlap, minLevel, maxLeve
|
||||
};
|
||||
|
||||
|
||||
$.TileSource.prototype = {
|
||||
$.TileSource.prototype = /** @lends OpenSeadragon.TileSource.prototype */{
|
||||
|
||||
/**
|
||||
* @function
|
||||
@ -240,16 +298,14 @@ $.TileSource.prototype = {
|
||||
* @throws {Error}
|
||||
*/
|
||||
getImageInfo: function( url ) {
|
||||
var _this = this,
|
||||
error,
|
||||
var _this = this,
|
||||
callbackName,
|
||||
callback,
|
||||
readySource,
|
||||
options,
|
||||
urlParts,
|
||||
filename,
|
||||
lastDot,
|
||||
tilesUrl;
|
||||
lastDot;
|
||||
|
||||
|
||||
if( url ) {
|
||||
@ -262,11 +318,40 @@ $.TileSource.prototype = {
|
||||
}
|
||||
|
||||
callback = function( data ){
|
||||
if( typeof(data) === "string" ) {
|
||||
data = $.parseXml( data );
|
||||
}
|
||||
var $TileSource = $.TileSource.determineType( _this, data, url );
|
||||
if ( !$TileSource ) {
|
||||
/**
|
||||
* Raised when an error occurs loading a TileSource.
|
||||
*
|
||||
* @event open-failed
|
||||
* @memberof OpenSeadragon.TileSource
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.TileSource} eventSource - A reference to the TileSource which raised the event.
|
||||
* @property {String} message
|
||||
* @property {String} source
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( 'open-failed', { message: "Unable to load TileSource", source: url } );
|
||||
return;
|
||||
}
|
||||
|
||||
options = $TileSource.prototype.configure.apply( _this, [ data, url ]);
|
||||
readySource = new $TileSource( options );
|
||||
_this.ready = true;
|
||||
_this.raiseEvent( 'ready', readySource );
|
||||
/**
|
||||
* Raised when a TileSource is opened and initialized.
|
||||
*
|
||||
* @event ready
|
||||
* @memberof OpenSeadragon.TileSource
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.TileSource} eventSource - A reference to the TileSource which raised the event.
|
||||
* @property {Object} tileSource
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( 'ready', { tileSource: readySource } );
|
||||
};
|
||||
|
||||
if( url.match(/\.js$/) ){
|
||||
@ -281,10 +366,46 @@ $.TileSource.prototype = {
|
||||
callback: callback
|
||||
});
|
||||
} else {
|
||||
// request info via xhr asyncronously.
|
||||
// request info via xhr asynchronously.
|
||||
$.makeAjaxRequest( url, function( xhr ) {
|
||||
var data = processResponse( xhr );
|
||||
callback( data );
|
||||
}, function ( xhr, exc ) {
|
||||
var msg;
|
||||
|
||||
/*
|
||||
IE < 10 will block XHR requests to different origins. Any property access on the request
|
||||
object will raise an exception which we'll attempt to handle by formatting the original
|
||||
exception rather than the second one raised when we try to access xhr.status
|
||||
*/
|
||||
try {
|
||||
msg = "HTTP " + xhr.status + " attempting to load TileSource";
|
||||
} catch ( e ) {
|
||||
var formattedExc;
|
||||
if ( typeof( exc ) == "undefined" || !exc.toString ) {
|
||||
formattedExc = "Unknown error";
|
||||
} else {
|
||||
formattedExc = exc.toString();
|
||||
}
|
||||
|
||||
msg = formattedExc + " attempting to load TileSource";
|
||||
}
|
||||
|
||||
/***
|
||||
* Raised when an error occurs loading a TileSource.
|
||||
*
|
||||
* @event open-failed
|
||||
* @memberof OpenSeadragon.TileSource
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.TileSource} eventSource - A reference to the TileSource which raised the event.
|
||||
* @property {String} message
|
||||
* @property {String} source
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( 'open-failed', {
|
||||
message: msg,
|
||||
source: url
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -362,13 +483,13 @@ $.TileSource.prototype = {
|
||||
};
|
||||
|
||||
|
||||
$.extend( true, $.TileSource.prototype, $.EventHandler.prototype );
|
||||
$.extend( true, $.TileSource.prototype, $.EventSource.prototype );
|
||||
|
||||
|
||||
/**
|
||||
* Decides whether to try to process the response as xml, json, or hand back
|
||||
* the text
|
||||
* @eprivate
|
||||
* @private
|
||||
* @inner
|
||||
* @function
|
||||
* @param {XMLHttpRequest} xhr - the completed network request
|
||||
@ -410,7 +531,7 @@ function processResponse( xhr ){
|
||||
/**
|
||||
* Determines the TileSource Implementation by introspection of OpenSeadragon
|
||||
* namespace, calling each TileSource implementation of 'isType'
|
||||
* @eprivate
|
||||
* @private
|
||||
* @inner
|
||||
* @function
|
||||
* @param {Object|Array|Document} data - the tile source configuration object
|
||||
@ -428,6 +549,8 @@ $.TileSource.determineType = function( tileSource, data, url ){
|
||||
return OpenSeadragon[ property ];
|
||||
}
|
||||
}
|
||||
|
||||
$.console.error( "No TileSource was able to open %s %s", url, data );
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,11 +1,46 @@
|
||||
/*
|
||||
* OpenSeadragon - TileSourceCollection
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @class TileSourceCollection
|
||||
* @memberof OpenSeadragon
|
||||
* @extends OpenSeadragon.TileSource
|
||||
*/
|
||||
$.TileSourceCollection = function( tileSize, tileSources, rows, layout ) {
|
||||
|
||||
var options;
|
||||
|
||||
if( $.isPlainObject( tileSize ) ){
|
||||
options = tileSize;
|
||||
@ -58,11 +93,10 @@ $.TileSourceCollection = function( tileSize, tileSources, rows, layout ) {
|
||||
|
||||
};
|
||||
|
||||
$.extend( $.TileSourceCollection.prototype, $.TileSource.prototype, {
|
||||
$.extend( $.TileSourceCollection.prototype, $.TileSource.prototype, /** @lends OpenSeadragon.TileSourceCollection.prototype */{
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @name OpenSeadragon.TileSourceCollection.prototype.getTileBounds
|
||||
* @param {Number} level
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
@ -84,7 +118,6 @@ $.extend( $.TileSourceCollection.prototype, $.TileSource.prototype, {
|
||||
/**
|
||||
*
|
||||
* @function
|
||||
* @name OpenSeadragon.TileSourceCollection.prototype.configure
|
||||
*/
|
||||
configure: function( data, url ){
|
||||
return;
|
||||
@ -93,7 +126,6 @@ $.extend( $.TileSourceCollection.prototype, $.TileSource.prototype, {
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @name OpenSeadragon.TileSourceCollection.prototype.getTileUrl
|
||||
* @param {Number} level
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
|
@ -1,12 +1,54 @@
|
||||
/*
|
||||
* OpenSeadragon - TmsTileSource
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Derived from the TMS tile source in Rainer Simon's seajax-utils project
|
||||
* <http://github.com/rsimon/seajax-utils>. Rainer Simon has contributed
|
||||
* the included code to the OpenSeadragon project under the New BSD license;
|
||||
* see <https://github.com/openseadragon/openseadragon/issues/58>.
|
||||
*/
|
||||
|
||||
|
||||
(function( $ ){
|
||||
|
||||
/**
|
||||
* A tilesource implementation for Tiled Map Services (TMS). Adopted from Rainer Simon
|
||||
* project http://github.com/rsimon/seajax-utils. TMS tile
|
||||
* scheme ( [ as supported by OpenLayers ] is described here
|
||||
* ( http://openlayers.org/dev/examples/tms.html ) )
|
||||
* @class TmsTileSource
|
||||
* @classdesc A tilesource implementation for Tiled Map Services (TMS).
|
||||
* TMS tile scheme ( [ as supported by OpenLayers ] is described here
|
||||
* ( http://openlayers.org/dev/examples/tms.html ).
|
||||
*
|
||||
* @class
|
||||
* @memberof OpenSeadragon
|
||||
* @extends OpenSeadragon.TileSource
|
||||
* @param {Number|Object} width - the pixel width of the image or the idiomatic
|
||||
* options object which is used instead of positional arguments.
|
||||
@ -50,14 +92,13 @@ $.TmsTileSource = function( width, height, tileSize, tileOverlap, tilesUrl ) {
|
||||
|
||||
};
|
||||
|
||||
$.extend( $.TmsTileSource.prototype, $.TileSource.prototype, {
|
||||
$.extend( $.TmsTileSource.prototype, $.TileSource.prototype, /** @lends OpenSeadragon.TmsTileSource.prototype */{
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the data and/or url imply the image service is supported by
|
||||
* this tile source.
|
||||
* @function
|
||||
* @name OpenSeadragon.TmsTileSource.prototype.supports
|
||||
* @param {Object|Array} data
|
||||
* @param {String} optional - url
|
||||
*/
|
||||
@ -68,7 +109,6 @@ $.extend( $.TmsTileSource.prototype, $.TileSource.prototype, {
|
||||
/**
|
||||
*
|
||||
* @function
|
||||
* @name OpenSeadragon.TmsTileSource.prototype.configure
|
||||
* @param {Object} data - the raw configuration
|
||||
* @param {String} url - the url the data was retreived from if any.
|
||||
* @return {Object} options - A dictionary of keyword arguments sufficient
|
||||
@ -81,7 +121,6 @@ $.extend( $.TmsTileSource.prototype, $.TileSource.prototype, {
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @name OpenSeadragon.TmsTileSource.prototype.getTileUrl
|
||||
* @param {Number} level
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
|
2191
src/viewer.js
416
src/viewport.js
@ -1,8 +1,46 @@
|
||||
/*
|
||||
* OpenSeadragon - Viewport
|
||||
*
|
||||
* Copyright (C) 2009 CodePlex Foundation
|
||||
* Copyright (C) 2010-2013 OpenSeadragon contributors
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* 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.
|
||||
*/
|
||||
|
||||
(function( $ ){
|
||||
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @class Viewport
|
||||
* @classdesc Handles coordinate-related functionality (zoom, pan, rotation, etc.) for an {@link OpenSeadragon.Viewer}.
|
||||
* A new instance is created for each TileSource opened (see {@link OpenSeadragon.Viewer#viewport}).
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
*/
|
||||
$.Viewport = function( options ) {
|
||||
|
||||
@ -19,7 +57,7 @@ $.Viewport = function( options ) {
|
||||
|
||||
//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
|
||||
//being passed directly on the options object
|
||||
if ( options.config ){
|
||||
$.extend( true, options, options.config );
|
||||
delete options.config;
|
||||
@ -45,7 +83,8 @@ $.Viewport = function( options ) {
|
||||
wrapVertical: $.DEFAULT_SETTINGS.wrapVertical,
|
||||
defaultZoomLevel: $.DEFAULT_SETTINGS.defaultZoomLevel,
|
||||
minZoomLevel: $.DEFAULT_SETTINGS.minZoomLevel,
|
||||
maxZoomLevel: $.DEFAULT_SETTINGS.maxZoomLevel
|
||||
maxZoomLevel: $.DEFAULT_SETTINGS.maxZoomLevel,
|
||||
degrees: $.DEFAULT_SETTINGS.degrees
|
||||
|
||||
}, options );
|
||||
|
||||
@ -70,11 +109,12 @@ $.Viewport = function( options ) {
|
||||
this.update();
|
||||
};
|
||||
|
||||
$.Viewport.prototype = {
|
||||
$.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @return {OpenSeadragon.Viewport} Chainable.
|
||||
* @fires OpenSeadragon.Viewer.event:reset-size
|
||||
*/
|
||||
resetContentSize: function( contentSize ){
|
||||
this.contentSize = contentSize;
|
||||
@ -86,9 +126,18 @@ $.Viewport.prototype = {
|
||||
this.homeBounds = new $.Rect( 0, 0, 1, this.contentAspectY );
|
||||
|
||||
if( this.viewer ){
|
||||
/**
|
||||
* Raised when the viewer's content size is reset (see {@link OpenSeadragon.Viewport#resetContentSize}).
|
||||
*
|
||||
* @event reset-size
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
||||
* @property {OpenSeadragon.Point} contentSize
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.viewer.raiseEvent( 'reset-size', {
|
||||
contentSize: contentSize,
|
||||
viewer: this.viewer
|
||||
contentSize: contentSize
|
||||
});
|
||||
}
|
||||
|
||||
@ -130,12 +179,22 @@ $.Viewport.prototype = {
|
||||
/**
|
||||
* @function
|
||||
* @param {Boolean} immediately
|
||||
* @fires OpenSeadragon.Viewer.event:home
|
||||
*/
|
||||
goHome: function( immediately ) {
|
||||
if( this.viewer ){
|
||||
/**
|
||||
* Raised when the "home" operation occurs (see {@link OpenSeadragon.Viewport#goHome}).
|
||||
*
|
||||
* @event home
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
||||
* @property {Boolean} immediately
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.viewer.raiseEvent( 'home', {
|
||||
immediately: immediately,
|
||||
viewer: this.viewer
|
||||
immediately: immediately
|
||||
});
|
||||
}
|
||||
return this.fitBounds( this.getHomeBounds(), immediately );
|
||||
@ -183,6 +242,7 @@ $.Viewport.prototype = {
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @param {Boolean} current - Pass true for the current location; defaults to false (target location).
|
||||
*/
|
||||
getBounds: function( current ) {
|
||||
var center = this.getCenter( current ),
|
||||
@ -199,6 +259,7 @@ $.Viewport.prototype = {
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @param {Boolean} current - Pass true for the current location; defaults to false (target location).
|
||||
*/
|
||||
getCenter: function( current ) {
|
||||
var centerCurrent = new $.Point(
|
||||
@ -249,6 +310,7 @@ $.Viewport.prototype = {
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @param {Boolean} current - Pass true for the current location; defaults to false (target location).
|
||||
*/
|
||||
getZoom: function( current ) {
|
||||
if ( current ) {
|
||||
@ -261,6 +323,7 @@ $.Viewport.prototype = {
|
||||
/**
|
||||
* @function
|
||||
* @return {OpenSeadragon.Viewport} Chainable.
|
||||
* @fires OpenSeadragon.Viewer.event:constrain
|
||||
*/
|
||||
applyConstraints: function( immediately ) {
|
||||
var actualZoom = this.getZoom(),
|
||||
@ -275,10 +338,8 @@ $.Viewport.prototype = {
|
||||
right,
|
||||
top,
|
||||
bottom,
|
||||
center,
|
||||
dx = 0,
|
||||
dy = 0,
|
||||
dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
|
||||
dy = 0;
|
||||
|
||||
if ( actualZoom != constrainedZoom ) {
|
||||
this.zoomTo( constrainedZoom, this.zoomPoint, immediately );
|
||||
@ -333,9 +394,18 @@ $.Viewport.prototype = {
|
||||
}
|
||||
|
||||
if( this.viewer ){
|
||||
/**
|
||||
* Raised when the viewport constraints are applied (see {@link OpenSeadragon.Viewport#applyConstraints}).
|
||||
*
|
||||
* @event constrain
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
||||
* @property {Boolean} immediately
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.viewer.raiseEvent( 'constrain', {
|
||||
immediately: immediately,
|
||||
viewer: this.viewer
|
||||
immediately: immediately
|
||||
});
|
||||
}
|
||||
|
||||
@ -459,12 +529,14 @@ $.Viewport.prototype = {
|
||||
* @param {OpenSeadragon.Point} delta
|
||||
* @param {Boolean} immediately
|
||||
* @return {OpenSeadragon.Viewport} Chainable.
|
||||
* @fires OpenSeadragon.Viewer.event:pan
|
||||
*/
|
||||
panBy: function( delta, immediately ) {
|
||||
var center = new $.Point(
|
||||
this.centerSpringX.target.value,
|
||||
this.centerSpringY.target.value
|
||||
);
|
||||
delta = delta.rotate( -this.degrees, new $.Point( 0, 0 ) );
|
||||
return this.panTo( center.plus( delta ), immediately );
|
||||
},
|
||||
|
||||
@ -473,6 +545,7 @@ $.Viewport.prototype = {
|
||||
* @param {OpenSeadragon.Point} center
|
||||
* @param {Boolean} immediately
|
||||
* @return {OpenSeadragon.Viewport} Chainable.
|
||||
* @fires OpenSeadragon.Viewer.event:pan
|
||||
*/
|
||||
panTo: function( center, immediately ) {
|
||||
if ( immediately ) {
|
||||
@ -484,10 +557,20 @@ $.Viewport.prototype = {
|
||||
}
|
||||
|
||||
if( this.viewer ){
|
||||
/**
|
||||
* Raised when the viewport is panned (see {@link OpenSeadragon.Viewport#panBy} and {@link OpenSeadragon.Viewport#panTo}).
|
||||
*
|
||||
* @event pan
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
||||
* @property {OpenSeadragon.Point} center
|
||||
* @property {Boolean} immediately
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.viewer.raiseEvent( 'pan', {
|
||||
center: center,
|
||||
immediately: immediately,
|
||||
viewer: this.viewer
|
||||
immediately: immediately
|
||||
});
|
||||
}
|
||||
|
||||
@ -497,18 +580,28 @@ $.Viewport.prototype = {
|
||||
/**
|
||||
* @function
|
||||
* @return {OpenSeadragon.Viewport} Chainable.
|
||||
* @fires OpenSeadragon.Viewer.event:zoom
|
||||
*/
|
||||
zoomBy: function( factor, refPoint, immediately ) {
|
||||
if( refPoint instanceof $.Point && !isNaN( refPoint.x ) && !isNaN( refPoint.y ) ) {
|
||||
refPoint = refPoint.rotate(
|
||||
-this.degrees,
|
||||
new $.Point( this.centerSpringX.target.value, this.centerSpringY.target.value )
|
||||
);
|
||||
}
|
||||
return this.zoomTo( this.zoomSpring.target.value * factor, refPoint, immediately );
|
||||
},
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @return {OpenSeadragon.Viewport} Chainable.
|
||||
* @fires OpenSeadragon.Viewer.event:zoom
|
||||
*/
|
||||
zoomTo: function( zoom, refPoint, immediately ) {
|
||||
|
||||
this.zoomPoint = refPoint instanceof $.Point ?
|
||||
this.zoomPoint = refPoint instanceof $.Point &&
|
||||
!isNaN(refPoint.x) &&
|
||||
!isNaN(refPoint.y) ?
|
||||
refPoint :
|
||||
null;
|
||||
|
||||
@ -519,11 +612,22 @@ $.Viewport.prototype = {
|
||||
}
|
||||
|
||||
if( this.viewer ){
|
||||
/**
|
||||
* Raised when the viewport zoom level changes (see {@link OpenSeadragon.Viewport#zoomBy} and {@link OpenSeadragon.Viewport#zoomTo}).
|
||||
*
|
||||
* @event zoom
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
||||
* @property {Number} zoom
|
||||
* @property {OpenSeadragon.Point} refPoint
|
||||
* @property {Boolean} immediately
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.viewer.raiseEvent( 'zoom', {
|
||||
zoom: zoom,
|
||||
refPoint: refPoint,
|
||||
immediately: immediately,
|
||||
viewer: this.viewer
|
||||
immediately: immediately
|
||||
});
|
||||
}
|
||||
|
||||
@ -531,29 +635,73 @@ $.Viewport.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Currently only 90 degree rotation is supported and it only works
|
||||
* with the canvas. Additionally, the navigator does not rotate yet,
|
||||
* debug mode doesn't rotate yet, and overlay rotation is only
|
||||
* partially supported.
|
||||
* @function
|
||||
* @return {OpenSeadragon.Viewport} Chainable.
|
||||
*/
|
||||
setRotation: function( degrees ) {
|
||||
if( !( this.viewer && this.viewer.drawer.canRotate() ) ) {
|
||||
return this;
|
||||
}
|
||||
|
||||
degrees = ( degrees + 360 ) % 360;
|
||||
if( degrees % 90 !== 0 ) {
|
||||
throw new Error('Currently only 0, 90, 180, and 270 degrees are supported.');
|
||||
}
|
||||
this.degrees = degrees;
|
||||
this.viewer.forceRedraw();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the current rotation in degrees.
|
||||
* @function
|
||||
* @return {Number} The current rotation in degrees.
|
||||
*/
|
||||
getRotation: function() {
|
||||
return this.degrees;
|
||||
},
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @return {OpenSeadragon.Viewport} Chainable.
|
||||
* @fires OpenSeadragon.Viewer.event:resize
|
||||
*/
|
||||
resize: function( newContainerSize, maintain ) {
|
||||
var oldBounds = this.getBounds(),
|
||||
newBounds = oldBounds,
|
||||
widthDeltaFactor = newContainerSize.x / this.containerSize.x;
|
||||
widthDeltaFactor;
|
||||
|
||||
this.containerSize = new $.Point(
|
||||
newContainerSize.x,
|
||||
newContainerSize.y
|
||||
);
|
||||
|
||||
if (maintain) {
|
||||
if ( maintain ) {
|
||||
widthDeltaFactor = newContainerSize.x / this.containerSize.x;
|
||||
newBounds.width = oldBounds.width * widthDeltaFactor;
|
||||
newBounds.height = newBounds.width / this.getAspectRatio();
|
||||
}
|
||||
|
||||
if( this.viewer ){
|
||||
/**
|
||||
* Raised when the viewer is resized (see {@link OpenSeadragon.Viewport#resize}).
|
||||
*
|
||||
* @event resize
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
||||
* @property {OpenSeadragon.Point} newContainerSize
|
||||
* @property {Boolean} maintain
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.viewer.raiseEvent( 'resize', {
|
||||
newContainerSize: newContainerSize,
|
||||
maintain: maintain,
|
||||
viewer: this.viewer
|
||||
maintain: maintain
|
||||
});
|
||||
}
|
||||
|
||||
@ -599,7 +747,9 @@ $.Viewport.prototype = {
|
||||
|
||||
|
||||
/**
|
||||
* Convert a delta (translation vector) from pixels coordinates to viewport coordinates
|
||||
* @function
|
||||
* @param {Boolean} current - Pass true for the current location; defaults to false (target location).
|
||||
*/
|
||||
deltaPixelsFromPoints: function( deltaPoints, current ) {
|
||||
return deltaPoints.times(
|
||||
@ -608,7 +758,9 @@ $.Viewport.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert a delta (translation vector) from viewport coordinates to pixels coordinates.
|
||||
* @function
|
||||
* @param {Boolean} current - Pass true for the current location; defaults to false (target location).
|
||||
*/
|
||||
deltaPointsFromPixels: function( deltaPixels, current ) {
|
||||
return deltaPixels.divide(
|
||||
@ -617,7 +769,9 @@ $.Viewport.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert image pixel coordinates to viewport coordinates.
|
||||
* @function
|
||||
* @param {Boolean} current - Pass true for the current location; defaults to false (target location).
|
||||
*/
|
||||
pixelFromPoint: function( point, current ) {
|
||||
var bounds = this.getBounds( current );
|
||||
@ -629,7 +783,9 @@ $.Viewport.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert viewport coordinates to image pixel coordinates.
|
||||
* @function
|
||||
* @param {Boolean} current - Pass true for the current location; defaults to false (target location).
|
||||
*/
|
||||
pointFromPixel: function( pixel, current ) {
|
||||
var bounds = this.getBounds( current );
|
||||
@ -641,34 +797,65 @@ $.Viewport.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Translates from Seajax viewer coordinate
|
||||
* system to image coordinate system
|
||||
* Translates from OpenSeadragon viewer coordinate system to image coordinate system.
|
||||
* This method can be called either by passing X,Y coordinates or an
|
||||
* OpenSeadragon.Point
|
||||
* @function
|
||||
* @param {OpenSeadragon.Point} viewerX the point in viewport coordinate system.
|
||||
* @param {Number} viewerX X coordinate in viewport coordinate system.
|
||||
* @param {Number} viewerY Y coordinate in viewport coordinate system.
|
||||
* @return {OpenSeadragon.Point} a point representing the coordinates in the image.
|
||||
*/
|
||||
viewportToImageCoordinates: function(viewerX, viewerY) {
|
||||
return new $.Point(viewerX * this.contentSize.x, viewerY * this.contentSize.y * this.contentAspectX);
|
||||
viewportToImageCoordinates: function( viewerX, viewerY ) {
|
||||
if ( arguments.length == 1 ) {
|
||||
//they passed a point instead of individual components
|
||||
return this.viewportToImageCoordinates( viewerX.x, viewerX.y );
|
||||
}
|
||||
return new $.Point( viewerX * this.contentSize.x, viewerY * this.contentSize.y * this.contentAspectX );
|
||||
},
|
||||
|
||||
/**
|
||||
* Translates from image coordinate system to
|
||||
* Seajax viewer coordinate system
|
||||
* Translates from image coordinate system to OpenSeadragon viewer coordinate system
|
||||
* This method can be called either by passing X,Y coordinates or an
|
||||
* OpenSeadragon.Point
|
||||
* @function
|
||||
* @param {OpenSeadragon.Point} imageX the point in image coordinate system.
|
||||
* @param {Number} imageX X coordinate in image coordinate system.
|
||||
* @param {Number} imageY Y coordinate in image coordinate system.
|
||||
* @return {OpenSeadragon.Point} a point representing the coordinates in the viewport.
|
||||
*/
|
||||
imageToViewportCoordinates: function( imageX, imageY ) {
|
||||
return new $.Point( imageX / this.contentSize.x, imageY / this.contentSize.y / this.contentAspectX);
|
||||
if ( arguments.length == 1 ) {
|
||||
//they passed a point instead of individual components
|
||||
return this.imageToViewportCoordinates( imageX.x, imageX.y );
|
||||
}
|
||||
return new $.Point( imageX / this.contentSize.x, imageY / this.contentSize.y / this.contentAspectX );
|
||||
},
|
||||
|
||||
/**
|
||||
* Translates from a rectanlge which describes a portion of
|
||||
* the image in pixel coordinates to OpenSeadragon viewport
|
||||
* rectangle coordinates.
|
||||
* Translates from a rectangle which describes a portion of the image in
|
||||
* pixel coordinates to OpenSeadragon viewport rectangle coordinates.
|
||||
* This method can be called either by passing X,Y,width,height or an
|
||||
* OpenSeadragon.Rect
|
||||
* @function
|
||||
* @param {OpenSeadragon.Rect} imageX the rectangle in image coordinate system.
|
||||
* @param {Number} imageX the X coordinate of the top left corner of the rectangle
|
||||
* in image coordinate system.
|
||||
* @param {Number} imageY the Y coordinate of the top left corner of the rectangle
|
||||
* in image coordinate system.
|
||||
* @param {Number} pixelWidth the width in pixel of the rectangle.
|
||||
* @param {Number} pixelHeight the height in pixel of the rectangle.
|
||||
*/
|
||||
imageToViewportRectangle: function( imageX, imageY, pixelWidth, pixelHeight ) {
|
||||
var coordA,
|
||||
coordB,
|
||||
rect;
|
||||
if( arguments.length == 1 ){
|
||||
if( arguments.length == 1 ) {
|
||||
//they passed a rectangle instead of individual components
|
||||
rect = imageX;
|
||||
return this.imageToViewportRectangle(rect.x, rect.y, rect.width, rect.height);
|
||||
return this.imageToViewportRectangle(
|
||||
rect.x, rect.y, rect.width, rect.height
|
||||
);
|
||||
}
|
||||
coordA = this.imageToViewportCoordinates(
|
||||
imageX, imageY
|
||||
@ -679,9 +866,166 @@ $.Viewport.prototype = {
|
||||
return new $.Rect(
|
||||
coordA.x,
|
||||
coordA.y,
|
||||
coordA.x + coordB.x,
|
||||
coordA.y + coordB.y
|
||||
coordB.x,
|
||||
coordB.y
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Translates from a rectangle which describes a portion of
|
||||
* the viewport in point coordinates to image rectangle coordinates.
|
||||
* This method can be called either by passing X,Y,width,height or an
|
||||
* OpenSeadragon.Rect
|
||||
* @function
|
||||
* @param {OpenSeadragon.Rect} viewerX the rectangle in viewport coordinate system.
|
||||
* @param {Number} viewerX the X coordinate of the top left corner of the rectangle
|
||||
* in viewport coordinate system.
|
||||
* @param {Number} imageY the Y coordinate of the top left corner of the rectangle
|
||||
* in viewport coordinate system.
|
||||
* @param {Number} pointWidth the width of the rectangle in viewport coordinate system.
|
||||
* @param {Number} pointHeight the height of the rectangle in viewport coordinate system.
|
||||
*/
|
||||
viewportToImageRectangle: function( viewerX, viewerY, pointWidth, pointHeight ) {
|
||||
var coordA,
|
||||
coordB,
|
||||
rect;
|
||||
if ( arguments.length == 1 ) {
|
||||
//they passed a rectangle instead of individual components
|
||||
rect = viewerX;
|
||||
return this.viewportToImageRectangle(
|
||||
rect.x, rect.y, rect.width, rect.height
|
||||
);
|
||||
}
|
||||
coordA = this.viewportToImageCoordinates( viewerX, viewerY );
|
||||
coordB = this.viewportToImageCoordinates( pointWidth, pointHeight );
|
||||
return new $.Rect(
|
||||
coordA.x,
|
||||
coordA.y,
|
||||
coordB.x,
|
||||
coordB.y
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert pixel coordinates relative to the viewer element to image
|
||||
* coordinates.
|
||||
* @param {OpenSeadragon.Point} pixel
|
||||
* @returns {OpenSeadragon.Point}
|
||||
*/
|
||||
viewerElementToImageCoordinates: function( pixel ) {
|
||||
var point = this.pointFromPixel( pixel, true );
|
||||
return this.viewportToImageCoordinates( point );
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert pixel coordinates relative to the image to
|
||||
* viewer element coordinates.
|
||||
* @param {OpenSeadragon.Point} pixel
|
||||
* @returns {OpenSeadragon.Point}
|
||||
*/
|
||||
imageToViewerElementCoordinates: function( pixel ) {
|
||||
var point = this.imageToViewportCoordinates( pixel );
|
||||
return this.pixelFromPoint( point, true );
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert pixel coordinates relative to the window to image coordinates.
|
||||
* @param {OpenSeadragon.Point} pixel
|
||||
* @returns {OpenSeadragon.Point}
|
||||
*/
|
||||
windowToImageCoordinates: function( pixel ) {
|
||||
var viewerCoordinates = pixel.minus(
|
||||
OpenSeadragon.getElementPosition( this.viewer.element ));
|
||||
return this.viewerElementToImageCoordinates( viewerCoordinates );
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert image coordinates to pixel coordinates relative to the window.
|
||||
* @param {OpenSeadragon.Point} pixel
|
||||
* @returns {OpenSeadragon.Point}
|
||||
*/
|
||||
imageToWindowCoordinates: function( pixel ) {
|
||||
var viewerCoordinates = this.imageToViewerElementCoordinates( pixel );
|
||||
return viewerCoordinates.plus(
|
||||
OpenSeadragon.getElementPosition( this.viewer.element ));
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert pixel coordinates relative to the viewer element to viewport
|
||||
* coordinates.
|
||||
* @param {OpenSeadragon.Point} pixel
|
||||
* @returns {OpenSeadragon.Point}
|
||||
*/
|
||||
viewerElementToViewportCoordinates: function( pixel ) {
|
||||
return this.pointFromPixel( pixel, true );
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert viewport coordinates to pixel coordinates relative to the
|
||||
* viewer element.
|
||||
* @param {OpenSeadragon.Point} point
|
||||
* @returns {OpenSeadragon.Point}
|
||||
*/
|
||||
viewportToViewerElementCoordinates: function( point ) {
|
||||
return this.pixelFromPoint( point, true );
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert pixel coordinates relative to the window to viewport coordinates.
|
||||
* @param {OpenSeadragon.Point} pixel
|
||||
* @returns {OpenSeadragon.Point}
|
||||
*/
|
||||
windowToViewportCoordinates: function( pixel ) {
|
||||
var viewerCoordinates = pixel.minus(
|
||||
OpenSeadragon.getElementPosition( this.viewer.element ));
|
||||
return this.viewerElementToViewportCoordinates( viewerCoordinates );
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert viewport coordinates to pixel coordinates relative to the window.
|
||||
* @param {OpenSeadragon.Point} point
|
||||
* @returns {OpenSeadragon.Point}
|
||||
*/
|
||||
viewportToWindowCoordinates: function( point ) {
|
||||
var viewerCoordinates = this.viewportToViewerElementCoordinates( point );
|
||||
return viewerCoordinates.plus(
|
||||
OpenSeadragon.getElementPosition( this.viewer.element ));
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert a viewport zoom to an image zoom.
|
||||
* Image zoom: ratio of the original image size to displayed image size.
|
||||
* 1 means original image size, 0.5 half size...
|
||||
* Viewport zoom: ratio of the displayed image's width to viewport's width.
|
||||
* 1 means identical width, 2 means image's width is twice the viewport's width...
|
||||
* @function
|
||||
* @param {Number} viewportZoom The viewport zoom
|
||||
* target zoom.
|
||||
* @returns {Number} imageZoom The image zoom
|
||||
*/
|
||||
viewportToImageZoom: function( viewportZoom ) {
|
||||
var imageWidth = this.viewer.source.dimensions.x;
|
||||
var containerWidth = this.getContainerSize().x;
|
||||
var viewportToImageZoomRatio = containerWidth / imageWidth;
|
||||
return viewportZoom * viewportToImageZoomRatio;
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert an image zoom to a viewport zoom.
|
||||
* Image zoom: ratio of the original image size to displayed image size.
|
||||
* 1 means original image size, 0.5 half size...
|
||||
* Viewport zoom: ratio of the displayed image's width to viewport's width.
|
||||
* 1 means identical width, 2 means image's width is twice the viewport's width...
|
||||
* @function
|
||||
* @param {Number} imageZoom The image zoom
|
||||
* target zoom.
|
||||
* @returns {Number} viewportZoom The viewport zoom
|
||||
*/
|
||||
imageToViewportZoom: function( imageZoom ) {
|
||||
var imageWidth = this.viewer.source.dimensions.x;
|
||||
var containerWidth = this.getContainerSize().x;
|
||||
var viewportToImageZoomRatio = imageWidth / containerWidth;
|
||||
return imageZoom * viewportToImageZoomRatio;
|
||||
}
|
||||
};
|
||||
|
||||
|
330
test/basic.js
@ -1,115 +1,303 @@
|
||||
/* global module, asyncTest, $, ok, equal, notEqual, start, test, Util, testLog */
|
||||
|
||||
(function() {
|
||||
var viewer;
|
||||
|
||||
// TODO: Tighten up springs and use "immediate" where possible, so tests run faster
|
||||
// TODO: Test drag
|
||||
module('Basic', {
|
||||
setup: function () {
|
||||
var example = $('<div id="example"></div>').appendTo("#qunit-fixture");
|
||||
|
||||
var viewer = null;
|
||||
testLog.reset();
|
||||
|
||||
// ----------
|
||||
asyncTest('Open', function() {
|
||||
$(document).ready(function() {
|
||||
viewer = OpenSeadragon({
|
||||
id: 'example',
|
||||
prefixUrl: '/build/openseadragon/images/',
|
||||
tileSources: '/test/data/testpattern.dzi',
|
||||
showNavigator: true
|
||||
springStiffness: 100 // Faster animation = faster tests
|
||||
});
|
||||
},
|
||||
teardown: function () {
|
||||
if (viewer && viewer.close) {
|
||||
viewer.close();
|
||||
}
|
||||
|
||||
ok(viewer, 'Viewer exists');
|
||||
viewer = null;
|
||||
}
|
||||
});
|
||||
|
||||
var openHandler = function(eventSender, eventData) {
|
||||
viewer.removeHandler('open', openHandler);
|
||||
ok(true, 'Open event was sent');
|
||||
equal(eventSender, viewer, 'Sender of open event was viewer');
|
||||
ok(eventData, 'Handler also received event data');
|
||||
ok(viewer.viewport, 'Viewport exists');
|
||||
start();
|
||||
};
|
||||
// ----------
|
||||
asyncTest('Open', function() {
|
||||
ok(viewer, 'Viewer exists');
|
||||
|
||||
viewer.addHandler('open', openHandler);
|
||||
var openHandler = function(event) {
|
||||
viewer.removeHandler('open', openHandler);
|
||||
ok(true, 'Open event was sent');
|
||||
ok(event, 'Handler received event data');
|
||||
equal(event.eventSource, viewer, 'Sender of open event was viewer');
|
||||
ok(viewer.viewport, 'Viewport exists');
|
||||
ok(viewer.source, 'source exists');
|
||||
ok(viewer._updateRequestId, 'timer is on');
|
||||
start();
|
||||
};
|
||||
|
||||
viewer.addHandler('open', openHandler);
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
asyncTest('Open Error Handling', function() {
|
||||
ok(viewer, 'Viewer exists');
|
||||
|
||||
viewer.addHandler('open', function(event) {
|
||||
ok(false, "The open event should not fire for failed opens");
|
||||
start();
|
||||
});
|
||||
|
||||
viewer.addHandler('open-failed', function(event) {
|
||||
ok(true, "The open-failed event should be fired when the source 404s");
|
||||
|
||||
equal($(".openseadragon-message").length, 1, "Open failures should display a message");
|
||||
|
||||
ok(testLog.log.contains('["AJAX request returned %s: %s",404,"/test/data/not-a-real-file"]'),
|
||||
"AJAX failures should be logged to the console");
|
||||
|
||||
start();
|
||||
});
|
||||
|
||||
viewer.open('/test/data/not-a-real-file');
|
||||
});
|
||||
|
||||
// ----------
|
||||
asyncTest('Zoom', function() {
|
||||
var viewport = viewer.viewport;
|
||||
equal(viewport.getZoom(), 1, 'We start out unzoomed');
|
||||
viewer.addHandler("open", function () {
|
||||
var viewport = viewer.viewport;
|
||||
|
||||
var zoomHandler = function() {
|
||||
viewer.removeHandler('animationfinish', zoomHandler);
|
||||
equal(viewport.getZoom(), 2, 'Zoomed correctly');
|
||||
start();
|
||||
};
|
||||
equal(viewport.getZoom(), 1, 'We start out unzoomed');
|
||||
|
||||
viewer.addHandler('animationfinish', zoomHandler);
|
||||
viewport.zoomTo(2);
|
||||
var zoomHandler = function() {
|
||||
viewer.removeHandler('animation-finish', zoomHandler);
|
||||
equal(viewport.getZoom(), 2, 'Zoomed correctly');
|
||||
start();
|
||||
};
|
||||
|
||||
viewer.addHandler('animation-finish', zoomHandler);
|
||||
viewport.zoomTo(2);
|
||||
});
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
// ----------
|
||||
asyncTest('Pan', function() {
|
||||
var viewport = viewer.viewport;
|
||||
var center = viewport.getCenter();
|
||||
ok(center.x === 0.5 && center.y === 0.5, 'We start out unpanned');
|
||||
viewer.addHandler("open", function () {
|
||||
var viewport = viewer.viewport,
|
||||
center = viewport.getCenter();
|
||||
|
||||
var panHandler = function() {
|
||||
viewer.removeHandler('animationfinish', panHandler);
|
||||
center = viewport.getCenter();
|
||||
ok(center.x === 0.1 && center.y === 0.1, 'Panned correctly');
|
||||
start();
|
||||
};
|
||||
ok(center.x === 0.5 && center.y === 0.5, 'We start out unpanned');
|
||||
|
||||
viewer.addHandler('animationfinish', panHandler);
|
||||
viewport.panTo(new OpenSeadragon.Point(0.1, 0.1));
|
||||
var panHandler = function() {
|
||||
viewer.removeHandler('animation-finish', panHandler);
|
||||
center = viewport.getCenter();
|
||||
ok(center.x === 0.1 && center.y === 0.1, 'Panned correctly');
|
||||
start();
|
||||
};
|
||||
|
||||
viewer.addHandler('animation-finish', panHandler);
|
||||
viewport.panTo(new OpenSeadragon.Point(0.1, 0.1));
|
||||
});
|
||||
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
// ----------
|
||||
asyncTest('Home', function() {
|
||||
var viewport = viewer.viewport;
|
||||
var center = viewport.getCenter();
|
||||
ok(center.x !== 0.5 && center.y !== 0.5, 'We start out panned');
|
||||
notEqual(viewport.getZoom(), 1, 'We start out zoomed');
|
||||
// Test setup:
|
||||
function opener() {
|
||||
var viewport = viewer.viewport;
|
||||
viewport.panTo(new OpenSeadragon.Point(0.1, 0.1));
|
||||
viewport.zoomTo(2);
|
||||
}
|
||||
|
||||
var homeHandler = function() {
|
||||
viewer.removeHandler('animationfinish', homeHandler);
|
||||
center = viewport.getCenter();
|
||||
ok(center.x === 0.5 && center.y === 0.5, 'We end up unpanned');
|
||||
equal(viewport.getZoom(), 1, 'We end up unzoomed');
|
||||
start();
|
||||
};
|
||||
function stage1() {
|
||||
var viewport = viewer.viewport,
|
||||
center = viewport.getCenter();
|
||||
|
||||
viewer.addHandler('animationfinish', homeHandler);
|
||||
viewport.goHome(true);
|
||||
viewer.removeHandler('animation-finish', stage1);
|
||||
|
||||
ok(center.x !== 0.5 && center.y !== 0.5, 'We start out panned');
|
||||
notEqual(viewport.getZoom(), 1, 'We start out zoomed');
|
||||
|
||||
var homeHandler = function() {
|
||||
viewer.removeHandler('animation-finish', homeHandler);
|
||||
center = viewport.getCenter();
|
||||
ok(center.x === 0.5 && center.y === 0.5, 'We end up unpanned');
|
||||
equal(viewport.getZoom(), 1, 'We end up unzoomed');
|
||||
start();
|
||||
};
|
||||
|
||||
viewer.addHandler('animation-finish', homeHandler);
|
||||
viewport.goHome(true);
|
||||
}
|
||||
|
||||
viewer.addHandler("open", opener);
|
||||
viewer.addHandler("animation-finish", stage1);
|
||||
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
// ----------
|
||||
asyncTest('Click', function() {
|
||||
var viewport = viewer.viewport;
|
||||
center = viewport.getCenter();
|
||||
ok(center.x === 0.5 && center.y === 0.5, 'We start out unpanned');
|
||||
equal(viewport.getZoom(), 1, 'We start out unzoomed');
|
||||
|
||||
var clickHandler = function() {
|
||||
viewer.removeHandler('animationfinish', clickHandler);
|
||||
viewer.addHandler("open", function () {
|
||||
var viewport = viewer.viewport,
|
||||
center = viewport.getCenter();
|
||||
ok(center.x > 0.37 && center.x < 0.38 && center.y > 0.37 && center.y < 0.38, 'Panned correctly');
|
||||
equal(viewport.getZoom(), 2, 'Zoomed correctly');
|
||||
start();
|
||||
};
|
||||
|
||||
viewer.addHandler('animationfinish', clickHandler);
|
||||
Util.simulateViewerClick(viewer, 0.25, 0.25);
|
||||
ok(center.x === 0.5 && center.y === 0.5, 'We start out unpanned');
|
||||
equal(viewport.getZoom(), 1, 'We start out unzoomed');
|
||||
|
||||
var clickHandler = function() {
|
||||
viewer.removeHandler('animation-finish', clickHandler);
|
||||
center = viewport.getCenter();
|
||||
ok(center.x > 0.37 && center.x < 0.38 && center.y > 0.37 && center.y < 0.38, 'Panned correctly');
|
||||
equal(viewport.getZoom(), 2, 'Zoomed correctly');
|
||||
start();
|
||||
};
|
||||
|
||||
viewer.addHandler('animation-finish', clickHandler);
|
||||
Util.simulateViewerClickWithDrag( {
|
||||
viewer: viewer,
|
||||
widthFactor: 0.25,
|
||||
heightFactor: 0.25,
|
||||
dragCount: 0,
|
||||
dragDx: 0,
|
||||
dragDy: 0
|
||||
} );
|
||||
} );
|
||||
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
// ----------
|
||||
asyncTest('FullPage', function() {
|
||||
viewer.addHandler("open", function () {
|
||||
ok(!viewer.isFullPage(), 'Started out not fullpage');
|
||||
ok(!$(viewer.element).hasClass('fullpage'),
|
||||
'No fullpage class on div');
|
||||
|
||||
var checkEnteringPreFullPage = function(event) {
|
||||
viewer.removeHandler('pre-full-page', checkEnteringPreFullPage);
|
||||
ok(event.fullPage, 'Switching to fullpage');
|
||||
ok(!viewer.isFullPage(), 'Not yet fullpage');
|
||||
};
|
||||
|
||||
var checkEnteringFullPage = function(event) {
|
||||
viewer.removeHandler('full-page', checkEnteringFullPage);
|
||||
ok(event.fullPage, 'Switched to fullpage');
|
||||
ok(viewer.isFullPage(), 'Enabled fullpage');
|
||||
ok($(viewer.element).hasClass('fullpage'),
|
||||
'Fullpage class added to div');
|
||||
|
||||
var checkExitingPreFullPage = function(event) {
|
||||
viewer.removeHandler('pre-full-page', checkExitingPreFullPage);
|
||||
ok(!event.fullPage, 'Exiting fullpage');
|
||||
ok(viewer.isFullPage(), 'Still fullpage');
|
||||
};
|
||||
|
||||
var checkExitingFullPage = function(event) {
|
||||
viewer.removeHandler('full-page', checkExitingFullPage);
|
||||
ok(!event.fullPage, 'Exiting fullpage');
|
||||
ok(!viewer.isFullPage(), 'Disabled fullpage');
|
||||
ok(!$(viewer.element).hasClass('fullpage'),
|
||||
'Fullpage class removed from div');
|
||||
start();
|
||||
};
|
||||
|
||||
viewer.addHandler("pre-full-page", checkExitingPreFullPage);
|
||||
viewer.addHandler("full-page", checkExitingFullPage);
|
||||
viewer.setFullPage(false);
|
||||
};
|
||||
viewer.addHandler("pre-full-page", checkEnteringPreFullPage);
|
||||
viewer.addHandler("full-page", checkEnteringFullPage);
|
||||
viewer.setFullPage(true);
|
||||
});
|
||||
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
asyncTest('FullScreen', function() {
|
||||
|
||||
if (!OpenSeadragon.supportsFullScreen) {
|
||||
expect(0);
|
||||
start();
|
||||
return;
|
||||
}
|
||||
|
||||
viewer.addHandler("open", function () {
|
||||
ok(!OpenSeadragon.isFullScreen(), 'Started out not fullscreen');
|
||||
|
||||
var checkEnteringPreFullScreen = function(event) {
|
||||
viewer.removeHandler('pre-full-screen', checkEnteringPreFullScreen);
|
||||
ok(event.fullScreen, 'Switching to fullscreen');
|
||||
ok(!OpenSeadragon.isFullScreen(), 'Not yet fullscreen');
|
||||
};
|
||||
|
||||
// The fullscreen mode is always denied during tests so we are
|
||||
// exiting directly.
|
||||
var checkExitingFullScreen = function(event) {
|
||||
viewer.removeHandler('full-screen', checkExitingFullScreen);
|
||||
ok(!event.fullScreen, 'Exiting fullscreen');
|
||||
ok(!OpenSeadragon.isFullScreen(), 'Disabled fullscreen');
|
||||
start();
|
||||
};
|
||||
viewer.addHandler("pre-full-screen", checkEnteringPreFullScreen);
|
||||
viewer.addHandler("full-screen", checkExitingFullScreen);
|
||||
viewer.setFullScreen(true);
|
||||
});
|
||||
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
// ----------
|
||||
asyncTest('Close', function() {
|
||||
var closeHandler = function() {
|
||||
viewer.removeHandler('close', closeHandler);
|
||||
ok(true, 'Close event was sent');
|
||||
start();
|
||||
};
|
||||
viewer.addHandler("open", function () {
|
||||
var closeHandler = function() {
|
||||
viewer.removeHandler('close', closeHandler);
|
||||
ok(!viewer.source, 'no source');
|
||||
ok(true, 'Close event was sent');
|
||||
ok(!viewer._updateRequestId, 'timer is off');
|
||||
setTimeout(function() {
|
||||
ok(!viewer._updateRequestId, 'timer is still off');
|
||||
start();
|
||||
}, 100);
|
||||
};
|
||||
|
||||
viewer.addHandler('close', closeHandler);
|
||||
viewer.close();
|
||||
viewer.addHandler('close', closeHandler);
|
||||
viewer.close();
|
||||
});
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
// ----------
|
||||
asyncTest('Destroy', function() {
|
||||
viewer.addHandler("open", function () {
|
||||
// Check that the DOM has been modified
|
||||
notEqual(0, $('#example').children().length);
|
||||
|
||||
var closeCalled = false;
|
||||
var closeHandler = function() {
|
||||
viewer.removeHandler('close', closeHandler);
|
||||
closeCalled = true;
|
||||
};
|
||||
|
||||
viewer.addHandler('close', closeHandler);
|
||||
viewer.destroy();
|
||||
|
||||
// Check that the DOM has been cleaned up
|
||||
equal(0, $('#example').children().length);
|
||||
equal(null, viewer.canvas);
|
||||
equal(null, viewer.keyboardCommandArea);
|
||||
equal(null, viewer.container);
|
||||
equal(null, viewer.element);
|
||||
equal(true, closeCalled);
|
||||
start();
|
||||
});
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
})();
|
||||
|
383
test/controls.js
vendored
Normal file
@ -0,0 +1,383 @@
|
||||
/* global module, asyncTest, $, ok, equal, notEqual, start, test, Util, testLog */
|
||||
|
||||
(function () {
|
||||
var viewer;
|
||||
|
||||
module('Controls', {
|
||||
setup: function () {
|
||||
var example = $('<div id="controlsTests"></div>').appendTo("#qunit-fixture");
|
||||
|
||||
testLog.reset();
|
||||
|
||||
},
|
||||
teardown: function () {
|
||||
if (viewer && viewer.close) {
|
||||
viewer.close();
|
||||
}
|
||||
|
||||
viewer = null;
|
||||
}
|
||||
});
|
||||
|
||||
asyncTest('ZoomControlOff', function () {
|
||||
|
||||
var openHandler = function () {
|
||||
viewer.removeHandler('open', openHandler);
|
||||
ok(!viewer.showZoomControl, 'showZoomControl should be off');
|
||||
ok(!viewer.zoomInButton, "zoomIn button should be null");
|
||||
ok(!viewer.zoomOutButton, "zoomOut button should be null");
|
||||
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer = OpenSeadragon({
|
||||
id: 'controlsTests',
|
||||
prefixUrl: '/build/openseadragon/images/',
|
||||
springStiffness: 100, // Faster animation = faster tests
|
||||
showZoomControl: false
|
||||
});
|
||||
viewer.addHandler('open', openHandler);
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
asyncTest('ZoomControlOn', function () {
|
||||
|
||||
var openHandler = function () {
|
||||
viewer.removeHandler('open', openHandler);
|
||||
ok(viewer.showZoomControl, 'showZoomControl should be on');
|
||||
ok(!!viewer.zoomInButton, "zoomIn button should not be null");
|
||||
ok(!!viewer.zoomOutButton, "zoomOut button should not be null");
|
||||
notEqual(viewer.buttons.buttons.indexOf(viewer.zoomInButton), -1,
|
||||
"The zoomIn button should be present");
|
||||
notEqual(viewer.buttons.buttons.indexOf(viewer.zoomOutButton), -1,
|
||||
"The zoomOut button should be present");
|
||||
|
||||
var oldZoom = viewer.viewport.getZoom();
|
||||
viewer.zoomInButton.onClick();
|
||||
var newZoom = viewer.viewport.getZoom();
|
||||
ok(oldZoom < newZoom, "OSD should have zoomed in.");
|
||||
oldZoom = newZoom;
|
||||
viewer.zoomOutButton.onClick();
|
||||
newZoom = viewer.viewport.getZoom();
|
||||
ok(oldZoom > newZoom, "OSD should have zoomed out.");
|
||||
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer = OpenSeadragon({
|
||||
id: 'controlsTests',
|
||||
prefixUrl: '/build/openseadragon/images/',
|
||||
springStiffness: 100, // Faster animation = faster tests
|
||||
showZoomControl: true
|
||||
});
|
||||
viewer.addHandler('open', openHandler);
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
asyncTest('HomeControlOff', function () {
|
||||
|
||||
var openHandler = function () {
|
||||
viewer.removeHandler('open', openHandler);
|
||||
ok(!viewer.showHomeControl, 'showHomeControl should be off');
|
||||
ok(!viewer.homeButton, "Home button should be null");
|
||||
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer = OpenSeadragon({
|
||||
id: 'controlsTests',
|
||||
prefixUrl: '/build/openseadragon/images/',
|
||||
springStiffness: 100, // Faster animation = faster tests
|
||||
showHomeControl: false
|
||||
});
|
||||
viewer.addHandler('open', openHandler);
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
asyncTest('HomeControlOn', function () {
|
||||
|
||||
var openHandler = function () {
|
||||
viewer.removeHandler('open', openHandler);
|
||||
ok(viewer.showHomeControl, 'showHomeControl should be on');
|
||||
ok(!!viewer.homeButton, "Home button should not be null");
|
||||
notEqual(viewer.buttons.buttons.indexOf(viewer.homeButton), -1,
|
||||
"The home button should be present");
|
||||
|
||||
viewer.viewport.zoomBy(1.1);
|
||||
var bounds = viewer.viewport.getBounds();
|
||||
var homeBounds = viewer.viewport.getHomeBounds();
|
||||
ok(bounds.x !== homeBounds.x ||
|
||||
bounds.y !== homeBounds.y ||
|
||||
bounds.width !== homeBounds.width ||
|
||||
bounds.height !== homeBounds.height,
|
||||
"OSD should not be at home.");
|
||||
viewer.homeButton.onRelease();
|
||||
bounds = viewer.viewport.getBounds();
|
||||
ok(bounds.x === homeBounds.x &&
|
||||
bounds.y === homeBounds.y &&
|
||||
bounds.width === homeBounds.width &&
|
||||
bounds.height === homeBounds.height, "OSD should have get home.");
|
||||
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer = OpenSeadragon({
|
||||
id: 'controlsTests',
|
||||
prefixUrl: '/build/openseadragon/images/',
|
||||
springStiffness: 100, // Faster animation = faster tests
|
||||
showHomeControl: true
|
||||
});
|
||||
viewer.addHandler('open', openHandler);
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
asyncTest('FullPageControlOff', function () {
|
||||
|
||||
var openHandler = function () {
|
||||
viewer.removeHandler('open', openHandler);
|
||||
ok(!viewer.showFullPageControl, 'showFullPageControl should be off');
|
||||
ok(!viewer.fullPageButton, "FullPage button should be null");
|
||||
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer = OpenSeadragon({
|
||||
id: 'controlsTests',
|
||||
prefixUrl: '/build/openseadragon/images/',
|
||||
springStiffness: 100, // Faster animation = faster tests
|
||||
showFullPageControl: false
|
||||
});
|
||||
viewer.addHandler('open', openHandler);
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
asyncTest('FullPageControlOn', function () {
|
||||
|
||||
var openHandler = function () {
|
||||
viewer.removeHandler('open', openHandler);
|
||||
ok(viewer.showHomeControl, 'showFullPageControl should be on');
|
||||
ok(!!viewer.fullPageButton, "FullPage button should not be null");
|
||||
notEqual(viewer.buttons.buttons.indexOf(viewer.fullPageButton), -1,
|
||||
"The full page button should be present");
|
||||
|
||||
ok(!viewer.isFullPage(), "OSD should not be in full page.");
|
||||
viewer.fullPageButton.onRelease();
|
||||
ok(viewer.isFullPage(), "OSD should be in full page.");
|
||||
viewer.fullPageButton.onRelease();
|
||||
ok(!viewer.isFullPage(), "OSD should not be in full page.");
|
||||
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer = OpenSeadragon({
|
||||
id: 'controlsTests',
|
||||
prefixUrl: '/build/openseadragon/images/',
|
||||
springStiffness: 100, // Faster animation = faster tests
|
||||
showHomeControl: true
|
||||
});
|
||||
viewer.addHandler('open', openHandler);
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
asyncTest('RotateControlOff', function () {
|
||||
|
||||
var openHandler = function (event) {
|
||||
viewer.removeHandler('open', openHandler);
|
||||
ok(true, 'Open event was sent');
|
||||
ok(viewer.drawer, 'Drawer exists');
|
||||
ok(viewer.drawer.canRotate(), 'drawer.canRotate needs to be true');
|
||||
ok(!viewer.showRotationControl, 'showRotationControl should be off');
|
||||
ok(!viewer.rotateLeftButton, "rotateLeft button should be null");
|
||||
ok(!viewer.rotateRightButton, "rotateRight button should be null");
|
||||
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer = OpenSeadragon({
|
||||
id: 'controlsTests',
|
||||
prefixUrl: '/build/openseadragon/images/',
|
||||
springStiffness: 100, // Faster animation = faster tests
|
||||
showRotationControl: false
|
||||
});
|
||||
viewer.addHandler('open', openHandler);
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
asyncTest('RotateControlOn', function () {
|
||||
|
||||
var openHandler = function (event) {
|
||||
viewer.removeHandler('open', openHandler);
|
||||
ok(true, 'Open event was sent');
|
||||
ok(viewer.drawer, 'Drawer exists');
|
||||
ok(viewer.drawer.canRotate(), 'drawer.canRotate needs to be true');
|
||||
ok(viewer.showRotationControl, 'showRotationControl should be true');
|
||||
notEqual(viewer.buttons.buttons.indexOf(viewer.rotateLeftButton), -1,
|
||||
"rotateLeft should be found");
|
||||
notEqual(viewer.buttons.buttons.indexOf(viewer.rotateRightButton), -1,
|
||||
"rotateRight should be found");
|
||||
|
||||
// Now simulate the left/right button clicks.
|
||||
// TODO: re-factor simulateViewerClickWithDrag so it'll accept any element, and use that.
|
||||
equal(viewer.viewport.degrees, 0, "Image should start at 0 degrees rotation");
|
||||
viewer.rotateLeftButton.onRelease();
|
||||
equal(viewer.viewport.degrees, 270, "Image should be 270 degrees rotation (left)");
|
||||
viewer.rotateRightButton.onRelease();
|
||||
equal(viewer.viewport.degrees, 0, "Image should be 270 degrees rotation (right)");
|
||||
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer = OpenSeadragon({
|
||||
id: 'controlsTests',
|
||||
prefixUrl: '/build/openseadragon/images/',
|
||||
springStiffness: 100, // Faster animation = faster tests
|
||||
showRotationControl: true
|
||||
});
|
||||
viewer.addHandler('open', openHandler);
|
||||
viewer.open('/test/data/testpattern.dzi');
|
||||
});
|
||||
|
||||
asyncTest('SequenceControlOff', function () {
|
||||
|
||||
var openHandler = function () {
|
||||
viewer.removeHandler('open', openHandler);
|
||||
ok(!viewer.showSequenceControl, 'showSequenceControl should be off');
|
||||
ok(!viewer.previousButton, "Previous button should be null");
|
||||
ok(!viewer.nextButton, "Next button should be null");
|
||||
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer = OpenSeadragon({
|
||||
id: 'controlsTests',
|
||||
prefixUrl: '/build/openseadragon/images/',
|
||||
tileSources: [
|
||||
'/test/data/testpattern.dzi',
|
||||
'/test/data/testpattern.dzi',
|
||||
'/test/data/testpattern.dzi'
|
||||
],
|
||||
springStiffness: 100, // Faster animation = faster tests
|
||||
showSequenceControl: false
|
||||
});
|
||||
viewer.addHandler('open', openHandler);
|
||||
});
|
||||
|
||||
asyncTest('SequenceControlOnPrevNextWrapOff', function () {
|
||||
|
||||
var openHandler = function () {
|
||||
viewer.removeHandler('open', openHandler);
|
||||
ok(viewer.showSequenceControl, 'showSequenceControl should be on');
|
||||
ok(!!viewer.previousButton, "Previous button should not be null");
|
||||
ok(!!viewer.nextButton, "Next button should not be null");
|
||||
notEqual(viewer.paging.buttons.indexOf(viewer.previousButton), -1,
|
||||
"The previous button should be present");
|
||||
notEqual(viewer.paging.buttons.indexOf(viewer.nextButton), -1,
|
||||
"The next button should be present");
|
||||
|
||||
equal(viewer.currentPage(), 0, "OSD should open on first page.");
|
||||
ok(viewer.previousButton.element.disabled,
|
||||
"Previous should be disabled on first page.");
|
||||
ok(!viewer.nextButton.element.disabled,
|
||||
"Next should be enabled on first page.");
|
||||
|
||||
viewer.nextButton.onRelease();
|
||||
equal(viewer.currentPage(), 1, "OSD should be on second page.");
|
||||
ok(!viewer.previousButton.element.disabled,
|
||||
"Previous should be enabled on second page.");
|
||||
ok(!viewer.nextButton.element.disabled,
|
||||
"Next should be enabled on second page.");
|
||||
|
||||
viewer.nextButton.onRelease();
|
||||
equal(viewer.currentPage(), 2, "OSD should be on third page.");
|
||||
ok(!viewer.previousButton.element.disabled,
|
||||
"Previous should be enabled on third page.");
|
||||
ok(viewer.nextButton.element.disabled,
|
||||
"Next should be disabled on third page.");
|
||||
|
||||
viewer.previousButton.onRelease();
|
||||
equal(viewer.currentPage(), 1, "OSD should be on second page.");
|
||||
ok(!viewer.previousButton.element.disabled,
|
||||
"Previous should be enabled on second page.");
|
||||
ok(!viewer.nextButton.element.disabled,
|
||||
"Next should be enabled on second page.");
|
||||
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer = OpenSeadragon({
|
||||
id: 'controlsTests',
|
||||
prefixUrl: '/build/openseadragon/images/',
|
||||
tileSources: [
|
||||
'/test/data/testpattern.dzi',
|
||||
'/test/data/testpattern.dzi',
|
||||
'/test/data/testpattern.dzi'
|
||||
],
|
||||
springStiffness: 100, // Faster animation = faster tests
|
||||
showSequenceControl: true,
|
||||
navPrevNextWrap: false
|
||||
});
|
||||
viewer.addHandler('open', openHandler);
|
||||
});
|
||||
|
||||
asyncTest('SequenceControlOnPrevNextWrapOn', function () {
|
||||
|
||||
var openHandler = function () {
|
||||
viewer.removeHandler('open', openHandler);
|
||||
ok(viewer.showSequenceControl, 'showSequenceControl should be on');
|
||||
ok(!!viewer.previousButton, "Previous button should not be null");
|
||||
ok(!!viewer.nextButton, "Next button should not be null");
|
||||
notEqual(viewer.paging.buttons.indexOf(viewer.previousButton), -1,
|
||||
"The previous button should be present");
|
||||
notEqual(viewer.paging.buttons.indexOf(viewer.nextButton), -1,
|
||||
"The next button should be present");
|
||||
|
||||
equal(viewer.currentPage(), 0, "OSD should open on first page.");
|
||||
ok(!viewer.previousButton.element.disabled,
|
||||
"Previous should be enabled on first page.");
|
||||
ok(!viewer.nextButton.element.disabled,
|
||||
"Next should be enabled on first page.");
|
||||
|
||||
viewer.previousButton.onRelease();
|
||||
equal(viewer.currentPage(), 2, "OSD should be on third page.");
|
||||
ok(!viewer.previousButton.element.disabled,
|
||||
"Previous should be enabled on third page.");
|
||||
ok(!viewer.nextButton.element.disabled,
|
||||
"Next should be enabled on third page.");
|
||||
|
||||
viewer.nextButton.onRelease();
|
||||
equal(viewer.currentPage(), 0, "OSD should be on first page.");
|
||||
ok(!viewer.previousButton.element.disabled,
|
||||
"Previous should be enabled on first page.");
|
||||
ok(!viewer.nextButton.element.disabled,
|
||||
"Next should be enabled on first page.");
|
||||
|
||||
viewer.close();
|
||||
start();
|
||||
};
|
||||
|
||||
viewer = OpenSeadragon({
|
||||
id: 'controlsTests',
|
||||
prefixUrl: '/build/openseadragon/images/',
|
||||
tileSources: [
|
||||
'/test/data/testpattern.dzi',
|
||||
'/test/data/testpattern.dzi',
|
||||
'/test/data/testpattern.dzi'
|
||||
],
|
||||
springStiffness: 100, // Faster animation = faster tests
|
||||
showSequenceControl: true,
|
||||
navPrevNextWrap: true
|
||||
});
|
||||
viewer.addHandler('open', openHandler);
|
||||
});
|
||||
|
||||
})();
|
BIN
test/data/A.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
test/data/BBlue.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
test/data/CCyan.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
test/data/DDandelion.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
26
test/data/iiif1_0.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"identifier": "iiif_1_0_files",
|
||||
"width": 775,
|
||||
"height": 1024,
|
||||
"scale_factors": [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"tile_width": 256,
|
||||
"tile_height": 256,
|
||||
"formats": [
|
||||
"jpg",
|
||||
"png"
|
||||
],
|
||||
"qualities": [
|
||||
"native",
|
||||
"bitonal",
|
||||
"grey",
|
||||
"color"
|
||||
],
|
||||
"profile": "http://library.stanford.edu/iiif/image-api/compliance.html#level1"
|
||||
}
|
26
test/data/iiif1_0.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<info xmlns="http://library.stanford.edu/iiif/image-api/ns/">
|
||||
<identifier>iiif_1_0_files</identifier>
|
||||
<width>775</width>
|
||||
<height>1024</height>
|
||||
<scale_factors>
|
||||
<scale_factor>1</scale_factor>
|
||||
<scale_factor>2</scale_factor>
|
||||
<scale_factor>3</scale_factor>
|
||||
<scale_factor>4</scale_factor>
|
||||
<scale_factor>5</scale_factor>
|
||||
<scale_factor>6</scale_factor>
|
||||
</scale_factors>
|
||||
<tile_width>256</tile_width>
|
||||
<tile_height>256</tile_height>
|
||||
<formats>
|
||||
<format>jpg</format>
|
||||
<format>png</format>
|
||||
</formats>
|
||||
<qualities>
|
||||
<quality>native</quality>
|
||||
<quality>bitonal</quality>
|
||||
<quality>grey</quality>
|
||||
<quality>color</quality>
|
||||
</qualities>
|
||||
<profile>http://library.stanford.edu/iiif/image-api/compliance.html#level1</profile>
|
||||
</info>
|
BIN
test/data/iiif_1_0_files/0,0,256,256/256,/0/native.jpg
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
test/data/iiif_1_0_files/0,0,512,512/256,/0/native.jpg
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
test/data/iiif_1_0_files/0,0,775,1024/194,/0/native.jpg
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
test/data/iiif_1_0_files/0,256,256,256/256,/0/native.jpg
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
test/data/iiif_1_0_files/0,512,256,256/256,/0/native.jpg
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
test/data/iiif_1_0_files/0,512,512,512/256,/0/native.jpg
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
test/data/iiif_1_0_files/0,768,256,256/256,/0/native.jpg
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
test/data/iiif_1_0_files/256,0,256,256/256,/0/native.jpg
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
test/data/iiif_1_0_files/256,256,256,256/256,/0/native.jpg
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
test/data/iiif_1_0_files/256,512,256,256/256,/0/native.jpg
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
test/data/iiif_1_0_files/256,768,256,256/256,/0/native.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
test/data/iiif_1_0_files/512,0,256,256/256,/0/native.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
test/data/iiif_1_0_files/512,0,263,512/132,/0/native.jpg
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
test/data/iiif_1_0_files/512,256,256,256/256,/0/native.jpg
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
test/data/iiif_1_0_files/512,512,256,256/256,/0/native.jpg
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
test/data/iiif_1_0_files/512,512,263,512/132,/0/native.jpg
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
test/data/iiif_1_0_files/512,768,256,256/256,/0/native.jpg
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
test/data/iiif_1_0_files/768,0,7,256/7,/0/native.jpg
Normal file
After Width: | Height: | Size: 717 B |
BIN
test/data/iiif_1_0_files/768,256,7,256/7,/0/native.jpg
Normal file
After Width: | Height: | Size: 716 B |
BIN
test/data/iiif_1_0_files/768,512,7,256/7,/0/native.jpg
Normal file
After Width: | Height: | Size: 717 B |
BIN
test/data/iiif_1_0_files/768,768,7,256/7,/0/native.jpg
Normal file
After Width: | Height: | Size: 712 B |
BIN
test/data/iiif_1_0_files/full/1,/0/native.jpg
Normal file
After Width: | Height: | Size: 633 B |
BIN
test/data/iiif_1_0_files/full/13,/0/native.jpg
Normal file
After Width: | Height: | Size: 810 B |
BIN
test/data/iiif_1_0_files/full/2,/0/native.jpg
Normal file
After Width: | Height: | Size: 663 B |
BIN
test/data/iiif_1_0_files/full/25,/0/native.jpg
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
test/data/iiif_1_0_files/full/4,/0/native.jpg
Normal file
After Width: | Height: | Size: 675 B |
BIN
test/data/iiif_1_0_files/full/49,/0/native.jpg
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
test/data/iiif_1_0_files/full/7,/0/native.jpg
Normal file
After Width: | Height: | Size: 683 B |