{"version":3,"file":"jarallax-video.min.js","sources":["../node_modules/video-worker/dist/video-worker.esm.js","../src/utils/global.js","../src/utils/ready.js","../src/ext-video.js","../src/ext-video.umd.js"],"sourcesContent":["/*!\n * Video Worker v2.2.0 (https://github.com/nk-o/video-worker)\n * Copyright 2024 nK <https://nkdev.info>\n * Licensed under MIT (https://github.com/nk-o/video-worker/blob/master/LICENSE)\n */\n\nvar defaults = {\n  autoplay: false,\n  loop: false,\n  mute: false,\n  volume: 100,\n  showControls: true,\n  accessibilityHidden: false,\n  // start / end video time in seconds\n  startTime: 0,\n  endTime: 0\n};\n\n/**\n * Extend like jQuery.extend\n *\n * @param {Object} out - output object.\n * @param {...any} args - additional objects to extend.\n *\n * @returns {Object}\n */\nfunction extend(out, ...args) {\n  out = out || {};\n  Object.keys(args).forEach(i => {\n    if (!args[i]) {\n      return;\n    }\n    Object.keys(args[i]).forEach(key => {\n      out[key] = args[i][key];\n    });\n  });\n  return out;\n}\n\nlet ID = 0;\nclass VideoWorkerBase {\n  type = 'none';\n  constructor(url, options) {\n    const self = this;\n    self.url = url;\n    self.options_default = {\n      ...defaults\n    };\n    self.options = extend({}, self.options_default, options);\n\n    // check URL\n    self.videoID = self.constructor.parseURL(url);\n\n    // init\n    if (self.videoID) {\n      self.init();\n    }\n  }\n  isValid() {\n    return !!this.videoID;\n  }\n  init() {\n    const self = this;\n    self.ID = ID;\n    ID += 1;\n    self.playerID = `VideoWorker-${self.ID}`;\n  }\n\n  // events\n  on(name, callback) {\n    this.userEventsList = this.userEventsList || [];\n\n    // add new callback in events list\n    (this.userEventsList[name] || (this.userEventsList[name] = [])).push(callback);\n  }\n  off(name, callback) {\n    if (!this.userEventsList || !this.userEventsList[name]) {\n      return;\n    }\n    if (!callback) {\n      delete this.userEventsList[name];\n    } else {\n      this.userEventsList[name].forEach((val, key) => {\n        if (val === callback) {\n          this.userEventsList[name][key] = false;\n        }\n      });\n    }\n  }\n  fire(name, ...args) {\n    if (this.userEventsList && typeof this.userEventsList[name] !== 'undefined') {\n      this.userEventsList[name].forEach(val => {\n        // call with all arguments\n        if (val) {\n          val.apply(this, args);\n        }\n      });\n    }\n  }\n\n  /**\n   * Methods used in providers.\n   */\n  /* eslint-disable */\n  static parseURL(url) {\n    return false;\n  }\n  play(start) {}\n  pause() {}\n  mute() {}\n  unmute() {}\n  setVolume(volume = false) {}\n  getVolume(callback) {}\n  getMuted(callback) {}\n  setCurrentTime(currentTime = false) {}\n  getCurrentTime(callback) {}\n  getImageURL(callback) {}\n  getVideo(callback) {}\n  /* eslint-enable */\n}\n\n/* eslint-disable import/no-mutable-exports */\n/* eslint-disable no-restricted-globals */\nlet win;\nif (typeof window !== 'undefined') {\n  win = window;\n} else if (typeof global !== 'undefined') {\n  win = global;\n} else if (typeof self !== 'undefined') {\n  win = self;\n} else {\n  win = {};\n}\nvar global$1 = win;\n\n// Deferred\n// thanks http://stackoverflow.com/questions/18096715/implement-deferred-object-without-using-jquery\nfunction Deferred() {\n  this.doneCallbacks = [];\n  this.failCallbacks = [];\n}\nDeferred.prototype = {\n  execute(list, args) {\n    let i = list.length;\n    // eslint-disable-next-line no-param-reassign\n    args = Array.prototype.slice.call(args);\n    while (i) {\n      i -= 1;\n      list[i].apply(null, args);\n    }\n  },\n  resolve(...args) {\n    this.execute(this.doneCallbacks, args);\n  },\n  reject(...args) {\n    this.execute(this.failCallbacks, args);\n  },\n  done(callback) {\n    this.doneCallbacks.push(callback);\n  },\n  fail(callback) {\n    this.failCallbacks.push(callback);\n  }\n};\n\nlet YoutubeAPIadded = 0;\nlet loadingYoutubePlayer = 0;\nconst loadingYoutubeDefer = /*#__PURE__*/new Deferred();\nfunction loadAPI$1() {\n  if (YoutubeAPIadded) {\n    return;\n  }\n  YoutubeAPIadded = true;\n  const src = 'https://www.youtube.com/iframe_api';\n\n  // add script in head section\n  let tag = document.createElement('script');\n  let head = document.getElementsByTagName('head')[0];\n  tag.src = src;\n  head.appendChild(tag);\n  head = null;\n  tag = null;\n}\nfunction onAPIready$1(callback) {\n  // Listen for global YT player callback\n  if ((typeof global$1.YT === 'undefined' || global$1.YT.loaded === 0) && !loadingYoutubePlayer) {\n    // Prevents Ready event from being called twice\n    loadingYoutubePlayer = 1;\n\n    // Creates deferred so, other players know when to wait.\n    global$1.onYouTubeIframeAPIReady = function () {\n      global$1.onYouTubeIframeAPIReady = null;\n      loadingYoutubeDefer.resolve('done');\n      callback();\n    };\n  } else if (typeof global$1.YT === 'object' && global$1.YT.loaded === 1) {\n    callback();\n  } else {\n    loadingYoutubeDefer.done(() => {\n      callback();\n    });\n  }\n}\nclass VideoWorkerYoutube extends VideoWorkerBase {\n  type = 'youtube';\n  static parseURL(url) {\n    // eslint-disable-next-line no-useless-escape\n    const regExp = /.*(?:youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|shorts\\/|watch\\?v=)([^#\\&\\?]*).*/;\n    const match = url.match(regExp);\n    return match && match[1].length === 11 ? match[1] : false;\n  }\n  init() {\n    super.init();\n    loadAPI$1();\n  }\n  play(start) {\n    const self = this;\n    if (!self.player || !self.player.playVideo) {\n      return;\n    }\n    if (typeof start !== 'undefined') {\n      self.player.seekTo(start || 0);\n    }\n    if (global$1.YT.PlayerState.PLAYING !== self.player.getPlayerState()) {\n      // Don't play if video is already ended and with no loop.\n      if (self.options.endTime && !self.options.loop) {\n        self.getCurrentTime(seconds => {\n          if (seconds < self.options.endTime) {\n            self.player.playVideo();\n          }\n        });\n      } else {\n        self.player.playVideo();\n      }\n    }\n  }\n  pause() {\n    const self = this;\n    if (!self.player || !self.player.pauseVideo) {\n      return;\n    }\n    if (global$1.YT.PlayerState.PLAYING === self.player.getPlayerState()) {\n      self.player.pauseVideo();\n    }\n  }\n  mute() {\n    const self = this;\n    if (!self.player || !self.player.mute) {\n      return;\n    }\n    self.player.mute();\n  }\n  unmute() {\n    const self = this;\n    if (!self.player || !self.player.unMute) {\n      return;\n    }\n    self.player.unMute();\n  }\n  setVolume(volume = false) {\n    const self = this;\n    if (!self.player || typeof volume !== 'number' || !self.player.setVolume) {\n      return;\n    }\n    self.player.setVolume(volume);\n  }\n  getVolume(callback) {\n    const self = this;\n    if (!self.player) {\n      callback(false);\n      return;\n    }\n    if (self.player.getVolume) {\n      callback(self.player.getVolume());\n    }\n  }\n  getMuted(callback) {\n    const self = this;\n    if (!self.player) {\n      callback(null);\n      return;\n    }\n    if (self.player.isMuted) {\n      callback(self.player.isMuted());\n    }\n  }\n  setCurrentTime(currentTime = false) {\n    const self = this;\n    if (!self.player || typeof currentTime !== 'number' || !self.player.seekTo) {\n      return;\n    }\n    self.player.seekTo(currentTime);\n  }\n  getCurrentTime(callback) {\n    const self = this;\n    if (!self.player || !self.player.getCurrentTime) {\n      return;\n    }\n    callback(self.player.getCurrentTime());\n  }\n  getImageURL(callback) {\n    const self = this;\n    if (self.videoImage) {\n      callback(self.videoImage);\n      return;\n    }\n    const availableSizes = ['maxresdefault', 'sddefault', 'hqdefault', '0'];\n    let step = 0;\n    const tempImg = new Image();\n    tempImg.onload = function () {\n      // if no thumbnail, youtube add their own image with width = 120px\n      if ((this.naturalWidth || this.width) !== 120 || step === availableSizes.length - 1) {\n        // ok\n        self.videoImage = `https://img.youtube.com/vi/${self.videoID}/${availableSizes[step]}.jpg`;\n        callback(self.videoImage);\n      } else {\n        // try another size\n        step += 1;\n        this.src = `https://img.youtube.com/vi/${self.videoID}/${availableSizes[step]}.jpg`;\n      }\n    };\n    tempImg.src = `https://img.youtube.com/vi/${self.videoID}/${availableSizes[step]}.jpg`;\n  }\n  getVideo(callback) {\n    const self = this;\n\n    // return generated video block\n    if (self.$video) {\n      callback(self.$video);\n      return;\n    }\n\n    // generate new video block\n    onAPIready$1(() => {\n      let hiddenDiv;\n      if (!self.$video) {\n        hiddenDiv = document.createElement('div');\n        hiddenDiv.style.display = 'none';\n      }\n      self.playerOptions = {\n        // GDPR Compliance.\n        host: 'https://www.youtube-nocookie.com',\n        videoId: self.videoID,\n        playerVars: {\n          autohide: 1,\n          rel: 0,\n          autoplay: 0,\n          // autoplay enable on mobile devices\n          playsinline: 1\n        }\n      };\n\n      // hide controls\n      if (!self.options.showControls) {\n        self.playerOptions.playerVars.iv_load_policy = 3;\n        self.playerOptions.playerVars.modestbranding = 1;\n        self.playerOptions.playerVars.controls = 0;\n        self.playerOptions.playerVars.showinfo = 0;\n        self.playerOptions.playerVars.disablekb = 1;\n      }\n\n      // events\n      let ytStarted;\n      let ytProgressInterval;\n      self.playerOptions.events = {\n        onReady(e) {\n          // mute\n          if (self.options.mute) {\n            e.target.mute();\n          } else if (typeof self.options.volume === 'number') {\n            e.target.setVolume(self.options.volume);\n          }\n\n          // autoplay\n          if (self.options.autoplay) {\n            self.play(self.options.startTime);\n          }\n          self.fire('ready', e);\n\n          // For seamless loops, set the endTime to 0.1 seconds less than the video's duration\n          // https://github.com/nk-o/video-worker/issues/2\n          if (self.options.loop && !self.options.endTime) {\n            const secondsOffset = 0.1;\n            self.options.endTime = self.player.getDuration() - secondsOffset;\n          }\n\n          // volumechange\n          setInterval(() => {\n            self.getVolume(volume => {\n              if (self.options.volume !== volume) {\n                self.options.volume = volume;\n                self.fire('volumechange', e);\n              }\n            });\n          }, 150);\n        },\n        onStateChange(e) {\n          // loop\n          if (self.options.loop && e.data === global$1.YT.PlayerState.ENDED) {\n            self.play(self.options.startTime);\n          }\n          if (!ytStarted && e.data === global$1.YT.PlayerState.PLAYING) {\n            ytStarted = 1;\n            self.fire('started', e);\n          }\n          if (e.data === global$1.YT.PlayerState.PLAYING) {\n            self.fire('play', e);\n          }\n          if (e.data === global$1.YT.PlayerState.PAUSED) {\n            self.fire('pause', e);\n          }\n          if (e.data === global$1.YT.PlayerState.ENDED) {\n            self.fire('ended', e);\n          }\n\n          // progress check\n          if (e.data === global$1.YT.PlayerState.PLAYING) {\n            ytProgressInterval = setInterval(() => {\n              self.fire('timeupdate', e);\n\n              // check for end of video and play again or stop\n              if (self.options.endTime && self.player.getCurrentTime() >= self.options.endTime) {\n                if (self.options.loop) {\n                  self.play(self.options.startTime);\n                } else {\n                  self.pause();\n                }\n              }\n            }, 150);\n          } else {\n            clearInterval(ytProgressInterval);\n          }\n        },\n        onError(e) {\n          self.fire('error', e);\n        }\n      };\n      const firstInit = !self.$video;\n      if (firstInit) {\n        const div = document.createElement('div');\n        div.setAttribute('id', self.playerID);\n        hiddenDiv.appendChild(div);\n        document.body.appendChild(hiddenDiv);\n      }\n      self.player = self.player || new global$1.YT.Player(self.playerID, self.playerOptions);\n      if (firstInit) {\n        self.$video = document.getElementById(self.playerID);\n\n        // add accessibility attributes\n        if (self.options.accessibilityHidden) {\n          self.$video.setAttribute('tabindex', '-1');\n          self.$video.setAttribute('aria-hidden', 'true');\n        }\n\n        // get video width and height\n        self.videoWidth = parseInt(self.$video.getAttribute('width'), 10) || 1280;\n        self.videoHeight = parseInt(self.$video.getAttribute('height'), 10) || 720;\n      }\n      callback(self.$video);\n    });\n  }\n}\n\nlet VimeoAPIadded = 0;\nlet loadingVimeoPlayer = 0;\nconst loadingVimeoDefer = /*#__PURE__*/new Deferred();\nfunction loadAPI() {\n  if (VimeoAPIadded) {\n    return;\n  }\n  VimeoAPIadded = true;\n\n  // Useful when Vimeo API added using RequireJS https://github.com/nk-o/video-worker/pull/7\n  if (typeof global$1.Vimeo !== 'undefined') {\n    return;\n  }\n  const src = 'https://player.vimeo.com/api/player.js';\n\n  // add script in head section\n  let tag = document.createElement('script');\n  let head = document.getElementsByTagName('head')[0];\n  tag.src = src;\n  head.appendChild(tag);\n  head = null;\n  tag = null;\n}\nfunction onAPIready(callback) {\n  if (typeof global$1.Vimeo === 'undefined' && !loadingVimeoPlayer) {\n    loadingVimeoPlayer = 1;\n    const vimeoInterval = setInterval(() => {\n      if (typeof global$1.Vimeo !== 'undefined') {\n        clearInterval(vimeoInterval);\n        loadingVimeoDefer.resolve('done');\n        callback();\n      }\n    }, 20);\n  } else if (typeof global$1.Vimeo !== 'undefined') {\n    callback();\n  } else {\n    loadingVimeoDefer.done(() => {\n      callback();\n    });\n  }\n}\nclass VideoWorkerVimeo extends VideoWorkerBase {\n  type = 'vimeo';\n  static parseURL(url) {\n    // eslint-disable-next-line no-useless-escape\n    const regExp = /https?:\\/\\/(?:www\\.|player\\.)?vimeo.com\\/(?:channels\\/(?:\\w+\\/)?|groups\\/([^/]*)\\/videos\\/|album\\/(\\d+)\\/video\\/|video\\/|)(\\d+)(?:$|\\/|\\?)/;\n    const match = url.match(regExp);\n    return match && match[3] ? match[3] : false;\n  }\n\n  // Try to extract a hash for private videos from the URL.\n  // Thanks to https://github.com/sampotts/plyr\n  static parseURLHash(url) {\n    /* This regex matches a hexadecimal hash if given in any of these forms:\n     *  - [https://player.]vimeo.com/video/{id}/{hash}[?params]\n     *  - [https://player.]vimeo.com/video/{id}?h={hash}[&params]\n     *  - [https://player.]vimeo.com/video/{id}?[params]&h={hash}\n     *  - video/{id}/{hash}\n     * If matched, the hash is available in capture group 4\n     */\n    const regex = /^.*(vimeo.com\\/|video\\/)(\\d+)(\\?.*&*h=|\\/)+([\\d,a-f]+)/;\n    const found = url.match(regex);\n    return found && found.length === 5 ? found[4] : null;\n  }\n  init() {\n    super.init();\n    loadAPI();\n  }\n  play(start) {\n    const self = this;\n    if (!self.player) {\n      return;\n    }\n    if (typeof start !== 'undefined') {\n      self.player.setCurrentTime(start);\n    }\n    self.player.getPaused().then(paused => {\n      if (paused) {\n        // Don't play if video is already ended and with no loop.\n        if (self.options.endTime && !self.options.loop) {\n          self.getCurrentTime(seconds => {\n            if (seconds < self.options.endTime) {\n              self.player.play();\n            }\n          });\n        } else {\n          self.player.play();\n        }\n      }\n    });\n  }\n  pause() {\n    const self = this;\n    if (!self.player) {\n      return;\n    }\n    self.player.getPaused().then(paused => {\n      if (!paused) {\n        self.player.pause();\n      }\n    });\n  }\n  mute() {\n    const self = this;\n    if (!self.player || !self.player.setVolume) {\n      return;\n    }\n    self.setVolume(0);\n  }\n  unmute() {\n    const self = this;\n    if (!self.player || !self.player.setVolume) {\n      return;\n    }\n\n    // In case the default volume is 0, we have to set 100 when unmute.\n    self.setVolume(self.options.volume || 100);\n  }\n  setVolume(volume = false) {\n    const self = this;\n    if (!self.player || typeof volume !== 'number' || !self.player.setVolume) {\n      return;\n    }\n    self.player.setVolume(volume / 100);\n  }\n  getVolume(callback) {\n    const self = this;\n    if (!self.player) {\n      callback(false);\n      return;\n    }\n    if (self.player.getVolume) {\n      self.player.getVolume().then(volume => {\n        callback(volume * 100);\n      });\n    }\n  }\n  getMuted(callback) {\n    const self = this;\n    if (!self.player) {\n      callback(null);\n      return;\n    }\n    if (self.player.getVolume) {\n      self.player.getVolume().then(volume => {\n        callback(!!volume);\n      });\n    }\n  }\n  setCurrentTime(currentTime = false) {\n    const self = this;\n    if (!self.player || typeof currentTime !== 'number' || !self.player.setCurrentTime) {\n      return;\n    }\n    self.player.setCurrentTime(currentTime);\n  }\n  getCurrentTime(callback) {\n    const self = this;\n    if (!self.player || !self.player.getCurrentTime) {\n      return;\n    }\n    self.player.getCurrentTime().then(currentTime => {\n      callback(currentTime);\n    });\n  }\n  getImageURL(callback) {\n    const self = this;\n    if (self.videoImage) {\n      callback(self.videoImage);\n      return;\n    }\n\n    // We should provide width to get HQ thumbnail URL.\n    let width = global$1.innerWidth || 1920;\n    if (global$1.devicePixelRatio) {\n      width *= global$1.devicePixelRatio;\n    }\n    width = Math.min(width, 1920);\n    let request = new XMLHttpRequest();\n    // https://vimeo.com/api/oembed.json?url=https://vimeo.com/235212527\n    request.open('GET', `https://vimeo.com/api/oembed.json?url=${self.url}&width=${width}`, true);\n    request.onreadystatechange = function () {\n      if (this.readyState === 4) {\n        if (this.status >= 200 && this.status < 400) {\n          // Success!\n          const response = JSON.parse(this.responseText);\n          if (response.thumbnail_url) {\n            self.videoImage = response.thumbnail_url;\n            callback(self.videoImage);\n          }\n        }\n      }\n    };\n    request.send();\n    request = null;\n  }\n  getVideo(callback) {\n    const self = this;\n\n    // return generated video block\n    if (self.$video) {\n      callback(self.$video);\n      return;\n    }\n\n    // generate new video block\n    onAPIready(() => {\n      let hiddenDiv;\n      if (!self.$video) {\n        hiddenDiv = document.createElement('div');\n        hiddenDiv.style.display = 'none';\n      }\n      self.playerOptions = {\n        // GDPR Compliance.\n        dnt: 1,\n        id: self.videoID,\n        autopause: 0,\n        transparent: 0,\n        autoplay: self.options.autoplay ? 1 : 0,\n        loop: self.options.loop ? 1 : 0,\n        muted: self.options.mute || self.options.volume === 0 ? 1 : 0\n      };\n\n      // private video hash\n      const urlHash = self.constructor.parseURLHash(self.url);\n      if (urlHash) {\n        self.playerOptions.h = urlHash;\n      }\n\n      // hide controls\n      if (!self.options.showControls) {\n        self.playerOptions.controls = 0;\n      }\n\n      // enable background option\n      if (!self.options.showControls && self.options.loop && self.options.autoplay) {\n        self.playerOptions.background = 1;\n      }\n      if (!self.$video) {\n        let playerOptionsString = '';\n        Object.keys(self.playerOptions).forEach(key => {\n          if (playerOptionsString !== '') {\n            playerOptionsString += '&';\n          }\n          playerOptionsString += `${key}=${encodeURIComponent(self.playerOptions[key])}`;\n        });\n\n        // we need to create iframe manually because when we create it using API\n        // js events won't triggers after iframe moved to another place\n        self.$video = document.createElement('iframe');\n        self.$video.setAttribute('id', self.playerID);\n        self.$video.setAttribute('src', `https://player.vimeo.com/video/${self.videoID}?${playerOptionsString}`);\n        self.$video.setAttribute('frameborder', '0');\n        self.$video.setAttribute('mozallowfullscreen', '');\n        self.$video.setAttribute('allowfullscreen', '');\n        self.$video.setAttribute('title', 'Vimeo video player');\n\n        // add accessibility attributes\n        if (self.options.accessibilityHidden) {\n          self.$video.setAttribute('tabindex', '-1');\n          self.$video.setAttribute('aria-hidden', 'true');\n        }\n        hiddenDiv.appendChild(self.$video);\n        document.body.appendChild(hiddenDiv);\n      }\n      self.player = self.player || new global$1.Vimeo.Player(self.$video, self.playerOptions);\n\n      // Since Vimeo removed the `volume` parameter, we have to set it manually.\n      if (!self.options.mute && typeof self.options.volume === 'number') {\n        self.setVolume(self.options.volume);\n      }\n\n      // set current time for autoplay\n      if (self.options.startTime && self.options.autoplay) {\n        self.player.setCurrentTime(self.options.startTime);\n      }\n\n      // get video width and height\n      self.player.getVideoWidth().then(width => {\n        self.videoWidth = width || 1280;\n      });\n      self.player.getVideoHeight().then(height => {\n        self.videoHeight = height || 720;\n      });\n\n      // events\n      let vmStarted;\n      self.player.on('timeupdate', e => {\n        if (!vmStarted) {\n          self.fire('started', e);\n          vmStarted = 1;\n        }\n        self.fire('timeupdate', e);\n\n        // check for end of video and play again or stop\n        if (self.options.endTime && e.seconds >= self.options.endTime) {\n          if (self.options.loop) {\n            self.play(self.options.startTime);\n          } else {\n            self.pause();\n          }\n        }\n      });\n      self.player.on('play', e => {\n        self.fire('play', e);\n\n        // check for the start time and start with it\n        if (self.options.startTime && e.seconds === 0) {\n          self.play(self.options.startTime);\n        }\n      });\n      self.player.on('pause', e => {\n        self.fire('pause', e);\n      });\n      self.player.on('ended', e => {\n        self.fire('ended', e);\n      });\n      self.player.on('loaded', e => {\n        self.fire('ready', e);\n      });\n      self.player.on('volumechange', e => {\n        self.getVolume(volume => {\n          self.options.volume = volume;\n        });\n        self.fire('volumechange', e);\n      });\n      self.player.on('error', e => {\n        self.fire('error', e);\n      });\n      callback(self.$video);\n    });\n  }\n}\n\nclass VideoWorkerLocal extends VideoWorkerBase {\n  type = 'local';\n  static parseURL(url) {\n    // eslint-disable-next-line no-useless-escape\n    const videoFormats = url.split(/,(?=mp4\\:|webm\\:|ogv\\:|ogg\\:)/);\n    const result = {};\n    let ready = 0;\n    videoFormats.forEach(val => {\n      // eslint-disable-next-line no-useless-escape\n      const match = val.match(/^(mp4|webm|ogv|ogg)\\:(.*)/);\n      if (match && match[1] && match[2]) {\n        // eslint-disable-next-line prefer-destructuring\n        result[match[1] === 'ogv' ? 'ogg' : match[1]] = match[2];\n        ready = 1;\n      }\n    });\n    return ready ? result : false;\n  }\n  play(start) {\n    const self = this;\n    if (!self.player) {\n      return;\n    }\n    if (typeof start !== 'undefined') {\n      self.player.currentTime = start;\n    }\n    if (self.player.paused) {\n      // Don't play if video is already ended and with no loop.\n      if (self.options.endTime && !self.options.loop) {\n        self.getCurrentTime(seconds => {\n          if (seconds < self.options.endTime) {\n            self.player.play();\n          }\n        });\n      } else {\n        self.player.play();\n      }\n    }\n  }\n  pause() {\n    const self = this;\n    if (!self.player || self.player.paused) {\n      return;\n    }\n    self.player.pause();\n  }\n  mute() {\n    const self = this;\n    if (!self.player) {\n      return;\n    }\n    self.$video.muted = true;\n  }\n  unmute() {\n    const self = this;\n    if (!self.player) {\n      return;\n    }\n    self.$video.muted = false;\n  }\n  setVolume(volume = false) {\n    const self = this;\n    if (!self.player || typeof volume !== 'number') {\n      return;\n    }\n    self.$video.volume = volume / 100;\n  }\n  getVolume(callback) {\n    const self = this;\n    if (!self.player) {\n      callback(false);\n      return;\n    }\n    callback(self.$video.volume * 100);\n  }\n  getMuted(callback) {\n    const self = this;\n    if (!self.player) {\n      callback(null);\n      return;\n    }\n    callback(self.$video.muted);\n  }\n  setCurrentTime(currentTime = false) {\n    const self = this;\n    if (!self.player || typeof currentTime !== 'number') {\n      return;\n    }\n    self.$video.currentTime = currentTime;\n  }\n  getCurrentTime(callback) {\n    const self = this;\n    if (!self.player) {\n      return;\n    }\n    callback(self.player.currentTime);\n  }\n  getImageURL(callback) {\n    const self = this;\n    if (self.videoImage) {\n      callback(self.videoImage);\n    }\n  }\n  getVideo(callback) {\n    const self = this;\n\n    // return generated video block\n    if (self.$video) {\n      callback(self.$video);\n      return;\n    }\n\n    // generate new video block\n    let hiddenDiv;\n    if (!self.$video) {\n      hiddenDiv = document.createElement('div');\n      hiddenDiv.style.display = 'none';\n    }\n    function addSourceElement(element, src, type) {\n      const source = document.createElement('source');\n      source.src = src;\n      source.type = type;\n      element.appendChild(source);\n    }\n    if (!self.$video) {\n      self.$video = document.createElement('video');\n      self.player = self.$video;\n\n      // show controls\n      if (self.options.showControls) {\n        self.$video.controls = true;\n      }\n\n      // set volume\n      if (typeof self.options.volume === 'number') {\n        self.setVolume(self.options.volume);\n      }\n\n      // mute (it is required to mute after the volume set)\n      if (self.options.mute) {\n        self.mute();\n      }\n\n      // loop\n      if (self.options.loop) {\n        self.$video.loop = true;\n      }\n\n      // autoplay enable on mobile devices\n      self.$video.setAttribute('playsinline', '');\n      self.$video.setAttribute('webkit-playsinline', '');\n\n      // add accessibility attributes\n      if (self.options.accessibilityHidden) {\n        self.$video.setAttribute('tabindex', '-1');\n        self.$video.setAttribute('aria-hidden', 'true');\n      }\n      self.$video.setAttribute('id', self.playerID);\n      hiddenDiv.appendChild(self.$video);\n      document.body.appendChild(hiddenDiv);\n      Object.keys(self.videoID).forEach(key => {\n        addSourceElement(self.$video, self.videoID[key], `video/${key}`);\n      });\n    }\n    let locStarted;\n    self.player.addEventListener('playing', e => {\n      if (!locStarted) {\n        self.fire('started', e);\n      }\n      locStarted = 1;\n    });\n    self.player.addEventListener('timeupdate', function (e) {\n      self.fire('timeupdate', e);\n\n      // check for end of video and play again or stop\n      if (self.options.endTime && this.currentTime >= self.options.endTime) {\n        if (self.options.loop) {\n          self.play(self.options.startTime);\n        } else {\n          self.pause();\n        }\n      }\n    });\n    self.player.addEventListener('play', e => {\n      self.fire('play', e);\n    });\n    self.player.addEventListener('pause', e => {\n      self.fire('pause', e);\n    });\n    self.player.addEventListener('ended', e => {\n      self.fire('ended', e);\n    });\n    self.player.addEventListener('loadedmetadata', function () {\n      // get video width and height\n      self.videoWidth = this.videoWidth || 1280;\n      self.videoHeight = this.videoHeight || 720;\n      self.fire('ready');\n\n      // autoplay\n      if (self.options.autoplay) {\n        self.play(self.options.startTime);\n      }\n    });\n    self.player.addEventListener('volumechange', e => {\n      self.getVolume(volume => {\n        self.options.volume = volume;\n      });\n      self.fire('volumechange', e);\n    });\n    self.player.addEventListener('error', e => {\n      self.fire('error', e);\n    });\n    callback(self.$video);\n  }\n}\n\nfunction VideoWorker(url, options) {\n  let result = false;\n  Object.keys(VideoWorker.providers).forEach(key => {\n    if (!result && VideoWorker.providers[key].parseURL(url)) {\n      result = new VideoWorker.providers[key](url, options);\n    }\n  });\n  return result || new VideoWorkerBase(url, options);\n}\nVideoWorker.BaseClass = VideoWorkerBase;\nVideoWorker.providers = {\n  Youtube: VideoWorkerYoutube,\n  Vimeo: VideoWorkerVimeo,\n  Local: VideoWorkerLocal\n};\n\nexport { VideoWorker as default };\n//# sourceMappingURL=video-worker.esm.js.map\n","/* eslint-disable import/no-mutable-exports */\n/* eslint-disable no-restricted-globals */\nlet win;\n\nif (typeof window !== 'undefined') {\n  win = window;\n} else if (typeof global !== 'undefined') {\n  win = global;\n} else if (typeof self !== 'undefined') {\n  win = self;\n} else {\n  win = {};\n}\n\nexport default win;\n","/**\n * Document ready callback.\n * @param {Function} callback - callback will be fired once Document ready.\n */\nfunction ready(callback) {\n  if (document.readyState === 'complete' || document.readyState === 'interactive') {\n    // Already ready or interactive, execute callback\n    callback();\n  } else {\n    document.addEventListener('DOMContentLoaded', callback, {\n      capture: true,\n      once: true,\n      passive: true,\n    });\n  }\n}\n\nexport default ready;\n","import VideoWorker from 'video-worker';\n\nimport global from './utils/global';\n\nfunction jarallaxVideo(jarallax = global.jarallax) {\n  if (typeof jarallax === 'undefined') {\n    return;\n  }\n\n  const Jarallax = jarallax.constructor;\n\n  // append video after when block will be visible.\n  const defOnScroll = Jarallax.prototype.onScroll;\n  Jarallax.prototype.onScroll = function () {\n    const self = this;\n\n    defOnScroll.apply(self);\n\n    const isReady =\n      !self.isVideoInserted &&\n      self.video &&\n      (!self.options.videoLazyLoading || self.isElementInViewport) &&\n      !self.options.disableVideo();\n\n    if (isReady) {\n      self.isVideoInserted = true;\n\n      self.video.getVideo((video) => {\n        const $parent = video.parentNode;\n        self.css(video, {\n          position: self.image.position,\n          top: '0px',\n          left: '0px',\n          right: '0px',\n          bottom: '0px',\n          width: '100%',\n          height: '100%',\n          maxWidth: 'none',\n          maxHeight: 'none',\n          pointerEvents: 'none',\n          transformStyle: 'preserve-3d',\n          backfaceVisibility: 'hidden',\n          margin: 0,\n          zIndex: -1,\n        });\n        self.$video = video;\n\n        // add Poster attribute to self-hosted video\n        if (self.video.type === 'local') {\n          if (self.image.src) {\n            self.$video.setAttribute('poster', self.image.src);\n          } else if (\n            self.image.$item &&\n            self.image.$item.tagName === 'IMG' &&\n            self.image.$item.src\n          ) {\n            self.$video.setAttribute('poster', self.image.$item.src);\n          }\n        }\n\n        // add classname to video element\n        if (self.options.videoClass) {\n          self.$video.setAttribute(\n            'class',\n            `${self.options.videoClass} ${self.options.videoClass}-${self.video.type}`\n          );\n        }\n\n        // insert video tag\n        self.image.$container.appendChild(video);\n\n        // remove parent video element (created by VideoWorker)\n        $parent.parentNode.removeChild($parent);\n\n        // call onVideoInsert event\n        if (self.options.onVideoInsert) {\n          self.options.onVideoInsert.call(self);\n        }\n      });\n    }\n  };\n\n  // cover video\n  const defCoverImage = Jarallax.prototype.coverImage;\n  Jarallax.prototype.coverImage = function () {\n    const self = this;\n    const imageData = defCoverImage.apply(self);\n    const node = self.image.$item ? self.image.$item.nodeName : false;\n\n    if (imageData && self.video && node && (node === 'IFRAME' || node === 'VIDEO')) {\n      let h = imageData.image.height;\n      let w = (h * self.image.width) / self.image.height;\n      let ml = (imageData.container.width - w) / 2;\n      let mt = imageData.image.marginTop;\n\n      if (imageData.container.width > w) {\n        w = imageData.container.width;\n        h = (w * self.image.height) / self.image.width;\n        ml = 0;\n        mt += (imageData.image.height - h) / 2;\n      }\n\n      // add video height over than need to hide controls\n      if (node === 'IFRAME') {\n        h += 400;\n        mt -= 200;\n      }\n\n      self.css(self.$video, {\n        width: `${w}px`,\n        marginLeft: `${ml}px`,\n        height: `${h}px`,\n        marginTop: `${mt}px`,\n      });\n    }\n\n    return imageData;\n  };\n\n  // init video\n  const defInitImg = Jarallax.prototype.initImg;\n  Jarallax.prototype.initImg = function () {\n    const self = this;\n    const defaultResult = defInitImg.apply(self);\n\n    if (!self.options.videoSrc) {\n      self.options.videoSrc = self.$item.getAttribute('data-jarallax-video') || null;\n    }\n\n    if (self.options.videoSrc) {\n      self.defaultInitImgResult = defaultResult;\n      return true;\n    }\n\n    return defaultResult;\n  };\n\n  const defCanInitParallax = Jarallax.prototype.canInitParallax;\n  Jarallax.prototype.canInitParallax = function () {\n    const self = this;\n    let defaultResult = defCanInitParallax.apply(self);\n\n    if (!self.options.videoSrc) {\n      return defaultResult;\n    }\n\n    // Init video api\n    const video = new VideoWorker(self.options.videoSrc, {\n      autoplay: true,\n      loop: self.options.videoLoop,\n      showControls: false,\n      accessibilityHidden: true,\n      startTime: self.options.videoStartTime || 0,\n      endTime: self.options.videoEndTime || 0,\n      mute: !self.options.videoVolume,\n      volume: self.options.videoVolume || 0,\n    });\n\n    // call onVideoWorkerInit event\n    if (self.options.onVideoWorkerInit) {\n      self.options.onVideoWorkerInit.call(self, video);\n    }\n\n    function resetDefaultImage() {\n      if (self.image.$default_item) {\n        self.image.$item = self.image.$default_item;\n        self.image.$item.style.display = 'block';\n\n        // set image width and height\n        self.coverImage();\n        self.onScroll();\n      }\n    }\n\n    if (video.isValid()) {\n      // Force enable parallax.\n      // When the parallax disabled on mobile devices, we still need to display videos.\n      // https://github.com/nk-o/jarallax/issues/159\n      if (this.options.disableParallax()) {\n        defaultResult = true;\n        self.image.position = 'absolute';\n        self.options.type = 'scroll';\n        self.options.speed = 1;\n      }\n\n      // if parallax will not be inited, we can add thumbnail on background.\n      if (!defaultResult) {\n        if (!self.defaultInitImgResult) {\n          video.getImageURL((url) => {\n            // save default user styles\n            const curStyle = self.$item.getAttribute('style');\n            if (curStyle) {\n              self.$item.setAttribute('data-jarallax-original-styles', curStyle);\n            }\n\n            // set new background\n            self.css(self.$item, {\n              'background-image': `url(\"${url}\")`,\n              'background-position': 'center',\n              'background-size': 'cover',\n            });\n          });\n        }\n\n        // init video\n      } else {\n        video.on('ready', () => {\n          if (self.options.videoPlayOnlyVisible) {\n            const oldOnScroll = self.onScroll;\n            self.onScroll = function () {\n              oldOnScroll.apply(self);\n              if (\n                !self.videoError &&\n                (self.options.videoLoop || (!self.options.videoLoop && !self.videoEnded))\n              ) {\n                if (self.isVisible()) {\n                  video.play();\n                } else {\n                  video.pause();\n                }\n              }\n            };\n          } else {\n            video.play();\n          }\n        });\n        video.on('started', () => {\n          self.image.$default_item = self.image.$item;\n          self.image.$item = self.$video;\n\n          // set video width and height\n          self.image.width = self.video.videoWidth || 1280;\n          self.image.height = self.video.videoHeight || 720;\n          self.coverImage();\n          self.onScroll();\n\n          // hide image\n          if (self.image.$default_item) {\n            self.image.$default_item.style.display = 'none';\n          }\n        });\n\n        video.on('ended', () => {\n          self.videoEnded = true;\n\n          if (!self.options.videoLoop) {\n            // show default image if Loop disabled.\n            resetDefaultImage();\n          }\n        });\n        video.on('error', () => {\n          self.videoError = true;\n\n          // show default image if video loading error.\n          resetDefaultImage();\n        });\n\n        self.video = video;\n\n        // set image if not exists\n        if (!self.defaultInitImgResult) {\n          // set empty image on self-hosted video if not defined\n          self.image.src =\n            'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';\n\n          if (video.type !== 'local') {\n            video.getImageURL((url) => {\n              self.image.bgImage = `url(\"${url}\")`;\n              self.init();\n            });\n\n            return false;\n          }\n        }\n      }\n    }\n\n    return defaultResult;\n  };\n\n  // Destroy video parallax\n  const defDestroy = Jarallax.prototype.destroy;\n  Jarallax.prototype.destroy = function () {\n    const self = this;\n\n    if (self.image.$default_item) {\n      self.image.$item = self.image.$default_item;\n      delete self.image.$default_item;\n    }\n\n    defDestroy.apply(self);\n  };\n}\n\nexport default jarallaxVideo;\n","import VideoWorker from 'video-worker';\n\nimport domReady from './utils/ready';\nimport global from './utils/global';\nimport jarallaxVideo from './ext-video';\n\njarallaxVideo();\n\n// data-jarallax-video initialization\ndomReady(() => {\n  if (typeof global.jarallax !== 'undefined') {\n    global.jarallax(document.querySelectorAll('[data-jarallax-video]'));\n  }\n});\n\n// We should add VideoWorker globally, since some project uses it.\nif (!global.VideoWorker) {\n  global.VideoWorker = VideoWorker;\n}\n\nexport default jarallaxVideo;\n"],"names":["defaults","autoplay","loop","mute","volume","showControls","accessibilityHidden","startTime","endTime","win","window","global","self","callback","jarallaxVideo","jarallax","Jarallax","constructor","defOnScroll","prototype","onScroll","this","apply","isVideoInserted","video","options","videoLazyLoading","isElementInViewport","disableVideo","getVideo","$parent","parentNode","css","position","image","top","left","right","bottom","width","height","maxWidth","maxHeight","pointerEvents","transformStyle","backfaceVisibility","margin","zIndex","$video","type","src","setAttribute","$item","tagName","videoClass","$container","appendChild","removeChild","onVideoInsert","call","defCoverImage","coverImage","imageData","node","nodeName","h","w","ml","container","mt","marginTop","marginLeft","defInitImg","initImg","defaultResult","videoSrc","getAttribute","defaultInitImgResult","defCanInitParallax","canInitParallax","VideoWorker","videoLoop","videoStartTime","videoEndTime","videoVolume","resetDefaultImage","$default_item","style","display","onVideoWorkerInit","isValid","disableParallax","speed","on","videoPlayOnlyVisible","oldOnScroll","videoError","videoEnded","isVisible","play","pause","videoWidth","videoHeight","getImageURL","url","bgImage","init","curStyle","defDestroy","destroy","document","querySelectorAll","readyState","addEventListener","capture","once","passive"],"mappings":"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","x_google_ignoreList":[0]}