thedrummeraki/tanoshimu

View on GitHub
app/assets/javascripts/episodes.js

Summary

Maintainability
D
2 days
Test Coverage
$(document).ready(function() {
  // Global variables
  var goingToShow = false;
  var goingToEpisode = false;
  var fullscreenOn = false;
  var videoLoaded = false;
  var savingProgress = false;
  var inactivityTime = 5000;
  var timeoutId;

  var $videoCont = null;
  var $video = null;
  var $progress = null;
  var $progressBar = null;
  var $playing_btn = null;
  var $paused_btn = null;
  var subtitlesMenu = null;
  var subtitlesMenuButtons = [];
  var videoPlaying = false;

  const show_id = $('.video-body').attr('show-id');
  const episode_id = $('.video-body').attr('episode-id');

  if ($('.video-body').size() > 0) {
    $playing_btn = $('.playing');
    $paused_btn = $('.paused');
    $progress = $('.progress-filled');
    $progressBar = $('.progress-bar');
    $video = $('#video-obj');
    $videoCont = $video.parent();

    setTimeout(() => {
      $video.removeAttr('muted');
      $video.get(0).muted = false;
    }, 500);

    for (var i = 0; i < $video.get(0).textTracks.length; i++) {
      var track = $video.get(0).textTracks[i];
      track.mode = 'hidden';
    }

    $('[hf-action="cc"]').on('click', toggleCCMenu);

    $('[go-to-show]').on('click', goToShow);
    $('[go-to-episode]').on('click', goToEpisode);
    $('[hf-action]').on('click', execHfAction);

    $('.video-clickable-zone').on('click', togglePlayPause);
    $('.video-clickable-zone').on('dblclick', toggleFullscreen);
    $progressBar.on('click', seek);
    $video.on('play', onPlay);
    $video.on('timeupdate', onProgress);
    $video.on('pause', onPause);
    $video.on('ended', onEnded);
    $video.on('loadedmetadata', setVideoDuration);

    document.addEventListener("mousemove", cancelFadeOutInControls, false);
    document.addEventListener("mousedown", cancelFadeOutInControls, false);
    document.addEventListener("keypress", cancelFadeOutInControls, false);
    document.addEventListener("touchmove", cancelFadeOutInControls, false);
    document.addEventListener('keypress', spaceBarTogglePlay);

    setFadeOutInControls();
    initCCMenu();
    setTracks();

    function initCCMenu() {
      if ($video.get(0).textTracks) {
        var df = document.createDocumentFragment();
        subtitlesMenu = df.appendChild(document.createElement('ul'));
        subtitlesMenu.className = 'subtitles-menu';
        subtitlesMenu.appendChild(createMenuItem('subtitles-off', '', 'Off'));
        for (var i = 0; i < $video.get(0).textTracks.length; i++) {
          var track = $video.get(0).textTracks[i];
          var id = 'subtitles-' + track.language;
          var menuItem = createMenuItem(id, track.language, track.label);
          subtitlesMenu.appendChild(menuItem);
        }
        $videoCont.append($(subtitlesMenu));
        $('[data-state="active"]').click();
      }
    }

    function createMenuItem(id, lang, label) {
      var listItem = document.createElement('li');

      var button = listItem.appendChild(document.createElement('button'));
      button.setAttribute('id', id);
      button.className = 'subtitles-button';
      button.setAttribute('data-state', 'inactive');
      if (lang && lang.length > 0) {
        button.setAttribute('lang', lang);
      }
      if (localStorage.savedCC === lang || !localStorage.savedCC && lang === '') {
        button.setAttribute('data-state', 'active');
      }
      button.value = label;
      button.appendChild(document.createTextNode(label));

      button.addEventListener('click', function(e) {
        subtitlesMenuButtons.map(function(v, i, a) {
          subtitlesMenuButtons[i].setAttribute('data-state', 'inactive');
        });
        var lang = this.getAttribute('lang');
        for (var i = 0; i < $video.get(0).textTracks.length; i++) {
          var track = $video.get(0).textTracks[i];
          if (track.language == lang) {
            track.mode = 'showing';
          } else {
            track.mode = 'hidden';
          }
          this.setAttribute('data-state', 'active');
        }
        setTimeout(function() {
          $('.subtitles-menu').fadeOut();
          localStorage.savedCC = lang;
        }, 100);
      });

      subtitlesMenuButtons.push(button);
      return listItem;
    }

    async function setTracks() {
      var tracks = document.querySelectorAll('[load-src]');
      for (var i = 0; i < tracks.length; i++) {
        let blob = await fetch(tracks[i].getAttribute('load-src')).then(r => r.blob());
        tracks[i].src = URL.createObjectURL(blob);
      }
    }

    function toggleCCMenu(e) {
      subtitlesMenu.style.display = (
        subtitlesMenu.style.display == 'block' ? 'none' : 'block'
      );
    }

    function goToShow(e) {
      if (goingToShow) {
        return;
      }
      goingToShow = true;
      var showId = this.getAttribute('go-to-show');
      pause(function() {
        window.location.href = '/shows/' + showId;
      });
    }

    function goToEpisode(e) {
      if (goingToEpisode) {
        return;
      }
      goingToEpisode = true;
      var showId = this.getAttribute('show-id');
      var episodeId = this.getAttribute('go-to-episode');
      pause(function() {
        window.location.href = '/shows/' + showId + '/episodes/' + episodeId;
      });
    }

    function execHfAction(e) {
      const action = this.getAttribute('hf-action');
      if (action === 'toggle-play-pause') {
        togglePlayPause();
      } else if (action == 'toggle-fullscreen') {
        toggleFullscreen();
      }
    }

    function spaceBarTogglePlay(e) {
      if (e.keyCode == 32) {
        togglePlayPause();
      }
    }

    function togglePlayPause(callback) {
      if (isPlaying()) {
        pause(callback);
      } else {
        play().then(callback);
      }
    }

    function setVideoDuration() {
      var duration = $video.get(0).duration;
      var hours = parseInt(duration / 60 / 60, 10);
      var minutes = parseInt(duration / 60, 10);
          var seconds = parseInt(duration % 60);

      min_sec = stringifyInts(minutes) + ':' + stringifyInts(seconds);
      if (hours > 0) {
        hours = stringifyInts(hours) + ':'
        $('time').children('.hours').show().text(hours);
      } else {
        $('time').children('.hours').hide();
      }
      $('time').children('.duration').text(min_sec);
      videoLoaded = true;
      $video.get(0).currentTime = duration * (parseFloat($video.attr('watched')) / 100);
    }

    function play() {
      return $video.get(0).play();
    }

    function onProgress(e) {
      var currentTime = this.currentTime;
      var duration = this.duration;
      var loadPercentage = (currentTime / duration) * 100;
      var width = loadPercentage + '%';
      $progress.css({width: width})

      var timeleft = duration - currentTime;
      var hours = parseInt(timeleft / 60 / 60, 10);
      var minutes = parseInt(timeleft / 60, 10);
          var seconds = parseInt(timeleft % 60);

      min_sec = stringifyInts(minutes) + ':' + stringifyInts(seconds);
      if (hours > 0) {
        hours = stringifyInts(hours) + ':'
        $('time').children('.hours').show().text(hours);
      } else {
        $('time').children('.hours').hide();
      }
      $('time').children('.duration').text(min_sec);
    }

    function getCurrentProgressRatio() {
      var video = $video.get(0);
      var duration = parseInt(video.duration);
      var currentTime = video.currentTime;
      return (currentTime / duration) * 100;
    }

    (function worker() {
      var ratio = getCurrentProgressRatio();

      if (!videoPlaying || ratio == 0) {
        setTimeout(worker, 5000);
        return;
      }

      $.ajax({
        type: 'PUT',
        url: '/shows/' + show_id + '/episodes/' + episode_id,
        data: {episode: {progress: ratio}},
        success: function(data) {
        },
        complete: function() {
          setTimeout(worker, 5000);
        }
      });
    })();

    function onPlay(e) {
      $playing_btn.addClass('active');
      $paused_btn.removeClass('active');
      videoPlaying = true;
    }

    function seek(e) {
      if (!videoLoaded) {
        return;
      }
      pause(function() {
        var video = $video.get(0);
        var progress = $progressBar.get(0);
        video.currentTime = (e.offsetX / progress.offsetWidth) * video.duration;
        play();
      });

    }

    function onPause(e) {
      $playing_btn.removeClass('active');
      $paused_btn.addClass('active');
      videoPlaying = false;
    }

    function onEnded() {
      cancelFadeOutInControls(true);
    }

    function pause(callback) {
      $video.get(0).pause();
      if (typeof(callback) === 'function') {
        callback();
      }
    }

    function isPlaying() {
      return !isPaused();
    }

    function isPaused() {
      return $video.get(0).paused;
    }

    function toggleControls() {
      if ($('.video-body').hasClass('muchuu')) {
        showControls();
      } else {
        hideControls();
      }
    }

    function setFadeOutInControls() {
      showControls();
      timeoutId = timeoutId = setTimeout(hideControls, inactivityTime);
    }

    function cancelFadeOutInControls(stop) {
      clearTimeout(timeoutId);
      if (stop !== undefined && stop === true) {
        showControls();
      } else {
        setFadeOutInControls();
      }
    }

    function hideControls() {
      $('.subtitles-menu').fadeOut();
      $('.controls-container').fadeOut(function() {
        $('.video-body').addClass('muchuu');
      });
    }

    function showControls() {
      $('.video-body').removeClass('muchuu');
      $('.controls-container').fadeIn();
    }

    function toggleFullscreen() {
      if (fullscreenOn) {
        exitFullscreen();
      } else {
        enterFullscreen($('.video-body').get(0));
      }
    }

    function enterFullscreen(video) {
      if (video.requestFullscreen) {
        video.requestFullscreen();
        fullscreenOn = true;
      } else if (video.mozRequestFullScreen) {
        video.mozRequestFullScreen();
        fullscreenOn = true;
      } else if (video.webkitRequestFullscreen) {
        video.webkitRequestFullscreen();
        fullscreenOn = true;
      } else if (video.msRequestFullscreen) {
        video.msRequestFullscreen();
        fullscreenOn = true;
      }
    }

    function exitFullscreen() {
      if (document.exitFullscreen) {
        document.exitFullscreen();
        fullscreenOn = false;
      } else if (document.mozCancelFullScreen) {
        document.mozCancelFullScreen();
        fullscreenOn = false;
      } else if (document.webkitExitFullscreen) {
        document.webkitExitFullscreen();
        fullscreenOn = false;
      } else if (document.msExitFullscreen) {
        document.msExitFullscreen();
        fullscreenOn = false;
      }
    }

    function onFullscreenChange(e) {
      fullscreenOn = document.fullscreenElement === e.target;
      console.log(fullscreenOn);
    }
  }
});