L1lith / Crunchyroll Timestamp Previewer

// ==UserScript==
// @name         Crunchyroll Timestamp Previewer
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  See the time on the progress bar before you click.
// @author       L1lith
// @match        http*://static.crunchyroll.com/vilos/player.*
// @grant        none
// @license      MIT
// @run-at       document-start
// ==/UserScript==

(function () {
  const registeredProgressDivs = []
  let videoLength = null
  const progressDivListener = event => {
    const rootProgressDiv = document.querySelector('.vjs-progress-control')
    if (rootProgressDiv && !registeredProgressDivs.includes(rootProgressDiv)) {
      registeredProgressDivs.push(rootProgressDiv)
      addTimeScroller(rootProgressDiv)
    }
  }
  let findVideoLengthInterval = null
  const findVideoLength = () => {
    try {
      videoLength = document.querySelector('.vjs-duration-display').innerText.match(/[0-9]+:[0-9]+/)[0].split(':').map(string => parseInt(string))
      videoLength = videoLength[0] + videoLength[1] / 60
    }
    catch (error) {
      return
    }
    if (videoLength === 0) return videoLength = null
    clearInterval(findVideoLengthInterval)
  }

  function addTimeScroller(rootProgressDiv) {
    const retrieveProgressDiv = rootProgressDiv.querySelector('.vjs-play-progress')

    let timeDiv = null
    const moveListener = event => {
      if (timeDiv === null || videoLength === null) return
      let currentTimeString = retrieveProgressDiv.getAttribute('data-current-time') //.split(':').map(string => parseInt(string))
      const progressHolder = rootProgressDiv.querySelector('.vjs-progress-holder')
      const xPercent = (event.pageX - progressHolder.getBoundingClientRect().left) / progressHolder.offsetWidth
      if (xPercent < 0 || xPercent > 1) return timeDiv.textContent = ""
      timeDiv.style.left = Math.round(xPercent * 10000) / 100 + "%"
      const targetTime = xPercent * videoLength
      const hour = Math.floor(targetTime)
      const seconds = Math.round((targetTime % 1) * 60)
      const formattedTime = [hour, seconds].map(value => value.toString()).map(value => value.length < 2 ? '0' + value : value).join(':')
      timeDiv.textContent = formattedTime
    }
    const mouseOverListener = () => {
      timeDiv = document.createElement('span')
      timeDiv.className = "scroll-time"
      timeDiv.style.fontSize = "2.5em"
      timeDiv.style.position = "absolute"
      timeDiv.style.bottom = "120%"
      timeDiv.style.left = "50%"
      timeDiv.style.zIndex = 100
      timeDiv.style.color = "white"
      timeDiv.style.transform = "translate(-50%, 0%)"
      timeDiv.style.textShadow = "0 0 6px black"
      timeDiv.style.pointerEvents = "none"
      rootProgressDiv.querySelector('.vjs-progress-holder').appendChild(timeDiv)
    }
    const mouseOutListener = () => {
      if (timeDiv === null) return
      rootProgressDiv.querySelector('.vjs-progress-holder').removeChild(timeDiv)
      timeDiv = null
    }
    rootProgressDiv.addEventListener('mousemove', moveListener)
    rootProgressDiv.addEventListener('mouseover', mouseOverListener)
    rootProgressDiv.addEventListener('mouseout', mouseOutListener)
    return () => {
      rootProgressDiv.removeEventListener('mouseover', moveListener)
      rootProgressDiv.removeEventListener('mouseover', mouseOverListener)
      rootProgressDiv.removeEventListener('mouseout', mouseOutListener)
    }
  }

  function run() {
    findVideoLengthInterval = setInterval(findVideoLength, 150)
    document.addEventListener('mouseover', progressDivListener)
  }
  window.addEventListener('load', run)
})();