Merge branch 'master' into master
285
.eslintrc.hound.json
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true
|
||||||
|
},
|
||||||
|
"extends": "eslint:recommended",
|
||||||
|
"rules": {
|
||||||
|
"indent": [
|
||||||
|
"error",
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"linebreak-style": [
|
||||||
|
"error",
|
||||||
|
"unix"
|
||||||
|
],
|
||||||
|
"quotes": [
|
||||||
|
"error",
|
||||||
|
"double"
|
||||||
|
],
|
||||||
|
"semi": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"no-unused-vars": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"args": "none"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"block-scoped-var": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"consistent-return": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"curly": [
|
||||||
|
"error",
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"eqeqeq": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-eval": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-implicit-globals": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-implied-eval": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-invalid-this": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-multi-spaces": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"exceptions": {
|
||||||
|
"Property": true,
|
||||||
|
"VariableDeclarator": true,
|
||||||
|
"AssignmentExpression": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-new-wrappers": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-new": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-return-assign": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-self-compare": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-unmodified-loop-condition": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-unused-expressions": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-useless-call": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-useless-concat": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-useless-escape": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-useless-return": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-with": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"radix": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"yoda": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-undef-init": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-use-before-define": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"functions": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"array-bracket-spacing": [
|
||||||
|
"error",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"block-spacing": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"brace-style": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"camelcase": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"comma-spacing": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"comma-style": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"computed-property-spacing": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"consistent-this": [
|
||||||
|
"error",
|
||||||
|
"self"
|
||||||
|
],
|
||||||
|
"eol-last": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"func-call-spacing": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"func-name-matching": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"key-spacing": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"mode": "minimum"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"keyword-spacing": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"max-len": [
|
||||||
|
"error",
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"max-statements-per-line": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"max": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"new-cap": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"new-parens": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-array-constructor": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-mixed-operators": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"groups": [
|
||||||
|
[
|
||||||
|
"&",
|
||||||
|
"|",
|
||||||
|
"^",
|
||||||
|
"~",
|
||||||
|
"<<",
|
||||||
|
">>",
|
||||||
|
">>>"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"==",
|
||||||
|
"!=",
|
||||||
|
"===",
|
||||||
|
"!==",
|
||||||
|
">",
|
||||||
|
">=",
|
||||||
|
"<",
|
||||||
|
"<="
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"&&",
|
||||||
|
"||"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"in",
|
||||||
|
"instanceof"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-new-object": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-tabs": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-trailing-spaces": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-unneeded-ternary": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-whitespace-before-property": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"object-curly-spacing": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"one-var-declaration-per-line": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"one-var": [
|
||||||
|
"error",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"operator-assignment": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"operator-linebreak": [
|
||||||
|
"error",
|
||||||
|
"after"
|
||||||
|
],
|
||||||
|
"quote-props": [
|
||||||
|
"error",
|
||||||
|
"as-needed"
|
||||||
|
],
|
||||||
|
"semi-spacing": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"space-before-blocks": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"space-before-function-paren": [
|
||||||
|
"error",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"space-in-parens": [
|
||||||
|
"error",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"space-infix-ops": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"space-unary-ops": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"words": false,
|
||||||
|
"nonwords": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"unicode-bom": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-caller": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-loop-func": [
|
||||||
|
"error"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"OpenSeadragon": true,
|
||||||
|
"define": false,
|
||||||
|
"module": false
|
||||||
|
}
|
||||||
|
}
|
285
.eslintrc.json
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true
|
||||||
|
},
|
||||||
|
"extends": "eslint:recommended",
|
||||||
|
"rules": {
|
||||||
|
"indent": [
|
||||||
|
"off",
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"linebreak-style": [
|
||||||
|
"error",
|
||||||
|
"unix"
|
||||||
|
],
|
||||||
|
"quotes": [
|
||||||
|
"off",
|
||||||
|
"double"
|
||||||
|
],
|
||||||
|
"semi": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"no-unused-vars": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"args": "none"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"block-scoped-var": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"consistent-return": [
|
||||||
|
"off"
|
||||||
|
],
|
||||||
|
"curly": [
|
||||||
|
"error",
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"eqeqeq": [
|
||||||
|
"off"
|
||||||
|
],
|
||||||
|
"no-eval": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-implicit-globals": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-implied-eval": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-invalid-this": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-multi-spaces": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"exceptions": {
|
||||||
|
"Property": true,
|
||||||
|
"VariableDeclarator": true,
|
||||||
|
"AssignmentExpression": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-new-wrappers": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-new": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-return-assign": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-self-compare": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-unmodified-loop-condition": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-unused-expressions": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-useless-call": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-useless-concat": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-useless-escape": [
|
||||||
|
"off"
|
||||||
|
],
|
||||||
|
"no-useless-return": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-with": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"radix": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"yoda": [
|
||||||
|
"off"
|
||||||
|
],
|
||||||
|
"no-undef-init": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-use-before-define": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"functions": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"array-bracket-spacing": [
|
||||||
|
"off",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"block-spacing": [
|
||||||
|
"off"
|
||||||
|
],
|
||||||
|
"brace-style": [
|
||||||
|
"off"
|
||||||
|
],
|
||||||
|
"camelcase": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"comma-spacing": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"comma-style": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"computed-property-spacing": [
|
||||||
|
"off"
|
||||||
|
],
|
||||||
|
"consistent-this": [
|
||||||
|
"off",
|
||||||
|
"self"
|
||||||
|
],
|
||||||
|
"eol-last": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"func-call-spacing": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"func-name-matching": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"key-spacing": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"mode": "minimum"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"keyword-spacing": [
|
||||||
|
"off"
|
||||||
|
],
|
||||||
|
"max-len": [
|
||||||
|
"off",
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"max-statements-per-line": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"max": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"new-cap": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"new-parens": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-array-constructor": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-mixed-operators": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"groups": [
|
||||||
|
[
|
||||||
|
"&",
|
||||||
|
"|",
|
||||||
|
"^",
|
||||||
|
"~",
|
||||||
|
"<<",
|
||||||
|
">>",
|
||||||
|
">>>"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"==",
|
||||||
|
"!=",
|
||||||
|
"===",
|
||||||
|
"!==",
|
||||||
|
">",
|
||||||
|
">=",
|
||||||
|
"<",
|
||||||
|
"<="
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"&&",
|
||||||
|
"||"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"in",
|
||||||
|
"instanceof"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-new-object": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-tabs": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-trailing-spaces": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-unneeded-ternary": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-whitespace-before-property": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"object-curly-spacing": [
|
||||||
|
"off",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"one-var-declaration-per-line": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"one-var": [
|
||||||
|
"off",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"operator-assignment": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"operator-linebreak": [
|
||||||
|
"error",
|
||||||
|
"after"
|
||||||
|
],
|
||||||
|
"quote-props": [
|
||||||
|
"off",
|
||||||
|
"as-needed"
|
||||||
|
],
|
||||||
|
"semi-spacing": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"space-before-blocks": [
|
||||||
|
"off"
|
||||||
|
],
|
||||||
|
"space-before-function-paren": [
|
||||||
|
"off",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"space-in-parens": [
|
||||||
|
"off",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"space-infix-ops": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"space-unary-ops": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"words": false,
|
||||||
|
"nonwords": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"unicode-bom": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-caller": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"no-loop-func": [
|
||||||
|
"error"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"OpenSeadragon": true,
|
||||||
|
"define": false,
|
||||||
|
"module": false
|
||||||
|
}
|
||||||
|
}
|
3
.hound.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
eslint:
|
||||||
|
enabled: true
|
||||||
|
config_file: .eslintrc.hound.json
|
16
.jshintrc
@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"browser": true,
|
|
||||||
"curly": true,
|
|
||||||
"eqeqeq": false,
|
|
||||||
"loopfunc": false,
|
|
||||||
"noarg": true,
|
|
||||||
"trailing": true,
|
|
||||||
"undef": true,
|
|
||||||
"unused": false,
|
|
||||||
|
|
||||||
"globals": {
|
|
||||||
"OpenSeadragon": true,
|
|
||||||
"define": false,
|
|
||||||
"module": false
|
|
||||||
}
|
|
||||||
}
|
|
9
.vscode/settings.json
vendored
@ -1,8 +1,5 @@
|
|||||||
// Place your settings in this file to overwrite default and user settings.
|
// Place your settings in this file to overwrite default and user settings.
|
||||||
{
|
{
|
||||||
// Controls the font size.
|
|
||||||
"editor.fontSize": 14,
|
|
||||||
|
|
||||||
// The number of spaces a tab is equal to.
|
// The number of spaces a tab is equal to.
|
||||||
"editor.tabSize": 4,
|
"editor.tabSize": 4,
|
||||||
|
|
||||||
@ -15,12 +12,6 @@
|
|||||||
// Columns at which to show vertical rulers
|
// Columns at which to show vertical rulers
|
||||||
"editor.rulers": [80],
|
"editor.rulers": [80],
|
||||||
|
|
||||||
// Controls after how many characters the editor will wrap to the next line. Setting this to 0 turns on viewport width wrapping
|
|
||||||
"editor.wrappingColumn": 0,
|
|
||||||
|
|
||||||
// Controls the indentation of wrapped lines. Can be one of 'none', 'same' or 'indent'.
|
|
||||||
"editor.wrappingIndent": "none",
|
|
||||||
|
|
||||||
// The default character set encoding to use when reading and writing files.
|
// The default character set encoding to use when reading and writing files.
|
||||||
"files.encoding": "utf8",
|
"files.encoding": "utf8",
|
||||||
|
|
||||||
|
18
Gruntfile.js
@ -5,12 +5,12 @@ module.exports = function(grunt) {
|
|||||||
// ----------
|
// ----------
|
||||||
grunt.loadNpmTasks("grunt-contrib-compress");
|
grunt.loadNpmTasks("grunt-contrib-compress");
|
||||||
grunt.loadNpmTasks("grunt-contrib-concat");
|
grunt.loadNpmTasks("grunt-contrib-concat");
|
||||||
grunt.loadNpmTasks("grunt-contrib-jshint");
|
|
||||||
grunt.loadNpmTasks("grunt-contrib-uglify");
|
grunt.loadNpmTasks("grunt-contrib-uglify");
|
||||||
grunt.loadNpmTasks("grunt-qunit-istanbul");
|
grunt.loadNpmTasks("grunt-qunit-istanbul");
|
||||||
grunt.loadNpmTasks("grunt-contrib-connect");
|
grunt.loadNpmTasks("grunt-contrib-connect");
|
||||||
grunt.loadNpmTasks("grunt-contrib-watch");
|
grunt.loadNpmTasks("grunt-contrib-watch");
|
||||||
grunt.loadNpmTasks("grunt-contrib-clean");
|
grunt.loadNpmTasks("grunt-contrib-clean");
|
||||||
|
grunt.loadNpmTasks("grunt-eslint");
|
||||||
grunt.loadNpmTasks("grunt-git-describe");
|
grunt.loadNpmTasks("grunt-git-describe");
|
||||||
grunt.loadNpmTasks('grunt-text-replace');
|
grunt.loadNpmTasks('grunt-text-replace');
|
||||||
|
|
||||||
@ -123,10 +123,11 @@ module.exports = function(grunt) {
|
|||||||
join_vars: false
|
join_vars: false
|
||||||
},
|
},
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
sourceMapName: 'build/openseadragon/openseadragon.min.js.map'
|
sourceMapName: 'build/openseadragon/openseadragon.min.js.map',
|
||||||
|
sourceMapIn: 'build/openseadragon/openseadragon.js.map'
|
||||||
},
|
},
|
||||||
openseadragon: {
|
openseadragon: {
|
||||||
src: sources,
|
src: distribution,
|
||||||
dest: minified
|
dest: minified
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -186,12 +187,11 @@ module.exports = function(grunt) {
|
|||||||
files: [ "Gruntfile.js", "src/*.js", "images/*" ],
|
files: [ "Gruntfile.js", "src/*.js", "images/*" ],
|
||||||
tasks: "watchTask"
|
tasks: "watchTask"
|
||||||
},
|
},
|
||||||
jshint: {
|
eslint: {
|
||||||
options: {
|
options: {
|
||||||
jshintrc: '.jshintrc'
|
configFile: '.eslintrc.json'
|
||||||
},
|
},
|
||||||
beforeconcat: sources,
|
target: sources
|
||||||
afterconcat: [ distribution ]
|
|
||||||
},
|
},
|
||||||
"git-describe": {
|
"git-describe": {
|
||||||
build: {}
|
build: {}
|
||||||
@ -264,8 +264,8 @@ module.exports = function(grunt) {
|
|||||||
// Build task.
|
// Build task.
|
||||||
// Cleans out the build folder and builds the code and images into it, checking lint.
|
// Cleans out the build folder and builds the code and images into it, checking lint.
|
||||||
grunt.registerTask("build", [
|
grunt.registerTask("build", [
|
||||||
"clean:build", "jshint:beforeconcat", "git-describe", "concat", "jshint:afterconcat",
|
"clean:build", "git-describe", "eslint", "concat", "uglify",
|
||||||
"uglify", "replace:cleanPaths", "copy:build"
|
"replace:cleanPaths", "copy:build"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// ----------
|
// ----------
|
||||||
|
@ -1,25 +1,48 @@
|
|||||||
OPENSEADRAGON CHANGELOG
|
OPENSEADRAGON CHANGELOG
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
2.2.2: (in progress)
|
2.3.0: (in progress)
|
||||||
|
|
||||||
* BREAKING CHANGE: Tile.distance has been removed (#1027)
|
* BREAKING CHANGE: Tile.distance has been removed (#1027)
|
||||||
|
* BREAKING CHANGE: Viewer's canvas-click event is now fired before it initiates the zoom (#1148)
|
||||||
|
* BREAKING CHANGE: Viewer's canvas-drag event is now fired before it pans (#1149)
|
||||||
|
* Optimization: Use the squared distance when comparing tiles (#1027)
|
||||||
|
* You can now prevent canvas-click events from zooming on a per-event basis (#1148)
|
||||||
|
* You can now prevent canvas-drag events from panning on a per-event basis (#1149)
|
||||||
* You can now set the rotation of individual tiled images (#1006)
|
* You can now set the rotation of individual tiled images (#1006)
|
||||||
* Fixed CORS bug in IE 10 (#967)
|
* Fixed CORS bug in IE 10 (#967)
|
||||||
* Added support for commonjs (#984)
|
* Added support for commonjs (#984)
|
||||||
* Added an option to addTiledImage to change the crossOriginPolicy (#981)
|
* Added an option to addTiledImage to change the crossOriginPolicy (#981)
|
||||||
* Fixed issue with tiles not appearing with wrapHorizontal/wrapVertical if you pan too far away from the origin (#987)
|
* Fixed issue with tiles not appearing with wrapHorizontal/wrapVertical if you pan too far away from the origin (#987, #1066)
|
||||||
* The Viewer's tileSources option is now smarter about detecting JSON vs XML vs URL (#999)
|
* The Viewer's tileSources option is now smarter about detecting JSON vs XML vs URL (#999)
|
||||||
* The navigationControlAnchor option now works for custom toolbar as well (#1004)
|
* The navigationControlAnchor option now works for custom toolbar as well (#1004)
|
||||||
* Added getFullyLoaded method and "fully-loaded-change" event to TiledImage to know when tiles are fully loaded (#837)
|
* Added getFullyLoaded method and "fully-loaded-change" event to TiledImage to know when tiles are fully loaded (#837, #1073)
|
||||||
* Fixed: Initial tile load wasn't happening in parallel (#1014)
|
* Fixed: Initial tile load wasn't happening in parallel (#1014)
|
||||||
* Added Zoomify tile source (#863)
|
* Added Zoomify tile source (#863)
|
||||||
* Fixed problem with "sparse image" DZI files (#995)
|
* Fixed problem with "sparse image" DZI files (#995)
|
||||||
* Optimization: Use the squared distance when comparing tiles (#1027)
|
|
||||||
* Fix IndexSizeError on IE and Edge that occurred under certain circumstances (e.g. multi-image with transparency) (#1035)
|
* Fix IndexSizeError on IE and Edge that occurred under certain circumstances (e.g. multi-image with transparency) (#1035)
|
||||||
* ImageTileSource now works in IE8 (#1041)
|
* ImageTileSource now works in IE8 (#1041)
|
||||||
* LegacyTileSource now allows any image URLs regardless of type (#1056)
|
* LegacyTileSource now allows any image URLs regardless of type (#1056)
|
||||||
* Fixed error in IE8 when zooming in (due to edge smoothing) (#1064)
|
* Fixed error in IE8 when zooming in (due to edge smoothing) (#1064)
|
||||||
|
* Improved DziTileSource guessing of tilesUrl (#1074)
|
||||||
|
* Fixed issue with OpenSeadragon.version in the minified JavaScript (#1099)
|
||||||
|
* Fixed smoothTileEdgesMinZoom performance degradation on single-tile images (#1101)
|
||||||
|
* Fixed issue with tiles not appearing after rotation (#1102)
|
||||||
|
* Fixed: The navigator wasn't respecting the constrainDuringPan setting (#1104)
|
||||||
|
* Fixed an issue causing overlays to be mis-positioned in some circumstances (#1119)
|
||||||
|
* Fixed: ImageTileSource would sometimes produce a double image (#1123)
|
||||||
|
* Fixed: console.debug caused exceptions on IE10 (#1129)
|
||||||
|
* Better compression for our UI images (#1134)
|
||||||
|
* Fixed: the reference strip would leak memory when opening new sets of images (#1175)
|
||||||
|
* You can now load tiles via AJAX and custom AJAX request headers (#1055)
|
||||||
|
* Added fix for supporting weird filenames that look like JSONs (#1189)
|
||||||
|
* Fixed: zoomTo/zoomBy ignore refPoint if immediately is true (#1184)
|
||||||
|
* Enabled configuration of ImageLoader timeout (#1192)
|
||||||
|
* Viewer.open() now supports an initialPage argument for sequenceMode (#1196)
|
||||||
|
* Fixed: IIPImageServer didn't work with the latest OSD release (#1199)
|
||||||
|
* Now clamping pixel ratio density to a minimum of 1, fixing display issues on low density devices (#1200)
|
||||||
|
* Improved calculation for determining which level to load first (#1198)
|
||||||
|
* Fixed: setItemIndex method not working with navigator inside "open" event (#1201)
|
||||||
|
|
||||||
2.2.1:
|
2.2.1:
|
||||||
|
|
||||||
|
BIN
images/button_grouphover.png
Executable file
After Width: | Height: | Size: 1.5 KiB |
BIN
images/button_hover.png
Executable file
After Width: | Height: | Size: 1.8 KiB |
BIN
images/button_pressed.png
Executable file
After Width: | Height: | Size: 1.9 KiB |
BIN
images/button_rest.png
Executable file
After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 977 B |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 1.1 KiB |
@ -18,12 +18,12 @@
|
|||||||
"grunt": "^0.4.5",
|
"grunt": "^0.4.5",
|
||||||
"grunt-contrib-clean": "^0.7.0",
|
"grunt-contrib-clean": "^0.7.0",
|
||||||
"grunt-contrib-compress": "^0.13.0",
|
"grunt-contrib-compress": "^0.13.0",
|
||||||
"grunt-contrib-concat": "^0.5.1",
|
"grunt-contrib-concat": "^1.0.1",
|
||||||
"grunt-contrib-connect": "^0.11.2",
|
"grunt-contrib-connect": "^0.11.2",
|
||||||
"grunt-contrib-jshint": "^0.11.0",
|
"grunt-contrib-uglify": "^2.0.0",
|
||||||
"grunt-contrib-uglify": "^0.11.0",
|
|
||||||
"grunt-contrib-watch": "^0.6.1",
|
"grunt-contrib-watch": "^0.6.1",
|
||||||
"grunt-git-describe": "^2.3.2",
|
"grunt-git-describe": "^2.3.2",
|
||||||
|
"grunt-eslint": "^19.0.0",
|
||||||
"grunt-qunit-istanbul": "^0.6.0",
|
"grunt-qunit-istanbul": "^0.6.0",
|
||||||
"grunt-text-replace": "^0.4.0",
|
"grunt-text-replace": "^0.4.0",
|
||||||
"qunitjs": "^1.20.0"
|
"qunitjs": "^1.20.0"
|
||||||
|
BIN
psd/button.psd
Executable file
@ -61,7 +61,7 @@ $.ButtonState = {
|
|||||||
* @memberof OpenSeadragon
|
* @memberof OpenSeadragon
|
||||||
* @extends OpenSeadragon.EventSource
|
* @extends OpenSeadragon.EventSource
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
* @param {Element} [options.element=null] Element to use as the button. If not specified, an HTML <button> element is created.
|
* @param {Element} [options.element=null] Element to use as the button. If not specified, an HTML <div> element is created.
|
||||||
* @param {String} [options.tooltip=null] Provides context help for the button when the
|
* @param {String} [options.tooltip=null] Provides context help for the button when the
|
||||||
* user hovers over it.
|
* user hovers over it.
|
||||||
* @param {String} [options.srcRest=null] URL of image to use in 'rest' state.
|
* @param {String} [options.srcRest=null] URL of image to use in 'rest' state.
|
||||||
@ -120,7 +120,7 @@ $.Button = function( options ) {
|
|||||||
* @member {Element} element
|
* @member {Element} element
|
||||||
* @memberof OpenSeadragon.Button#
|
* @memberof OpenSeadragon.Button#
|
||||||
*/
|
*/
|
||||||
this.element = options.element || $.makeNeutralElement( "div" );
|
this.element = options.element || $.makeNeutralElement("div");
|
||||||
|
|
||||||
//if the user has specified the element to bind the control to explicitly
|
//if the user has specified the element to bind the control to explicitly
|
||||||
//then do not add the default control images
|
//then do not add the default control images
|
||||||
@ -158,7 +158,7 @@ $.Button = function( options ) {
|
|||||||
this.imgDown.style.visibility =
|
this.imgDown.style.visibility =
|
||||||
"hidden";
|
"hidden";
|
||||||
|
|
||||||
if ( $.Browser.vendor == $.BROWSERS.FIREFOX && $.Browser.version < 3 ){
|
if ($.Browser.vendor == $.BROWSERS.FIREFOX && $.Browser.version < 3) {
|
||||||
this.imgGroup.style.top =
|
this.imgGroup.style.top =
|
||||||
this.imgHover.style.top =
|
this.imgHover.style.top =
|
||||||
this.imgDown.style.top =
|
this.imgDown.style.top =
|
||||||
@ -172,13 +172,13 @@ $.Button = function( options ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.addHandler( "press", this.onPress );
|
this.addHandler("press", this.onPress);
|
||||||
this.addHandler( "release", this.onRelease );
|
this.addHandler("release", this.onRelease);
|
||||||
this.addHandler( "click", this.onClick );
|
this.addHandler("click", this.onClick);
|
||||||
this.addHandler( "enter", this.onEnter );
|
this.addHandler("enter", this.onEnter);
|
||||||
this.addHandler( "exit", this.onExit );
|
this.addHandler("exit", this.onExit);
|
||||||
this.addHandler( "focus", this.onFocus );
|
this.addHandler("focus", this.onFocus);
|
||||||
this.addHandler( "blur", this.onBlur );
|
this.addHandler("blur", this.onBlur);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The button's current state.
|
* The button's current state.
|
||||||
|
@ -115,10 +115,10 @@ $.Control = function ( element, options, container ) {
|
|||||||
if ( this.anchor == $.ControlAnchor.ABSOLUTE ) {
|
if ( this.anchor == $.ControlAnchor.ABSOLUTE ) {
|
||||||
this.wrapper = $.makeNeutralElement( "div" );
|
this.wrapper = $.makeNeutralElement( "div" );
|
||||||
this.wrapper.style.position = "absolute";
|
this.wrapper.style.position = "absolute";
|
||||||
this.wrapper.style.top = typeof ( options.top ) == "number" ? ( options.top + 'px' ) : options.top;
|
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.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.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.width = typeof (options.width) == "number" ? (options.width + 'px') : options.width;
|
||||||
this.wrapper.style.margin = "0px";
|
this.wrapper.style.margin = "0px";
|
||||||
this.wrapper.style.padding = "0px";
|
this.wrapper.style.padding = "0px";
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
i;
|
i;
|
||||||
|
|
||||||
$.extend( true, this, {
|
$.extend( true, this, {
|
||||||
id: 'controldock-'+$.now()+'-'+Math.floor(Math.random()*1000000),
|
id: 'controldock-' + $.now() + '-' + Math.floor(Math.random() * 1000000),
|
||||||
container: $.makeNeutralElement( 'div' ),
|
container: $.makeNeutralElement( 'div' ),
|
||||||
controls: []
|
controls: []
|
||||||
}, options );
|
}, options );
|
||||||
|
@ -285,8 +285,8 @@ $.Drawer.prototype = {
|
|||||||
return new $.Rect(
|
return new $.Rect(
|
||||||
topLeft.x * $.pixelDensityRatio,
|
topLeft.x * $.pixelDensityRatio,
|
||||||
topLeft.y * $.pixelDensityRatio,
|
topLeft.y * $.pixelDensityRatio,
|
||||||
size.x * $.pixelDensityRatio,
|
size.x * $.pixelDensityRatio,
|
||||||
size.y * $.pixelDensityRatio
|
size.y * $.pixelDensityRatio
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -328,7 +328,11 @@ $.Drawer.prototype = {
|
|||||||
// the viewport get rotated later on, we will need to resize it.
|
// the viewport get rotated later on, we will need to resize it.
|
||||||
if (this.viewport.getRotation() === 0) {
|
if (this.viewport.getRotation() === 0) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.viewer.addOnceHandler('rotate', function resizeSketchCanvas() {
|
this.viewer.addHandler('rotate', function resizeSketchCanvas() {
|
||||||
|
if (self.viewport.getRotation() === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.viewer.removeHandler('rotate', resizeSketchCanvas);
|
||||||
var sketchCanvasSize = self._calculateSketchCanvasSize();
|
var sketchCanvasSize = self._calculateSketchCanvasSize();
|
||||||
self.sketchCanvas.width = sketchCanvasSize.x;
|
self.sketchCanvas.width = sketchCanvasSize.x;
|
||||||
self.sketchCanvas.height = sketchCanvasSize.y;
|
self.sketchCanvas.height = sketchCanvasSize.y;
|
||||||
@ -470,7 +474,7 @@ $.Drawer.prototype = {
|
|||||||
position.x - widthExt * scale,
|
position.x - widthExt * scale,
|
||||||
position.y - heightExt * scale,
|
position.y - heightExt * scale,
|
||||||
(this.canvas.width + 2 * widthExt) * scale,
|
(this.canvas.width + 2 * widthExt) * scale,
|
||||||
(this.canvas.height + 2 * heightExt) * scale,
|
(this.canvas.height + 2 * heightExt) * scale,
|
||||||
-widthExt,
|
-widthExt,
|
||||||
-heightExt,
|
-heightExt,
|
||||||
this.canvas.width + 2 * widthExt,
|
this.canvas.width + 2 * widthExt,
|
||||||
@ -496,9 +500,9 @@ $.Drawer.prototype = {
|
|||||||
if ( this.viewport.degrees !== 0 ) {
|
if ( this.viewport.degrees !== 0 ) {
|
||||||
this._offsetForRotation({degrees: this.viewport.degrees});
|
this._offsetForRotation({degrees: this.viewport.degrees});
|
||||||
}
|
}
|
||||||
if (tiledImage.getRotation() !== 0) {
|
if (tiledImage.getRotation(true) % 360 !== 0) {
|
||||||
this._offsetForRotation({
|
this._offsetForRotation({
|
||||||
degrees: tiledImage.getRotation(),
|
degrees: tiledImage.getRotation(true),
|
||||||
point: tiledImage.viewport.pixelFromPointNoRotate(
|
point: tiledImage.viewport.pixelFromPointNoRotate(
|
||||||
tiledImage._getRotationPoint(true), true)
|
tiledImage._getRotationPoint(true), true)
|
||||||
});
|
});
|
||||||
@ -565,7 +569,7 @@ $.Drawer.prototype = {
|
|||||||
if ( this.viewport.degrees !== 0 ) {
|
if ( this.viewport.degrees !== 0 ) {
|
||||||
this._restoreRotationChanges();
|
this._restoreRotationChanges();
|
||||||
}
|
}
|
||||||
if (tiledImage.getRotation() !== 0) {
|
if (tiledImage.getRotation(true) % 360 !== 0) {
|
||||||
this._restoreRotationChanges();
|
this._restoreRotationChanges();
|
||||||
}
|
}
|
||||||
context.restore();
|
context.restore();
|
||||||
|
@ -140,7 +140,7 @@ $.extend( $.DziTileSource.prototype, $.TileSource.prototype, /** @lends OpenSead
|
|||||||
|
|
||||||
if (url && !options.tilesUrl) {
|
if (url && !options.tilesUrl) {
|
||||||
options.tilesUrl = url.replace(
|
options.tilesUrl = url.replace(
|
||||||
/([^\/]+?)(\.(dzi|xml|js))?\/?(\?.*)?$/, '$1_files/');
|
/([^\/]+?)(\.(dzi|xml|js)?(\?[^\/]*)?)?\/?$/, '$1_files/');
|
||||||
|
|
||||||
if (url.search(/\.(dzi|xml|js)\?/) != -1) {
|
if (url.search(/\.(dzi|xml|js)\?/) != -1) {
|
||||||
options.queryParams = url.match(/\?.*/);
|
options.queryParams = url.match(/\?.*/);
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
*/
|
*/
|
||||||
$.IIIFTileSource = function( options ){
|
$.IIIFTileSource = function( options ){
|
||||||
|
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
|
||||||
$.extend( true, this, options );
|
$.extend( true, this, options );
|
||||||
|
|
||||||
@ -86,7 +87,7 @@ $.IIIFTileSource = function( options ){
|
|||||||
} else if ( canBeTiled(options.profile) ) {
|
} else if ( canBeTiled(options.profile) ) {
|
||||||
// use the largest of tileOptions that is smaller than the short dimension
|
// use the largest of tileOptions that is smaller than the short dimension
|
||||||
var shortDim = Math.min( this.height, this.width ),
|
var shortDim = Math.min( this.height, this.width ),
|
||||||
tileOptions = [256,512,1024],
|
tileOptions = [256, 512, 1024],
|
||||||
smallerTiles = [];
|
smallerTiles = [];
|
||||||
|
|
||||||
for ( var c = 0; c < tileOptions.length; c++ ) {
|
for ( var c = 0; c < tileOptions.length; c++ ) {
|
||||||
@ -393,14 +394,16 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
|
|||||||
*/
|
*/
|
||||||
function constructLevels(options) {
|
function constructLevels(options) {
|
||||||
var levels = [];
|
var levels = [];
|
||||||
for(var i=0; i<options.sizes.length; i++) {
|
for(var i = 0; i < options.sizes.length; i++) {
|
||||||
levels.push({
|
levels.push({
|
||||||
url: options['@id'] + '/full/' + options.sizes[i].width + ',/0/default.jpg',
|
url: options['@id'] + '/full/' + options.sizes[i].width + ',/0/default.jpg',
|
||||||
width: options.sizes[i].width,
|
width: options.sizes[i].width,
|
||||||
height: options.sizes[i].height
|
height: options.sizes[i].height
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return levels.sort(function(a,b){return a.width - b.width;});
|
return levels.sort(function(a, b) {
|
||||||
|
return a.width - b.width;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,15 +32,27 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function( $ ){
|
(function($){
|
||||||
|
|
||||||
// private class
|
/**
|
||||||
function ImageJob ( options ) {
|
* @private
|
||||||
|
* @class ImageJob
|
||||||
|
* @classdesc Handles downloading of a single image.
|
||||||
|
* @param {Object} options - Options for this ImageJob.
|
||||||
|
* @param {String} [options.src] - URL of image to download.
|
||||||
|
* @param {String} [options.loadWithAjax] - Whether to load this image with AJAX.
|
||||||
|
* @param {String} [options.ajaxHeaders] - Headers to add to the image request if using AJAX.
|
||||||
|
* @param {String} [options.crossOriginPolicy] - CORS policy to use for downloads
|
||||||
|
* @param {Function} [options.callback] - Called once image has been downloaded.
|
||||||
|
* @param {Function} [options.abort] - Called when this image job is aborted.
|
||||||
|
* @param {Number} [options.timeout] - The max number of milliseconds that this image job may take to complete.
|
||||||
|
*/
|
||||||
|
function ImageJob (options) {
|
||||||
|
|
||||||
$.extend( true, this, {
|
$.extend(true, this, {
|
||||||
timeout: $.DEFAULT_SETTINGS.timeout,
|
timeout: $.DEFAULT_SETTINGS.timeout,
|
||||||
jobId: null
|
jobId: null
|
||||||
}, options );
|
}, options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image object which will contain downloaded image.
|
* Image object which will contain downloaded image.
|
||||||
@ -52,42 +64,103 @@ function ImageJob ( options ) {
|
|||||||
|
|
||||||
ImageJob.prototype = {
|
ImageJob.prototype = {
|
||||||
errorMsg: null,
|
errorMsg: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the image job.
|
||||||
|
* @method
|
||||||
|
*/
|
||||||
start: function(){
|
start: function(){
|
||||||
var _this = this;
|
var self = this;
|
||||||
|
var selfAbort = this.abort;
|
||||||
|
|
||||||
this.image = new Image();
|
this.image = new Image();
|
||||||
|
|
||||||
if ( this.crossOriginPolicy !== false ) {
|
|
||||||
this.image.crossOrigin = this.crossOriginPolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.image.onload = function(){
|
this.image.onload = function(){
|
||||||
_this.finish( true );
|
self.finish(true);
|
||||||
};
|
};
|
||||||
this.image.onabort = this.image.onerror = function(){
|
this.image.onabort = this.image.onerror = function() {
|
||||||
_this.errorMsg = "Image load aborted";
|
self.errorMsg = "Image load aborted";
|
||||||
_this.finish( false );
|
self.finish(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.jobId = window.setTimeout( function(){
|
this.jobId = window.setTimeout(function(){
|
||||||
_this.errorMsg = "Image load exceeded timeout";
|
self.errorMsg = "Image load exceeded timeout";
|
||||||
_this.finish( false );
|
self.finish(false);
|
||||||
}, this.timeout);
|
}, this.timeout);
|
||||||
|
|
||||||
this.image.src = this.src;
|
// Load the tile with an AJAX request if the loadWithAjax option is
|
||||||
|
// set. Otherwise load the image by setting the source proprety of the image object.
|
||||||
|
if (this.loadWithAjax) {
|
||||||
|
this.request = $.makeAjaxRequest({
|
||||||
|
url: this.src,
|
||||||
|
withCredentials: this.ajaxWithCredentials,
|
||||||
|
headers: this.ajaxHeaders,
|
||||||
|
responseType: "arraybuffer",
|
||||||
|
success: function(request) {
|
||||||
|
var blb;
|
||||||
|
// Make the raw data into a blob.
|
||||||
|
// BlobBuilder fallback adapted from
|
||||||
|
// http://stackoverflow.com/questions/15293694/blob-constructor-browser-compatibility
|
||||||
|
try {
|
||||||
|
blb = new window.Blob([request.response]);
|
||||||
|
} catch (e) {
|
||||||
|
var BlobBuilder = (
|
||||||
|
window.BlobBuilder ||
|
||||||
|
window.WebKitBlobBuilder ||
|
||||||
|
window.MozBlobBuilder ||
|
||||||
|
window.MSBlobBuilder
|
||||||
|
);
|
||||||
|
if (e.name === 'TypeError' && BlobBuilder) {
|
||||||
|
var bb = new BlobBuilder();
|
||||||
|
bb.append(request.response);
|
||||||
|
blb = bb.getBlob();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the blob is empty for some reason consider the image load a failure.
|
||||||
|
if (blb.size === 0) {
|
||||||
|
self.errorMsg = "Empty image response.";
|
||||||
|
self.finish(false);
|
||||||
|
}
|
||||||
|
// Create a URL for the blob data and make it the source of the image object.
|
||||||
|
// This will still trigger Image.onload to indicate a successful tile load.
|
||||||
|
var url = (window.URL || window.webkitURL).createObjectURL(blb);
|
||||||
|
self.image.src = url;
|
||||||
|
},
|
||||||
|
error: function(request) {
|
||||||
|
self.errorMsg = "Image load aborted - XHR error";
|
||||||
|
self.finish(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Provide a function to properly abort the request.
|
||||||
|
this.abort = function() {
|
||||||
|
self.request.abort();
|
||||||
|
|
||||||
|
// Call the existing abort function if available
|
||||||
|
if (typeof selfAbort === "function") {
|
||||||
|
selfAbort();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
if (this.crossOriginPolicy !== false) {
|
||||||
|
this.image.crossOrigin = this.crossOriginPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.image.src = this.src;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
finish: function( successful ) {
|
finish: function(successful) {
|
||||||
this.image.onload = this.image.onerror = this.image.onabort = null;
|
this.image.onload = this.image.onerror = this.image.onabort = null;
|
||||||
if (!successful) {
|
if (!successful) {
|
||||||
this.image = null;
|
this.image = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( this.jobId ) {
|
if (this.jobId) {
|
||||||
window.clearTimeout( this.jobId );
|
window.clearTimeout(this.jobId);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.callback( this );
|
this.callback(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -99,14 +172,16 @@ ImageJob.prototype = {
|
|||||||
* You generally won't have to interact with the ImageLoader directly.
|
* You generally won't have to interact with the ImageLoader directly.
|
||||||
* @param {Object} options - Options for this ImageLoader.
|
* @param {Object} options - Options for this ImageLoader.
|
||||||
* @param {Number} [options.jobLimit] - The number of concurrent image requests. See imageLoaderLimit in {@link OpenSeadragon.Options} for details.
|
* @param {Number} [options.jobLimit] - The number of concurrent image requests. See imageLoaderLimit in {@link OpenSeadragon.Options} for details.
|
||||||
|
* @param {Number} [options.timeout] - The max number of milliseconds that an image job may take to complete.
|
||||||
*/
|
*/
|
||||||
$.ImageLoader = function( options ) {
|
$.ImageLoader = function(options) {
|
||||||
|
|
||||||
$.extend( true, this, {
|
$.extend(true, this, {
|
||||||
jobLimit: $.DEFAULT_SETTINGS.imageLoaderLimit,
|
jobLimit: $.DEFAULT_SETTINGS.imageLoaderLimit,
|
||||||
|
timeout: $.DEFAULT_SETTINGS.timeout,
|
||||||
jobQueue: [],
|
jobQueue: [],
|
||||||
jobsInProgress: 0
|
jobsInProgress: 0
|
||||||
}, options );
|
}, options);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -116,22 +191,32 @@ $.ImageLoader.prototype = {
|
|||||||
/**
|
/**
|
||||||
* Add an unloaded image to the loader queue.
|
* Add an unloaded image to the loader queue.
|
||||||
* @method
|
* @method
|
||||||
* @param {String} src - URL of image to download.
|
* @param {Object} options - Options for this job.
|
||||||
* @param {String} crossOriginPolicy - CORS policy to use for downloads
|
* @param {String} [options.src] - URL of image to download.
|
||||||
* @param {Function} callback - Called once image has been downloaded.
|
* @param {String} [options.loadWithAjax] - Whether to load this image with AJAX.
|
||||||
|
* @param {String} [options.ajaxHeaders] - Headers to add to the image request if using AJAX.
|
||||||
|
* @param {String|Boolean} [options.crossOriginPolicy] - CORS policy to use for downloads
|
||||||
|
* @param {Boolean} [options.ajaxWithCredentials] - Whether to set withCredentials on AJAX
|
||||||
|
* requests.
|
||||||
|
* @param {Function} [options.callback] - Called once image has been downloaded.
|
||||||
|
* @param {Function} [options.abort] - Called when this image job is aborted.
|
||||||
*/
|
*/
|
||||||
addJob: function( options ) {
|
addJob: function(options) {
|
||||||
var _this = this,
|
var _this = this,
|
||||||
complete = function( job ) {
|
complete = function(job) {
|
||||||
completeJob( _this, job, options.callback );
|
completeJob(_this, job, options.callback);
|
||||||
},
|
},
|
||||||
jobOptions = {
|
jobOptions = {
|
||||||
src: options.src,
|
src: options.src,
|
||||||
|
loadWithAjax: options.loadWithAjax,
|
||||||
|
ajaxHeaders: options.loadWithAjax ? options.ajaxHeaders : null,
|
||||||
crossOriginPolicy: options.crossOriginPolicy,
|
crossOriginPolicy: options.crossOriginPolicy,
|
||||||
|
ajaxWithCredentials: options.ajaxWithCredentials,
|
||||||
callback: complete,
|
callback: complete,
|
||||||
abort: options.abort
|
abort: options.abort,
|
||||||
|
timeout: this.timeout
|
||||||
},
|
},
|
||||||
newJob = new ImageJob( jobOptions );
|
newJob = new ImageJob(jobOptions);
|
||||||
|
|
||||||
if ( !this.jobLimit || this.jobsInProgress < this.jobLimit ) {
|
if ( !this.jobLimit || this.jobsInProgress < this.jobLimit ) {
|
||||||
newJob.start();
|
newJob.start();
|
||||||
@ -166,18 +251,18 @@ $.ImageLoader.prototype = {
|
|||||||
* @param job - The ImageJob that has completed.
|
* @param job - The ImageJob that has completed.
|
||||||
* @param callback - Called once cleanup is finished.
|
* @param callback - Called once cleanup is finished.
|
||||||
*/
|
*/
|
||||||
function completeJob( loader, job, callback ) {
|
function completeJob(loader, job, callback) {
|
||||||
var nextJob;
|
var nextJob;
|
||||||
|
|
||||||
loader.jobsInProgress--;
|
loader.jobsInProgress--;
|
||||||
|
|
||||||
if ( (!loader.jobLimit || loader.jobsInProgress < loader.jobLimit) && loader.jobQueue.length > 0) {
|
if ((!loader.jobLimit || loader.jobsInProgress < loader.jobLimit) && loader.jobQueue.length > 0) {
|
||||||
nextJob = loader.jobQueue.shift();
|
nextJob = loader.jobQueue.shift();
|
||||||
nextJob.start();
|
nextJob.start();
|
||||||
loader.jobsInProgress++;
|
loader.jobsInProgress++;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback( job.image, job.errorMsg );
|
callback(job.image, job.errorMsg, job.request);
|
||||||
}
|
}
|
||||||
|
|
||||||
}( OpenSeadragon ));
|
}(OpenSeadragon));
|
||||||
|
@ -217,7 +217,7 @@ function filterFiles( files ){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return filtered.sort(function(a,b){
|
return filtered.sort(function(a, b) {
|
||||||
return a.height - b.height;
|
return a.height - b.height;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -253,7 +253,7 @@ function configureFromXML( tileSource, xmlDoc ){
|
|||||||
for ( i = 0; i < levels.length; i++ ) {
|
for ( i = 0; i < levels.length; i++ ) {
|
||||||
level = levels[ i ];
|
level = levels[ i ];
|
||||||
|
|
||||||
conf.levels .push({
|
conf.levels.push({
|
||||||
url: level.getAttribute( "url" ),
|
url: level.getAttribute( "url" ),
|
||||||
width: parseInt( level.getAttribute( "width" ), 10 ),
|
width: parseInt( level.getAttribute( "width" ), 10 ),
|
||||||
height: parseInt( level.getAttribute( "height" ), 10 )
|
height: parseInt( level.getAttribute( "height" ), 10 )
|
||||||
|
@ -160,6 +160,7 @@
|
|||||||
* @memberof OpenSeadragon.MouseTracker#
|
* @memberof OpenSeadragon.MouseTracker#
|
||||||
*/
|
*/
|
||||||
this.dblClickDistThreshold = options.dblClickDistThreshold || $.DEFAULT_SETTINGS.dblClickDistThreshold;
|
this.dblClickDistThreshold = options.dblClickDistThreshold || $.DEFAULT_SETTINGS.dblClickDistThreshold;
|
||||||
|
/*eslint-disable no-multi-spaces*/
|
||||||
this.userData = options.userData || null;
|
this.userData = options.userData || null;
|
||||||
this.stopDelay = options.stopDelay || 50;
|
this.stopDelay = options.stopDelay || 50;
|
||||||
|
|
||||||
@ -182,6 +183,7 @@
|
|||||||
this.keyHandler = options.keyHandler || null;
|
this.keyHandler = options.keyHandler || null;
|
||||||
this.focusHandler = options.focusHandler || null;
|
this.focusHandler = options.focusHandler || null;
|
||||||
this.blurHandler = options.blurHandler || null;
|
this.blurHandler = options.blurHandler || null;
|
||||||
|
/*eslint-enable no-multi-spaces*/
|
||||||
|
|
||||||
//Store private properties in a scope sealed hash map
|
//Store private properties in a scope sealed hash map
|
||||||
var _this = this;
|
var _this = this;
|
||||||
@ -1370,6 +1372,7 @@
|
|||||||
eventParams = getCaptureEventParams( tracker, $.MouseTracker.havePointerEvents ? 'pointerevent' : pointerType );
|
eventParams = getCaptureEventParams( tracker, $.MouseTracker.havePointerEvents ? 'pointerevent' : pointerType );
|
||||||
// We emulate mouse capture by hanging listeners on the document object.
|
// We emulate mouse capture by hanging listeners on the document object.
|
||||||
// (Note we listen on the capture phase so the captured handlers will get called first)
|
// (Note we listen on the capture phase so the captured handlers will get called first)
|
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
if (isInIframe && canAccessEvents(window.top)) {
|
if (isInIframe && canAccessEvents(window.top)) {
|
||||||
$.addEvent(
|
$.addEvent(
|
||||||
window.top,
|
window.top,
|
||||||
@ -1413,6 +1416,7 @@
|
|||||||
eventParams = getCaptureEventParams( tracker, $.MouseTracker.havePointerEvents ? 'pointerevent' : pointerType );
|
eventParams = getCaptureEventParams( tracker, $.MouseTracker.havePointerEvents ? 'pointerevent' : pointerType );
|
||||||
// We emulate mouse capture by hanging listeners on the document object.
|
// We emulate mouse capture by hanging listeners on the document object.
|
||||||
// (Note we listen on the capture phase so the captured handlers will get called first)
|
// (Note we listen on the capture phase so the captured handlers will get called first)
|
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
if (isInIframe && canAccessEvents(window.top)) {
|
if (isInIframe && canAccessEvents(window.top)) {
|
||||||
$.removeEvent(
|
$.removeEvent(
|
||||||
window.top,
|
window.top,
|
||||||
@ -1703,7 +1707,7 @@
|
|||||||
|
|
||||||
// Calculate deltaY
|
// Calculate deltaY
|
||||||
if ( $.MouseTracker.wheelEventName == "mousewheel" ) {
|
if ( $.MouseTracker.wheelEventName == "mousewheel" ) {
|
||||||
simulatedEvent.deltaY = - 1 / $.DEFAULT_SETTINGS.pixelsPerWheelLine * event.wheelDelta;
|
simulatedEvent.deltaY = -event.wheelDelta / $.DEFAULT_SETTINGS.pixelsPerWheelLine;
|
||||||
} else {
|
} else {
|
||||||
simulatedEvent.deltaY = event.detail;
|
simulatedEvent.deltaY = event.detail;
|
||||||
}
|
}
|
||||||
@ -2207,10 +2211,7 @@
|
|||||||
* @inner
|
* @inner
|
||||||
*/
|
*/
|
||||||
function onTouchCancel( tracker, event ) {
|
function onTouchCancel( tracker, event ) {
|
||||||
var i,
|
var pointsList = tracker.getActivePointersListByType('touch');
|
||||||
touchCount = event.changedTouches.length,
|
|
||||||
gPoints = [],
|
|
||||||
pointsList = tracker.getActivePointersListByType( 'touch' );
|
|
||||||
|
|
||||||
abortTouchContacts( tracker, event, pointsList );
|
abortTouchContacts( tracker, event, pointsList );
|
||||||
}
|
}
|
||||||
@ -2565,8 +2566,7 @@
|
|||||||
* Gesture points associated with the event.
|
* Gesture points associated with the event.
|
||||||
*/
|
*/
|
||||||
function updatePointersExit( tracker, event, gPoints ) {
|
function updatePointersExit( tracker, event, gPoints ) {
|
||||||
var delegate = THIS[ tracker.hash ],
|
var pointsList = tracker.getActivePointersListByType(gPoints[0].type),
|
||||||
pointsList = tracker.getActivePointersListByType( gPoints[ 0 ].type ),
|
|
||||||
i,
|
i,
|
||||||
gPointCount = gPoints.length,
|
gPointCount = gPoints.length,
|
||||||
curGPoint,
|
curGPoint,
|
||||||
@ -2801,7 +2801,6 @@
|
|||||||
var delegate = THIS[ tracker.hash ],
|
var delegate = THIS[ tracker.hash ],
|
||||||
pointsList = tracker.getActivePointersListByType( gPoints[ 0 ].type ),
|
pointsList = tracker.getActivePointersListByType( gPoints[ 0 ].type ),
|
||||||
propagate,
|
propagate,
|
||||||
insideElementReleased,
|
|
||||||
releasePoint,
|
releasePoint,
|
||||||
releaseTime,
|
releaseTime,
|
||||||
i,
|
i,
|
||||||
@ -2866,7 +2865,7 @@
|
|||||||
{
|
{
|
||||||
eventSource: tracker,
|
eventSource: tracker,
|
||||||
pointerType: gPoints[ 0 ].type,
|
pointerType: gPoints[ 0 ].type,
|
||||||
position: getPointRelativeToAbsolute( gPoints[ 0 ].currentPos, tracker.element ),
|
position: getPointRelativeToAbsolute(gPoints[0].currentPos, tracker.element),
|
||||||
button: buttonChanged,
|
button: buttonChanged,
|
||||||
buttons: pointsList.buttons,
|
buttons: pointsList.buttons,
|
||||||
isTouchEvent: gPoints[ 0 ].type === 'touch',
|
isTouchEvent: gPoints[ 0 ].type === 'touch',
|
||||||
@ -3292,4 +3291,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} ( OpenSeadragon ) );
|
}(OpenSeadragon));
|
||||||
|
@ -121,7 +121,7 @@ $.Navigator = function( options ){
|
|||||||
//At some browser magnification levels the display regions lines up correctly, but at some there appears to
|
//At some browser magnification levels the display regions lines up correctly, but at some there appears to
|
||||||
//be a one pixel gap.
|
//be a one pixel gap.
|
||||||
this.fudge = new $.Point(1, 1);
|
this.fudge = new $.Point(1, 1);
|
||||||
this.totalBorderWidths = new $.Point(this.borderWidth*2, this.borderWidth*2).minus(this.fudge);
|
this.totalBorderWidths = new $.Point(this.borderWidth * 2, this.borderWidth * 2).minus(this.fudge);
|
||||||
|
|
||||||
|
|
||||||
if ( options.controlOptions.anchor != $.ControlAnchor.NONE ) {
|
if ( options.controlOptions.anchor != $.ControlAnchor.NONE ) {
|
||||||
@ -180,8 +180,8 @@ $.Navigator = function( options ){
|
|||||||
|
|
||||||
if ( this._resizeWithViewer ) {
|
if ( this._resizeWithViewer ) {
|
||||||
if ( options.width && options.height ) {
|
if ( options.width && options.height ) {
|
||||||
this.element.style.height = typeof ( options.height ) == "number" ? ( options.height + 'px' ) : 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;
|
this.element.style.width = typeof (options.width) == "number" ? (options.width + 'px') : options.width;
|
||||||
} else {
|
} else {
|
||||||
viewerSize = $.getElementSize( viewer.element );
|
viewerSize = $.getElementSize( viewer.element );
|
||||||
this.element.style.height = Math.round( viewerSize.y * options.sizeRatio ) + 'px';
|
this.element.style.height = Math.round( viewerSize.y * options.sizeRatio ) + 'px';
|
||||||
@ -231,8 +231,10 @@ $.Navigator = function( options ){
|
|||||||
});
|
});
|
||||||
|
|
||||||
viewer.world.addHandler("item-index-change", function(event) {
|
viewer.world.addHandler("item-index-change", function(event) {
|
||||||
var item = _this.world.getItemAt(event.previousIndex);
|
window.setTimeout(function(){
|
||||||
_this.world.setItemIndex(item, event.newIndex);
|
var item = _this.world.getItemAt(event.previousIndex);
|
||||||
|
_this.world.setItemIndex(item, event.newIndex);
|
||||||
|
}, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
viewer.world.addHandler("remove-item", function(event) {
|
viewer.world.addHandler("remove-item", function(event) {
|
||||||
@ -369,9 +371,11 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /*
|
|||||||
|
|
||||||
// private
|
// private
|
||||||
_matchBounds: function(myItem, theirItem, immediately) {
|
_matchBounds: function(myItem, theirItem, immediately) {
|
||||||
var bounds = theirItem.getBounds();
|
var bounds = theirItem.getBoundsNoRotate();
|
||||||
myItem.setPosition(bounds.getTopLeft(), immediately);
|
myItem.setPosition(bounds.getTopLeft(), immediately);
|
||||||
myItem.setWidth(bounds.width, immediately);
|
myItem.setWidth(bounds.width, immediately);
|
||||||
|
myItem.setRotation(theirItem.getRotation(), immediately);
|
||||||
|
myItem.setClip(theirItem.getClip());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -405,6 +409,9 @@ function onCanvasDrag( event ) {
|
|||||||
event.delta
|
event.delta
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
if( this.viewer.constrainDuringPan ){
|
||||||
|
this.viewer.viewport.applyConstraints();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,6 +415,7 @@
|
|||||||
* The max number of images we should keep in memory (per drawer).
|
* The max number of images we should keep in memory (per drawer).
|
||||||
*
|
*
|
||||||
* @property {Number} [timeout=30000]
|
* @property {Number} [timeout=30000]
|
||||||
|
* The max number of milliseconds that an image job may take to complete.
|
||||||
*
|
*
|
||||||
* @property {Boolean} [useCanvas=true]
|
* @property {Boolean} [useCanvas=true]
|
||||||
* Set to false to not use an HTML canvas element for image rendering even if canvas is supported.
|
* Set to false to not use an HTML canvas element for image rendering even if canvas is supported.
|
||||||
@ -588,9 +589,16 @@
|
|||||||
* not use CORS, and the canvas will be tainted.
|
* not use CORS, and the canvas will be tainted.
|
||||||
*
|
*
|
||||||
* @property {Boolean} [ajaxWithCredentials=false]
|
* @property {Boolean} [ajaxWithCredentials=false]
|
||||||
* Whether to set the withCredentials XHR flag for AJAX requests (when loading tile sources).
|
* Whether to set the withCredentials XHR flag for AJAX requests.
|
||||||
* Note that this can be overridden at the {@link OpenSeadragon.TileSource} level.
|
* Note that this can be overridden at the {@link OpenSeadragon.TileSource} level.
|
||||||
*
|
*
|
||||||
|
* @property {Boolean} [loadTilesWithAjax=false]
|
||||||
|
* Whether to load tile data using AJAX requests.
|
||||||
|
* Note that this can be overridden at the {@link OpenSeadragon.TileSource} level.
|
||||||
|
*
|
||||||
|
* @property {Object} [ajaxHeaders={}]
|
||||||
|
* A set of headers to include when making AJAX requests for tile sources or tiles.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -863,7 +871,7 @@ function OpenSeadragon( options ){
|
|||||||
try {
|
try {
|
||||||
// We test if the canvas is tainted by retrieving data from it.
|
// We test if the canvas is tainted by retrieving data from it.
|
||||||
// An exception will be raised if the canvas is tainted.
|
// An exception will be raised if the canvas is tainted.
|
||||||
var data = canvas.getContext('2d').getImageData(0, 0, 1, 1);
|
canvas.getContext('2d').getImageData(0, 0, 1, 1);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
isTainted = true;
|
isTainted = true;
|
||||||
}
|
}
|
||||||
@ -871,7 +879,8 @@ function OpenSeadragon( options ){
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A ratio comparing the device screen's pixel density to the canvas's backing store pixel density. Defaults to 1 if canvas isn't supported by the browser.
|
* A ratio comparing the device screen's pixel density to the canvas's backing store pixel density,
|
||||||
|
* clamped to a minimum of 1. Defaults to 1 if canvas isn't supported by the browser.
|
||||||
* @member {Number} pixelDensityRatio
|
* @member {Number} pixelDensityRatio
|
||||||
* @memberof OpenSeadragon
|
* @memberof OpenSeadragon
|
||||||
*/
|
*/
|
||||||
@ -884,7 +893,7 @@ function OpenSeadragon( options ){
|
|||||||
context.msBackingStorePixelRatio ||
|
context.msBackingStorePixelRatio ||
|
||||||
context.oBackingStorePixelRatio ||
|
context.oBackingStorePixelRatio ||
|
||||||
context.backingStorePixelRatio || 1;
|
context.backingStorePixelRatio || 1;
|
||||||
return devicePixelRatio / backingStoreRatio;
|
return Math.max(devicePixelRatio, 1) / backingStoreRatio;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1009,6 +1018,8 @@ function OpenSeadragon( options ){
|
|||||||
initialPage: 0,
|
initialPage: 0,
|
||||||
crossOriginPolicy: false,
|
crossOriginPolicy: false,
|
||||||
ajaxWithCredentials: false,
|
ajaxWithCredentials: false,
|
||||||
|
loadTilesWithAjax: false,
|
||||||
|
ajaxHeaders: {},
|
||||||
|
|
||||||
//PAN AND ZOOM SETTINGS AND CONSTRAINTS
|
//PAN AND ZOOM SETTINGS AND CONSTRAINTS
|
||||||
panHorizontal: true,
|
panHorizontal: true,
|
||||||
@ -1030,10 +1041,46 @@ function OpenSeadragon( options ){
|
|||||||
dblClickDistThreshold: 20,
|
dblClickDistThreshold: 20,
|
||||||
springStiffness: 6.5,
|
springStiffness: 6.5,
|
||||||
animationTime: 1.2,
|
animationTime: 1.2,
|
||||||
gestureSettingsMouse: { scrollToZoom: true, clickToZoom: true, dblClickToZoom: false, pinchToZoom: false, flickEnabled: false, flickMinSpeed: 120, flickMomentum: 0.25, pinchRotate: false },
|
gestureSettingsMouse: {
|
||||||
gestureSettingsTouch: { scrollToZoom: false, clickToZoom: false, dblClickToZoom: true, pinchToZoom: true, flickEnabled: true, flickMinSpeed: 120, flickMomentum: 0.25, pinchRotate: false },
|
scrollToZoom: true,
|
||||||
gestureSettingsPen: { scrollToZoom: false, clickToZoom: true, dblClickToZoom: false, pinchToZoom: false, flickEnabled: false, flickMinSpeed: 120, flickMomentum: 0.25, pinchRotate: false },
|
clickToZoom: true,
|
||||||
gestureSettingsUnknown: { scrollToZoom: false, clickToZoom: false, dblClickToZoom: true, pinchToZoom: true, flickEnabled: true, flickMinSpeed: 120, flickMomentum: 0.25, pinchRotate: false },
|
dblClickToZoom: false,
|
||||||
|
pinchToZoom: false,
|
||||||
|
flickEnabled: false,
|
||||||
|
flickMinSpeed: 120,
|
||||||
|
flickMomentum: 0.25,
|
||||||
|
pinchRotate: false
|
||||||
|
},
|
||||||
|
gestureSettingsTouch: {
|
||||||
|
scrollToZoom: false,
|
||||||
|
clickToZoom: false,
|
||||||
|
dblClickToZoom: true,
|
||||||
|
pinchToZoom: true,
|
||||||
|
flickEnabled: true,
|
||||||
|
flickMinSpeed: 120,
|
||||||
|
flickMomentum: 0.25,
|
||||||
|
pinchRotate: false
|
||||||
|
},
|
||||||
|
gestureSettingsPen: {
|
||||||
|
scrollToZoom: false,
|
||||||
|
clickToZoom: true,
|
||||||
|
dblClickToZoom: false,
|
||||||
|
pinchToZoom: false,
|
||||||
|
flickEnabled: false,
|
||||||
|
flickMinSpeed: 120,
|
||||||
|
flickMomentum: 0.25,
|
||||||
|
pinchRotate: false
|
||||||
|
},
|
||||||
|
gestureSettingsUnknown: {
|
||||||
|
scrollToZoom: false,
|
||||||
|
clickToZoom: false,
|
||||||
|
dblClickToZoom: true,
|
||||||
|
pinchToZoom: true,
|
||||||
|
flickEnabled: true,
|
||||||
|
flickMinSpeed: 120,
|
||||||
|
flickMomentum: 0.25,
|
||||||
|
pinchRotate: false
|
||||||
|
},
|
||||||
zoomPerClick: 2,
|
zoomPerClick: 2,
|
||||||
zoomPerScroll: 1.2,
|
zoomPerScroll: 1.2,
|
||||||
zoomPerSecond: 1.0,
|
zoomPerSecond: 1.0,
|
||||||
@ -1509,7 +1556,7 @@ function OpenSeadragon( options ){
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// We can't reassign the function yet, as there was no scroll.
|
// We can't reassign the function yet, as there was no scroll.
|
||||||
return new $.Point(0,0);
|
return new $.Point(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $.getPageScroll();
|
return $.getPageScroll();
|
||||||
@ -1677,13 +1724,15 @@ function OpenSeadragon( options ){
|
|||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
now: function( ) {
|
now: function( ) {
|
||||||
if (Date.now) {
|
if (Date.now) {
|
||||||
$.now = Date.now;
|
$.now = Date.now;
|
||||||
} else {
|
} else {
|
||||||
$.now = function() { return new Date().getTime(); };
|
$.now = function() {
|
||||||
}
|
return new Date().getTime();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return $.now();
|
return $.now();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -1793,7 +1842,7 @@ function OpenSeadragon( options ){
|
|||||||
addClass: function( element, className ) {
|
addClass: function( element, className ) {
|
||||||
element = $.getElement( element );
|
element = $.getElement( element );
|
||||||
|
|
||||||
if ( ! element.className ) {
|
if (!element.className) {
|
||||||
element.className = className;
|
element.className = className;
|
||||||
} else if ( ( ' ' + element.className + ' ' ).
|
} else if ( ( ' ' + element.className + ' ' ).
|
||||||
indexOf( ' ' + className + ' ' ) === -1 ) {
|
indexOf( ' ' + className + ' ' ) === -1 ) {
|
||||||
@ -2017,6 +2066,7 @@ function OpenSeadragon( options ){
|
|||||||
* @returns {String} The value of the url parameter or null if no param matches.
|
* @returns {String} The value of the url parameter or null if no param matches.
|
||||||
*/
|
*/
|
||||||
getUrlParameter: function( key ) {
|
getUrlParameter: function( key ) {
|
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
var value = URLPARAMS[ key ];
|
var value = URLPARAMS[ key ];
|
||||||
return value ? value : null;
|
return value ? value : null;
|
||||||
},
|
},
|
||||||
@ -2086,11 +2136,16 @@ function OpenSeadragon( options ){
|
|||||||
* @param {String} options.url - the url to request
|
* @param {String} options.url - the url to request
|
||||||
* @param {Function} options.success - a function to call on a successful response
|
* @param {Function} options.success - a function to call on a successful response
|
||||||
* @param {Function} options.error - a function to call on when an error occurs
|
* @param {Function} options.error - a function to call on when an error occurs
|
||||||
|
* @param {Object} options.headers - headers to add to the AJAX request
|
||||||
|
* @param {String} options.responseType - the response type of the the AJAX request
|
||||||
* @param {Boolean} [options.withCredentials=false] - whether to set the XHR's withCredentials
|
* @param {Boolean} [options.withCredentials=false] - whether to set the XHR's withCredentials
|
||||||
* @throws {Error}
|
* @throws {Error}
|
||||||
|
* @returns {XMLHttpRequest}
|
||||||
*/
|
*/
|
||||||
makeAjaxRequest: function( url, onSuccess, onError ) {
|
makeAjaxRequest: function( url, onSuccess, onError ) {
|
||||||
var withCredentials;
|
var withCredentials;
|
||||||
|
var headers;
|
||||||
|
var responseType;
|
||||||
|
|
||||||
// Note that our preferred API is that you pass in a single object; the named
|
// Note that our preferred API is that you pass in a single object; the named
|
||||||
// arguments are for legacy support.
|
// arguments are for legacy support.
|
||||||
@ -2098,6 +2153,8 @@ function OpenSeadragon( options ){
|
|||||||
onSuccess = url.success;
|
onSuccess = url.success;
|
||||||
onError = url.error;
|
onError = url.error;
|
||||||
withCredentials = url.withCredentials;
|
withCredentials = url.withCredentials;
|
||||||
|
headers = url.headers;
|
||||||
|
responseType = url.responseType || null;
|
||||||
url = url.url;
|
url = url.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2113,9 +2170,9 @@ function OpenSeadragon( options ){
|
|||||||
if ( request.readyState == 4 ) {
|
if ( request.readyState == 4 ) {
|
||||||
request.onreadystatechange = function(){};
|
request.onreadystatechange = function(){};
|
||||||
|
|
||||||
// With protocols other than http/https, the status is 200
|
// With protocols other than http/https, a successful request status is in
|
||||||
// on Firefox and 0 on other browsers
|
// the 200's on Firefox and 0 on other browsers
|
||||||
if ( request.status === 200 ||
|
if ( (request.status >= 200 && request.status < 300) ||
|
||||||
( request.status === 0 &&
|
( request.status === 0 &&
|
||||||
protocol !== "http:" &&
|
protocol !== "http:" &&
|
||||||
protocol !== "https:" )) {
|
protocol !== "https:" )) {
|
||||||
@ -2133,11 +2190,23 @@ function OpenSeadragon( options ){
|
|||||||
try {
|
try {
|
||||||
request.open( "GET", url, true );
|
request.open( "GET", url, true );
|
||||||
|
|
||||||
|
if (responseType) {
|
||||||
|
request.responseType = responseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers) {
|
||||||
|
for (var headerName in headers) {
|
||||||
|
if (headers.hasOwnProperty(headerName) && headers[headerName]) {
|
||||||
|
request.setRequestHeader(headerName, headers[headerName]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (withCredentials) {
|
if (withCredentials) {
|
||||||
request.withCredentials = true;
|
request.withCredentials = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
request.send( null );
|
request.send(null);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
var msg = e.message;
|
var msg = e.message;
|
||||||
|
|
||||||
@ -2174,7 +2243,7 @@ function OpenSeadragon( options ){
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
xdr.onerror = function (e) {
|
xdr.onerror = function (e) {
|
||||||
if ( $.isFunction ( onError ) ) {
|
if ($.isFunction(onError)) {
|
||||||
onError({ // Faking an xhr object
|
onError({ // Faking an xhr object
|
||||||
responseText: xdr.responseText,
|
responseText: xdr.responseText,
|
||||||
status: 444, // 444 No Response
|
status: 444, // 444 No Response
|
||||||
@ -2197,6 +2266,8 @@ function OpenSeadragon( options ){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return request;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2337,6 +2408,7 @@ function OpenSeadragon( options ){
|
|||||||
// Should only be used by IE8 in non standards mode
|
// Should only be used by IE8 in non standards mode
|
||||||
$.parseJSON = function(string) {
|
$.parseJSON = function(string) {
|
||||||
/*jshint evil:true*/
|
/*jshint evil:true*/
|
||||||
|
//eslint-disable-next-line no-eval
|
||||||
return eval('(' + string + ')');
|
return eval('(' + string + ')');
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -2352,6 +2424,7 @@ function OpenSeadragon( options ){
|
|||||||
*/
|
*/
|
||||||
imageFormatSupported: function( extension ) {
|
imageFormatSupported: function( extension ) {
|
||||||
extension = extension ? extension : "";
|
extension = extension ? extension : "";
|
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
return !!FILEFORMATS[ extension.toLowerCase() ];
|
return !!FILEFORMATS[ extension.toLowerCase() ];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2388,8 +2461,7 @@ function OpenSeadragon( options ){
|
|||||||
(function() {
|
(function() {
|
||||||
//A small auto-executing routine to determine the browser vendor,
|
//A small auto-executing routine to determine the browser vendor,
|
||||||
//version and supporting feature sets.
|
//version and supporting feature sets.
|
||||||
var app = navigator.appName,
|
var ver = navigator.appVersion,
|
||||||
ver = navigator.appVersion,
|
|
||||||
ua = navigator.userAgent,
|
ua = navigator.userAgent,
|
||||||
regex;
|
regex;
|
||||||
|
|
||||||
@ -2411,7 +2483,7 @@ function OpenSeadragon( options ){
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "Netscape":
|
case "Netscape":
|
||||||
if( !!window.addEventListener ){
|
if (window.addEventListener) {
|
||||||
if ( ua.indexOf( "Firefox" ) >= 0 ) {
|
if ( ua.indexOf( "Firefox" ) >= 0 ) {
|
||||||
$.Browser.vendor = $.BROWSERS.FIREFOX;
|
$.Browser.vendor = $.BROWSERS.FIREFOX;
|
||||||
$.Browser.version = parseFloat(
|
$.Browser.version = parseFloat(
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
* compatibility.
|
* compatibility.
|
||||||
* @member OverlayPlacement
|
* @member OverlayPlacement
|
||||||
* @memberof OpenSeadragon
|
* @memberof OpenSeadragon
|
||||||
|
* @see OpenSeadragon.Placement
|
||||||
* @static
|
* @static
|
||||||
* @readonly
|
* @readonly
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
@ -247,6 +248,8 @@
|
|||||||
element.prevNextSibling = element.nextSibling;
|
element.prevNextSibling = element.nextSibling;
|
||||||
container.appendChild(element);
|
container.appendChild(element);
|
||||||
|
|
||||||
|
// have to set position before calculating size, fix #1116
|
||||||
|
this.style.position = "absolute";
|
||||||
// this.size is used by overlays which don't get scaled in at
|
// this.size is used by overlays which don't get scaled in at
|
||||||
// least one direction when this.checkResize is set to false.
|
// least one direction when this.checkResize is set to false.
|
||||||
this.size = $.getElementSize(element);
|
this.size = $.getElementSize(element);
|
||||||
@ -285,7 +288,6 @@
|
|||||||
style[transformProp] = "";
|
style[transformProp] = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
style.position = "absolute";
|
|
||||||
|
|
||||||
if (style.display !== 'none') {
|
if (style.display !== 'none') {
|
||||||
style.display = 'block';
|
style.display = 'block';
|
||||||
@ -400,7 +402,7 @@
|
|||||||
* @param {OpenSeadragon.Point|OpenSeadragon.Rect|Object} location
|
* @param {OpenSeadragon.Point|OpenSeadragon.Rect|Object} location
|
||||||
* If an object is specified, the options are the same than the constructor
|
* If an object is specified, the options are the same than the constructor
|
||||||
* except for the element which can not be changed.
|
* except for the element which can not be changed.
|
||||||
* @param {OpenSeadragon.Placement} position
|
* @param {OpenSeadragon.Placement} placement
|
||||||
*/
|
*/
|
||||||
update: function(location, placement) {
|
update: function(location, placement) {
|
||||||
var options = $.isPlainObject(location) ? location : {
|
var options = $.isPlainObject(location) ? location : {
|
||||||
|
@ -178,6 +178,7 @@ $.ReferenceStrip = function ( options ) {
|
|||||||
this.panelWidth = ( viewerSize.x * this.sizeRatio ) + 8;
|
this.panelWidth = ( viewerSize.x * this.sizeRatio ) + 8;
|
||||||
this.panelHeight = ( viewerSize.y * this.sizeRatio ) + 8;
|
this.panelHeight = ( viewerSize.y * this.sizeRatio ) + 8;
|
||||||
this.panels = [];
|
this.panels = [];
|
||||||
|
this.miniViewers = {};
|
||||||
|
|
||||||
/*jshint loopfunc:true*/
|
/*jshint loopfunc:true*/
|
||||||
for ( i = 0; i < viewer.tileSources.length; i++ ) {
|
for ( i = 0; i < viewer.tileSources.length; i++ ) {
|
||||||
@ -293,6 +294,12 @@ $.extend( $.ReferenceStrip.prototype, $.EventSource.prototype, $.Viewer.prototyp
|
|||||||
|
|
||||||
// Overrides Viewer.destroy
|
// Overrides Viewer.destroy
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
|
if (this.miniViewers) {
|
||||||
|
for (var key in this.miniViewers) {
|
||||||
|
this.miniViewers[key].destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.element) {
|
if (this.element) {
|
||||||
this.element.parentNode.removeChild(this.element);
|
this.element.parentNode.removeChild(this.element);
|
||||||
}
|
}
|
||||||
@ -463,6 +470,8 @@ function loadPanels( strip, viewerSize, scroll ) {
|
|||||||
miniViewer.displayRegion
|
miniViewer.displayRegion
|
||||||
);
|
);
|
||||||
|
|
||||||
|
strip.miniViewers[element.id] = miniViewer;
|
||||||
|
|
||||||
element.activePanel = true;
|
element.activePanel = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -592,6 +601,4 @@ function onKeyPress( event ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}(OpenSeadragon));
|
||||||
|
|
||||||
} ( OpenSeadragon ) );
|
|
||||||
|
@ -206,6 +206,7 @@ $.Spring.prototype = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
|
* @returns true if the value got updated, false otherwise
|
||||||
*/
|
*/
|
||||||
update: function() {
|
update: function() {
|
||||||
this.current.time = $.now();
|
this.current.time = $.now();
|
||||||
@ -226,14 +227,17 @@ $.Spring.prototype = {
|
|||||||
transform(
|
transform(
|
||||||
this.springStiffness,
|
this.springStiffness,
|
||||||
( this.current.time - this.start.time ) /
|
( this.current.time - this.start.time ) /
|
||||||
( this.target.time - this.start.time )
|
( this.target.time - this.start.time )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
var oldValue = this.current.value;
|
||||||
if (this._exponential) {
|
if (this._exponential) {
|
||||||
this.current.value = Math.exp(currentValue);
|
this.current.value = Math.exp(currentValue);
|
||||||
} else {
|
} else {
|
||||||
this.current.value = currentValue;
|
this.current.value = currentValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return oldValue != this.current.value;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,14 +75,14 @@ $.extend( $, /** @lends OpenSeadragon */{
|
|||||||
container = I18N,
|
container = I18N,
|
||||||
i;
|
i;
|
||||||
|
|
||||||
for ( i = 0; i < props.length-1; i++ ) {
|
for (i = 0; i < props.length - 1; i++) {
|
||||||
// in case not a subproperty
|
// in case not a subproperty
|
||||||
container = container[ props[ i ] ] || {};
|
container = container[ props[ i ] ] || {};
|
||||||
}
|
}
|
||||||
string = container[ props[ i ] ];
|
string = container[ props[ i ] ];
|
||||||
|
|
||||||
if ( typeof( string ) != "string" ) {
|
if ( typeof( string ) != "string" ) {
|
||||||
$.console.debug( "Untranslated source string:", prop );
|
$.console.log( "Untranslated source string:", prop );
|
||||||
string = ""; // FIXME: this breaks gettext()-style convention, which would return source
|
string = ""; // FIXME: this breaks gettext()-style convention, which would return source
|
||||||
}
|
}
|
||||||
|
|
||||||
|
27
src/tile.js
@ -47,8 +47,10 @@
|
|||||||
* @param {String} url The URL of this tile's image.
|
* @param {String} url The URL of this tile's image.
|
||||||
* @param {CanvasRenderingContext2D} context2D The context2D of this tile if it
|
* @param {CanvasRenderingContext2D} context2D The context2D of this tile if it
|
||||||
* is provided directly by the tile source.
|
* is provided directly by the tile source.
|
||||||
|
* @param {Boolean} loadWithAjax Whether this tile image should be loaded with an AJAX request .
|
||||||
|
* @param {Object} ajaxHeaders The headers to send with this tile's AJAX request (if applicable).
|
||||||
*/
|
*/
|
||||||
$.Tile = function(level, x, y, bounds, exists, url, context2D) {
|
$.Tile = function(level, x, y, bounds, exists, url, context2D, loadWithAjax, ajaxHeaders) {
|
||||||
/**
|
/**
|
||||||
* The zoom level this tile belongs to.
|
* The zoom level this tile belongs to.
|
||||||
* @member {Number} level
|
* @member {Number} level
|
||||||
@ -91,6 +93,29 @@ $.Tile = function(level, x, y, bounds, exists, url, context2D) {
|
|||||||
* @memberOf OpenSeadragon.Tile#
|
* @memberOf OpenSeadragon.Tile#
|
||||||
*/
|
*/
|
||||||
this.context2D = context2D;
|
this.context2D = context2D;
|
||||||
|
/**
|
||||||
|
* Whether to load this tile's image with an AJAX request.
|
||||||
|
* @member {Boolean} loadWithAjax
|
||||||
|
* @memberof OpenSeadragon.Tile#
|
||||||
|
*/
|
||||||
|
this.loadWithAjax = loadWithAjax;
|
||||||
|
/**
|
||||||
|
* The headers to be used in requesting this tile's image.
|
||||||
|
* Only used if loadWithAjax is set to true.
|
||||||
|
* @member {Object} ajaxHeaders
|
||||||
|
* @memberof OpenSeadragon.Tile#
|
||||||
|
*/
|
||||||
|
this.ajaxHeaders = ajaxHeaders;
|
||||||
|
/**
|
||||||
|
* The unique cache key for this tile.
|
||||||
|
* @member {String} cacheKey
|
||||||
|
* @memberof OpenSeadragon.Tile#
|
||||||
|
*/
|
||||||
|
if (this.ajaxHeaders) {
|
||||||
|
this.cacheKey = this.url + "+" + JSON.stringify(this.ajaxHeaders);
|
||||||
|
} else {
|
||||||
|
this.cacheKey = this.url;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Is this tile loaded?
|
* Is this tile loaded?
|
||||||
* @member {Boolean} loaded
|
* @member {Boolean} loaded
|
||||||
|
@ -140,6 +140,7 @@ $.TileCache.prototype = {
|
|||||||
* may temporarily surpass that number, but should eventually come back down to the max specified.
|
* may temporarily surpass that number, but should eventually come back down to the max specified.
|
||||||
* @param {Object} options - Tile info.
|
* @param {Object} options - Tile info.
|
||||||
* @param {OpenSeadragon.Tile} options.tile - The tile to cache.
|
* @param {OpenSeadragon.Tile} options.tile - The tile to cache.
|
||||||
|
* @param {String} options.tile.cacheKey - The unique key used to identify this tile in the cache.
|
||||||
* @param {Image} options.image - The image of the tile to cache.
|
* @param {Image} options.image - The image of the tile to cache.
|
||||||
* @param {OpenSeadragon.TiledImage} options.tiledImage - The TiledImage that owns that tile.
|
* @param {OpenSeadragon.TiledImage} options.tiledImage - The TiledImage that owns that tile.
|
||||||
* @param {Number} [options.cutoff=0] - If adding this tile goes over the cache max count, this
|
* @param {Number} [options.cutoff=0] - If adding this tile goes over the cache max count, this
|
||||||
@ -149,16 +150,16 @@ $.TileCache.prototype = {
|
|||||||
cacheTile: function( options ) {
|
cacheTile: function( options ) {
|
||||||
$.console.assert( options, "[TileCache.cacheTile] options is required" );
|
$.console.assert( options, "[TileCache.cacheTile] options is required" );
|
||||||
$.console.assert( options.tile, "[TileCache.cacheTile] options.tile is required" );
|
$.console.assert( options.tile, "[TileCache.cacheTile] options.tile is required" );
|
||||||
$.console.assert( options.tile.url, "[TileCache.cacheTile] options.tile.url is required" );
|
$.console.assert( options.tile.cacheKey, "[TileCache.cacheTile] options.tile.cacheKey is required" );
|
||||||
$.console.assert( options.tiledImage, "[TileCache.cacheTile] options.tiledImage is required" );
|
$.console.assert( options.tiledImage, "[TileCache.cacheTile] options.tiledImage is required" );
|
||||||
|
|
||||||
var cutoff = options.cutoff || 0;
|
var cutoff = options.cutoff || 0;
|
||||||
var insertionIndex = this._tilesLoaded.length;
|
var insertionIndex = this._tilesLoaded.length;
|
||||||
|
|
||||||
var imageRecord = this._imagesLoaded[options.tile.url];
|
var imageRecord = this._imagesLoaded[options.tile.cacheKey];
|
||||||
if (!imageRecord) {
|
if (!imageRecord) {
|
||||||
$.console.assert( options.image, "[TileCache.cacheTile] options.image is required to create an ImageRecord" );
|
$.console.assert( options.image, "[TileCache.cacheTile] options.image is required to create an ImageRecord" );
|
||||||
imageRecord = this._imagesLoaded[options.tile.url] = new ImageRecord({
|
imageRecord = this._imagesLoaded[options.tile.cacheKey] = new ImageRecord({
|
||||||
image: options.image
|
image: options.image
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -232,9 +233,9 @@ $.TileCache.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// private
|
// private
|
||||||
getImageRecord: function(url) {
|
getImageRecord: function(cacheKey) {
|
||||||
$.console.assert(url, '[TileCache.getImageRecord] url is required');
|
$.console.assert(cacheKey, '[TileCache.getImageRecord] cacheKey is required');
|
||||||
return this._imagesLoaded[url];
|
return this._imagesLoaded[cacheKey];
|
||||||
},
|
},
|
||||||
|
|
||||||
// private
|
// private
|
||||||
@ -246,11 +247,11 @@ $.TileCache.prototype = {
|
|||||||
tile.unload();
|
tile.unload();
|
||||||
tile.cacheImageRecord = null;
|
tile.cacheImageRecord = null;
|
||||||
|
|
||||||
var imageRecord = this._imagesLoaded[tile.url];
|
var imageRecord = this._imagesLoaded[tile.cacheKey];
|
||||||
imageRecord.removeTile(tile);
|
imageRecord.removeTile(tile);
|
||||||
if (!imageRecord.getTileCount()) {
|
if (!imageRecord.getTileCount()) {
|
||||||
imageRecord.destroy();
|
imageRecord.destroy();
|
||||||
delete this._imagesLoaded[tile.url];
|
delete this._imagesLoaded[tile.cacheKey];
|
||||||
this._imagesLoadedCount--;
|
this._imagesLoadedCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +76,12 @@
|
|||||||
* @param {Boolean} [options.debugMode] - See {@link OpenSeadragon.Options}.
|
* @param {Boolean} [options.debugMode] - See {@link OpenSeadragon.Options}.
|
||||||
* @param {String|CanvasGradient|CanvasPattern|Function} [options.placeholderFillStyle] - See {@link OpenSeadragon.Options}.
|
* @param {String|CanvasGradient|CanvasPattern|Function} [options.placeholderFillStyle] - See {@link OpenSeadragon.Options}.
|
||||||
* @param {String|Boolean} [options.crossOriginPolicy] - See {@link OpenSeadragon.Options}.
|
* @param {String|Boolean} [options.crossOriginPolicy] - See {@link OpenSeadragon.Options}.
|
||||||
|
* @param {Boolean} [options.ajaxWithCredentials] - See {@link OpenSeadragon.Options}.
|
||||||
|
* @param {Boolean} [options.loadTilesWithAjax]
|
||||||
|
* Whether to load tile data using AJAX requests.
|
||||||
|
* Defaults to the setting in {@link OpenSeadragon.Options}.
|
||||||
|
* @param {Object} [options.ajaxHeaders={}]
|
||||||
|
* A set of headers to include when making tile AJAX requests.
|
||||||
*/
|
*/
|
||||||
$.TiledImage = function( options ) {
|
$.TiledImage = function( options ) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
@ -133,7 +139,7 @@ $.TiledImage = function( options ) {
|
|||||||
var fitBoundsPlacement = options.fitBoundsPlacement || OpenSeadragon.Placement.CENTER;
|
var fitBoundsPlacement = options.fitBoundsPlacement || OpenSeadragon.Placement.CENTER;
|
||||||
delete options.fitBoundsPlacement;
|
delete options.fitBoundsPlacement;
|
||||||
|
|
||||||
this._degrees = $.positiveModulo(options.degrees || 0, 360);
|
var degrees = options.degrees || 0;
|
||||||
delete options.degrees;
|
delete options.degrees;
|
||||||
|
|
||||||
$.extend( true, this, {
|
$.extend( true, this, {
|
||||||
@ -147,6 +153,7 @@ $.TiledImage = function( options ) {
|
|||||||
_midDraw: false, // Is the tiledImage currently updating the viewport?
|
_midDraw: false, // Is the tiledImage currently updating the viewport?
|
||||||
_needsDraw: true, // Does the tiledImage need to update the viewport again?
|
_needsDraw: true, // Does the tiledImage need to update the viewport again?
|
||||||
_hasOpaqueTile: false, // Do we have even one fully opaque tile?
|
_hasOpaqueTile: false, // Do we have even one fully opaque tile?
|
||||||
|
_tilesLoading: 0, // The number of pending tile requests.
|
||||||
//configurable settings
|
//configurable settings
|
||||||
springStiffness: $.DEFAULT_SETTINGS.springStiffness,
|
springStiffness: $.DEFAULT_SETTINGS.springStiffness,
|
||||||
animationTime: $.DEFAULT_SETTINGS.animationTime,
|
animationTime: $.DEFAULT_SETTINGS.animationTime,
|
||||||
@ -161,6 +168,7 @@ $.TiledImage = function( options ) {
|
|||||||
iOSDevice: $.DEFAULT_SETTINGS.iOSDevice,
|
iOSDevice: $.DEFAULT_SETTINGS.iOSDevice,
|
||||||
debugMode: $.DEFAULT_SETTINGS.debugMode,
|
debugMode: $.DEFAULT_SETTINGS.debugMode,
|
||||||
crossOriginPolicy: $.DEFAULT_SETTINGS.crossOriginPolicy,
|
crossOriginPolicy: $.DEFAULT_SETTINGS.crossOriginPolicy,
|
||||||
|
ajaxWithCredentials: $.DEFAULT_SETTINGS.ajaxWithCredentials,
|
||||||
placeholderFillStyle: $.DEFAULT_SETTINGS.placeholderFillStyle,
|
placeholderFillStyle: $.DEFAULT_SETTINGS.placeholderFillStyle,
|
||||||
opacity: $.DEFAULT_SETTINGS.opacity,
|
opacity: $.DEFAULT_SETTINGS.opacity,
|
||||||
preload: $.DEFAULT_SETTINGS.preload,
|
preload: $.DEFAULT_SETTINGS.preload,
|
||||||
@ -190,6 +198,12 @@ $.TiledImage = function( options ) {
|
|||||||
animationTime: this.animationTime
|
animationTime: this.animationTime
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._degreesSpring = new $.Spring({
|
||||||
|
initial: degrees,
|
||||||
|
springStiffness: this.springStiffness,
|
||||||
|
animationTime: this.animationTime
|
||||||
|
});
|
||||||
|
|
||||||
this._updateForScale();
|
this._updateForScale();
|
||||||
|
|
||||||
if (fitBounds) {
|
if (fitBounds) {
|
||||||
@ -273,16 +287,12 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
* @returns {Boolean} Whether the TiledImage animated.
|
* @returns {Boolean} Whether the TiledImage animated.
|
||||||
*/
|
*/
|
||||||
update: function() {
|
update: function() {
|
||||||
var oldX = this._xSpring.current.value;
|
var xUpdated = this._xSpring.update();
|
||||||
var oldY = this._ySpring.current.value;
|
var yUpdated = this._ySpring.update();
|
||||||
var oldScale = this._scaleSpring.current.value;
|
var scaleUpdated = this._scaleSpring.update();
|
||||||
|
var degreesUpdated = this._degreesSpring.update();
|
||||||
|
|
||||||
this._xSpring.update();
|
if (xUpdated || yUpdated || scaleUpdated || degreesUpdated) {
|
||||||
this._ySpring.update();
|
|
||||||
this._scaleSpring.update();
|
|
||||||
|
|
||||||
if (this._xSpring.current.value !== oldX || this._ySpring.current.value !== oldY ||
|
|
||||||
this._scaleSpring.current.value !== oldScale) {
|
|
||||||
this._updateForScale();
|
this._updateForScale();
|
||||||
this._needsDraw = true;
|
this._needsDraw = true;
|
||||||
return true;
|
return true;
|
||||||
@ -317,7 +327,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
*/
|
*/
|
||||||
getBounds: function(current) {
|
getBounds: function(current) {
|
||||||
return this.getBoundsNoRotate(current)
|
return this.getBoundsNoRotate(current)
|
||||||
.rotate(this._degrees, this._getRotationPoint(current));
|
.rotate(this.getRotation(current), this._getRotationPoint(current));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -366,7 +376,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
clip.width,
|
clip.width,
|
||||||
clip.height);
|
clip.height);
|
||||||
}
|
}
|
||||||
return bounds.rotate(this._degrees, this._getRotationPoint(current));
|
return bounds.rotate(this.getRotation(current), this._getRotationPoint(current));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -401,7 +411,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
point = new $.Point(viewerX, viewerY);
|
point = new $.Point(viewerX, viewerY);
|
||||||
}
|
}
|
||||||
|
|
||||||
point = point.rotate(-this._degrees, this._getRotationPoint(current));
|
point = point.rotate(-this.getRotation(current), this._getRotationPoint(current));
|
||||||
return current ?
|
return current ?
|
||||||
this._viewportToImageDelta(
|
this._viewportToImageDelta(
|
||||||
point.x - this._xSpring.current.value,
|
point.x - this._xSpring.current.value,
|
||||||
@ -443,7 +453,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
point.y += this._ySpring.target.value;
|
point.y += this._ySpring.target.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return point.rotate(this._degrees, this._getRotationPoint(current));
|
return point.rotate(this.getRotation(current), this._getRotationPoint(current));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -457,7 +467,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
* @param {Boolean} [current=false] - Pass true to use the current location; false for target location.
|
* @param {Boolean} [current=false] - Pass true to use the current location; false for target location.
|
||||||
* @return {OpenSeadragon.Rect} A rect representing the coordinates in the viewport.
|
* @return {OpenSeadragon.Rect} A rect representing the coordinates in the viewport.
|
||||||
*/
|
*/
|
||||||
imageToViewportRectangle: function( imageX, imageY, pixelWidth, pixelHeight, current ) {
|
imageToViewportRectangle: function(imageX, imageY, pixelWidth, pixelHeight, current) {
|
||||||
var rect = imageX;
|
var rect = imageX;
|
||||||
if (rect instanceof $.Rect) {
|
if (rect instanceof $.Rect) {
|
||||||
//they passed a rect instead of individual components
|
//they passed a rect instead of individual components
|
||||||
@ -474,7 +484,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
coordA.y,
|
coordA.y,
|
||||||
coordB.x,
|
coordB.x,
|
||||||
coordB.y,
|
coordB.y,
|
||||||
rect.degrees + this._degrees
|
rect.degrees + this.getRotation(current)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -506,7 +516,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
coordA.y,
|
coordA.y,
|
||||||
coordB.x,
|
coordB.x,
|
||||||
coordB.y,
|
coordB.y,
|
||||||
rect.degrees - this._degrees
|
rect.degrees - this.getRotation(current)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -559,7 +569,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
// coordinates (x in [0, 1] and y in [0, aspectRatio])
|
// coordinates (x in [0, 1] and y in [0, aspectRatio])
|
||||||
_viewportToTiledImageRectangle: function(rect) {
|
_viewportToTiledImageRectangle: function(rect) {
|
||||||
var scale = this._scaleSpring.current.value;
|
var scale = this._scaleSpring.current.value;
|
||||||
rect = rect.rotate(-this.getRotation(), this._getRotationPoint(true));
|
rect = rect.rotate(-this.getRotation(true), this._getRotationPoint(true));
|
||||||
return new $.Rect(
|
return new $.Rect(
|
||||||
(rect.x - this._xSpring.current.value) / scale,
|
(rect.x - this._xSpring.current.value) / scale,
|
||||||
(rect.y - this._ySpring.current.value) / scale,
|
(rect.y - this._ySpring.current.value) / scale,
|
||||||
@ -581,7 +591,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
viewportToImageZoom: function( viewportZoom ) {
|
viewportToImageZoom: function( viewportZoom ) {
|
||||||
var ratio = this._scaleSpring.current.value *
|
var ratio = this._scaleSpring.current.value *
|
||||||
this.viewport._containerInnerSize.x / this.source.dimensions.x;
|
this.viewport._containerInnerSize.x / this.source.dimensions.x;
|
||||||
return ratio * viewportZoom ;
|
return ratio * viewportZoom;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -788,24 +798,33 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current rotation of this tiled image in degrees.
|
* Get the rotation of this tiled image in degrees.
|
||||||
* @returns {Number} the current rotation of this tiled image in degrees.
|
* @param {Boolean} [current=false] True for current rotation, false for target.
|
||||||
|
* @returns {Number} the rotation of this tiled image in degrees.
|
||||||
*/
|
*/
|
||||||
getRotation: function() {
|
getRotation: function(current) {
|
||||||
return this._degrees;
|
return current ?
|
||||||
|
this._degreesSpring.current.value :
|
||||||
|
this._degreesSpring.target.value;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the current rotation of this tiled image in degrees.
|
* Set the current rotation of this tiled image in degrees.
|
||||||
* @param {Number} degrees the rotation in degrees.
|
* @param {Number} degrees the rotation in degrees.
|
||||||
|
* @param {Boolean} [immediately=false] Whether to animate to the new angle
|
||||||
|
* or rotate immediately.
|
||||||
* @fires OpenSeadragon.TiledImage.event:bounds-change
|
* @fires OpenSeadragon.TiledImage.event:bounds-change
|
||||||
*/
|
*/
|
||||||
setRotation: function(degrees) {
|
setRotation: function(degrees, immediately) {
|
||||||
degrees = $.positiveModulo(degrees, 360);
|
if (this._degreesSpring.target.value === degrees &&
|
||||||
if (this._degrees === degrees) {
|
this._degreesSpring.isAtTargetValue()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._degrees = degrees;
|
if (immediately) {
|
||||||
|
this._degreesSpring.resetTo(degrees);
|
||||||
|
} else {
|
||||||
|
this._degreesSpring.springTo(degrees);
|
||||||
|
}
|
||||||
this._needsDraw = true;
|
this._needsDraw = true;
|
||||||
this._raiseBoundsChange();
|
this._raiseBoundsChange();
|
||||||
},
|
},
|
||||||
@ -915,9 +934,16 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
// private
|
/**
|
||||||
|
* @private
|
||||||
|
* @inner
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
_updateViewport: function() {
|
_updateViewport: function() {
|
||||||
this._needsDraw = false;
|
this._needsDraw = false;
|
||||||
|
this._tilesLoading = 0;
|
||||||
|
|
||||||
// Reset tile's internal drawn state
|
// Reset tile's internal drawn state
|
||||||
while (this.lastDrawn.length > 0) {
|
while (this.lastDrawn.length > 0) {
|
||||||
@ -972,7 +998,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
var targetZeroRatio = viewport.deltaPixelsFromPointsNoRotate(
|
var targetZeroRatio = viewport.deltaPixelsFromPointsNoRotate(
|
||||||
this.source.getPixelRatio(
|
this.source.getPixelRatio(
|
||||||
Math.max(
|
Math.max(
|
||||||
this.source.getClosestLevel(viewport.containerSize) - 1,
|
this.source.getClosestLevel(),
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@ -1014,11 +1040,67 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
this._needsDraw = true;
|
this._needsDraw = true;
|
||||||
this._setFullyLoaded(false);
|
this._setFullyLoaded(false);
|
||||||
} else {
|
} else {
|
||||||
this._setFullyLoaded(true);
|
this._setFullyLoaded(this._tilesLoading === 0);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// private
|
||||||
|
_getCornerTiles: function(level, topLeftBound, bottomRightBound) {
|
||||||
|
var leftX;
|
||||||
|
var rightX;
|
||||||
|
if (this.wrapHorizontal) {
|
||||||
|
leftX = $.positiveModulo(topLeftBound.x, 1);
|
||||||
|
rightX = $.positiveModulo(bottomRightBound.x, 1);
|
||||||
|
} else {
|
||||||
|
leftX = Math.max(0, topLeftBound.x);
|
||||||
|
rightX = Math.min(1, bottomRightBound.x);
|
||||||
|
}
|
||||||
|
var topY;
|
||||||
|
var bottomY;
|
||||||
|
var aspectRatio = 1 / this.source.aspectRatio;
|
||||||
|
if (this.wrapVertical) {
|
||||||
|
topY = $.positiveModulo(topLeftBound.y, aspectRatio);
|
||||||
|
bottomY = $.positiveModulo(bottomRightBound.y, aspectRatio);
|
||||||
|
} else {
|
||||||
|
topY = Math.max(0, topLeftBound.y);
|
||||||
|
bottomY = Math.min(aspectRatio, bottomRightBound.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
var topLeftTile = this.source.getTileAtPoint(level, new $.Point(leftX, topY));
|
||||||
|
var bottomRightTile = this.source.getTileAtPoint(level, new $.Point(rightX, bottomY));
|
||||||
|
var numTiles = this.source.getNumTiles(level);
|
||||||
|
|
||||||
|
if (this.wrapHorizontal) {
|
||||||
|
topLeftTile.x += numTiles.x * Math.floor(topLeftBound.x);
|
||||||
|
bottomRightTile.x += numTiles.x * Math.floor(bottomRightBound.x);
|
||||||
|
}
|
||||||
|
if (this.wrapVertical) {
|
||||||
|
topLeftTile.y += numTiles.y * Math.floor(topLeftBound.y / aspectRatio);
|
||||||
|
bottomRightTile.y += numTiles.y * Math.floor(bottomRightBound.y / aspectRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
topLeft: topLeftTile,
|
||||||
|
bottomRight: bottomRightTile,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @inner
|
||||||
|
* Updates all tiles at a given resolution level.
|
||||||
|
* @param {OpenSeadragon.TiledImage} tiledImage - Which TiledImage is being drawn.
|
||||||
|
* @param {Boolean} haveDrawn
|
||||||
|
* @param {Boolean} drawLevel
|
||||||
|
* @param {Number} level
|
||||||
|
* @param {Number} levelOpacity
|
||||||
|
* @param {Number} levelVisibility
|
||||||
|
* @param {OpenSeadragon.Point} viewportTL - The index of the most top-left visible tile.
|
||||||
|
* @param {OpenSeadragon.Point} viewportBR - The index of the most bottom-right visible tile.
|
||||||
|
* @param {Number} currentTime
|
||||||
|
* @param {OpenSeadragon.Tile} best - The current "best" tile to draw.
|
||||||
|
*/
|
||||||
function updateLevel(tiledImage, haveDrawn, drawLevel, level, levelOpacity,
|
function updateLevel(tiledImage, haveDrawn, drawLevel, level, levelOpacity,
|
||||||
levelVisibility, drawArea, currentTime, best) {
|
levelVisibility, drawArea, currentTime, best) {
|
||||||
|
|
||||||
@ -1059,23 +1141,13 @@ function updateLevel(tiledImage, haveDrawn, drawLevel, level, levelOpacity,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//OK, a new drawing so do your calculations
|
|
||||||
var topLeftTile = tiledImage.source.getTileAtPoint(level, topLeftBound);
|
|
||||||
var bottomRightTile = tiledImage.source.getTileAtPoint(level, bottomRightBound);
|
|
||||||
var numberOfTiles = tiledImage.source.getNumTiles(level);
|
|
||||||
|
|
||||||
resetCoverage(tiledImage.coverage, level);
|
resetCoverage(tiledImage.coverage, level);
|
||||||
|
|
||||||
if (!tiledImage.wrapHorizontal) {
|
//OK, a new drawing so do your calculations
|
||||||
// Adjust for floating point error
|
var cornerTiles = tiledImage._getCornerTiles(level, topLeftBound, bottomRightBound);
|
||||||
topLeftTile.x = Math.max(topLeftTile.x, 0);
|
var topLeftTile = cornerTiles.topLeft;
|
||||||
bottomRightTile.x = Math.min(bottomRightTile.x, numberOfTiles.x - 1);
|
var bottomRightTile = cornerTiles.bottomRight;
|
||||||
}
|
var numberOfTiles = tiledImage.source.getNumTiles(level);
|
||||||
if (!tiledImage.wrapVertical) {
|
|
||||||
// Adjust for floating point error
|
|
||||||
topLeftTile.y = Math.max(topLeftTile.y, 0);
|
|
||||||
bottomRightTile.y = Math.min(bottomRightTile.y, numberOfTiles.y - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
var viewportCenter = tiledImage.viewport.pixelFromPoint(
|
var viewportCenter = tiledImage.viewport.pixelFromPoint(
|
||||||
tiledImage.viewport.getCenter());
|
tiledImage.viewport.getCenter());
|
||||||
@ -1112,11 +1184,29 @@ function updateLevel(tiledImage, haveDrawn, drawLevel, level, levelOpacity,
|
|||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTile( tiledImage, drawLevel, haveDrawn, x, y, level, levelOpacity, levelVisibility, viewportCenter, numberOfTiles, currentTime, best){
|
/**
|
||||||
|
* @private
|
||||||
|
* @inner
|
||||||
|
* Update a single tile at a particular resolution level.
|
||||||
|
* @param {OpenSeadragon.TiledImage} tiledImage - Which TiledImage is being drawn.
|
||||||
|
* @param {Boolean} haveDrawn
|
||||||
|
* @param {Boolean} drawLevel
|
||||||
|
* @param {Number} x
|
||||||
|
* @param {Number} y
|
||||||
|
* @param {Number} level
|
||||||
|
* @param {Number} levelOpacity
|
||||||
|
* @param {Number} levelVisibility
|
||||||
|
* @param {OpenSeadragon.Point} viewportCenter
|
||||||
|
* @param {Number} numberOfTiles
|
||||||
|
* @param {Number} currentTime
|
||||||
|
* @param {OpenSeadragon.Tile} best - The current "best" tile to draw.
|
||||||
|
*/
|
||||||
|
function updateTile( tiledImage, haveDrawn, drawLevel, x, y, level, levelOpacity, levelVisibility, viewportCenter, numberOfTiles, currentTime, best){
|
||||||
|
|
||||||
var tile = getTile(
|
var tile = getTile(
|
||||||
x, y,
|
x, y,
|
||||||
level,
|
level,
|
||||||
|
tiledImage,
|
||||||
tiledImage.source,
|
tiledImage.source,
|
||||||
tiledImage.tilesMatrix,
|
tiledImage.tilesMatrix,
|
||||||
currentTime,
|
currentTime,
|
||||||
@ -1175,7 +1265,7 @@ function updateTile( tiledImage, drawLevel, haveDrawn, x, y, level, levelOpacity
|
|||||||
if (tile.context2D) {
|
if (tile.context2D) {
|
||||||
setTileLoaded(tiledImage, tile);
|
setTileLoaded(tiledImage, tile);
|
||||||
} else {
|
} else {
|
||||||
var imageRecord = tiledImage._tileCache.getImageRecord(tile.url);
|
var imageRecord = tiledImage._tileCache.getImageRecord(tile.cacheKey);
|
||||||
if (imageRecord) {
|
if (imageRecord) {
|
||||||
var image = imageRecord.getImage();
|
var image = imageRecord.getImage();
|
||||||
setTileLoaded(tiledImage, tile, image);
|
setTileLoaded(tiledImage, tile, image);
|
||||||
@ -1198,7 +1288,7 @@ function updateTile( tiledImage, drawLevel, haveDrawn, x, y, level, levelOpacity
|
|||||||
}
|
}
|
||||||
} else if ( tile.loading ) {
|
} else if ( tile.loading ) {
|
||||||
// the tile is already in the download queue
|
// the tile is already in the download queue
|
||||||
// thanks josh1093 for finally translating this typo
|
tiledImage._tilesLoading++;
|
||||||
} else {
|
} else {
|
||||||
best = compareTiles( best, tile );
|
best = compareTiles( best, tile );
|
||||||
}
|
}
|
||||||
@ -1206,12 +1296,39 @@ function updateTile( tiledImage, drawLevel, haveDrawn, x, y, level, levelOpacity
|
|||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTile( x, y, level, tileSource, tilesMatrix, time, numTiles, worldWidth, worldHeight ) {
|
/**
|
||||||
|
* @private
|
||||||
|
* @inner
|
||||||
|
* Obtains a tile at the given location.
|
||||||
|
* @param {Number} x
|
||||||
|
* @param {Number} y
|
||||||
|
* @param {Number} level
|
||||||
|
* @param {OpenSeadragon.TiledImage} tiledImage
|
||||||
|
* @param {OpenSeadragon.TileSource} tileSource
|
||||||
|
* @param {Object} tilesMatrix - A '3d' dictionary [level][x][y] --> Tile.
|
||||||
|
* @param {Number} time
|
||||||
|
* @param {Number} numTiles
|
||||||
|
* @param {Number} worldWidth
|
||||||
|
* @param {Number} worldHeight
|
||||||
|
* @returns {OpenSeadragon.Tile}
|
||||||
|
*/
|
||||||
|
function getTile(
|
||||||
|
x, y,
|
||||||
|
level,
|
||||||
|
tiledImage,
|
||||||
|
tileSource,
|
||||||
|
tilesMatrix,
|
||||||
|
time,
|
||||||
|
numTiles,
|
||||||
|
worldWidth,
|
||||||
|
worldHeight
|
||||||
|
) {
|
||||||
var xMod,
|
var xMod,
|
||||||
yMod,
|
yMod,
|
||||||
bounds,
|
bounds,
|
||||||
exists,
|
exists,
|
||||||
url,
|
url,
|
||||||
|
ajaxHeaders,
|
||||||
context2D,
|
context2D,
|
||||||
tile;
|
tile;
|
||||||
|
|
||||||
@ -1228,6 +1345,18 @@ function getTile( x, y, level, tileSource, tilesMatrix, time, numTiles, worldWid
|
|||||||
bounds = tileSource.getTileBounds( level, xMod, yMod );
|
bounds = tileSource.getTileBounds( level, xMod, yMod );
|
||||||
exists = tileSource.tileExists( level, xMod, yMod );
|
exists = tileSource.tileExists( level, xMod, yMod );
|
||||||
url = tileSource.getTileUrl( level, xMod, yMod );
|
url = tileSource.getTileUrl( level, xMod, yMod );
|
||||||
|
|
||||||
|
// Headers are only applicable if loadTilesWithAjax is set
|
||||||
|
if (tiledImage.loadTilesWithAjax) {
|
||||||
|
ajaxHeaders = tileSource.getTileAjaxHeaders( level, xMod, yMod );
|
||||||
|
// Combine tile AJAX headers with tiled image AJAX headers (if applicable)
|
||||||
|
if ($.isPlainObject(tiledImage.ajaxHeaders)) {
|
||||||
|
ajaxHeaders = $.extend({}, tiledImage.ajaxHeaders, ajaxHeaders);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ajaxHeaders = null;
|
||||||
|
}
|
||||||
|
|
||||||
context2D = tileSource.getContext2D ?
|
context2D = tileSource.getContext2D ?
|
||||||
tileSource.getContext2D(level, xMod, yMod) : undefined;
|
tileSource.getContext2D(level, xMod, yMod) : undefined;
|
||||||
|
|
||||||
@ -1241,7 +1370,9 @@ function getTile( x, y, level, tileSource, tilesMatrix, time, numTiles, worldWid
|
|||||||
bounds,
|
bounds,
|
||||||
exists,
|
exists,
|
||||||
url,
|
url,
|
||||||
context2D
|
context2D,
|
||||||
|
tiledImage.loadTilesWithAjax,
|
||||||
|
ajaxHeaders
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1251,13 +1382,24 @@ function getTile( x, y, level, tileSource, tilesMatrix, time, numTiles, worldWid
|
|||||||
return tile;
|
return tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @inner
|
||||||
|
* Dispatch a job to the ImageLoader to load the Image for a Tile.
|
||||||
|
* @param {OpenSeadragon.TiledImage} tiledImage
|
||||||
|
* @param {OpenSeadragon.Tile} tile
|
||||||
|
* @param {Number} time
|
||||||
|
*/
|
||||||
function loadTile( tiledImage, tile, time ) {
|
function loadTile( tiledImage, tile, time ) {
|
||||||
tile.loading = true;
|
tile.loading = true;
|
||||||
tiledImage._imageLoader.addJob({
|
tiledImage._imageLoader.addJob({
|
||||||
src: tile.url,
|
src: tile.url,
|
||||||
|
loadWithAjax: tile.loadWithAjax,
|
||||||
|
ajaxHeaders: tile.ajaxHeaders,
|
||||||
crossOriginPolicy: tiledImage.crossOriginPolicy,
|
crossOriginPolicy: tiledImage.crossOriginPolicy,
|
||||||
callback: function( image, errorMsg ){
|
ajaxWithCredentials: tiledImage.ajaxWithCredentials,
|
||||||
onTileLoad( tiledImage, tile, time, image, errorMsg );
|
callback: function( image, errorMsg, tileRequest ){
|
||||||
|
onTileLoad( tiledImage, tile, time, image, errorMsg, tileRequest );
|
||||||
},
|
},
|
||||||
abort: function() {
|
abort: function() {
|
||||||
tile.loading = false;
|
tile.loading = false;
|
||||||
@ -1265,7 +1407,18 @@ function loadTile( tiledImage, tile, time ) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTileLoad( tiledImage, tile, time, image, errorMsg ) {
|
/**
|
||||||
|
* @private
|
||||||
|
* @inner
|
||||||
|
* Callback fired when a Tile's Image finished downloading.
|
||||||
|
* @param {OpenSeadragon.TiledImage} tiledImage
|
||||||
|
* @param {OpenSeadragon.Tile} tile
|
||||||
|
* @param {Number} time
|
||||||
|
* @param {Image} image
|
||||||
|
* @param {String} errorMsg
|
||||||
|
* @param {XMLHttpRequest} tileRequest
|
||||||
|
*/
|
||||||
|
function onTileLoad( tiledImage, tile, time, image, errorMsg, tileRequest ) {
|
||||||
if ( !image ) {
|
if ( !image ) {
|
||||||
$.console.log( "Tile %s failed to load: %s - error: %s", tile, tile.url, errorMsg );
|
$.console.log( "Tile %s failed to load: %s - error: %s", tile, tile.url, errorMsg );
|
||||||
/**
|
/**
|
||||||
@ -1278,8 +1431,15 @@ function onTileLoad( tiledImage, tile, time, image, errorMsg ) {
|
|||||||
* @property {OpenSeadragon.TiledImage} tiledImage - The tiled image the tile belongs to.
|
* @property {OpenSeadragon.TiledImage} tiledImage - The tiled image the tile belongs to.
|
||||||
* @property {number} time - The time in milliseconds when the tile load began.
|
* @property {number} time - The time in milliseconds when the tile load began.
|
||||||
* @property {string} message - The error message.
|
* @property {string} message - The error message.
|
||||||
|
* @property {XMLHttpRequest} tileRequest - The XMLHttpRequest used to load the tile if available.
|
||||||
*/
|
*/
|
||||||
tiledImage.viewer.raiseEvent("tile-load-failed", {tile: tile, tiledImage: tiledImage, time: time, message: errorMsg});
|
tiledImage.viewer.raiseEvent("tile-load-failed", {
|
||||||
|
tile: tile,
|
||||||
|
tiledImage: tiledImage,
|
||||||
|
time: time,
|
||||||
|
message: errorMsg,
|
||||||
|
tileRequest: tileRequest
|
||||||
|
});
|
||||||
tile.loading = false;
|
tile.loading = false;
|
||||||
tile.exists = false;
|
tile.exists = false;
|
||||||
return;
|
return;
|
||||||
@ -1294,7 +1454,7 @@ function onTileLoad( tiledImage, tile, time, image, errorMsg ) {
|
|||||||
var finish = function() {
|
var finish = function() {
|
||||||
var cutoff = Math.ceil( Math.log(
|
var cutoff = Math.ceil( Math.log(
|
||||||
tiledImage.source.getTileWidth(tile.level) ) / Math.log( 2 ) );
|
tiledImage.source.getTileWidth(tile.level) ) / Math.log( 2 ) );
|
||||||
setTileLoaded(tiledImage, tile, image, cutoff);
|
setTileLoaded(tiledImage, tile, image, cutoff, tileRequest);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check if we're mid-update; this can happen on IE8 because image load events for
|
// Check if we're mid-update; this can happen on IE8 because image load events for
|
||||||
@ -1307,7 +1467,15 @@ function onTileLoad( tiledImage, tile, time, image, errorMsg ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTileLoaded(tiledImage, tile, image, cutoff) {
|
/**
|
||||||
|
* @private
|
||||||
|
* @inner
|
||||||
|
* @param {OpenSeadragon.TiledImage} tiledImage
|
||||||
|
* @param {OpenSeadragon.Tile} tile
|
||||||
|
* @param {Image} image
|
||||||
|
* @param {Number} cutoff
|
||||||
|
*/
|
||||||
|
function setTileLoaded(tiledImage, tile, image, cutoff, tileRequest) {
|
||||||
var increment = 0;
|
var increment = 0;
|
||||||
|
|
||||||
function getCompletionCallback() {
|
function getCompletionCallback() {
|
||||||
@ -1342,6 +1510,7 @@ function setTileLoaded(tiledImage, tile, image, cutoff) {
|
|||||||
* @property {Image} image - The image of the tile.
|
* @property {Image} image - The image of the tile.
|
||||||
* @property {OpenSeadragon.TiledImage} tiledImage - The tiled image of the loaded tile.
|
* @property {OpenSeadragon.TiledImage} tiledImage - The tiled image of the loaded tile.
|
||||||
* @property {OpenSeadragon.Tile} tile - The tile which has been loaded.
|
* @property {OpenSeadragon.Tile} tile - The tile which has been loaded.
|
||||||
|
* @property {XMLHttpRequest} tiledImage - The AJAX request that loaded this tile (if applicable).
|
||||||
* @property {function} getCompletionCallback - A function giving a callback to call
|
* @property {function} getCompletionCallback - A function giving a callback to call
|
||||||
* when the asynchronous processing of the image is done. The image will be
|
* when the asynchronous processing of the image is done. The image will be
|
||||||
* marked as entirely loaded when the callback has been called once for each
|
* marked as entirely loaded when the callback has been called once for each
|
||||||
@ -1350,6 +1519,7 @@ function setTileLoaded(tiledImage, tile, image, cutoff) {
|
|||||||
tiledImage.viewer.raiseEvent("tile-loaded", {
|
tiledImage.viewer.raiseEvent("tile-loaded", {
|
||||||
tile: tile,
|
tile: tile,
|
||||||
tiledImage: tiledImage,
|
tiledImage: tiledImage,
|
||||||
|
tileRequest: tileRequest,
|
||||||
image: image,
|
image: image,
|
||||||
getCompletionCallback: getCompletionCallback
|
getCompletionCallback: getCompletionCallback
|
||||||
});
|
});
|
||||||
@ -1357,6 +1527,16 @@ function setTileLoaded(tiledImage, tile, image, cutoff) {
|
|||||||
getCompletionCallback()();
|
getCompletionCallback()();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @inner
|
||||||
|
* @param {OpenSeadragon.Tile} tile
|
||||||
|
* @param {Boolean} overlap
|
||||||
|
* @param {OpenSeadragon.Viewport} viewport
|
||||||
|
* @param {OpenSeadragon.Point} viewportCenter
|
||||||
|
* @param {Number} levelVisibility
|
||||||
|
* @param {OpenSeadragon.TiledImage} tiledImage
|
||||||
|
*/
|
||||||
function positionTile( tile, overlap, viewport, viewportCenter, levelVisibility, tiledImage ){
|
function positionTile( tile, overlap, viewport, viewportCenter, levelVisibility, tiledImage ){
|
||||||
var boundsTL = tile.bounds.getTopLeft();
|
var boundsTL = tile.bounds.getTopLeft();
|
||||||
|
|
||||||
@ -1387,7 +1567,23 @@ function positionTile( tile, overlap, viewport, viewportCenter, levelVisibility,
|
|||||||
tile.visibility = levelVisibility;
|
tile.visibility = levelVisibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @inner
|
||||||
|
* Updates the opacity of a tile according to the time it has been on screen
|
||||||
|
* to perform a fade-in.
|
||||||
|
* Updates coverage once a tile is fully opaque.
|
||||||
|
* Returns whether the fade-in has completed.
|
||||||
|
*
|
||||||
|
* @param {OpenSeadragon.TiledImage} tiledImage
|
||||||
|
* @param {OpenSeadragon.Tile} tile
|
||||||
|
* @param {Number} x
|
||||||
|
* @param {Number} y
|
||||||
|
* @param {Number} level
|
||||||
|
* @param {Number} levelOpacity
|
||||||
|
* @param {Number} currentTime
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
function blendTile( tiledImage, tile, x, y, level, levelOpacity, currentTime ){
|
function blendTile( tiledImage, tile, x, y, level, levelOpacity, currentTime ){
|
||||||
var blendTimeMillis = 1000 * tiledImage.blendTime,
|
var blendTimeMillis = 1000 * tiledImage.blendTime,
|
||||||
deltaTime,
|
deltaTime,
|
||||||
@ -1428,6 +1624,12 @@ function blendTile( tiledImage, tile, x, y, level, levelOpacity, currentTime ){
|
|||||||
* Note that out-of-bounds tiles provide coverage in this sense, since
|
* Note that out-of-bounds tiles provide coverage in this sense, since
|
||||||
* there's no content that they would need to cover. Tiles at non-existent
|
* there's no content that they would need to cover. Tiles at non-existent
|
||||||
* levels that are within the image bounds, however, do not.
|
* levels that are within the image bounds, however, do not.
|
||||||
|
*
|
||||||
|
* @param {Object} coverage - A '3d' dictionary [level][x][y] --> Boolean.
|
||||||
|
* @param {Number} level - The resolution level of the tile.
|
||||||
|
* @param {Number} x - The X position of the tile.
|
||||||
|
* @param {Number} y - The Y position of the tile.
|
||||||
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
function providesCoverage( coverage, level, x, y ) {
|
function providesCoverage( coverage, level, x, y ) {
|
||||||
var rows,
|
var rows,
|
||||||
@ -1467,6 +1669,12 @@ function providesCoverage( coverage, level, x, y ) {
|
|||||||
* Returns true if the given tile is completely covered by higher-level
|
* Returns true if the given tile is completely covered by higher-level
|
||||||
* tiles of higher resolution representing the same content. If neither x
|
* tiles of higher resolution representing the same content. If neither x
|
||||||
* nor y is given, returns true if the entire visible level is covered.
|
* nor y is given, returns true if the entire visible level is covered.
|
||||||
|
*
|
||||||
|
* @param {Object} coverage - A '3d' dictionary [level][x][y] --> Boolean.
|
||||||
|
* @param {Number} level - The resolution level of the tile.
|
||||||
|
* @param {Number} x - The X position of the tile.
|
||||||
|
* @param {Number} y - The Y position of the tile.
|
||||||
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
function isCovered( coverage, level, x, y ) {
|
function isCovered( coverage, level, x, y ) {
|
||||||
if ( x === undefined || y === undefined ) {
|
if ( x === undefined || y === undefined ) {
|
||||||
@ -1485,6 +1693,12 @@ function isCovered( coverage, level, x, y ) {
|
|||||||
* @private
|
* @private
|
||||||
* @inner
|
* @inner
|
||||||
* Sets whether the given tile provides coverage or not.
|
* Sets whether the given tile provides coverage or not.
|
||||||
|
*
|
||||||
|
* @param {Object} coverage - A '3d' dictionary [level][x][y] --> Boolean.
|
||||||
|
* @param {Number} level - The resolution level of the tile.
|
||||||
|
* @param {Number} x - The X position of the tile.
|
||||||
|
* @param {Number} y - The Y position of the tile.
|
||||||
|
* @param {Boolean} covers - Whether the tile provides coverage.
|
||||||
*/
|
*/
|
||||||
function setCoverage( coverage, level, x, y, covers ) {
|
function setCoverage( coverage, level, x, y, covers ) {
|
||||||
if ( !coverage[ level ] ) {
|
if ( !coverage[ level ] ) {
|
||||||
@ -1508,6 +1722,9 @@ function setCoverage( coverage, level, x, y, covers ) {
|
|||||||
* Resets coverage information for the given level. This should be called
|
* Resets coverage information for the given level. This should be called
|
||||||
* after every draw routine. Note that at the beginning of the next draw
|
* after every draw routine. Note that at the beginning of the next draw
|
||||||
* routine, coverage for every visible tile should be explicitly set.
|
* routine, coverage for every visible tile should be explicitly set.
|
||||||
|
*
|
||||||
|
* @param {Object} coverage - A '3d' dictionary [level][x][y] --> Boolean.
|
||||||
|
* @param {Number} level - The resolution level of tiles to completely reset.
|
||||||
*/
|
*/
|
||||||
function resetCoverage( coverage, level ) {
|
function resetCoverage( coverage, level ) {
|
||||||
coverage[ level ] = {};
|
coverage[ level ] = {};
|
||||||
@ -1518,6 +1735,10 @@ function resetCoverage( coverage, level ) {
|
|||||||
* @inner
|
* @inner
|
||||||
* Determines whether the 'last best' tile for the area is better than the
|
* Determines whether the 'last best' tile for the area is better than the
|
||||||
* tile in question.
|
* tile in question.
|
||||||
|
*
|
||||||
|
* @param {OpenSeadragon.Tile} previousBest
|
||||||
|
* @param {OpenSeadragon.Tile} tile
|
||||||
|
* @returns {OpenSeadragon.Tile} The new best tile.
|
||||||
*/
|
*/
|
||||||
function compareTiles( previousBest, tile ) {
|
function compareTiles( previousBest, tile ) {
|
||||||
if ( !previousBest ) {
|
if ( !previousBest ) {
|
||||||
@ -1535,6 +1756,13 @@ function compareTiles( previousBest, tile ) {
|
|||||||
return previousBest;
|
return previousBest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @inner
|
||||||
|
* Draws a TiledImage.
|
||||||
|
* @param {OpenSeadragon.TiledImage} tiledImage
|
||||||
|
* @param {OpenSeadragon.Tile[]} lastDrawn - An unordered list of Tiles drawn last frame.
|
||||||
|
*/
|
||||||
function drawTiles( tiledImage, lastDrawn ) {
|
function drawTiles( tiledImage, lastDrawn ) {
|
||||||
if (tiledImage.opacity === 0 || lastDrawn.length === 0) {
|
if (tiledImage.opacity === 0 || lastDrawn.length === 0) {
|
||||||
return;
|
return;
|
||||||
@ -1551,9 +1779,12 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|||||||
|
|
||||||
var zoom = tiledImage.viewport.getZoom(true);
|
var zoom = tiledImage.viewport.getZoom(true);
|
||||||
var imageZoom = tiledImage.viewportToImageZoom(zoom);
|
var imageZoom = tiledImage.viewportToImageZoom(zoom);
|
||||||
// TODO: support tile edge smoothing with tiled image rotation.
|
|
||||||
if (imageZoom > tiledImage.smoothTileEdgesMinZoom && !tiledImage.iOSDevice &&
|
if (lastDrawn.length > 1 &&
|
||||||
tiledImage.getRotation() === 0 && $.supportsCanvas) {
|
imageZoom > tiledImage.smoothTileEdgesMinZoom &&
|
||||||
|
!tiledImage.iOSDevice &&
|
||||||
|
tiledImage.getRotation(true) % 360 === 0 && // TODO: support tile edge smoothing with tiled image rotation.
|
||||||
|
$.supportsCanvas) {
|
||||||
// When zoomed in a lot (>100%) the tile edges are visible.
|
// When zoomed in a lot (>100%) the tile edges are visible.
|
||||||
// So we have to composite them at ~100% and scale them up together.
|
// So we have to composite them at ~100% and scale them up together.
|
||||||
// Note: Disabled on iOS devices per default as it causes a native crash
|
// Note: Disabled on iOS devices per default as it causes a native crash
|
||||||
@ -1586,9 +1817,9 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|||||||
useSketch: useSketch
|
useSketch: useSketch
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (tiledImage._degrees !== 0) {
|
if (tiledImage.getRotation(true) % 360 !== 0) {
|
||||||
tiledImage._drawer._offsetForRotation({
|
tiledImage._drawer._offsetForRotation({
|
||||||
degrees: tiledImage._degrees,
|
degrees: tiledImage.getRotation(true),
|
||||||
point: tiledImage.viewport.pixelFromPointNoRotate(
|
point: tiledImage.viewport.pixelFromPointNoRotate(
|
||||||
tiledImage._getRotationPoint(true), true),
|
tiledImage._getRotationPoint(true), true),
|
||||||
useSketch: useSketch
|
useSketch: useSketch
|
||||||
@ -1601,7 +1832,7 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|||||||
tiledImage._drawer.saveContext(useSketch);
|
tiledImage._drawer.saveContext(useSketch);
|
||||||
|
|
||||||
var box = tiledImage.imageToViewportRectangle(tiledImage._clip, true);
|
var box = tiledImage.imageToViewportRectangle(tiledImage._clip, true);
|
||||||
box = box.rotate(-tiledImage._degrees, tiledImage._getRotationPoint());
|
box = box.rotate(-tiledImage.getRotation(true), tiledImage._getRotationPoint(true));
|
||||||
var clipRect = tiledImage._drawer.viewportToDrawerRectangle(box);
|
var clipRect = tiledImage._drawer.viewportToDrawerRectangle(box);
|
||||||
if (sketchScale) {
|
if (sketchScale) {
|
||||||
clipRect = clipRect.times(sketchScale);
|
clipRect = clipRect.times(sketchScale);
|
||||||
@ -1663,7 +1894,7 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!sketchScale) {
|
if (!sketchScale) {
|
||||||
if (tiledImage._degrees !== 0) {
|
if (tiledImage.getRotation(true) % 360 !== 0) {
|
||||||
tiledImage._drawer._restoreRotationChanges(useSketch);
|
tiledImage._drawer._restoreRotationChanges(useSketch);
|
||||||
}
|
}
|
||||||
if (tiledImage.viewport.degrees !== 0) {
|
if (tiledImage.viewport.degrees !== 0) {
|
||||||
@ -1679,9 +1910,9 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|||||||
useSketch: false
|
useSketch: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (tiledImage._degrees !== 0) {
|
if (tiledImage.getRotation(true) % 360 !== 0) {
|
||||||
tiledImage._drawer._offsetForRotation({
|
tiledImage._drawer._offsetForRotation({
|
||||||
degrees: tiledImage._degrees,
|
degrees: tiledImage.getRotation(true),
|
||||||
point: tiledImage.viewport.pixelFromPointNoRotate(
|
point: tiledImage.viewport.pixelFromPointNoRotate(
|
||||||
tiledImage._getRotationPoint(true), true),
|
tiledImage._getRotationPoint(true), true),
|
||||||
useSketch: false
|
useSketch: false
|
||||||
@ -1696,7 +1927,7 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|||||||
bounds: bounds
|
bounds: bounds
|
||||||
});
|
});
|
||||||
if (sketchScale) {
|
if (sketchScale) {
|
||||||
if (tiledImage._degrees !== 0) {
|
if (tiledImage.getRotation(true) % 360 !== 0) {
|
||||||
tiledImage._drawer._restoreRotationChanges(false);
|
tiledImage._drawer._restoreRotationChanges(false);
|
||||||
}
|
}
|
||||||
if (tiledImage.viewport.degrees !== 0) {
|
if (tiledImage.viewport.degrees !== 0) {
|
||||||
@ -1707,6 +1938,13 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|||||||
drawDebugInfo( tiledImage, lastDrawn );
|
drawDebugInfo( tiledImage, lastDrawn );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @inner
|
||||||
|
* Draws special debug information for a TiledImage if in debug mode.
|
||||||
|
* @param {OpenSeadragon.TiledImage} tiledImage
|
||||||
|
* @param {OpenSeadragon.Tile[]} lastDrawn - An unordered list of Tiles drawn last frame.
|
||||||
|
*/
|
||||||
function drawDebugInfo( tiledImage, lastDrawn ) {
|
function drawDebugInfo( tiledImage, lastDrawn ) {
|
||||||
if( tiledImage.debugMode ) {
|
if( tiledImage.debugMode ) {
|
||||||
for ( var i = lastDrawn.length - 1; i >= 0; i-- ) {
|
for ( var i = lastDrawn.length - 1; i >= 0; i-- ) {
|
||||||
|
@ -65,6 +65,8 @@
|
|||||||
* @param {Boolean} [options.ajaxWithCredentials]
|
* @param {Boolean} [options.ajaxWithCredentials]
|
||||||
* If this TileSource needs to make an AJAX call, this specifies whether to set
|
* If this TileSource needs to make an AJAX call, this specifies whether to set
|
||||||
* the XHR's withCredentials (for accessing secure data).
|
* the XHR's withCredentials (for accessing secure data).
|
||||||
|
* @param {Object} [options.ajaxHeaders]
|
||||||
|
* A set of headers to include in AJAX requests.
|
||||||
* @param {Number} [options.width]
|
* @param {Number} [options.width]
|
||||||
* Width of the source image at max resolution in pixels.
|
* Width of the source image at max resolution in pixels.
|
||||||
* @param {Number} [options.height]
|
* @param {Number} [options.height]
|
||||||
@ -187,8 +189,8 @@ $.TileSource = function( width, height, tileSize, tileOverlap, minLevel, maxLeve
|
|||||||
//explicit configuration via positional args in constructor
|
//explicit configuration via positional args in constructor
|
||||||
//or the more idiomatic 'options' object
|
//or the more idiomatic 'options' object
|
||||||
this.ready = true;
|
this.ready = true;
|
||||||
this.aspectRatio = ( options.width && options.height ) ?
|
this.aspectRatio = (options.width && options.height) ?
|
||||||
( options.width / options.height ) : 1;
|
(options.width / options.height) : 1;
|
||||||
this.dimensions = new $.Point( options.width, options.height );
|
this.dimensions = new $.Point( options.width, options.height );
|
||||||
|
|
||||||
if ( this.tileSize ){
|
if ( this.tileSize ){
|
||||||
@ -318,25 +320,20 @@ $.TileSource.prototype = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} level
|
* @returns {Number} The highest level in this tile source that can be contained in a single tile.
|
||||||
*/
|
*/
|
||||||
getClosestLevel: function( rect ) {
|
getClosestLevel: function() {
|
||||||
var i,
|
var i,
|
||||||
tilesPerSide,
|
|
||||||
tiles;
|
tiles;
|
||||||
|
|
||||||
for( i = this.minLevel; i < this.maxLevel; i++ ){
|
for (i = this.minLevel + 1; i <= this.maxLevel; i++){
|
||||||
tiles = this.getNumTiles( i );
|
tiles = this.getNumTiles(i);
|
||||||
tilesPerSide = new $.Point(
|
if (tiles.x > 1 || tiles.y > 1) {
|
||||||
Math.floor( rect.x / this.getTileWidth(i) ),
|
|
||||||
Math.floor( rect.y / this.getTileHeight(i) )
|
|
||||||
);
|
|
||||||
|
|
||||||
if( tiles.x + 1 >= tilesPerSide.x && tiles.y + 1 >= tilesPerSide.y ){
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Math.max( 0, i - 1 );
|
|
||||||
|
return i - 1;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -345,17 +342,25 @@ $.TileSource.prototype = {
|
|||||||
* @param {OpenSeadragon.Point} point
|
* @param {OpenSeadragon.Point} point
|
||||||
*/
|
*/
|
||||||
getTileAtPoint: function(level, point) {
|
getTileAtPoint: function(level, point) {
|
||||||
|
var validPoint = point.x >= 0 && point.x <= 1 &&
|
||||||
|
point.y >= 0 && point.y <= 1 / this.aspectRatio;
|
||||||
|
$.console.assert(validPoint, "[TileSource.getTileAtPoint] must be called with a valid point.");
|
||||||
|
|
||||||
var widthScaled = this.dimensions.x * this.getLevelScale(level);
|
var widthScaled = this.dimensions.x * this.getLevelScale(level);
|
||||||
var pixelX = $.positiveModulo(point.x, 1) * widthScaled;
|
var pixelX = point.x * widthScaled;
|
||||||
var pixelY = $.positiveModulo(point.y, 1 / this.aspectRatio) * widthScaled;
|
var pixelY = point.y * widthScaled;
|
||||||
|
|
||||||
var x = Math.floor(pixelX / this.getTileWidth());
|
var x = Math.floor(pixelX / this.getTileWidth(level));
|
||||||
var y = Math.floor(pixelY / this.getTileHeight());
|
var y = Math.floor(pixelY / this.getTileHeight(level));
|
||||||
|
|
||||||
// Fix for wrapping
|
// When point.x == 1 or point.y == 1 / this.aspectRatio we want to
|
||||||
var numTiles = this.getNumTiles(level);
|
// return the last tile of the row/column
|
||||||
x += numTiles.x * Math.floor(point.x);
|
if (point.x >= 1) {
|
||||||
y += numTiles.y * Math.floor(point.y * this.aspectRatio);
|
x = this.getNumTiles(level).x - 1;
|
||||||
|
}
|
||||||
|
if (point.y >= 1 / this.aspectRatio) {
|
||||||
|
y = this.getNumTiles(level).y - 1;
|
||||||
|
}
|
||||||
|
|
||||||
return new $.Point(x, y);
|
return new $.Point(x, y);
|
||||||
},
|
},
|
||||||
@ -455,7 +460,7 @@ $.TileSource.prototype = {
|
|||||||
//TODO: Its not very flexible to require tile sources to end jsonp
|
//TODO: Its not very flexible to require tile sources to end jsonp
|
||||||
// request for info with a url that ends with '.js' but for
|
// request for info with a url that ends with '.js' but for
|
||||||
// now it's the only way I see to distinguish uniformly.
|
// now it's the only way I see to distinguish uniformly.
|
||||||
callbackName = url.split( '/' ).pop().replace('.js','');
|
callbackName = url.split('/').pop().replace('.js', '');
|
||||||
$.jsonp({
|
$.jsonp({
|
||||||
url: url,
|
url: url,
|
||||||
async: false,
|
async: false,
|
||||||
@ -467,6 +472,7 @@ $.TileSource.prototype = {
|
|||||||
$.makeAjaxRequest( {
|
$.makeAjaxRequest( {
|
||||||
url: url,
|
url: url,
|
||||||
withCredentials: this.ajaxWithCredentials,
|
withCredentials: this.ajaxWithCredentials,
|
||||||
|
headers: this.ajaxHeaders,
|
||||||
success: function( xhr ) {
|
success: function( xhr ) {
|
||||||
var data = processResponse( xhr );
|
var data = processResponse( xhr );
|
||||||
callback( data );
|
callback( data );
|
||||||
@ -551,7 +557,7 @@ $.TileSource.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for retriving the url which will return an image for the
|
* Responsible for retrieving the url which will return an image for the
|
||||||
* region specified by the given x, y, and level components.
|
* region specified by the given x, y, and level components.
|
||||||
* This method is not implemented by this class other than to throw an Error
|
* This method is not implemented by this class other than to throw an Error
|
||||||
* announcing you have to implement it. Because of the variety of tile
|
* announcing you have to implement it. Because of the variety of tile
|
||||||
@ -567,6 +573,23 @@ $.TileSource.prototype = {
|
|||||||
throw new Error( "Method not implemented." );
|
throw new Error( "Method not implemented." );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Responsible for retrieving the headers which will be attached to the image request for the
|
||||||
|
* region specified by the given x, y, and level components.
|
||||||
|
* This option is only relevant if {@link OpenSeadragon.Options}.loadTilesWithAjax is set to true.
|
||||||
|
* The headers returned here will override headers specified at the Viewer or TiledImage level.
|
||||||
|
* Specifying a falsy value for a header will clear its existing value set at the Viewer or
|
||||||
|
* TiledImage level (if any).
|
||||||
|
* @function
|
||||||
|
* @param {Number} level
|
||||||
|
* @param {Number} x
|
||||||
|
* @param {Number} y
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
getTileAjaxHeaders: function( level, x, y ) {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} level
|
* @param {Number} level
|
||||||
@ -575,12 +598,12 @@ $.TileSource.prototype = {
|
|||||||
*/
|
*/
|
||||||
tileExists: function( level, x, y ) {
|
tileExists: function( level, x, y ) {
|
||||||
var numTiles = this.getNumTiles( level );
|
var numTiles = this.getNumTiles( level );
|
||||||
return level >= this.minLevel &&
|
return level >= this.minLevel &&
|
||||||
level <= this.maxLevel &&
|
level <= this.maxLevel &&
|
||||||
x >= 0 &&
|
x >= 0 &&
|
||||||
y >= 0 &&
|
y >= 0 &&
|
||||||
x < numTiles.x &&
|
x < numTiles.x &&
|
||||||
y < numTiles.y;
|
y < numTiles.y;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -621,7 +644,11 @@ function processResponse( xhr ){
|
|||||||
data = xhr.responseText;
|
data = xhr.responseText;
|
||||||
}
|
}
|
||||||
}else if( responseText.match(/\s*[\{\[].*/) ){
|
}else if( responseText.match(/\s*[\{\[].*/) ){
|
||||||
data = $.parseJSON(responseText);
|
try{
|
||||||
|
data = $.parseJSON(responseText);
|
||||||
|
} catch(e){
|
||||||
|
data = responseText;
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
data = responseText;
|
data = responseText;
|
||||||
}
|
}
|
||||||
|
@ -32,11 +32,11 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function( $ ){
|
(function($) {
|
||||||
|
|
||||||
// deprecated
|
// deprecated
|
||||||
$.TileSourceCollection = function( tileSize, tileSources, rows, layout ) {
|
$.TileSourceCollection = function(tileSize, tileSources, rows, layout) {
|
||||||
$.console.error('TileSourceCollection is deprecated; use World instead');
|
$.console.error('TileSourceCollection is deprecated; use World instead');
|
||||||
};
|
};
|
||||||
|
|
||||||
}( OpenSeadragon ));
|
}(OpenSeadragon));
|
||||||
|
@ -83,7 +83,7 @@ $.TmsTileSource = function( width, height, tileSize, tileOverlap, tilesUrl ) {
|
|||||||
} else {
|
} else {
|
||||||
max = bufferedHeight / 256;
|
max = bufferedHeight / 256;
|
||||||
}
|
}
|
||||||
options.maxLevel = Math.ceil(Math.log(max)/Math.log(2)) - 1;
|
options.maxLevel = Math.ceil(Math.log(max) / Math.log(2)) - 1;
|
||||||
options.tileSize = 256;
|
options.tileSize = 256;
|
||||||
options.width = bufferedWidth;
|
options.width = bufferedWidth;
|
||||||
options.height = bufferedHeight;
|
options.height = bufferedHeight;
|
||||||
@ -129,7 +129,7 @@ $.extend( $.TmsTileSource.prototype, $.TileSource.prototype, /** @lends OpenSead
|
|||||||
// Convert from Deep Zoom definition to TMS zoom definition
|
// Convert from Deep Zoom definition to TMS zoom definition
|
||||||
var yTiles = this.getNumTiles( level ).y - 1;
|
var yTiles = this.getNumTiles( level ).y - 1;
|
||||||
|
|
||||||
return this.tilesUrl + level + "/" + x + "/" + (yTiles - y) + ".png";
|
return this.tilesUrl + level + "/" + x + "/" + (yTiles - y) + ".png";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
159
src/viewer.js
@ -96,6 +96,12 @@ $.Viewer = function( options ) {
|
|||||||
//internal state and dom identifiers
|
//internal state and dom identifiers
|
||||||
id: options.id,
|
id: options.id,
|
||||||
hash: options.hash || nextHash++,
|
hash: options.hash || nextHash++,
|
||||||
|
/**
|
||||||
|
* Index for page to be shown first next time open() is called (only used in sequenceMode).
|
||||||
|
* @member {Number} initialPage
|
||||||
|
* @memberof OpenSeadragon.Viewer#
|
||||||
|
*/
|
||||||
|
initialPage: 0,
|
||||||
|
|
||||||
//dom nodes
|
//dom nodes
|
||||||
/**
|
/**
|
||||||
@ -221,7 +227,7 @@ $.Viewer = function( options ) {
|
|||||||
$.ControlDock.call( this, options );
|
$.ControlDock.call( this, options );
|
||||||
|
|
||||||
//Deal with tile sources
|
//Deal with tile sources
|
||||||
if ( this.xmlPath ){
|
if (this.xmlPath) {
|
||||||
//Deprecated option. Now it is preferred to use the tileSources option
|
//Deprecated option. Now it is preferred to use the tileSources option
|
||||||
this.tileSources = [ this.xmlPath ];
|
this.tileSources = [ this.xmlPath ];
|
||||||
}
|
}
|
||||||
@ -268,7 +274,7 @@ $.Viewer = function( options ) {
|
|||||||
|
|
||||||
this.innerTracker = new $.MouseTracker({
|
this.innerTracker = new $.MouseTracker({
|
||||||
element: this.canvas,
|
element: this.canvas,
|
||||||
startDisabled: this.mouseNavEnabled ? false : true,
|
startDisabled: !this.mouseNavEnabled,
|
||||||
clickTimeThreshold: this.clickTimeThreshold,
|
clickTimeThreshold: this.clickTimeThreshold,
|
||||||
clickDistThreshold: this.clickDistThreshold,
|
clickDistThreshold: this.clickDistThreshold,
|
||||||
dblClickTimeThreshold: this.dblClickTimeThreshold,
|
dblClickTimeThreshold: this.dblClickTimeThreshold,
|
||||||
@ -291,7 +297,7 @@ $.Viewer = function( options ) {
|
|||||||
|
|
||||||
this.outerTracker = new $.MouseTracker({
|
this.outerTracker = new $.MouseTracker({
|
||||||
element: this.container,
|
element: this.container,
|
||||||
startDisabled: this.mouseNavEnabled ? false : true,
|
startDisabled: !this.mouseNavEnabled,
|
||||||
clickTimeThreshold: this.clickTimeThreshold,
|
clickTimeThreshold: this.clickTimeThreshold,
|
||||||
clickDistThreshold: this.clickDistThreshold,
|
clickDistThreshold: this.clickDistThreshold,
|
||||||
dblClickTimeThreshold: this.dblClickTimeThreshold,
|
dblClickTimeThreshold: this.dblClickTimeThreshold,
|
||||||
@ -370,7 +376,8 @@ $.Viewer = function( options ) {
|
|||||||
|
|
||||||
// Create the image loader
|
// Create the image loader
|
||||||
this.imageLoader = new $.ImageLoader({
|
this.imageLoader = new $.ImageLoader({
|
||||||
jobLimit: this.imageLoaderLimit
|
jobLimit: this.imageLoaderLimit,
|
||||||
|
timeout: options.timeout
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create the tile cache
|
// Create the tile cache
|
||||||
@ -481,11 +488,13 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|||||||
* except for the index property; images are added in sequence.
|
* except for the index property; images are added in sequence.
|
||||||
* A TileSource specifier is anything you could pass as the tileSource property
|
* A TileSource specifier is anything you could pass as the tileSource property
|
||||||
* of the options parameter for {@link OpenSeadragon.Viewer#addTiledImage}.
|
* of the options parameter for {@link OpenSeadragon.Viewer#addTiledImage}.
|
||||||
|
* @param {Number} initialPage - If sequenceMode is true, display this page initially
|
||||||
|
* for the given tileSources. If specified, will overwrite the Viewer's existing initialPage property.
|
||||||
* @return {OpenSeadragon.Viewer} Chainable.
|
* @return {OpenSeadragon.Viewer} Chainable.
|
||||||
* @fires OpenSeadragon.Viewer.event:open
|
* @fires OpenSeadragon.Viewer.event:open
|
||||||
* @fires OpenSeadragon.Viewer.event:open-failed
|
* @fires OpenSeadragon.Viewer.event:open-failed
|
||||||
*/
|
*/
|
||||||
open: function (tileSources) {
|
open: function (tileSources, initialPage) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
|
|
||||||
this.close();
|
this.close();
|
||||||
@ -500,6 +509,10 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|||||||
this.referenceStrip = null;
|
this.referenceStrip = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof initialPage != 'undefined' && !isNaN(initialPage)) {
|
||||||
|
this.initialPage = initialPage;
|
||||||
|
}
|
||||||
|
|
||||||
this.tileSources = tileSources;
|
this.tileSources = tileSources;
|
||||||
this._sequenceIndex = Math.max(0, Math.min(this.tileSources.length - 1, this.initialPage));
|
this._sequenceIndex = Math.max(0, Math.min(this.tileSources.length - 1, this.initialPage));
|
||||||
if (this.tileSources.length) {
|
if (this.tileSources.length) {
|
||||||
@ -674,7 +687,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|||||||
this.navigator.close();
|
this.navigator.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ! this.preserveOverlays) {
|
if (!this.preserveOverlays) {
|
||||||
this.clearOverlays();
|
this.clearOverlays();
|
||||||
this.overlaysContainer.innerHTML = "";
|
this.overlaysContainer.innerHTML = "";
|
||||||
}
|
}
|
||||||
@ -869,7 +882,6 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|||||||
bodyStyle = body.style,
|
bodyStyle = body.style,
|
||||||
docStyle = document.documentElement.style,
|
docStyle = document.documentElement.style,
|
||||||
_this = this,
|
_this = this,
|
||||||
hash,
|
|
||||||
nodes,
|
nodes,
|
||||||
i;
|
i;
|
||||||
|
|
||||||
@ -1031,9 +1043,9 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|||||||
$.setPageScroll( _this.pageScroll );
|
$.setPageScroll( _this.pageScroll );
|
||||||
var pageScroll = $.getPageScroll();
|
var pageScroll = $.getPageScroll();
|
||||||
restoreScrollCounter++;
|
restoreScrollCounter++;
|
||||||
if ( restoreScrollCounter < 10 &&
|
if (restoreScrollCounter < 10 &&
|
||||||
pageScroll.x !== _this.pageScroll.x ||
|
(pageScroll.x !== _this.pageScroll.x ||
|
||||||
pageScroll.y !== _this.pageScroll.y ) {
|
pageScroll.y !== _this.pageScroll.y)) {
|
||||||
$.requestAnimationFrame( restoreScroll );
|
$.requestAnimationFrame( restoreScroll );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1234,6 +1246,15 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|||||||
* @param {String} [options.compositeOperation] How the image is composited onto other images.
|
* @param {String} [options.compositeOperation] How the image is composited onto other images.
|
||||||
* @param {String} [options.crossOriginPolicy] The crossOriginPolicy for this specific image,
|
* @param {String} [options.crossOriginPolicy] The crossOriginPolicy for this specific image,
|
||||||
* overriding viewer.crossOriginPolicy.
|
* overriding viewer.crossOriginPolicy.
|
||||||
|
* @param {Boolean} [options.ajaxWithCredentials] Whether to set withCredentials on tile AJAX
|
||||||
|
* @param {Boolean} [options.loadTilesWithAjax]
|
||||||
|
* Whether to load tile data using AJAX requests.
|
||||||
|
* Defaults to the setting in {@link OpenSeadragon.Options}.
|
||||||
|
* @param {Object} [options.ajaxHeaders]
|
||||||
|
* A set of headers to include when making tile AJAX requests.
|
||||||
|
* Note that these headers will be merged over any headers specified in {@link OpenSeadragon.Options}.
|
||||||
|
* Specifying a falsy value for a header will clear its existing value set at the Viewer level (if any).
|
||||||
|
* requests.
|
||||||
* @param {Function} [options.success] A function that gets called when the image is
|
* @param {Function} [options.success] A function that gets called when the image is
|
||||||
* successfully added. It's passed the event object which contains a single property:
|
* successfully added. It's passed the event object which contains a single property:
|
||||||
* "item", the resulting TiledImage.
|
* "item", the resulting TiledImage.
|
||||||
@ -1275,6 +1296,17 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|||||||
if (options.crossOriginPolicy === undefined) {
|
if (options.crossOriginPolicy === undefined) {
|
||||||
options.crossOriginPolicy = options.tileSource.crossOriginPolicy !== undefined ? options.tileSource.crossOriginPolicy : this.crossOriginPolicy;
|
options.crossOriginPolicy = options.tileSource.crossOriginPolicy !== undefined ? options.tileSource.crossOriginPolicy : this.crossOriginPolicy;
|
||||||
}
|
}
|
||||||
|
if (options.ajaxWithCredentials === undefined) {
|
||||||
|
options.ajaxWithCredentials = this.ajaxWithCredentials;
|
||||||
|
}
|
||||||
|
if (options.loadTilesWithAjax === undefined) {
|
||||||
|
options.loadTilesWithAjax = this.loadTilesWithAjax;
|
||||||
|
}
|
||||||
|
if (options.ajaxHeaders === undefined || options.ajaxHeaders === null) {
|
||||||
|
options.ajaxHeaders = this.ajaxHeaders;
|
||||||
|
} else if ($.isPlainObject(options.ajaxHeaders) && $.isPlainObject(this.ajaxHeaders)) {
|
||||||
|
options.ajaxHeaders = $.extend({}, this.ajaxHeaders, options.ajaxHeaders);
|
||||||
|
}
|
||||||
|
|
||||||
var myQueueItem = {
|
var myQueueItem = {
|
||||||
options: options
|
options: options
|
||||||
@ -1390,6 +1422,9 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|||||||
smoothTileEdgesMinZoom: _this.smoothTileEdgesMinZoom,
|
smoothTileEdgesMinZoom: _this.smoothTileEdgesMinZoom,
|
||||||
iOSDevice: _this.iOSDevice,
|
iOSDevice: _this.iOSDevice,
|
||||||
crossOriginPolicy: queueItem.options.crossOriginPolicy,
|
crossOriginPolicy: queueItem.options.crossOriginPolicy,
|
||||||
|
ajaxWithCredentials: queueItem.options.ajaxWithCredentials,
|
||||||
|
loadTilesWithAjax: queueItem.options.loadTilesWithAjax,
|
||||||
|
ajaxHeaders: queueItem.options.ajaxHeaders,
|
||||||
debugMode: _this.debugMode
|
debugMode: _this.debugMode
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1531,7 +1566,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|||||||
onNextHandler = $.delegate( this, onNext ),
|
onNextHandler = $.delegate( this, onNext ),
|
||||||
onPreviousHandler = $.delegate( this, onPrevious ),
|
onPreviousHandler = $.delegate( this, onPrevious ),
|
||||||
navImages = this.navImages,
|
navImages = this.navImages,
|
||||||
useGroup = true ;
|
useGroup = true;
|
||||||
|
|
||||||
if( this.showSequenceControl ){
|
if( this.showSequenceControl ){
|
||||||
|
|
||||||
@ -1627,7 +1662,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|||||||
onBlurHandler = $.delegate( this, onBlur ),
|
onBlurHandler = $.delegate( this, onBlur ),
|
||||||
navImages = this.navImages,
|
navImages = this.navImages,
|
||||||
buttons = [],
|
buttons = [],
|
||||||
useGroup = true ;
|
useGroup = true;
|
||||||
|
|
||||||
|
|
||||||
if ( this.showNavigationControl ) {
|
if ( this.showNavigationControl ) {
|
||||||
@ -1998,7 +2033,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|||||||
element = $.getElement( element );
|
element = $.getElement( element );
|
||||||
i = getOverlayIndex( this.currentOverlays, element );
|
i = getOverlayIndex( this.currentOverlays, element );
|
||||||
|
|
||||||
if (i>=0) {
|
if (i >= 0) {
|
||||||
return this.currentOverlays[i];
|
return this.currentOverlays[i];
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@ -2119,6 +2154,7 @@ function _getSafeElemSize (oElement) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
* @private
|
* @private
|
||||||
@ -2134,7 +2170,12 @@ function getTileSourceImplementation( viewer, tileSource, imgOptions, successCal
|
|||||||
tileSource = $.parseXml( tileSource );
|
tileSource = $.parseXml( tileSource );
|
||||||
//json should start with "{" or "[" and end with "}" or "]"
|
//json should start with "{" or "[" and end with "}" or "]"
|
||||||
} else if ( tileSource.match(/^\s*[\{\[].*[\}\]]\s*$/ ) ) {
|
} else if ( tileSource.match(/^\s*[\{\[].*[\}\]]\s*$/ ) ) {
|
||||||
tileSource = $.parseJSON(tileSource);
|
try {
|
||||||
|
var tileSourceJ = $.parseJSON(tileSource);
|
||||||
|
tileSource = tileSourceJ;
|
||||||
|
} catch (e) {
|
||||||
|
//tileSource = tileSource;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2162,6 +2203,7 @@ function getTileSourceImplementation( viewer, tileSource, imgOptions, successCal
|
|||||||
crossOriginPolicy: imgOptions.crossOriginPolicy !== undefined ?
|
crossOriginPolicy: imgOptions.crossOriginPolicy !== undefined ?
|
||||||
imgOptions.crossOriginPolicy : viewer.crossOriginPolicy,
|
imgOptions.crossOriginPolicy : viewer.crossOriginPolicy,
|
||||||
ajaxWithCredentials: viewer.ajaxWithCredentials,
|
ajaxWithCredentials: viewer.ajaxWithCredentials,
|
||||||
|
ajaxHeaders: viewer.ajaxHeaders,
|
||||||
useCanvas: viewer.useCanvas,
|
useCanvas: viewer.useCanvas,
|
||||||
success: function( event ) {
|
success: function( event ) {
|
||||||
successCallback( event.tileSource );
|
successCallback( event.tileSource );
|
||||||
@ -2469,16 +2511,15 @@ function onCanvasClick( event ) {
|
|||||||
this.canvas.focus();
|
this.canvas.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !event.preventDefaultAction && this.viewport && event.quick ) {
|
var canvasClickEventArgs = {
|
||||||
gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
|
tracker: event.eventSource,
|
||||||
if ( gestureSettings.clickToZoom ) {
|
position: event.position,
|
||||||
this.viewport.zoomBy(
|
quick: event.quick,
|
||||||
event.shift ? 1.0 / this.zoomPerClick : this.zoomPerClick,
|
shift: event.shift,
|
||||||
this.viewport.pointFromPixel( event.position, true )
|
originalEvent: event.originalEvent,
|
||||||
);
|
preventDefaultAction: event.preventDefaultAction
|
||||||
this.viewport.applyConstraints();
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Raised when a mouse press/release or touch/remove occurs on the {@link OpenSeadragon.Viewer#canvas} element.
|
* Raised when a mouse press/release or touch/remove occurs on the {@link OpenSeadragon.Viewer#canvas} element.
|
||||||
*
|
*
|
||||||
@ -2491,15 +2532,21 @@ function onCanvasClick( event ) {
|
|||||||
* @property {Boolean} quick - True only if the clickDistThreshold and clickTimeThreshold are both passed. Useful for differentiating between clicks and drags.
|
* @property {Boolean} quick - True only if the clickDistThreshold and clickTimeThreshold are both passed. Useful for differentiating between clicks and drags.
|
||||||
* @property {Boolean} shift - True if the shift key was pressed during this event.
|
* @property {Boolean} shift - True if the shift key was pressed during this event.
|
||||||
* @property {Object} originalEvent - The original DOM event.
|
* @property {Object} originalEvent - The original DOM event.
|
||||||
|
* @property {Boolean} preventDefaultAction - Set to true to prevent default click to zoom behaviour. Default: false.
|
||||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||||
*/
|
*/
|
||||||
this.raiseEvent( 'canvas-click', {
|
this.raiseEvent( 'canvas-click', canvasClickEventArgs);
|
||||||
tracker: event.eventSource,
|
|
||||||
position: event.position,
|
if ( !canvasClickEventArgs.preventDefaultAction && this.viewport && event.quick ) {
|
||||||
quick: event.quick,
|
gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
|
||||||
shift: event.shift,
|
if ( gestureSettings.clickToZoom ) {
|
||||||
originalEvent: event.originalEvent
|
this.viewport.zoomBy(
|
||||||
});
|
event.shift ? 1.0 / this.zoomPerClick : this.zoomPerClick,
|
||||||
|
this.viewport.pointFromPixel( event.position, true )
|
||||||
|
);
|
||||||
|
this.viewport.applyConstraints();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCanvasDblClick( event ) {
|
function onCanvasDblClick( event ) {
|
||||||
@ -2538,20 +2585,16 @@ function onCanvasDblClick( event ) {
|
|||||||
|
|
||||||
function onCanvasDrag( event ) {
|
function onCanvasDrag( event ) {
|
||||||
var gestureSettings;
|
var gestureSettings;
|
||||||
|
var canvasDragEventArgs = {
|
||||||
if ( !event.preventDefaultAction && this.viewport ) {
|
tracker: event.eventSource,
|
||||||
gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
|
position: event.position,
|
||||||
if( !this.panHorizontal ){
|
delta: event.delta,
|
||||||
event.delta.x = 0;
|
speed: event.speed,
|
||||||
}
|
direction: event.direction,
|
||||||
if( !this.panVertical ){
|
shift: event.shift,
|
||||||
event.delta.y = 0;
|
originalEvent: event.originalEvent,
|
||||||
}
|
preventDefaultAction: event.preventDefaultAction
|
||||||
this.viewport.panBy( this.viewport.deltaPointsFromPixels( event.delta.negate() ), gestureSettings.flickEnabled );
|
};
|
||||||
if( this.constrainDuringPan ){
|
|
||||||
this.viewport.applyConstraints();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Raised when a mouse or touch drag operation occurs on the {@link OpenSeadragon.Viewer#canvas} element.
|
* Raised when a mouse or touch drag operation occurs on the {@link OpenSeadragon.Viewer#canvas} element.
|
||||||
*
|
*
|
||||||
@ -2566,17 +2609,25 @@ function onCanvasDrag( event ) {
|
|||||||
* @property {Number} direction - Current computed direction, expressed as an angle counterclockwise relative to the positive X axis (-pi to pi, in radians). Only valid if speed > 0.
|
* @property {Number} direction - Current computed direction, expressed as an angle counterclockwise relative to the positive X axis (-pi to pi, in radians). Only valid if speed > 0.
|
||||||
* @property {Boolean} shift - True if the shift key was pressed during this event.
|
* @property {Boolean} shift - True if the shift key was pressed during this event.
|
||||||
* @property {Object} originalEvent - The original DOM event.
|
* @property {Object} originalEvent - The original DOM event.
|
||||||
|
* @property {Boolean} preventDefaultAction - Set to true to prevent default drag behaviour. Default: false.
|
||||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||||
*/
|
*/
|
||||||
this.raiseEvent( 'canvas-drag', {
|
this.raiseEvent( 'canvas-drag', canvasDragEventArgs);
|
||||||
tracker: event.eventSource,
|
if ( !canvasDragEventArgs.preventDefaultAction && this.viewport ) {
|
||||||
position: event.position,
|
gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
|
||||||
delta: event.delta,
|
if( !this.panHorizontal ){
|
||||||
speed: event.speed,
|
event.delta.x = 0;
|
||||||
direction: event.direction,
|
}
|
||||||
shift: event.shift,
|
if( !this.panVertical ){
|
||||||
originalEvent: event.originalEvent
|
event.delta.y = 0;
|
||||||
});
|
}
|
||||||
|
if( event.delta.x !== 0 || event.delta.y !== 0 ){
|
||||||
|
this.viewport.panBy( this.viewport.deltaPointsFromPixels( event.delta.negate() ), gestureSettings.flickEnabled );
|
||||||
|
if( this.constrainDuringPan ){
|
||||||
|
this.viewport.applyConstraints();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCanvasDragEnd( event ) {
|
function onCanvasDragEnd( event ) {
|
||||||
|
@ -60,11 +60,11 @@ $.Viewport = function( options ) {
|
|||||||
//backward compatibility for positional args while prefering more
|
//backward compatibility for positional args while prefering more
|
||||||
//idiomatic javascript options object as the only argument
|
//idiomatic javascript options object as the only argument
|
||||||
var args = arguments;
|
var args = arguments;
|
||||||
if( args.length && args[ 0 ] instanceof $.Point ){
|
if (args.length && args[0] instanceof $.Point) {
|
||||||
options = {
|
options = {
|
||||||
containerSize: args[ 0 ],
|
containerSize: args[0],
|
||||||
contentSize: args[ 1 ],
|
contentSize: args[1],
|
||||||
config: args[ 2 ]
|
config: args[2]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,7 +805,8 @@ $.Viewport.prototype = {
|
|||||||
* @return {OpenSeadragon.Viewport} Chainable.
|
* @return {OpenSeadragon.Viewport} Chainable.
|
||||||
* @fires OpenSeadragon.Viewer.event:zoom
|
* @fires OpenSeadragon.Viewer.event:zoom
|
||||||
*/
|
*/
|
||||||
zoomTo: function( zoom, refPoint, immediately ) {
|
zoomTo: function(zoom, refPoint, immediately) {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
this.zoomPoint = refPoint instanceof $.Point &&
|
this.zoomPoint = refPoint instanceof $.Point &&
|
||||||
!isNaN(refPoint.x) &&
|
!isNaN(refPoint.x) &&
|
||||||
@ -813,13 +814,15 @@ $.Viewport.prototype = {
|
|||||||
refPoint :
|
refPoint :
|
||||||
null;
|
null;
|
||||||
|
|
||||||
if ( immediately ) {
|
if (immediately) {
|
||||||
this.zoomSpring.resetTo( zoom );
|
this._adjustCenterSpringsForZoomPoint(function() {
|
||||||
|
_this.zoomSpring.resetTo(zoom);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.zoomSpring.springTo( zoom );
|
this.zoomSpring.springTo(zoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( this.viewer ){
|
if (this.viewer) {
|
||||||
/**
|
/**
|
||||||
* Raised when the viewport zoom level changes (see {@link OpenSeadragon.Viewport#zoomBy} and {@link OpenSeadragon.Viewport#zoomTo}).
|
* Raised when the viewport zoom level changes (see {@link OpenSeadragon.Viewport#zoomBy} and {@link OpenSeadragon.Viewport#zoomTo}).
|
||||||
*
|
*
|
||||||
@ -832,7 +835,7 @@ $.Viewport.prototype = {
|
|||||||
* @property {Boolean} immediately
|
* @property {Boolean} immediately
|
||||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||||
*/
|
*/
|
||||||
this.viewer.raiseEvent( 'zoom', {
|
this.viewer.raiseEvent('zoom', {
|
||||||
zoom: zoom,
|
zoom: zoom,
|
||||||
refPoint: refPoint,
|
refPoint: refPoint,
|
||||||
immediately: immediately
|
immediately: immediately
|
||||||
@ -938,25 +941,10 @@ $.Viewport.prototype = {
|
|||||||
* @returns {Boolean} True if any change has been made, false otherwise.
|
* @returns {Boolean} True if any change has been made, false otherwise.
|
||||||
*/
|
*/
|
||||||
update: function() {
|
update: function() {
|
||||||
|
var _this = this;
|
||||||
if (this.zoomPoint) {
|
this._adjustCenterSpringsForZoomPoint(function() {
|
||||||
var oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true);
|
_this.zoomSpring.update();
|
||||||
this.zoomSpring.update();
|
});
|
||||||
var newZoomPixel = this.pixelFromPoint(this.zoomPoint, true);
|
|
||||||
|
|
||||||
var deltaZoomPixels = newZoomPixel.minus(oldZoomPixel);
|
|
||||||
var deltaZoomPoints = this.deltaPointsFromPixels(
|
|
||||||
deltaZoomPixels, true);
|
|
||||||
|
|
||||||
this.centerSpringX.shiftBy(deltaZoomPoints.x);
|
|
||||||
this.centerSpringY.shiftBy(deltaZoomPoints.y);
|
|
||||||
|
|
||||||
if (this.zoomSpring.isAtTargetValue()) {
|
|
||||||
this.zoomPoint = null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.zoomSpring.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.centerSpringX.update();
|
this.centerSpringX.update();
|
||||||
this.centerSpringY.update();
|
this.centerSpringY.update();
|
||||||
@ -972,6 +960,27 @@ $.Viewport.prototype = {
|
|||||||
return changed;
|
return changed;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_adjustCenterSpringsForZoomPoint: function(zoomSpringHandler) {
|
||||||
|
if (this.zoomPoint) {
|
||||||
|
var oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true);
|
||||||
|
zoomSpringHandler();
|
||||||
|
var newZoomPixel = this.pixelFromPoint(this.zoomPoint, true);
|
||||||
|
|
||||||
|
var deltaZoomPixels = newZoomPixel.minus(oldZoomPixel);
|
||||||
|
var deltaZoomPoints = this.deltaPointsFromPixels(
|
||||||
|
deltaZoomPixels, true);
|
||||||
|
|
||||||
|
this.centerSpringX.shiftBy(deltaZoomPoints.x);
|
||||||
|
this.centerSpringY.shiftBy(deltaZoomPoints.y);
|
||||||
|
|
||||||
|
if (this.zoomSpring.isAtTargetValue()) {
|
||||||
|
this.zoomPoint = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
zoomSpringHandler();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a delta (translation vector) from viewport coordinates to pixels
|
* Convert a delta (translation vector) from viewport coordinates to pixels
|
||||||
* coordinates. This method does not take rotation into account.
|
* coordinates. This method does not take rotation into account.
|
||||||
@ -1208,6 +1217,7 @@ $.Viewport.prototype = {
|
|||||||
* in image coordinate system.
|
* in image coordinate system.
|
||||||
* @param {Number} [pixelWidth] the width in pixel of the rectangle.
|
* @param {Number} [pixelWidth] the width in pixel of the rectangle.
|
||||||
* @param {Number} [pixelHeight] the height in pixel of the rectangle.
|
* @param {Number} [pixelHeight] the height in pixel of the rectangle.
|
||||||
|
* @returns {OpenSeadragon.Rect} This image's bounds in viewport coordinates
|
||||||
*/
|
*/
|
||||||
imageToViewportRectangle: function(imageX, imageY, pixelWidth, pixelHeight) {
|
imageToViewportRectangle: function(imageX, imageY, pixelWidth, pixelHeight) {
|
||||||
var rect = imageX;
|
var rect = imageX;
|
||||||
|
@ -212,7 +212,8 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
|||||||
// We need to make sure any pending images are canceled so the world items don't get messed up
|
// We need to make sure any pending images are canceled so the world items don't get messed up
|
||||||
this.viewer._cancelPendingImages();
|
this.viewer._cancelPendingImages();
|
||||||
var item;
|
var item;
|
||||||
for (var i = 0; i < this._items.length; i++) {
|
var i;
|
||||||
|
for (i = 0; i < this._items.length; i++) {
|
||||||
item = this._items[i];
|
item = this._items[i];
|
||||||
item.removeHandler('bounds-change', this._delegatedFigureSizes);
|
item.removeHandler('bounds-change', this._delegatedFigureSizes);
|
||||||
item.removeHandler('clip-change', this._delegatedFigureSizes);
|
item.removeHandler('clip-change', this._delegatedFigureSizes);
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
* tilesUrl: "/test/data/zoomify/"
|
* tilesUrl: "/test/data/zoomify/"
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* The tileSize is currently hardcoded to 256 (the usual Zoomify default). The tileUrl must the the path to the image _directory_.
|
* The tileSize is currently hardcoded to 256 (the usual Zoomify default). The tileUrl must the path to the image _directory_.
|
||||||
*
|
*
|
||||||
* 2) Loading image metadata from xml file: (CURRENTLY NOT SUPPORTED)
|
* 2) Loading image metadata from xml file: (CURRENTLY NOT SUPPORTED)
|
||||||
*
|
*
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
<script src="/src/iiiftilesource.js"></script>
|
<script src="/src/iiiftilesource.js"></script>
|
||||||
<script src="/src/osmtilesource.js"></script>
|
<script src="/src/osmtilesource.js"></script>
|
||||||
<script src="/src/tmstilesource.js"></script>
|
<script src="/src/tmstilesource.js"></script>
|
||||||
|
<script src="/src/zoomifytilesource.js"></script>
|
||||||
<script src="/src/legacytilesource.js"></script>
|
<script src="/src/legacytilesource.js"></script>
|
||||||
<script src="/src/imagetilesource.js"></script>
|
<script src="/src/imagetilesource.js"></script>
|
||||||
<script src="/src/tilesourcecollection.js"></script>
|
<script src="/src/tilesourcecollection.js"></script>
|
||||||
@ -79,6 +80,8 @@
|
|||||||
<script src="/test/modules/tilesourcecollection.js"></script>
|
<script src="/test/modules/tilesourcecollection.js"></script>
|
||||||
<script src="/test/modules/spring.js"></script>
|
<script src="/test/modules/spring.js"></script>
|
||||||
<script src="/test/modules/rectangle.js"></script>
|
<script src="/test/modules/rectangle.js"></script>
|
||||||
|
<script src="/test/modules/ajax-tiles.js"></script>
|
||||||
|
<script src="/test/modules/imageloader.js"></script>
|
||||||
<!-- The navigator tests are the slowest (for now; hopefully they can be sped up)
|
<!-- The navigator tests are the slowest (for now; hopefully they can be sped up)
|
||||||
so we put them last. -->
|
so we put them last. -->
|
||||||
<script src="/test/modules/navigator.js"></script>
|
<script src="/test/modules/navigator.js"></script>
|
||||||
|
BIN
test/data/testpattern.blob
Normal file
After Width: | Height: | Size: 508 KiB |
75
test/demo/customheaders.html
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>OpenSeadragon Custom Request Headers Demo</title>
|
||||||
|
<script type="text/javascript" src='../../build/openseadragon/openseadragon.js'></script>
|
||||||
|
<script type="text/javascript" src='../lib/jquery-1.9.1.min.js'></script>
|
||||||
|
<style type="text/css">
|
||||||
|
|
||||||
|
.osd-viewer {
|
||||||
|
width: 800px;
|
||||||
|
height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Demo of how the loadTilesWithAjax and ajaxHeaders options as well as the getTileHeaders() method on TileSource can be applied.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Examine the network requests in your browser developer tools to see the custom headers sent with each request.
|
||||||
|
</p>
|
||||||
|
<div id="contentDiv" class="osd-viewer"></div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
// These values are generated by a script that concatenates all the tile files and records
|
||||||
|
// their byte ranges in a multi-dimensional array.
|
||||||
|
var tileManifest = {"tileRanges":[[[[0,3467]]],[[[3467,6954]]],[[[344916,348425]]],[[[348425,351948]]],[[[351948,355576]]],[[[355576,359520]]],[[[359520,364663]]],[[[364663,374196]]],[[[374196,407307]]],[[[407307,435465],[435465,463663]],[[463663,491839],[491839,520078]]],[[[6954,29582],[29582,50315],[50315,71936],[71936,92703]],[[92703,113385],[113385,133265],[133265,154763],[154763,175710]],[[175710,197306],[197306,218807],[218807,242177],[242177,263007]],[[263007,283790],[283790,304822],[304822,325691],[325691,344916]]]],"totalSize":520078}
|
||||||
|
|
||||||
|
// This tile source demonstrates how you can retrieve individual tiles from a single file
|
||||||
|
// using the Range header.
|
||||||
|
var myCustomTileSource = {
|
||||||
|
width: 1000,
|
||||||
|
height: 1000,
|
||||||
|
tileWidth: 254,
|
||||||
|
tileHeight: 254,
|
||||||
|
tileOverlap: 1,
|
||||||
|
maxLevel: 10,
|
||||||
|
minLevel: 0,
|
||||||
|
// The tile URL is always the same. Only the Range header changes
|
||||||
|
getTileUrl: function () {
|
||||||
|
return "/test/data/testpattern.blob";
|
||||||
|
},
|
||||||
|
// This method will send the appropriate range header for this tile based on the data
|
||||||
|
// in tileByteRanges.
|
||||||
|
getTileAjaxHeaders: function(level, x, y) {
|
||||||
|
return {
|
||||||
|
Range: "bytes=" + tileManifest.tileRanges[level][x][y].join("-") + "/" + tileManifest.totalSize
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var viewer = OpenSeadragon({
|
||||||
|
id: "contentDiv",
|
||||||
|
prefixUrl: "../../build/openseadragon/images/",
|
||||||
|
showNavigator: true,
|
||||||
|
loadTilesWithAjax: true,
|
||||||
|
ajaxHeaders: {
|
||||||
|
// Example of using the viewer-level ajaxHeaders option
|
||||||
|
// for providing an authentication token.
|
||||||
|
"Authentication": "Bearer MY_AUTH_TOKEN"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
viewer.addTiledImage({
|
||||||
|
// The headers specified here will be combined with those in the Viewer object (if any)
|
||||||
|
ajaxHeaders: {
|
||||||
|
"X-My-TiledImage-Header": "Something"
|
||||||
|
},
|
||||||
|
tileSource: myCustomTileSource
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
38
test/demo/zoomify.html
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>OpenSeadragon Zoomify Demo</title>
|
||||||
|
<script type="text/javascript" src='../../build/openseadragon/openseadragon.js'></script>
|
||||||
|
<script type="text/javascript" src='../lib/jquery-1.9.1.min.js'></script>
|
||||||
|
<style type="text/css">
|
||||||
|
|
||||||
|
.openseadragon1 {
|
||||||
|
width: 800px;
|
||||||
|
height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
Simple demo page to show a default OpenSeadragon viewer with a Zoomify tile source.
|
||||||
|
</div>
|
||||||
|
<div id="contentDiv" class="openseadragon1"></div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var viewer = OpenSeadragon({
|
||||||
|
debugMode: true,
|
||||||
|
id: "contentDiv",
|
||||||
|
prefixUrl: "../../build/openseadragon/images/",
|
||||||
|
tileSources: [{
|
||||||
|
type: "zoomifytileservice",
|
||||||
|
width: 1000,
|
||||||
|
height: 1000,
|
||||||
|
tilesUrl: "../data/zoomify/"
|
||||||
|
}],
|
||||||
|
showNavigator:true
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
242
test/modules/ajax-tiles.js
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
/* global module, asyncTest, start, $, ok, equal, deepEqual, testLog */
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var viewer;
|
||||||
|
|
||||||
|
// These values are generated by a script that concatenates all the tile files and records
|
||||||
|
// their byte ranges in a multi-dimensional array.
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
|
var tileManifest = {"tileRanges":[[[[0,3467]]],[[[3467,6954]]],[[[344916,348425]]],[[[348425,351948]]],[[[351948,355576]]],[[[355576,359520]]],[[[359520,364663]]],[[[364663,374196]]],[[[374196,407307]]],[[[407307,435465],[435465,463663]],[[463663,491839],[491839,520078]]],[[[6954,29582],[29582,50315],[50315,71936],[71936,92703]],[[92703,113385],[113385,133265],[133265,154763],[154763,175710]],[[175710,197306],[197306,218807],[218807,242177],[242177,263007]],[[263007,283790],[283790,304822],[304822,325691],[325691,344916]]]],"totalSize":520078}
|
||||||
|
|
||||||
|
function getTileRangeHeader(level, x, y) {
|
||||||
|
return 'bytes=' + tileManifest.tileRanges[level][x][y].join('-') + '/' + tileManifest.totalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This tile source demonstrates how you can retrieve individual tiles from a single file
|
||||||
|
// using the Range header.
|
||||||
|
var customTileSource = {
|
||||||
|
width: 1000,
|
||||||
|
height: 1000,
|
||||||
|
tileWidth: 254,
|
||||||
|
tileHeight: 254,
|
||||||
|
tileOverlap: 1,
|
||||||
|
maxLevel: 10,
|
||||||
|
minLevel: 0,
|
||||||
|
// The tile URL is always the same. Only the Range header changes
|
||||||
|
getTileUrl: function () {
|
||||||
|
return '/test/data/testpattern.blob';
|
||||||
|
},
|
||||||
|
// This method will send the appropriate range header for this tile based on the data
|
||||||
|
// in tileByteRanges.
|
||||||
|
getTileAjaxHeaders: function(level, x, y) {
|
||||||
|
return {
|
||||||
|
Range: getTileRangeHeader(level, x, y)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module('AJAX-Tiles', {
|
||||||
|
setup: function() {
|
||||||
|
$('<div id="example"></div>').appendTo('#qunit-fixture');
|
||||||
|
|
||||||
|
testLog.reset();
|
||||||
|
|
||||||
|
viewer = OpenSeadragon({
|
||||||
|
id: 'example',
|
||||||
|
prefixUrl: '/build/openseadragon/images/',
|
||||||
|
springStiffness: 100, // Faster animation = faster tests,
|
||||||
|
loadTilesWithAjax: true,
|
||||||
|
ajaxHeaders: {
|
||||||
|
'X-Viewer-Header': 'ViewerHeaderValue'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
teardown: function() {
|
||||||
|
if (viewer && viewer.close) {
|
||||||
|
viewer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
viewer = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest('tile-loaded event includes AJAX request object', function() {
|
||||||
|
var tileLoaded = function tileLoaded(evt) {
|
||||||
|
viewer.removeHandler('tile-loaded', tileLoaded);
|
||||||
|
ok(evt.tileRequest, 'Event includes tileRequest property');
|
||||||
|
equal(evt.tileRequest.readyState, XMLHttpRequest.DONE, 'tileRequest is in completed state');
|
||||||
|
start();
|
||||||
|
};
|
||||||
|
|
||||||
|
viewer.addHandler('tile-loaded', tileLoaded);
|
||||||
|
viewer.open(customTileSource);
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest('withCredentials is set in tile AJAX requests', function() {
|
||||||
|
var tileLoaded = function tileLoaded(evt) {
|
||||||
|
viewer.removeHandler('tile-loaded', tileLoaded);
|
||||||
|
ok(evt.tileRequest, 'Event includes tileRequest property');
|
||||||
|
equal(evt.tileRequest.readyState, XMLHttpRequest.DONE, 'tileRequest is in completed state');
|
||||||
|
equal(evt.tileRequest.withCredentials, true, 'withCredentials is set in tile request');
|
||||||
|
start();
|
||||||
|
};
|
||||||
|
|
||||||
|
viewer.addHandler('tile-loaded', tileLoaded);
|
||||||
|
viewer.addTiledImage({
|
||||||
|
tileSource: customTileSource,
|
||||||
|
ajaxWithCredentials: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest('tile-load-failed event includes AJAX request object', function() {
|
||||||
|
// Create a tile source that points to a broken URL
|
||||||
|
var brokenTileSource = OpenSeadragon.extend({}, customTileSource, {
|
||||||
|
getTileUrl: function () {
|
||||||
|
return '/test/data/testpattern.blob.invalid';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var tileLoadFailed = function tileLoadFailed(evt) {
|
||||||
|
viewer.removeHandler('tile-load-failed', tileLoadFailed);
|
||||||
|
ok(evt.tileRequest, 'Event includes tileRequest property');
|
||||||
|
equal(evt.tileRequest.readyState, XMLHttpRequest.DONE, 'tileRequest is in completed state');
|
||||||
|
start();
|
||||||
|
};
|
||||||
|
|
||||||
|
viewer.addHandler('tile-load-failed', tileLoadFailed);
|
||||||
|
viewer.open(brokenTileSource);
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest('Headers can be set per-tile', function() {
|
||||||
|
var tileLoaded = function tileLoaded(evt) {
|
||||||
|
viewer.removeHandler('tile-loaded', tileLoaded);
|
||||||
|
var tile = evt.tile;
|
||||||
|
ok(tile, 'tile property exists on event');
|
||||||
|
ok(tile.ajaxHeaders, 'Tile has ajaxHeaders property');
|
||||||
|
equal(tile.ajaxHeaders.Range, getTileRangeHeader(tile.level, tile.x, tile.y), 'Tile has correct range header.');
|
||||||
|
start();
|
||||||
|
};
|
||||||
|
|
||||||
|
viewer.addHandler('tile-loaded', tileLoaded);
|
||||||
|
|
||||||
|
viewer.open(customTileSource);
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest('Headers are propagated correctly', function() {
|
||||||
|
// Create a tile source that sets a static header for tiles
|
||||||
|
var staticHeaderTileSource = OpenSeadragon.extend({}, customTileSource, {
|
||||||
|
getTileAjaxHeaders: function() {
|
||||||
|
return {
|
||||||
|
'X-Tile-Header': 'TileHeaderValue'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var expectedHeaders = {
|
||||||
|
'X-Viewer-Header': 'ViewerHeaderValue',
|
||||||
|
'X-TiledImage-Header': 'TiledImageHeaderValue',
|
||||||
|
'X-Tile-Header': 'TileHeaderValue'
|
||||||
|
};
|
||||||
|
|
||||||
|
var tileLoaded = function tileLoaded(evt) {
|
||||||
|
viewer.removeHandler('tile-loaded', tileLoaded);
|
||||||
|
var tile = evt.tile;
|
||||||
|
ok(tile, 'tile property exists on event');
|
||||||
|
ok(tile.ajaxHeaders, 'Tile has ajaxHeaders property');
|
||||||
|
deepEqual(
|
||||||
|
tile.ajaxHeaders, expectedHeaders,
|
||||||
|
'Tile headers include headers set on Viewer and TiledImage'
|
||||||
|
);
|
||||||
|
start();
|
||||||
|
};
|
||||||
|
|
||||||
|
viewer.addHandler('tile-loaded', tileLoaded);
|
||||||
|
|
||||||
|
viewer.addTiledImage({
|
||||||
|
ajaxHeaders: {
|
||||||
|
'X-TiledImage-Header': 'TiledImageHeaderValue'
|
||||||
|
},
|
||||||
|
tileSource: staticHeaderTileSource
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest('Viewer headers are overwritten by TiledImage', function() {
|
||||||
|
// Create a tile source that sets a static header for tiles
|
||||||
|
var staticHeaderTileSource = OpenSeadragon.extend({}, customTileSource, {
|
||||||
|
getTileAjaxHeaders: function() {
|
||||||
|
return {
|
||||||
|
'X-Tile-Header': 'TileHeaderValue'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var expectedHeaders = {
|
||||||
|
'X-Viewer-Header': 'ViewerHeaderValue-Overwritten',
|
||||||
|
'X-TiledImage-Header': 'TiledImageHeaderValue',
|
||||||
|
'X-Tile-Header': 'TileHeaderValue'
|
||||||
|
};
|
||||||
|
|
||||||
|
var tileLoaded = function tileLoaded(evt) {
|
||||||
|
viewer.removeHandler('tile-loaded', tileLoaded);
|
||||||
|
var tile = evt.tile;
|
||||||
|
ok(tile, 'tile property exists on event');
|
||||||
|
ok(tile.ajaxHeaders, 'Tile has ajaxHeaders property');
|
||||||
|
deepEqual(
|
||||||
|
tile.ajaxHeaders, expectedHeaders,
|
||||||
|
'TiledImage header overwrites viewer header'
|
||||||
|
);
|
||||||
|
start();
|
||||||
|
};
|
||||||
|
|
||||||
|
viewer.addHandler('tile-loaded', tileLoaded);
|
||||||
|
|
||||||
|
viewer.addTiledImage({
|
||||||
|
ajaxHeaders: {
|
||||||
|
'X-TiledImage-Header': 'TiledImageHeaderValue',
|
||||||
|
'X-Viewer-Header': 'ViewerHeaderValue-Overwritten'
|
||||||
|
},
|
||||||
|
tileSource: staticHeaderTileSource
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest('TiledImage headers are overwritten by Tile', function() {
|
||||||
|
|
||||||
|
var expectedHeaders = {
|
||||||
|
'X-Viewer-Header': 'ViewerHeaderValue',
|
||||||
|
'X-TiledImage-Header': 'TiledImageHeaderValue-Overwritten',
|
||||||
|
'X-Tile-Header': 'TileHeaderValue'
|
||||||
|
};
|
||||||
|
|
||||||
|
var tileLoaded = function tileLoaded(evt) {
|
||||||
|
viewer.removeHandler('tile-loaded', tileLoaded);
|
||||||
|
var tile = evt.tile;
|
||||||
|
ok(tile, 'tile property exists on event');
|
||||||
|
ok(tile.ajaxHeaders, 'Tile has ajaxHeaders property');
|
||||||
|
deepEqual(
|
||||||
|
tile.ajaxHeaders, expectedHeaders,
|
||||||
|
'Tile header overwrites TiledImage header'
|
||||||
|
);
|
||||||
|
start();
|
||||||
|
};
|
||||||
|
|
||||||
|
viewer.addHandler('tile-loaded', tileLoaded);
|
||||||
|
|
||||||
|
// Create a tile source that sets a static header for tiles
|
||||||
|
var staticHeaderTileSource = OpenSeadragon.extend({}, customTileSource, {
|
||||||
|
getTileAjaxHeaders: function() {
|
||||||
|
return {
|
||||||
|
'X-TiledImage-Header': 'TiledImageHeaderValue-Overwritten',
|
||||||
|
'X-Tile-Header': 'TileHeaderValue'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
viewer.addTiledImage({
|
||||||
|
ajaxHeaders: {
|
||||||
|
'X-TiledImage-Header': 'TiledImageHeaderValue'
|
||||||
|
},
|
||||||
|
tileSource: staticHeaderTileSource
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
@ -331,7 +331,7 @@
|
|||||||
height: 155
|
height: 155
|
||||||
} ]
|
} ]
|
||||||
} );
|
} );
|
||||||
viewer.addHandler('tile-drawn', function() {
|
viewer.addOnceHandler('tile-drawn', function() {
|
||||||
ok(OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
ok(OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
||||||
"Canvas should be tainted.");
|
"Canvas should be tainted.");
|
||||||
start();
|
start();
|
||||||
@ -355,7 +355,7 @@
|
|||||||
height: 155
|
height: 155
|
||||||
} ]
|
} ]
|
||||||
} );
|
} );
|
||||||
viewer.addHandler('tile-drawn', function() {
|
viewer.addOnceHandler('tile-drawn', function() {
|
||||||
ok(!OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
ok(!OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
||||||
"Canvas should not be tainted.");
|
"Canvas should not be tainted.");
|
||||||
start();
|
start();
|
||||||
@ -385,7 +385,7 @@
|
|||||||
},
|
},
|
||||||
crossOriginPolicy : false
|
crossOriginPolicy : false
|
||||||
} );
|
} );
|
||||||
viewer.addHandler('tile-drawn', function() {
|
viewer.addOnceHandler('tile-drawn', function() {
|
||||||
ok(OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
ok(OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
||||||
"Canvas should be tainted.");
|
"Canvas should be tainted.");
|
||||||
start();
|
start();
|
||||||
@ -414,7 +414,7 @@
|
|||||||
crossOriginPolicy : "Anonymous"
|
crossOriginPolicy : "Anonymous"
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
viewer.addHandler('tile-drawn', function() {
|
viewer.addOnceHandler('tile-drawn', function() {
|
||||||
ok(!OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
ok(!OpenSeadragon.isCanvasTainted(viewer.drawer.context.canvas),
|
||||||
"Canvas should not be tainted.");
|
"Canvas should not be tainted.");
|
||||||
start();
|
start();
|
||||||
@ -423,4 +423,12 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
test('version object', function() {
|
||||||
|
equal(typeof OpenSeadragon.version.versionStr, "string", "versionStr should be a string");
|
||||||
|
ok(OpenSeadragon.version.major >= 0, "major should be a positive number");
|
||||||
|
ok(OpenSeadragon.version.minor >= 0, "minor should be a positive number");
|
||||||
|
ok(OpenSeadragon.version.revision >= 0, "revision should be a positive number");
|
||||||
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -32,7 +32,13 @@
|
|||||||
'relative link should stay the same');
|
'relative link should stay the same');
|
||||||
testImplicitTilesUrl(
|
testImplicitTilesUrl(
|
||||||
'/p/foo.dzi?a=1&b=2', '/p/foo_files/',
|
'/p/foo.dzi?a=1&b=2', '/p/foo_files/',
|
||||||
'querystring in dzi url should be ignored');
|
'querystring in dzi url should be ignored after slashes');
|
||||||
|
testImplicitTilesUrl(
|
||||||
|
'/iiipsrv?DeepZoom=/path/my.dzi', '/iiipsrv?DeepZoom=/path/my_files/',
|
||||||
|
'querystring in dzi url should not be ignored before slashes');
|
||||||
|
testImplicitTilesUrl(
|
||||||
|
'/fcg-bin/iipsrv.fcgi?Deepzoom=123test.tif.dzi', '/fcg-bin/iipsrv.fcgi?Deepzoom=123test.tif_files/',
|
||||||
|
'filename in querystring does not have to contain slash');
|
||||||
});
|
});
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
88
test/modules/imageloader.js
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* global module, asyncTest, $, ok, equal, notEqual, start, test, Util, testLog */
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var viewer,
|
||||||
|
baseOptions = {
|
||||||
|
id: 'example',
|
||||||
|
prefixUrl: '/build/openseadragon/images/',
|
||||||
|
springStiffness: 100 // Faster animation = faster tests
|
||||||
|
};
|
||||||
|
|
||||||
|
module('ImageLoader', {
|
||||||
|
setup: function () {
|
||||||
|
var example = $('<div id="example"></div>').appendTo("#qunit-fixture");
|
||||||
|
|
||||||
|
testLog.reset();
|
||||||
|
},
|
||||||
|
teardown: function () {
|
||||||
|
if (viewer && viewer.close) {
|
||||||
|
viewer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
viewer = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
|
||||||
|
test('Default timeout', function() {
|
||||||
|
var actual,
|
||||||
|
expected = OpenSeadragon.DEFAULT_SETTINGS.timeout,
|
||||||
|
message,
|
||||||
|
options = OpenSeadragon.extend(true, baseOptions, {
|
||||||
|
imageLoaderLimit: 1
|
||||||
|
}),
|
||||||
|
viewer = OpenSeadragon(options),
|
||||||
|
imageLoader = viewer.imageLoader;
|
||||||
|
|
||||||
|
message = 'ImageLoader timeout should be set to the default value of ' + expected + ' when none is specified';
|
||||||
|
actual = imageLoader.timeout;
|
||||||
|
equal(actual, expected, message);
|
||||||
|
|
||||||
|
// Manually seize the ImageLoader
|
||||||
|
imageLoader.jobsInProgress = imageLoader.jobLimit;
|
||||||
|
imageLoader.addJob({
|
||||||
|
src: 'test',
|
||||||
|
loadWithAjax: false,
|
||||||
|
crossOriginPolicy: 'test',
|
||||||
|
ajaxWithCredentials: false,
|
||||||
|
abort: function() {}
|
||||||
|
});
|
||||||
|
|
||||||
|
message = 'ImageJob should inherit the ImageLoader timeout value';
|
||||||
|
actual = imageLoader.jobQueue.shift().timeout;
|
||||||
|
equal(actual, expected, message);
|
||||||
|
});
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
|
||||||
|
test('Configure timeout', function() {
|
||||||
|
var actual,
|
||||||
|
expected = 123456,
|
||||||
|
message,
|
||||||
|
options = OpenSeadragon.extend(true, baseOptions, {
|
||||||
|
imageLoaderLimit: 1,
|
||||||
|
timeout: expected
|
||||||
|
}),
|
||||||
|
viewer = OpenSeadragon(options),
|
||||||
|
imageLoader = viewer.imageLoader;
|
||||||
|
|
||||||
|
message = 'ImageLoader timeout should be configurable';
|
||||||
|
actual = imageLoader.timeout;
|
||||||
|
equal(actual, expected, message);
|
||||||
|
|
||||||
|
imageLoader.jobsInProgress = imageLoader.jobLimit;
|
||||||
|
imageLoader.addJob({
|
||||||
|
src: 'test',
|
||||||
|
loadWithAjax: false,
|
||||||
|
crossOriginPolicy: 'test',
|
||||||
|
ajaxWithCredentials: false,
|
||||||
|
abort: function() {}
|
||||||
|
});
|
||||||
|
|
||||||
|
message = 'ImageJob should inherit the ImageLoader timeout value';
|
||||||
|
actual = imageLoader.jobQueue.shift().timeout;
|
||||||
|
equal(actual, expected, message);
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
@ -217,7 +217,7 @@
|
|||||||
var firstImage = viewer.world.getItemAt(0);
|
var firstImage = viewer.world.getItemAt(0);
|
||||||
firstImage.addHandler('fully-loaded-change', function() {
|
firstImage.addHandler('fully-loaded-change', function() {
|
||||||
var imageData = viewer.drawer.context.getImageData(0, 0,
|
var imageData = viewer.drawer.context.getImageData(0, 0,
|
||||||
500 * OpenSeadragon.pixelDensityRatio, 500 * density);
|
500 * density, 500 * density);
|
||||||
|
|
||||||
// Pixel 250,250 will be in the hole of the A
|
// Pixel 250,250 will be in the hole of the A
|
||||||
var expectedVal = getPixelValue(imageData, 250 * density, 250 * density);
|
var expectedVal = getPixelValue(imageData, 250 * density, 250 * density);
|
||||||
|
@ -22,11 +22,11 @@
|
|||||||
|
|
||||||
test("getInvalidString", function() {
|
test("getInvalidString", function() {
|
||||||
equal(OpenSeadragon.getString("Greeting"), "", "Handled unset string key");
|
equal(OpenSeadragon.getString("Greeting"), "", "Handled unset string key");
|
||||||
ok(testLog.debug.contains('["Untranslated source string:","Greeting"]'),
|
ok(testLog.log.contains('["Untranslated source string:","Greeting"]'),
|
||||||
'Invalid string keys are logged');
|
'Invalid string keys are logged');
|
||||||
|
|
||||||
equal(OpenSeadragon.getString("Errors"), "", "Handled requesting parent key");
|
equal(OpenSeadragon.getString("Errors"), "", "Handled requesting parent key");
|
||||||
ok(testLog.debug.contains('["Untranslated source string:","Errors"]'),
|
ok(testLog.log.contains('["Untranslated source string:","Errors"]'),
|
||||||
'Invalid string parent keys are logged');
|
'Invalid string parent keys are logged');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -25,12 +25,14 @@
|
|||||||
|
|
||||||
var fakeTile0 = {
|
var fakeTile0 = {
|
||||||
url: 'foo.jpg',
|
url: 'foo.jpg',
|
||||||
|
cacheKey: 'foo.jpg',
|
||||||
image: {},
|
image: {},
|
||||||
unload: function() {}
|
unload: function() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
var fakeTile1 = {
|
var fakeTile1 = {
|
||||||
url: 'foo.jpg',
|
url: 'foo.jpg',
|
||||||
|
cacheKey: 'foo.jpg',
|
||||||
image: {},
|
image: {},
|
||||||
unload: function() {}
|
unload: function() {}
|
||||||
};
|
};
|
||||||
@ -74,18 +76,21 @@
|
|||||||
|
|
||||||
var fakeTile0 = {
|
var fakeTile0 = {
|
||||||
url: 'different.jpg',
|
url: 'different.jpg',
|
||||||
|
cacheKey: 'different.jpg',
|
||||||
image: {},
|
image: {},
|
||||||
unload: function() {}
|
unload: function() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
var fakeTile1 = {
|
var fakeTile1 = {
|
||||||
url: 'same.jpg',
|
url: 'same.jpg',
|
||||||
|
cacheKey: 'same.jpg',
|
||||||
image: {},
|
image: {},
|
||||||
unload: function() {}
|
unload: function() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
var fakeTile2 = {
|
var fakeTile2 = {
|
||||||
url: 'same.jpg',
|
url: 'same.jpg',
|
||||||
|
cacheKey: 'same.jpg',
|
||||||
image: {},
|
image: {},
|
||||||
unload: function() {}
|
unload: function() {}
|
||||||
};
|
};
|
||||||
|
@ -319,10 +319,16 @@
|
|||||||
|
|
||||||
function testDefaultRotation() {
|
function testDefaultRotation() {
|
||||||
var image = viewer.world.getItemAt(0);
|
var image = viewer.world.getItemAt(0);
|
||||||
strictEqual(image.getRotation(), 0, 'image has default rotation');
|
strictEqual(image.getRotation(true), 0, 'image has default current rotation');
|
||||||
|
strictEqual(image.getRotation(false), 0, 'image has default target rotation');
|
||||||
|
|
||||||
image.setRotation(400);
|
image.setRotation(400);
|
||||||
strictEqual(image.getRotation(), 40, 'rotation is set correctly');
|
strictEqual(image.getRotation(true), 0, 'current rotation is not changed');
|
||||||
|
strictEqual(image.getRotation(false), 400, 'target rotation is set correctly');
|
||||||
|
|
||||||
|
image.setRotation(200, true);
|
||||||
|
strictEqual(image.getRotation(true), 200, 'current rotation is set correctly');
|
||||||
|
strictEqual(image.getRotation(false), 200, 'target rotation is set correctly');
|
||||||
|
|
||||||
viewer.addOnceHandler('open', testTileSourceRotation);
|
viewer.addOnceHandler('open', testTileSourceRotation);
|
||||||
viewer.open({
|
viewer.open({
|
||||||
@ -333,7 +339,8 @@
|
|||||||
|
|
||||||
function testTileSourceRotation() {
|
function testTileSourceRotation() {
|
||||||
var image = viewer.world.getItemAt(0);
|
var image = viewer.world.getItemAt(0);
|
||||||
strictEqual(image.getRotation(), 300, 'image has correct rotation');
|
strictEqual(image.getRotation(true), -60, 'image has correct current rotation');
|
||||||
|
strictEqual(image.getRotation(false), -60, 'image has correct target rotation');
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,4 +522,159 @@
|
|||||||
}]);
|
}]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// PhantomJS is missing Function.prototype.bind
|
||||||
|
function bind(func, _this) {
|
||||||
|
return function() {
|
||||||
|
return func.apply(_this, arguments);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test('_getCornerTiles without wrapping', function() {
|
||||||
|
var tiledImageMock = {
|
||||||
|
wrapHorizontal: false,
|
||||||
|
wrapVertical: false,
|
||||||
|
source: new OpenSeadragon.TileSource({
|
||||||
|
width: 1500,
|
||||||
|
height: 1000,
|
||||||
|
tileWidth: 200,
|
||||||
|
tileHeight: 150,
|
||||||
|
tileOverlap: 1,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
var _getCornerTiles = bind(
|
||||||
|
OpenSeadragon.TiledImage.prototype._getCornerTiles,
|
||||||
|
tiledImageMock);
|
||||||
|
|
||||||
|
function assertCornerTiles(topLeftBound, bottomRightBound,
|
||||||
|
expectedTopLeft, expectedBottomRight) {
|
||||||
|
var cornerTiles = _getCornerTiles(11, topLeftBound, bottomRightBound);
|
||||||
|
ok(cornerTiles.topLeft.equals(expectedTopLeft),
|
||||||
|
'Top left tile should be ' + expectedTopLeft.toString() +
|
||||||
|
' found ' + cornerTiles.topLeft.toString());
|
||||||
|
ok(cornerTiles.bottomRight.equals(expectedBottomRight),
|
||||||
|
'Bottom right tile should be ' + expectedBottomRight.toString() +
|
||||||
|
' found ' + cornerTiles.bottomRight.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(0, 0),
|
||||||
|
new OpenSeadragon.Point(1, 10 / 15),
|
||||||
|
new OpenSeadragon.Point(0, 0),
|
||||||
|
new OpenSeadragon.Point(7, 6)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Floating point errors should be handled
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(-1e-14, -1e-14),
|
||||||
|
new OpenSeadragon.Point(1 + 1e-14, 10 / 15 + 1e-14),
|
||||||
|
new OpenSeadragon.Point(0, 0),
|
||||||
|
new OpenSeadragon.Point(7, 6)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(0.3, 0.5),
|
||||||
|
new OpenSeadragon.Point(0.5, 0.6),
|
||||||
|
new OpenSeadragon.Point(2, 5),
|
||||||
|
new OpenSeadragon.Point(3, 6)
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
test('_getCornerTiles with horizontal wrapping', function() {
|
||||||
|
var tiledImageMock = {
|
||||||
|
wrapHorizontal: true,
|
||||||
|
wrapVertical: false,
|
||||||
|
source: new OpenSeadragon.TileSource({
|
||||||
|
width: 1500,
|
||||||
|
height: 1000,
|
||||||
|
tileWidth: 200,
|
||||||
|
tileHeight: 150,
|
||||||
|
tileOverlap: 1,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
var _getCornerTiles = bind(
|
||||||
|
OpenSeadragon.TiledImage.prototype._getCornerTiles,
|
||||||
|
tiledImageMock);
|
||||||
|
|
||||||
|
function assertCornerTiles(topLeftBound, bottomRightBound,
|
||||||
|
expectedTopLeft, expectedBottomRight) {
|
||||||
|
var cornerTiles = _getCornerTiles(11, topLeftBound, bottomRightBound);
|
||||||
|
ok(cornerTiles.topLeft.equals(expectedTopLeft),
|
||||||
|
'Top left tile should be ' + expectedTopLeft.toString() +
|
||||||
|
' found ' + cornerTiles.topLeft.toString());
|
||||||
|
ok(cornerTiles.bottomRight.equals(expectedBottomRight),
|
||||||
|
'Bottom right tile should be ' + expectedBottomRight.toString() +
|
||||||
|
' found ' + cornerTiles.bottomRight.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(0, 0),
|
||||||
|
new OpenSeadragon.Point(1, 10 / 15),
|
||||||
|
new OpenSeadragon.Point(0, 0),
|
||||||
|
new OpenSeadragon.Point(8, 6)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(-1, 0),
|
||||||
|
new OpenSeadragon.Point(0.5, 10 / 15 + 1e-14),
|
||||||
|
new OpenSeadragon.Point(-8, 0),
|
||||||
|
new OpenSeadragon.Point(3, 6)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(1.3, 0.5),
|
||||||
|
new OpenSeadragon.Point(1.5, 0.6),
|
||||||
|
new OpenSeadragon.Point(10, 5),
|
||||||
|
new OpenSeadragon.Point(11, 6)
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
test('_getCornerTiles with vertical wrapping', function() {
|
||||||
|
var tiledImageMock = {
|
||||||
|
wrapHorizontal: false,
|
||||||
|
wrapVertical: true,
|
||||||
|
source: new OpenSeadragon.TileSource({
|
||||||
|
width: 1500,
|
||||||
|
height: 1000,
|
||||||
|
tileWidth: 200,
|
||||||
|
tileHeight: 150,
|
||||||
|
tileOverlap: 1,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
var _getCornerTiles = bind(
|
||||||
|
OpenSeadragon.TiledImage.prototype._getCornerTiles,
|
||||||
|
tiledImageMock);
|
||||||
|
|
||||||
|
function assertCornerTiles(topLeftBound, bottomRightBound,
|
||||||
|
expectedTopLeft, expectedBottomRight) {
|
||||||
|
var cornerTiles = _getCornerTiles(11, topLeftBound, bottomRightBound);
|
||||||
|
ok(cornerTiles.topLeft.equals(expectedTopLeft),
|
||||||
|
'Top left tile should be ' + expectedTopLeft.toString() +
|
||||||
|
' found ' + cornerTiles.topLeft.toString());
|
||||||
|
ok(cornerTiles.bottomRight.equals(expectedBottomRight),
|
||||||
|
'Bottom right tile should be ' + expectedBottomRight.toString() +
|
||||||
|
' found ' + cornerTiles.bottomRight.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(0, 0),
|
||||||
|
new OpenSeadragon.Point(1, 10 / 15),
|
||||||
|
new OpenSeadragon.Point(0, 0),
|
||||||
|
new OpenSeadragon.Point(7, 7)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(0, -10 / 15 / 2),
|
||||||
|
new OpenSeadragon.Point(0.5, 0.5),
|
||||||
|
new OpenSeadragon.Point(0, -4),
|
||||||
|
new OpenSeadragon.Point(3, 5)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertCornerTiles(
|
||||||
|
new OpenSeadragon.Point(0, 10 / 15 + 0.1),
|
||||||
|
new OpenSeadragon.Point(0.3, 10 / 15 + 0.3),
|
||||||
|
new OpenSeadragon.Point(0, 7),
|
||||||
|
new OpenSeadragon.Point(2, 9)
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -48,4 +48,54 @@
|
|||||||
Util.testDeprecation(source, 'getTileSize');
|
Util.testDeprecation(source, 'getTileSize');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('getTileAtPoint', function() {
|
||||||
|
var tileSource = new OpenSeadragon.TileSource({
|
||||||
|
width: 1500,
|
||||||
|
height: 1000,
|
||||||
|
tileWidth: 200,
|
||||||
|
tileHeight: 150,
|
||||||
|
tileOverlap: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
equal(tileSource.maxLevel, 11, "The max level should be 11.");
|
||||||
|
|
||||||
|
function assertTileAtPoint(level, position, expected) {
|
||||||
|
var actual = tileSource.getTileAtPoint(level, position);
|
||||||
|
ok(actual.equals(expected), "The tile at level " + level +
|
||||||
|
", position " + position.toString() +
|
||||||
|
" should be tile " + expected.toString() +
|
||||||
|
" got " + actual.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTileAtPoint(11, new OpenSeadragon.Point(0, 0), new OpenSeadragon.Point(0, 0));
|
||||||
|
assertTileAtPoint(11, new OpenSeadragon.Point(0.5, 0.5), new OpenSeadragon.Point(3, 5));
|
||||||
|
assertTileAtPoint(11, new OpenSeadragon.Point(1, 10 / 15), new OpenSeadragon.Point(7, 6));
|
||||||
|
|
||||||
|
assertTileAtPoint(10, new OpenSeadragon.Point(0, 0), new OpenSeadragon.Point(0, 0));
|
||||||
|
assertTileAtPoint(10, new OpenSeadragon.Point(0.5, 0.5), new OpenSeadragon.Point(1, 2));
|
||||||
|
assertTileAtPoint(10, new OpenSeadragon.Point(1, 10 / 15), new OpenSeadragon.Point(3, 3));
|
||||||
|
|
||||||
|
assertTileAtPoint(9, new OpenSeadragon.Point(0, 0), new OpenSeadragon.Point(0, 0));
|
||||||
|
assertTileAtPoint(9, new OpenSeadragon.Point(0.5, 0.5), new OpenSeadragon.Point(0, 1));
|
||||||
|
assertTileAtPoint(9, new OpenSeadragon.Point(1, 10 / 15), new OpenSeadragon.Point(1, 1));
|
||||||
|
|
||||||
|
// For all other levels, there is only one tile.
|
||||||
|
for (var level = 8; level >= 0; level--) {
|
||||||
|
assertTileAtPoint(level, new OpenSeadragon.Point(0, 0), new OpenSeadragon.Point(0, 0));
|
||||||
|
assertTileAtPoint(level, new OpenSeadragon.Point(0.5, 0.5), new OpenSeadragon.Point(0, 0));
|
||||||
|
assertTileAtPoint(level, new OpenSeadragon.Point(1, 10 / 15), new OpenSeadragon.Point(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for issue #1113
|
||||||
|
tileSource = new OpenSeadragon.TileSource({
|
||||||
|
width: 1006,
|
||||||
|
height: 1009,
|
||||||
|
tileWidth: 1006,
|
||||||
|
tileHeight: 1009,
|
||||||
|
tileOverlap: 0,
|
||||||
|
maxLevel: 0,
|
||||||
|
});
|
||||||
|
assertTileAtPoint(0, new OpenSeadragon.Point(1, 1009 / 1006), new OpenSeadragon.Point(0, 0));
|
||||||
|
});
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
var TALL_PATH = '/test/data/tall.dzi';
|
var TALL_PATH = '/test/data/tall.dzi';
|
||||||
var WIDE_PATH = '/test/data/wide.dzi';
|
var WIDE_PATH = '/test/data/wide.dzi';
|
||||||
|
|
||||||
var testZoomLevels = [-1, 0, 0.1, 0.5, 4, 10];
|
var testZoomLevels = [0.1, 0.2, 0.5, 1, 4, 10];
|
||||||
|
|
||||||
var testPoints = [
|
var testPoints = [
|
||||||
new OpenSeadragon.Point(0, 0),
|
new OpenSeadragon.Point(0, 0),
|
||||||
@ -59,7 +59,6 @@
|
|||||||
var reopenViewerHelper = function(config) {
|
var reopenViewerHelper = function(config) {
|
||||||
var expected, level, actual, i = 0;
|
var expected, level, actual, i = 0;
|
||||||
var openHandler = function(event) {
|
var openHandler = function(event) {
|
||||||
viewer.removeHandler('open', openHandler);
|
|
||||||
var viewport = viewer.viewport;
|
var viewport = viewer.viewport;
|
||||||
expected = config.processExpected(level, expected);
|
expected = config.processExpected(level, expected);
|
||||||
actual = viewport[config.method]();
|
actual = viewport[config.method]();
|
||||||
@ -70,7 +69,7 @@
|
|||||||
"Test " + config.method + " with zoom level of " + level + ". Expected : " + expected + ", got " + actual
|
"Test " + config.method + " with zoom level of " + level + ". Expected : " + expected + ", got " + actual
|
||||||
);
|
);
|
||||||
i++;
|
i++;
|
||||||
if(i < testZoomLevels.length){
|
if (i < testZoomLevels.length) {
|
||||||
level = expected = testZoomLevels[i];
|
level = expected = testZoomLevels[i];
|
||||||
var viewerConfig = {
|
var viewerConfig = {
|
||||||
id: VIEWER_ID,
|
id: VIEWER_ID,
|
||||||
@ -80,15 +79,22 @@
|
|||||||
|
|
||||||
viewerConfig[config.property] = level;
|
viewerConfig[config.property] = level;
|
||||||
viewer = OpenSeadragon(viewerConfig);
|
viewer = OpenSeadragon(viewerConfig);
|
||||||
viewer.addHandler('open', openHandler);
|
viewer.addOnceHandler('open', openHandler);
|
||||||
viewer.open(DZI_PATH);
|
viewer.open(DZI_PATH);
|
||||||
} else {
|
} else {
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
viewer.addHandler('open', openHandler);
|
|
||||||
level = expected = testZoomLevels[i];
|
level = expected = testZoomLevels[i];
|
||||||
viewer[config.property] = level;
|
var viewerConfig = {
|
||||||
|
id: VIEWER_ID,
|
||||||
|
prefixUrl: PREFIX_URL,
|
||||||
|
springStiffness: SPRING_STIFFNESS
|
||||||
|
};
|
||||||
|
|
||||||
|
viewerConfig[config.property] = level;
|
||||||
|
viewer = OpenSeadragon(viewerConfig);
|
||||||
|
viewer.addOnceHandler('open', openHandler);
|
||||||
viewer.open(DZI_PATH);
|
viewer.open(DZI_PATH);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -211,15 +217,9 @@
|
|||||||
property: 'defaultZoomLevel',
|
property: 'defaultZoomLevel',
|
||||||
method: 'getHomeBounds',
|
method: 'getHomeBounds',
|
||||||
processExpected: function(level, expected) {
|
processExpected: function(level, expected) {
|
||||||
// Have to special case this to avoid dividing by 0
|
var sideLength = 1.0 / viewer.defaultZoomLevel; // it's a square in this case
|
||||||
if(level === -1 || level === 0){
|
var position = 0.5 - (sideLength / 2.0);
|
||||||
expected = new OpenSeadragon.Rect(0, 0, 1, 1);
|
return new OpenSeadragon.Rect(position, position, sideLength, sideLength);
|
||||||
} else {
|
|
||||||
var sideLength = 1.0 / viewer.defaultZoomLevel; // it's a square in this case
|
|
||||||
var position = 0.5 - (sideLength / 2.0);
|
|
||||||
expected = new OpenSeadragon.Rect(position, position, sideLength, sideLength);
|
|
||||||
}
|
|
||||||
return expected;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -333,44 +333,39 @@
|
|||||||
// I don't use the helper for this one because it sets a couple more
|
// I don't use the helper for this one because it sets a couple more
|
||||||
// properties that would need special casing.
|
// properties that would need special casing.
|
||||||
asyncTest('getHomeZoomWithHomeFillsViewer', function() {
|
asyncTest('getHomeZoomWithHomeFillsViewer', function() {
|
||||||
var expected, level, i = 0;
|
var i = 0;
|
||||||
var openHandler = function(event) {
|
var openHandler = function(event) {
|
||||||
viewer.removeHandler('open', openHandler);
|
|
||||||
var viewport = viewer.viewport;
|
var viewport = viewer.viewport;
|
||||||
viewport.zoomTo(ZOOM_FACTOR, null, true);
|
viewport.zoomTo(ZOOM_FACTOR, null, true);
|
||||||
|
|
||||||
// Special cases for oddball levels
|
|
||||||
if (level === -1) {
|
|
||||||
expected = 0.25;
|
|
||||||
} else if(level === 0){
|
|
||||||
expected = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
equal(
|
equal(
|
||||||
viewport.getHomeZoom(),
|
viewport.getHomeZoom(),
|
||||||
expected,
|
testZoomLevels[i],
|
||||||
"Test getHomeZoom with homeFillsViewer = true and default zoom level of " + expected
|
"Test getHomeZoom with homeFillsViewer = true and default zoom level of " + testZoomLevels[i]
|
||||||
);
|
);
|
||||||
i++;
|
i++;
|
||||||
if(i < testZoomLevels.length){
|
if (i < testZoomLevels.length) {
|
||||||
level = expected = testZoomLevels[i];
|
|
||||||
viewer = OpenSeadragon({
|
viewer = OpenSeadragon({
|
||||||
id: VIEWER_ID,
|
id: VIEWER_ID,
|
||||||
prefixUrl: PREFIX_URL,
|
prefixUrl: PREFIX_URL,
|
||||||
springStiffness: SPRING_STIFFNESS,
|
springStiffness: SPRING_STIFFNESS,
|
||||||
defaultZoomLevel: level,
|
defaultZoomLevel: testZoomLevels[i],
|
||||||
homeFillsViewer: true
|
homeFillsViewer: true
|
||||||
});
|
});
|
||||||
viewer.addHandler('open', openHandler);
|
viewer.addOnceHandler('open', openHandler);
|
||||||
viewer.open(TALL_PATH); // use a different image for homeFillsViewer
|
viewer.open(TALL_PATH); // use a different image for homeFillsViewer
|
||||||
} else {
|
} else {
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
viewer.addHandler('open', openHandler);
|
viewer = OpenSeadragon({
|
||||||
level = expected = testZoomLevels[i];
|
id: VIEWER_ID,
|
||||||
viewer.homeFillsViewer = true;
|
prefixUrl: PREFIX_URL,
|
||||||
viewer.defaultZoomLevel = expected;
|
springStiffness: SPRING_STIFFNESS,
|
||||||
|
defaultZoomLevel: testZoomLevels[i],
|
||||||
|
homeFillsViewer: true
|
||||||
|
});
|
||||||
|
viewer.addOnceHandler('open', openHandler);
|
||||||
viewer.open(TALL_PATH); // use a different image for homeFillsViewer
|
viewer.open(TALL_PATH); // use a different image for homeFillsViewer
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -725,27 +720,18 @@
|
|||||||
viewer.open(DZI_PATH);
|
viewer.open(DZI_PATH);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest('zoomBy', function(){
|
asyncTest('zoomBy no ref point', function() {
|
||||||
var openHandler = function(event) {
|
var openHandler = function(event) {
|
||||||
viewer.removeHandler('open', openHandler);
|
viewer.removeHandler('open', openHandler);
|
||||||
var viewport = viewer.viewport;
|
var viewport = viewer.viewport;
|
||||||
|
|
||||||
for (var i = 0; i < testZoomLevels.length; i++){
|
for (var i = 0; i < testZoomLevels.length; i++) {
|
||||||
viewport.zoomBy(testZoomLevels[i], null, true);
|
viewport.zoomBy(testZoomLevels[i], null, true);
|
||||||
propEqual(
|
propEqual(
|
||||||
viewport.getZoom(),
|
viewport.getZoom(),
|
||||||
testZoomLevels[i],
|
testZoomLevels[i],
|
||||||
"Zoomed by the correct amount."
|
"Zoomed by the correct amount."
|
||||||
);
|
);
|
||||||
|
|
||||||
// now use a ref point
|
|
||||||
// TODO: check the ending position due to ref point
|
|
||||||
viewport.zoomBy(testZoomLevels[i], testPoints[i], true);
|
|
||||||
propEqual(
|
|
||||||
viewport.getZoom(),
|
|
||||||
testZoomLevels[i],
|
|
||||||
"Zoomed by the correct amount."
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start();
|
start();
|
||||||
@ -754,27 +740,88 @@
|
|||||||
viewer.open(DZI_PATH);
|
viewer.open(DZI_PATH);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest('zoomTo', function(){
|
asyncTest('zoomBy with ref point', function() {
|
||||||
var openHandler = function(event) {
|
var openHandler = function(event) {
|
||||||
viewer.removeHandler('open', openHandler);
|
viewer.removeHandler('open', openHandler);
|
||||||
var viewport = viewer.viewport;
|
var viewport = viewer.viewport;
|
||||||
|
|
||||||
for (var i = 0; i < testZoomLevels.length; i++){
|
var expectedCenters = [
|
||||||
|
new OpenSeadragon.Point(5, 5),
|
||||||
|
new OpenSeadragon.Point(6.996, 6.996),
|
||||||
|
new OpenSeadragon.Point(7.246, 6.996),
|
||||||
|
new OpenSeadragon.Point(7.246, 6.996),
|
||||||
|
new OpenSeadragon.Point(7.621, 7.371),
|
||||||
|
new OpenSeadragon.Point(7.621, 7.371),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var i = 0; i < testZoomLevels.length; i++) {
|
||||||
|
viewport.zoomBy(testZoomLevels[i], testPoints[i], true);
|
||||||
|
propEqual(
|
||||||
|
viewport.getZoom(),
|
||||||
|
testZoomLevels[i],
|
||||||
|
"Zoomed by the correct amount."
|
||||||
|
);
|
||||||
|
assertPointsEquals(
|
||||||
|
viewport.getCenter(),
|
||||||
|
expectedCenters[i],
|
||||||
|
1e-14,
|
||||||
|
"Panned to the correct location."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
start();
|
||||||
|
};
|
||||||
|
viewer.addHandler('open', openHandler);
|
||||||
|
viewer.open(DZI_PATH);
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest('zoomTo no ref point', function() {
|
||||||
|
var openHandler = function(event) {
|
||||||
|
viewer.removeHandler('open', openHandler);
|
||||||
|
var viewport = viewer.viewport;
|
||||||
|
|
||||||
|
for (var i = 0; i < testZoomLevels.length; i++) {
|
||||||
viewport.zoomTo(testZoomLevels[i], null, true);
|
viewport.zoomTo(testZoomLevels[i], null, true);
|
||||||
propEqual(
|
propEqual(
|
||||||
viewport.getZoom(),
|
viewport.getZoom(),
|
||||||
testZoomLevels[i],
|
testZoomLevels[i],
|
||||||
"Zoomed to the correct level."
|
"Zoomed to the correct level."
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// now use a ref point
|
start();
|
||||||
// TODO: check the ending position due to ref point
|
};
|
||||||
|
viewer.addHandler('open', openHandler);
|
||||||
|
viewer.open(DZI_PATH);
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest('zoomTo with ref point', function() {
|
||||||
|
var openHandler = function(event) {
|
||||||
|
viewer.removeHandler('open', openHandler);
|
||||||
|
var viewport = viewer.viewport;
|
||||||
|
|
||||||
|
var expectedCenters = [
|
||||||
|
new OpenSeadragon.Point(5, 5),
|
||||||
|
new OpenSeadragon.Point(4.7505, 4.7505),
|
||||||
|
new OpenSeadragon.Point(4.6005, 4.7505),
|
||||||
|
new OpenSeadragon.Point(4.8455, 4.9955),
|
||||||
|
new OpenSeadragon.Point(5.2205, 5.3705),
|
||||||
|
new OpenSeadragon.Point(5.2205, 5.3705),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var i = 0; i < testZoomLevels.length; i++) {
|
||||||
viewport.zoomTo(testZoomLevels[i], testPoints[i], true);
|
viewport.zoomTo(testZoomLevels[i], testPoints[i], true);
|
||||||
propEqual(
|
propEqual(
|
||||||
viewport.getZoom(),
|
viewport.getZoom(),
|
||||||
testZoomLevels[i],
|
testZoomLevels[i],
|
||||||
"Zoomed to the correct level."
|
"Zoomed to the correct level."
|
||||||
);
|
);
|
||||||
|
assertPointsEquals(
|
||||||
|
viewport.getCenter(),
|
||||||
|
expectedCenters[i],
|
||||||
|
1e-14,
|
||||||
|
"Panned to the correct location."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
start();
|
start();
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
<script src="/test/lib/jquery-1.9.1.min.js"></script>
|
<script src="/test/lib/jquery-1.9.1.min.js"></script>
|
||||||
<script src="/test/lib/jquery-ui-1.10.2/js/jquery-ui-1.10.2.min.js"></script>
|
<script src="/test/lib/jquery-ui-1.10.2/js/jquery-ui-1.10.2.min.js"></script>
|
||||||
<script src="/test/lib/jquery.simulate.js"></script>
|
<script src="/test/lib/jquery.simulate.js"></script>
|
||||||
<script src="/build/openseadragon/openseadragon.js"></script>
|
<script src="/build/openseadragon/openseadragon.min.js"></script>
|
||||||
<script src="/test/helpers/legacy.mouse.shim.js"></script>
|
<script src="/test/helpers/legacy.mouse.shim.js"></script>
|
||||||
<script src="/test/helpers/test.js"></script>
|
<script src="/test/helpers/test.js"></script>
|
||||||
<script src="/test/helpers/touch.js"></script>
|
<script src="/test/helpers/touch.js"></script>
|
||||||
@ -42,6 +42,8 @@
|
|||||||
<script src="/test/modules/tilesourcecollection.js"></script>
|
<script src="/test/modules/tilesourcecollection.js"></script>
|
||||||
<script src="/test/modules/spring.js"></script>
|
<script src="/test/modules/spring.js"></script>
|
||||||
<script src="/test/modules/rectangle.js"></script>
|
<script src="/test/modules/rectangle.js"></script>
|
||||||
|
<script src="/test/modules/ajax-tiles.js"></script>
|
||||||
|
<script src="/test/modules/imageloader.js"></script>
|
||||||
<!-- The navigator tests are the slowest (for now; hopefully they can be sped up)
|
<!-- The navigator tests are the slowest (for now; hopefully they can be sped up)
|
||||||
so we put them last. -->
|
so we put them last. -->
|
||||||
<script src="/test/modules/navigator.js"></script>
|
<script src="/test/modules/navigator.js"></script>
|
||||||
|