diff --git a/minerva_analysis/client/dist/vendor_bundle.js b/minerva_analysis/client/dist/vendor_bundle.js index 438611c8b..8fe586452 100644 --- a/minerva_analysis/client/dist/vendor_bundle.js +++ b/minerva_analysis/client/dist/vendor_bundle.js @@ -12941,7 +12941,7 @@ eval("/*\nobject-assign\n(c) Sindre Sorhus\n@license MIT\n*/\n\n\n\n/* eslint-di /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { -eval("var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;function _typeof(obj){\"@babel/helpers - typeof\";return _typeof=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(obj){return typeof obj;}:function(obj){return obj&&\"function\"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?\"symbol\":typeof obj;},_typeof(obj);}//! openseadragon 2.3.1\n//! Built on 2023-07-27\n//! Git commit: unknown\n//! http://openseadragon.github.io\n//! License: http://openseadragon.github.io/license/\n/*\n * OpenSeadragon\n *\n * Copyright (C) 2009 CodePlex Foundation\n * Copyright (C) 2010-2013 OpenSeadragon contributors\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * - Redistributions of source code must retain the above copyright notice,\n * this list of conditions and the following disclaimer.\n *\n * - Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n *\n * - Neither the name of CodePlex Foundation nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\n * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */ /*\n * Portions of this source file taken from jQuery:\n *\n * Copyright 2011 John Resig\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */ /*\n * Portions of this source file taken from mattsnider.com:\n *\n * Copyright (c) 2006-2013 Matt Snider\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT\n * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\n * THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */ /**\n * @namespace OpenSeadragon\n * @version openseadragon 2.3.1\n * @classdesc The root namespace for OpenSeadragon. All utility methods\n * and classes are defined on or below this namespace.\n *\n */ // Typedefs\n/**\n * All required and optional settings for instantiating a new instance of an OpenSeadragon image viewer.\n *\n * @typedef {Object} Options\n * @memberof OpenSeadragon\n *\n * @property {String} id\n * Id of the element to append the viewer's container element to. If not provided, the 'element' property must be provided.\n * If both the element and id properties are specified, the viewer is appended to the element provided in the element property.\n *\n * @property {Element} element\n * The element to append the viewer's container element to. If not provided, the 'id' property must be provided.\n * If both the element and id properties are specified, the viewer is appended to the element provided in the element property.\n *\n * @property {Array|String|Function|Object} [tileSources=null]\n * Tile source(s) to open initially. This is a complex parameter; see\n * {@link OpenSeadragon.Viewer#open} for details.\n *\n * @property {Number} [tabIndex=0]\n * Tabbing order index to assign to the viewer element. Positive values are selected in increasing order. When tabIndex is 0\n * source order is used. A negative value omits the viewer from the tabbing order.\n *\n * @property {Array} overlays Array of objects defining permanent overlays of\n * the viewer. The overlays added via this option and later removed with\n * {@link OpenSeadragon.Viewer#removeOverlay} will be added back when a new\n * image is opened.\n * To add overlays which can be definitively removed, one must use\n * {@link OpenSeadragon.Viewer#addOverlay}\n * If displaying a sequence of images, the overlays can be associated\n * with a specific page by passing the overlays array to the page's\n * tile source configuration.\n * Expected properties:\n * * x, y, (or px, py for pixel coordinates) to define the location.\n * * width, height in point if using x,y or in pixels if using px,py. If width\n * and height are specified, the overlay size is adjusted when zooming,\n * otherwise the size stays the size of the content (or the size defined by CSS).\n * * className to associate a class to the overlay\n * * id to set the overlay element. If an element with this id already exists,\n * it is reused, otherwise it is created. If not specified, a new element is\n * created.\n * * placement a string to define the relative position to the viewport.\n * Only used if no width and height are specified. Default: 'TOP_LEFT'.\n * See {@link OpenSeadragon.Placement} for possible values.\n *\n * @property {String} [xmlPath=null]\n * DEPRECATED. A relative path to load a DZI file from the server.\n * Prefer the newer Options.tileSources.\n *\n * @property {String} [prefixUrl='/images/']\n * Prepends the prefixUrl to navImages paths, which is very useful\n * since the default paths are rarely useful for production\n * environments.\n *\n * @property {OpenSeadragon.NavImages} [navImages]\n * An object with a property for each button or other built-in navigation\n * control, eg the current 'zoomIn', 'zoomOut', 'home', and 'fullpage'.\n * Each of those in turn provides an image path for each state of the button\n * or navigation control, eg 'REST', 'GROUP', 'HOVER', 'PRESS'. Finally the\n * image paths, by default assume there is a folder on the servers root path\n * called '/images', eg '/images/zoomin_rest.png'. If you need to adjust\n * these paths, prefer setting the option.prefixUrl rather than overriding\n * every image path directly through this setting.\n *\n * @property {Boolean} [debugMode=false]\n * TODO: provide an in-screen panel providing event detail feedback.\n *\n * @property {String} [debugGridColor=['#437AB2', '#1B9E77', '#D95F02', '#7570B3', '#E7298A', '#66A61E', '#E6AB02', '#A6761D', '#666666']]\n * The colors of grids in debug mode. Each tiled image's grid uses a consecutive color.\n * If there are more tiled images than provided colors, the color vector is recycled.\n *\n * @property {Number} [blendTime=0]\n * Specifies the duration of animation as higher or lower level tiles are\n * replacing the existing tile.\n *\n * @property {Boolean} [alwaysBlend=false]\n * Forces the tile to always blend. By default the tiles skip blending\n * when the blendTime is surpassed and the current animation frame would\n * not complete the blend.\n *\n * @property {Boolean} [autoHideControls=true]\n * If the user stops interacting with the viewport, fade the navigation\n * controls. Useful for presentation since the controls are by default\n * floated on top of the image the user is viewing.\n *\n * @property {Boolean} [immediateRender=false]\n * Render the best closest level first, ignoring the lowering levels which\n * provide the effect of very blurry to sharp. It is recommended to change\n * setting to true for mobile devices.\n *\n * @property {Number} [defaultZoomLevel=0]\n * Zoom level to use when image is first opened or the home button is clicked.\n * If 0, adjusts to fit viewer.\n *\n * @property {Number} [opacity=1]\n * Default proportional opacity of the tiled images (1=opaque, 0=hidden)\n * Hidden images do not draw and only load when preloading is allowed.\n *\n * @property {Boolean} [preload=false]\n * Default switch for loading hidden images (true loads, false blocks)\n *\n * @property {String} [compositeOperation=null]\n * Valid values are 'source-over', 'source-atop', 'source-in', 'source-out',\n * 'destination-over', 'destination-atop', 'destination-in',\n * 'destination-out', 'lighter', 'copy' or 'xor'\n *\n * @property {String|CanvasGradient|CanvasPattern|Function} [placeholderFillStyle=null]\n * Draws a colored rectangle behind the tile if it is not loaded yet.\n * You can pass a CSS color value like \"#FF8800\".\n * When passing a function the tiledImage and canvas context are available as argument which is useful when you draw a gradient or pattern.\n *\n * @property {Number} [degrees=0]\n * Initial rotation.\n *\n * @property {Boolean} [flipped=false]\n * Initial flip state.\n *\n * @property {Number} [minZoomLevel=null]\n *\n * @property {Number} [maxZoomLevel=null]\n *\n * @property {Boolean} [homeFillsViewer=false]\n * Make the 'home' button fill the viewer and clip the image, instead\n * of fitting the image to the viewer and letterboxing.\n *\n * @property {Boolean} [panHorizontal=true]\n * Allow horizontal pan.\n *\n * @property {Boolean} [panVertical=true]\n * Allow vertical pan.\n *\n * @property {Boolean} [constrainDuringPan=false]\n *\n * @property {Boolean} [wrapHorizontal=false]\n * Set to true to force the image to wrap horizontally within the viewport.\n * Useful for maps or images representing the surface of a sphere or cylinder.\n *\n * @property {Boolean} [wrapVertical=false]\n * Set to true to force the image to wrap vertically within the viewport.\n * Useful for maps or images representing the surface of a sphere or cylinder.\n *\n * @property {Number} [minZoomImageRatio=0.9]\n * The minimum percentage ( expressed as a number between 0 and 1 ) of\n * the viewport height or width at which the zoom out will be constrained.\n * Setting it to 0, for example will allow you to zoom out infinity.\n *\n * @property {Number} [maxZoomPixelRatio=1.1]\n * The maximum ratio to allow a zoom-in to affect the highest level pixel\n * ratio. This can be set to Infinity to allow 'infinite' zooming into the\n * image though it is less effective visually if the HTML5 Canvas is not\n * availble on the viewing device.\n *\n * @property {Number} [smoothTileEdgesMinZoom=1.1]\n * A zoom percentage ( where 1 is 100% ) of the highest resolution level.\n * When zoomed in beyond this value alternative compositing will be used to\n * smooth out the edges between tiles. This will have a performance impact.\n * Can be set to Infinity to turn it off.\n * Note: This setting is ignored on iOS devices due to a known bug (See {@link https://github.com/openseadragon/openseadragon/issues/952})\n *\n * @property {Boolean} [iOSDevice=?]\n * True if running on an iOS device, false otherwise.\n * Used to disable certain features that behave differently on iOS devices.\n *\n * @property {Boolean} [autoResize=true]\n * Set to false to prevent polling for viewer size changes. Useful for providing custom resize behavior.\n *\n * @property {Boolean} [preserveImageSizeOnResize=false]\n * Set to true to have the image size preserved when the viewer is resized. This requires autoResize=true (default).\n *\n * @property {Number} [minScrollDeltaTime=50]\n * Number of milliseconds between canvas-scroll events. This value helps normalize the rate of canvas-scroll\n * events between different devices, causing the faster devices to slow down enough to make the zoom control\n * more manageable.\n *\n * @property {Number} [pixelsPerWheelLine=40]\n * For pixel-resolution scrolling devices, the number of pixels equal to one scroll line.\n *\n * @property {Number} [pixelsPerArrowPress=40]\n * The number of pixels viewport moves when an arrow key is pressed.\n *\n * @property {Number} [visibilityRatio=0.5]\n * The percentage ( as a number from 0 to 1 ) of the source image which\n * must be kept within the viewport. If the image is dragged beyond that\n * limit, it will 'bounce' back until the minimum visibility ratio is\n * achieved. Setting this to 0 and wrapHorizontal ( or wrapVertical ) to\n * true will provide the effect of an infinitely scrolling viewport.\n *\n * @property {Object} [viewportMargins={}]\n * Pushes the \"home\" region in from the sides by the specified amounts.\n * Possible subproperties (Numbers, in screen coordinates): left, top, right, bottom.\n *\n * @property {Number} [imageLoaderLimit=0]\n * The maximum number of image requests to make concurrently. By default\n * it is set to 0 allowing the browser to make the maximum number of\n * image requests in parallel as allowed by the browsers policy.\n *\n * @property {Number} [clickTimeThreshold=300]\n * The number of milliseconds within which a pointer down-up event combination\n * will be treated as a click gesture.\n *\n * @property {Number} [clickDistThreshold=5]\n * The maximum distance allowed between a pointer down event and a pointer up event\n * to be treated as a click gesture.\n *\n * @property {Number} [dblClickTimeThreshold=300]\n * The number of milliseconds within which two pointer down-up event combinations\n * will be treated as a double-click gesture.\n *\n * @property {Number} [dblClickDistThreshold=20]\n * The maximum distance allowed between two pointer click events\n * to be treated as a double-click gesture.\n *\n * @property {Number} [springStiffness=6.5]\n *\n * @property {Number} [animationTime=1.2]\n * Specifies the animation duration per each {@link OpenSeadragon.Spring}\n * which occur when the image is dragged or zoomed.\n *\n * @property {OpenSeadragon.GestureSettings} [gestureSettingsMouse]\n * Settings for gestures generated by a mouse pointer device. (See {@link OpenSeadragon.GestureSettings})\n * @property {Boolean} [gestureSettingsMouse.scrollToZoom=true] - Zoom on scroll gesture\n * @property {Boolean} [gestureSettingsMouse.clickToZoom=true] - Zoom on click gesture\n * @property {Boolean} [gestureSettingsMouse.dblClickToZoom=false] - Zoom on double-click gesture. Note: If set to true\n * then clickToZoom should be set to false to prevent multiple zooms.\n * @property {Boolean} [gestureSettingsMouse.pinchToZoom=false] - Zoom on pinch gesture\n * @property {Boolean} [gestureSettingsMouse.zoomToRefPoint=true] - If zoomToRefPoint is true, the zoom is centered at the pointer position. Otherwise,\n * the zoom is centered at the canvas center.\n * @property {Boolean} [gestureSettingsMouse.flickEnabled=false] - Enable flick gesture\n * @property {Number} [gestureSettingsMouse.flickMinSpeed=120] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second)\n * @property {Number} [gestureSettingsMouse.flickMomentum=0.25] - If flickEnabled is true, the momentum factor for the flick gesture\n * @property {Boolean} [gestureSettingsMouse.pinchRotate=false] - If pinchRotate is true, the user will have the ability to rotate the image using their fingers.\n *\n * @property {OpenSeadragon.GestureSettings} [gestureSettingsTouch]\n * Settings for gestures generated by a touch pointer device. (See {@link OpenSeadragon.GestureSettings})\n * @property {Boolean} [gestureSettingsTouch.scrollToZoom=false] - Zoom on scroll gesture\n * @property {Boolean} [gestureSettingsTouch.clickToZoom=false] - Zoom on click gesture\n * @property {Boolean} [gestureSettingsTouch.dblClickToZoom=true] - Zoom on double-click gesture. Note: If set to true\n * then clickToZoom should be set to false to prevent multiple zooms.\n * @property {Boolean} [gestureSettingsTouch.pinchToZoom=true] - Zoom on pinch gesture\n * @property {Boolean} [gestureSettingsTouch.zoomToRefPoint=true] - If zoomToRefPoint is true, the zoom is centered at the pointer position. Otherwise,\n * the zoom is centered at the canvas center.\n * @property {Boolean} [gestureSettingsTouch.flickEnabled=true] - Enable flick gesture\n * @property {Number} [gestureSettingsTouch.flickMinSpeed=120] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second)\n * @property {Number} [gestureSettingsTouch.flickMomentum=0.25] - If flickEnabled is true, the momentum factor for the flick gesture\n * @property {Boolean} [gestureSettingsTouch.pinchRotate=false] - If pinchRotate is true, the user will have the ability to rotate the image using their fingers.\n *\n * @property {OpenSeadragon.GestureSettings} [gestureSettingsPen]\n * Settings for gestures generated by a pen pointer device. (See {@link OpenSeadragon.GestureSettings})\n * @property {Boolean} [gestureSettingsPen.scrollToZoom=false] - Zoom on scroll gesture\n * @property {Boolean} [gestureSettingsPen.clickToZoom=true] - Zoom on click gesture\n * @property {Boolean} [gestureSettingsPen.dblClickToZoom=false] - Zoom on double-click gesture. Note: If set to true\n * then clickToZoom should be set to false to prevent multiple zooms.\n * @property {Boolean} [gestureSettingsPen.pinchToZoom=false] - Zoom on pinch gesture\n * @property {Boolean} [gestureSettingsPan.zoomToRefPoint=true] - If zoomToRefPoint is true, the zoom is centered at the pointer position. Otherwise,\n * the zoom is centered at the canvas center.\n * @property {Boolean} [gestureSettingsPen.flickEnabled=false] - Enable flick gesture\n * @property {Number} [gestureSettingsPen.flickMinSpeed=120] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second)\n * @property {Number} [gestureSettingsPen.flickMomentum=0.25] - If flickEnabled is true, the momentum factor for the flick gesture\n * @property {Boolean} [gestureSettingsPen.pinchRotate=false] - If pinchRotate is true, the user will have the ability to rotate the image using their fingers.\n *\n * @property {OpenSeadragon.GestureSettings} [gestureSettingsUnknown]\n * Settings for gestures generated by unknown pointer devices. (See {@link OpenSeadragon.GestureSettings})\n * @property {Boolean} [gestureSettingsUnknown.scrollToZoom=true] - Zoom on scroll gesture\n * @property {Boolean} [gestureSettingsUnknown.clickToZoom=false] - Zoom on click gesture\n * @property {Boolean} [gestureSettingsUnknown.dblClickToZoom=true] - Zoom on double-click gesture. Note: If set to true\n * then clickToZoom should be set to false to prevent multiple zooms.\n * @property {Boolean} [gestureSettingsUnknown.pinchToZoom=true] - Zoom on pinch gesture\n * @property {Boolean} [gestureSettingsUnknown.zoomToRefPoint=true] - If zoomToRefPoint is true, the zoom is centered at the pointer position. Otherwise,\n * the zoom is centered at the canvas center.\n * @property {Boolean} [gestureSettingsUnknown.flickEnabled=true] - Enable flick gesture\n * @property {Number} [gestureSettingsUnknown.flickMinSpeed=120] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second)\n * @property {Number} [gestureSettingsUnknown.flickMomentum=0.25] - If flickEnabled is true, the momentum factor for the flick gesture\n * @property {Boolean} [gestureSettingsUnknown.pinchRotate=false] - If pinchRotate is true, the user will have the ability to rotate the image using their fingers.\n *\n * @property {Number} [zoomPerClick=2.0]\n * The \"zoom distance\" per mouse click or touch tap. Note: Setting this to 1.0 effectively disables the click-to-zoom feature (also see gestureSettings[Mouse|Touch|Pen].clickToZoom/dblClickToZoom).\n *\n * @property {Number} [zoomPerScroll=1.2]\n * The \"zoom distance\" per mouse scroll or touch pinch. Note: Setting this to 1.0 effectively disables the mouse-wheel zoom feature (also see gestureSettings[Mouse|Touch|Pen].scrollToZoom}).\n *\n * @property {Number} [zoomPerSecond=1.0]\n * The number of seconds to animate a single zoom event over.\n *\n * @property {Boolean} [showNavigator=false]\n * Set to true to make the navigator minimap appear.\n *\n * @property {String} [navigatorId=navigator-GENERATED DATE]\n * The ID of a div to hold the navigator minimap.\n * If an ID is specified, the navigatorPosition, navigatorSizeRatio, navigatorMaintainSizeRatio, navigator[Top|Left|Height|Width] and navigatorAutoFade options will be ignored.\n * If an ID is not specified, a div element will be generated and placed on top of the main image.\n *\n * @property {String} [navigatorPosition='TOP_RIGHT']\n * Valid values are 'TOP_LEFT', 'TOP_RIGHT', 'BOTTOM_LEFT', 'BOTTOM_RIGHT', or 'ABSOLUTE'.
\n * If 'ABSOLUTE' is specified, then navigator[Top|Left|Height|Width] determines the size and position of the navigator minimap in the viewer, and navigatorSizeRatio and navigatorMaintainSizeRatio are ignored.
\n * For 'TOP_LEFT', 'TOP_RIGHT', 'BOTTOM_LEFT', and 'BOTTOM_RIGHT', the navigatorSizeRatio or navigator[Height|Width] values determine the size of the navigator minimap.\n *\n * @property {Number} [navigatorSizeRatio=0.2]\n * Ratio of navigator size to viewer size. Ignored if navigator[Height|Width] are specified.\n *\n * @property {Boolean} [navigatorMaintainSizeRatio=false]\n * If true, the navigator minimap is resized (using navigatorSizeRatio) when the viewer size changes.\n *\n * @property {Number|String} [navigatorTop=null]\n * Specifies the location of the navigator minimap (see navigatorPosition).\n *\n * @property {Number|String} [navigatorLeft=null]\n * Specifies the location of the navigator minimap (see navigatorPosition).\n *\n * @property {Number|String} [navigatorHeight=null]\n * Specifies the size of the navigator minimap (see navigatorPosition).\n * If specified, navigatorSizeRatio and navigatorMaintainSizeRatio are ignored.\n *\n * @property {Number|String} [navigatorWidth=null]\n * Specifies the size of the navigator minimap (see navigatorPosition).\n * If specified, navigatorSizeRatio and navigatorMaintainSizeRatio are ignored.\n *\n * @property {Boolean} [navigatorAutoResize=true]\n * Set to false to prevent polling for navigator size changes. Useful for providing custom resize behavior.\n * Setting to false can also improve performance when the navigator is configured to a fixed size.\n *\n * @property {Boolean} [navigatorAutoFade=true]\n * If the user stops interacting with the viewport, fade the navigator minimap.\n * Setting to false will make the navigator minimap always visible.\n *\n * @property {Boolean} [navigatorRotate=true]\n * If true, the navigator will be rotated together with the viewer.\n *\n * @property {Number} [controlsFadeDelay=2000]\n * The number of milliseconds to wait once the user has stopped interacting\n * with the interface before begining to fade the controls. Assumes\n * showNavigationControl and autoHideControls are both true.\n *\n * @property {Number} [controlsFadeLength=1500]\n * The number of milliseconds to animate the controls fading out.\n *\n * @property {Number} [maxImageCacheCount=200]\n * The max number of images we should keep in memory (per drawer).\n *\n * @property {Number} [timeout=30000]\n * The max number of milliseconds that an image job may take to complete.\n *\n * @property {Boolean} [useCanvas=true]\n * Set to false to not use an HTML canvas element for image rendering even if canvas is supported.\n *\n * @property {Number} [minPixelRatio=0.5]\n * The higher the minPixelRatio, the lower the quality of the image that\n * is considered sufficient to stop rendering a given zoom level. For\n * example, if you are targeting mobile devices with less bandwith you may\n * try setting this to 1.5 or higher.\n *\n * @property {Boolean} [mouseNavEnabled=true]\n * Is the user able to interact with the image via mouse or touch. Default\n * interactions include draging the image in a plane, and zooming in toward\n * and away from the image.\n *\n * @property {Boolean} [showNavigationControl=true]\n * Set to false to prevent the appearance of the default navigation controls.
\n * Note that if set to false, the customs buttons set by the options\n * zoomInButton, zoomOutButton etc, are rendered inactive.\n *\n * @property {OpenSeadragon.ControlAnchor} [navigationControlAnchor=TOP_LEFT]\n * Placement of the default navigation controls.\n * To set the placement of the sequence controls, see the\n * sequenceControlAnchor option.\n *\n * @property {Boolean} [showZoomControl=true]\n * If true then + and - buttons to zoom in and out are displayed.
\n * Note: {@link OpenSeadragon.Options.showNavigationControl} is overriding\n * this setting when set to false.\n *\n * @property {Boolean} [showHomeControl=true]\n * If true then the 'Go home' button is displayed to go back to the original\n * zoom and pan.
\n * Note: {@link OpenSeadragon.Options.showNavigationControl} is overriding\n * this setting when set to false.\n *\n * @property {Boolean} [showFullPageControl=true]\n * If true then the 'Toggle full page' button is displayed to switch\n * between full page and normal mode.
\n * Note: {@link OpenSeadragon.Options.showNavigationControl} is overriding\n * this setting when set to false.\n *\n * @property {Boolean} [showRotationControl=false]\n * If true then the rotate left/right controls will be displayed as part of the\n * standard controls. This is also subject to the browser support for rotate\n * (e.g. viewer.drawer.canRotate()).
\n * Note: {@link OpenSeadragon.Options.showNavigationControl} is overriding\n * this setting when set to false.\n *\n * @property {Boolean} [showFlipControl=false]\n * If true then the flip controls will be displayed as part of the\n * standard controls.\n *\n * @property {Boolean} [showSequenceControl=true]\n * If sequenceMode is true, then provide buttons for navigating forward and\n * backward through the images.\n *\n * @property {OpenSeadragon.ControlAnchor} [sequenceControlAnchor=TOP_LEFT]\n * Placement of the default sequence controls.\n *\n * @property {Boolean} [navPrevNextWrap=false]\n * If true then the 'previous' button will wrap to the last image when\n * viewing the first image and the 'next' button will wrap to the first\n * image when viewing the last image.\n *\n * @property {String} zoomInButton\n * Set the id of the custom 'Zoom in' button to use.\n * This is useful to have a custom button anywhere in the web page.
\n * To only change the button images, consider using\n * {@link OpenSeadragon.Options.navImages}\n *\n * @property {String} zoomOutButton\n * Set the id of the custom 'Zoom out' button to use.\n * This is useful to have a custom button anywhere in the web page.
\n * To only change the button images, consider using\n * {@link OpenSeadragon.Options.navImages}\n *\n * @property {String} homeButton\n * Set the id of the custom 'Go home' button to use.\n * This is useful to have a custom button anywhere in the web page.
\n * To only change the button images, consider using\n * {@link OpenSeadragon.Options.navImages}\n *\n * @property {String} fullPageButton\n * Set the id of the custom 'Toggle full page' button to use.\n * This is useful to have a custom button anywhere in the web page.
\n * To only change the button images, consider using\n * {@link OpenSeadragon.Options.navImages}\n *\n * @property {String} rotateLeftButton\n * Set the id of the custom 'Rotate left' button to use.\n * This is useful to have a custom button anywhere in the web page.
\n * To only change the button images, consider using\n * {@link OpenSeadragon.Options.navImages}\n *\n * @property {String} rotateRightButton\n * Set the id of the custom 'Rotate right' button to use.\n * This is useful to have a custom button anywhere in the web page.
\n * To only change the button images, consider using\n * {@link OpenSeadragon.Options.navImages}\n *\n * @property {String} previousButton\n * Set the id of the custom 'Previous page' button to use.\n * This is useful to have a custom button anywhere in the web page.
\n * To only change the button images, consider using\n * {@link OpenSeadragon.Options.navImages}\n *\n * @property {String} nextButton\n * Set the id of the custom 'Next page' button to use.\n * This is useful to have a custom button anywhere in the web page.
\n * To only change the button images, consider using\n * {@link OpenSeadragon.Options.navImages}\n *\n * @property {Boolean} [sequenceMode=false]\n * Set to true to have the viewer treat your tilesources as a sequence of images to\n * be opened one at a time rather than all at once.\n *\n * @property {Number} [initialPage=0]\n * If sequenceMode is true, display this page initially.\n *\n * @property {Boolean} [preserveViewport=false]\n * If sequenceMode is true, then normally navigating through each image resets the\n * viewport to 'home' position. If preserveViewport is set to true, then the viewport\n * position is preserved when navigating between images in the sequence.\n *\n * @property {Boolean} [preserveOverlays=false]\n * If sequenceMode is true, then normally navigating through each image\n * resets the overlays.\n * If preserveOverlays is set to true, then the overlays added with {@link OpenSeadragon.Viewer#addOverlay}\n * are preserved when navigating between images in the sequence.\n * Note: setting preserveOverlays overrides any overlays specified in the global\n * \"overlays\" option for the Viewer. It's also not compatible with specifying\n * per-tileSource overlays via the options, as those overlays will persist\n * even after the tileSource is closed.\n *\n * @property {Boolean} [showReferenceStrip=false]\n * If sequenceMode is true, then display a scrolling strip of image thumbnails for\n * navigating through the images.\n *\n * @property {String} [referenceStripScroll='horizontal']\n *\n * @property {Element} [referenceStripElement=null]\n *\n * @property {Number} [referenceStripHeight=null]\n *\n * @property {Number} [referenceStripWidth=null]\n *\n * @property {String} [referenceStripPosition='BOTTOM_LEFT']\n *\n * @property {Number} [referenceStripSizeRatio=0.2]\n *\n * @property {Boolean} [collectionMode=false]\n * Set to true to have the viewer arrange your TiledImages in a grid or line.\n *\n * @property {Number} [collectionRows=3]\n * If collectionMode is true, specifies how many rows the grid should have. Use 1 to make a line.\n * If collectionLayout is 'vertical', specifies how many columns instead.\n *\n * @property {Number} [collectionColumns=0]\n * If collectionMode is true, specifies how many columns the grid should have. Use 1 to make a line.\n * If collectionLayout is 'vertical', specifies how many rows instead. Ignored if collectionRows is not set to a falsy value.\n *\n * @property {String} [collectionLayout='horizontal']\n * If collectionMode is true, specifies whether to arrange vertically or horizontally.\n *\n * @property {Number} [collectionTileSize=800]\n * If collectionMode is true, specifies the size, in viewport coordinates, for each TiledImage to fit into.\n * The TiledImage will be centered within a square of the specified size.\n *\n * @property {Number} [collectionTileMargin=80]\n * If collectionMode is true, specifies the margin, in viewport coordinates, between each TiledImage.\n *\n * @property {String|Boolean} [crossOriginPolicy=false]\n * Valid values are 'Anonymous', 'use-credentials', and false. If false, canvas requests will\n * not use CORS, and the canvas will be tainted.\n *\n * @property {Boolean} [ajaxWithCredentials=false]\n * Whether to set the withCredentials XHR flag for AJAX requests.\n * Note that this can be overridden at the {@link OpenSeadragon.TileSource} level.\n *\n * @property {Boolean} [loadTilesWithAjax=false]\n * Whether to load tile data using AJAX requests.\n * Note that this can be overridden at the {@link OpenSeadragon.TileSource} level.\n *\n * @property {Object} [ajaxHeaders={}]\n * A set of headers to include when making AJAX requests for tile sources or tiles.\n *\n */ /**\n * Settings for gestures generated by a pointer device.\n *\n * @typedef {Object} GestureSettings\n * @memberof OpenSeadragon\n *\n * @property {Boolean} scrollToZoom\n * Set to false to disable zooming on scroll gestures.\n *\n * @property {Boolean} clickToZoom\n * Set to false to disable zooming on click gestures.\n *\n * @property {Boolean} dblClickToZoom\n * Set to false to disable zooming on double-click gestures. Note: If set to true\n * then clickToZoom should be set to false to prevent multiple zooms.\n *\n * @property {Boolean} pinchToZoom\n * Set to false to disable zooming on pinch gestures.\n *\n * @property {Boolean} flickEnabled\n * Set to false to disable the kinetic panning effect (flick) at the end of a drag gesture.\n *\n * @property {Number} flickMinSpeed\n * If flickEnabled is true, the minimum speed (in pixels-per-second) required to cause the kinetic panning effect (flick) at the end of a drag gesture.\n *\n * @property {Number} flickMomentum\n * If flickEnabled is true, a constant multiplied by the velocity to determine the distance of the kinetic panning effect (flick) at the end of a drag gesture.\n * A larger value will make the flick feel \"lighter\", while a smaller value will make the flick feel \"heavier\".\n * Note: springStiffness and animationTime also affect the \"spring\" used to stop the flick animation.\n *\n */ /**\n * The names for the image resources used for the image navigation buttons.\n *\n * @typedef {Object} NavImages\n * @memberof OpenSeadragon\n *\n * @property {Object} zoomIn - Images for the zoom-in button.\n * @property {String} zoomIn.REST\n * @property {String} zoomIn.GROUP\n * @property {String} zoomIn.HOVER\n * @property {String} zoomIn.DOWN\n *\n * @property {Object} zoomOut - Images for the zoom-out button.\n * @property {String} zoomOut.REST\n * @property {String} zoomOut.GROUP\n * @property {String} zoomOut.HOVER\n * @property {String} zoomOut.DOWN\n *\n * @property {Object} home - Images for the home button.\n * @property {String} home.REST\n * @property {String} home.GROUP\n * @property {String} home.HOVER\n * @property {String} home.DOWN\n *\n * @property {Object} fullpage - Images for the full-page button.\n * @property {String} fullpage.REST\n * @property {String} fullpage.GROUP\n * @property {String} fullpage.HOVER\n * @property {String} fullpage.DOWN\n *\n * @property {Object} rotateleft - Images for the rotate left button.\n * @property {String} rotateleft.REST\n * @property {String} rotateleft.GROUP\n * @property {String} rotateleft.HOVER\n * @property {String} rotateleft.DOWN\n *\n * @property {Object} rotateright - Images for the rotate right button.\n * @property {String} rotateright.REST\n * @property {String} rotateright.GROUP\n * @property {String} rotateright.HOVER\n * @property {String} rotateright.DOWN\n *\n * @property {Object} flip - Images for the flip button.\n * @property {String} flip.REST\n * @property {String} flip.GROUP\n * @property {String} flip.HOVER\n * @property {String} flip.DOWN\n *\n * @property {Object} previous - Images for the previous button.\n * @property {String} previous.REST\n * @property {String} previous.GROUP\n * @property {String} previous.HOVER\n * @property {String} previous.DOWN\n *\n * @property {Object} next - Images for the next button.\n * @property {String} next.REST\n * @property {String} next.GROUP\n * @property {String} next.HOVER\n * @property {String} next.DOWN\n *\n */function OpenSeadragon(options){return new OpenSeadragon.Viewer(options);}(function($){/**\n * The OpenSeadragon version.\n *\n * @member {Object} OpenSeadragon.version\n * @property {String} versionStr - The version number as a string ('major.minor.revision').\n * @property {Number} major - The major version number.\n * @property {Number} minor - The minor version number.\n * @property {Number} revision - The revision number.\n * @since 1.0.0\n */$.version={versionStr:'2.3.1',major:parseInt('2',10),minor:parseInt('3',10),revision:parseInt('1',10)};/**\n * Taken from jquery 1.6.1\n * [[Class]] -> type pairs\n * @private\n */var class2type={'[object Boolean]':'boolean','[object Number]':'number','[object String]':'string','[object Function]':'function','[object Array]':'array','[object Date]':'date','[object RegExp]':'regexp','[object Object]':'object'},// Save a reference to some core methods\ntoString=Object.prototype.toString,hasOwn=Object.prototype.hasOwnProperty;/**\n * Taken from jQuery 1.6.1\n * @function isFunction\n * @memberof OpenSeadragon\n * @see {@link http://www.jquery.com/ jQuery}\n */$.isFunction=function(obj){return $.type(obj)===\"function\";};/**\n * Taken from jQuery 1.6.1\n * @function isArray\n * @memberof OpenSeadragon\n * @see {@link http://www.jquery.com/ jQuery}\n */$.isArray=Array.isArray||function(obj){return $.type(obj)===\"array\";};/**\n * A crude way of determining if an object is a window.\n * Taken from jQuery 1.6.1\n * @function isWindow\n * @memberof OpenSeadragon\n * @see {@link http://www.jquery.com/ jQuery}\n */$.isWindow=function(obj){return obj&&_typeof(obj)===\"object\"&&\"setInterval\"in obj;};/**\n * Taken from jQuery 1.6.1\n * @function type\n * @memberof OpenSeadragon\n * @see {@link http://www.jquery.com/ jQuery}\n */$.type=function(obj){return obj===null||obj===undefined?String(obj):class2type[toString.call(obj)]||\"object\";};/**\n * Taken from jQuery 1.6.1\n * @function isPlainObject\n * @memberof OpenSeadragon\n * @see {@link http://www.jquery.com/ jQuery}\n */$.isPlainObject=function(obj){// Must be an Object.\n// Because of IE, we also have to check the presence of the constructor property.\n// Make sure that DOM nodes and window objects don't pass through, as well\nif(!obj||OpenSeadragon.type(obj)!==\"object\"||obj.nodeType||$.isWindow(obj)){return false;}// Not own constructor property must be Object\nif(obj.constructor&&!hasOwn.call(obj,\"constructor\")&&!hasOwn.call(obj.constructor.prototype,\"isPrototypeOf\")){return false;}// Own properties are enumerated firstly, so to speed up,\n// if last one is own, then all properties are own.\nvar lastKey;for(var key in obj){lastKey=key;}return lastKey===undefined||hasOwn.call(obj,lastKey);};/**\n * Taken from jQuery 1.6.1\n * @function isEmptyObject\n * @memberof OpenSeadragon\n * @see {@link http://www.jquery.com/ jQuery}\n */$.isEmptyObject=function(obj){for(var name in obj){return false;}return true;};/**\n * Shim around Object.freeze. Does nothing if Object.freeze is not supported.\n * @param {Object} obj The object to freeze.\n * @return {Object} obj The frozen object.\n */$.freezeObject=function(obj){if(Object.freeze){$.freezeObject=Object.freeze;}else{$.freezeObject=function(obj){return obj;};}return $.freezeObject(obj);};/**\n * True if the browser supports the HTML5 canvas element\n * @member {Boolean} supportsCanvas\n * @memberof OpenSeadragon\n */$.supportsCanvas=function(){var canvasElement=document.createElement('canvas');return!!($.isFunction(canvasElement.getContext)&&canvasElement.getContext('2d'));}();/**\n * Test whether the submitted canvas is tainted or not.\n * @argument {Canvas} canvas The canvas to test.\n * @returns {Boolean} True if the canvas is tainted.\n */$.isCanvasTainted=function(canvas){var isTainted=false;try{// We test if the canvas is tainted by retrieving data from it.\n// An exception will be raised if the canvas is tainted.\ncanvas.getContext('2d').getImageData(0,0,1,1);}catch(e){isTainted=true;}return isTainted;};/**\n * A ratio comparing the device screen's pixel density to the canvas's backing store pixel density,\n * clamped to a minimum of 1. Defaults to 1 if canvas isn't supported by the browser.\n * @member {Number} pixelDensityRatio\n * @memberof OpenSeadragon\n */$.pixelDensityRatio=function(){if($.supportsCanvas){var context=document.createElement('canvas').getContext('2d');var devicePixelRatio=window.devicePixelRatio||1;var backingStoreRatio=context.webkitBackingStorePixelRatio||context.mozBackingStorePixelRatio||context.msBackingStorePixelRatio||context.oBackingStorePixelRatio||context.backingStorePixelRatio||1;return Math.max(devicePixelRatio,1)/backingStoreRatio;}else{return 1;}}();})(OpenSeadragon);/**\n * This closure defines all static methods available to the OpenSeadragon\n * namespace. Many, if not most, are taked directly from jQuery for use\n * to simplify and reduce common programming patterns. More static methods\n * from jQuery may eventually make their way into this though we are\n * attempting to avoid an explicit dependency on jQuery only because\n * OpenSeadragon is a broadly useful code base and would be made less broad\n * by requiring jQuery fully.\n *\n * Some static methods have also been refactored from the original OpenSeadragon\n * project.\n */(function($){/**\n * Taken from jQuery 1.6.1\n * @function extend\n * @memberof OpenSeadragon\n * @see {@link http://www.jquery.com/ jQuery}\n */$.extend=function(){var options,name,src,copy,copyIsArray,clone,target=arguments[0]||{},length=arguments.length,deep=false,i=1;// Handle a deep copy situation\nif(typeof target===\"boolean\"){deep=target;target=arguments[1]||{};// skip the boolean and the target\ni=2;}// Handle case when target is a string or something (possible in deep copy)\nif(_typeof(target)!==\"object\"&&!OpenSeadragon.isFunction(target)){target={};}// extend jQuery itself if only one argument is passed\nif(length===i){target=this;--i;}for(;i how much of the viewer can be negative space\nminPixelRatio:0.5,//->closer to 0 draws tiles meant for a higher zoom at this zoom\ndefaultZoomLevel:0,minZoomLevel:null,maxZoomLevel:null,homeFillsViewer:false,//UI RESPONSIVENESS AND FEEL\nclickTimeThreshold:300,clickDistThreshold:5,dblClickTimeThreshold:300,dblClickDistThreshold:20,springStiffness:6.5,animationTime:1.2,gestureSettingsMouse:{scrollToZoom:true,clickToZoom:true,dblClickToZoom:false,pinchToZoom:false,zoomToRefPoint:true,flickEnabled:false,flickMinSpeed:120,flickMomentum:0.25,pinchRotate:false},gestureSettingsTouch:{scrollToZoom:false,clickToZoom:false,dblClickToZoom:true,pinchToZoom:true,zoomToRefPoint:true,flickEnabled:true,flickMinSpeed:120,flickMomentum:0.25,pinchRotate:false},gestureSettingsPen:{scrollToZoom:false,clickToZoom:true,dblClickToZoom:false,pinchToZoom:false,zoomToRefPoint:true,flickEnabled:false,flickMinSpeed:120,flickMomentum:0.25,pinchRotate:false},gestureSettingsUnknown:{scrollToZoom:false,clickToZoom:false,dblClickToZoom:true,pinchToZoom:true,zoomToRefPoint:true,flickEnabled:true,flickMinSpeed:120,flickMomentum:0.25,pinchRotate:false},zoomPerClick:2,zoomPerScroll:1.2,zoomPerSecond:1.0,blendTime:0,alwaysBlend:false,autoHideControls:true,immediateRender:false,minZoomImageRatio:0.9,//-> closer to 0 allows zoom out to infinity\nmaxZoomPixelRatio:1.1,//-> higher allows 'over zoom' into pixels\nsmoothTileEdgesMinZoom:1.1,//-> higher than maxZoomPixelRatio disables it\niOSDevice:isIOSDevice(),pixelsPerWheelLine:40,pixelsPerArrowPress:40,autoResize:true,preserveImageSizeOnResize:false,// requires autoResize=true\nminScrollDeltaTime:50,//DEFAULT CONTROL SETTINGS\nshowSequenceControl:true,//SEQUENCE\nsequenceControlAnchor:null,//SEQUENCE\npreserveViewport:false,//SEQUENCE\npreserveOverlays:false,//SEQUENCE\nnavPrevNextWrap:false,//SEQUENCE\nshowNavigationControl:true,//ZOOM/HOME/FULL/ROTATION\nnavigationControlAnchor:null,//ZOOM/HOME/FULL/ROTATION\nshowZoomControl:true,//ZOOM\nshowHomeControl:true,//HOME\nshowFullPageControl:true,//FULL\nshowRotationControl:false,//ROTATION\nshowFlipControl:false,//FLIP\ncontrolsFadeDelay:2000,//ZOOM/HOME/FULL/SEQUENCE\ncontrolsFadeLength:1500,//ZOOM/HOME/FULL/SEQUENCE\nmouseNavEnabled:true,//GENERAL MOUSE INTERACTIVITY\n//VIEWPORT NAVIGATOR SETTINGS\nshowNavigator:false,navigatorId:null,navigatorPosition:null,navigatorSizeRatio:0.2,navigatorMaintainSizeRatio:false,navigatorTop:null,navigatorLeft:null,navigatorHeight:null,navigatorWidth:null,navigatorAutoResize:true,navigatorAutoFade:true,navigatorRotate:true,// INITIAL ROTATION\ndegrees:0,// INITIAL FLIP STATE\nflipped:false,// APPEARANCE\nopacity:1,preload:false,compositeOperation:null,placeholderFillStyle:null,//REFERENCE STRIP SETTINGS\nshowReferenceStrip:false,referenceStripScroll:'horizontal',referenceStripElement:null,referenceStripHeight:null,referenceStripWidth:null,referenceStripPosition:'BOTTOM_LEFT',referenceStripSizeRatio:0.2,//COLLECTION VISUALIZATION SETTINGS\ncollectionRows:3,//or columns depending on layout\ncollectionColumns:0,//columns in horizontal layout, rows in vertical layout\ncollectionLayout:'horizontal',//vertical\ncollectionMode:false,collectionTileSize:800,collectionTileMargin:80,//PERFORMANCE SETTINGS\nimageLoaderLimit:0,maxImageCacheCount:200,timeout:30000,useCanvas:true,// Use canvas element for drawing if available\n//INTERFACE RESOURCE SETTINGS\nprefixUrl:\"/images/\",navImages:{zoomIn:{REST:'zoomin_rest.png',GROUP:'zoomin_grouphover.png',HOVER:'zoomin_hover.png',DOWN:'zoomin_pressed.png'},zoomOut:{REST:'zoomout_rest.png',GROUP:'zoomout_grouphover.png',HOVER:'zoomout_hover.png',DOWN:'zoomout_pressed.png'},home:{REST:'home_rest.png',GROUP:'home_grouphover.png',HOVER:'home_hover.png',DOWN:'home_pressed.png'},fullpage:{REST:'fullpage_rest.png',GROUP:'fullpage_grouphover.png',HOVER:'fullpage_hover.png',DOWN:'fullpage_pressed.png'},rotateleft:{REST:'rotateleft_rest.png',GROUP:'rotateleft_grouphover.png',HOVER:'rotateleft_hover.png',DOWN:'rotateleft_pressed.png'},rotateright:{REST:'rotateright_rest.png',GROUP:'rotateright_grouphover.png',HOVER:'rotateright_hover.png',DOWN:'rotateright_pressed.png'},flip:{// Flip icon designed by Yaroslav Samoylov from the Noun Project and modified by Nelson Campos ncampos@criteriamarathon.com, https://thenounproject.com/term/flip/136289/\nREST:'flip_rest.png',GROUP:'flip_grouphover.png',HOVER:'flip_hover.png',DOWN:'flip_pressed.png'},previous:{REST:'previous_rest.png',GROUP:'previous_grouphover.png',HOVER:'previous_hover.png',DOWN:'previous_pressed.png'},next:{REST:'next_rest.png',GROUP:'next_grouphover.png',HOVER:'next_hover.png',DOWN:'next_pressed.png'}},//DEVELOPER SETTINGS\ndebugMode:false,debugGridColor:['#437AB2','#1B9E77','#D95F02','#7570B3','#E7298A','#66A61E','#E6AB02','#A6761D','#666666']},/**\n * TODO: get rid of this. I can't see how it's required at all. Looks\n * like an early legacy code artifact.\n * @static\n * @ignore\n */SIGNAL:\"----seadragon----\",/**\n * Returns a function which invokes the method as if it were a method belonging to the object.\n * @function\n * @param {Object} object\n * @param {Function} method\n * @returns {Function}\n */delegate:function delegate(object,method){return function(){var args=arguments;if(args===undefined){args=[];}return method.apply(object,args);};},/**\n * An enumeration of Browser vendors.\n * @static\n * @type {Object}\n * @property {Number} UNKNOWN\n * @property {Number} IE\n * @property {Number} FIREFOX\n * @property {Number} SAFARI\n * @property {Number} CHROME\n * @property {Number} OPERA\n */BROWSERS:{UNKNOWN:0,IE:1,FIREFOX:2,SAFARI:3,CHROME:4,OPERA:5},/**\n * Returns a DOM Element for the given id or element.\n * @function\n * @param {String|Element} element Accepts an id or element.\n * @returns {Element} The element with the given id, null, or the element itself.\n */getElement:function getElement(element){if(typeof element==\"string\"){element=document.getElementById(element);}return element;},/**\n * Determines the position of the upper-left corner of the element.\n * @function\n * @param {Element|String} element - the elemenet we want the position for.\n * @returns {OpenSeadragon.Point} - the position of the upper left corner of the element.\n */getElementPosition:function getElementPosition(element){var result=new $.Point(),isFixed,offsetParent;element=$.getElement(element);isFixed=$.getElementStyle(element).position==\"fixed\";offsetParent=getOffsetParent(element,isFixed);while(offsetParent){result.x+=element.offsetLeft;result.y+=element.offsetTop;if(isFixed){result=result.plus($.getPageScroll());}element=offsetParent;isFixed=$.getElementStyle(element).position==\"fixed\";offsetParent=getOffsetParent(element,isFixed);}return result;},/**\n * Determines the position of the upper-left corner of the element adjusted for current page and/or element scroll.\n * @function\n * @param {Element|String} element - the element we want the position for.\n * @returns {OpenSeadragon.Point} - the position of the upper left corner of the element adjusted for current page and/or element scroll.\n */getElementOffset:function getElementOffset(element){element=$.getElement(element);var doc=element&&element.ownerDocument,docElement,win,boundingRect={top:0,left:0};if(!doc){return new $.Point();}docElement=doc.documentElement;if(_typeof(element.getBoundingClientRect)!==( true?\"undefined\":undefined)){boundingRect=element.getBoundingClientRect();}win=doc==doc.window?doc:doc.nodeType===9?doc.defaultView||doc.parentWindow:false;return new $.Point(boundingRect.left+(win.pageXOffset||docElement.scrollLeft)-(docElement.clientLeft||0),boundingRect.top+(win.pageYOffset||docElement.scrollTop)-(docElement.clientTop||0));},/**\n * Determines the height and width of the given element.\n * @function\n * @param {Element|String} element\n * @returns {OpenSeadragon.Point}\n */getElementSize:function getElementSize(element){element=$.getElement(element);return new $.Point(element.clientWidth,element.clientHeight);},/**\n * Returns the CSSStyle object for the given element.\n * @function\n * @param {Element|String} element\n * @returns {CSSStyle}\n */getElementStyle:document.documentElement.currentStyle?function(element){element=$.getElement(element);return element.currentStyle;}:function(element){element=$.getElement(element);return window.getComputedStyle(element,\"\");},/**\n * Returns the property with the correct vendor prefix appended.\n * @param {String} property the property name\n * @returns {String} the property with the correct prefix or null if not\n * supported.\n */getCssPropertyWithVendorPrefix:function getCssPropertyWithVendorPrefix(property){var memo={};$.getCssPropertyWithVendorPrefix=function(property){if(memo[property]!==undefined){return memo[property];}var style=document.createElement('div').style;var result=null;if(style[property]!==undefined){result=property;}else{var prefixes=['Webkit','Moz','MS','O','webkit','moz','ms','o'];var suffix=$.capitalizeFirstLetter(property);for(var i=0;i=offset.x&&point.x=offset.y;},/**\n * Gets the latest event, really only useful internally since its\n * specific to IE behavior.\n * @function\n * @param {Event} [event]\n * @returns {Event}\n * @deprecated For internal use only\n * @private\n */getEvent:function getEvent(event){if(event){$.getEvent=function(event){return event;};}else{$.getEvent=function(){return window.event;};}return $.getEvent(event);},/**\n * Gets the position of the mouse on the screen for a given event.\n * @function\n * @param {Event} [event]\n * @returns {OpenSeadragon.Point}\n */getMousePosition:function getMousePosition(event){if(typeof event.pageX==\"number\"){$.getMousePosition=function(event){var result=new $.Point();event=$.getEvent(event);result.x=event.pageX;result.y=event.pageY;return result;};}else if(typeof event.clientX==\"number\"){$.getMousePosition=function(event){var result=new $.Point();event=$.getEvent(event);result.x=event.clientX+document.body.scrollLeft+document.documentElement.scrollLeft;result.y=event.clientY+document.body.scrollTop+document.documentElement.scrollTop;return result;};}else{throw new Error(\"Unknown event mouse position, no known technique.\");}return $.getMousePosition(event);},/**\n * Determines the page's current scroll position.\n * @function\n * @returns {OpenSeadragon.Point}\n */getPageScroll:function getPageScroll(){var docElement=document.documentElement||{},body=document.body||{};if(typeof window.pageXOffset==\"number\"){$.getPageScroll=function(){return new $.Point(window.pageXOffset,window.pageYOffset);};}else if(body.scrollLeft||body.scrollTop){$.getPageScroll=function(){return new $.Point(document.body.scrollLeft,document.body.scrollTop);};}else if(docElement.scrollLeft||docElement.scrollTop){$.getPageScroll=function(){return new $.Point(document.documentElement.scrollLeft,document.documentElement.scrollTop);};}else{// We can't reassign the function yet, as there was no scroll.\nreturn new $.Point(0,0);}return $.getPageScroll();},/**\n * Set the page scroll position.\n * @function\n * @returns {OpenSeadragon.Point}\n */setPageScroll:function setPageScroll(scroll){if(typeof window.scrollTo!==\"undefined\"){$.setPageScroll=function(scroll){window.scrollTo(scroll.x,scroll.y);};}else{var originalScroll=$.getPageScroll();if(originalScroll.x===scroll.x&&originalScroll.y===scroll.y){// We are already correctly positioned and there\n// is no way to detect the correct method.\nreturn;}document.body.scrollLeft=scroll.x;document.body.scrollTop=scroll.y;var currentScroll=$.getPageScroll();if(currentScroll.x!==originalScroll.x&¤tScroll.y!==originalScroll.y){$.setPageScroll=function(scroll){document.body.scrollLeft=scroll.x;document.body.scrollTop=scroll.y;};return;}document.documentElement.scrollLeft=scroll.x;document.documentElement.scrollTop=scroll.y;currentScroll=$.getPageScroll();if(currentScroll.x!==originalScroll.x&¤tScroll.y!==originalScroll.y){$.setPageScroll=function(scroll){document.documentElement.scrollLeft=scroll.x;document.documentElement.scrollTop=scroll.y;};return;}// We can't find anything working, so we do nothing.\n$.setPageScroll=function(scroll){};}return $.setPageScroll(scroll);},/**\n * Determines the size of the browsers window.\n * @function\n * @returns {OpenSeadragon.Point}\n */getWindowSize:function getWindowSize(){var docElement=document.documentElement||{},body=document.body||{};if(typeof window.innerWidth=='number'){$.getWindowSize=function(){return new $.Point(window.innerWidth,window.innerHeight);};}else if(docElement.clientWidth||docElement.clientHeight){$.getWindowSize=function(){return new $.Point(document.documentElement.clientWidth,document.documentElement.clientHeight);};}else if(body.clientWidth||body.clientHeight){$.getWindowSize=function(){return new $.Point(document.body.clientWidth,document.body.clientHeight);};}else{throw new Error(\"Unknown window size, no known technique.\");}return $.getWindowSize();},/**\n * Wraps the given element in a nest of divs so that the element can\n * be easily centered using CSS tables\n * @function\n * @param {Element|String} element\n * @returns {Element} outermost wrapper element\n */makeCenteredNode:function makeCenteredNode(element){// Convert a possible ID to an actual HTMLElement\nelement=$.getElement(element);/*\n CSS tables require you to have a display:table/row/cell hierarchy so we need to create\n three nested wrapper divs:\n */var wrappers=[$.makeNeutralElement('div'),$.makeNeutralElement('div'),$.makeNeutralElement('div')];// It feels like we should be able to pass style dicts to makeNeutralElement:\n$.extend(wrappers[0].style,{display:\"table\",height:\"100%\",width:\"100%\"});$.extend(wrappers[1].style,{display:\"table-row\"});$.extend(wrappers[2].style,{display:\"table-cell\",verticalAlign:\"middle\",textAlign:\"center\"});wrappers[0].appendChild(wrappers[1]);wrappers[1].appendChild(wrappers[2]);wrappers[2].appendChild(element);return wrappers[0];},/**\n * Creates an easily positionable element of the given type that therefor\n * serves as an excellent container element.\n * @function\n * @param {String} tagName\n * @returns {Element}\n */makeNeutralElement:function makeNeutralElement(tagName){var element=document.createElement(tagName),style=element.style;style.background=\"transparent none\";style.border=\"none\";style.margin=\"0px\";style.padding=\"0px\";style.position=\"static\";return element;},/**\n * Returns the current milliseconds, using Date.now() if available\n * @function\n */now:function now(){if(Date.now){$.now=Date.now;}else{$.now=function(){return new Date().getTime();};}return $.now();},/**\n * Ensures an image is loaded correctly to support alpha transparency.\n * Generally only IE has issues doing this correctly for formats like\n * png.\n * @function\n * @param {String} src\n * @returns {Element}\n */makeTransparentImage:function makeTransparentImage(src){$.makeTransparentImage=function(src){var img=$.makeNeutralElement(\"img\");img.src=src;return img;};if($.Browser.vendor==$.BROWSERS.IE&&$.Browser.version<7){$.makeTransparentImage=function(src){var img=$.makeNeutralElement(\"img\"),element=null;element=$.makeNeutralElement(\"span\");element.style.display=\"inline-block\";img.onload=function(){element.style.width=element.style.width||img.width+\"px\";element.style.height=element.style.height||img.height+\"px\";img.onload=null;img=null;// to prevent memory leaks in IE\n};img.src=src;element.style.filter=\"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='\"+src+\"', sizingMethod='scale')\";return element;};}return $.makeTransparentImage(src);},/**\n * Sets the opacity of the specified element.\n * @function\n * @param {Element|String} element\n * @param {Number} opacity\n * @param {Boolean} [usesAlpha]\n */setElementOpacity:function setElementOpacity(element,opacity,usesAlpha){var ieOpacity,ieFilter;element=$.getElement(element);if(usesAlpha&&!$.Browser.alpha){opacity=Math.round(opacity);}if($.Browser.opacity){element.style.opacity=opacity<1?opacity:\"\";}else{if(opacity<1){ieOpacity=Math.round(100*opacity);ieFilter=\"alpha(opacity=\"+ieOpacity+\")\";element.style.filter=ieFilter;}else{element.style.filter=\"\";}}},/**\n * Sets the specified element's touch-action style attribute to 'none'.\n * @function\n * @param {Element|String} element\n */setElementTouchActionNone:function setElementTouchActionNone(element){element=$.getElement(element);if(typeof element.style.touchAction!=='undefined'){element.style.touchAction='none';}else if(typeof element.style.msTouchAction!=='undefined'){element.style.msTouchAction='none';}},/**\n * Add the specified CSS class to the element if not present.\n * @function\n * @param {Element|String} element\n * @param {String} className\n */addClass:function addClass(element,className){element=$.getElement(element);if(!element.className){element.className=className;}else if((' '+element.className+' ').indexOf(' '+className+' ')===-1){element.className+=' '+className;}},/**\n * Find the first index at which an element is found in an array or -1\n * if not present.\n *\n * Code taken and adapted from\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Compatibility\n *\n * @function\n * @param {Array} array The array from which to find the element\n * @param {Object} searchElement The element to find\n * @param {Number} [fromIndex=0] Index to start research.\n * @returns {Number} The index of the element in the array.\n */indexOf:function indexOf(array,searchElement,fromIndex){if(Array.prototype.indexOf){this.indexOf=function(array,searchElement,fromIndex){return array.indexOf(searchElement,fromIndex);};}else{this.indexOf=function(array,searchElement,fromIndex){var i,pivot=fromIndex?fromIndex:0,length;if(!array){throw new TypeError();}length=array.length;if(length===0||pivot>=length){return-1;}if(pivot<0){pivot=length-Math.abs(pivot);}for(i=pivot;i=200&&request.status<300||request.status===0&&protocol!==\"http:\"&&protocol!==\"https:\"){onSuccess(request);}else{$.console.log(\"AJAX request returned %d: %s\",request.status,url);if($.isFunction(onError)){onError(request);}}}};try{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){request.withCredentials=true;}request.send(null);}catch(e){var msg=e.message;/*\n IE < 10 does not support CORS and an XHR request to a different origin will fail as soon\n as send() is called. This is particularly easy to miss during development and appear in\n production if you use a CDN or domain sharding and the security policy is likely to break\n exception handlers since any attempt to access a property of the request object will\n raise an access denied TypeError inside the catch block.\n\n To be friendlier, we'll check for this specific error and add a documentation pointer\n to point developers in the right direction. We test the exception number because IE's\n error messages are localized.\n */var oldIE=$.Browser.vendor==$.BROWSERS.IE&&$.Browser.version<10;if(oldIE&&typeof e.number!=\"undefined\"&&e.number==-2147024891){msg+=\"\\nSee http://msdn.microsoft.com/en-us/library/ms537505(v=vs.85).aspx#xdomain\";}$.console.log(\"%s while making AJAX request: %s\",e.name,msg);request.onreadystatechange=function(){};if(window.XDomainRequest){// IE9 or IE8 might as well try to use XDomainRequest\nvar xdr=new XDomainRequest();if(xdr){xdr.onload=function(e){if($.isFunction(onSuccess)){onSuccess({// Faking an xhr object\nresponseText:xdr.responseText,status:200,// XDomainRequest doesn't support status codes, so we just fake one! :/\nstatusText:'OK'});}};xdr.onerror=function(e){if($.isFunction(onError)){onError({// Faking an xhr object\nresponseText:xdr.responseText,status:444,// 444 No Response\nstatusText:'An error happened. Due to an XDomainRequest deficiency we can not extract any information about this error. Upgrade your browser.'});}};try{xdr.open('GET',url);xdr.send();}catch(e2){if($.isFunction(onError)){onError(request,e);}}}}else{if($.isFunction(onError)){onError(request,e);}}}return request;},/**\n * Taken from jQuery 1.6.1\n * @function\n * @param {Object} options\n * @param {String} options.url\n * @param {Function} options.callback\n * @param {String} [options.param='callback'] The name of the url parameter\n * to request the jsonp provider with.\n * @param {String} [options.callbackName=] The name of the callback to\n * request the jsonp provider with.\n */jsonp:function jsonp(options){var script,url=options.url,head=document.head||document.getElementsByTagName(\"head\")[0]||document.documentElement,jsonpCallback=options.callbackName||'openseadragon'+$.now(),previous=window[jsonpCallback],replace=\"$1\"+jsonpCallback+\"$2\",callbackParam=options.param||'callback',callback=options.callback;url=url.replace(/(\\=)\\?(&|$)|\\?\\?/i,replace);// Add callback manually\nurl+=(/\\?/.test(url)?\"&\":\"?\")+callbackParam+\"=\"+jsonpCallback;// Install callback\nwindow[jsonpCallback]=function(response){if(!previous){try{delete window[jsonpCallback];}catch(e){//swallow\n}}else{window[jsonpCallback]=previous;}if(callback&&$.isFunction(callback)){callback(response);}};script=document.createElement(\"script\");//TODO: having an issue with async info requests\nif(undefined!==options.async||false!==options.async){script.async=\"async\";}if(options.scriptCharset){script.charset=options.scriptCharset;}script.src=url;// Attach handlers for all browsers\nscript.onload=script.onreadystatechange=function(_,isAbort){if(isAbort||!script.readyState||/loaded|complete/.test(script.readyState)){// Handle memory leak in IE\nscript.onload=script.onreadystatechange=null;// Remove the script\nif(head&&script.parentNode){head.removeChild(script);}// Dereference the script\nscript=undefined;}};// Use insertBefore instead of appendChild to circumvent an IE6 bug.\n// This arises when a base node is used (#2709 and #4378).\nhead.insertBefore(script,head.firstChild);},/**\n * Fully deprecated. Will throw an error.\n * @function\n * @deprecated use {@link OpenSeadragon.Viewer#open}\n */createFromDZI:function createFromDZI(){throw\"OpenSeadragon.createFromDZI is deprecated, use Viewer.open.\";},/**\n * Parses an XML string into a DOM Document.\n * @function\n * @param {String} string\n * @returns {Document}\n */parseXml:function parseXml(string){if(window.DOMParser){$.parseXml=function(string){var xmlDoc=null,parser;parser=new DOMParser();xmlDoc=parser.parseFromString(string,\"text/xml\");return xmlDoc;};}else if(window.ActiveXObject){$.parseXml=function(string){var xmlDoc=null;xmlDoc=new ActiveXObject(\"Microsoft.XMLDOM\");xmlDoc.async=false;xmlDoc.loadXML(string);return xmlDoc;};}else{throw new Error(\"Browser doesn't support XML DOM.\");}return $.parseXml(string);},/**\n * Parses a JSON string into a Javascript object.\n * @function\n * @param {String} string\n * @returns {Object}\n */parseJSON:function parseJSON(string){if(window.JSON&&window.JSON.parse){$.parseJSON=window.JSON.parse;}else{// Should only be used by IE8 in non standards mode\n$.parseJSON=function(string){/*jshint evil:true*/ //eslint-disable-next-line no-eval\nreturn eval('('+string+')');};}return $.parseJSON(string);},/**\n * Reports whether the image format is supported for tiling in this\n * version.\n * @function\n * @param {String} [extension]\n * @returns {Boolean}\n */imageFormatSupported:function imageFormatSupported(extension){extension=extension?extension:\"\";// eslint-disable-next-line no-use-before-define\nreturn!!FILEFORMATS[extension.toLowerCase()];}});/**\n * The current browser vendor, version, and related information regarding detected features.\n * @member {Object} Browser\n * @memberof OpenSeadragon\n * @static\n * @type {Object}\n * @property {OpenSeadragon.BROWSERS} vendor - One of the {@link OpenSeadragon.BROWSERS} enumeration values.\n * @property {Number} version\n * @property {Boolean} alpha - Does the browser support image alpha transparency.\n */$.Browser={vendor:$.BROWSERS.UNKNOWN,version:0,alpha:true};var FILEFORMATS={\"bmp\":false,\"jpeg\":true,\"jpg\":true,\"png\":true,\"tif\":false,\"wdp\":false},URLPARAMS={};(function(){//A small auto-executing routine to determine the browser vendor,\n//version and supporting feature sets.\nvar ver=navigator.appVersion,ua=navigator.userAgent,regex;//console.error( 'appName: ' + navigator.appName );\n//console.error( 'appVersion: ' + navigator.appVersion );\n//console.error( 'userAgent: ' + navigator.userAgent );\nswitch(navigator.appName){case\"Microsoft Internet Explorer\":if(!!window.attachEvent&&!!window.ActiveXObject){$.Browser.vendor=$.BROWSERS.IE;$.Browser.version=parseFloat(ua.substring(ua.indexOf(\"MSIE\")+5,ua.indexOf(\";\",ua.indexOf(\"MSIE\"))));}break;case\"Netscape\":if(window.addEventListener){if(ua.indexOf(\"Firefox\")>=0){$.Browser.vendor=$.BROWSERS.FIREFOX;$.Browser.version=parseFloat(ua.substring(ua.indexOf(\"Firefox\")+8));}else if(ua.indexOf(\"Safari\")>=0){$.Browser.vendor=ua.indexOf(\"Chrome\")>=0?$.BROWSERS.CHROME:$.BROWSERS.SAFARI;$.Browser.version=parseFloat(ua.substring(ua.substring(0,ua.indexOf(\"Safari\")).lastIndexOf(\"/\")+1,ua.indexOf(\"Safari\")));}else{regex=new RegExp(\"Trident/.*rv:([0-9]{1,}[.0-9]{0,})\");if(regex.exec(ua)!==null){$.Browser.vendor=$.BROWSERS.IE;$.Browser.version=parseFloat(RegExp.$1);}}}break;case\"Opera\":$.Browser.vendor=$.BROWSERS.OPERA;$.Browser.version=parseFloat(ver);break;}// ignore '?' portion of query string\nvar query=window.location.search.substring(1),parts=query.split('&'),part,sep,i;for(i=0;i0){URLPARAMS[part.substring(0,sep)]=decodeURIComponent(part.substring(sep+1));}}//determine if this browser supports image alpha transparency\n$.Browser.alpha=!($.Browser.vendor==$.BROWSERS.IE&&$.Browser.version<9||$.Browser.vendor==$.BROWSERS.CHROME&&$.Browser.version<2);//determine if this browser supports element.style.opacity\n$.Browser.opacity=!($.Browser.vendor==$.BROWSERS.IE&&$.Browser.version<9);})();//TODO: $.console is often used inside a try/catch block which generally\n// prevents allowings errors to occur with detection until a debugger\n// is attached. Although I've been guilty of the same anti-pattern\n// I eventually was convinced that errors should naturally propogate in\n// all but the most special cases.\n/**\n * A convenient alias for console when available, and a simple null\n * function when console is unavailable.\n * @static\n * @private\n */var nullfunction=function nullfunction(msg){//document.location.hash = msg;\n};$.console=window.console||{log:nullfunction,debug:nullfunction,info:nullfunction,warn:nullfunction,error:nullfunction,assert:nullfunction};// Adding support for HTML5's requestAnimationFrame as suggested by acdha.\n// Implementation taken from matt synder's post here:\n// http://mattsnider.com/cross-browser-and-legacy-supported-requestframeanimation/\n(function(w){// most browsers have an implementation\nvar requestAnimationFrame=w.requestAnimationFrame||w.mozRequestAnimationFrame||w.webkitRequestAnimationFrame||w.msRequestAnimationFrame;var cancelAnimationFrame=w.cancelAnimationFrame||w.mozCancelAnimationFrame||w.webkitCancelAnimationFrame||w.msCancelAnimationFrame;// polyfill, when necessary\nif(requestAnimationFrame&&cancelAnimationFrame){// We can't assign these window methods directly to $ because they\n// expect their \"this\" to be \"window\", so we call them in wrappers.\n$.requestAnimationFrame=function(){return requestAnimationFrame.apply(w,arguments);};$.cancelAnimationFrame=function(){return cancelAnimationFrame.apply(w,arguments);};}else{var aAnimQueue=[],processing=[],iRequestId=0,iIntervalId;// create a mock requestAnimationFrame function\n$.requestAnimationFrame=function(callback){aAnimQueue.push([++iRequestId,callback]);if(!iIntervalId){iIntervalId=setInterval(function(){if(aAnimQueue.length){var time=$.now();// Process all of the currently outstanding frame\n// requests, but none that get added during the\n// processing.\n// Swap the arrays so we don't have to create a new\n// array every frame.\nvar temp=processing;processing=aAnimQueue;aAnimQueue=temp;while(processing.length){processing.shift()[1](time);}}else{// don't continue the interval, if unnecessary\nclearInterval(iIntervalId);iIntervalId=undefined;}},1000/50);// estimating support for 50 frames per second\n}return iRequestId;};// create a mock cancelAnimationFrame function\n$.cancelAnimationFrame=function(requestId){// find the request ID and remove it\nvar i,j;for(i=0,j=aAnimQueue.length;i}\n */getActivePointersListsExceptType:function getActivePointersListsExceptType(type){var delegate=THIS[this.hash];var listArray=[];for(var i=0;iDeprecated. Use buttons instead.\n * @param {Boolean} event.isTouchEvent\n * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */enterHandler:function enterHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {String} event.pointerType\n * \"mouse\", \"touch\", \"pen\", etc.\n * @param {OpenSeadragon.Point} event.position\n * The position of the event relative to the tracked element.\n * @param {Number} event.buttons\n * Current buttons pressed.\n * Combination of bit flags 0: none, 1: primary (or touch contact), 2: secondary, 4: aux (often middle), 8: X1 (often back), 16: X2 (often forward), 32: pen eraser.\n * @param {Number} event.pointers\n * Number of pointers (all types) active in the tracked element.\n * @param {Boolean} event.insideElementPressed\n * True if the left mouse button is currently being pressed and was\n * initiated inside the tracked element, otherwise false.\n * @param {Boolean} event.buttonDownAny\n * Was the button down anywhere in the screen during the event. Deprecated. Use buttons instead.\n * @param {Boolean} event.isTouchEvent\n * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */exitHandler:function exitHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {String} event.pointerType\n * \"mouse\", \"touch\", \"pen\", etc.\n * @param {OpenSeadragon.Point} event.position\n * The position of the event relative to the tracked element.\n * @param {Number} event.buttons\n * Current buttons pressed.\n * Combination of bit flags 0: none, 1: primary (or touch contact), 2: secondary, 4: aux (often middle), 8: X1 (often back), 16: X2 (often forward), 32: pen eraser.\n * @param {Boolean} event.isTouchEvent\n * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */pressHandler:function pressHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {String} event.pointerType\n * \"mouse\", \"touch\", \"pen\", etc.\n * @param {OpenSeadragon.Point} event.position\n * The position of the event relative to the tracked element.\n * @param {Number} event.button\n * Button which caused the event.\n * -1: none, 0: primary/left, 1: aux/middle, 2: secondary/right, 3: X1/back, 4: X2/forward, 5: pen eraser.\n * @param {Number} event.buttons\n * Current buttons pressed.\n * Combination of bit flags 0: none, 1: primary (or touch contact), 2: secondary, 4: aux (often middle), 8: X1 (often back), 16: X2 (often forward), 32: pen eraser.\n * @param {Boolean} event.isTouchEvent\n * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */nonPrimaryPressHandler:function nonPrimaryPressHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {String} event.pointerType\n * \"mouse\", \"touch\", \"pen\", etc.\n * @param {OpenSeadragon.Point} event.position\n * The position of the event relative to the tracked element.\n * @param {Number} event.buttons\n * Current buttons pressed.\n * Combination of bit flags 0: none, 1: primary (or touch contact), 2: secondary, 4: aux (often middle), 8: X1 (often back), 16: X2 (often forward), 32: pen eraser.\n * @param {Boolean} event.insideElementPressed\n * True if the left mouse button is currently being pressed and was\n * initiated inside the tracked element, otherwise false.\n * @param {Boolean} event.insideElementReleased\n * True if the cursor inside the tracked element when the button was released.\n * @param {Boolean} event.isTouchEvent\n * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */releaseHandler:function releaseHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {String} event.pointerType\n * \"mouse\", \"touch\", \"pen\", etc.\n * @param {OpenSeadragon.Point} event.position\n * The position of the event relative to the tracked element.\n * @param {Number} event.button\n * Button which caused the event.\n * -1: none, 0: primary/left, 1: aux/middle, 2: secondary/right, 3: X1/back, 4: X2/forward, 5: pen eraser.\n * @param {Number} event.buttons\n * Current buttons pressed.\n * Combination of bit flags 0: none, 1: primary (or touch contact), 2: secondary, 4: aux (often middle), 8: X1 (often back), 16: X2 (often forward), 32: pen eraser.\n * @param {Boolean} event.isTouchEvent\n * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */nonPrimaryReleaseHandler:function nonPrimaryReleaseHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {String} event.pointerType\n * \"mouse\", \"touch\", \"pen\", etc.\n * @param {OpenSeadragon.Point} event.position\n * The position of the event relative to the tracked element.\n * @param {Number} event.buttons\n * Current buttons pressed.\n * Combination of bit flags 0: none, 1: primary (or touch contact), 2: secondary, 4: aux (often middle), 8: X1 (often back), 16: X2 (often forward), 32: pen eraser.\n * @param {Boolean} event.isTouchEvent\n * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */moveHandler:function moveHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {String} event.pointerType\n * \"mouse\", \"touch\", \"pen\", etc.\n * @param {OpenSeadragon.Point} event.position\n * The position of the event relative to the tracked element.\n * @param {Number} event.scroll\n * The scroll delta for the event.\n * @param {Boolean} event.shift\n * True if the shift key was pressed during this event.\n * @param {Boolean} event.isTouchEvent\n * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead. Touch devices no longer generate scroll event.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */scrollHandler:function scrollHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {String} event.pointerType\n * \"mouse\", \"touch\", \"pen\", etc.\n * @param {OpenSeadragon.Point} event.position\n * The position of the event relative to the tracked element.\n * @param {Boolean} event.quick\n * True only if the clickDistThreshold and clickTimeThreshold are both passed. Useful for ignoring drag events.\n * @param {Boolean} event.shift\n * True if the shift key was pressed during this event.\n * @param {Boolean} event.isTouchEvent\n * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */clickHandler:function clickHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {String} event.pointerType\n * \"mouse\", \"touch\", \"pen\", etc.\n * @param {OpenSeadragon.Point} event.position\n * The position of the event relative to the tracked element.\n * @param {Boolean} event.shift\n * True if the shift key was pressed during this event.\n * @param {Boolean} event.isTouchEvent\n * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */dblClickHandler:function dblClickHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {String} event.pointerType\n * \"mouse\", \"touch\", \"pen\", etc.\n * @param {OpenSeadragon.Point} event.position\n * The position of the event relative to the tracked element.\n * @param {Number} event.buttons\n * Current buttons pressed.\n * Combination of bit flags 0: none, 1: primary (or touch contact), 2: secondary, 4: aux (often middle), 8: X1 (often back), 16: X2 (often forward), 32: pen eraser.\n * @param {OpenSeadragon.Point} event.delta\n * The x,y components of the difference between the current position and the last drag event position. Useful for ignoring or weighting the events.\n * @param {Number} event.speed\n * Current computed speed, in pixels per second.\n * @param {Number} event.direction\n * Current computed direction, expressed as an angle counterclockwise relative to the positive X axis (-pi to pi, in radians). Only valid if speed > 0.\n * @param {Boolean} event.shift\n * True if the shift key was pressed during this event.\n * @param {Boolean} event.isTouchEvent\n * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */dragHandler:function dragHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {String} event.pointerType\n * \"mouse\", \"touch\", \"pen\", etc.\n * @param {OpenSeadragon.Point} event.position\n * The position of the event relative to the tracked element.\n * @param {Number} event.speed\n * Speed at the end of a drag gesture, in pixels per second.\n * @param {Number} event.direction\n * Direction at the end of a drag gesture, expressed as an angle counterclockwise relative to the positive X axis (-pi to pi, in radians). Only valid if speed > 0.\n * @param {Boolean} event.shift\n * True if the shift key was pressed during this event.\n * @param {Boolean} event.isTouchEvent\n * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */dragEndHandler:function dragEndHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {String} event.pointerType\n * \"mouse\", \"touch\", \"pen\", etc.\n * @param {Array.} event.gesturePoints\n * Gesture points associated with the gesture. Velocity data can be found here.\n * @param {OpenSeadragon.Point} event.lastCenter\n * The previous center point of the two pinch contact points relative to the tracked element.\n * @param {OpenSeadragon.Point} event.center\n * The center point of the two pinch contact points relative to the tracked element.\n * @param {Number} event.lastDistance\n * The previous distance between the two pinch contact points in CSS pixels.\n * @param {Number} event.distance\n * The distance between the two pinch contact points in CSS pixels.\n * @param {Boolean} event.shift\n * True if the shift key was pressed during this event.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */pinchHandler:function pinchHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {String} event.pointerType\n * \"mouse\", \"touch\", \"pen\", etc.\n * @param {OpenSeadragon.Point} event.position\n * The position of the event relative to the tracked element.\n * @param {Number} event.buttons\n * Current buttons pressed.\n * Combination of bit flags 0: none, 1: primary (or touch contact), 2: secondary, 4: aux (often middle), 8: X1 (often back), 16: X2 (often forward), 32: pen eraser.\n * @param {Boolean} event.isTouchEvent\n * True if the original event is a touch event, otherwise false. Deprecated. Use pointerType and/or originalEvent instead.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */stopHandler:function stopHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {Number} event.keyCode\n * The key code that was pressed.\n * @param {Boolean} event.ctrl\n * True if the ctrl key was pressed during this event.\n * @param {Boolean} event.shift\n * True if the shift key was pressed during this event.\n * @param {Boolean} event.alt\n * True if the alt key was pressed during this event.\n * @param {Boolean} event.meta\n * True if the meta key was pressed during this event.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */keyDownHandler:function keyDownHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {Number} event.keyCode\n * The key code that was pressed.\n * @param {Boolean} event.ctrl\n * True if the ctrl key was pressed during this event.\n * @param {Boolean} event.shift\n * True if the shift key was pressed during this event.\n * @param {Boolean} event.alt\n * True if the alt key was pressed during this event.\n * @param {Boolean} event.meta\n * True if the meta key was pressed during this event.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */keyUpHandler:function keyUpHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {Number} event.keyCode\n * The key code that was pressed.\n * @param {Boolean} event.ctrl\n * True if the ctrl key was pressed during this event.\n * @param {Boolean} event.shift\n * True if the shift key was pressed during this event.\n * @param {Boolean} event.alt\n * True if the alt key was pressed during this event.\n * @param {Boolean} event.meta\n * True if the meta key was pressed during this event.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */keyHandler:function keyHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */focusHandler:function focusHandler(){},/**\n * Implement or assign implementation to these handlers during or after\n * calling the constructor.\n * @function\n * @param {Object} event\n * @param {OpenSeadragon.MouseTracker} event.eventSource\n * A reference to the tracker instance.\n * @param {Object} event.originalEvent\n * The original event object.\n * @param {Boolean} event.preventDefaultAction\n * Set to true to prevent the tracker subscriber from performing its default action (subscriber implementation dependent). Default: false.\n * @param {Object} event.userData\n * Arbitrary user-defined object.\n */blurHandler:function blurHandler(){}};/**\n * Resets all active mousetrakers. (Added to patch issue #697 \"Mouse up outside map will cause \"canvas-drag\" event to stick\")\n *\n * @private\n * @member resetAllMouseTrackers\n * @memberof OpenSeadragon.MouseTracker\n */$.MouseTracker.resetAllMouseTrackers=function(){for(var i=0;i8||'onwheel'in document.createElement('div')?'wheel':// Modern browsers support 'wheel'\ndocument.onmousewheel!==undefined?'mousewheel':// Webkit and IE support at least 'mousewheel'\n'DOMMouseScroll';// Assume old Firefox\n/**\n * Detect legacy mouse capture support.\n */$.MouseTracker.supportsMouseCapture=function(){var divElement=document.createElement('div');return $.isFunction(divElement.setCapture)&&$.isFunction(divElement.releaseCapture);}();/**\n * Detect browser pointer device event model(s) and build appropriate list of events to subscribe to.\n */$.MouseTracker.subscribeEvents=[\"click\",\"dblclick\",\"keydown\",\"keyup\",\"keypress\",\"focus\",\"blur\",$.MouseTracker.wheelEventName];if($.MouseTracker.wheelEventName==\"DOMMouseScroll\"){// Older Firefox\n$.MouseTracker.subscribeEvents.push(\"MozMousePixelScroll\");}// Note: window.navigator.pointerEnable is deprecated on IE 11 and not part of W3C spec.\nif(window.PointerEvent&&(window.navigator.pointerEnabled||$.Browser.vendor!==$.BROWSERS.IE)){// IE11 and other W3C Pointer Event implementations (see http://www.w3.org/TR/pointerevents)\n$.MouseTracker.havePointerEvents=true;$.MouseTracker.subscribeEvents.push(\"pointerover\",\"pointerout\",\"pointerdown\",\"pointerup\",\"pointermove\",\"pointercancel\");$.MouseTracker.unprefixedPointerEvents=true;if(navigator.maxTouchPoints){$.MouseTracker.maxTouchPoints=navigator.maxTouchPoints;}else{$.MouseTracker.maxTouchPoints=0;}$.MouseTracker.haveMouseEnter=false;}else if(window.MSPointerEvent&&window.navigator.msPointerEnabled){// IE10\n$.MouseTracker.havePointerEvents=true;$.MouseTracker.subscribeEvents.push(\"MSPointerOver\",\"MSPointerOut\",\"MSPointerDown\",\"MSPointerUp\",\"MSPointerMove\",\"MSPointerCancel\");$.MouseTracker.unprefixedPointerEvents=false;if(navigator.msMaxTouchPoints){$.MouseTracker.maxTouchPoints=navigator.msMaxTouchPoints;}else{$.MouseTracker.maxTouchPoints=0;}$.MouseTracker.haveMouseEnter=false;}else{// Legacy W3C mouse events\n$.MouseTracker.havePointerEvents=false;if($.Browser.vendor===$.BROWSERS.IE&&$.Browser.version<9){$.MouseTracker.subscribeEvents.push(\"mouseenter\",\"mouseleave\");$.MouseTracker.haveMouseEnter=true;}else{$.MouseTracker.subscribeEvents.push(\"mouseover\",\"mouseout\");$.MouseTracker.haveMouseEnter=false;}$.MouseTracker.subscribeEvents.push(\"mousedown\",\"mouseup\",\"mousemove\");if('ontouchstart'in window){// iOS, Android, and other W3c Touch Event implementations\n// (see http://www.w3.org/TR/touch-events/)\n// (see https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html)\n// (see https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html)\n$.MouseTracker.subscribeEvents.push(\"touchstart\",\"touchend\",\"touchmove\",\"touchcancel\");}if('ongesturestart'in window){// iOS (see https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html)\n// Subscribe to these to prevent default gesture handling\n$.MouseTracker.subscribeEvents.push(\"gesturestart\",\"gesturechange\");}$.MouseTracker.mousePointerId=\"legacy-mouse\";$.MouseTracker.maxTouchPoints=10;}///////////////////////////////////////////////////////////////////////////////\n// Classes and typedefs\n///////////////////////////////////////////////////////////////////////////////\n/**\n * Represents a point of contact on the screen made by a mouse cursor, pen, touch, or other pointer device.\n *\n * @typedef {Object} GesturePoint\n * @memberof OpenSeadragon.MouseTracker\n *\n * @property {Number} id\n * Identifier unique from all other active GesturePoints for a given pointer device.\n * @property {String} type\n * The pointer device type: \"mouse\", \"touch\", \"pen\", etc.\n * @property {Boolean} captured\n * True if events for the gesture point are captured to the tracked element.\n * @property {Boolean} isPrimary\n * True if the gesture point is a master pointer amongst the set of active pointers for each pointer type. True for mouse and primary (first) touch/pen pointers.\n * @property {Boolean} insideElementPressed\n * True if button pressed or contact point initiated inside the screen area of the tracked element.\n * @property {Boolean} insideElement\n * True if pointer or contact point is currently inside the bounds of the tracked element.\n * @property {Number} speed\n * Current computed speed, in pixels per second.\n * @property {Number} direction\n * Current computed direction, expressed as an angle counterclockwise relative to the positive X axis (-pi to pi, in radians). Only valid if speed > 0.\n * @property {OpenSeadragon.Point} contactPos\n * The initial pointer contact position, relative to the page including any scrolling. Only valid if the pointer has contact (pressed, touch contact, pen contact).\n * @property {Number} contactTime\n * The initial pointer contact time, in milliseconds. Only valid if the pointer has contact (pressed, touch contact, pen contact).\n * @property {OpenSeadragon.Point} lastPos\n * The last pointer position, relative to the page including any scrolling.\n * @property {Number} lastTime\n * The last pointer contact time, in milliseconds.\n * @property {OpenSeadragon.Point} currentPos\n * The current pointer position, relative to the page including any scrolling.\n * @property {Number} currentTime\n * The current pointer contact time, in milliseconds.\n */ /**\n * @class GesturePointList\n * @classdesc Provides an abstraction for a set of active {@link OpenSeadragon.MouseTracker.GesturePoint|GesturePoint} objects for a given pointer device type.\n * Active pointers are any pointer being tracked for this element which are in the hit-test area\n * of the element (for hover-capable devices) and/or have contact or a button press initiated in the element.\n * @memberof OpenSeadragon.MouseTracker\n * @param {String} type - The pointer device type: \"mouse\", \"touch\", \"pen\", etc.\n */$.MouseTracker.GesturePointList=function(type){this._gPoints=[];/**\n * The pointer device type: \"mouse\", \"touch\", \"pen\", etc.\n * @member {String} type\n * @memberof OpenSeadragon.MouseTracker.GesturePointList#\n */this.type=type;/**\n * Current buttons pressed for the device.\n * Combination of bit flags 0: none, 1: primary (or touch contact), 2: secondary, 4: aux (often middle), 8: X1 (often back), 16: X2 (often forward), 32: pen eraser.\n * @member {Number} buttons\n * @memberof OpenSeadragon.MouseTracker.GesturePointList#\n */this.buttons=0;/**\n * Current number of contact points (touch points, mouse down, etc.) for the device.\n * @member {Number} contacts\n * @memberof OpenSeadragon.MouseTracker.GesturePointList#\n */this.contacts=0;/**\n * Current number of clicks for the device. Used for multiple click gesture tracking.\n * @member {Number} clicks\n * @memberof OpenSeadragon.MouseTracker.GesturePointList#\n */this.clicks=0;/**\n * Current number of captured pointers for the device.\n * @member {Number} captureCount\n * @memberof OpenSeadragon.MouseTracker.GesturePointList#\n */this.captureCount=0;};/** @lends OpenSeadragon.MouseTracker.GesturePointList.prototype */$.MouseTracker.GesturePointList.prototype={/**\n * @function\n * @returns {Number} Number of gesture points in the list.\n */getLength:function getLength(){return this._gPoints.length;},/**\n * @function\n * @returns {Array.} The list of gesture points in the list as an array (read-only).\n */asArray:function asArray(){return this._gPoints;},/**\n * @function\n * @param {OpenSeadragon.MouseTracker.GesturePoint} gesturePoint - A gesture point to add to the list.\n * @returns {Number} Number of gesture points in the list.\n */add:function add(gp){return this._gPoints.push(gp);},/**\n * @function\n * @param {Number} id - The id of the gesture point to remove from the list.\n * @returns {Number} Number of gesture points in the list.\n */removeById:function removeById(id){var i,len=this._gPoints.length;for(i=0;i1&&(this.type===\"mouse\"||this.type===\"pen\")){this.contacts=1;}},/**\n * Decrement this pointer's contact count.\n * It will make sure the count does not go below 0.\n * @function\n */removeContact:function removeContact(){--this.contacts;if(this.contacts<0){this.contacts=0;}}};///////////////////////////////////////////////////////////////////////////////\n// Utility functions\n///////////////////////////////////////////////////////////////////////////////\n/**\n * Removes all tracked pointers.\n * @private\n * @inner\n */function clearTrackedPointers(tracker){var delegate=THIS[tracker.hash],i,pointerListCount=delegate.activePointersLists.length;for(i=0;i0){$.removeEvent($.MouseTracker.captureElement,'mousemove',delegate.mousemovecaptured,true);$.removeEvent($.MouseTracker.captureElement,'mouseup',delegate.mouseupcaptured,true);$.removeEvent($.MouseTracker.captureElement,$.MouseTracker.unprefixedPointerEvents?'pointermove':'MSPointerMove',delegate.pointermovecaptured,true);$.removeEvent($.MouseTracker.captureElement,$.MouseTracker.unprefixedPointerEvents?'pointerup':'MSPointerUp',delegate.pointerupcaptured,true);$.removeEvent($.MouseTracker.captureElement,'touchmove',delegate.touchmovecaptured,true);$.removeEvent($.MouseTracker.captureElement,'touchend',delegate.touchendcaptured,true);delegate.activePointersLists[i].captureCount=0;}}for(i=0;i0){for(i=0;i0){// simulate touchend/mouseup\nupdatePointersUp(tracker,event,abortGPoints,0);// 0 means primary button press/release or touch contact\n// release pointer capture\npointsList.captureCount=1;releasePointer(tracker,pointsList.type);// simulate touchleave/mouseout\nupdatePointersExit(tracker,event,abortGPoints);}}}/**\n * @private\n * @inner\n */function onTouchStart(tracker,event){var time,i,j,touchCount=event.changedTouches.length,gPoints=[],parentGPoints,pointsList=tracker.getActivePointersListByType('touch');time=$.now();if(pointsList.getLength()>event.touches.length-touchCount){$.console.warn('Tracked touch contact count doesn\\'t match event.touches.length. Removing all tracked touch pointers.');abortContacts(tracker,event,pointsList);}for(i=0;i} gPoints\n * Gesture points associated with the event.\n */function updatePointersEnter(tracker,event,gPoints){var pointsList=tracker.getActivePointersListByType(gPoints[0].type),i,gPointCount=gPoints.length,curGPoint,updateGPoint,propagate;for(i=0;i} gPoints\n * Gesture points associated with the event.\n */function updatePointersExit(tracker,event,gPoints){var pointsList=tracker.getActivePointersListByType(gPoints[0].type),i,gPointCount=gPoints.length,curGPoint,updateGPoint,propagate;for(i=0;i} gPoints\n * Gesture points associated with the event.\n * @param {Number} buttonChanged\n * The button involved in the event: -1: none, 0: primary/left, 1: aux/middle, 2: secondary/right, 3: X1/back, 4: X2/forward, 5: pen eraser.\n * Note on chorded button presses (a button pressed when another button is already pressed): In the W3C Pointer Events model,\n * only one pointerdown/pointerup event combo is fired. Chorded button state changes instead fire pointermove events.\n *\n * @returns {Boolean} True if pointers should be captured to the tracked element, otherwise false.\n */function updatePointersDown(tracker,event,gPoints,buttonChanged){var delegate=THIS[tracker.hash],propagate,pointsList=tracker.getActivePointersListByType(gPoints[0].type),i,gPointCount=gPoints.length,curGPoint,updateGPoint;if(typeof event.buttons!=='undefined'){pointsList.buttons=event.buttons;}else{if($.Browser.vendor===$.BROWSERS.IE&&$.Browser.version<9){if(buttonChanged===0){// Primary\npointsList.buttons+=1;}else if(buttonChanged===1){// Aux\npointsList.buttons+=4;}else if(buttonChanged===2){// Secondary\npointsList.buttons+=2;}else if(buttonChanged===3){// X1 (Back)\npointsList.buttons+=8;}else if(buttonChanged===4){// X2 (Forward)\npointsList.buttons+=16;}else if(buttonChanged===5){// Pen Eraser\npointsList.buttons+=32;}}else{if(buttonChanged===0){// Primary\npointsList.buttons|=1;}else if(buttonChanged===1){// Aux\npointsList.buttons|=4;}else if(buttonChanged===2){// Secondary\npointsList.buttons|=2;}else if(buttonChanged===3){// X1 (Back)\npointsList.buttons|=8;}else if(buttonChanged===4){// X2 (Forward)\npointsList.buttons|=16;}else if(buttonChanged===5){// Pen Eraser\npointsList.buttons|=32;}}}// Some pointers may steal control from another pointer without firing the appropriate release events\n// e.g. Touching a screen while click-dragging with certain mice.\nvar otherPointsLists=tracker.getActivePointersListsExceptType(gPoints[0].type);for(i=0;i} gPoints\n * Gesture points associated with the event.\n * @param {Number} buttonChanged\n * The button involved in the event: -1: none, 0: primary/left, 1: aux/middle, 2: secondary/right, 3: X1/back, 4: X2/forward, 5: pen eraser.\n * Note on chorded button presses (a button pressed when another button is already pressed): In the W3C Pointer Events model,\n * only one pointerdown/pointerup event combo is fired. Chorded button state changes instead fire pointermove events.\n *\n * @returns {Boolean} True if pointer capture should be released from the tracked element, otherwise false.\n */function updatePointersUp(tracker,event,gPoints,buttonChanged){var delegate=THIS[tracker.hash],pointsList=tracker.getActivePointersListByType(gPoints[0].type),propagate,releasePoint,releaseTime,i,gPointCount=gPoints.length,curGPoint,updateGPoint,releaseCapture=false,wasCaptured=false,quick;if(typeof event.buttons!=='undefined'){pointsList.buttons=event.buttons;}else{if($.Browser.vendor===$.BROWSERS.IE&&$.Browser.version<9){if(buttonChanged===0){// Primary\npointsList.buttons-=1;}else if(buttonChanged===1){// Aux\npointsList.buttons-=4;}else if(buttonChanged===2){// Secondary\npointsList.buttons-=2;}else if(buttonChanged===3){// X1 (Back)\npointsList.buttons-=8;}else if(buttonChanged===4){// X2 (Forward)\npointsList.buttons-=16;}else if(buttonChanged===5){// Pen Eraser\npointsList.buttons-=32;}}else{if(buttonChanged===0){// Primary\npointsList.buttons^=~1;}else if(buttonChanged===1){// Aux\npointsList.buttons^=~4;}else if(buttonChanged===2){// Secondary\npointsList.buttons^=~2;}else if(buttonChanged===3){// X1 (Back)\npointsList.buttons^=~8;}else if(buttonChanged===4){// X2 (Forward)\npointsList.buttons^=~16;}else if(buttonChanged===5){// Pen Eraser\npointsList.buttons^=~32;}}}// Only capture and track primary button, pen, and touch contacts\nif(buttonChanged!==0){// Aux Release\nif(tracker.nonPrimaryReleaseHandler){propagate=tracker.nonPrimaryReleaseHandler({eventSource:tracker,pointerType:gPoints[0].type,position:getPointRelativeToAbsolute(gPoints[0].currentPos,tracker.element),button:buttonChanged,buttons:pointsList.buttons,isTouchEvent:gPoints[0].type==='touch',originalEvent:event,preventDefaultAction:false,userData:tracker.userData});if(propagate===false){$.cancelEvent(event);}}// A primary mouse button may have been released while the non-primary button was down\nvar otherPointsList=tracker.getActivePointersListByType(\"mouse\");// Stop tracking the mouse; see https://github.com/openseadragon/openseadragon/pull/1223\nabortContacts(tracker,event,otherPointsList);// No-op if no active pointer\nreturn false;}for(i=0;i} gPoints\n * Gesture points associated with the event.\n */function updatePointersMove(tracker,event,gPoints){var delegate=THIS[tracker.hash],pointsList=tracker.getActivePointersListByType(gPoints[0].type),i,gPointCount=gPoints.length,curGPoint,updateGPoint,gPointArray,delta,propagate;if(typeof event.buttons!=='undefined'){pointsList.buttons=event.buttons;}for(i=0;i} gPoints\n * Gesture points associated with the event.\n */function updatePointersCancel(tracker,event,gPoints){updatePointersUp(tracker,event,gPoints,0);updatePointersExit(tracker,event,gPoints);}/**\n * @private\n * @inner\n */function handlePointerStop(tracker,originalMoveEvent,pointerType){if(tracker.stopHandler){tracker.stopHandler({eventSource:tracker,pointerType:pointerType,position:getMouseRelative(originalMoveEvent,tracker.element),buttons:tracker.getActivePointersListByType(pointerType).buttons,isTouchEvent:pointerType==='touch',originalEvent:originalMoveEvent,preventDefaultAction:false,userData:tracker.userData});}}/**\n * True if inside an iframe, otherwise false.\n * @member {Boolean} isInIframe\n * @private\n * @inner\n */var isInIframe=function(){try{return window.self!==window.top;}catch(e){return true;}}();/**\n * @function\n * @private\n * @inner\n * @returns {Boolean} True if the target has access rights to events, otherwise false.\n */function canAccessEvents(target){try{return target.addEventListener&&target.removeEventListener;}catch(e){return false;}}})(OpenSeadragon);/*\n * OpenSeadragon - Control\n *\n * Copyright (C) 2009 CodePlex Foundation\n * Copyright (C) 2010-2013 OpenSeadragon contributors\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * - Redistributions of source code must retain the above copyright notice,\n * this list of conditions and the following disclaimer.\n *\n * - Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n *\n * - Neither the name of CodePlex Foundation nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\n * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */(function($){/**\n * An enumeration of supported locations where controls can be anchored.\n * The anchoring is always relative to the container.\n * @member ControlAnchor\n * @memberof OpenSeadragon\n * @static\n * @type {Object}\n * @property {Number} NONE\n * @property {Number} TOP_LEFT\n * @property {Number} TOP_RIGHT\n * @property {Number} BOTTOM_LEFT\n * @property {Number} BOTTOM_RIGHT\n * @property {Number} ABSOLUTE\n */$.ControlAnchor={NONE:0,TOP_LEFT:1,TOP_RIGHT:2,BOTTOM_RIGHT:3,BOTTOM_LEFT:4,ABSOLUTE:5};/**\n * @class Control\n * @classdesc A Control represents any interface element which is meant to allow the user\n * to interact with the zoomable interface. Any control can be anchored to any\n * element.\n *\n * @memberof OpenSeadragon\n * @param {Element} element - the control element to be anchored in the container.\n * @param {Object } options - All required and optional settings for configuring a control element.\n * @param {OpenSeadragon.ControlAnchor} [options.anchor=OpenSeadragon.ControlAnchor.NONE] - the position of the control\n * relative to the container.\n * @param {Boolean} [options.attachToViewer=true] - Whether the control should be added directly to the viewer, or\n * directly to the container\n * @param {Boolean} [options.autoFade=true] - Whether the control should have the autofade behavior\n * @param {Element} container - the element to control will be anchored too.\n */$.Control=function(element,options,container){var parent=element.parentNode;if(typeof options==='number'){$.console.error(\"Passing an anchor directly into the OpenSeadragon.Control constructor is deprecated; \"+\"please use an options object instead. \"+\"Support for this deprecated variant is scheduled for removal in December 2013\");options={anchor:options};}options.attachToViewer=typeof options.attachToViewer==='undefined'?true:options.attachToViewer;/**\n * True if the control should have autofade behavior.\n * @member {Boolean} autoFade\n * @memberof OpenSeadragon.Control#\n */this.autoFade=typeof options.autoFade==='undefined'?true:options.autoFade;/**\n * The element providing the user interface with some type of control (e.g. a zoom-in button).\n * @member {Element} element\n * @memberof OpenSeadragon.Control#\n */this.element=element;/**\n * The position of the Control relative to its container.\n * @member {OpenSeadragon.ControlAnchor} anchor\n * @memberof OpenSeadragon.Control#\n */this.anchor=options.anchor;/**\n * The Control's containing element.\n * @member {Element} container\n * @memberof OpenSeadragon.Control#\n */this.container=container;/**\n * A neutral element surrounding the control element.\n * @member {Element} wrapper\n * @memberof OpenSeadragon.Control#\n */if(this.anchor==$.ControlAnchor.ABSOLUTE){this.wrapper=$.makeNeutralElement(\"div\");this.wrapper.style.position=\"absolute\";this.wrapper.style.top=typeof options.top==\"number\"?options.top+'px':options.top;this.wrapper.style.left=typeof options.left==\"number\"?options.left+'px':options.left;this.wrapper.style.height=typeof options.height==\"number\"?options.height+'px':options.height;this.wrapper.style.width=typeof options.width==\"number\"?options.width+'px':options.width;this.wrapper.style.margin=\"0px\";this.wrapper.style.padding=\"0px\";this.element.style.position=\"relative\";this.element.style.top=\"0px\";this.element.style.left=\"0px\";this.element.style.height=\"100%\";this.element.style.width=\"100%\";}else{this.wrapper=$.makeNeutralElement(\"div\");this.wrapper.style.display=\"inline-block\";if(this.anchor==$.ControlAnchor.NONE){// IE6 fix\nthis.wrapper.style.width=this.wrapper.style.height=\"100%\";}}this.wrapper.appendChild(this.element);if(options.attachToViewer){if(this.anchor==$.ControlAnchor.TOP_RIGHT||this.anchor==$.ControlAnchor.BOTTOM_RIGHT){this.container.insertBefore(this.wrapper,this.container.firstChild);}else{this.container.appendChild(this.wrapper);}}else{parent.appendChild(this.wrapper);}};/** @lends OpenSeadragon.Control.prototype */$.Control.prototype={/**\n * Removes the control from the container.\n * @function\n */destroy:function destroy(){this.wrapper.removeChild(this.element);this.container.removeChild(this.wrapper);},/**\n * Determines if the control is currently visible.\n * @function\n * @return {Boolean} true if currenly visible, false otherwise.\n */isVisible:function isVisible(){return this.wrapper.style.display!=\"none\";},/**\n * Toggles the visibility of the control.\n * @function\n * @param {Boolean} visible - true to make visible, false to hide.\n */setVisible:function setVisible(visible){this.wrapper.style.display=visible?this.anchor==$.ControlAnchor.ABSOLUTE?'block':'inline-block':\"none\";},/**\n * Sets the opacity level for the control.\n * @function\n * @param {Number} opactiy - a value between 1 and 0 inclusively.\n */setOpacity:function setOpacity(opacity){if(this.element[$.SIGNAL]&&$.Browser.vendor==$.BROWSERS.IE){$.setElementOpacity(this.element,opacity,true);}else{$.setElementOpacity(this.wrapper,opacity,true);}}};})(OpenSeadragon);/*\n * OpenSeadragon - ControlDock\n *\n * Copyright (C) 2009 CodePlex Foundation\n * Copyright (C) 2010-2013 OpenSeadragon contributors\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * - Redistributions of source code must retain the above copyright notice,\n * this list of conditions and the following disclaimer.\n *\n * - Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n *\n * - Neither the name of CodePlex Foundation nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\n * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */(function($){/**\n * @class ControlDock\n * @classdesc Provides a container element (a <form> element) with support for the layout of control elements.\n *\n * @memberof OpenSeadragon\n */$.ControlDock=function(options){var layouts=['topleft','topright','bottomright','bottomleft'],layout,i;$.extend(true,this,{id:'controldock-'+$.now()+'-'+Math.floor(Math.random()*1000000),container:$.makeNeutralElement('div'),controls:[]},options);// Disable the form's submit; otherwise button clicks and return keys\n// can trigger it.\nthis.container.onsubmit=function(){return false;};if(this.element){this.element=$.getElement(this.element);this.element.appendChild(this.container);this.element.style.position='relative';this.container.style.width='100%';this.container.style.height='100%';}for(i=0;i=0){return;// they're trying to add a duplicate control\n}switch(controlOptions.anchor){case $.ControlAnchor.TOP_RIGHT:div=this.controls.topright;element.style.position=\"relative\";element.style.paddingRight=\"0px\";element.style.paddingTop=\"0px\";break;case $.ControlAnchor.BOTTOM_RIGHT:div=this.controls.bottomright;element.style.position=\"relative\";element.style.paddingRight=\"0px\";element.style.paddingBottom=\"0px\";break;case $.ControlAnchor.BOTTOM_LEFT:div=this.controls.bottomleft;element.style.position=\"relative\";element.style.paddingLeft=\"0px\";element.style.paddingBottom=\"0px\";break;case $.ControlAnchor.TOP_LEFT:div=this.controls.topleft;element.style.position=\"relative\";element.style.paddingLeft=\"0px\";element.style.paddingTop=\"0px\";break;case $.ControlAnchor.ABSOLUTE:div=this.container;element.style.margin=\"0px\";element.style.padding=\"0px\";break;default:case $.ControlAnchor.NONE:div=this.container;element.style.margin=\"0px\";element.style.padding=\"0px\";break;}this.controls.push(new $.Control(element,controlOptions,div));element.style.display=\"inline-block\";},/**\n * @function\n * @return {OpenSeadragon.ControlDock} Chainable.\n */removeControl:function removeControl(element){element=$.getElement(element);var i=getControlIndex(this,element);if(i>=0){this.controls[i].destroy();this.controls.splice(i,1);}return this;},/**\n * @function\n * @return {OpenSeadragon.ControlDock} Chainable.\n */clearControls:function clearControls(){while(this.controls.length>0){this.controls.pop().destroy();}return this;},/**\n * @function\n * @return {Boolean}\n */areControlsEnabled:function areControlsEnabled(){var i;for(i=this.controls.length-1;i>=0;i--){if(this.controls[i].isVisible()){return true;}}return false;},/**\n * @function\n * @return {OpenSeadragon.ControlDock} Chainable.\n */setControlsEnabled:function setControlsEnabled(enabled){var i;for(i=this.controls.length-1;i>=0;i--){this.controls[i].setVisible(enabled);}return this;}};///////////////////////////////////////////////////////////////////////////////\n// Utility methods\n///////////////////////////////////////////////////////////////////////////////\nfunction getControlIndex(dock,element){var controls=dock.controls,i;for(i=controls.length-1;i>=0;i--){if(controls[i].element==element){return i;}}return-1;}})(OpenSeadragon);/*\n * OpenSeadragon - Placement\n *\n * Copyright (C) 2010-2016 OpenSeadragon contributors\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * - Redistributions of source code must retain the above copyright notice,\n * this list of conditions and the following disclaimer.\n *\n * - Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n *\n * - Neither the name of CodePlex Foundation nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\n * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */(function($){/**\n * An enumeration of positions to anchor an element.\n * @member Placement\n * @memberOf OpenSeadragon\n * @static\n * @readonly\n * @property {OpenSeadragon.Placement} CENTER\n * @property {OpenSeadragon.Placement} TOP_LEFT\n * @property {OpenSeadragon.Placement} TOP\n * @property {OpenSeadragon.Placement} TOP_RIGHT\n * @property {OpenSeadragon.Placement} RIGHT\n * @property {OpenSeadragon.Placement} BOTTOM_RIGHT\n * @property {OpenSeadragon.Placement} BOTTOM\n * @property {OpenSeadragon.Placement} BOTTOM_LEFT\n * @property {OpenSeadragon.Placement} LEFT\n */$.Placement=$.freezeObject({CENTER:0,TOP_LEFT:1,TOP:2,TOP_RIGHT:3,RIGHT:4,BOTTOM_RIGHT:5,BOTTOM:6,BOTTOM_LEFT:7,LEFT:8,properties:{0:{isLeft:false,isHorizontallyCentered:true,isRight:false,isTop:false,isVerticallyCentered:true,isBottom:false},1:{isLeft:true,isHorizontallyCentered:false,isRight:false,isTop:true,isVerticallyCentered:false,isBottom:false},2:{isLeft:false,isHorizontallyCentered:true,isRight:false,isTop:true,isVerticallyCentered:false,isBottom:false},3:{isLeft:false,isHorizontallyCentered:false,isRight:true,isTop:true,isVerticallyCentered:false,isBottom:false},4:{isLeft:false,isHorizontallyCentered:false,isRight:true,isTop:false,isVerticallyCentered:true,isBottom:false},5:{isLeft:false,isHorizontallyCentered:false,isRight:true,isTop:false,isVerticallyCentered:false,isBottom:true},6:{isLeft:false,isHorizontallyCentered:true,isRight:false,isTop:false,isVerticallyCentered:false,isBottom:true},7:{isLeft:true,isHorizontallyCentered:false,isRight:false,isTop:false,isVerticallyCentered:false,isBottom:true},8:{isLeft:true,isHorizontallyCentered:false,isRight:false,isTop:false,isVerticallyCentered:true,isBottom:false}}});})(OpenSeadragon);/*\n * OpenSeadragon - Viewer\n *\n * Copyright (C) 2009 CodePlex Foundation\n * Copyright (C) 2010-2013 OpenSeadragon contributors\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * - Redistributions of source code must retain the above copyright notice,\n * this list of conditions and the following disclaimer.\n *\n * - Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n *\n * - Neither the name of CodePlex Foundation nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\n * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */(function($){// dictionary from hash to private properties\nvar THIS={};var nextHash=1;/**\n *\n * The main point of entry into creating a zoomable image on the page.
\n *
\n * We have provided an idiomatic javascript constructor which takes\n * a single object, but still support the legacy positional arguments.
\n *
\n * The options below are given in order that they appeared in the constructor\n * as arguments and we translate a positional call into an idiomatic call.
\n *
\n * To create a viewer, you can use either of this methods:
\n *
    \n *
  • var viewer = new OpenSeadragon.Viewer(options);
  • \n *
  • var viewer = OpenSeadragon(options);
  • \n *
\n * @class Viewer\n * @classdesc The main OpenSeadragon viewer class.\n *\n * @memberof OpenSeadragon\n * @extends OpenSeadragon.EventSource\n * @extends OpenSeadragon.ControlDock\n * @param {OpenSeadragon.Options} options - Viewer options.\n *\n **/$.Viewer=function(options){var args=arguments,_this=this,i;//backward compatibility for positional args while prefering more\n//idiomatic javascript options object as the only argument\nif(!$.isPlainObject(options)){options={id:args[0],xmlPath:args.length>1?args[1]:undefined,prefixUrl:args.length>2?args[2]:undefined,controls:args.length>3?args[3]:undefined,overlays:args.length>4?args[4]:undefined};}//options.config and the general config argument are deprecated\n//in favor of the more direct specification of optional settings\n//being pass directly on the options object\nif(options.config){$.extend(true,options,options.config);delete options.config;}//Public properties\n//Allow the options object to override global defaults\n$.extend(true,this,{//internal state and dom identifiers\nid:options.id,hash:options.hash||nextHash++,/**\n * Index for page to be shown first next time open() is called (only used in sequenceMode).\n * @member {Number} initialPage\n * @memberof OpenSeadragon.Viewer#\n */initialPage:0,//dom nodes\n/**\n * The parent element of this Viewer instance, passed in when the Viewer was created.\n * @member {Element} element\n * @memberof OpenSeadragon.Viewer#\n */element:null,/**\n * A <div> element (provided by {@link OpenSeadragon.ControlDock}), the base element of this Viewer instance.

\n * Child element of {@link OpenSeadragon.Viewer#element}.\n * @member {Element} container\n * @memberof OpenSeadragon.Viewer#\n */container:null,/**\n * A <div> element, the element where user-input events are handled for panning and zooming.

\n * Child element of {@link OpenSeadragon.Viewer#container},\n * positioned on top of {@link OpenSeadragon.Viewer#keyboardCommandArea}.

\n * The parent of {@link OpenSeadragon.Drawer#canvas} instances.\n * @member {Element} canvas\n * @memberof OpenSeadragon.Viewer#\n */canvas:null,// Overlays list. An overlay allows to add html on top of the viewer.\noverlays:[],// Container inside the canvas where overlays are drawn.\noverlaysContainer:null,//private state properties\npreviousBody:[],//This was originally initialized in the constructor and so could never\n//have anything in it. now it can because we allow it to be specified\n//in the options and is only empty by default if not specified. Also\n//this array was returned from get_controls which I find confusing\n//since this object has a controls property which is treated in other\n//functions like clearControls. I'm removing the accessors.\ncustomControls:[],//These are originally not part options but declared as members\n//in initialize. It's still considered idiomatic to put them here\nsource:null,/**\n * Handles rendering of tiles in the viewer. Created for each TileSource opened.\n * @member {OpenSeadragon.Drawer} drawer\n * @memberof OpenSeadragon.Viewer#\n */drawer:null,world:null,/**\n * Handles coordinate-related functionality - zoom, pan, rotation, etc. Created for each TileSource opened.\n * @member {OpenSeadragon.Viewport} viewport\n * @memberof OpenSeadragon.Viewer#\n */viewport:null,/**\n * @member {OpenSeadragon.Navigator} navigator\n * @memberof OpenSeadragon.Viewer#\n */navigator:null,//A collection viewport is a separate viewport used to provide\n//simultaneous rendering of sets of tiles\ncollectionViewport:null,collectionDrawer:null,//UI image resources\n//TODO: rename navImages to uiImages\nnavImages:null,//interface button controls\nbuttons:null,//TODO: this is defunct so safely remove it\nprofiler:null},$.DEFAULT_SETTINGS,options);if(typeof this.hash===\"undefined\"){throw new Error(\"A hash must be defined, either by specifying options.id or options.hash.\");}if(typeof THIS[this.hash]!==\"undefined\"){// We don't want to throw an error here, as the user might have discarded\n// the previous viewer with the same hash and now want to recreate it.\n$.console.warn(\"Hash \"+this.hash+\" has already been used.\");}//Private state properties\nTHIS[this.hash]={\"fsBoundsDelta\":new $.Point(1,1),\"prevContainerSize\":null,\"animating\":false,\"forceRedraw\":false,\"mouseInside\":false,\"group\":null,// whether we should be continuously zooming\n\"zooming\":false,// how much we should be continuously zooming by\n\"zoomFactor\":null,\"lastZoomTime\":null,\"fullPage\":false,\"onfullscreenchange\":null};this._sequenceIndex=0;this._firstOpen=true;this._updateRequestId=null;this._loadQueue=[];this.currentOverlays=[];this._lastScrollTime=$.now();// variable used to help normalize the scroll event speed of different devices\n//Inherit some behaviors and properties\n$.EventSource.call(this);this.addHandler('open-failed',function(event){var msg=$.getString(\"Errors.OpenFailed\",event.eventSource,event.message);_this._showMessage(msg);});$.ControlDock.call(this,options);//Deal with tile sources\nif(this.xmlPath){//Deprecated option. Now it is preferred to use the tileSources option\nthis.tileSources=[this.xmlPath];}this.element=this.element||document.getElementById(this.id);this.canvas=$.makeNeutralElement(\"div\");this.canvas.className=\"openseadragon-canvas\";(function(style){style.width=\"100%\";style.height=\"100%\";style.overflow=\"hidden\";style.position=\"absolute\";style.top=\"0px\";style.left=\"0px\";})(this.canvas.style);$.setElementTouchActionNone(this.canvas);if(options.tabIndex!==\"\"){this.canvas.tabIndex=options.tabIndex===undefined?0:options.tabIndex;}//the container is created through applying the ControlDock constructor above\nthis.container.className=\"openseadragon-container\";(function(style){style.width=\"100%\";style.height=\"100%\";style.position=\"relative\";style.overflow=\"hidden\";style.left=\"0px\";style.top=\"0px\";style.textAlign=\"left\";// needed to protect against\n})(this.container.style);this.container.insertBefore(this.canvas,this.container.firstChild);this.element.appendChild(this.container);//Used for toggling between fullscreen and default container size\n//TODO: these can be closure private and shared across Viewer\n// instances.\nthis.bodyWidth=document.body.style.width;this.bodyHeight=document.body.style.height;this.bodyOverflow=document.body.style.overflow;this.docOverflow=document.documentElement.style.overflow;this.innerTracker=new $.MouseTracker({element:this.canvas,startDisabled:!this.mouseNavEnabled,clickTimeThreshold:this.clickTimeThreshold,clickDistThreshold:this.clickDistThreshold,dblClickTimeThreshold:this.dblClickTimeThreshold,dblClickDistThreshold:this.dblClickDistThreshold,keyDownHandler:$.delegate(this,onCanvasKeyDown),keyHandler:$.delegate(this,onCanvasKeyPress),clickHandler:$.delegate(this,onCanvasClick),dblClickHandler:$.delegate(this,onCanvasDblClick),dragHandler:$.delegate(this,onCanvasDrag),dragEndHandler:$.delegate(this,onCanvasDragEnd),enterHandler:$.delegate(this,onCanvasEnter),exitHandler:$.delegate(this,onCanvasExit),pressHandler:$.delegate(this,onCanvasPress),releaseHandler:$.delegate(this,onCanvasRelease),nonPrimaryPressHandler:$.delegate(this,onCanvasNonPrimaryPress),nonPrimaryReleaseHandler:$.delegate(this,onCanvasNonPrimaryRelease),scrollHandler:$.delegate(this,onCanvasScroll),pinchHandler:$.delegate(this,onCanvasPinch)});this.outerTracker=new $.MouseTracker({element:this.container,startDisabled:!this.mouseNavEnabled,clickTimeThreshold:this.clickTimeThreshold,clickDistThreshold:this.clickDistThreshold,dblClickTimeThreshold:this.dblClickTimeThreshold,dblClickDistThreshold:this.dblClickDistThreshold,enterHandler:$.delegate(this,onContainerEnter),exitHandler:$.delegate(this,onContainerExit)});if(this.toolbar){this.toolbar=new $.ControlDock({element:this.toolbar});}this.bindStandardControls();THIS[this.hash].prevContainerSize=_getSafeElemSize(this.container);// Create the world\nthis.world=new $.World({viewer:this});this.world.addHandler('add-item',function(event){// For backwards compatibility, we maintain the source property\n_this.source=_this.world.getItemAt(0).source;THIS[_this.hash].forceRedraw=true;if(!_this._updateRequestId){_this._updateRequestId=scheduleUpdate(_this,updateMulti);}});this.world.addHandler('remove-item',function(event){// For backwards compatibility, we maintain the source property\nif(_this.world.getItemCount()){_this.source=_this.world.getItemAt(0).source;}else{_this.source=null;}THIS[_this.hash].forceRedraw=true;});this.world.addHandler('metrics-change',function(event){if(_this.viewport){_this.viewport._setContentBounds(_this.world.getHomeBounds(),_this.world.getContentFactor());}});this.world.addHandler('item-index-change',function(event){// For backwards compatibility, we maintain the source property\n_this.source=_this.world.getItemAt(0).source;});// Create the viewport\nthis.viewport=new $.Viewport({containerSize:THIS[this.hash].prevContainerSize,springStiffness:this.springStiffness,animationTime:this.animationTime,minZoomImageRatio:this.minZoomImageRatio,maxZoomPixelRatio:this.maxZoomPixelRatio,visibilityRatio:this.visibilityRatio,wrapHorizontal:this.wrapHorizontal,wrapVertical:this.wrapVertical,defaultZoomLevel:this.defaultZoomLevel,minZoomLevel:this.minZoomLevel,maxZoomLevel:this.maxZoomLevel,viewer:this,degrees:this.degrees,flipped:this.flipped,navigatorRotate:this.navigatorRotate,homeFillsViewer:this.homeFillsViewer,margins:this.viewportMargins});this.viewport._setContentBounds(this.world.getHomeBounds(),this.world.getContentFactor());// Create the image loader\nthis.imageLoader=new $.ImageLoader({jobLimit:this.imageLoaderLimit,timeout:options.timeout});// Create the tile cache\nthis.tileCache=new $.TileCache({maxImageCacheCount:this.maxImageCacheCount});// Create the drawer\nthis.drawer=new $.Drawer({viewer:this,viewport:this.viewport,element:this.canvas,debugGridColor:this.debugGridColor});// Overlay container\nthis.overlaysContainer=$.makeNeutralElement(\"div\");this.canvas.appendChild(this.overlaysContainer);// Now that we have a drawer, see if it supports rotate. If not we need to remove the rotate buttons\nif(!this.drawer.canRotate()){// Disable/remove the rotate left/right buttons since they aren't supported\nif(this.rotateLeft){i=this.buttons.buttons.indexOf(this.rotateLeft);this.buttons.buttons.splice(i,1);this.buttons.element.removeChild(this.rotateLeft.element);}if(this.rotateRight){i=this.buttons.buttons.indexOf(this.rotateRight);this.buttons.buttons.splice(i,1);this.buttons.element.removeChild(this.rotateRight.element);}}//Instantiate a navigator if configured\nif(this.showNavigator){this.navigator=new $.Navigator({id:this.navigatorId,position:this.navigatorPosition,sizeRatio:this.navigatorSizeRatio,maintainSizeRatio:this.navigatorMaintainSizeRatio,top:this.navigatorTop,left:this.navigatorLeft,width:this.navigatorWidth,height:this.navigatorHeight,autoResize:this.navigatorAutoResize,autoFade:this.navigatorAutoFade,prefixUrl:this.prefixUrl,viewer:this,navigatorRotate:this.navigatorRotate,crossOriginPolicy:this.crossOriginPolicy});}// Sequence mode\nif(this.sequenceMode){this.bindSequenceControls();}// Open initial tilesources\nif(this.tileSources){this.open(this.tileSources);}// Add custom controls\nfor(i=0;i