{"version":3,"sources":["jsdelivr-header.js","/npm/photo-sphere-viewer@4.1.0/src/data/constants.js","/npm/photo-sphere-viewer@4.1.0/src/utils/browser.js","/npm/photo-sphere-viewer@4.1.0/src/utils/math.js","/npm/photo-sphere-viewer@4.1.0/src/utils/misc.js","/npm/photo-sphere-viewer@4.1.0/src/PSVError.js","/npm/photo-sphere-viewer@4.1.0/src/utils/psv.js","/npm/photo-sphere-viewer@4.1.0/src/Animation.js","/npm/photo-sphere-viewer@4.1.0/src/components/AbstractComponent.js","/npm/photo-sphere-viewer@4.1.0/src/buttons/AbstractButton.js","/npm/photo-sphere-viewer@4.1.0/src/buttons/AutorotateButton.js","/npm/photo-sphere-viewer@4.1.0/src/buttons/CustomButton.js","/npm/photo-sphere-viewer@4.1.0/src/buttons/DownloadButton.js","/npm/photo-sphere-viewer@4.1.0/src/buttons/FullscreenButton.js","/npm/photo-sphere-viewer@4.1.0/src/buttons/MenuButton.js","/npm/photo-sphere-viewer@4.1.0/src/data/system.js","/npm/photo-sphere-viewer@4.1.0/src/buttons/AbstractZoomButton.js","/npm/photo-sphere-viewer@4.1.0/src/buttons/ZoomInButton.js","/npm/photo-sphere-viewer@4.1.0/src/buttons/ZoomOutButton.js","/npm/photo-sphere-viewer@4.1.0/src/buttons/ZoomRangeButton.js","/npm/photo-sphere-viewer@4.1.0/src/data/config.js","/npm/photo-sphere-viewer@4.1.0/src/buttons/CaptionButton.js","/npm/photo-sphere-viewer@4.1.0/src/components/NavbarCaption.js","/npm/photo-sphere-viewer@4.1.0/src/components/Navbar.js","/npm/photo-sphere-viewer@4.1.0/src/plugins/AbstractPlugin.js","/npm/photo-sphere-viewer@4.1.0/src/components/Loader.js","/npm/photo-sphere-viewer@4.1.0/src/components/Notification.js","/npm/photo-sphere-viewer@4.1.0/src/components/Overlay.js","/npm/photo-sphere-viewer@4.1.0/src/components/Panel.js","/npm/photo-sphere-viewer@4.1.0/src/services/AbstractService.js","/npm/photo-sphere-viewer@4.1.0/src/services/DataHelper.js","/npm/photo-sphere-viewer@4.1.0/src/services/EventsHandler.js","/npm/photo-sphere-viewer@4.1.0/src/services/Renderer.js","/npm/photo-sphere-viewer@4.1.0/src/services/TextureLoader.js","/npm/photo-sphere-viewer@4.1.0/src/components/Tooltip.js","/npm/photo-sphere-viewer@4.1.0/src/services/TooltipRenderer.js","/npm/photo-sphere-viewer@4.1.0/src/Viewer.js"],"names":[],"mappings":"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","file":"/npm/photo-sphere-viewer@4.1.0/dist/photo-sphere-viewer.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/photo-sphere-viewer@4.1.0/dist/photo-sphere-viewer.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","/**\n * @namespace PSV.constants\n */\n\n/**\n * @summary Number of pixels bellow which a mouse move will be considered as a click\n * @memberOf PSV.constants\n * @type {number}\n * @constant\n */\nexport const MOVE_THRESHOLD = 4;\n\n/**\n * @summary Delay in milliseconds between two clicks to consider a double click\n * @memberOf PSV.constants\n * @type {number}\n * @constant\n */\nexport const DBLCLICK_DELAY = 300;\n\n/**\n * @summary Delay in milliseconds to emulate a long touch\n * @memberOf PSV.constants\n * @type {number}\n * @constant\n */\nexport const LONGTOUCH_DELAY = 500;\n\n/**\n * @summary Delay in milliseconds to for the two fingers overlay to appear\n * @memberOf PSV.constants\n * @type {number}\n * @constant\n */\nexport const TWOFINGERSOVERLAY_DELAY = 100;\n\n/**\n * @summary Duration in milliseconds of the \"ctrl zoom\" overlay\n * @memberOf PSV.constants\n * @type {number}\n * @constant\n */\nexport const CTRLZOOM_TIMEOUT = 2000;\n\n/**\n * @summary Time size of the mouse position history used to compute inertia\n * @memberOf PSV.constants\n * @type {number}\n * @constant\n */\nexport const INERTIA_WINDOW = 300;\n\n/**\n * @summary Radius of the THREE.SphereGeometry, Half-length of the THREE.BoxGeometry\n * @memberOf PSV.constants\n * @type {number}\n * @constant\n */\nexport const SPHERE_RADIUS = 100;\n\n/**\n * @summary Number of vertice of the THREE.SphereGeometry\n * @memberOf PSV.constants\n * @type {number}\n * @constant\n */\nexport const SPHERE_VERTICES = 64;\n\n/**\n * @summary Number of vertices of each side of the THREE.BoxGeometry\n * @memberOf PSV.constants\n * @type {number}\n * @constant\n */\nexport const CUBE_VERTICES = 8;\n\n/**\n * @summary Order of cube textures for arrays\n * @memberOf PSV.constants\n * @type {number[]}\n * @constant\n */\nexport const CUBE_MAP = [0, 2, 4, 5, 3, 1];\n\n/**\n * @summary Order of cube textures for maps\n * @memberOf PSV.constants\n * @type {string[]}\n * @constant\n */\nexport const CUBE_HASHMAP = ['left', 'right', 'top', 'bottom', 'back', 'front'];\n\n/**\n * @summary Property name added to viewer element\n * @memberOf PSV.constants\n * @type {string}\n * @constant\n */\nexport const VIEWER_DATA = 'photoSphereViewer';\n\n/**\n * @summary Available actions\n * @memberOf PSV.constants\n * @enum {string}\n * @constant\n */\nexport const ACTIONS = {\n  ROTATE_LAT_UP    : 'rotateLatitudeUp',\n  ROTATE_LAT_DOWN  : 'rotateLatitudeDown',\n  ROTATE_LONG_RIGHT: 'rotateLongitudeRight',\n  ROTATE_LONG_LEFT : 'rotateLongitudeLeft',\n  ZOOM_IN          : 'zoomIn',\n  ZOOM_OUT         : 'zoomOut',\n  TOGGLE_AUTOROTATE: 'toggleAutorotate',\n};\n\n/**\n * @summary Available events names\n * @memberOf PSV.constants\n * @enum {string}\n * @constant\n */\nexport const EVENTS = {\n  /**\n   * @event autorotate\n   * @memberof PSV\n   * @summary Triggered when the automatic rotation is enabled/disabled\n   * @param {boolean} enabled\n   */\n  AUTOROTATE        : 'autorotate',\n  /**\n   * @event before-render\n   * @memberof PSV\n   * @summary Triggered before a render, used to modify the view\n   * @param {number} timestamp - time provided by requestAnimationFrame\n   */\n  BEFORE_RENDER     : 'before-render',\n  /**\n   * @event before-rotate\n   * @memberOf PSV\n   * @summary Triggered before a rotate operation, can be cancelled\n   * @param {PSV.ExtendedPosition}\n   */\n  BEFORE_ROTATE     : 'before-rotate',\n  /**\n   * @event click\n   * @memberof PSV\n   * @summary Triggered when the user clicks on the viewer (everywhere excluding the navbar and the side panel)\n   * @param {PSV.ClickData} data\n   */\n  CLICK             : 'click',\n  /**\n   * @event close-panel\n   * @memberof PSV\n   * @summary Trigered when the panel is closed\n   * @param {string} [id]\n   */\n  CLOSE_PANEL       : 'close-panel',\n  /**\n   * @event config-changed\n   * @memberOf PSV\n   * @summary Triggered after a call to setOption/setOptions\n   * @param {string[]} name of changed options\n   */\n  CONFIG_CHANGED    : 'config-changed',\n  /**\n   * @event dblclick\n   * @memberof PSV\n   * @summary Triggered when the user double clicks on the viewer. The simple `click` event is always fired before `dblclick`\n   * @param {PSV.ClickData} data\n   */\n  DOUBLE_CLICK      : 'dblclick',\n  /**\n   * @event fullscreen-updated\n   * @memberof PSV\n   * @summary Triggered when the fullscreen mode is enabled/disabled\n   * @param {boolean} enabled\n   */\n  FULLSCREEN_UPDATED: 'fullscreen-updated',\n  /**\n   * @event hide-notification\n   * @memberof PSV\n   * @summary Trigered when the notification is hidden\n   */\n  HIDE_NOTIFICATION : 'hide-notification',\n  /**\n   * @event hide-overlay\n   * @memberof PSV\n   * @summary Trigered when the overlay is hidden\n   * @param {string} [id]\n   */\n  HIDE_OVERLAY      : 'hide-overlay',\n  /**\n   * @event hide-tooltip\n   * @memberof PSV\n   * @summary Trigered when the tooltip is hidden\n   * @param {*} Data associated to this tooltip\n   */\n  HIDE_TOOLTIP      : 'hide-tooltip',\n  /**\n   * @event open-panel\n   * @memberof PSV\n   * @summary Triggered when the panel is opened\n   * @param {string} [id]\n   */\n  OPEN_PANEL        : 'open-panel',\n  /**\n   * @event panorama-loaded\n   * @memberof PSV\n   * @summary Triggered when a panorama image has been loaded\n   */\n  PANORAMA_LOADED   : 'panorama-loaded',\n  /**\n   * @event position-updated\n   * @memberof PSV\n   * @summary Triggered when the view longitude and/or latitude changes\n   * @param {PSV.Position} position\n   */\n  POSITION_UPDATED  : 'position-updated',\n  /**\n   * @event ready\n   * @memberof PSV\n   * @summary Triggered when the panorama image has been loaded and the viewer is ready to perform the first render\n   */\n  READY             : 'ready',\n  /**\n   * @event render\n   * @memberof PSV\n   * @summary Triggered on each viewer render, **this event is triggered very often**\n   */\n  RENDER            : 'render',\n  /**\n   * @event show-notification\n   * @memberof PSV\n   * @summary Trigered when the notification is shown\n   */\n  SHOW_NOTIFICATION : 'show-notification',\n  /**\n   * @event show-overlay\n   * @memberof PSV\n   * @summary Trigered when the overlay is shown\n   * @param {string} [id]\n   */\n  SHOW_OVERLAY      : 'show-overlay',\n  /**\n   * @event show-tooltip\n   * @memberof PSV\n   * @summary Trigered when the tooltip is shown\n   * @param {*} Data associated to this tooltip\n   * @param {PSV.components.Tooltip} Instance of the tooltip\n   */\n  SHOW_TOOLTIP      : 'show-tooltip',\n  /**\n   * @event size-updated\n   * @memberof PSV\n   * @summary Triggered when the viewer size changes\n   * @param {PSV.Size} size\n   */\n  SIZE_UPDATED      : 'size-updated',\n  /**\n   * @event stop-all\n   * @memberof PSV\n   * @summary Triggered when all current animations are stopped\n   */\n  STOP_ALL          : 'stop-all',\n  /**\n   * @event zoom-updated\n   * @memberof PSV\n   * @summary Triggered when the zoom level changes\n   * @param {number} zoomLevel\n   */\n  ZOOM_UPDATED      : 'zoom-updated',\n};\n\n/**\n * @summary Available change events names\n * @memberOf PSV.constants\n * @enum {string}\n * @constant\n */\nexport const CHANGE_EVENTS = {\n  /**\n   * @event get-animate-position\n   * @memberof PSV\n   * @param {Position} position\n   * @returns {Position}\n   * @summary Called to alter the target position of an animation\n   */\n  GET_ANIMATE_POSITION: 'get-animate-position',\n  /**\n   * @event get-rotate-position\n   * @memberof PSV\n   * @param {Position} position\n   * @returns {Position}\n   * @summary Called to alter the target position of a rotation\n   */\n  GET_ROTATE_POSITION : 'get-rotate-position',\n};\n\n/**\n * @summary Internal identifiers for various stuff\n * @memberOf PSV.constants\n * @enum {string}\n * @constant\n */\nexport const IDS = {\n  MENU       : 'menu',\n  TWO_FINGERS: 'twoFingers',\n  CTRL_ZOOM  : 'ctrlZoom',\n  ERROR      : 'error',\n};\n\n/* eslint-disable */\n// @formatter:off\n/**\n * @summary Collection of easing functions\n * @memberOf PSV.constants\n * @see {@link https://gist.github.com/frederickk/6165768}\n * @type {Object<string, Function>}\n * @constant\n */\nexport const EASINGS = {\n  linear    : (t) => t,\n\n  inQuad    : (t) => t*t,\n  outQuad   : (t) => t*(2-t),\n  inOutQuad : (t) => t<.5 ? 2*t*t : -1+(4-2*t)*t,\n\n  inCubic   : (t) => t*t*t,\n  outCubic  : (t) => (--t)*t*t+1,\n  inOutCubic: (t) => t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1,\n\n  inQuart   : (t) => t*t*t*t,\n  outQuart  : (t) => 1-(--t)*t*t*t,\n  inOutQuart: (t) => t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t,\n\n  inQuint   : (t) => t*t*t*t*t,\n  outQuint  : (t) => 1+(--t)*t*t*t*t,\n  inOutQuint: (t) => t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t,\n\n  inSine    : (t) => 1-Math.cos(t*(Math.PI/2)),\n  outSine   : (t) => Math.sin(t*(Math.PI/2)),\n  inOutSine : (t) => .5-.5*Math.cos(Math.PI*t),\n\n  inExpo    : (t) => Math.pow(2, 10*(t-1)),\n  outExpo   : (t) => 1-Math.pow(2, -10*t),\n  inOutExpo : (t) => (t=t*2-1)<0 ? .5*Math.pow(2, 10*t) : 1-.5*Math.pow(2, -10*t),\n\n  inCirc    : (t) => 1-Math.sqrt(1-t*t),\n  outCirc   : (t) => Math.sqrt(1-(t-1)*(t-1)),\n  inOutCirc : (t) => (t*=2)<1 ? .5-.5*Math.sqrt(1-t*t) : .5+.5*Math.sqrt(1-(t-=2)*t)\n};\n// @formatter:on\n/* eslint-enable */\n","/**\n * @summary Toggles a CSS class\n * @memberOf PSV.utils\n * @param {HTMLElement|SVGElement} element\n * @param {string} className\n * @param {boolean} [active] - forced state\n */\nexport function toggleClass(element, className, active) {\n  // manual implementation for IE11 and SVGElement\n  if (!element.classList) {\n    let currentClassName = element.getAttribute('class') || '';\n    const currentActive = currentClassName.indexOf(className) !== -1;\n    const regex = new RegExp('(?:^|\\\\s)' + className + '(?:\\\\s|$)');\n\n    if ((active === undefined || active) && !currentActive) {\n      currentClassName += currentClassName.length > 0 ? ' ' + className : className;\n    }\n    else if (!active) {\n      currentClassName = currentClassName.replace(regex, ' ');\n    }\n\n    element.setAttribute('class', currentClassName);\n  }\n  else if (active === undefined) {\n    element.classList.toggle(className);\n  }\n  else if (active && !element.classList.contains(className)) {\n    element.classList.add(className);\n  }\n  else if (!active) {\n    element.classList.remove(className);\n  }\n}\n\n/**\n * @summary Adds one or several CSS classes to an element\n * @memberOf PSV.utils\n * @param {HTMLElement} element\n * @param {string} className\n */\nexport function addClasses(element, className) {\n  if (className) {\n    className.split(' ').forEach((name) => {\n      toggleClass(element, name, true);\n    });\n  }\n}\n\n/**\n * @summary Removes one or several CSS classes to an element\n * @memberOf PSV.utils\n * @param {HTMLElement} element\n * @param {string} className\n */\nexport function removeClasses(element, className) {\n  if (className) {\n    className.split(' ').forEach((name) => {\n      toggleClass(element, name, false);\n    });\n  }\n}\n\n/**\n * @summary Searches if an element has a particular parent at any level including itself\n * @memberOf PSV.utils\n * @param {HTMLElement} el\n * @param {HTMLElement} parent\n * @returns {boolean}\n */\nexport function hasParent(el, parent) {\n  let test = el;\n\n  do {\n    if (test === parent) {\n      return true;\n    }\n    test = test.parentNode;\n  } while (test);\n\n  return false;\n}\n\n/**\n * @summary Gets the closest parent (can by itself)\n * @memberOf PSV.utils\n * @param {HTMLElement|SVGElement} el\n * @param {string} selector\n * @returns {HTMLElement}\n */\nexport function getClosest(el, selector) {\n  const matches = el.matches || el.msMatchesSelector;\n  let test = el;\n  // When el is document or window, the matches does not exist\n  if (!matches) {\n    return null;\n  }\n\n  do {\n    if (matches.bind(test)(selector)) {\n      return test;\n    }\n    test = test instanceof SVGElement ? test.parentNode : test.parentElement;\n  } while (test);\n\n  return null;\n}\n\n/**\n * @summary Map between keyboard events `keyCode|which` and `key`\n * @memberOf PSV.utils\n * @type {Object<int, string>}\n * @readonly\n * @private\n */\nconst KEYMAP = {\n  13 : 'Enter',\n  17 : 'Control',\n  27 : 'Escape',\n  32 : ' ',\n  33 : 'PageUp',\n  34 : 'PageDown',\n  37 : 'ArrowLeft',\n  38 : 'ArrowUp',\n  39 : 'ArrowRight',\n  40 : 'ArrowDown',\n  46 : 'Delete',\n  107: '+',\n  109: '-',\n};\n\n/**\n * @summary Map for non standard keyboard events `key` for IE and Edge\n * @see https://github.com/shvaikalesh/shim-keyboard-event-key\n * @type {Object<string, string>}\n * @readonly\n * @private\n */\nconst MS_KEYMAP = {\n  Add     : '+',\n  Del     : 'Delete',\n  Down    : 'ArrowDown',\n  Esc     : 'Escape',\n  Left    : 'ArrowLeft',\n  Right   : 'ArrowRight',\n  Spacebar: ' ',\n  Subtract: '-',\n  Up      : 'ArrowUp',\n};\n\n/**\n * @summary Returns the key name of a KeyboardEvent\n * @memberOf PSV.utils\n * @param {KeyboardEvent} evt\n * @returns {string}\n */\nexport function getEventKey(evt) {\n  let key = evt.key || KEYMAP[evt.keyCode || evt.which];\n\n  if (key && MS_KEYMAP[key]) {\n    key = MS_KEYMAP[key];\n  }\n\n  return key;\n}\n\n/**\n * @summary Detects if fullscreen is enabled\n * @memberOf PSV.utils\n * @param {HTMLElement} elt\n * @returns {boolean}\n */\nexport function isFullscreenEnabled(elt) {\n  /* eslint-disable-next-line max-len */\n  return (document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement) === elt;\n}\n\n/**\n * @summary Enters fullscreen mode\n * @memberOf PSV.utils\n * @param {HTMLElement} elt\n */\nexport function requestFullscreen(elt) {\n  /* eslint-disable-next-line max-len */\n  (elt.requestFullscreen || elt.mozRequestFullScreen || elt.webkitRequestFullscreen || elt.msRequestFullscreen).call(elt);\n}\n\n/**\n * @summary Exits fullscreen mode\n * @memberOf PSV.utils\n */\nexport function exitFullscreen() {\n  /* eslint-disable-next-line max-len */\n  (document.exitFullscreen || document.mozCancelFullScreen || document.webkitExitFullscreen || document.msExitFullscreen).call(document);\n}\n\n/**\n * @summary Gets an element style\n * @memberOf PSV.utils\n * @param {HTMLElement} elt\n * @param {string} prop\n * @returns {*}\n */\nexport function getStyle(elt, prop) {\n  return window.getComputedStyle(elt, null)[prop];\n}\n\n/**\n * @summary Normalize mousewheel values accross browsers\n * @memberOf PSV.utils\n * @description From Facebook's Fixed Data Table\n * {@link https://github.com/facebookarchive/fixed-data-table/blob/master/src/vendor_upstream/dom/normalizeWheel.js}\n * @copyright Facebook\n * @param {WheelEvent} event\n * @returns {{spinX: number, spinY: number, pixelX: number, pixelY: number}}\n */\nexport function normalizeWheel(event) {\n  const PIXEL_STEP = 10;\n  const LINE_HEIGHT = 40;\n  const PAGE_HEIGHT = 800;\n\n  let spinX = 0;\n  let spinY = 0;\n  let pixelX = 0;\n  let pixelY = 0;\n\n  // Legacy\n  if ('detail' in event) {\n    spinY = event.detail;\n  }\n  if ('wheelDelta' in event) {\n    spinY = -event.wheelDelta / 120;\n  }\n  if ('wheelDeltaY' in event) {\n    spinY = -event.wheelDeltaY / 120;\n  }\n  if ('wheelDeltaX' in event) {\n    spinX = -event.wheelDeltaX / 120;\n  }\n\n  // side scrolling on FF with DOMMouseScroll\n  if ('axis' in event && event.axis === event.HORIZONTAL_AXIS) {\n    spinX = spinY;\n    spinY = 0;\n  }\n\n  pixelX = spinX * PIXEL_STEP;\n  pixelY = spinY * PIXEL_STEP;\n\n  if ('deltaY' in event) {\n    pixelY = event.deltaY;\n  }\n  if ('deltaX' in event) {\n    pixelX = event.deltaX;\n  }\n\n  if ((pixelX || pixelY) && event.deltaMode) {\n    // delta in LINE units\n    if (event.deltaMode === 1) {\n      pixelX *= LINE_HEIGHT;\n      pixelY *= LINE_HEIGHT;\n    }\n    // delta in PAGE units\n    else {\n      pixelX *= PAGE_HEIGHT;\n      pixelY *= PAGE_HEIGHT;\n    }\n  }\n\n  // Fall-back if spin cannot be determined\n  if (pixelX && !spinX) {\n    spinX = (pixelX < 1) ? -1 : 1;\n  }\n  if (pixelY && !spinY) {\n    spinY = (pixelY < 1) ? -1 : 1;\n  }\n\n  return { spinX, spinY, pixelX, pixelY };\n}\n","/**\n * @summary Ensures that a number is in a given interval\n * @memberOf PSV.utils\n * @param {number} x\n * @param {number} min\n * @param {number} max\n * @returns {number}\n */\nexport function bound(x, min, max) {\n  return Math.max(min, Math.min(max, x));\n}\n\n/**\n * @summary Checks if a value is an integer\n * @memberOf PSV.utils\n * @param {*} value\n * @returns {boolean}\n */\nexport function isInteger(value) {\n  if (Number.isInteger) {\n    return Number.isInteger(value);\n  }\n  return typeof value === 'number' && Number.isFinite(value) && Math.floor(value) === value;\n}\n\n\n/**\n * @summary Computes the sum of an array\n * @memberOf PSV.utils\n * @param {number[]} array\n * @returns {number}\n */\nexport function sum(array) {\n  return array.reduce((a, b) => a + b, 0);\n}\n\n/**\n * @summary Computes the distance between two points\n * @memberOf PSV.utils\n * @param {PSV.Point} p1\n * @param {PSV.Point} p2\n * @returns {number}\n */\nexport function distance(p1, p2) {\n  return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));\n}\n\n/**\n * @summary Compute the shortest offset between two longitudes\n * @memberOf PSV.utils\n * @param {number} from\n * @param {number} to\n * @returns {number}\n */\nexport function getShortestArc(from, to) {\n  const tCandidates = [\n    0, // direct\n    Math.PI * 2, // clock-wise cross zero\n    -Math.PI * 2, // counter-clock-wise cross zero\n  ];\n\n  return tCandidates.reduce((value, candidate) => {\n    const newCandidate = to - from + candidate;\n    return Math.abs(newCandidate) < Math.abs(value) ? newCandidate : value;\n  }, Infinity);\n}\n\n/**\n * @summary Computes the angle between the current position and a target position\n * @memberOf PSV.utils\n * @param {PSV.Position} position1\n * @param {PSV.Position} position2\n * @returns {number}\n */\nexport function getAngle(position1, position2) {\n  return Math.acos(\n    Math.cos(position1.latitude)\n    * Math.cos(position2.latitude)\n    * Math.cos(position1.longitude - position2.longitude)\n    + Math.sin(position1.latitude)\n    * Math.sin(position2.latitude)\n  );\n}\n\n/**\n * Returns the distance between two points on a sphere of radius one\n * @memberOf PSV.utils\n * @param {number[]} p1\n * @param {number[]} p2\n * @returns {number}\n */\nexport function greatArcDistance(p1, p2) {\n  const [λ1, φ1] = p1;\n  const [λ2, φ2] = p2;\n\n  const x = (λ2 - λ1) * Math.cos((φ1 + φ2) / 2);\n  const y = (φ2 - φ1);\n  return Math.sqrt(x * x + y * y);\n}\n","/**\n * @summary Transforms a string to dash-case{@link https://github.com/shahata/dasherize}\n * @memberOf PSV.utils\n * @param {string} str\n * @returns {string}\n */\nexport function dasherize(str) {\n  return str.replace(/[A-Z](?:(?=[^A-Z])|[A-Z]*(?=[A-Z][^A-Z]|$))/g, (s, i) => {\n    return (i > 0 ? '-' : '') + s.toLowerCase();\n  });\n}\n\n/**\n * @summary Returns a function, that, when invoked, will only be triggered at most once during a given window of time.\n * @memberOf PSV.utils\n * @copyright underscore.js - modified by Clément Prévost {@link http://stackoverflow.com/a/27078401}\n * @param {Function} func\n * @param {number} wait\n * @returns {Function}\n */\nexport function throttle(func, wait) {\n  /* eslint-disable */\n  let self, args, result;\n  let timeout;\n  let previous = 0;\n  const later = function() {\n    previous = Date.now();\n    timeout = undefined;\n    result = func.apply(self, args);\n    if (!timeout) {\n      self = args = null;\n    }\n  };\n  return function() {\n    const now = Date.now();\n    if (!previous) {\n      previous = now;\n    }\n    const remaining = wait - (now - previous);\n    self = this;\n    args = arguments;\n    if (remaining <= 0 || remaining > wait) {\n      if (timeout) {\n        clearTimeout(timeout);\n        timeout = undefined;\n      }\n      previous = now;\n      result = func.apply(self, args);\n      if (!timeout) {\n        self = args = null;\n      }\n    }\n    else if (!timeout) {\n      timeout = setTimeout(later, remaining);\n    }\n    return result;\n  };\n  /* eslint-enable */\n}\n\n/**\n * @summary Test if an object is a plain object\n * @memberOf PSV.utils\n * @description Test if an object is a plain object, i.e. is constructed\n * by the built-in Object constructor and inherits directly from Object.prototype\n * or null. Some built-in objects pass the test, e.g. Math which is a plain object\n * and some host or exotic objects may pass also.\n * {@link http://stackoverflow.com/a/5878101/1207670}\n * @param {*} obj\n * @returns {boolean}\n */\nexport function isPlainObject(obj) {\n  // Basic check for Type object that's not null\n  if (typeof obj === 'object' && obj !== null) {\n    // If Object.getPrototypeOf supported, use it\n    if (typeof Object.getPrototypeOf === 'function') {\n      const proto = Object.getPrototypeOf(obj);\n      return proto === Object.prototype || proto === null;\n    }\n\n    // Otherwise, use internal class\n    // This should be reliable as if getPrototypeOf not supported, is pre-ES5\n    return Object.prototype.toString.call(obj) === '[object Object]';\n  }\n\n  // Not an object\n  return false;\n}\n\n/**\n * @summary Merges the enumerable attributes of two objects\n * @memberOf PSV.utils\n * @description Replaces arrays and alters the target object.\n * @copyright Nicholas Fisher <nfisher110@gmail.com>\n * @param {Object} target\n * @param {Object} src\n * @returns {Object} target\n */\nexport function deepmerge(target, src) {\n  /* eslint-disable */\n  let first = src;\n\n  return (function merge(target, src) {\n    if (Array.isArray(src)) {\n      if (!target || !Array.isArray(target)) {\n        target = [];\n      }\n      else {\n        target.length = 0;\n      }\n      src.forEach(function(e, i) {\n        target[i] = merge(null, e);\n      });\n    }\n    else if (typeof src === 'object') {\n      if (!target || Array.isArray(target)) {\n        target = {};\n      }\n      Object.keys(src).forEach(function(key) {\n        if (typeof src[key] !== 'object' || !src[key] || !isPlainObject(src[key])) {\n          target[key] = src[key];\n        }\n        else if (src[key] != first) {\n          if (!target[key]) {\n            target[key] = merge(null, src[key]);\n          }\n          else {\n            merge(target[key], src[key]);\n          }\n        }\n      });\n    }\n    else {\n      target = src;\n    }\n\n    return target;\n  }(target, src));\n  /* eslint-enable */\n}\n\n/**\n * @summary Deeply clones an object\n * @memberOf PSV.utils\n * @param {Object} src\n * @returns {Object}\n */\nexport function clone(src) {\n  return deepmerge(null, src);\n}\n\n/**\n * @summery Test of an object is empty\n * @memberOf PSV.utils\n * @param {object} obj\n * @returns {boolean}\n */\nexport function isEmpty(obj) {\n  return !obj || (Object.keys(obj).length === 0 && obj.constructor === Object);\n}\n\n/**\n * @summary Loops over enumerable properties of an object\n * @memberOf PSV.utils\n * @param {Object} object\n * @param {Function} callback\n */\nexport function each(object, callback) {\n  Object.keys(object).forEach((key) => {\n    callback(object[key], key);\n  });\n}\n\n/**\n * @summary Returns the intersection between two arrays\n * @memberOf PSV.utils\n * @template T\n * @param {T[]} array1\n * @param {T[]} array2\n * @returns {T[]}\n */\nexport function intersect(array1, array2) {\n  return array1.filter(value => array2.indexOf(value) !== -1);\n}\n","/**\n * @summary Custom error used in the lib\n * @param {string} message\n * @constructor\n * @memberOf PSV\n */\nfunction PSVError(message) {\n  this.message = message;\n\n  // Use V8's native method if available, otherwise fallback\n  if ('captureStackTrace' in Error) {\n    Error.captureStackTrace(this, PSVError);\n  }\n  else {\n    this.stack = (new Error()).stack;\n  }\n}\n\nPSVError.prototype = Object.create(Error.prototype);\nPSVError.prototype.name = 'PSVError';\nPSVError.prototype.constructor = PSVError;\n\nexport { PSVError };\n","import * as THREE from 'three';\nimport { PSVError } from '../PSVError';\nimport { bound } from './math';\n\n/**\n * @summary Displays a warning in the console\n * @memberOf PSV.utils\n * @param {string} message\n */\nexport function logWarn(message) {\n  console.warn(`PhotoSphereViewer: ${message}`);\n}\n\n/**\n * @summary Returns the value of a given attribute in the panorama metadata\n * @memberOf PSV.utils\n * @param {string} data\n * @param {string} attr\n * @returns (string)\n */\nexport function getXMPValue(data, attr) {\n  // XMP data are stored in children\n  let result = data.match('<GPano:' + attr + '>(.*)</GPano:' + attr + '>');\n  if (result !== null) {\n    return result[1];\n  }\n\n  // XMP data are stored in attributes\n  result = data.match('GPano:' + attr + '=\"(.*?)\"');\n  if (result !== null) {\n    return result[1];\n  }\n\n  return null;\n}\n\n/**\n * @readonly\n * @private\n * @type {{top: string, left: string, bottom: string, center: string, right: string}}\n */\nconst CSS_POSITIONS = {\n  top   : '0%',\n  bottom: '100%',\n  left  : '0%',\n  right : '100%',\n  center: '50%',\n};\n\n/**\n * @summary Translate CSS values like \"top center\" or \"10% 50%\" as top and left positions\n * @memberOf PSV.utils\n * @description The implementation is as close as possible to the \"background-position\" specification\n * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/background-position}\n * @param {string|object} value\n * @returns {PSV.Point}\n */\nexport function parsePosition(value) {\n  if (!value) {\n    return { x: 0.5, y: 0.5 };\n  }\n\n  if (typeof value === 'object') {\n    return value;\n  }\n\n  let tokens = value.toLocaleLowerCase().split(' ').slice(0, 2);\n\n  if (tokens.length === 1) {\n    if (CSS_POSITIONS[tokens[0]] !== undefined) {\n      tokens = [tokens[0], 'center'];\n    }\n    else {\n      tokens = [tokens[0], tokens[0]];\n    }\n  }\n\n  const xFirst = tokens[1] !== 'left' && tokens[1] !== 'right' && tokens[0] !== 'top' && tokens[0] !== 'bottom';\n\n  tokens = tokens.map(token => CSS_POSITIONS[token] || token);\n\n  if (!xFirst) {\n    tokens.reverse();\n  }\n\n  const parsed = tokens.join(' ').match(/^([0-9.]+)% ([0-9.]+)%$/);\n\n  if (parsed) {\n    return {\n      x: parseFloat(parsed[1]) / 100,\n      y: parseFloat(parsed[2]) / 100,\n    };\n  }\n  else {\n    return { x: 0.5, y: 0.5 };\n  }\n}\n\n/**\n * @summary Parses an speed\n * @memberOf PSV.utils\n * @param {string|number} speed - The speed, in radians/degrees/revolutions per second/minute\n * @returns {number} radians per second\n * @throws {PSV.PSVError} when the speed cannot be parsed\n */\nexport function parseSpeed(speed) {\n  let parsed;\n\n  if (typeof speed === 'string') {\n    const speedStr = speed.toString().trim();\n\n    // Speed extraction\n    let speedValue = parseFloat(speedStr.replace(/^(-?[0-9]+(?:\\.[0-9]*)?).*$/, '$1'));\n    const speedUnit = speedStr.replace(/^-?[0-9]+(?:\\.[0-9]*)?(.*)$/, '$1').trim();\n\n    // \"per minute\" -> \"per second\"\n    if (speedUnit.match(/(pm|per minute)$/)) {\n      speedValue /= 60;\n    }\n\n    // Which unit?\n    switch (speedUnit) {\n      // Degrees per minute / second\n      case 'dpm':\n      case 'degrees per minute':\n      case 'dps':\n      case 'degrees per second':\n        parsed = THREE.Math.degToRad(speedValue);\n        break;\n\n      // Radians per minute / second\n      case 'rdpm':\n      case 'radians per minute':\n      case 'rdps':\n      case 'radians per second':\n        parsed = speedValue;\n        break;\n\n      // Revolutions per minute / second\n      case 'rpm':\n      case 'revolutions per minute':\n      case 'rps':\n      case 'revolutions per second':\n        parsed = speedValue * Math.PI * 2;\n        break;\n\n      // Unknown unit\n      default:\n        throw new PSVError('Unknown speed unit \"' + speedUnit + '\"');\n    }\n  }\n  else {\n    parsed = speed;\n  }\n\n  return parsed;\n}\n\n/**\n * @summary Parses an angle value in radians or degrees and returns a normalized value in radians\n * @memberOf PSV.utils\n * @param {string|number} angle - eg: 3.14, 3.14rad, 180deg\n * @param {boolean} [zeroCenter=false] - normalize between -Pi - Pi instead of 0 - 2*Pi\n * @param {boolean} [halfCircle=zeroCenter] - normalize between -Pi/2 - Pi/2 instead of -Pi - Pi\n * @returns {number}\n * @throws {PSV.PSVError} when the angle cannot be parsed\n */\nexport function parseAngle(angle, zeroCenter = false, halfCircle = zeroCenter) {\n  let parsed;\n\n  if (typeof angle === 'string') {\n    const match = angle.toLowerCase().trim().match(/^(-?[0-9]+(?:\\.[0-9]*)?)(.*)$/);\n\n    if (!match) {\n      throw new PSVError('Unknown angle \"' + angle + '\"');\n    }\n\n    const value = parseFloat(match[1]);\n    const unit = match[2];\n\n    if (unit) {\n      switch (unit) {\n        case 'deg':\n        case 'degs':\n          parsed = THREE.Math.degToRad(value);\n          break;\n        case 'rad':\n        case 'rads':\n          parsed = value;\n          break;\n        default:\n          throw new PSVError('Unknown angle unit \"' + unit + '\"');\n      }\n    }\n    else {\n      parsed = value;\n    }\n  }\n  else if (typeof angle === 'number' && !isNaN(angle)) {\n    parsed = angle;\n  }\n  else {\n    throw new PSVError('Unknown angle \"' + angle + '\"');\n  }\n\n  parsed = (zeroCenter ? parsed + Math.PI : parsed) % (Math.PI * 2);\n\n  if (parsed < 0) {\n    parsed += Math.PI * 2;\n  }\n\n  return zeroCenter ? bound(parsed - Math.PI, -Math.PI / (halfCircle ? 2 : 1), Math.PI / (halfCircle ? 2 : 1)) : parsed;\n}\n","import { EASINGS } from './data/constants';\nimport { each } from './utils';\n\n/**\n * @callback OnTick\n * @summary Function called for each animation frame with computed properties\n * @memberOf PSV.Animation\n * @param {Object.<string, number>} properties - current values\n * @param {float} progress - 0 to 1\n */\n\n/**\n * @summary Interpolation helper for animations\n * @memberOf PSV\n * @description\n * Implements the Promise API with an additional \"cancel\" and \"finally\" methods.\n * The promise is resolved when the animation is complete and rejected if the animation is cancelled.\n * @example\n * new Animation({\n *     properties: {\n *         width: {start: 100, end: 200}\n *     },\n *     duration: 5000,\n *     onTick: (properties) => element.style.width = `${properties.width}px`;\n * })\n */\nexport class Animation {\n\n  /**\n   * @param {Object} options\n   * @param {Object.<string, Object>} options.properties\n   * @param {number} options.properties[].start\n   * @param {number} options.properties[].end\n   * @param {number} options.duration\n   * @param {number} [options.delay=0]\n   * @param {string} [options.easing='linear']\n   * @param {PSV.Animation.OnTick} options.onTick - called on each frame\n   */\n  constructor(options) {\n    this.__cancelled = false;\n    this.__resolved = false;\n\n    this.__promise = new Promise((resolve, reject) => {\n      this.__resolve = resolve;\n      this.__reject = reject;\n    });\n\n    if (options) {\n      if (!options.easing || typeof options.easing === 'string') {\n        options.easing = EASINGS[options.easing || 'linear'];\n      }\n      this.__start = null;\n      this.options = options;\n\n      if (options.delay) {\n        this.__delayTimeout = setTimeout(() => {\n          this.__delayTimeout = null;\n          window.requestAnimationFrame(t => this.__run(t));\n        }, options.delay);\n      }\n      else {\n        window.requestAnimationFrame(t => this.__run(t));\n      }\n    }\n  }\n\n  /**\n   * @summary Main loop for the animation\n   * @param {number} timestamp\n   * @private\n   */\n  __run(timestamp) {\n    // the animation has been cancelled\n    if (this.__cancelled) {\n      return;\n    }\n\n    // first iteration\n    if (this.__start === null) {\n      this.__start = timestamp;\n    }\n\n    // compute progress\n    const progress = (timestamp - this.__start) / this.options.duration;\n    const current = {};\n\n    if (progress < 1.0) {\n      // interpolate properties\n      each(this.options.properties, (prop, name) => {\n        if (prop) {\n          current[name] = prop.start + (prop.end - prop.start) * this.options.easing(progress);\n        }\n      });\n\n      this.options.onTick(current, progress);\n\n      window.requestAnimationFrame(t => this.__run(t));\n    }\n    else {\n      // call onTick one last time with final values\n      each(this.options.properties, (prop, name) => {\n        if (prop) {\n          current[name] = prop.end;\n        }\n      });\n\n      this.options.onTick(current, 1.0);\n\n      window.requestAnimationFrame(() => {\n        this.__resolved = true;\n        this.__resolve();\n      });\n    }\n  }\n\n  /**\n   * @summary Animation chaining\n   * @param {Function} [onFulfilled] - Called when the animation is complete, can return a new animation\n   * @param {Function} [onRejected] - Called when the animation is cancelled\n   * @returns {PSV.Animation}\n   */\n  then(onFulfilled = null, onRejected = null) {\n    const p = new Animation();\n\n    // Allow cancellation to climb up the promise chain\n    p.__promise.then(null, () => this.cancel());\n\n    this.__promise.then(\n      () => p.__resolve(onFulfilled ? onFulfilled() : undefined),\n      () => p.__reject(onRejected ? onRejected() : undefined)\n    );\n\n    return p;\n  }\n\n  /**\n   * @summary Alias to `.then(null, onRejected)`\n   * @param {Function} onRejected - Called when the animation has been cancelled\n   * @returns {PSV.Animation}\n   */\n  catch(onRejected) {\n    return this.then(undefined, onRejected);\n  }\n\n  /**\n   * @summary Alias to `.then(onFinally, onFinally)`\n   * @param {Function} onFinally - Called when the animation is either complete or cancelled\n   * @returns {PSV.Animation}\n   */\n  finally(onFinally) {\n    return this.then(onFinally, onFinally);\n  }\n\n  /**\n   * @summary Cancels the animation\n   */\n  cancel() {\n    if (!this.__cancelled && !this.__resolved) {\n      this.__cancelled = true;\n      this.__reject();\n\n      if (this.__delayTimeout) {\n        window.cancelAnimationFrame(this.__delayTimeout);\n        this.__delayTimeout = null;\n      }\n    }\n  }\n\n  /**\n   * @summary Returns a resolved animation promise\n   * @returns {PSV.Animation}\n   */\n  static resolve() {\n    const p = Promise.resolve();\n    p.cancel = () => {\n    };\n    p.finally = (onFinally) => {\n      return p.then(onFinally, onFinally);\n    };\n    return p;\n  }\n\n}\n","/**\n * @namespace PSV.components\n */\n\n/**\n * @summary Base component class\n * @memberof PSV.components\n * @abstract\n */\nexport class AbstractComponent {\n\n  /**\n   * @param {PSV.Viewer | PSV.components.AbstractComponent} parent\n   * @param {string} className - CSS class added to the component's container\n   */\n  constructor(parent, className) {\n    /**\n     * @summary Reference to main controller\n     * @type {PSV.Viewer}\n     * @readonly\n     */\n    this.psv = parent.psv || parent;\n\n    /**\n     * @member {PSV.Viewer|PSV.components.AbstractComponent}\n     * @readonly\n     */\n    this.parent = parent;\n    this.parent.children.push(this);\n\n    /**\n     * @summary All child components\n     * @type {PSV.components.AbstractComponent[]}\n     * @readonly\n     * @package\n     */\n    this.children = [];\n\n    /**\n     * @summary Internal properties\n     * @member {Object}\n     * @protected\n     * @property {boolean} visible - Visibility of the component\n     */\n    this.prop = {\n      visible: true,\n    };\n\n    /**\n     * @member {HTMLElement}\n     * @readonly\n     */\n    this.container = document.createElement('div');\n    this.container.className = className;\n    this.parent.container.appendChild(this.container);\n  }\n\n  /**\n   * @summary Destroys the component\n   * @protected\n   */\n  destroy() {\n    this.parent.container.removeChild(this.container);\n\n    const childIdx = this.parent.children.indexOf(this);\n    if (childIdx !== -1) {\n      this.parent.children.splice(childIdx, 1);\n    }\n\n    this.children.slice().forEach(child => child.destroy());\n    this.children.length = 0;\n\n    delete this.container;\n    delete this.parent;\n    delete this.psv;\n    delete this.prop;\n  }\n\n  /**\n   * @summary Refresh UI\n   * @description Must be be a very lightweight operation\n   * @package\n   */\n  refreshUi() {\n    this.children.every((child) => {\n      child.refreshUi();\n      return this.psv.prop.uiRefresh === true;\n    });\n  }\n\n  /**\n   * @summary Displays or hides the component\n   */\n  toggle() {\n    if (this.isVisible()) {\n      this.hide();\n    }\n    else {\n      this.show();\n    }\n  }\n\n  /**\n   * @summary Hides the component\n   */\n  hide() {\n    this.container.style.display = 'none';\n    this.prop.visible = false;\n  }\n\n  /**\n   * @summary Displays the component\n   */\n  show() {\n    this.container.style.display = '';\n    this.prop.visible = true;\n  }\n\n  /**\n   * @summary Check if the component is visible\n   * @returns {boolean}\n   */\n  isVisible() {\n    return this.prop.visible;\n  }\n\n}\n","import { AbstractComponent } from '../components/AbstractComponent';\nimport { PSVError } from '../PSVError';\nimport { isPlainObject, toggleClass } from '../utils';\n\n/**\n * @namespace PSV.buttons\n */\n\n/**\n * @summary Base navbar button class\n * @extends PSV.components.AbstractComponent\n * @memberof PSV.buttons\n * @abstract\n */\nexport class AbstractButton extends AbstractComponent {\n\n  /**\n   * @summary Unique identifier of the button\n   * @member {string}\n   * @readonly\n   * @static\n   */\n  static id = null;\n\n  /**\n   * @summary SVG icon name injected in the button\n   * @member {string}\n   * @readonly\n   * @static\n   */\n  static icon = null;\n\n  /**\n   * @summary SVG icon name injected in the button when it is active\n   * @member {string}\n   * @readonly\n   * @static\n   */\n  static iconActive = null;\n\n  /**\n   * @param {PSV.components.Navbar} navbar\n   * @param {string} [className] - Additional CSS classes\n   * @param {boolean} [collapsable=false] - `true` if the button can be moved to menu when the navbar is too small\n   */\n  constructor(navbar, className = '', collapsable = false) {\n    super(navbar, 'psv-button ' + className);\n\n    /**\n     * @override\n     * @property {string} id - Unique identifier of the button\n     * @property {boolean} enabled\n     * @property {boolean} supported\n     * @property {boolean} collapsed\n     * @property {boolean} active\n     * @property {number} width\n     */\n    this.prop = {\n      ...this.prop,\n      id         : this.constructor.id,\n      collapsable: collapsable,\n      enabled    : true,\n      supported  : true,\n      collapsed  : false,\n      active     : false,\n      width      : this.container.offsetWidth,\n    };\n\n    if (this.constructor.icon) {\n      this.__setIcon(this.constructor.icon);\n    }\n\n    if (this.prop.id && this.psv.config.lang[this.prop.id]) {\n      this.container.title = this.psv.config.lang[this.prop.id];\n    }\n\n    this.container.addEventListener('click', (e) => {\n      if (this.prop.enabled) {\n        this.onClick();\n      }\n      e.stopPropagation();\n    });\n  }\n\n  /**\n   * @package\n   */\n  checkSupported() {\n    const supportedOrObject = this.isSupported();\n    if (isPlainObject(supportedOrObject)) {\n      if (supportedOrObject.initial === false) {\n        this.hide();\n        this.prop.supported = false;\n      }\n\n      supportedOrObject.promise.then((supported) => {\n        if (!this.prop) {\n          return; // the component has been destroyed\n        }\n        this.prop.supported = supported;\n        if (!supported && this.prop.visible) {\n          this.hide();\n        }\n        else if (supported && !this.prop.visible) {\n          this.show();\n        }\n      });\n    }\n    else if (!supportedOrObject) {\n      this.hide();\n      this.prop.supported = false;\n    }\n  }\n\n  /**\n   * @summary Checks if the button can be displayed\n   * @returns {boolean|{initial: boolean, promise: Promise<boolean>}}\n   */\n  isSupported() {\n    return true;\n  }\n\n  /**\n   * @summary Changes the active state of the button\n   * @param {boolean} [active] - forced state\n   */\n  toggleActive(active) {\n    this.prop.active = active !== undefined ? active : !this.prop.active;\n    toggleClass(this.container, 'psv-button--active', this.prop.active);\n\n    if (this.constructor.iconActive) {\n      this.__setIcon(this.prop.active ? this.constructor.iconActive : this.constructor.icon);\n    }\n  }\n\n  /**\n   * @override\n   */\n  show(refresh = true) {\n    if (!this.isVisible()) {\n      this.prop.visible = true;\n      if (!this.prop.collapsed) {\n        this.container.style.display = '';\n      }\n      if (refresh) {\n        this.psv.refreshUi(`show button ${this.prop.id}`);\n      }\n    }\n  }\n\n  /**\n   * @override\n   */\n  hide(refresh = true) {\n    if (this.isVisible()) {\n      this.prop.visible = false;\n      this.container.style.display = 'none';\n      if (refresh) {\n        this.psv.refreshUi(`hide button ${this.prop.id}`);\n      }\n    }\n  }\n\n  /**\n   * @summary Disables the button\n   */\n  disable() {\n    this.container.classList.add('psv-button--disabled');\n    this.prop.enabled = false;\n  }\n\n  /**\n   * @summary Enables the button\n   */\n  enable() {\n    this.container.classList.remove('psv-button--disabled');\n    this.prop.enabled = true;\n  }\n\n  /**\n   * @summary Collapses the button in the navbar menu\n   */\n  collapse() {\n    this.prop.collapsed = true;\n    this.container.style.display = 'none';\n  }\n\n  /**\n   * @summary Uncollapses the button from the navbar menu\n   */\n  uncollapse() {\n    this.prop.collapsed = false;\n    if (this.prop.visible) {\n      this.container.style.display = '';\n    }\n  }\n\n  /**\n   * @summary Set the button icon\n   * @param {string} icon SVG\n   * @param {HTMLElement} [container] - default is the main button container\n   * @private\n   */\n  __setIcon(icon, container = this.container) {\n    if (icon) {\n      container.innerHTML = icon;\n      // classList not supported on IE11, className is read-only !!!!\n      container.querySelector('svg').setAttribute('class', 'psv-button-svg');\n    }\n    else {\n      container.innerHTML = '';\n    }\n  }\n\n  /**\n   * @summary Action when the button is clicked\n   * @private\n   * @abstract\n   */\n  onClick() {\n    throw new PSVError(`onClick not implemented for button \"${this.prop.id}\".`);\n  }\n\n}\n","import { EVENTS } from '../data/constants';\nimport playActive from '../icons/play-active.svg';\nimport play from '../icons/play.svg';\nimport { AbstractButton } from './AbstractButton';\n\n/**\n * @summary Navigation bar autorotate button class\n * @extends PSV.buttons.AbstractButton\n * @memberof PSV.buttons\n */\nexport class AutorotateButton extends AbstractButton {\n\n  static id = 'autorotate';\n  static icon = play;\n  static iconActive = playActive;\n\n  /**\n   * @param {PSV.components.Navbar} navbar\n   */\n  constructor(navbar) {\n    super(navbar, 'psv-button--hover-scale psv-autorotate-button', true);\n\n    this.psv.on(EVENTS.AUTOROTATE, this);\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    this.psv.off(EVENTS.AUTOROTATE, this);\n\n    super.destroy();\n  }\n\n  /**\n   * @summary Handles events\n   * @param {Event} e\n   * @private\n   */\n  handleEvent(e) {\n    /* eslint-disable */\n    switch (e.type) {\n      // @formatter:off\n      case EVENTS.AUTOROTATE: this.toggleActive(e.args[0]); break;\n      // @formatter:on\n    }\n    /* eslint-enable */\n  }\n\n  /**\n   * @override\n   * @description Toggles autorotate\n   */\n  onClick() {\n    this.psv.toggleAutorotate();\n  }\n\n}\n","import { addClasses } from '../utils';\nimport { AbstractButton } from './AbstractButton';\n\n/**\n * @summary Navigation bar custom button class\n * @extends PSV.buttons.AbstractButton\n * @memberof PSV.buttons\n */\nexport class CustomButton extends AbstractButton {\n\n  /**\n   * @param {PSV.components.Navbar} navbar\n   * @param {PSV.NavbarCustomButton} config\n   */\n  constructor(navbar, config) {\n    super(navbar, 'psv-custom-button', config.collapsable !== false);\n\n    /**\n     * @member {Object}\n     * @readonly\n     * @private\n     */\n    this.config = config;\n\n    if (this.config.id) {\n      this.prop.id = this.config.id;\n    }\n    else {\n      this.prop.id = 'psvButton-' + Math.random().toString(36).substr(2, 9);\n    }\n\n    if (this.config.className) {\n      addClasses(this.container, this.config.className);\n    }\n\n    if (this.config.title) {\n      this.container.title = this.config.title;\n    }\n\n    if (this.config.content) {\n      this.container.innerHTML = this.config.content;\n    }\n\n    this.width = this.container.offsetWidth;\n\n    if (this.config.enabled === false) {\n      this.disable();\n    }\n\n    if (this.config.visible === false) {\n      this.hide();\n    }\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    delete this.config;\n\n    super.destroy();\n  }\n\n  /**\n   * @override\n   * @description Calls user method\n   */\n  onClick() {\n    if (this.config.onClick) {\n      this.config.onClick.apply(this.psv);\n    }\n  }\n\n}\n","import { AbstractButton } from './AbstractButton';\nimport download from '../icons/download.svg';\n\n/**\n * @summary Navigation bar download button class\n * @extends PSV.buttons.AbstractButton\n * @memberof PSV.buttons\n */\nexport class DownloadButton extends AbstractButton {\n\n  static id = 'download';\n  static icon = download;\n\n  /**\n   * @param {PSV.components.Navbar} navbar\n   */\n  constructor(navbar) {\n    super(navbar, 'psv-button--hover-scale psv-download-button', true);\n  }\n\n  /**\n   * @override\n   * @description Asks the browser to download the panorama source file\n   */\n  onClick() {\n    const link = document.createElement('a');\n    link.href = this.psv.config.panorama;\n    link.download = this.psv.config.panorama;\n    this.psv.container.appendChild(link);\n    link.click();\n\n    setTimeout(() => {\n      this.psv.container.removeChild(link);\n    }, 100);\n  }\n\n}\n","import { EVENTS } from '../data/constants';\nimport fullscreenIn from '../icons/fullscreen-in.svg';\nimport fullscreenOut from '../icons/fullscreen-out.svg';\nimport { AbstractButton } from './AbstractButton';\n\n/**\n * @summary Navigation bar fullscreen button class\n * @extends PSV.buttons.AbstractButton\n * @memberof PSV.buttons\n */\nexport class FullscreenButton extends AbstractButton {\n\n  static id = 'fullscreen';\n  static icon = fullscreenIn;\n  static iconActive = fullscreenOut;\n\n  /**\n   * @param {PSV.components.Navbar} navbar\n   */\n  constructor(navbar) {\n    super(navbar, 'psv-button--hover-scale psv-fullscreen-button');\n\n    this.psv.on(EVENTS.FULLSCREEN_UPDATED, this);\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    this.psv.off(EVENTS.FULLSCREEN_UPDATED, this);\n\n    super.destroy();\n  }\n\n  /**\n   * Handle events\n   * @param {Event} e\n   * @private\n   */\n  handleEvent(e) {\n    /* eslint-disable */\n    switch (e.type) {\n      // @formatter:off\n      case EVENTS.FULLSCREEN_UPDATED: this.toggleActive(e.args[0]); break;\n      // @formatter:on\n    }\n    /* eslint-enable */\n  }\n\n  /**\n   * @override\n   * @description Toggles fullscreen\n   */\n  onClick() {\n    this.psv.toggleFullscreen();\n  }\n\n}\n","import { EVENTS, IDS } from '../data/constants';\nimport menuIcon from '../icons/menu.svg';\nimport { dasherize, getClosest } from '../utils';\nimport { AbstractButton } from './AbstractButton';\n\n/**\n * @summary Navigation bar menu button class\n * @extends PSV.buttons.AbstractButton\n * @memberof PSV.buttons\n */\nexport class MenuButton extends AbstractButton {\n\n  static id = 'menu';\n  static icon = menuIcon;\n\n  /**\n   * @summary Property name added to buttons list\n   * @type {string}\n   * @constant\n   */\n  static BUTTON_DATA = 'psvButton';\n\n  /**\n   * @summary Menu template\n   * @param {AbstractButton[]} buttons\n   * @param {PSV.Viewer} psv\n   * @param {string} dataKey\n   * @returns {string}\n   */\n  static MENU_TEMPLATE = (buttons, psv, dataKey) => `\n<div class=\"psv-panel-menu psv-panel-menu--stripped\">\n  <h1 class=\"psv-panel-menu-title\">${menuIcon} ${psv.config.lang.menu}</h1>\n  <ul class=\"psv-panel-menu-list\">\n    ${buttons.map(button => `\n    <li data-${dataKey}=\"${button.prop.id}\" class=\"psv-panel-menu-item\">\n      <span class=\"psv-panel-menu-item-icon\">${button.container.innerHTML}</span>\n      <span class=\"psv-panel-menu-item-label\">${button.container.title}</span>\n    </li>\n    `).join('')}\n  </ul>\n</div>\n`;\n\n  /**\n   * @param {PSV.components.Navbar} navbar\n   */\n  constructor(navbar) {\n    super(navbar, 'psv-button--hover-scale psv-menu-button');\n\n    this.psv.on(EVENTS.OPEN_PANEL, this);\n    this.psv.on(EVENTS.CLOSE_PANEL, this);\n\n    this.hide();\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    this.psv.off(EVENTS.OPEN_PANEL, this);\n    this.psv.off(EVENTS.CLOSE_PANEL, this);\n\n    super.destroy();\n  }\n\n  /**\n   * @summary Handles events\n   * @param {Event} e\n   * @private\n   */\n  handleEvent(e) {\n    /* eslint-disable */\n    switch (e.type) {\n      // @formatter:off\n      case EVENTS.OPEN_PANEL:  this.toggleActive(e.args[0] === IDS.MENU); break;\n      case EVENTS.CLOSE_PANEL: this.toggleActive(false); break;\n      // @formatter:on\n    }\n    /* eslint-enable */\n  }\n\n  /**\n   * @override\n   */\n  hide(refresh) {\n    super.hide(refresh);\n    this.__hideMenu();\n  }\n\n  /**\n   * @override\n   */\n  show(refresh) {\n    super.show(refresh);\n\n    if (this.prop.active) {\n      this.__showMenu();\n    }\n  }\n\n  /**\n   * @override\n   * @description Toggles menu\n   */\n  onClick() {\n    if (this.prop.active) {\n      this.__hideMenu();\n    }\n    else {\n      this.__showMenu();\n    }\n  }\n\n  __showMenu() {\n    this.psv.panel.show({\n      id          : IDS.MENU,\n      content     : MenuButton.MENU_TEMPLATE(this.parent.collapsed, this.psv, dasherize(MenuButton.BUTTON_DATA)),\n      noMargin    : true,\n      clickHandler: (e) => {\n        const li = e.target ? getClosest(e.target, 'li') : undefined;\n        const buttonId = li ? li.dataset[MenuButton.BUTTON_DATA] : undefined;\n\n        if (buttonId) {\n          this.parent.getButton(buttonId).onClick();\n          this.__hideMenu();\n        }\n      },\n    });\n  }\n\n  __hideMenu() {\n    if (this.psv.panel) {\n      this.psv.panel.hide(IDS.MENU);\n    }\n  }\n\n}\n","/**\n * @summary General information about the system\n * @constant\n * @memberOf PSV\n * @property {boolean} loaded - Indicates if the system has been loaded yet\n * @property {Function} load - Loads the system if not already loaded\n * @property {number} pixelRatio\n * @property {boolean} isWebGLSupported\n * @property {number} maxTextureWidth\n * @property {number} maxCanvasWidth\n * @property {string} mouseWheelEvent\n * @property {string} fullscreenEvent\n * @property {Promise<boolean>} isTouchEnabled\n */\nexport const SYSTEM = {\n  loaded          : false,\n  pixelRatio      : 1,\n  isWebGLSupported: false,\n  isTouchEnabled  : null,\n  maxTextureWidth : 0,\n  maxCanvasWidth  : 0,\n  mouseWheelEvent : null,\n  fullscreenEvent : null,\n};\n\n/**\n * @summary Loads the system if not already loaded\n */\nSYSTEM.load = () => {\n  if (!SYSTEM.loaded) {\n    const ctx = getWebGLCtx();\n\n    SYSTEM.loaded = true;\n    SYSTEM.pixelRatio = window.devicePixelRatio || 1;\n    SYSTEM.isWebGLSupported = ctx != null;\n    SYSTEM.isTouchEnabled = isTouchEnabled();\n    SYSTEM.maxTextureWidth = getMaxTextureWidth(ctx);\n    SYSTEM.maxCanvasWidth = getMaxCanvasWidth(SYSTEM.maxTextureWidth);\n    SYSTEM.mouseWheelEvent = getMouseWheelEvent();\n    SYSTEM.fullscreenEvent = getFullscreenEvent();\n  }\n};\n\n/**\n * @summary Tries to return a canvas webgl context\n * @returns {WebGLRenderingContext}\n * @private\n */\nfunction getWebGLCtx() {\n  const canvas = document.createElement('canvas');\n  const names = ['webgl', 'experimental-webgl', 'moz-webgl', 'webkit-3d'];\n  let context = null;\n\n  if (!canvas.getContext) {\n    return null;\n  }\n\n  if (names.some((name) => {\n    try {\n      context = canvas.getContext(name);\n      return context !== null;\n    }\n    catch (e) {\n      return false;\n    }\n  })) {\n    return context;\n  }\n  else {\n    return null;\n  }\n}\n\n/**\n * @summary Detects if the user is using a touch screen\n * @returns {Promise<boolean>}\n * @private\n */\nfunction isTouchEnabled() {\n  return new Promise((resolve) => {\n    const listener = (e) => {\n      if (e) {\n        resolve(true);\n      }\n      else {\n        resolve(false);\n      }\n\n      window.removeEventListener('touchstart', listener);\n    };\n\n    window.addEventListener('touchstart', listener, false);\n\n    // after 10 secs auto-reject the promise\n    setTimeout(listener, 10000);\n  });\n}\n\n/**\n * @summary Gets max texture width in WebGL context\n * @returns {number}\n * @private\n */\nfunction getMaxTextureWidth(ctx) {\n  if (ctx !== null) {\n    return ctx.getParameter(ctx.MAX_TEXTURE_SIZE);\n  }\n  else {\n    return 0;\n  }\n}\n\n/**\n * @summary Gets max canvas width supported by the browser.\n * We only test powers of 2 and height = width / 2 because that's what we need to generate WebGL textures\n * @param maxWidth\n * @return {number}\n * @private\n */\nfunction getMaxCanvasWidth(maxWidth) {\n  const canvas = document.createElement('canvas');\n  const ctx = canvas.getContext('2d');\n  canvas.width = maxWidth;\n  canvas.height = maxWidth / 2;\n\n  while (canvas.width > 1024) {\n    ctx.fillStyle = 'white';\n    ctx.fillRect(0, 0, 1, 1);\n\n    try {\n      if (ctx.getImageData(0, 0, 1, 1).data[0] === 255) {\n        return canvas.width;\n      }\n    }\n    catch (e) {\n      // continue\n    }\n\n    canvas.width /= 2;\n    canvas.height /= 2;\n  }\n\n  return 0;\n}\n\n/**\n * @summary Gets the event name for mouse wheel\n * @returns {string}\n * @private\n */\nfunction getMouseWheelEvent() {\n  if ('onwheel' in document.createElement('div')) { // Modern browsers support \"wheel\"\n    return 'wheel';\n  }\n  else if (document.onmousewheel !== undefined) { // Webkit and IE support at least \"mousewheel\"\n    return 'mousewheel';\n  }\n  else { // let's assume that remaining browsers are older Firefox\n    return 'DOMMouseScroll';\n  }\n}\n\n/**\n * @summary Map between fullsceen method and fullscreen event name\n * @type {Object<string, string>}\n * @readonly\n * @private\n */\nconst FULLSCREEN_EVT_MAP = {\n  exitFullscreen      : 'fullscreenchange',\n  webkitExitFullscreen: 'webkitfullscreenchange',\n  mozCancelFullScreen : 'mozfullscreenchange',\n  msExitFullscreen    : 'MSFullscreenChange',\n};\n\n\n/**\n * @summary  Gets the event name for fullscreen\n * @returns {string}\n * @private\n */\nfunction getFullscreenEvent() {\n  const validExits = Object.keys(FULLSCREEN_EVT_MAP).filter(exit => exit in document);\n\n  if (validExits.length) {\n    return FULLSCREEN_EVT_MAP[validExits[0]];\n  }\n  else {\n    return null;\n  }\n}\n","import { Animation } from '../Animation';\nimport { SYSTEM } from '../data/system';\nimport { AbstractButton } from './AbstractButton';\n\n/**\n * @summary Navigation bar zoom button class\n * @extends PSV.buttons.AbstractButton\n * @memberof PSV.buttons\n */\nexport class AbstractZoomButton extends AbstractButton {\n\n  /**\n   * @param {PSV.components.Navbar} navbar\n   * @param {number} value\n   */\n  constructor(navbar, value) {\n    super(navbar, 'psv-button--hover-scale psv-zoom-button');\n\n    /**\n     * @override\n     * @property {number} value\n     * @property {boolean} buttondown\n     * @property {*} longPressTimeout\n     * @property {PSV.Animation} longPressAnimation\n     */\n    this.prop = {\n      ...this.prop,\n      value             : value,\n      buttondown        : false,\n      longPressTimeout  : null,\n      longPressAnimation: null,\n    };\n\n    this.container.addEventListener('mousedown', this);\n    this.psv.container.addEventListener('mouseup', this);\n    this.psv.container.addEventListener('touchend', this);\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    this.__onMouseUp();\n\n    this.psv.container.removeEventListener('mouseup', this);\n    this.psv.container.removeEventListener('touchend', this);\n\n    super.destroy();\n  }\n\n  /**\n   * @summary Handles events\n   * @param {Event} e\n   * @private\n   */\n  handleEvent(e) {\n    /* eslint-disable */\n    switch (e.type) {\n      // @formatter:off\n      case 'mousedown': this.__onMouseDown(); break;\n      case 'mouseup':   this.__onMouseUp(); break;\n      case 'touchend':  this.__onMouseUp(); break;\n      // @formatter:on\n    }\n    /* eslint-enable */\n  }\n\n  /**\n   * @override\n   */\n  isSupported() {\n    return { initial: true, promise: SYSTEM.isTouchEnabled.then(enabled => !enabled) };\n  }\n\n  /**\n   * @override\n   */\n  onClick() {\n    // nothing\n  }\n\n  /**\n   * @summary Handles click events\n   * @description Zooms in and register long press timer\n   * @private\n   */\n  __onMouseDown() {\n    if (!this.prop.enabled) {\n      return;\n    }\n\n    this.prop.buttondown = true;\n    this.prop.longPressTimeout = setTimeout(() => this.__startLongPressInterval(), 100);\n  }\n\n  /**\n   * @summary Continues zooming as long as the user presses the button\n   * @private\n   */\n  __startLongPressInterval() {\n    if (!this.prop.buttondown) {\n      return;\n    }\n\n    const end = this.prop.value < 0 ? 0 : 100;\n\n    this.prop.longPressAnimation = new Animation({\n      properties: {\n        zoom: { start: this.psv.prop.zoomLvl, end: end },\n      },\n      duration  : 1500 * Math.abs(this.psv.prop.zoomLvl - end) / 100,\n      easing    : 'linear',\n      onTick    : (properties) => {\n        this.psv.zoom(properties.zoom);\n      },\n    })\n      .catch(() => {}); // ignore cancellation\n  }\n\n  /**\n   * @summary Handles mouse up events\n   * @private\n   */\n  __onMouseUp() {\n    if (!this.prop.enabled || !this.prop.buttondown) {\n      return;\n    }\n\n    if (this.prop.longPressAnimation) {\n      this.prop.longPressAnimation.cancel();\n      this.prop.longPressAnimation = null;\n    }\n    else {\n      this.psv.zoom(this.psv.prop.zoomLvl + this.prop.value * this.psv.config.zoomButtonIncrement);\n    }\n\n    if (this.prop.longPressTimeout) {\n      clearTimeout(this.prop.longPressTimeout);\n    }\n\n    this.prop.buttondown = false;\n  }\n\n}\n","import { AbstractZoomButton } from './AbstractZoomButton';\nimport zoomIn from '../icons/zoom-in.svg';\n\n/**\n * @summary Navigation bar zoom-in button class\n * @extends PSV.buttons.AbstractZoomButton\n * @memberof PSV.buttons\n */\nexport class ZoomInButton extends AbstractZoomButton {\n\n  static id = 'zoomIn';\n  static icon = zoomIn;\n\n  /**\n   * @param {PSV.components.Navbar} navbar\n   */\n  constructor(navbar) {\n    super(navbar, 1);\n  }\n\n}\n","import { AbstractZoomButton } from './AbstractZoomButton';\nimport zoomOut from '../icons/zoom-out.svg';\n\n/**\n * @summary Navigation bar zoom-out button class\n * @extends PSV.buttons.AbstractZoomButton\n * @memberof PSV.buttons\n */\nexport class ZoomOutButton extends AbstractZoomButton {\n\n  static id = 'zoomOut';\n  static icon = zoomOut;\n\n  /**\n   * @param {PSV.components.Navbar} navbar\n   */\n  constructor(navbar) {\n    super(navbar, -1);\n  }\n\n}\n","import { EVENTS } from '../data/constants';\nimport { SYSTEM } from '../data/system';\nimport { getStyle } from '../utils';\nimport { AbstractButton } from './AbstractButton';\n\n/**\n * @summary Navigation bar zoom button class\n * @extends PSV.buttons.AbstractButton\n * @memberof PSV.buttons\n */\nexport class ZoomRangeButton extends AbstractButton {\n\n  static id = 'zoomRange';\n\n  /**\n   * @param {PSV.components.Navbar} navbar\n   */\n  constructor(navbar) {\n    super(navbar, 'psv-zoom-range');\n\n    /**\n     * @override\n     * @property {boolean} mousedown\n     * @property {number} mediaMinWidth\n     */\n    this.prop = {\n      ...this.prop,\n      mousedown    : false,\n      mediaMinWidth: 0,\n    };\n\n    /**\n     * @member {HTMLElement}\n     * @readonly\n     * @private\n     */\n    this.zoomRange = document.createElement('div');\n    this.zoomRange.className = 'psv-zoom-range-line';\n    this.container.appendChild(this.zoomRange);\n\n    /**\n     * @member {HTMLElement}\n     * @readonly\n     * @private\n     */\n    this.zoomValue = document.createElement('div');\n    this.zoomValue.className = 'psv-zoom-range-handle';\n    this.zoomRange.appendChild(this.zoomValue);\n\n    this.prop.mediaMinWidth = parseInt(getStyle(this.container, 'maxWidth'), 10);\n\n    this.container.addEventListener('mousedown', this);\n    this.container.addEventListener('touchstart', this);\n    this.psv.container.addEventListener('mousemove', this);\n    this.psv.container.addEventListener('touchmove', this);\n    this.psv.container.addEventListener('mouseup', this);\n    this.psv.container.addEventListener('touchend', this);\n\n    this.psv.on(EVENTS.ZOOM_UPDATED, this);\n\n    if (this.psv.prop.ready) {\n      this.__moveZoomValue(this.psv.prop.zoomLvl);\n    }\n    else {\n      this.psv.once(EVENTS.READY, this);\n    }\n\n    this.refreshUi();\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    this.__stopZoomChange();\n\n    this.psv.container.removeEventListener('mousemove', this);\n    this.psv.container.removeEventListener('touchmove', this);\n    this.psv.container.removeEventListener('mouseup', this);\n    this.psv.container.removeEventListener('touchend', this);\n\n    delete this.zoomRange;\n    delete this.zoomValue;\n\n    this.psv.off(EVENTS.ZOOM_UPDATED, this);\n\n    super.destroy();\n  }\n\n  /**\n   * @summary Handles events\n   * @param {Event} e\n   * @private\n   */\n  handleEvent(e) {\n    /* eslint-disable */\n    switch (e.type) {\n      // @formatter:off\n      case 'mousedown':    this.__initZoomChangeWithMouse(e); break;\n      case 'touchstart':   this.__initZoomChangeByTouch(e);   break;\n      case 'mousemove':    this.__changeZoomWithMouse(e);     break;\n      case 'touchmove':    this.__changeZoomByTouch(e);       break;\n      case 'mouseup':      this.__stopZoomChange(e);          break;\n      case 'touchend':     this.__stopZoomChange(e);          break;\n      case EVENTS.ZOOM_UPDATED: this.__moveZoomValue(e.args[0]); break;\n      case EVENTS.READY:        this.__moveZoomValue(this.psv.prop.zoomLvl); break;\n      // @formatter:on\n    }\n    /* eslint-enable */\n  }\n\n  /**\n   * @override\n   */\n  isSupported() {\n    return { initial: true, promise: SYSTEM.isTouchEnabled.then(enabled => !enabled) };\n  }\n\n  /**\n   * @override\n   */\n  refreshUi() {\n    if (this.prop.supported) {\n      if (this.psv.prop.size.width <= this.prop.mediaMinWidth && this.prop.visible) {\n        this.hide();\n      }\n      else if (this.psv.prop.size.width > this.prop.mediaMinWidth && !this.prop.visible) {\n        this.show();\n      }\n    }\n  }\n\n  /**\n   * @override\n   */\n  onClick() {\n    // nothing\n  }\n\n  /**\n   * @summary Moves the zoom cursor\n   * @param {number} level\n   * @private\n   */\n  __moveZoomValue(level) {\n    this.zoomValue.style.left = (level / 100 * this.zoomRange.offsetWidth - this.zoomValue.offsetWidth / 2) + 'px';\n  }\n\n  /**\n   * @summary Handles mouse down events\n   * @param {MouseEvent} evt\n   * @private\n   */\n  __initZoomChangeWithMouse(evt) {\n    if (!this.prop.enabled) {\n      return;\n    }\n\n    this.prop.mousedown = true;\n    this.__changeZoom(evt.clientX);\n  }\n\n  /**\n   * @summary Handles touch events\n   * @param {TouchEvent} evt\n   * @private\n   */\n  __initZoomChangeByTouch(evt) {\n    if (!this.prop.enabled) {\n      return;\n    }\n\n    this.prop.mousedown = true;\n    this.__changeZoom(evt.changedTouches[0].clientX);\n  }\n\n  /**\n   * @summary Handles mouse up events\n   * @private\n   */\n  __stopZoomChange() {\n    if (!this.prop.enabled) {\n      return;\n    }\n\n    this.prop.mousedown = false;\n    this.prop.buttondown = false;\n  }\n\n  /**\n   * @summary Handles mouse move events\n   * @param {MouseEvent} evt\n   * @private\n   */\n  __changeZoomWithMouse(evt) {\n    if (!this.prop.enabled || !this.prop.mousedown) {\n      return;\n    }\n\n    evt.preventDefault();\n    this.__changeZoom(evt.clientX);\n  }\n\n  /**\n   * @summary Handles touch move events\n   * @param {TouchEvent} evt\n   * @private\n   */\n  __changeZoomByTouch(evt) {\n    if (!this.prop.enabled || !this.prop.mousedown) {\n      return;\n    }\n    this.__changeZoom(evt.changedTouches[0].clientX);\n  }\n\n  /**\n   * @summary Zoom change\n   * @param {number} x - mouse/touch position\n   * @private\n   */\n  __changeZoom(x) {\n    const userInput = x - this.zoomRange.getBoundingClientRect().left;\n    const zoomLevel = userInput / this.zoomRange.offsetWidth * 100;\n    this.psv.zoom(zoomLevel);\n  }\n\n}\n","import { PSVError } from '../PSVError';\nimport { bound, clone, deepmerge, each, logWarn, parseAngle, parseSpeed } from '../utils';\nimport { ACTIONS } from './constants';\n\n/**\n * @summary Default options\n * @type {PSV.Options}\n * @memberOf PSV\n * @constant\n */\nexport const DEFAULTS = {\n  panorama           : null,\n  container          : null,\n  caption            : null,\n  loadingImg         : null,\n  loadingTxt         : 'Loading...',\n  size               : null,\n  fisheye            : false,\n  minFov             : 30,\n  maxFov             : 90,\n  defaultZoomLvl     : 50,\n  defaultLong        : 0,\n  defaultLat         : 0,\n  sphereCorrection   : {\n    pan : 0,\n    tilt: 0,\n    roll: 0,\n  },\n  moveSpeed          : 1,\n  zoomButtonIncrement: 2,\n  autorotateDelay    : null,\n  autorotateSpeed    : '2rpm',\n  autorotateLat      : null,\n  moveInertia        : true,\n  mousewheel         : true,\n  mousewheelSpeed    : 1,\n  mousemove          : true,\n  captureCursor      : false,\n  mousewheelCtrlKey  : false,\n  touchmoveTwoFingers: false,\n  useXmpData         : true,\n  panoData           : null,\n  withCredentials    : false,\n  navbar             : [\n    'autorotate',\n    'zoomOut',\n    'zoomRange',\n    'zoomIn',\n    'download',\n    'caption',\n    'fullscreen',\n  ],\n  lang               : {\n    autorotate: 'Automatic rotation',\n    zoom      : 'Zoom',\n    zoomOut   : 'Zoom out',\n    zoomIn    : 'Zoom in',\n    download  : 'Download',\n    fullscreen: 'Fullscreen',\n    menu      : 'Menu',\n    twoFingers: 'Use two fingers to navigate',\n    ctrlZoom  : 'Use ctrl + scroll to zoom the image',\n    loadError : 'The panorama can\\'t be loaded',\n  },\n  keyboard           : {\n    'ArrowUp'   : ACTIONS.ROTATE_LAT_UP,\n    'ArrowDown' : ACTIONS.ROTATE_LAT_DOWN,\n    'ArrowRight': ACTIONS.ROTATE_LONG_RIGHT,\n    'ArrowLeft' : ACTIONS.ROTATE_LONG_LEFT,\n    'PageUp'    : ACTIONS.ZOOM_IN,\n    'PageDown'  : ACTIONS.ZOOM_OUT,\n    '+'         : ACTIONS.ZOOM_IN,\n    '-'         : ACTIONS.ZOOM_OUT,\n    ' '         : ACTIONS.TOGGLE_AUTOROTATE,\n  },\n  plugins            : [],\n};\n\n/**\n * @summary List of unmodifiable options and their error messages\n * @private\n */\nexport const READONLY_OPTIONS = {\n  panorama : 'Use setPanorama method to change the panorama',\n  panoData : 'Use setPanorama method to change the panorama',\n  container: 'Cannot change viewer container',\n  plugins  : 'Cannot change plugins',\n};\n\n/**\n * @summary Parsers/validators for each option\n * @private\n */\nexport const CONFIG_PARSERS = {\n  container      : (container) => {\n    if (!container) {\n      throw new PSVError('No value given for container.');\n    }\n    return container;\n  },\n  defaultLat     : (defaultLat) => {\n    // defaultLat is between -PI/2 and PI/2\n    return parseAngle(defaultLat, true);\n  },\n  minFov         : (minFov, config) => {\n    // minFov and maxFov must be ordered\n    if (config.maxFov < minFov) {\n      logWarn('maxFov cannot be lower than minFov');\n      // eslint-disable-next-line no-param-reassign\n      minFov = config.maxFov;\n    }\n    // minFov between 1 and 179\n    return bound(minFov, 1, 179);\n  },\n  maxFov         : (maxFov, config) => {\n    // minFov and maxFov must be ordered\n    if (maxFov < config.minFov) {\n      // eslint-disable-next-line no-param-reassign\n      maxFov = config.minFov;\n    }\n    // maxFov between 1 and 179\n    return bound(maxFov, 1, 179);\n  },\n  lang           : (lang) => {\n    if (Array.isArray(lang.twoFingers)) {\n      logWarn('lang.twoFingers must not be an array');\n      lang.twoFingers = lang.twoFingers[0];\n    }\n    return {\n      ...DEFAULTS.lang,\n      ...lang,\n    };\n  },\n  keyboard       : (keyboard) => {\n    // keyboard=true becomes the default map\n    if (keyboard === true) {\n      return clone(DEFAULTS.keyboard);\n    }\n    return keyboard;\n  },\n  autorotateLat  : (autorotateLat, config) => {\n    // default autorotateLat is defaultLat\n    if (autorotateLat === null) {\n      return parseAngle(config.defaultLat, true);\n    }\n    // autorotateLat is between -PI/2 and PI/2\n    else {\n      return parseAngle(autorotateLat, true);\n    }\n  },\n  autorotateSpeed: (autorotateSpeed) => {\n    return parseSpeed(autorotateSpeed);\n  },\n  fisheye        : (fisheye) => {\n    // translate boolean fisheye to amount\n    if (fisheye === true) {\n      return 1;\n    }\n    else if (fisheye === false) {\n      return 0;\n    }\n    return fisheye;\n  },\n  plugins        : (plugins) => {\n    return plugins\n      .map((plugin) => {\n        if (Array.isArray(plugin)) {\n          return plugin;\n        }\n        else {\n          return [plugin];\n        }\n      })\n      .filter(plugin => !!plugin[0]);\n  },\n};\n\n/**\n * @summary Merge user config with default config and performs validation\n * @param {PSV.Options} options\n * @returns {PSV.Options}\n * @memberOf PSV\n * @private\n */\nexport function getConfig(options) {\n  const tempConfig = clone(DEFAULTS);\n  deepmerge(tempConfig, options);\n\n  const config = {};\n\n  each(tempConfig, (value, key) => {\n    if (!Object.prototype.hasOwnProperty.call(DEFAULTS, key)) {\n      throw new PSVError(`Unknown option ${key}`);\n    }\n\n    if (CONFIG_PARSERS[key]) {\n      config[key] = CONFIG_PARSERS[key](value, tempConfig);\n    }\n    else {\n      config[key] = value;\n    }\n  });\n\n  return config;\n}\n","import { AbstractButton } from './AbstractButton';\nimport { EVENTS } from '../data/constants';\nimport info from '../icons/info.svg';\n\n/**\n * @summary Navigation bar caption button class\n * @extends PSV.buttons.AbstractButton\n * @memberof PSV.buttons\n */\nexport class CaptionButton extends AbstractButton {\n\n  static id = 'caption';\n  static icon = info;\n\n  /**\n   * @param {PSV.components.NavbarCaption} caption\n   */\n  constructor(caption) {\n    super(caption, 'psv-button--hover-scale psv-caption-button');\n\n    this.psv.on(EVENTS.HIDE_NOTIFICATION, this);\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    this.psv.off(EVENTS.HIDE_NOTIFICATION, this);\n\n    super.destroy();\n  }\n\n  /**\n   * @summary Handles events\n   * @param {Event} e\n   * @private\n   */\n  handleEvent(e) {\n    /* eslint-disable */\n    switch (e.type) {\n      // @formatter:off\n      case EVENTS.HIDE_NOTIFICATION: this.toggleActive(false); break;\n      // @formatter:on\n    }\n    /* eslint-enable */\n  }\n\n  /**\n   * @override\n   * @description Toggles caption\n   */\n  onClick() {\n    if (this.psv.notification.prop.visible) {\n      this.psv.notification.hide();\n    }\n    else {\n      this.psv.notification.show(this.parent.prop.caption);\n      this.toggleActive(true);\n    }\n  }\n\n}\n","import { CaptionButton } from '../buttons/CaptionButton';\nimport { AbstractComponent } from './AbstractComponent';\n\n/**\n * @summary Navbar caption class\n * @extends PSV.components.AbstractComponent\n * @memberof PSV.components\n */\nexport class NavbarCaption extends AbstractComponent {\n\n  static id = 'caption';\n\n  /**\n   * @param {PSV.components.Navbar} navbar\n   * @param {string} caption\n   */\n  constructor(navbar, caption) {\n    super(navbar, 'psv-caption');\n\n    /**\n     * @member {PSV.buttons.CaptionButton}\n     * @readonly\n     * @private\n     */\n    this.button = new CaptionButton(this);\n    this.button.hide();\n\n    /**\n     * @override\n     * @property {string} id\n     * @property {boolean} collapsable\n     * @property {number} width\n     * @property {string} caption\n     * @property {boolean} contentVisible - if the content is visible in the navbar\n     * @property {number} contentWidth - with of the caption content\n     */\n    this.prop = {\n      ...this.prop,\n      id            : this.constructor.id,\n      collapsable   : false,\n      width         : this.button.prop.width,\n      caption       : '',\n      contentVisible: true,\n      contentWidth  : 0,\n    };\n\n    /**\n     * @member {HTMLElement}\n     * @readonly\n     * @private\n     */\n    this.content = document.createElement('div');\n    this.content.className = 'psv-caption-content';\n    this.container.appendChild(this.content);\n\n    this.setCaption(caption);\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    delete this.button;\n    delete this.content;\n\n    super.destroy();\n  }\n\n  /**\n   * @summary Sets the bar caption\n   * @param {string} html\n   */\n  setCaption(html) {\n    this.prop.caption = html || '';\n    this.content.innerHTML = this.prop.caption;\n\n    if (html) {\n      this.show(false);\n\n      this.content.style.display = '';\n      this.prop.contentWidth = this.content.offsetWidth;\n\n      this.refreshUi();\n    }\n    else {\n      this.hide();\n    }\n  }\n\n  /**\n   * @summary Toggles content and icon depending on available space\n   * @private\n   */\n  refreshUi() {\n    const availableWidth = this.container.offsetWidth;\n    if (availableWidth >= this.prop.contentWidth && !this.prop.contentVisible) {\n      this.content.style.display = '';\n      this.prop.contentVisible = true;\n      this.button.hide(false);\n    }\n    else if (availableWidth < this.prop.contentWidth && this.prop.contentVisible) {\n      this.content.style.display = 'none';\n      this.prop.contentVisible = false;\n      this.button.show(false);\n    }\n  }\n\n}\n","import { AutorotateButton } from '../buttons/AutorotateButton';\nimport { CustomButton } from '../buttons/CustomButton';\nimport { DownloadButton } from '../buttons/DownloadButton';\nimport { FullscreenButton } from '../buttons/FullscreenButton';\nimport { MenuButton } from '../buttons/MenuButton';\nimport { ZoomInButton } from '../buttons/ZoomInButton';\nimport { ZoomOutButton } from '../buttons/ZoomOutButton';\nimport { ZoomRangeButton } from '../buttons/ZoomRangeButton';\nimport { DEFAULTS } from '../data/config';\nimport { PSVError } from '../PSVError';\nimport { clone, logWarn } from '../utils';\nimport { AbstractComponent } from './AbstractComponent';\nimport { NavbarCaption } from './NavbarCaption';\n\n/**\n * @summary List of available buttons\n * @type {Object<string, Class<PSV.buttons.AbstractButton>>}\n * @private\n */\nconst AVAILABLE_BUTTONS = {};\n\n/**\n * @summary Register a new button available for all viewers\n * @param {Class<PSV.buttons.AbstractButton>} button\n * @memberOf PSV\n */\nexport function registerButton(button) {\n  if (!button.id) {\n    throw new PSVError('Button ID is required');\n  }\n\n  AVAILABLE_BUTTONS[button.id] = button;\n}\n\n[\n  AutorotateButton,\n  ZoomInButton,\n  ZoomRangeButton,\n  ZoomOutButton,\n  DownloadButton,\n  FullscreenButton,\n].forEach(registerButton);\n\n/**\n * @summary Navigation bar class\n * @extends PSV.components.AbstractComponent\n * @memberof PSV.components\n */\nexport class Navbar extends AbstractComponent {\n\n  /**\n   * @param {PSV.Viewer} psv\n   */\n  constructor(psv) {\n    super(psv, 'psv-navbar');\n\n    /**\n     * @summary List of buttons of the navbar\n     * @member {PSV.buttons.AbstractButton[]}\n     * @override\n     */\n    this.children = [];\n\n    /**\n     * @summary List of collapsed buttons\n     * @member {PSV.buttons.AbstractButton[]}\n     * @private\n     */\n    this.collapsed = [];\n  }\n\n  /**\n   * @summary Change the buttons visible on the navbar\n   * @param {string|Array<string|PSV.NavbarCustomButton>} buttons\n   */\n  setButtons(buttons) {\n    this.children.slice().forEach(item => item.destroy());\n    this.children.length = 0;\n\n    /* eslint-disable no-new */\n    this.__cleanButtons(buttons).forEach((button) => {\n      if (typeof button === 'object') {\n        new CustomButton(this, button);\n      }\n      else if (AVAILABLE_BUTTONS[button]) {\n        new AVAILABLE_BUTTONS[button](this);\n      }\n      else if (button === 'caption') {\n        new NavbarCaption(this, this.psv.config.caption);\n      }\n      else if (button === 'zoom') {\n        new ZoomOutButton(this);\n        new ZoomRangeButton(this);\n        new ZoomInButton(this);\n      }\n      else {\n        throw new PSVError('Unknown button ' + button);\n      }\n    });\n\n    new MenuButton(this);\n    /* eslint-enable no-new */\n\n    this.children.forEach((item) => {\n      if (typeof item.checkSupported === 'function') {\n        item.checkSupported();\n      }\n    });\n  }\n\n  /**\n   * @summary Sets the bar caption\n   * @param {string} html\n   */\n  setCaption(html) {\n    const caption = this.getButton('caption', false);\n\n    if (!caption) {\n      throw new PSVError('Cannot set caption, the navbar caption container is not initialized.');\n    }\n\n    caption.setCaption(html);\n  }\n\n  /**\n   * @summary Returns a button by its identifier\n   * @param {string} id\n   * @param {boolean} [warnNotFound=true]\n   * @returns {PSV.buttons.AbstractButton}\n   */\n  getButton(id, warnNotFound = true) {\n    let button = null;\n\n    this.children.some((item) => {\n      if (item.prop.id === id) {\n        button = item;\n        return true;\n      }\n      else {\n        return false;\n      }\n    });\n\n    if (!button && warnNotFound) {\n      logWarn(`button \"${id}\" not found in the navbar`);\n    }\n\n    return button;\n  }\n\n  /**\n   * @summary Shows the navbar\n   */\n  show() {\n    this.container.classList.add('psv-navbar--open');\n    this.prop.visible = true;\n  }\n\n  /**\n   * @summary Hides the navbar\n   */\n  hide() {\n    this.container.classList.remove('psv-navbar--open');\n    this.prop.visible = false;\n  }\n\n  /**\n   * @override\n   */\n  refreshUi() {\n    super.refreshUi();\n\n    if (this.psv.prop.uiRefresh === true) {\n      const availableWidth = this.container.offsetWidth;\n\n      let totalWidth = 0;\n      const visibleButtons = [];\n      const collapsableButtons = [];\n\n      this.children.forEach((item) => {\n        if (item.prop.visible) {\n          totalWidth += item.prop.width;\n          visibleButtons.push(item);\n          if (item.prop.collapsable) {\n            collapsableButtons.push(item);\n          }\n        }\n      });\n\n      if (!visibleButtons.length) {\n        return;\n      }\n\n      if (availableWidth < totalWidth && collapsableButtons.length > 0) {\n        collapsableButtons.forEach(item => item.collapse());\n        this.collapsed = collapsableButtons;\n\n        this.getButton(MenuButton.id).show(false);\n      }\n      else if (availableWidth >= totalWidth && this.collapsed.length > 0) {\n        this.collapsed.forEach(item => item.uncollapse());\n        this.collapsed = [];\n\n        this.getButton(MenuButton.id).hide(false);\n      }\n\n      const caption = this.getButton(NavbarCaption.id, false);\n      if (caption) {\n        caption.refreshUi();\n      }\n    }\n  }\n\n  /**\n   * @summary Ensure the buttons configuration is correct\n   * @private\n   */\n  __cleanButtons(buttons) {\n    // true becomes the default array\n    if (buttons === true) {\n      return clone(DEFAULTS.navbar);\n    }\n    // can be a space or coma separated list\n    else if (typeof buttons === 'string') {\n      return buttons.split(/[ ,]/);\n    }\n    else {\n      return buttons || [];\n    }\n  }\n\n}\n","import { EventEmitter } from 'uevent';\n\n/**\n * @namespace PSV.plugins\n */\n\n/**\n * @summary Base plugins class\n * @memberof PSV.plugins\n * @abstract\n */\nexport class AbstractPlugin extends EventEmitter {\n\n  /**\n   * @summary Unique identifier of the plugin\n   * @member {string}\n   * @readonly\n   * @static\n   */\n  static id = null;\n\n  /**\n   * @param {PSV.Viewer} psv\n   */\n  constructor(psv) {\n    super();\n\n    /**\n     * @summary Reference to main controller\n     * @type {PSV.Viewer}\n     * @readonly\n     */\n    this.psv = psv;\n  }\n\n  /**\n   * @summary Destroys the plugin\n   * @package\n   */\n  destroy() {\n    delete this.psv;\n  }\n\n}\n","import { SYSTEM } from '../data/system';\nimport { getStyle } from '../utils';\nimport { AbstractComponent } from './AbstractComponent';\n\n/**\n * @summary Loader class\n * @extends PSV.components.AbstractComponent\n * @memberof PSV.components\n */\nexport class Loader extends AbstractComponent {\n\n  /**\n   * @param {PSV.Viewer} psv\n   */\n  constructor(psv) {\n    super(psv, 'psv-loader-container');\n\n    /**\n     * @summary Inner container for vertical center\n     * @member {HTMLElement}\n     * @readonly\n     * @private\n     */\n    this.loader = document.createElement('div');\n    this.loader.className = 'psv-loader';\n    this.container.appendChild(this.loader);\n\n    /**\n     * @summary Animation canvas\n     * @member {HTMLCanvasElement}\n     * @readonly\n     * @private\n     */\n    this.canvas = document.createElement('canvas');\n    this.canvas.className = 'psv-loader-canvas';\n\n    this.canvas.width = this.loader.clientWidth * SYSTEM.pixelRatio;\n    this.canvas.height = this.loader.clientWidth * SYSTEM.pixelRatio;\n    this.loader.appendChild(this.canvas);\n\n    /**\n     * @override\n     * @property {number} thickness\n     * @property {string} current\n     */\n    this.prop = {\n      ...this.prop,\n      tickness: (this.loader.offsetWidth - this.loader.clientWidth) / 2 * SYSTEM.pixelRatio,\n      current : null,\n    };\n\n    this.refreshUi();\n    this.hide();\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    delete this.loader;\n    delete this.canvas;\n\n    super.destroy();\n  }\n\n  /**\n   * @override\n   */\n  refreshUi() {\n    if (this.prop.current !== (this.psv.config.loadingImg || this.psv.config.loadingTxt)) {\n      if (this.prop.current) {\n        this.loader.removeChild(this.loader.lastChild);\n      }\n\n      let inner;\n      if (this.psv.config.loadingImg) {\n        inner = document.createElement('img');\n        inner.className = 'psv-loader-image';\n        inner.src = this.psv.config.loadingImg;\n      }\n      else if (this.psv.config.loadingTxt) {\n        inner = document.createElement('div');\n        inner.className = 'psv-loader-text';\n        inner.innerHTML = this.psv.config.loadingTxt;\n      }\n      if (inner) {\n        const size = Math.round(Math.sqrt(2 * Math.pow((this.canvas.width / 2 - this.prop.tickness / 2) / SYSTEM.pixelRatio, 2)));\n        inner.style.maxWidth = size + 'px';\n        inner.style.maxHeight = size + 'px';\n        this.loader.appendChild(inner);\n      }\n\n      this.prop.current = this.psv.config.loadingImg || this.psv.config.loadingTxt;\n    }\n  }\n\n  /**\n   * @summary Sets the loader progression\n   * @param {number} value - from 0 to 100\n   */\n  setProgress(value) {\n    const context = this.canvas.getContext('2d');\n\n    context.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n    context.lineWidth = this.prop.tickness;\n    context.strokeStyle = getStyle(this.loader, 'color');\n\n    context.beginPath();\n    context.arc(\n      this.canvas.width / 2, this.canvas.height / 2,\n      this.canvas.width / 2 - this.prop.tickness / 2,\n      -Math.PI / 2, value / 100 * 2 * Math.PI - Math.PI / 2\n    );\n    context.stroke();\n  }\n\n}\n","import { EVENTS } from '../data/constants';\nimport { AbstractComponent } from './AbstractComponent';\n\n/**\n * @summary Notification class\n * @extends PSV.components.AbstractComponent\n * @memberof PSV.components\n */\nexport class Notification extends AbstractComponent {\n\n  /**\n   * @param {PSV.Viewer} psv\n   */\n  constructor(psv) {\n    super(psv, 'psv-notification');\n\n    /**\n     * @override\n     * @property {*} timeout\n     */\n    this.prop = {\n      ...this.prop,\n      visible: false,\n      timeout: null,\n    };\n\n    /**\n     * Notification content\n     * @member {HTMLElement}\n     * @readonly\n     * @private\n     */\n    this.content = document.createElement('div');\n    this.content.className = 'psv-notification-content';\n    this.container.appendChild(this.content);\n\n    this.content.addEventListener('click', () => this.hide());\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    delete this.content;\n\n    super.destroy();\n  }\n\n  /**\n   * @summary Displays a notification on the viewer\n   * @param {Object|string} config\n   * @param {string} config.content\n   * @param {number} [config.timeout]\n   * @fires PSV.show-notification\n   *\n   * @example\n   * viewer.showNotification({ content: 'Hello world', timeout: 5000 })\n   * @example\n   * viewer.showNotification('Hello world')\n   */\n  show(config) {\n    if (this.prop.timeout) {\n      clearTimeout(this.prop.timeout);\n      this.prop.timeout = null;\n    }\n\n    if (typeof config === 'string') {\n      config = { content: config }; // eslint-disable-line no-param-reassign\n    }\n\n    this.content.innerHTML = config.content;\n    this.prop.visible = true;\n\n    this.container.classList.add('psv-notification--visible');\n\n    this.psv.trigger(EVENTS.SHOW_NOTIFICATION);\n\n    if (config.timeout) {\n      this.prop.timeout = setTimeout(() => this.hide(), config.timeout);\n    }\n  }\n\n  /**\n   * @summary Hides the notification\n   * @fires PSV.hide-notification\n   */\n  hide() {\n    if (this.prop.visible) {\n      this.container.classList.remove('psv-notification--visible');\n\n      this.prop.visible = false;\n\n      this.psv.trigger(EVENTS.HIDE_NOTIFICATION);\n    }\n  }\n\n}\n","import { EVENTS } from '../data/constants';\nimport { AbstractComponent } from './AbstractComponent';\nimport { PSVError } from '../PSVError';\n\n/**\n * @summary Overlay class\n * @extends PSV.components.AbstractComponent\n * @memberof PSV.components\n */\nexport class Overlay extends AbstractComponent {\n\n  /**\n   * @param {PSV.Viewer} psv\n   */\n  constructor(psv) {\n    super(psv, 'psv-overlay');\n\n    /**\n     * @override\n     * @property {string} contentId\n     * @property {boolean} dissmisable\n     */\n    this.prop = {\n      ...this.prop,\n      contentId  : undefined,\n      dissmisable: true,\n    };\n\n    /**\n     * Image container\n     * @member {HTMLElement}\n     * @readonly\n     * @private\n     */\n    this.image = document.createElement('div');\n    this.image.className = 'psv-overlay-image';\n    this.container.appendChild(this.image);\n\n    /**\n     * Text container\n     * @member {HTMLElement}\n     * @readonly\n     * @private\n     */\n    this.text = document.createElement('div');\n    this.text.className = 'psv-overlay-text';\n    this.container.appendChild(this.text);\n\n    /**\n     * Subtext container\n     * @member {HTMLElement}\n     * @readonly\n     * @private\n     */\n    this.subtext = document.createElement('div');\n    this.subtext.className = 'psv-overlay-subtext';\n    this.container.appendChild(this.subtext);\n\n    this.container.addEventListener('mouseup', (e) => {\n      e.stopPropagation();\n      if (this.prop.dissmisable) {\n        this.hide();\n      }\n    }, true);\n\n    super.hide();\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    delete this.image;\n    delete this.text;\n    delete this.subtext;\n\n    super.destroy();\n  }\n\n  /**\n   * @override\n   * @param {string} [id]\n   */\n  isVisible(id) {\n    return this.prop.visible && (!id || !this.prop.contentId || this.prop.contentId === id);\n  }\n\n  /**\n   * @override\n   */\n  toggle() {\n    throw new PSVError('Overlay cannot be toggled');\n  }\n\n  /**\n   * @summary Displays an overlay on the viewer\n   * @param {Object|string} config\n   * @param {string} [config.id]\n   * @param {string} config.image\n   * @param {string} config.text\n   * @param {string} [config.subtext]\n   * @param {boolean} [config.dissmisable=true]\n   * @fires PSV.show-overlay\n   *\n   * @example\n   * viewer.showOverlay({\n   *   image: '<svg></svg>',\n   *   text: '....',\n   *   subtext: '....'\n   * })\n   */\n  show(config) {\n    if (typeof config === 'string') {\n      config = { text: config }; // eslint-disable-line no-param-reassign\n    }\n\n    this.prop.contentId = config.id;\n    this.prop.dissmisable = config.dissmisable !== false;\n    this.image.innerHTML = config.image || '';\n    this.text.innerHTML = config.text || '';\n    this.subtext.innerHTML = config.subtext || '';\n\n    super.show();\n\n    this.psv.trigger(EVENTS.SHOW_OVERLAY, config.id);\n  }\n\n  /**\n   * @summary Hides the overlay\n   * @param {string} [id]\n   * @fires PSV.hide-overlay\n   */\n  hide(id) {\n    if (this.isVisible() && (!id || !this.prop.contentId || this.prop.contentId === id)) {\n      const contentId = this.prop.contentId;\n\n      super.hide();\n\n      this.prop.contentId = undefined;\n\n      this.psv.trigger(EVENTS.HIDE_OVERLAY, contentId);\n    }\n  }\n\n}\n","import { EVENTS } from '../data/constants';\nimport { SYSTEM } from '../data/system';\nimport { PSVError } from '../PSVError';\nimport { toggleClass } from '../utils';\nimport { AbstractComponent } from './AbstractComponent';\n\n/**\n * @summary Minimum width of the panel\n * @type {number}\n * @constant\n * @private\n */\nconst PANEL_MIN_WIDTH = 200;\n\n/**\n * @summary Panel class\n * @extends PSV.components.AbstractComponent\n * @memberof PSV.components\n */\nexport class Panel extends AbstractComponent {\n\n  /**\n   * @param {PSV.Viewer} psv\n   */\n  constructor(psv) {\n    super(psv, 'psv-panel');\n\n    /**\n     * @override\n     * @property {string} contentId\n     * @property {number} mouseX\n     * @property {number} mouseY\n     * @property {boolean} mousedown\n     * @property {function} clickHandler\n     */\n    this.prop = {\n      ...this.prop,\n      visible     : false,\n      contentId   : undefined,\n      mouseX      : 0,\n      mouseY      : 0,\n      mousedown   : false,\n      clickHandler: null,\n    };\n\n    const resizer = document.createElement('div');\n    resizer.className = 'psv-panel-resizer';\n    this.container.appendChild(resizer);\n\n    const closeBtn = document.createElement('div');\n    closeBtn.className = 'psv-panel-close-button';\n    this.container.appendChild(closeBtn);\n\n    /**\n     * @summary Content container\n     * @member {HTMLElement}\n     * @readonly\n     * @private\n     */\n    this.content = document.createElement('div');\n    this.content.className = 'psv-panel-content';\n    this.container.appendChild(this.content);\n\n    // Stop wheel event bubling from panel\n    this.container.addEventListener(SYSTEM.mouseWheelEvent, e => e.stopPropagation());\n\n    closeBtn.addEventListener('click', () => this.hide());\n\n    // Event for panel resizing + stop bubling\n    resizer.addEventListener('mousedown', this);\n    resizer.addEventListener('touchstart', this);\n    this.psv.container.addEventListener('mouseup', this);\n    this.psv.container.addEventListener('touchend', this);\n    this.psv.container.addEventListener('mousemove', this);\n    this.psv.container.addEventListener('touchmove', this);\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    this.psv.container.removeEventListener('mousemove', this);\n    this.psv.container.removeEventListener('touchmove', this);\n    this.psv.container.removeEventListener('mouseup', this);\n    this.psv.container.removeEventListener('touchend', this);\n\n    delete this.prop;\n    delete this.content;\n\n    super.destroy();\n  }\n\n  /**\n   * @summary Handles events\n   * @param {Event} e\n   * @private\n   */\n  handleEvent(e) {\n    /* eslint-disable */\n    switch (e.type) {\n      // @formatter:off\n      case 'mousedown':  this.__onMouseDown(e);  break;\n      case 'touchstart': this.__onTouchStart(e); break;\n      case 'mousemove':  this.__onMouseMove(e);  break;\n      case 'touchmove':  this.__onTouchMove(e);  break;\n      case 'mouseup':    this.__onMouseUp(e);    break;\n      case 'touchend':   this.__onMouseUp(e);    break;\n      // @formatter:on\n    }\n    /* eslint-enable */\n  }\n\n  /**\n   * @override\n   * @param {string} [id]\n   */\n  isVisible(id) {\n    return this.prop.visible && (!id || !this.prop.contentId || this.prop.contentId === id);\n  }\n\n  /**\n   * @override\n   */\n  toggle() {\n    throw new PSVError('Panel cannot be toggled');\n  }\n\n  /**\n   * @summary Shows the panel\n   * @param {Object} config\n   * @param {string} [config.id]\n   * @param {string} config.content\n   * @param {boolean} [config.noMargin=false]\n   * @param {Function} [config.clickHandler]\n   * @fires PSV.open-panel\n   */\n  show(config) {\n    if (typeof config === 'string') {\n      config = { content: config }; // eslint-disable-line no-param-reassign\n    }\n\n    this.prop.contentId = config.id;\n    this.prop.visible = true;\n\n    if (this.prop.clickHandler) {\n      this.content.removeEventListener('click', this.prop.clickHandler);\n      this.prop.clickHandler = null;\n    }\n\n    this.content.innerHTML = config.content;\n    this.content.scrollTop = 0;\n    this.container.classList.add('psv-panel--open');\n\n    toggleClass(this.content, 'psv-panel-content--no-margin', config.noMargin === true);\n\n    if (config.clickHandler) {\n      this.prop.clickHandler = config.clickHandler;\n      this.content.addEventListener('click', config.clickHandler);\n    }\n\n    this.psv.trigger(EVENTS.OPEN_PANEL, config.id);\n  }\n\n  /**\n   * @summary Hides the panel\n   * @param {string} [id]\n   * @fires PSV.close-panel\n   */\n  hide(id) {\n    if (this.isVisible(id)) {\n      const contentId = this.prop.contentId;\n\n      this.prop.visible = false;\n      this.prop.contentId = undefined;\n\n      this.content.innerHTML = null;\n      this.container.classList.remove('psv-panel--open');\n\n      if (this.prop.clickHandler) {\n        this.content.removeEventListener('click', this.prop.clickHandler);\n        this.prop.clickHandler = null;\n      }\n\n      this.psv.trigger(EVENTS.CLOSE_PANEL, contentId);\n    }\n  }\n\n  /**\n   * @summary Handles mouse down events\n   * @param {MouseEvent} evt\n   * @private\n   */\n  __onMouseDown(evt) {\n    evt.stopPropagation();\n    this.__startResize(evt);\n  }\n\n  /**\n   * @summary Handles touch events\n   * @param {TouchEvent} evt\n   * @private\n   */\n  __onTouchStart(evt) {\n    evt.stopPropagation();\n    this.__startResize(evt.changedTouches[0]);\n  }\n\n  /**\n   * @summary Handles mouse up events\n   * @param {MouseEvent} evt\n   * @private\n   */\n  __onMouseUp(evt) {\n    if (this.prop.mousedown) {\n      evt.stopPropagation();\n      this.prop.mousedown = false;\n      this.content.classList.remove('psv-panel-content--no-interaction');\n    }\n  }\n\n  /**\n   * @summary Handles mouse move events\n   * @param {MouseEvent} evt\n   * @private\n   */\n  __onMouseMove(evt) {\n    if (this.prop.mousedown) {\n      evt.stopPropagation();\n      this.__resize(evt);\n    }\n  }\n\n  /**\n   * @summary Handles touch move events\n   * @param {TouchEvent} evt\n   * @private\n   */\n  __onTouchMove(evt) {\n    if (this.prop.mousedown) {\n      this.__resize(evt.touches[0]);\n    }\n  }\n\n  /**\n   * @summary Initializes the panel resize\n   * @param {MouseEvent|Touch} evt\n   * @private\n   */\n  __startResize(evt) {\n    this.prop.mouseX = evt.clientX;\n    this.prop.mouseY = evt.clientY;\n    this.prop.mousedown = true;\n    this.content.classList.add('psv-panel-content--no-interaction');\n  }\n\n  /**\n   * @summary Resizes the panel\n   * @param {MouseEvent|Touch} evt\n   * @private\n   */\n  __resize(evt) {\n    const x = evt.clientX;\n    const y = evt.clientY;\n\n    this.container.style.width = Math.max(PANEL_MIN_WIDTH, this.container.offsetWidth - (x - this.prop.mouseX)) + 'px';\n\n    this.prop.mouseX = x;\n    this.prop.mouseY = y;\n  }\n\n}\n","/**\n * @namespace PSV.services\n */\n\n/**\n * @summary Base services class\n * @memberof PSV.services\n * @abstract\n */\nexport class AbstractService {\n\n  /**\n   * @param {PSV.Viewer} psv\n   */\n  constructor(psv) {\n    /**\n     * @summary Reference to main controller\n     * @type {PSV.Viewer}\n     * @readonly\n     */\n    this.psv = psv;\n\n    /**\n     * @summary Configuration holder\n     * @type {PSV.Options}\n     * @readonly\n     */\n    this.config = psv.config;\n\n    /**\n     * @summary Properties holder\n     * @type {Object}\n     * @readonly\n     */\n    this.prop = psv.prop;\n  }\n\n  /**\n   * @summary Destroys the service\n   */\n  destroy() {\n    delete this.psv;\n    delete this.config;\n    delete this.prop;\n  }\n\n}\n","import * as THREE from 'three';\nimport { SPHERE_RADIUS } from '../data/constants';\nimport { PSVError } from '../PSVError';\nimport { parseAngle, parseSpeed } from '../utils';\nimport { AbstractService } from './AbstractService';\n\n/**\n * @summary Collections of data converters for the current viewer\n * @extends PSV.services.AbstractService\n * @memberof PSV.services\n */\nexport class DataHelper extends AbstractService {\n\n  /**\n   * @param {PSV.Viewer} psv\n   */\n  constructor(psv) {\n    super(psv);\n  }\n\n  /**\n   * @summary Converts vertical FOV to zoom level\n   * @param {number} fov\n   * @returns {number}\n   */\n  fovToZoomLevel(fov) {\n    const temp = Math.round((fov - this.config.minFov) / (this.config.maxFov - this.config.minFov) * 100);\n    return temp - 2 * (temp - 50);\n  }\n\n  /**\n   * @summary Converts zoom level to vertical FOV\n   * @param {number} level\n   * @returns {number}\n   */\n  zoomLevelToFov(level) {\n    return this.config.maxFov + (level / 100) * (this.config.minFov - this.config.maxFov);\n  }\n\n  /**\n   * @summary Convert vertical FOV to horizontal FOV\n   * @param {number} vFov\n   * @returns {number}\n   */\n  vFovToHFov(vFov) {\n    return THREE.Math.radToDeg(2 * Math.atan(Math.tan(THREE.Math.degToRad(vFov) / 2) * this.prop.aspect));\n  }\n\n  /**\n   * @summary Converts a speed into a duration from current position to a new position\n   * @param {string|number} value\n   * @param {number} angle\n   * @returns {number}\n   */\n  speedToDuration(value, angle) {\n    if (!value || typeof value !== 'number') {\n      // desired radial speed\n      const speed = value ? parseSpeed(value) : this.config.autorotateSpeed;\n      // compute duration\n      return angle / Math.abs(speed) * 1000;\n    }\n    else {\n      return Math.abs(value);\n    }\n  }\n\n  /**\n   * @summary Converts pixel texture coordinates to spherical radians coordinates\n   * @param {PSV.Point} point\n   * @returns {PSV.Position}\n   */\n  textureCoordsToSphericalCoords(point) {\n    if (this.prop.isCubemap) {\n      throw new PSVError('Unable to use texture coords with cubemap.');\n    }\n\n    const panoData = this.prop.panoData;\n    const relativeX = (point.x + panoData.croppedX) / panoData.fullWidth * Math.PI * 2;\n    const relativeY = (point.y + panoData.croppedY) / panoData.fullHeight * Math.PI;\n\n    return {\n      longitude: relativeX >= Math.PI ? relativeX - Math.PI : relativeX + Math.PI,\n      latitude : Math.PI / 2 - relativeY,\n    };\n  }\n\n  /**\n   * @summary Converts spherical radians coordinates to pixel texture coordinates\n   * @param {PSV.Position} position\n   * @returns {PSV.Point}\n   */\n  sphericalCoordsToTextureCoords(position) {\n    if (this.prop.isCubemap) {\n      throw new PSVError('Unable to use texture coords with cubemap.');\n    }\n\n    const panoData = this.prop.panoData;\n    const relativeLong = position.longitude / Math.PI / 2 * panoData.fullWidth;\n    const relativeLat = position.latitude / Math.PI * panoData.fullHeight;\n\n    return {\n      x: Math.round(position.longitude < Math.PI ? relativeLong + panoData.fullWidth / 2 : relativeLong - panoData.fullWidth / 2) - panoData.croppedX,\n      y: Math.round(panoData.fullHeight / 2 - relativeLat) - panoData.croppedY,\n    };\n  }\n\n  /**\n   * @summary Converts spherical radians coordinates to a THREE.Vector3\n   * @param {PSV.Position} position\n   * @returns {external:THREE.Vector3}\n   */\n  sphericalCoordsToVector3(position) {\n    return new THREE.Vector3(\n      SPHERE_RADIUS * -Math.cos(position.latitude) * Math.sin(position.longitude),\n      SPHERE_RADIUS * Math.sin(position.latitude),\n      SPHERE_RADIUS * Math.cos(position.latitude) * Math.cos(position.longitude)\n    );\n  }\n\n  /**\n   * @summary Converts a THREE.Vector3 to spherical radians coordinates\n   * @param {external:THREE.Vector3} vector\n   * @returns {PSV.Position}\n   */\n  vector3ToSphericalCoords(vector) {\n    const phi = Math.acos(vector.y / Math.sqrt(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z));\n    const theta = Math.atan2(vector.x, vector.z);\n\n    return {\n      longitude: theta < 0 ? -theta : Math.PI * 2 - theta,\n      latitude : Math.PI / 2 - phi,\n    };\n  }\n\n  /**\n   * @summary Converts position on the viewer to a THREE.Vector3\n   * @param {PSV.Point} viewerPoint\n   * @returns {external:THREE.Vector3}\n   */\n  viewerCoordsToVector3(viewerPoint) {\n    const screen = new THREE.Vector2(\n      2 * viewerPoint.x / this.prop.size.width - 1,\n      -2 * viewerPoint.y / this.prop.size.height + 1\n    );\n\n    this.psv.renderer.raycaster.setFromCamera(screen, this.psv.renderer.camera);\n\n    const intersects = this.psv.renderer.raycaster.intersectObjects(this.psv.renderer.scene.children);\n\n    if (intersects.length === 1) {\n      return intersects[0].point;\n    }\n    else {\n      return null;\n    }\n  }\n\n  /**\n   * @summary Converts a THREE.Vector3 to position on the viewer\n   * @param {external:THREE.Vector3} vector\n   * @returns {PSV.Point}\n   */\n  vector3ToViewerCoords(vector) {\n    const vectorClone = vector.clone();\n    vectorClone.project(this.psv.renderer.camera);\n\n    return {\n      x: Math.round((vectorClone.x + 1) / 2 * this.prop.size.width),\n      y: Math.round((1 - vectorClone.y) / 2 * this.prop.size.height),\n    };\n  }\n\n  /**\n   * @summary Checks if an object is a {PSV.ExtendedPosition}, ie has x/y or longitude/latitude\n   * @param {object} object\n   * @returns {boolean}\n   */\n  isExtendedPosition(object) {\n    return [['x', 'y'], ['longitude', 'latitude']].some(([key1, key2]) => {\n      return key1 in object && key2 in object;\n    });\n  }\n\n  /**\n   * @summary Converts x/y to latitude/longitude if present and ensure boundaries\n   * @param {PSV.ExtendedPosition} position\n   * @returns {PSV.Position}\n   */\n  cleanPosition(position) {\n    if ('x' in position && 'y' in position) {\n      return this.textureCoordsToSphericalCoords(position);\n    }\n    else {\n      return {\n        longitude: parseAngle(position.longitude),\n        latitude : parseAngle(position.latitude, true),\n      };\n    }\n  }\n\n  /**\n   * @summary Ensure a SphereCorrection object is valide\n   * @param {PSV.SphereCorrection} sphereCorrection\n   * @returns {PSV.SphereCorrection}\n   */\n  cleanSphereCorrection(sphereCorrection) {\n    return {\n      pan : parseAngle(sphereCorrection.pan || 0),\n      tilt: parseAngle(sphereCorrection.tilt || 0, true),\n      roll: parseAngle(sphereCorrection.roll || 0, true, false),\n    };\n  }\n\n}\n","import { Animation } from '../Animation';\nimport {\n  ACTIONS,\n  CTRLZOOM_TIMEOUT,\n  DBLCLICK_DELAY,\n  EVENTS,\n  IDS,\n  INERTIA_WINDOW,\n  LONGTOUCH_DELAY,\n  TWOFINGERSOVERLAY_DELAY,\n  MOVE_THRESHOLD\n} from '../data/constants';\nimport { SYSTEM } from '../data/system';\nimport gestureIcon from '../icons/gesture.svg';\nimport mousewheelIcon from '../icons/mousewheel.svg';\nimport { clone, distance, getClosest, getEventKey, isFullscreenEnabled, normalizeWheel, throttle } from '../utils';\nimport { AbstractService } from './AbstractService';\n\n/**\n * @summary Events handler\n * @extends PSV.services.AbstractService\n * @memberof PSV.services\n */\nexport class EventsHandler extends AbstractService {\n\n  /**\n   * @param {PSV.Viewer} psv\n   */\n  constructor(psv) {\n    super(psv);\n\n    /**\n     * @summary Internal properties\n     * @member {Object}\n     * @property {boolean} moving - is the user moving\n     * @property {boolean} zooming - is the user zooming\n     * @property {number} startMouseX - start x position of the click/touch\n     * @property {number} startMouseY - start y position of the click/touch\n     * @property {number} mouseX - current x position of the cursor\n     * @property {number} mouseY - current y position of the cursor\n     * @property {number[][]} mouseHistory - list of latest positions of the cursor, [time, x, y]\n     * @property {number} pinchDist - distance between fingers when zooming\n     * @property {boolean} ctrlKeyDown - when the Ctrl key is pressed\n     * @property {PSV.ClickData} dblclickData - temporary storage of click data between two clicks\n     * @property {number} dblclickTimeout - timeout id for double click\n     * @property {number} twofingersTimeout - timeout id for \"two fingers\" overlay\n     * @property {number} ctrlZoomTimeout - timeout id for \"ctrol zoom\" overlay\n     * @protected\n     */\n    this.state = {\n      keyboardEnabled  : false,\n      moving           : false,\n      zooming          : false,\n      startMouseX      : 0,\n      startMouseY      : 0,\n      mouseX           : 0,\n      mouseY           : 0,\n      mouseHistory     : [],\n      pinchDist        : 0,\n      ctrlKeyDown      : false,\n      dblclickData     : null,\n      dblclickTimeout  : null,\n      longtouchTimeout : null,\n      twofingersTimeout: null,\n      ctrlZoomTimeout  : null,\n    };\n\n    /**\n     * @summary Throttled wrapper of {@link PSV.Viewer#autoSize}\n     * @type {Function}\n     * @private\n     */\n    this.__onResize = throttle(() => this.psv.autoSize(), 50);\n  }\n\n  /**\n   * @summary Initializes event handlers\n   * @protected\n   */\n  init() {\n    window.addEventListener('resize', this);\n    window.addEventListener('keydown', this);\n    window.addEventListener('keyup', this);\n    this.psv.container.addEventListener('mouseenter', this);\n    this.psv.container.addEventListener('mousedown', this);\n    this.psv.container.addEventListener('mouseleave', this);\n    window.addEventListener('mouseup', this);\n    this.psv.container.addEventListener('touchstart', this);\n    window.addEventListener('touchend', this);\n    this.psv.container.addEventListener('mousemove', this);\n    this.psv.container.addEventListener('touchmove', this);\n    this.psv.container.addEventListener(SYSTEM.mouseWheelEvent, this);\n\n    if (SYSTEM.fullscreenEvent) {\n      document.addEventListener(SYSTEM.fullscreenEvent, this);\n    }\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    window.removeEventListener('resize', this);\n    window.removeEventListener('keydown', this);\n    window.removeEventListener('keyup', this);\n    this.psv.container.removeEventListener('mouseenter', this);\n    this.psv.container.removeEventListener('mousedown', this);\n    this.psv.container.removeEventListener('mouseleave', this);\n    window.removeEventListener('mouseup', this);\n    this.psv.container.removeEventListener('touchstart', this);\n    window.removeEventListener('touchend', this);\n    this.psv.container.removeEventListener('mousemove', this);\n    this.psv.container.removeEventListener('touchmove', this);\n    this.psv.container.removeEventListener(SYSTEM.mouseWheelEvent, this);\n\n    if (SYSTEM.fullscreenEvent) {\n      document.removeEventListener(SYSTEM.fullscreenEvent, this);\n    }\n\n    clearTimeout(this.state.dblclickTimeout);\n    clearTimeout(this.state.longtouchTimeout);\n    clearTimeout(this.state.twofingersTimeout);\n    clearTimeout(this.state.ctrlZoomTimeout);\n\n    delete this.state;\n\n    super.destroy();\n  }\n\n  /**\n   * @summary Handles events\n   * @param {Event} evt\n   * @private\n   */\n  handleEvent(evt) {\n    /* eslint-disable */\n    switch (evt.type) {\n      // @formatter:off\n      case 'resize':   this.__onResize(); break;\n      case 'keydown':  this.__onKeyDown(evt); break;\n      case 'keyup':    this.__onKeyUp(); break;\n      case 'mouseup':  this.__onMouseUp(evt); break;\n      case 'touchend': this.__onTouchEnd(evt); break;\n      case SYSTEM.fullscreenEvent: this.__fullscreenToggled(); break;\n      // @formatter:on\n    }\n    /* eslint-enable */\n\n    if (!getClosest(evt.target, '.psv-navbar') && !getClosest(evt.target, '.psv-panel')) {\n      /* eslint-disable */\n      switch (evt.type) {\n        // @formatter:off\n        case 'mousedown':  this.__onMouseDown(evt); break;\n        case 'mouseenter': this.__onMouseEnter(evt); break;\n        case 'touchstart': this.__onTouchStart(evt); break;\n        case 'mouseleave': this.__onMouseLeave(evt); break;\n        case 'mousemove':  this.__onMouseMove(evt); break;\n        case 'touchmove':  this.__onTouchMove(evt); break;\n        case SYSTEM.mouseWheelEvent: this.__onMouseWheel(evt); break;\n        // @formatter:on\n      }\n      /* eslint-enable */\n    }\n  }\n\n  /**\n   * @summary Enables the keyboard controls\n   * @protected\n   */\n  enableKeyboard() {\n    this.state.keyboardEnabled = true;\n  }\n\n  /**\n   * @summary Disables the keyboard controls\n   * @protected\n   */\n  disableKeyboard() {\n    this.state.keyboardEnabled = false;\n  }\n\n  /**\n   * @summary Handles keyboard events\n   * @param {KeyboardEvent} evt\n   * @private\n   */\n  __onKeyDown(evt) {\n    const key = getEventKey(evt);\n\n    if (this.config.mousewheelCtrlKey) {\n      this.state.ctrlKeyDown = key === 'Control';\n\n      if (this.state.ctrlKeyDown) {\n        clearTimeout(this.state.ctrlZoomTimeout);\n        this.psv.overlay.hide(IDS.CTRL_ZOOM);\n      }\n    }\n\n    if (!this.state.keyboardEnabled) {\n      return;\n    }\n\n    let dLong = 0;\n    let dLat = 0;\n    let dZoom = 0;\n\n    /* eslint-disable */\n    switch (this.config.keyboard[key]) {\n      // @formatter:off\n      case ACTIONS.ROTATE_LAT_UP    : dLat = 0.01;   break;\n      case ACTIONS.ROTATE_LAT_DOWN  : dLat = -0.01;  break;\n      case ACTIONS.ROTATE_LONG_RIGHT: dLong = 0.01;  break;\n      case ACTIONS.ROTATE_LONG_LEFT : dLong = -0.01; break;\n      case ACTIONS.ZOOM_IN          : dZoom = 1;     break;\n      case ACTIONS.ZOOM_OUT         : dZoom = -1;    break;\n      case ACTIONS.TOGGLE_AUTOROTATE: this.psv.toggleAutorotate(); break;\n      // @formatter:on\n    }\n    /* eslint-enable */\n\n    if (dZoom !== 0) {\n      this.psv.zoom(this.prop.zoomLvl + dZoom * this.config.zoomButtonIncrement);\n    }\n    else if (dLat !== 0 || dLong !== 0) {\n      this.psv.rotate({\n        longitude: this.prop.position.longitude + dLong * this.prop.moveSpeed * this.prop.hFov,\n        latitude : this.prop.position.latitude + dLat * this.prop.moveSpeed * this.prop.vFov,\n      });\n    }\n  }\n\n  /**\n   * @summary Handles keyboard events\n   * @private\n   */\n  __onKeyUp() {\n    this.state.ctrlKeyDown = false;\n  }\n\n  /**\n   * @summary Handles mouse down events\n   * @param {MouseEvent} evt\n   * @private\n   */\n  __onMouseDown(evt) {\n    if (!this.config.mousemove || this.config.captureCursor) {\n      return;\n    }\n\n    this.__startMove(evt);\n  }\n\n  /**\n   * @summary Handles mouse enter events\n   * @param {MouseEvent} evt\n   * @private\n   */\n  __onMouseEnter(evt) {\n    if (!this.config.mousemove || !this.config.captureCursor) {\n      return;\n    }\n\n    this.__startMove(evt);\n  }\n\n  /**\n   * @summary Handles mouse up events\n   * @param {MouseEvent} evt\n   * @private\n   */\n  __onMouseUp(evt) {\n    if (!this.config.mousemove || this.config.captureCursor) {\n      return;\n    }\n\n    this.__stopMove(evt);\n  }\n\n  /**\n   * @summary Handles mouse leave events\n   * @param {MouseEvent} evt\n   * @private\n   */\n  __onMouseLeave(evt) {\n    if (!this.config.mousemove || !this.config.captureCursor) {\n      return;\n    }\n\n    this.__stopMove(evt);\n  }\n\n  /**\n   * @summary Handles mouse move events\n   * @param {MouseEvent} evt\n   * @private\n   */\n  __onMouseMove(evt) {\n    if (!this.config.mousemove) {\n      return;\n    }\n\n    if (evt.buttons !== 0) {\n      evt.preventDefault();\n      this.__move(evt);\n    }\n    else if (this.config.captureCursor) {\n      this.__moveAbsolute(evt);\n    }\n  }\n\n  /**\n   * @summary Handles touch events\n   * @param {TouchEvent} evt\n   * @private\n   */\n  __onTouchStart(evt) {\n    if (!this.config.mousemove) {\n      return;\n    }\n\n    if (evt.touches.length === 1) {\n      if (!this.config.touchmoveTwoFingers) {\n        this.__startMove(evt.touches[0]);\n        evt.preventDefault(); // prevent mouse events emulation\n      }\n\n      if (!this.prop.longtouchTimeout) {\n        this.prop.longtouchTimeout = setTimeout(() => {\n          this.__click(evt.touches[0], true);\n          this.prop.longtouchTimeout = null;\n        }, LONGTOUCH_DELAY);\n      }\n    }\n    else if (evt.touches.length === 2) {\n      this.__cancelLongTouch();\n      this.__startMoveZoom(evt);\n      evt.preventDefault();\n    }\n  }\n\n  /**\n   * @summary Handles touch events\n   * @param {TouchEvent} evt\n   * @private\n   */\n  __onTouchEnd(evt) {\n    if (!this.config.mousemove) {\n      return;\n    }\n\n    this.__cancelLongTouch();\n\n    if (evt.touches.length === 1) {\n      this.__stopMoveZoom();\n    }\n    else if (evt.touches.length === 0) {\n      this.__stopMove(evt.changedTouches[0]);\n    }\n\n    if (this.config.touchmoveTwoFingers) {\n      this.__cancelTwoFingersOverlay();\n      this.psv.overlay.hide(IDS.TWO_FINGERS);\n    }\n  }\n\n  /**\n   * @summary Handles touch move events\n   * @param {TouchEvent} evt\n   * @private\n   */\n  __onTouchMove(evt) {\n    if (!this.config.mousemove) {\n      return;\n    }\n\n    if (evt.touches.length === 1) {\n      if (this.config.touchmoveTwoFingers) {\n        if (!this.prop.twofingersTimeout) {\n          this.prop.twofingersTimeout = setTimeout(() => {\n            this.psv.overlay.show({\n              id: IDS.TWO_FINGERS,\n              image: gestureIcon,\n              text: this.config.lang.twoFingers,\n            });\n          }, TWOFINGERSOVERLAY_DELAY);\n        }\n      }\n      else {\n        evt.preventDefault();\n        this.__move(evt.touches[0]);\n      }\n    }\n    else if (evt.touches.length === 2) {\n      evt.preventDefault();\n      this.__moveZoom(evt);\n      if (this.config.touchmoveTwoFingers) {\n        this.__cancelTwoFingersOverlay();\n      }\n    }\n  }\n\n  /**\n   * @summary Cancel the long touch timer if any\n   * @private\n   */\n  __cancelLongTouch() {\n    if (this.prop.longtouchTimeout) {\n      clearTimeout(this.prop.longtouchTimeout);\n      this.prop.longtouchTimeout = null;\n    }\n  }\n\n  /**\n   * @summary Cancel the two fingers overlay timer if any\n   * @private\n   */\n  __cancelTwoFingersOverlay() {\n    if (this.prop.twofingersTimeout) {\n      clearTimeout(this.prop.twofingersTimeout);\n      this.prop.twofingersTimeout = null;\n    }\n  }\n\n  /**\n   * @summary Handles mouse wheel events\n   * @param {WheelEvent} evt\n   * @private\n   */\n  __onMouseWheel(evt) {\n    if (!this.config.mousewheel) {\n      return;\n    }\n\n    if (this.config.mousewheelCtrlKey && !this.state.ctrlKeyDown) {\n      this.psv.overlay.show({\n        id: IDS.CTRL_ZOOM,\n        image: mousewheelIcon,\n        text: this.config.lang.ctrlZoom,\n      });\n\n      clearTimeout(this.state.ctrlZoomTimeout);\n      this.state.ctrlZoomTimeout = setTimeout(() => this.psv.overlay.hide(IDS.CTRL_ZOOM), CTRLZOOM_TIMEOUT);\n\n      return;\n    }\n\n    evt.preventDefault();\n    evt.stopPropagation();\n\n    const delta = normalizeWheel(evt).spinY * 5;\n\n    if (delta !== 0) {\n      this.psv.zoom(this.prop.zoomLvl - delta * this.config.mousewheelSpeed);\n    }\n  }\n\n  /**\n   * @summary Handles fullscreen events\n   * @param {boolean} [force] force state\n   * @fires PSV.fullscreen-updated\n   * @package\n   */\n  __fullscreenToggled(force) {\n    this.prop.fullscreen = force !== undefined ? force : isFullscreenEnabled(this.psv.container);\n\n    if (this.config.keyboard) {\n      if (this.prop.fullscreen) {\n        this.psv.startKeyboardControl();\n      }\n      else {\n        this.psv.stopKeyboardControl();\n      }\n    }\n\n    this.psv.trigger(EVENTS.FULLSCREEN_UPDATED, this.prop.fullscreen);\n  }\n\n  /**\n   * @summary Initializes the movement\n   * @param {MouseEvent|Touch} evt\n   * @private\n   */\n  __startMove(evt) {\n    this.psv.stopAutorotate();\n    this.psv.stopAnimation()\n      .then(() => {\n        this.state.mouseX = evt.clientX;\n        this.state.mouseY = evt.clientY;\n        this.state.startMouseX = this.state.mouseX;\n        this.state.startMouseY = this.state.mouseY;\n        this.state.moving = true;\n        this.state.zooming = false;\n\n        this.state.mouseHistory.length = 0;\n        this.__logMouseMove(evt);\n      });\n  }\n\n  /**\n   * @summary Initializes the combines move and zoom\n   * @param {TouchEvent} evt\n   * @private\n   */\n  __startMoveZoom(evt) {\n    const p1 = { x: evt.touches[0].clientX, y: evt.touches[0].clientY };\n    const p2 = { x: evt.touches[1].clientX, y: evt.touches[1].clientY };\n\n    this.state.pinchDist = distance(p1, p2);\n    this.state.mouseX = (p1.x + p2.x) / 2;\n    this.state.mouseY = (p1.y + p2.y) / 2;\n    this.state.startMouseX = this.state.mouseX;\n    this.state.startMouseY = this.state.mouseY;\n    this.state.moving = true;\n    this.state.zooming = true;\n  }\n\n  /**\n   * @summary Stops the movement\n   * @description If the move threshold was not reached a click event is triggered, otherwise an animation is launched to simulate inertia\n   * @param {MouseEvent|Touch} evt\n   * @private\n   */\n  __stopMove(evt) {\n    if (!getClosest(evt.target, '.psv-container')) {\n      this.state.moving = false;\n      this.state.mouseHistory.length = 0;\n      return;\n    }\n\n    if (this.state.moving) {\n      // move threshold to trigger a click\n      if (Math.abs(evt.clientX - this.state.startMouseX) < MOVE_THRESHOLD && Math.abs(evt.clientY - this.state.startMouseY) < MOVE_THRESHOLD) {\n        this.__click(evt);\n        this.state.moving = false;\n      }\n      // inertia animation\n      else if (this.config.moveInertia) {\n        this.__logMouseMove(evt);\n        this.__stopMoveInertia(evt);\n      }\n      else {\n        this.state.moving = false;\n      }\n\n      this.state.mouseHistory.length = 0;\n    }\n  }\n\n  /**\n   * @summary Stops the combined move and zoom\n   * @private\n   */\n  __stopMoveZoom() {\n    this.state.mouseHistory.length = 0;\n    this.state.moving = false;\n    this.state.zooming = false;\n  }\n\n  /**\n   * @summary Performs an animation to simulate inertia when the movement stops\n   * @param {MouseEvent|Touch} evt\n   * @private\n   */\n  __stopMoveInertia(evt) {\n    const direction = {\n      x: evt.clientX - this.state.mouseHistory[0][1],\n      y: evt.clientY - this.state.mouseHistory[0][2],\n    };\n\n    const norm = Math.sqrt(direction.x * direction.x + direction.y * direction.y);\n\n    this.prop.animationPromise = new Animation({\n      properties: {\n        clientX: { start: evt.clientX, end: evt.clientX + direction.x },\n        clientY: { start: evt.clientY, end: evt.clientY + direction.y },\n      },\n      duration  : norm * INERTIA_WINDOW / 100,\n      easing    : 'outCirc',\n      onTick    : (properties) => {\n        this.__move(properties, false);\n      },\n    })\n      .finally(() => {\n        this.state.moving = false;\n      });\n  }\n\n  /**\n   * @summary Triggers an event with all coordinates when a simple click is performed\n   * @param {MouseEvent|Touch} evt\n   * @param {boolean} [longtouch=false]\n   * @fires PSV.click\n   * @fires PSV.dblclick\n   * @private\n   */\n  __click(evt, longtouch = false) {\n    const boundingRect = this.psv.container.getBoundingClientRect();\n\n    /**\n     * @type {PSV.ClickData}\n     */\n    const data = {\n      rightclick: longtouch || evt.button === 2,\n      target    : evt.target,\n      clientX   : evt.clientX,\n      clientY   : evt.clientY,\n      viewerX   : evt.clientX - boundingRect.left,\n      viewerY   : evt.clientY - boundingRect.top,\n    };\n\n    const intersect = this.psv.dataHelper.viewerCoordsToVector3({\n      x: data.viewerX,\n      y: data.viewerY,\n    });\n\n    if (intersect) {\n      const sphericalCoords = this.psv.dataHelper.vector3ToSphericalCoords(intersect);\n      data.longitude = sphericalCoords.longitude;\n      data.latitude = sphericalCoords.latitude;\n\n      // TODO: for cubemap, computes texture's index and coordinates\n      if (!this.prop.isCubemap) {\n        const textureCoords = this.psv.dataHelper.sphericalCoordsToTextureCoords(data);\n        data.textureX = textureCoords.x;\n        data.textureY = textureCoords.y;\n      }\n\n      if (!this.state.dblclickTimeout) {\n        this.psv.trigger(EVENTS.CLICK, data);\n\n        this.state.dblclickData = clone(data);\n        this.state.dblclickTimeout = setTimeout(() => {\n          this.state.dblclickTimeout = null;\n          this.state.dblclickData = null;\n        }, DBLCLICK_DELAY);\n      }\n      else {\n        if (Math.abs(this.state.dblclickData.clientX - data.clientX) < MOVE_THRESHOLD\n          && Math.abs(this.state.dblclickData.clientY - data.clientY) < MOVE_THRESHOLD) {\n          this.psv.trigger(EVENTS.DOUBLE_CLICK, this.state.dblclickData);\n        }\n\n        clearTimeout(this.state.dblclickTimeout);\n        this.state.dblclickTimeout = null;\n        this.state.dblclickData = null;\n      }\n    }\n  }\n\n  /**\n   * @summary Performs movement\n   * @param {MouseEvent|Touch} evt\n   * @param {boolean} [log=true]\n   * @private\n   */\n  __move(evt, log) {\n    if (this.state.moving) {\n      const x = evt.clientX;\n      const y = evt.clientY;\n\n      const rotation = {\n        longitude: (x - this.state.mouseX) / this.prop.size.width * this.prop.moveSpeed * this.prop.hFov * SYSTEM.pixelRatio,\n        latitude : (y - this.state.mouseY) / this.prop.size.height * this.prop.moveSpeed * this.prop.vFov * SYSTEM.pixelRatio,\n      };\n\n      this.psv.rotate({\n        longitude: this.prop.position.longitude - rotation.longitude,\n        latitude : this.prop.position.latitude + rotation.latitude,\n      });\n\n      this.state.mouseX = x;\n      this.state.mouseY = y;\n\n      if (log !== false) {\n        this.__logMouseMove(evt);\n      }\n    }\n  }\n\n  /**\n   * @summary Performs movement absolute to cursor position in viewer\n   * @param {MouseEvent} evt\n   * @private\n   */\n  __moveAbsolute(evt) {\n    if (this.state.moving) {\n      const containerRect = this.psv.container.getBoundingClientRect();\n      this.psv.rotate({\n        longitude: ((evt.clientX - containerRect.left) / containerRect.width - 0.5) * Math.PI * 2,\n        latitude : -((evt.clientY - containerRect.top) / containerRect.height - 0.5) * Math.PI,\n      });\n    }\n  }\n\n  /**\n   * @summary Perfoms combined move and zoom\n   * @param {TouchEvent} evt\n   * @private\n   */\n  __moveZoom(evt) {\n    if (this.state.zooming && this.state.moving) {\n      const p1 = { x: evt.touches[0].clientX, y: evt.touches[0].clientY };\n      const p2 = { x: evt.touches[1].clientX, y: evt.touches[1].clientY };\n\n      const p = distance(p1, p2);\n      const delta = 80 * (p - this.state.pinchDist) / this.prop.size.width;\n\n      this.psv.zoom(this.prop.zoomLvl + delta);\n\n      this.__move({\n        clientX: (p1.x + p2.x) / 2,\n        clientY: (p1.y + p2.y) / 2,\n      });\n\n      this.state.pinchDist = p;\n    }\n  }\n\n  /**\n   * @summary Stores each mouse position during a mouse move\n   * @description Positions older than \"INERTIA_WINDOW\" are removed<br>\n   *     Positions before a pause of \"INERTIA_WINDOW\" / 10 are removed\n   * @param {MouseEvent|Touch} evt\n   * @private\n   */\n  __logMouseMove(evt) {\n    const now = Date.now();\n    this.state.mouseHistory.push([now, evt.clientX, evt.clientY]);\n\n    let previous = null;\n\n    for (let i = 0; i < this.state.mouseHistory.length;) {\n      if (this.state.mouseHistory[0][i] < now - INERTIA_WINDOW) {\n        this.state.mouseHistory.splice(i, 1);\n      }\n      else if (previous && this.state.mouseHistory[0][i] - previous > INERTIA_WINDOW / 10) {\n        this.state.mouseHistory.splice(0, i);\n        i = 0;\n        previous = this.state.mouseHistory[0][i];\n      }\n      else {\n        i++;\n        previous = this.state.mouseHistory[0][i];\n      }\n    }\n  }\n\n}\n","import * as THREE from 'three';\nimport { Animation } from '../Animation';\nimport { CUBE_VERTICES, EVENTS, SPHERE_RADIUS, SPHERE_VERTICES } from '../data/constants';\nimport { SYSTEM } from '../data/system';\nimport { logWarn } from '../utils';\nimport { AbstractService } from './AbstractService';\n\n/**\n * @summary Viewer and renderer\n * @extends PSV.services.AbstractService\n * @memberof PSV.services\n */\nexport class Renderer extends AbstractService {\n\n  /**\n   * @param {PSV.Viewer} psv\n   */\n  constructor(psv) {\n    super(psv);\n\n    /**\n     * @member {number}\n     * @private\n     */\n    this.mainReqid = undefined;\n\n    /**\n     * @member {external:THREE.WebGLRenderer}\n     * @readonly\n     * @protected\n     */\n    this.renderer = null;\n\n    /**\n     * @member {external:THREE.Scene}\n     * @readonly\n     * @protected\n     */\n    this.scene = null;\n\n    /**\n     * @member {external:THREE.PerspectiveCamera}\n     * @readonly\n     * @protected\n     */\n    this.camera = null;\n\n    /**\n     * @member {external:THREE.Mesh}\n     * @readonly\n     * @protected\n     */\n    this.mesh = null;\n\n    /**\n     * @member {external:THREE.Raycaster}\n     * @readonly\n     * @protected\n     */\n    this.raycaster = null;\n\n    /**\n     * @member {HTMLElement}\n     * @readonly\n     * @protected\n     */\n    this.canvasContainer = document.createElement('div');\n    this.canvasContainer.className = 'psv-canvas-container';\n    this.canvasContainer.style.cursor = this.psv.config.mousemove ? 'move' : 'default';\n    this.psv.container.appendChild(this.canvasContainer);\n\n    psv.on(EVENTS.SIZE_UPDATED, (e, size) => {\n      if (this.renderer) {\n        this.renderer.setSize(size.width, size.height);\n      }\n    });\n\n    psv.on(EVENTS.CONFIG_CHANGED, () => {\n      this.canvasContainer.style.cursor = this.psv.config.mousemove ? 'move' : 'default';\n    });\n\n    this.hide();\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    // cancel render loop\n    if (this.mainReqid) {\n      window.cancelAnimationFrame(this.mainReqid);\n    }\n\n    // destroy ThreeJS view\n    if (this.scene) {\n      this.__cleanTHREEScene(this.scene);\n    }\n\n    // remove container\n    this.psv.container.removeChild(this.canvasContainer);\n\n    delete this.canvasContainer;\n    delete this.renderer;\n    delete this.scene;\n    delete this.camera;\n    delete this.mesh;\n    delete this.raycaster;\n\n    super.destroy();\n  }\n\n  /**\n   * @summary Hides the viewer\n   */\n  hide() {\n    this.canvasContainer.style.opacity = 0;\n  }\n\n  /**\n   * @summary Shows the viewer\n   */\n  show() {\n    this.canvasContainer.style.opacity = 1;\n  }\n\n  /**\n   * @summary Main event loop, calls {@link render} if `prop.needsUpdate` is true\n   * @param {number} timestamp\n   * @fires PSV.before-render\n   * @package\n   */\n  __renderLoop(timestamp) {\n    this.psv.trigger(EVENTS.BEFORE_RENDER, timestamp);\n\n    if (this.prop.needsUpdate) {\n      this.render();\n      this.prop.needsUpdate = false;\n    }\n\n    this.mainReqid = window.requestAnimationFrame(t => this.__renderLoop(t));\n  }\n\n  /**\n   * @summary Performs a render\n   * @description Do not call this method directly, instead call\n   * {@link PSV.Viewer#needsUpdate} on {@link PSV.event:before-render}.\n   * @fires PSV.render\n   */\n  render() {\n    this.prop.direction = this.psv.dataHelper.sphericalCoordsToVector3(this.prop.position);\n    this.camera.position.set(0, 0, 0);\n    this.camera.lookAt(this.prop.direction);\n\n    if (this.config.fisheye) {\n      this.camera.position.copy(this.prop.direction).multiplyScalar(this.config.fisheye / 2).negate();\n    }\n\n    this.camera.aspect = this.prop.aspect;\n    this.camera.fov = this.prop.vFov;\n    this.camera.updateProjectionMatrix();\n\n    this.renderer.render(this.scene, this.camera);\n\n    this.psv.trigger(EVENTS.RENDER);\n  }\n\n  /**\n   * @summary Applies the texture to the scene, creates the scene if needed\n   * @param {PSV.TextureData} textureData\n   * @fires PSV.panorama-loaded\n   * @package\n   */\n  setTexture(textureData) {\n    const { texture, panoData } = textureData;\n    this.prop.panoData = panoData;\n\n    if (!this.scene) {\n      this.__createScene();\n    }\n\n    if (this.prop.isCubemap) {\n      for (let i = 0; i < 6; i++) {\n        if (this.mesh.material[i].map) {\n          this.mesh.material[i].map.dispose();\n        }\n\n        this.mesh.material[i].map = texture[i];\n      }\n    }\n    else {\n      if (this.mesh.material.map) {\n        this.mesh.material.map.dispose();\n      }\n\n      this.mesh.material.map = texture;\n    }\n\n    this.psv.needsUpdate();\n\n    this.psv.trigger(EVENTS.PANORAMA_LOADED);\n  }\n\n  /**\n   * @summary Apply a SphereCorrection to a Mesh\n   * @param {PSV.SphereCorrection} sphereCorrection\n   * @param {external:THREE.Mesh} [mesh=this.mesh]\n   * @package\n   */\n  setSphereCorrection(sphereCorrection, mesh = this.mesh) {\n    const cleanCorrection = this.psv.dataHelper.cleanSphereCorrection(sphereCorrection);\n\n    mesh.rotation.set(\n      cleanCorrection.tilt,\n      cleanCorrection.pan,\n      cleanCorrection.roll\n    );\n  }\n\n  /**\n   * @summary Creates the 3D scene and GUI components\n   * @private\n   */\n  __createScene() {\n    this.raycaster = new THREE.Raycaster();\n\n    this.renderer = new THREE.WebGLRenderer();\n    this.renderer.setSize(this.prop.size.width, this.prop.size.height);\n    this.renderer.setPixelRatio(SYSTEM.pixelRatio);\n\n    this.camera = new THREE.PerspectiveCamera(this.prop.vFov, this.prop.size.width / this.prop.size.height, 1, 3 * SPHERE_RADIUS);\n    this.camera.position.set(0, 0, 0);\n\n    this.scene = new THREE.Scene();\n    this.scene.add(this.camera);\n\n    if (this.prop.isCubemap) {\n      this.mesh = this.__createCubemap();\n    }\n    else {\n      this.mesh = this.__createSphere();\n    }\n\n    this.scene.add(this.mesh);\n\n    // create canvas container\n    this.renderer.domElement.className = 'psv-canvas';\n    this.canvasContainer.appendChild(this.renderer.domElement);\n  }\n\n  /**\n   * @summary Creates the sphere mesh\n   * @param {number} [scale=1]\n   * @returns {external:THREE.Mesh}\n   * @private\n   */\n  __createSphere(scale = 1) {\n    // The middle of the panorama is placed at longitude=0\n    const geometry = new THREE.SphereGeometry(SPHERE_RADIUS * scale, SPHERE_VERTICES, SPHERE_VERTICES, -Math.PI / 2);\n\n    const material = new THREE.MeshBasicMaterial({\n      side: THREE.BackSide,\n    });\n\n    const mesh = new THREE.Mesh(geometry, material);\n    mesh.scale.set(-1, 1, 1);\n\n    return mesh;\n  }\n\n  /**\n   * @summary Creates the cube mesh\n   * @param {number} [scale=1]\n   * @returns {external:THREE.Mesh}\n   * @private\n   */\n  __createCubemap(scale = 1) {\n    const cubeSize = SPHERE_RADIUS * 2 * scale;\n    const geometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize, CUBE_VERTICES, CUBE_VERTICES, CUBE_VERTICES);\n\n    const materials = [];\n    for (let i = 0; i < 6; i++) {\n      materials.push(new THREE.MeshBasicMaterial({\n        side: THREE.BackSide,\n      }));\n    }\n\n    const mesh = new THREE.Mesh(geometry, materials);\n    mesh.scale.set(1, 1, -1);\n\n    return mesh;\n  }\n\n  /**\n   * @summary Performs transition between the current and a new texture\n   * @param {PSV.TextureData} textureData\n   * @param {PSV.PanoramaOptions} options\n   * @returns {PSV.Animation}\n   * @package\n   */\n  transition(textureData, options) {\n    const { texture } = textureData;\n\n    let positionProvided = this.psv.dataHelper.isExtendedPosition(options);\n    const zoomProvided = 'zoom' in options;\n\n    let mesh;\n\n    if (this.prop.isCubemap) {\n      if (positionProvided) {\n        logWarn('cannot perform cubemap transition to different position');\n        positionProvided = false;\n      }\n\n      mesh = this.__createCubemap(0.9);\n\n      mesh.material.forEach((material, i) => {\n        material.map = texture[i];\n        material.transparent = true;\n        material.opacity = 0;\n      });\n    }\n    else {\n      mesh = this.__createSphere(0.9);\n\n      mesh.material.map = texture;\n      mesh.material.transparent = true;\n      mesh.material.opacity = 0;\n\n      if (options.sphereCorrection) {\n        this.setSphereCorrection(options.sphereCorrection, mesh);\n      }\n    }\n\n    // rotate the new sphere to make the target position face the camera\n    if (positionProvided) {\n      const cleanPosition = this.psv.dataHelper.cleanPosition(options);\n\n      // Longitude rotation along the vertical axis\n      const verticalAxis = new THREE.Vector3(0, 1, 0);\n      mesh.rotateOnWorldAxis(verticalAxis, cleanPosition.longitude - this.prop.position.longitude);\n\n      // Latitude rotation along the camera horizontal axis\n      const horizontalAxis = new THREE.Vector3(0, 1, 0).cross(this.camera.getWorldDirection(new THREE.Vector3())).normalize();\n      mesh.rotateOnWorldAxis(horizontalAxis, cleanPosition.latitude - this.prop.position.latitude);\n\n      // TODO: find a better way to handle ranges\n      if (this.config.latitudeRange || this.config.longitudeRange) {\n        this.config.longitudeRange = null;\n        this.config.latitudeRange = null;\n        logWarn('trying to perform transition with longitudeRange and/or latitudeRange, ranges cleared');\n      }\n    }\n\n    this.scene.add(mesh);\n    this.psv.needsUpdate();\n\n    return new Animation({\n      properties: {\n        opacity: { start: 0.0, end: 1.0 },\n        zoom   : zoomProvided ? { start: this.prop.zoomLvl, end: options.zoom } : undefined,\n      },\n      duration  : options.transition,\n      easing    : 'outCubic',\n      onTick    : (properties) => {\n        if (this.prop.isCubemap) {\n          for (let i = 0; i < 6; i++) {\n            mesh.material[i].opacity = properties.opacity;\n          }\n        }\n        else {\n          mesh.material.opacity = properties.opacity;\n        }\n\n        if (zoomProvided) {\n          this.psv.zoom(properties.zoom);\n        }\n\n        this.psv.needsUpdate();\n      },\n    })\n      .then(() => {\n        // remove temp sphere and transfer the texture to the main sphere\n        this.setTexture(textureData);\n        this.scene.remove(mesh);\n\n        mesh.geometry.dispose();\n        mesh.geometry = null;\n\n        if (options.sphereCorrection) {\n          this.setSphereCorrection(options.sphereCorrection);\n        }\n        else {\n          this.setSphereCorrection({});\n        }\n\n        // actually rotate the camera\n        if (positionProvided) {\n          this.psv.rotate(options);\n        }\n      });\n  }\n\n  /**\n   * @summary Calls `dispose` on all objects and textures\n   * @param {external:THREE.Object3D} object\n   * @private\n   */\n  __cleanTHREEScene(object) {\n    object.traverse((item) => {\n      if (item.geometry) {\n        item.geometry.dispose();\n      }\n\n      if (item.material) {\n        if (Array.isArray(item.material)) {\n          item.material.forEach((material) => {\n            if (material.map) {\n              material.map.dispose();\n            }\n\n            material.dispose();\n          });\n        }\n        else {\n          if (item.material.map) {\n            item.material.map.dispose();\n          }\n\n          item.material.dispose();\n        }\n      }\n\n      if (item.dispose && !(item instanceof THREE.Scene)) {\n        item.dispose();\n      }\n\n      if (item !== object) {\n        this.__cleanTHREEScene(item);\n      }\n    });\n  }\n\n}\n","import * as THREE from 'three';\nimport { CUBE_HASHMAP, CUBE_MAP } from '../data/constants';\nimport { SYSTEM } from '../data/system';\nimport { PSVError } from '../PSVError';\nimport { getXMPValue, logWarn, sum } from '../utils';\nimport { AbstractService } from './AbstractService';\n\n/**\n * @summary Texture loader\n * @extends PSV.services.AbstractService\n * @memberof PSV.services\n */\nexport class TextureLoader extends AbstractService {\n\n  /**\n   * @param {PSV.Viewer} psv\n   */\n  constructor(psv) {\n    super(psv);\n\n    /**\n     * @summary Current HTTP requests\n     * @type {XMLHttpRequest[]}\n     * @private\n     */\n    this.requests = [];\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    this.abortLoading();\n    super.destroy();\n  }\n\n  /**\n   * @summary Loads the panorama texture(s)\n   * @param {string|string[]|PSV.Cubemap} panorama\n   * @param {PSV.PanoData | PSV.PanoDataProvider} [newPanoData]\n   * @returns {Promise.<PSV.TextureData>}\n   * @throws {PSV.PSVError} when the image cannot be loaded\n   * @package\n   */\n  loadTexture(panorama, newPanoData) {\n    const tempPanorama = [];\n\n    if (Array.isArray(panorama)) {\n      if (panorama.length !== 6) {\n        throw new PSVError('Must provide exactly 6 image paths when using cubemap.');\n      }\n\n      // reorder images\n      for (let i = 0; i < 6; i++) {\n        tempPanorama[i] = panorama[CUBE_MAP[i]];\n      }\n\n      return this.__loadCubemapTexture(tempPanorama);\n    }\n    else if (typeof panorama === 'object') {\n      if (!CUBE_HASHMAP.every(side => !!panorama[side])) {\n        throw new PSVError('Must provide exactly left, front, right, back, top, bottom when using cubemap.');\n      }\n\n      // transform into array\n      CUBE_HASHMAP.forEach((side, i) => {\n        tempPanorama[i] = panorama[side];\n      });\n\n      return this.__loadCubemapTexture(tempPanorama);\n    }\n    else {\n      return this.__loadEquirectangularTexture(panorama, newPanoData);\n    }\n  }\n\n  /**\n   * @summary Cancels current HTTP requests\n   */\n  abortLoading() {\n    [...this.requests].forEach(r => r.abort());\n  }\n\n  /**\n   * @summary Loads a Blob with FileLoader\n   * @param {string} url\n   * @param {function(number)} [onProgress]\n   * @returns {Promise<Blob>}\n   * @private\n   */\n  __loadFile(url, onProgress) {\n    return new Promise((resolve, reject) => {\n      let progress = 0;\n      onProgress && onProgress(progress);\n\n      const loader = new THREE.FileLoader();\n\n      if (this.config.withCredentials) {\n        loader.setWithCredentials(true);\n      }\n\n      loader.setResponseType('blob');\n\n      const request = loader.load(\n        url,\n        (result) => {\n          const rIdx = this.requests.indexOf(request);\n          if (rIdx !== -1) this.requests.splice(rIdx, 1);\n\n          progress = 100;\n          onProgress && onProgress(progress);\n          resolve(result);\n        },\n        (e) => {\n          if (e.lengthComputable) {\n            const newProgress = e.loaded / e.total * 100;\n            if (newProgress > progress) {\n              progress = newProgress;\n              onProgress && onProgress(progress);\n            }\n          }\n        },\n        (err) => {\n          const rIdx = this.requests.indexOf(request);\n          if (rIdx !== -1) this.requests.splice(rIdx, 1);\n\n          reject(err);\n        }\n      );\n\n      // when we hit the cache, the result is the cache value\n      if (request instanceof XMLHttpRequest) {\n        this.requests.push(request);\n      }\n    });\n  }\n\n  /**\n   * @summary Loads an Image using FileLoader to have progress events\n   * @param {string} url\n   * @param {function(number)} [onProgress]\n   * @returns {Promise<Image>}\n   * @private\n   */\n  __loadImage(url, onProgress) {\n    return this.__loadFile(url, onProgress)\n      .then(result => new Promise((resolve, reject) => {\n        const img = document.createElementNS('http://www.w3.org/1999/xhtml', 'img');\n        img.onload = () => {\n          URL.revokeObjectURL(img.src);\n          resolve(img);\n        };\n        img.onerror = reject;\n        img.src = URL.createObjectURL(result);\n      }));\n  }\n\n  /**\n   * @summmary read a Blob as string\n   * @param {Blob} blob\n   * @returns {Promise<string>}\n   * @private\n   */\n  __loadBlobAsString(blob) {\n    return new Promise((resolve, reject) => {\n      const reader = new FileReader();\n      reader.onload = () => resolve(reader.result);\n      reader.onerror = reject;\n      reader.readAsText(blob);\n    });\n  }\n\n  /**\n   * @summary Loads the sphere texture\n   * @param {string} panorama\n   * @param {PSV.PanoData | PSV.PanoDataProvider} [newPanoData]\n   * @returns {Promise.<PSV.TextureData>}\n   * @throws {PSV.PSVError} when the image cannot be loaded\n   * @private\n   */\n  __loadEquirectangularTexture(panorama, newPanoData) {\n    /* eslint no-shadow: [\"error\", {allow: [\"newPanoData\"]}] */\n    if (this.prop.isCubemap === true) {\n      throw new PSVError('The viewer was initialized with an cubemap, cannot switch to equirectangular panorama.');\n    }\n\n    this.prop.isCubemap = false;\n\n    return (\n      newPanoData || !this.config.useXmpData\n        ? this.__loadImage(panorama, p => this.psv.loader.setProgress(p))\n          .then(img => ({ img, newPanoData }))\n        : this.__loadXMP(panorama, p => this.psv.loader.setProgress(p))\n          .then(newPanoData => this.__loadImage(panorama).then(img => ({ img, newPanoData })))\n    )\n      .then(({ img, newPanoData }) => {\n        if (typeof newPanoData === 'function') {\n          // eslint-disable-next-line no-param-reassign\n          newPanoData = newPanoData(img);\n        }\n\n        const panoData = newPanoData || {\n          fullWidth    : img.width,\n          fullHeight   : img.height,\n          croppedWidth : img.width,\n          croppedHeight: img.height,\n          croppedX     : 0,\n          croppedY     : 0,\n        };\n\n        if (panoData.croppedWidth !== img.width || panoData.croppedHeight !== img.height) {\n          logWarn(`Invalid panoData, croppedWidth and/or croppedHeight is not coherent with loaded image\n    panoData: ${panoData.croppedWidth}x${panoData.croppedHeight}, image: ${img.width}x${img.height}`);\n        }\n\n        const texture = this.__createEquirectangularTexture(img, panoData);\n\n        return { texture, panoData };\n      });\n  }\n\n  /**\n   * @summary Loads the XMP data of an image\n   * @param {string} panorama\n   * @param {function(number)} [onProgress]\n   * @returns {Promise<PSV.PanoData>}\n   * @throws {PSV.PSVError} when the image cannot be loaded\n   * @private\n   */\n  __loadXMP(panorama, onProgress) {\n    return this.__loadFile(panorama, onProgress)\n      .then(blob => this.__loadBlobAsString(blob))\n      .then((binary) => {\n        const a = binary.indexOf('<x:xmpmeta');\n        const b = binary.indexOf('</x:xmpmeta>');\n        const data = binary.substring(a, b);\n        let panoData = null;\n\n        if (a !== -1 && b !== -1 && data.indexOf('GPano:') !== -1) {\n          panoData = {\n            fullWidth    : parseInt(getXMPValue(data, 'FullPanoWidthPixels'), 10),\n            fullHeight   : parseInt(getXMPValue(data, 'FullPanoHeightPixels'), 10),\n            croppedWidth : parseInt(getXMPValue(data, 'CroppedAreaImageWidthPixels'), 10),\n            croppedHeight: parseInt(getXMPValue(data, 'CroppedAreaImageHeightPixels'), 10),\n            croppedX     : parseInt(getXMPValue(data, 'CroppedAreaLeftPixels'), 10),\n            croppedY     : parseInt(getXMPValue(data, 'CroppedAreaTopPixels'), 10),\n          };\n\n          if (!panoData.fullWidth || !panoData.fullHeight || !panoData.croppedWidth || !panoData.croppedHeight) {\n            logWarn('invalid XMP data');\n            panoData = null;\n          }\n        }\n\n        return panoData;\n      });\n  }\n\n  /**\n   * @summary Creates the final texture from image and panorama data\n   * @param {Image} img\n   * @param {PSV.PanoData} panoData\n   * @returns {external:THREE.Texture}\n   * @private\n   */\n  __createEquirectangularTexture(img, panoData) {\n    let texture;\n\n    // resize image / fill cropped parts with black\n    if (panoData.fullWidth > SYSTEM.maxTextureWidth\n      || panoData.croppedWidth !== panoData.fullWidth\n      || panoData.croppedHeight !== panoData.fullHeight\n    ) {\n      const resizedPanoData = { ...panoData };\n\n      const ratio = SYSTEM.maxCanvasWidth / panoData.fullWidth;\n\n      resizedPanoData.fullWidth *= ratio;\n      resizedPanoData.fullHeight *= ratio;\n      resizedPanoData.croppedWidth *= ratio;\n      resizedPanoData.croppedHeight *= ratio;\n      resizedPanoData.croppedX *= ratio;\n      resizedPanoData.croppedY *= ratio;\n\n      const buffer = document.createElement('canvas');\n      buffer.width = resizedPanoData.fullWidth;\n      buffer.height = resizedPanoData.fullHeight;\n\n      const ctx = buffer.getContext('2d');\n      ctx.drawImage(img,\n        resizedPanoData.croppedX, resizedPanoData.croppedY,\n        resizedPanoData.croppedWidth, resizedPanoData.croppedHeight);\n\n      texture = new THREE.Texture(buffer);\n    }\n    else {\n      texture = new THREE.Texture(img);\n    }\n\n    texture.needsUpdate = true;\n    texture.minFilter = THREE.LinearFilter;\n    texture.generateMipmaps = false;\n\n    return texture;\n  }\n\n  /**\n   * @summary Load the six textures of the cube\n   * @param {string[]} panorama\n   * @returns {Promise.<PSV.TextureData>}\n   * @throws {PSV.PSVError} when the image cannot be loaded\n   * @private\n   */\n  __loadCubemapTexture(panorama) {\n    if (this.prop.isCubemap === false) {\n      throw new PSVError('The viewer was initialized with an equirectangular panorama, cannot switch to cubemap.');\n    }\n\n    if (this.config.fisheye) {\n      logWarn('fisheye effect with cubemap texture can generate distorsion');\n    }\n\n    this.prop.isCubemap = true;\n\n    const promises = [];\n    const progress = [0, 0, 0, 0, 0, 0];\n\n    for (let i = 0; i < 6; i++) {\n      promises.push(\n        this.__loadImage(panorama[i], (p) => {\n          progress[i] = p;\n          this.psv.loader.setProgress(sum(progress) / 6);\n        })\n          .then(img => this.__createCubemapTexture(img))\n      );\n    }\n\n    return Promise.all(promises)\n      .then(texture => ({ texture }));\n  }\n\n  /**\n   * @summary Creates the final texture from image\n   * @param {Image} img\n   * @returns {external:THREE.Texture}\n   * @private\n   */\n  __createCubemapTexture(img) {\n    let texture;\n\n    // resize image\n    if (img.width > SYSTEM.maxTextureWidth) {\n      const buffer = document.createElement('canvas');\n      const ratio = SYSTEM.maxCanvasWidth / img.width;\n\n      buffer.width = img.width * ratio;\n      buffer.height = img.height * ratio;\n\n      const ctx = buffer.getContext('2d');\n      ctx.drawImage(img, 0, 0, buffer.width, buffer.height);\n\n      texture = new THREE.Texture(buffer);\n    }\n    else {\n      texture = new THREE.Texture(img);\n    }\n\n    texture.needsUpdate = true;\n    texture.minFilter = THREE.LinearFilter;\n    texture.generateMipmaps = false;\n\n    return texture;\n  }\n\n  /**\n   * @summary Preload a panorama file without displaying it\n   * @param {string} panorama\n   * @returns {Promise}\n   */\n  preloadPanorama(panorama) {\n    return this.loadTexture(panorama);\n  }\n\n}\n","import { EVENTS } from '../data/constants';\nimport { PSVError } from '../PSVError';\nimport { addClasses, parsePosition } from '../utils';\nimport { AbstractComponent } from './AbstractComponent';\n\nconst LEFT_MAP = { 0: 'left', 0.5: 'center', 1: 'right' };\nconst TOP_MAP = { 0: 'top', 0.5: 'center', 1: 'bottom' };\nconst STATE = { NONE: 0, SHOWING: 1, HIDING: 2, READY: 3 };\n\n/**\n * @typedef {Object} PSV.components.Tooltip.Position\n * @summary Object defining the tooltip position\n * @property {number} top - Position of the tip of the arrow of the tooltip, in pixels\n * @property {number} left - Position of the tip of the arrow of the tooltip, in pixels\n * @property {string|string[]} [position='top center'] - Tooltip position toward it's arrow tip.\n *           Accepted values are combinations of `top`, `center`, `bottom` and `left`, `center`, `right`\n * @property {Object} [box] - Used when displaying a tooltip on a marker\n * @property {number} [box.width=0]\n * @property {number} [box.height=0]\n */\n\n/**\n * @typedef {PSV.components.Tooltip.Position} PSV.components.Tooltip.Config\n * @summary Object defining the tooltip configuration\n * @property {string} content - HTML content of the tooltip\n * @property {string} [className] - Additional CSS class added to the tooltip\n * @property {*} [data] - Userdata associated to the tooltip\n */\n\n/**\n * @summary Tooltip class\n * @extends PSV.components.AbstractComponent\n * @memberof PSV.components\n */\nexport class Tooltip extends AbstractComponent {\n\n  /**\n   * @param {PSV.Viewer} psv\n   * @param {{arrow: number, offset: number}} size\n   */\n  constructor(psv, size) {\n    super(psv, 'psv-tooltip');\n\n    /**\n     * @override\n     * @property {number} arrow\n     * @property {number} offset\n     * @property {number} width\n     * @property {number} height\n     * @property {string} pos\n     * @property {string} state\n     * @property {*} data\n     */\n    this.prop = {\n      ...this.prop,\n      ...size,\n      state : STATE.NONE,\n      width : 0,\n      height: 0,\n      pos   : '',\n      data  : null,\n    };\n\n    /**\n     * Tooltip content\n     * @member {HTMLElement}\n     * @readonly\n     * @private\n     */\n    this.content = document.createElement('div');\n    this.content.className = 'psv-tooltip-content';\n    this.container.appendChild(this.content);\n\n    /**\n     * Tooltip arrow\n     * @member {HTMLElement}\n     * @readonly\n     * @package\n     */\n    this.arrow = document.createElement('div');\n    this.arrow.className = 'psv-tooltip-arrow';\n    this.container.appendChild(this.arrow);\n\n    this.container.addEventListener('transitionend', this);\n\n    this.container.style.top = '-1000px';\n    this.container.style.left = '-1000px';\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    delete this.arrow;\n    delete this.content;\n\n    super.destroy();\n  }\n\n  /**\n   * @summary Handles events\n   * @param {Event} e\n   * @private\n   */\n  handleEvent(e) {\n    /* eslint-disable */\n    switch (e.type) {\n      // @formatter:off\n      case 'transitionend': this.__onTransitionEnd(e); break;\n      // @formatter:on\n    }\n    /* eslint-enable */\n  }\n\n  /**\n   * @override\n   */\n  toggle() {\n    throw new PSVError('Tooltip cannot be toggled');\n  }\n\n  /**\n   * @summary Displays the tooltip on the viewer\n   * Do not call this method directly, use {@link PSV.services.TooltipRenderer} instead.\n   * @param {PSV.components.Tooltip.Config} config\n   *\n   * @fires PSV.show-tooltip\n   * @throws {PSV.PSVError} when the configuration is incorrect\n   *\n   * @package\n   */\n  show(config) {\n    if (this.prop.state !== STATE.NONE) {\n      throw new PSVError('Initialized tooltip cannot be re-initialized');\n    }\n\n    if (config.className) {\n      addClasses(this.container, config.className);\n    }\n\n    this.content.innerHTML = config.content;\n\n    const rect = this.container.getBoundingClientRect();\n    this.prop.width = rect.right - rect.left;\n    this.prop.height = rect.bottom - rect.top;\n\n    this.prop.state = STATE.READY;\n\n    this.move(config);\n\n    this.prop.data = config.data;\n    this.prop.state = STATE.SHOWING;\n\n    this.psv.trigger(EVENTS.SHOW_TOOLTIP, this.prop.data, this);\n  }\n\n  /**\n   * @summary Moves the tooltip to a new position\n   * @param {PSV.components.Tooltip.Position} config\n   *\n   * @throws {PSV.PSVError} when the configuration is incorrect\n   */\n  move(config) {\n    if (this.prop.state !== STATE.SHOWING && this.prop.state !== STATE.READY) {\n      throw new PSVError('Uninitialized tooltip cannot be moved');\n    }\n\n    const t = this.container;\n    const a = this.arrow;\n\n    if (!config.position) {\n      config.position = ['top', 'center'];\n    }\n\n    // parse position\n    if (typeof config.position === 'string') {\n      const tempPos = parsePosition(config.position);\n\n      if (!(tempPos.x in LEFT_MAP) || !(tempPos.y in TOP_MAP)) {\n        throw new PSVError(`Unable to parse tooltip position \"${config.position}\"`);\n      }\n\n      config.position = [TOP_MAP[tempPos.y], LEFT_MAP[tempPos.x]];\n    }\n\n    if (config.position[0] === 'center' && config.position[1] === 'center') {\n      throw new PSVError('Unable to parse tooltip position \"center center\"');\n    }\n\n    // compute size\n    const style = {\n      posClass : config.position.slice(),\n      width    : this.prop.width,\n      height   : this.prop.height,\n      top      : 0,\n      left     : 0,\n      arrowTop : 0,\n      arrowLeft: 0,\n    };\n\n    // set initial position\n    this.__computeTooltipPosition(style, config);\n\n    // correct position if overflow\n    let refresh = false;\n    if (style.top < this.prop.offset) {\n      style.posClass[0] = 'bottom';\n      refresh = true;\n    }\n    else if (style.top + style.height > this.psv.prop.size.height - this.prop.offset) {\n      style.posClass[0] = 'top';\n      refresh = true;\n    }\n    if (style.left < this.prop.offset) {\n      style.posClass[1] = 'right';\n      refresh = true;\n    }\n    else if (style.left + style.width > this.psv.prop.size.width - this.prop.offset) {\n      style.posClass[1] = 'left';\n      refresh = true;\n    }\n    if (refresh) {\n      this.__computeTooltipPosition(style, config);\n    }\n\n    // apply position\n    t.style.top = style.top + 'px';\n    t.style.left = style.left + 'px';\n\n    a.style.top = style.arrowTop + 'px';\n    a.style.left = style.arrowLeft + 'px';\n\n    const newPos = style.posClass.join('-');\n    if (newPos !== this.prop.pos) {\n      t.classList.remove(`psv-tooltip--${this.prop.pos}`);\n\n      this.prop.pos = newPos;\n      t.classList.add(`psv-tooltip--${this.prop.pos}`);\n    }\n  }\n\n  /**\n   * @summary Hides the tooltip\n   * @fires PSV.hide-tooltip\n   */\n  hide() {\n    this.container.classList.remove('psv-tooltip--visible');\n    this.prop.state = STATE.HIDING;\n\n    this.psv.trigger(EVENTS.HIDE_TOOLTIP, this.prop.data);\n  }\n\n  /**\n   * @summary Finalize transition\n   * @param {TransitionEvent} e\n   * @private\n   */\n  __onTransitionEnd(e) {\n    if (e.propertyName === 'transform') {\n      switch (this.prop.state) {\n        case STATE.SHOWING:\n          this.container.classList.add('psv-tooltip--visible');\n          this.prop.state = STATE.READY;\n          break;\n\n        case STATE.HIDING:\n          this.prop.state = STATE.NONE;\n          this.destroy();\n          break;\n\n        default:\n          // nothing\n      }\n    }\n  }\n\n  /**\n   * @summary Computes the position of the tooltip and its arrow\n   * @param {Object} style\n   * @param {Object} config\n   * @private\n   */\n  __computeTooltipPosition(style, config) {\n    let topBottom = false;\n\n    if (!config.box) {\n      config.box = {\n        width : 0,\n        height: 0,\n      };\n    }\n\n    switch (style.posClass[0]) {\n      case 'bottom':\n        style.top = config.top + config.box.height + this.prop.offset + this.prop.arrow;\n        style.arrowTop = -this.prop.arrow * 2;\n        topBottom = true;\n        break;\n\n      case 'center':\n        style.top = config.top + config.box.height / 2 - style.height / 2;\n        style.arrowTop = style.height / 2 - this.prop.arrow;\n        break;\n\n      case 'top':\n        style.top = config.top - style.height - this.prop.offset - this.prop.arrow;\n        style.arrowTop = style.height;\n        topBottom = true;\n        break;\n\n      // no default\n    }\n\n    switch (style.posClass[1]) {\n      case 'right':\n        if (topBottom) {\n          style.left = config.left + config.box.width / 2 - this.prop.offset - this.prop.arrow;\n          style.arrowLeft = this.prop.offset;\n        }\n        else {\n          style.left = config.left + config.box.width + this.prop.offset + this.prop.arrow;\n          style.arrowLeft = -this.prop.arrow * 2;\n        }\n        break;\n\n      case 'center':\n        style.left = config.left + config.box.width / 2 - style.width / 2;\n        style.arrowLeft = style.width / 2 - this.prop.arrow;\n        break;\n\n      case 'left':\n        if (topBottom) {\n          style.left = config.left - style.width + config.box.width / 2 + this.prop.offset + this.prop.arrow;\n          style.arrowLeft = style.width - this.prop.offset - this.prop.arrow * 2;\n        }\n        else {\n          style.left = config.left - style.width - this.prop.offset - this.prop.arrow;\n          style.arrowLeft = style.width;\n        }\n        break;\n\n      // no default\n    }\n  }\n\n}\n","import { Tooltip } from '../components/Tooltip';\nimport { getStyle } from '../utils';\nimport { AbstractService } from './AbstractService';\n\n/**\n * @summary Tooltip renderer\n * @extends PSV.services.AbstractService\n * @memberof PSV.services\n */\nexport class TooltipRenderer extends AbstractService {\n\n  /**\n   * @param {PSV.Viewer} psv\n   */\n  constructor(psv) {\n    super(psv);\n\n    const testTooltip = new Tooltip(this.psv);\n\n    /**\n     * @summary Computed static sizes\n     * @member {Object}\n     * @package\n     * @property {number} arrowSize\n     * @property {number} offset\n     */\n    this.size = {\n      arrow : parseInt(getStyle(testTooltip.arrow, 'borderTopWidth'), 10),\n      offset: parseInt(getStyle(testTooltip.container, 'outlineWidth'), 10),\n    };\n\n    testTooltip.destroy();\n  }\n\n  /**\n   * @override\n   */\n  destroy() {\n    delete this.size;\n\n    super.destroy();\n  }\n\n  /**\n   * @summary Displays a tooltip on the viewer\n   * @param {PSV.components.Tooltip.Config} config\n   * @returns {PSV.components.Tooltip}\n   *\n   * @fires PSV.show-tooltip\n   * @throws {PSV.PSVError} when the configuration is incorrect\n   *\n   * @example\n   * viewer.tooltip.create({ content: 'Hello world', top: 200, left: 450, position: 'center bottom'})\n   */\n  create(config) {\n    const tooltip = new Tooltip(this.psv, this.size);\n    tooltip.show(config);\n\n    return tooltip;\n  }\n\n}\n","import * as THREE from 'three';\nimport { EventEmitter } from 'uevent';\nimport { Animation } from './Animation';\nimport { Loader } from './components/Loader';\nimport { Navbar } from './components/Navbar';\nimport { Notification } from './components/Notification';\nimport { Overlay } from './components/Overlay';\nimport { Panel } from './components/Panel';\nimport { CONFIG_PARSERS, DEFAULTS, getConfig, READONLY_OPTIONS } from './data/config';\nimport { CHANGE_EVENTS, EVENTS, IDS, VIEWER_DATA } from './data/constants';\nimport { SYSTEM } from './data/system';\nimport errorIcon from './icons/error.svg';\nimport { PSVError } from './PSVError';\nimport { DataHelper } from './services/DataHelper';\nimport { EventsHandler } from './services/EventsHandler';\nimport { Renderer } from './services/Renderer';\nimport { TextureLoader } from './services/TextureLoader';\nimport { TooltipRenderer } from './services/TooltipRenderer';\nimport {\n  bound,\n  each,\n  exitFullscreen,\n  getAngle,\n  getShortestArc,\n  isFullscreenEnabled,\n  requestFullscreen,\n  throttle,\n  toggleClass\n} from './utils';\n\nTHREE.Cache.enabled = true;\n\n/**\n * @summary Main class\n * @memberOf PSV\n * @extends {external:uEvent.EventEmitter}\n */\nexport class Viewer extends EventEmitter {\n\n  /**\n   * @param {PSV.Options} options\n   * @fires PSV.ready\n   * @throws {PSV.PSVError} when the configuration is incorrect\n   */\n  constructor(options) {\n    super();\n\n    SYSTEM.load();\n\n    // must support WebGL\n    if (!SYSTEM.isWebGLSupported) {\n      throw new PSVError('WebGL is not supported.');\n    }\n\n    if (SYSTEM.maxCanvasWidth === 0 || SYSTEM.maxTextureWidth === 0) {\n      throw new PSVError('Unable to detect system capabilities');\n    }\n\n    /**\n     * @summary Internal properties\n     * @member {Object}\n     * @protected\n     * @property {boolean} ready - when all components are loaded\n     * @property {boolean} needsUpdate - if the view needs to be renderer\n     * @property {boolean} isCubemap - if the panorama is a cubemap\n     * @property {PSV.Position} position - current direction of the camera\n     * @property {external:THREE.Vector3} direction - direction of the camera\n     * @property {number} zoomLvl - current zoom level\n     * @property {number} vFov - vertical FOV\n     * @property {number} hFov - horizontal FOV\n     * @property {number} aspect - viewer aspect ratio\n     * @property {number} moveSpeed - move speed (computed with pixel ratio and configuration moveSpeed)\n     * @property {Function} autorotateCb - update callback of the automatic rotation\n     * @property {PSV.Animation} animationPromise - promise of the current animation (either go to position or image transition)\n     * @property {Promise} loadingPromise - promise of the setPanorama method\n     * @property startTimeout - timeout id of the automatic rotation delay\n     * @property {PSV.Size} size - size of the container\n     * @property {PSV.PanoData} panoData - panorama metadata\n     */\n    this.prop = {\n      ready           : false,\n      uiRefresh       : false,\n      needsUpdate     : false,\n      fullscreen      : false,\n      isCubemap       : undefined,\n      position        : {\n        longitude: 0,\n        latitude : 0,\n      },\n      direction       : null,\n      zoomLvl         : null,\n      vFov            : null,\n      hFov            : null,\n      aspect          : null,\n      moveSpeed       : 0.1,\n      autorotateCb    : null,\n      animationPromise: null,\n      loadingPromise  : null,\n      startTimeout    : null,\n      size            : {\n        width : 0,\n        height: 0,\n      },\n      panoData        : {\n        fullWidth    : 0,\n        fullHeight   : 0,\n        croppedWidth : 0,\n        croppedHeight: 0,\n        croppedX     : 0,\n        croppedY     : 0,\n      },\n    };\n\n    /**\n     * @summary Configuration holder\n     * @type {PSV.Options}\n     * @readonly\n     */\n    this.config = getConfig(options);\n\n    /**\n     * @summary Top most parent\n     * @member {HTMLElement}\n     * @readonly\n     */\n    this.parent = (typeof options.container === 'string') ? document.getElementById(options.container) : options.container;\n    this.parent[VIEWER_DATA] = this;\n\n    /**\n     * @summary Main container\n     * @member {HTMLElement}\n     * @readonly\n     */\n    this.container = document.createElement('div');\n    this.container.classList.add('psv-container');\n    this.parent.appendChild(this.container);\n\n    /**\n     * @summary All child components\n     * @type {PSV.components.AbstractComponent[]}\n     * @readonly\n     * @package\n     */\n    this.children = [];\n\n    /**\n     * @summary All plugins\n     * @type {Object<string, PSV.plugins.AbstractPlugin>}\n     * @readonly\n     * @package\n     */\n    this.plugins = {};\n\n    /**\n     * @summary Main render controller\n     * @type {PSV.services.Renderer}\n     * @readonly\n     */\n    this.renderer = new Renderer(this);\n\n    /**\n     * @summary Textures loader\n     * @type {PSV.services.TextureLoader}\n     * @readonly\n     */\n    this.textureLoader = new TextureLoader(this);\n\n    /**\n     * @summary Main event handler\n     * @type {PSV.services.EventsHandler}\n     * @readonly\n     */\n    this.eventsHandler = new EventsHandler(this);\n\n    /**\n     * @summary Utilities to help converting data\n     * @type {PSV.services.DataHelper}\n     * @readonly\n     */\n    this.dataHelper = new DataHelper(this);\n\n    /**\n     * @member {PSV.components.Loader}\n     * @readonly\n     */\n    this.loader = new Loader(this);\n\n    /**\n     * @member {PSV.components.Navbar}\n     * @readonly\n     */\n    this.navbar = new Navbar(this);\n\n    /**\n     * @member {PSV.components.Panel}\n     * @readonly\n     */\n    this.panel = new Panel(this);\n\n    /**\n     * @member {PSV.services.TooltipRenderer}\n     * @readonly\n     */\n    this.tooltip = new TooltipRenderer(this);\n\n    /**\n     * @member {PSV.components.Notification}\n     * @readonly\n     */\n    this.notification = new Notification(this);\n\n    /**\n     * @member {PSV.components.Overlay}\n     * @readonly\n     */\n    this.overlay = new Overlay(this);\n\n    this.eventsHandler.init();\n\n    this.__resizeRefresh = throttle(() => this.refreshUi('resize'), 500);\n\n    // apply container size\n    this.resize(this.config.size);\n\n    // actual move speed depends on pixel-ratio\n    this.prop.moveSpeed = THREE.Math.degToRad(this.config.moveSpeed / SYSTEM.pixelRatio);\n\n    // init plugins\n    this.config.plugins.forEach(([plugin, opts]) => {\n      this.plugins[plugin.id] = new plugin(this, opts); // eslint-disable-line new-cap\n    });\n\n    // init buttons\n    this.navbar.setButtons(this.config.navbar);\n\n    // load panorama\n    if (this.config.panorama) {\n      this.setPanorama(this.config.panorama);\n    }\n\n    SYSTEM.isTouchEnabled.then(enabled => toggleClass(this.container, 'psv--is-touch', enabled));\n\n    // enable GUI after first render\n    this.once(EVENTS.RENDER, () => {\n      if (this.config.navbar) {\n        this.container.classList.add('psv--has-navbar');\n        this.navbar.show();\n      }\n\n      // Queue autorotate\n      if (this.config.autorotateDelay) {\n        this.prop.startTimeout = setTimeout(() => this.startAutorotate(), this.config.autorotateDelay);\n      }\n\n      this.prop.ready = true;\n\n      setTimeout(() => {\n        this.refreshUi('init');\n\n        this.trigger(EVENTS.READY);\n      }, 0);\n    });\n  }\n\n  /**\n   * @summary Destroys the viewer\n   * @description The memory used by the ThreeJS context is not totally cleared. This will be fixed as soon as possible.\n   */\n  destroy() {\n    this.__stopAll();\n    this.stopKeyboardControl();\n    this.exitFullscreen();\n\n    this.eventsHandler.destroy();\n    this.renderer.destroy();\n    this.textureLoader.destroy();\n    this.dataHelper.destroy();\n\n    this.children.slice().forEach(child => child.destroy());\n    this.children.length = 0;\n\n    each(this.plugins, plugin => plugin.destroy());\n    delete this.plugins;\n\n    this.parent.removeChild(this.container);\n    delete this.parent[VIEWER_DATA];\n\n    delete this.parent;\n    delete this.container;\n\n    delete this.loader;\n    delete this.navbar;\n    delete this.panel;\n    delete this.tooltip;\n    delete this.notification;\n    delete this.overlay;\n\n    delete this.config;\n  }\n\n  /**\n   * @summary Refresh UI\n   * @package\n   */\n  refreshUi(reason) {\n    if (!this.prop.ready) {\n      return;\n    }\n\n    if (!this.prop.uiRefresh) {\n      // console.log(`PhotoSphereViewer: UI Refresh, ${reason}`);\n\n      this.prop.uiRefresh = true;\n\n      this.children.every((child) => {\n        child.refreshUi();\n        return this.prop.uiRefresh === true;\n      });\n\n      this.prop.uiRefresh = false;\n    }\n    else if (this.prop.uiRefresh !== 'new') {\n      this.prop.uiRefresh = 'new';\n\n      // wait for current refresh to cancel\n      setTimeout(() => {\n        this.prop.uiRefresh = false;\n        this.refreshUi(reason);\n      });\n    }\n  }\n\n  /**\n   * @summary Returns the instance of a plugin if it exists\n   * @param {Class<PSV.plugins.AbstractPlugin>|string} pluginId\n   * @returns {PSV.plugins.AbstractPlugin}\n   */\n  getPlugin(pluginId) {\n    return pluginId ? this.plugins[typeof pluginId === 'function' ? pluginId.id : pluginId] : null;\n  }\n\n  /**\n   * @summary Returns the current position of the camera\n   * @returns {PSV.Position}\n   */\n  getPosition() {\n    return {\n      longitude: this.prop.position.longitude,\n      latitude : this.prop.position.latitude,\n    };\n  }\n\n  /**\n   * @summary Returns the current zoom level\n   * @returns {number}\n   */\n  getZoomLevel() {\n    return this.prop.zoomLvl;\n  }\n\n  /**\n   * @summary Returns the current viewer size\n   * @returns {PSV.Size}\n   */\n  getSize() {\n    return {\n      width : this.prop.size.width,\n      height: this.prop.size.height,\n    };\n  }\n\n  /**\n   * @summary Checks if the automatic rotation is enabled\n   * @returns {boolean}\n   */\n  isAutorotateEnabled() {\n    return !!this.prop.autorotateCb;\n  }\n\n  /**\n   * @summary Checks if the viewer is in fullscreen\n   * @returns {boolean}\n   */\n  isFullscreenEnabled() {\n    if (SYSTEM.fullscreenEvent) {\n      return isFullscreenEnabled(this.container);\n    }\n    else {\n      return this.prop.fullscreen;\n    }\n  }\n\n  /**\n   * @summary Flags the view has changed for the next render\n   */\n  needsUpdate() {\n    this.prop.needsUpdate = true;\n\n    if (!this.renderer.mainReqid && this.renderer.renderer) {\n      this.renderer.__renderLoop(+new Date());\n    }\n  }\n\n  /**\n   * @summary Resizes the canvas when the window is resized\n   * @fires PSV.size-updated\n   */\n  autoSize() {\n    if (this.container.clientWidth !== this.prop.size.width || this.container.clientHeight !== this.prop.size.height) {\n      this.prop.size.width = Math.round(this.container.clientWidth);\n      this.prop.size.height = Math.round(this.container.clientHeight);\n      this.prop.aspect = this.prop.size.width / this.prop.size.height;\n      this.prop.hFov = this.dataHelper.vFovToHFov(this.prop.vFov);\n\n      this.needsUpdate();\n      this.trigger(EVENTS.SIZE_UPDATED, this.getSize());\n      this.__resizeRefresh();\n    }\n  }\n\n  /**\n   * @summary Loads a new panorama file\n   * @description Loads a new panorama file, optionally changing the camera position/zoom and activating the transition animation.<br>\n   * If the \"options\" parameter is not defined, the camera will not move and the ongoing animation will continue.<br>\n   * If another loading is already in progress it will be aborted.\n   * @param {string|string[]|PSV.Cubemap} path - URL of the new panorama file\n   * @param {PSV.PanoramaOptions} [options]\n   * @returns {Promise}\n   */\n  setPanorama(path, options = {}) {\n    if (this.prop.loadingPromise !== null) {\n      this.textureLoader.abortLoading();\n    }\n\n    if (!this.prop.ready) {\n      if (!('longitude' in options) && !this.prop.isCubemap) {\n        options.longitude = this.config.defaultLong;\n      }\n      if (!('latitude' in options) && !this.prop.isCubemap) {\n        options.latitude = this.config.defaultLat;\n      }\n      if (!('zoom' in options)) {\n        options.zoom = this.config.defaultZoomLvl;\n      }\n      if (!('sphereCorrection' in options)) {\n        options.sphereCorrection = this.config.sphereCorrection;\n      }\n      if (!('panoData' in options)) {\n        options.panoData = this.config.panoData;\n      }\n    }\n\n    if (options.transition === undefined || options.transition === true) {\n      options.transition = 1500;\n    }\n    if (options.showLoader === undefined) {\n      options.showLoader = true;\n    }\n\n    const positionProvided = this.dataHelper.isExtendedPosition(options);\n    const zoomProvided = 'zoom' in options;\n\n    if (positionProvided || zoomProvided) {\n      this.__stopAll();\n    }\n\n    this.hideError();\n\n    this.config.panorama = path;\n\n    const done = (err) => {\n      if (err && err.type === 'abort') {\n        console.warn(err);\n      }\n      else if (err) {\n        this.showError(this.config.lang.loadError);\n        console.error(err);\n      }\n\n      this.loader.hide();\n      this.renderer.show();\n\n      this.prop.loadingPromise = null;\n\n      if (err) {\n        return Promise.reject(err);\n      }\n      else {\n        return true;\n      }\n    };\n\n    if (!options.transition || !this.prop.ready) {\n      if (options.showLoader || !this.prop.ready) {\n        this.loader.show();\n      }\n\n      this.prop.loadingPromise = this.textureLoader.loadTexture(this.config.panorama, options.panoData)\n        .then((textureData) => {\n          this.renderer.setTexture(textureData);\n\n          if (options.sphereCorrection) {\n            this.renderer.setSphereCorrection(options.sphereCorrection);\n          }\n          if (zoomProvided) {\n            this.zoom(options.zoom);\n          }\n          if (positionProvided) {\n            this.rotate(options);\n          }\n        })\n        .then(done, done);\n    }\n    else {\n      if (options.showLoader) {\n        this.loader.show();\n      }\n\n      this.prop.loadingPromise = this.textureLoader.loadTexture(this.config.panorama)\n        .then((textureData) => {\n          this.loader.hide();\n\n          return this.renderer.transition(textureData, options);\n        })\n        .then(done, done);\n    }\n\n    return this.prop.loadingPromise;\n  }\n\n  /**\n   * @summary Update options\n   * @param {PSV.Options} options\n   * @fires PSV.config-changed\n   */\n  setOptions(options) {\n    each(options, (value, key) => {\n      if (!Object.prototype.hasOwnProperty.call(DEFAULTS, key)) {\n        throw new PSVError(`Unknown option ${key}`);\n      }\n\n      if (READONLY_OPTIONS[key]) {\n        throw new PSVError(READONLY_OPTIONS[key]);\n      }\n\n      if (CONFIG_PARSERS[key]) {\n        this.config[key] = CONFIG_PARSERS[key](value, options);\n      }\n      else {\n        this.config[key] = value;\n      }\n\n      switch (key) {\n        case 'caption':\n          this.navbar.setCaption(value);\n          break;\n\n        case 'size':\n          this.resize(value);\n          break;\n\n        case 'sphereCorrection':\n          this.renderer.setSphereCorrection(value);\n          break;\n\n        case 'navbar':\n        case 'lang':\n          this.navbar.setButtons(this.config.navbar);\n          break;\n\n        case 'moveSpeed':\n          this.prop.moveSpeed = THREE.Math.degToRad(value / SYSTEM.pixelRatio);\n          break;\n\n        case 'minFov':\n        case 'maxFov':\n          this.prop.zoomLvl = this.dataHelper.fovToZoomLevel(this.prop.vFov);\n          this.trigger(EVENTS.ZOOM_UPDATED, this.getZoomLevel());\n          break;\n\n        default:\n          break;\n      }\n    });\n\n    this.needsUpdate();\n    this.refreshUi('set options');\n\n    this.trigger(EVENTS.CONFIG_CHANGED, Object.keys(options));\n  }\n\n  /**\n   * @summary Update options\n   * @param {string} option\n   * @param {any} value\n   * @fires PSV.config-changed\n   */\n  setOption(option, value) {\n    this.setOptions({ [option]: value });\n  }\n\n  /**\n   * @summary Starts the automatic rotation\n   * @fires PSV.autorotate\n   */\n  startAutorotate() {\n    this.__stopAll();\n\n    this.prop.autorotateCb = (() => {\n      let last;\n      let elapsed;\n\n      return (e, timestamp) => {\n        elapsed = last === undefined ? 0 : timestamp - last;\n        last = timestamp;\n\n        this.rotate({\n          longitude: this.prop.position.longitude + this.config.autorotateSpeed * elapsed / 1000,\n          latitude : this.prop.position.latitude - (this.prop.position.latitude - this.config.autorotateLat) / 200,\n        });\n      };\n    })();\n\n    this.on(EVENTS.BEFORE_RENDER, this.prop.autorotateCb);\n\n    this.trigger(EVENTS.AUTOROTATE, true);\n  }\n\n  /**\n   * @summary Stops the automatic rotation\n   * @fires PSV.autorotate\n   */\n  stopAutorotate() {\n    if (this.prop.startTimeout) {\n      clearTimeout(this.prop.startTimeout);\n      this.prop.startTimeout = null;\n    }\n\n    if (this.isAutorotateEnabled()) {\n      this.off(EVENTS.BEFORE_RENDER, this.prop.autorotateCb);\n      this.prop.autorotateCb = null;\n\n      this.trigger(EVENTS.AUTOROTATE, false);\n    }\n  }\n\n  /**\n   * @summary Starts or stops the automatic rotation\n   * @fires PSV.autorotate\n   */\n  toggleAutorotate() {\n    if (this.isAutorotateEnabled()) {\n      this.stopAutorotate();\n    }\n    else {\n      this.startAutorotate();\n    }\n  }\n\n  /**\n   * @summary Displays an error message\n   * @param {string} message\n   */\n  showError(message) {\n    this.overlay.show({\n      id         : IDS.ERROR,\n      image      : errorIcon,\n      text       : message,\n      dissmisable: false,\n    });\n  }\n\n  /**\n   * @summary Hides the error message\n   */\n  hideError() {\n    this.overlay.hide(IDS.ERROR);\n  }\n\n  /**\n   * @summary Rotates the view to specific longitude and latitude\n   * @param {PSV.ExtendedPosition} position\n   * @fires PSV.before-rotate\n   * @fires PSV.position-updated\n   */\n  rotate(position) {\n    const e = this.trigger(EVENTS.BEFORE_ROTATE, position);\n    if (e.isDefaultPrevented()) {\n      return;\n    }\n\n    const cleanPosition = this.change(CHANGE_EVENTS.GET_ROTATE_POSITION, this.dataHelper.cleanPosition(position));\n\n    if (this.prop.position.longitude !== cleanPosition.longitude || this.prop.position.latitude !== cleanPosition.latitude) {\n      this.prop.position.longitude = cleanPosition.longitude;\n      this.prop.position.latitude = cleanPosition.latitude;\n\n      this.needsUpdate();\n\n      this.trigger(EVENTS.POSITION_UPDATED, this.getPosition());\n    }\n  }\n\n  /**\n   * @summary Rotates and zooms the view with a smooth animation\n   * @param {PSV.AnimateOptions} options - position and/or zoom level\n   * @returns {PSV.Animation}\n   */\n  animate(options) {\n    this.__stopAll();\n\n    const positionProvided = this.dataHelper.isExtendedPosition(options);\n    const zoomProvided = 'zoom' in options;\n\n    const animProperties = {};\n    let duration;\n\n    // clean/filter position and compute duration\n    if (positionProvided) {\n      const cleanPosition = this.change(CHANGE_EVENTS.GET_ANIMATE_POSITION, this.dataHelper.cleanPosition(options));\n\n      // longitude offset for shortest arc\n      const tOffset = getShortestArc(this.prop.position.longitude, cleanPosition.longitude);\n\n      animProperties.longitude = { start: this.prop.position.longitude, end: this.prop.position.longitude + tOffset };\n      animProperties.latitude = { start: this.prop.position.latitude, end: cleanPosition.latitude };\n\n      duration = this.dataHelper.speedToDuration(options.speed, getAngle(this.prop.position, cleanPosition));\n    }\n\n    // clean/filter zoom and compute duration\n    if (zoomProvided) {\n      const dZoom = Math.abs(options.zoom - this.prop.zoomLvl);\n\n      animProperties.zoom = { start: this.prop.zoomLvl, end: options.zoom };\n\n      if (!duration) {\n        // if animating zoom only and a speed is given, use an arbitrary PI/4 to compute the duration\n        duration = this.dataHelper.speedToDuration(options.speed, Math.PI / 4 * dZoom / 100);\n      }\n    }\n\n    // if no animation needed\n    if (!duration) {\n      if (positionProvided) {\n        this.rotate(options);\n      }\n      if (zoomProvided) {\n        this.zoom(options.zoom);\n      }\n\n      return Animation.resolve();\n    }\n\n    this.prop.animationPromise = new Animation({\n      properties: animProperties,\n      duration  : duration,\n      easing    : 'inOutSine',\n      onTick    : (properties) => {\n        if (positionProvided) {\n          this.rotate(properties);\n        }\n        if (zoomProvided) {\n          this.zoom(properties.zoom);\n        }\n      },\n    });\n\n    return this.prop.animationPromise;\n  }\n\n  /**\n   * @summary Stops the ongoing animation\n   * @description The return value is a Promise because the is no guaranty the animation can be stopped synchronously.\n   * @returns {Promise} Resolved when the animation has ben cancelled\n   */\n  stopAnimation() {\n    if (this.prop.animationPromise) {\n      return new Promise((resolve) => {\n        this.prop.animationPromise.finally(resolve);\n        this.prop.animationPromise.cancel();\n        this.prop.animationPromise = null;\n      });\n    }\n    else {\n      return Promise.resolve();\n    }\n  }\n\n  /**\n   * @summary Zooms to a specific level between `max_fov` and `min_fov`\n   * @param {number} level - new zoom level from 0 to 100\n   * @fires PSV.zoom-updated\n   */\n  zoom(level) {\n    const newZoomLvl = bound(level, 0, 100);\n\n    if (this.prop.zoomLvl !== newZoomLvl) {\n      this.prop.zoomLvl = newZoomLvl;\n      this.prop.vFov = this.dataHelper.zoomLevelToFov(this.prop.zoomLvl);\n      this.prop.hFov = this.dataHelper.vFovToHFov(this.prop.vFov);\n\n      this.needsUpdate();\n      this.trigger(EVENTS.ZOOM_UPDATED, this.getZoomLevel());\n      this.rotate(this.prop.position);\n    }\n  }\n\n  /**\n   * @summary Increases the zoom level by 1\n   */\n  zoomIn() {\n    this.zoom(this.prop.zoomLvl + this.config.zoomButtonIncrement);\n  }\n\n  /**\n   * @summary Decreases the zoom level by 1\n   */\n  zoomOut() {\n    this.zoom(this.prop.zoomLvl - this.config.zoomButtonIncrement);\n  }\n\n  /**\n   * @summary Resizes the viewer\n   * @param {PSV.CssSize} size\n   */\n  resize(size) {\n    ['width', 'height'].forEach((dim) => {\n      if (size && size[dim]) {\n        if (/^[0-9.]+$/.test(size[dim])) {\n          size[dim] += 'px';\n        }\n        this.parent.style[dim] = size[dim];\n      }\n    });\n\n    this.autoSize();\n  }\n\n  /**\n   * @summary Enters the fullscreen mode\n   * @fires PSV.fullscreen-updated\n   */\n  enterFullscreen() {\n    if (SYSTEM.fullscreenEvent) {\n      requestFullscreen(this.container);\n    }\n    else {\n      this.container.classList.add('psv-container--fullscreen');\n      this.autoSize();\n      this.eventsHandler.__fullscreenToggled(true);\n    }\n  }\n\n  /**\n   * @summary Exits the fullscreen mode\n   * @fires PSV.fullscreen-updated\n   */\n  exitFullscreen() {\n    if (this.isFullscreenEnabled()) {\n      if (SYSTEM.fullscreenEvent) {\n        exitFullscreen();\n      }\n      else {\n        this.container.classList.remove('psv-container--fullscreen');\n        this.autoSize();\n        this.eventsHandler.__fullscreenToggled(false);\n      }\n    }\n  }\n\n  /**\n   * @summary Enters or exits the fullscreen mode\n   * @fires PSV.fullscreen-updated\n   */\n  toggleFullscreen() {\n    if (!this.isFullscreenEnabled()) {\n      this.enterFullscreen();\n    }\n    else {\n      this.exitFullscreen();\n    }\n  }\n\n  /**\n   * @summary Enables the keyboard controls (done automatically when entering fullscreen)\n   */\n  startKeyboardControl() {\n    this.eventsHandler.enableKeyboard();\n  }\n\n  /**\n   * @summary Disables the keyboard controls (done automatically when exiting fullscreen)\n   */\n  stopKeyboardControl() {\n    this.eventsHandler.disableKeyboard();\n  }\n\n  /**\n   * @summary Stops all current animations\n   * @private\n   */\n  __stopAll() {\n    this.stopAutorotate();\n    this.stopAnimation();\n\n    this.trigger(EVENTS.STOP_ALL);\n  }\n\n}\n"]}