diff --git a/Enhanced RT.user.js b/Enhanced RT.user.js
index 61f5422..94ae1d1 100644
--- a/Enhanced RT.user.js
+++ b/Enhanced RT.user.js
@@ -1,6 +1,6 @@
// ==UserScript==
// @name Enhanced RT
-// @version 2.0.6
+// @version 3.0.0
// @description Enhancments for the Rooster Teeth family of websites
// @include *://*.roosterteeth.com/*
// @exclude *://store.roosterteeth.com/*
@@ -51,6 +51,15 @@ To be fixed
Versions
========
+3.0.0
+-Added initial support for the Rooster Teeth Beta site.
+-Created Beta site Recently Added video page which uses Rooster Teeth's API to determine available channles and videos.
+-Beta site Recently Added page displays videos in a grid view, allows the user to loaded additional videos on the page, and the videos can be filtered by channel.
+-Beta site RECENT VIDEOS text on home page is converted to a clickable link to the Recently Added page.
+-Beta site video comment timestamps are converted to clickable links.
+-Beta site Binge Mode on/off setting added to the settings page.
+
+
2.0.6
-Removed temporary fix that adds Sugar Pine 7 to the channel filter drop down options. No longer needed now that it has been officially added to the website.
@@ -248,6 +257,10 @@ commentsStopPlayback = ((localStorage.getItem("commentsStopPlayback") == null) ?
replaceFavicon = ((localStorage.getItem("replaceFavicon") == null) ? 0 : localStorage.getItem("replaceFavicon"));
+// SVOD Beta Load Endless Video Setting
+var videoBinge = ((localStorage.getItem("video-binge") == null) ? "true" : localStorage.getItem("video-binge"));
+
+
// *************
// Detect Domain
// *************
@@ -323,6 +336,11 @@ else if(window.location.host.search("sugarpine7.roosterteeth.com") >= 0) // Suga
// favicon
var favIcon = "";
}
+else if(window.location.host.search("svod.roosterteeth.com") >= 0) // SVOD
+{
+ currentSite = "SVOD";
+ var favIcon = "";
+}
else
{
currentSite = "Unknown";
@@ -333,6 +351,9 @@ else
//console.log(currentSiteDomain);
+if(currentSite != "SVOD") // Not on SVOD
+{
+
// **************
// Change favicon
// **************
@@ -370,7 +391,7 @@ currentPage = parseInt(currentPage);
// *************
if(window.location.pathname=="/EnhancedRT/settings")
{
- var settings = document.getElementById("body-block");
+ var settings = document.getElementById("body-block");
var settingsHTML = "
Enhanced RT Settings
Recently Added Page Settings
\n";
//";
for ( i = 0; i < hide.length; i++)
@@ -476,6 +497,8 @@ if(window.location.pathname=="/EnhancedRT/settings")
}
+
+
// *******************
// Recently Added Page
// *******************
@@ -509,7 +532,7 @@ if(window.location.pathname=="/episode/recently-added")
/**/
-
+
for ( i = 0; i < hide.length; i++)
{
filtersHTML = filtersHTML.concat("");
@@ -1058,4 +1081,1027 @@ if(window.location.pathname.search("/livestream/") >= 0)
window.scrollTo(0, parseInt(scrollPos));
}
}
+}
+
+}// Not on SVOD
+else // On SVOD
+{
+ // Try to use MutationObserver to detect page changes since Beta site loads pages differently
+
+ /*
+ // select the target node
+ var target = document.getElementsByClassName("main-col")[0];
+
+ // create an observer instance
+ var observer = new MutationObserver(function(mutations) {
+ mutations.forEach(function(mutation) {
+ console.log(mutation);
+ });
+ console.log("Page Change Detected");
+ console.log(window.location.pathname);
+ });
+
+ // configuration of the observer:
+ //var config = { attributeFilter: ["style"] };
+ var config = { childList:true, subtree:true };
+
+
+ // pass in the target node, as well as the observer options
+ observer.observe(target, config);
+ */
+
+
+ (function(win) {
+ 'use strict';
+
+ var listeners = [],
+ doc = win.document,
+ MutationObserver = win.MutationObserver || win.WebKitMutationObserver,
+ observer;
+
+ function ready(selector, fn) {
+ // Store the selector and callback to be monitored
+ listeners.push({
+ selector: selector,
+ fn: fn
+ });
+ if (!observer) {
+ // Watch for changes in the document
+ observer = new MutationObserver(check);
+ observer.observe(document.getElementsByClassName("main-col")[0], {
+ childList: true,
+ subtree: true
+ });
+ }
+ // Check if the element is currently in the DOM
+ check();
+ }
+
+ function check() {
+ // Check the DOM for elements matching a stored selector
+ for (var i = 0, len = listeners.length, listener, elements; i < len; i++) {
+ listener = listeners[i];
+ // Query for elements matching the specified selector
+ elements = doc.querySelectorAll(listener.selector);
+ for (var j = 0, jLen = elements.length, element; j < jLen; j++) {
+ element = elements[j];
+ // Make sure the callback isn't invoked with the
+ // same element more than once
+ if (!element.ready) {
+ element.ready = true;
+ // Invoke the callback with the element
+ listener.fn.call(element, element);
+ }
+ }
+ }
+ }
+
+ // Expose `ready`
+ win.ready = ready;
+
+ })(this);
+
+
+ ready('.carousel-title', function(element) {
+ //console.log("Enhanced RT: Carousel Detected");
+ //console.log(element.childNodes[0].nodeValue);
+
+ if(element.childNodes[0] != undefined && element.childNodes[0].nodeValue == "recent videos")
+ {
+ var recentLink = document.createElement("a");
+ recentLink.className = "carousel-title link";
+ recentLink.href = "/episode/recently-added";
+ recentLink.appendChild(document.createTextNode("recent videos "));
+ var recentArrow = document.createElement("i");
+ recentArrow.className = "show-more icon-keyboard_arrow_right";
+ recentLink.appendChild(recentArrow);
+ element.parentNode.insertBefore(recentLink, element);
+ element.parentNode.removeChild(element);
+ }
+
+ });
+
+
+ ready('.episode-main', function(element) {
+ if(window.location.pathname.search("/episode/recently-added") >= 0)
+ {
+ //console.log("Enhanced RT: Recently Added Page Detected");
+ //console.log(element);
+ recentlyAdded();
+ }
+ });
+
+
+ ready('.Linkify', function(element) {
+ if(window.location.pathname.search("/episode/") >= 0)
+ {
+ //console.log("Enhanced RT: Comment Detected");
+ //console.log(element);
+ detectVideoTimestamps(element);
+ }
+ });
+
+ ready('.settings-app', function(element) {
+ //console.log("Enhanced RT: Settings Page Detected");
+ displaySettings();
+ });
+
+
+
+ // *******************
+ // Settings Page
+ // *******************
+ function displaySettings()
+ {
+ //console.log(document.getElementsByClassName("simplebar-content")[1]);
+
+ // Create elements for Enhanced RT settings
+ var settingsDiv = document.createElement("div");
+ settingsDiv.className = "settings-app__page";
+ settingsDiv.style = "margin-top: 50px;";
+
+ var settingsSection = document.createElement("section");
+ settingsSection.className = "settings-app__section";
+
+ var settingsHeader = document.createElement("h2");
+ settingsHeader.className = "settings-app__subheading";
+ settingsHeader.appendChild(document.createTextNode("Enhanced RT"));
+
+ var settingsList = document.createElement("ul");
+ settingsList.className = "form-list";
+
+ var settingsItem = document.createElement("li");
+ settingsItem.className = "form-list__row qa-username-form";
+
+ var settingsLabel = document.createElement("span");
+ settingsLabel.className = "form-list__label";
+ settingsLabel.appendChild(document.createTextNode("Binge Mode"));
+
+ var settingsCell = document.createElement("div");
+ settingsCell.className = "form-list__cell";
+
+ var settingsCheckbox = document.createElement("input");
+ settingsCheckbox.type = "checkbox";
+ settingsCheckbox.id = "video-binge";
+ settingsCheckbox.defaultChecked = ((videoBinge == "true") ? true : false);
+ //console.log(videoBinge);
+ //console.log(settingsCheckbox.defaultChecked);
+
+ settingsCheckbox.style="position: static; opacity: 100; pointer-events:auto; margin:0 0 0 1em; width: 17px; height: 17px;";
+
+ settingsDiv.appendChild(settingsSection);
+ settingsSection.appendChild(settingsHeader);
+ settingsSection.appendChild(settingsList);
+ settingsList.appendChild(settingsItem);
+ settingsItem.appendChild(settingsLabel);
+ settingsItem.appendChild(settingsCell);
+ settingsCell.appendChild(settingsCheckbox);
+
+ document.getElementsByClassName("simplebar-content")[1].appendChild(settingsDiv);
+
+
+ document.getElementById("video-binge").onclick = function (event)
+ {
+ if(videoBinge == "true")
+ {
+ videoBinge = "false";
+ localStorage.setItem("video-binge", videoBinge);
+ }
+ else
+ {
+ videoBinge = "true";
+ localStorage.setItem("video-binge", videoBinge);
+ }
+ };
+
+
+ //console.log(document.getElementsByClassName("simplebar-content")[1]);
+
+ }
+
+ // Get settings from local storage
+ var watchedFilter = new Array;
+ var watchedFilterString = localStorage.getItem("enhancedRT_watchedFilter");
+ watchedFilter = ((watchedFilterString == null) ? [] : JSON.parse(watchedFilterString));
+
+ var streamFilter = new Array;
+ var streamFilterString = localStorage.getItem("enhancedRT_streamFilter");
+ streamFilter = ((streamFilterString == null) ? [] : JSON.parse(streamFilterString));
+
+ var channelFilter = new Array;
+ var channelFilterString = localStorage.getItem("enhancedRT_channelFilter");
+ channelFilter = ((channelFilterString == null) ? [] : JSON.parse(channelFilterString));
+
+ var seriesFilter = new Array;
+ var seriesFilterString = localStorage.getItem("enhancedRT_seriesFilter");
+ seriesFilter = ((seriesFilterString == null) ? [] : JSON.parse(seriesFilterString));
+
+
+ // *******************
+ // Recently Added Page
+ // *******************
+ function recentlyAdded()
+ {
+
+
+ var episodePage = 1;
+ var episodesPerPage = 24;
+
+
+ // ***Initial Setup Start***
+
+ // Create elements for episode grid
+ var showWrapperDiv = document.createElement("div");
+ showWrapperDiv.className = "show-main__wrapper";
+
+ // Start by appending parent element to page. The other elements will be added to it.
+ document.getElementsByClassName("simplebar-content")[1].appendChild(showWrapperDiv);
+
+ // ***Filters Setup Start***
+
+ // Filters
+ var CenterHeader = document.createElement("center");
+ var headerDiv = document.createElement("div");
+ var pageTitleHeader = document.createElement("h4");
+ pageTitleHeader.className = "shows-title";
+ var pageTitleSpan = document.createElement("span");
+ CenterHeader.appendChild(headerDiv);
+ headerDiv.appendChild(pageTitleHeader);
+ pageTitleHeader.appendChild(pageTitleSpan);
+ pageTitleSpan.appendChild(document.createTextNode("Recently Added (Enhanced RT)"));
+ showWrapperDiv.appendChild(CenterHeader);
+
+
+
+
+ // Get List of Channels
+ var channelsXMLHttp = new XMLHttpRequest();
+
+ channelsXMLHttp.onreadystatechange = function() {
+ if (this.readyState == 4 && this.status == 200) {
+ var channelsObj = JSON.parse(this.responseText);
+
+ for (var i = 0, len = channelsObj.data.length; i < len; i++)
+ {
+ //console.log("Name: " + channelsObj.data[i].attributes.name + " ID: " + channelsObj.data[i].uuid);
+ //channelArray[channelsObj.data[i].uuid] = "true";
+
+
+ var channelLabel = document.createElement("label");
+ channelLabel.style = "font-size: 1.64rem;";
+ var channelCheckbox = document.createElement("input");
+ channelCheckbox.type = "checkbox";
+ channelCheckbox.id = channelsObj.data[i].uuid;
+ channelCheckbox.defaultChecked = ((channelFilter.indexOf(channelsObj.data[i].uuid) == -1) ? true : false);
+ channelCheckbox.style = "position: static; opacity: 100; pointer-events:auto; margin:0 0 0 1em; width: 17px; height: 17px;";
+ channelLabel.appendChild(channelCheckbox);
+ channelLabel.appendChild(document.createTextNode(channelsObj.data[i].attributes.name));
+
+ headerDiv.appendChild(channelLabel);
+
+ channelLabel.onclick = function (event)
+ {
+ if(event.target.checked == true)
+ {
+ //console.log("onclick checked: " + event.target.checked);
+ if (channelFilter.indexOf(event.target.id) != -1) {
+ channelFilter.splice(channelFilter.indexOf(event.target.id), 1);
+ }
+ localStorage.setItem("enhancedRT_channelFilter", JSON.stringify(channelFilter));
+ }
+ else if(event.target.checked == false)
+ {
+ //console.log("onclick unchecked: " + event.target.checked);
+ if (channelFilter.indexOf(event.target.id) == -1) {
+ channelFilter.push(event.target.id)
+ }
+ localStorage.setItem("enhancedRT_channelFilter", JSON.stringify(channelFilter));
+ }
+
+ hideVideos();
+ checkForEndlessTrigger();
+ };
+
+ }
+ }
+ };
+
+ // Request channels list from server
+ channelsXMLHttp.open("GET", "https://svod-be.roosterteeth.com/api/v1/channels", true);
+ channelsXMLHttp.send();
+
+ /*
+ for ( i = 0; i < hide.length; i++)
+ {
+ //"
+ var channelLabel = document.createElement("label");
+ //channelLabel.style = "color:#666;font-size:12px;";
+ channelLabel.style = "font-size: 1.64rem;";
+
+ var channelCheckbox = document.createElement("input");
+ //channelCheckbox.style = "margin:0 0 0 1em;";
+ channelCheckbox.type = "checkbox";
+ channelCheckbox.id = hide[i][hideText];
+ channelCheckbox.defaultChecked = ((hide[i][hideValue] == 0) ? true : false);
+ channelCheckbox.style = "position: static; opacity: 100; pointer-events:auto; margin:0 0 0 1em; width: 17px; height: 17px;";
+ channelLabel.appendChild(channelCheckbox);
+ channelLabel.appendChild(document.createTextNode(hide[i][hideName]));
+
+ headerDiv.appendChild(channelLabel);
+
+ document.getElementById( hide[i][hideText] ).onclick = function (event) {
+ if(hide[eval(event.target.id)][hideValue] == 1)
+ {
+ hide[eval(event.target.id)][hideValue] = 0;
+ localStorage.setItem(hide[eval(event.target.id)][hideText], hide[eval(event.target.id)][hideValue]);
+ }
+ else
+ {
+ hide[eval(event.target.id)][hideValue] = 1;
+ localStorage.setItem(hide[eval(event.target.id)][hideText], hide[eval(event.target.id)][hideValue]);
+ }
+
+ hideVideos();
+ checkForEndlessTrigger();
+ };
+ }
+ */
+
+ /*
+ var rtLogoDiv = document.createElement("div");
+ rtLogoDiv.style="background-color: #c9373f; width: 50px; height: 50px; -webkit-mask-box-image: url(https://svod.roosterteeth.com/img/RT_Cockbite_White.png);"
+ headerDiv.appendChild(rtLogoDiv);
+ var ahLogoDiv = document.createElement("div");
+ ahLogoDiv.style="background-color: #5f9f41; width: 50px; height: 50px; -webkit-mask-box-image: url(https://svod.roosterteeth.com/img/AH_Logo_White.png);"
+ headerDiv.appendChild(ahLogoDiv);
+ var fhLogoDiv = document.createElement("div");
+ fhLogoDiv.style="background-color: #fe8204; width: 50px; height: 50px; -webkit-mask-box-image: url(https://svod.roosterteeth.com/img/FH_Logo_White.png);"
+ headerDiv.appendChild(fhLogoDiv);
+ var saLogoDiv = document.createElement("div");
+ saLogoDiv.style="background-color: #00aeef; width: 50px; height: 50px; -webkit-mask-box-image: url(https://svod.roosterteeth.com/img/SA_Logo_White.png);"
+ headerDiv.appendChild(saLogoDiv);
+ var ccLogoDiv = document.createElement("div");
+ ccLogoDiv.style="background-color: #d5b037; width: 50px; height: 50px; -webkit-mask-box-image: url(https://svod.roosterteeth.com/img/CC_Logo_White.png);"
+ headerDiv.appendChild(ccLogoDiv);
+ var sp7LogoDiv = document.createElement("div");
+ sp7LogoDiv.style="background-color: #1bb479; width: 50px; height: 50px; -webkit-mask-box-image: url(https://svod.roosterteeth.com/img/SP7_Logo_White.png);"
+ headerDiv.appendChild(sp7LogoDiv);
+ var gaLogoDiv = document.createElement("div");
+ gaLogoDiv.style="background-color: #8b54dc; width: 50px; height: 50px; -webkit-mask-box-image: url(https://svod.roosterteeth.com/img/GA_Logo_White.png);"
+ headerDiv.appendChild(gaLogoDiv);
+ var tkLogoDiv = document.createElement("div");
+ tkLogoDiv.style="background-color: #00639d; width: 50px; height: 50px; -webkit-mask-box-image: url(https://svod.roosterteeth.com/img/TK_Logo_White.png);"
+ headerDiv.appendChild(tkLogoDiv);
+ var jtLogoDiv = document.createElement("div");
+ jtLogoDiv.style="background-color: #FC1334; width: 175px; height: 175px; -webkit-mask-image: url(https://rtv3-image.roosterteeth.com/store/bed8a666-3528-4c89-9dc9-643bacf0c681.png/original/SongsAboutGamesLogo.png); -webkit-mask-position: right; transform: scale(0.33);"
+ headerDiv.appendChild(jtLogoDiv);
+
+ https://svod.roosterteeth.com/img/JT_Logo_White.png
+ */
+
+
+ // ***Filters Setup End***
+
+
+
+ // ***Episode Grid Setup Start***
+
+
+ var showContainerSection = document.createElement("section");
+ showContainerSection.className = "show-container";
+
+ var showContentDiv = document.createElement("div");
+ showContentDiv.className = "show-content";
+
+ var carouselContainerSection = document.createElement("section");
+ carouselContainerSection.className = "carousel-container";
+
+ var episodeGridContainerDiv = document.createElement("div");
+ episodeGridContainerDiv.className = "episode-grid-container row";
+
+ var showMoreDiv = document.createElement("div");
+ showMoreDiv.className = "col s12 show-more";
+ showMoreDiv.appendChild(document.createTextNode("show more"));
+
+ var arrowDownIcon = document.createElement("i");
+ arrowDownIcon.className = "icon-keyboard_arrow_down";
+
+ // Connect elements for episode grid
+ showWrapperDiv.appendChild(showContainerSection);
+ showContainerSection.appendChild(showContentDiv);
+ showContentDiv.appendChild(carouselContainerSection);
+ carouselContainerSection.appendChild(episodeGridContainerDiv);
+ episodeGridContainerDiv.appendChild(showMoreDiv);
+ showMoreDiv.appendChild(arrowDownIcon);
+
+ showMoreDiv.onclick = function (event)
+ {
+ getEpisodes(xmlhttp, episodePage, episodesPerPage);
+ episodePage++;
+ hideVideos();
+ //checkForEndlessTrigger();
+ };
+
+ // Move footer to new location
+ document.getElementsByClassName("show-main__wrapper")[0].appendChild(document.getElementsByClassName("footer-container")[0]);
+
+ // Delete episodes div that will not be used
+ document.getElementsByClassName("episode-content")[0].remove();
+
+
+
+ // ***Episode Grid Setup End***
+
+
+
+ // ***Episode Clone Setup Start***
+
+
+
+ // Create elements used to display individual episode
+ var episodeDiv = document.createElement("div");
+ episodeDiv.className = "col s12 m4 l3";
+
+ var episodeCardDiv = document.createElement("div");
+ episodeCardDiv.className = "episode-card";
+
+ var cardContentDiv = document.createElement("div");
+ cardContentDiv.className = "card-content";
+
+ var cardImageDiv = document.createElement("div");
+ cardImageDiv.className = "card-image-wrapper";
+
+ var imageLink = document.createElement("a");
+ imageLink.href = "***Episode URL***";
+
+ var imageDiv = document.createElement("div");
+ imageDiv.className = "image";
+ imageDiv.style = "background-image: url(\"***Thumbnail URL***\");";
+
+ var timestampDiv = document.createElement("div");
+ timestampDiv.className = "timestamp";
+ timestampDiv.appendChild(document.createTextNode("***Timestamp Text***"));
+
+
+ var infoDiv = document.createElement("div");
+ infoDiv.className = "info-line";
+
+ var infoLeftDiv = document.createElement("div");
+ infoLeftDiv.className = "info-left";
+
+ var titleLink = document.createElement("a");
+ titleLink.className = "episode-title";
+ titleLink.href = "***Episode URL***";
+ titleLink.appendChild(document.createTextNode("***Episode Title Text***"));
+
+ var episodeExtraDiv = document.createElement("div");
+ episodeExtraDiv.className = "episode-extra";
+ var dateText = document.createTextNode("***Episode Date***");
+
+ var seriesLink = document.createElement("a");
+ seriesLink.className = "episode-extra__link";
+ seriesLink.href = "***Series URL***";
+ seriesLink.appendChild(document.createTextNode("***Series Name Text***"));
+
+
+ // Connect elements for individual episode
+ episodeDiv.appendChild(episodeCardDiv);
+ episodeCardDiv.appendChild(cardContentDiv);
+ cardContentDiv.appendChild(cardImageDiv);
+ cardImageDiv.appendChild(imageLink);
+ imageLink.appendChild(imageDiv);
+ imageLink.appendChild(timestampDiv);
+ cardContentDiv.appendChild(infoDiv);
+ infoDiv.appendChild(infoLeftDiv);
+ infoLeftDiv.appendChild(titleLink);
+ infoLeftDiv.appendChild(episodeExtraDiv);
+ episodeExtraDiv.appendChild(seriesLink);
+ episodeExtraDiv.appendChild(dateText);
+
+
+
+
+ // ***Episode Clone Setup Start***
+
+
+
+ // ***Initial Setup End***
+
+
+
+
+ // Get List of Episodes
+ var xmlhttp = new XMLHttpRequest();
+ /*
+ xmlhttp.status = function() {
+ console.log();
+
+ }
+ */
+ xmlhttp.onreadystatechange = function() {
+ if (this.readyState == 4 && this.status == 200) {
+
+ // Episode list
+ var myObj = JSON.parse(this.responseText);
+
+ // Parse episodes in list
+ for (var i = 0, len = myObj.data.length; i < len; i++) {
+ //console.log("Title: " + myObj.data[i].attributes.title + " Show: " + myObj.data[i].attributes.show_title + " Channel: " + myObj.data[i].attributes.channel_id);
+
+ // Clone element structure for individual episodes. Don't need to rebuild the whole structure for each episode.
+ var cloneEpisodeDiv = episodeDiv.cloneNode(true);
+
+ // Update cloned elements with current episodes information
+ cloneEpisodeDiv.id = myObj.data[i].attributes.channel_id;
+ cloneEpisodeDiv.getElementsByClassName("card-image-wrapper")[0].childNodes[0].href = "/episode/" + myObj.data[i].attributes.slug;
+ cloneEpisodeDiv.getElementsByClassName("image")[0].style = "background-image: url(\"" + myObj.data[i].included.images["0"].attributes.small + "\");";
+ cloneEpisodeDiv.getElementsByClassName("episode-title")[0].href = "/episode/" + myObj.data[i].attributes.slug;
+ cloneEpisodeDiv.getElementsByClassName("episode-title")[0].childNodes[0].nodeValue = myObj.data[i].attributes.display_title;
+ cloneEpisodeDiv.getElementsByClassName("episode-extra__link")[0].href = "/series/" + myObj.data[i].attributes.show_slug;
+ cloneEpisodeDiv.getElementsByClassName("episode-extra__link")[0].childNodes[0].nodeValue = myObj.data[i].attributes.show_title;
+
+ // Format episode length to human readable
+ var totalSeconds = myObj.data[i].attributes.length;
+ hours = Math.floor(totalSeconds / 3600);
+ totalSeconds %= 3600;
+ minutes = Math.floor(totalSeconds / 60);
+ seconds = totalSeconds % 60;
+ cloneEpisodeDiv.getElementsByClassName("timestamp")[0].childNodes[0].nodeValue = ((hours == 0) ? minutes : hours + ":" + ('0'+minutes).slice(-2)) +':'+ ('0'+seconds).slice(-2);
+
+ // Format episode date to human readable
+ var episodeDate = new Date(myObj.data[i].sort["0"]);
+ var episodeDateFormatted = ('0' + (episodeDate.getMonth()+1)).slice(-2) + '/' + ('0' + episodeDate.getDate()).slice(-2) + '/' + episodeDate.getFullYear();
+ cloneEpisodeDiv.getElementsByClassName("episode-extra")[0].childNodes[1].nodeValue = " | " + episodeDateFormatted;
+
+ // Add episode to page
+ document.getElementsByClassName("episode-grid-container")[0].insertBefore(cloneEpisodeDiv, document.getElementsByClassName("show-more")[0]);
+ }
+
+ hideVideos();
+ }
+ };
+
+ // Get initial set of episodes
+ getEpisodes(xmlhttp, episodePage, episodesPerPage);
+ episodePage++;
+
+
+
+
+
+
+
+
+
+ // *********************
+ // Endless Video Loading
+ // *********************
+
+
+ // Setup scroll listener
+
+
+ /*document.addEventListener("scroll", function (event)
+ {
+ console.log("Scrolling");
+
+ checkForEndlessTrigger();
+ });
+
+ window.onscroll=window.onresize= check;
+ document.addEventListener("wheel", function (e) {
+
+ check();
+
+ }, true);
+
+ function check()
+ {
+ console.log("Scrolling");
+
+ }
+ */
+
+
+ /*
+ var observer = new IntersectionObserver((entries, observer) => {
+ entries.forEach(entry => {
+ //callback(entry.intersectionRatio > 0);
+ console.log("Show More Visible");
+ });
+ }, options);
+
+ var options = {root: document.documentElement}
+ observer.observe(showMoreDiv);
+
+
+ // Don't load a new page if already loading one.
+ var endlessLoadingInProgress = 0;
+
+ // Number of pages loaded without a break
+ var endlessPagesLoaded = 1;
+
+ // Is loading paused?
+ var loadingPaused = 0;
+ */
+
+ checkForEndlessTrigger = function()
+ {
+ /*
+ console.log("checkForEndlessTrigger");
+ //var endlessFrameHTML = document.getElementsByClassName("pagination")[0];
+ //if(endlessFrameHTML == undefined){return;}
+ //var endlessOffset = endlessFrameHTML.offsetTop + endlessFrameHTML.clientHeight;
+ var endlessOffset = showMoreDiv.offsetTop + showMoreDiv.clientHeight;
+ var pageOffset = window.pageYOffset + window.innerHeight;
+
+ // Check if scrolled low enough to load more videos
+ if(pageOffset > (endlessOffset - 100) && endlessVideos == 1)
+ {
+ //console.log("EndlessTriggered");
+
+ }
+ */
+ };
+
+ //checkForEndlessTrigger();
+ }
+
+
+
+
+ function getEpisodes(xmlhttp, episodePage, episodesPerPage)
+ {
+ //Make sure you can't request more episodes if a request is already in progress.
+ //Make sure you can't keep loading past the last page of videos available.
+ //Make Loading Animation, possibly the orange loading circle used on the Beta site.
+ // Stop loading every 10 pages and show button to load more
+
+ // Request episodes list from server
+ xmlhttp.open("GET", "https://svod-be.roosterteeth.com/api/v1/episodes?page=" + episodePage + "&per_page=" + episodesPerPage, true);
+ xmlhttp.send();
+ }
+
+
+
+
+ // *******************************
+ // Hide Watched or Filtered Videos
+ // *******************************
+ function hideVideos()
+ {
+
+ var episode = document.getElementsByClassName("col s12 m4 l3");
+ for ( i = 0; i < episode.length; i++)
+ {
+ if(channelFilter.indexOf(episode[i].id) != -1)
+ {
+ episode[i].style.display = "none";
+ }
+ else
+ {
+ episode[i].style.display = "";
+ }
+ }
+
+ /*
+ var episode = document.getElementsByClassName("col s12 m4 l3");
+ for ( i = 0; i < episode.length; i++)
+ {
+ //episode[i].style.display = "";
+
+ if(episode[i].id == "achievement-hunter")
+ {
+ if(hide[hideAH][hideValue] == 1)
+ {
+ episode[i].style.display = "none";
+ }
+ }
+ else if(episode[i].id == "the-know")
+ {
+ if(hide[hideTK][hideValue] == 1)
+ {
+ episode[i].style.display = "none";
+ }
+ }
+ else if(episode[i].id == "rooster-teeth")
+ {
+ if(hide[hideRT][hideValue] == 1)
+ {
+ episode[i].style.display = "none";
+ }
+ }
+ else if(episode[i].id == "funhaus")
+ {
+ if(hide[hideFH][hideValue] == 1)
+ {
+ episode[i].style.display = "none";
+ }
+ }
+ else if(episode[i].id == "screwattack")
+ {
+ if(hide[hideSA][hideValue] == 1)
+ {
+ episode[i].style.display = "none";
+ }
+ }
+ else if(episode[i].id == "cow-chop")
+ {
+ if(hide[hideCC][hideValue] == 1)
+ {
+ episode[i].style.display = "none";
+ }
+ }
+ else if(episode[i].id == "game-attack")
+ {
+ if(hide[hideGA][hideValue] == 1)
+ {
+ episode[i].style.display = "none";
+ }
+ }
+ else if(episode[i].id == "sugar-pine-7")
+ {
+ if(hide[hideSP7][hideValue] == 1)
+ {
+ episode[i].style.display = "none";
+ }
+ }
+ else if(hide[hideUnknown][hideValue] == 1)
+ {
+ episode[i].style.display = "none";
+ }
+ */
+
+
+
+ /*
+ // Hide Streams
+ if(hide[hideStreams][hideValue] == 1)
+ {
+ if(episode[i].childNodes[0].childNodes[0].childNodes[0].childNodes[0].href.search("episode/(.*-full-stream|fullhaus|.*-live-stream|past-livestreams|.*yt-primetime)") >= 0)
+ {
+ episode[i].style.display = "none";
+ }
+ }
+ */
+
+ /*
+ if(hide[hideWatched][hideValue] == 1)
+ {
+ var watched = document.getElementsByClassName("watched");
+ for ( i = 0; i < watched.length; i++)
+ {
+ //watched[i].parentNode.parentNode.parentNode.parentNode.parentNode.style.display = " "+((hide[hideWatched][hideValue] == 1) ? "none" : "")+"";
+ watched[i].parentNode.parentNode.parentNode.parentNode.parentNode.style.display = "none";
+ }
+ }
+ */
+
+ //}
+
+ }
+
+
+
+
+
+ // **************
+ // Any Video Page
+ // **************
+ function detectVideoTimestamps(comment)
+ {
+ //console.log(comment);
+
+ for ( var i = 0; i < comment.childNodes.length; i++)
+ {
+ //comment.childNodes[i].nodeValue = comment[i].childNodes[i].nodeValue.replace(/(?!]*?>)(-)?((\d|\d\d)(:))?(\d|\d\d)(:)(\d\d)(?![^<]*?<\/a>)/g, "$1$3$4$5$6$7");
+ //console.log("i: " + i);
+
+ var currentNode = i;
+ var splitTimestamp = null;
+ var contiguousTextCount = 0;
+ var contiguousText;
+
+ if(comment.childNodes[i].nodeName == "#text") // Only check text nodes for timestamps
+ {
+ //console.log(comment.childNodes[i].nodeValue);
+ contiguousText = comment.childNodes[i].nodeValue;
+ contiguousTextCount++;
+
+ while(comment.childNodes[i+1] != undefined && comment.childNodes[i+1].nodeName == "#text")
+ {
+ contiguousText += comment.childNodes[i+1].nodeValue;
+ contiguousTextCount++;
+ i++;
+ }
+
+ //console.log("contiguousTextCount: " + contiguousTextCount + " Text: " + contiguousText);
+ //splitTimestamp = comment.childNodes[i].nodeValue.split(/([\d]{0,2}:?[\d]{1,2}:[\d]{2})/g);
+ //splitTimestamp = comment.childNodes[i].nodeValue.split(/((?:(?:2[0-3]|[01]?[0-9]):)?[0-5]?[0-9]:[0-5][0-9])/g);
+ splitTimestamp = contiguousText.split(/((?:(?:2[0-3]|[01]?[0-9]):)?[0-5]?[0-9]:[0-5][0-9])/g);
+ //console.log(splitTimestamp);
+ }
+
+ if(splitTimestamp != null && splitTimestamp.length > 1) // If array size is 1 we know that there were no matches.
+ {
+ //console.log("splitTimestamp checked");
+
+
+
+ for ( var j = 0; j < splitTimestamp.length; j++)
+ {
+ //console.log("j: " + j);
+ //console.log(splitTimestamp[j]);
+ if(splitTimestamp[j] != "") // Split produces empty arrary elements if match is at the end or begining of string. Ignore them.
+ {
+
+ //var matchTimestamp = splitTimestamp[j].match(/([\d]{0,2}:)?([\d]{1,2}):([\d]{2})/);
+ var matchTimestamp = splitTimestamp[j].match(/(?:(2[0-3]|[01]?[0-9]):)?([0-5]?[0-9]):([0-5][0-9])/);
+ if(matchTimestamp != null)
+ {
+ var commentNode = document.createElement("a");
+ commentNode.onclick = getTimestampLink(matchTimestamp);
+ commentNode.href = "javascript:undefined";
+ commentNode.title = "Go to video timestamp " + matchTimestamp[0];
+ commentNode.appendChild(document.createTextNode(matchTimestamp[0]));
+
+
+
+ }
+ else
+ {
+ var commentNode = document.createTextNode(splitTimestamp[j]);
+ }
+
+ if(comment.childNodes[i+1] != undefined)
+ {
+ comment.insertBefore(commentNode, comment.childNodes[i+1]);
+ }
+ else
+ {
+ comment.appendChild(commentNode);
+ }
+
+ i++; // We inserted a new child so we need to increment i so it still points at the next child.
+ }
+ }
+
+ while(contiguousTextCount > 0)
+ {
+ comment.removeChild(comment.childNodes[currentNode]); // Remove the node we replaced with timestamp link
+ contiguousTextCount--;
+ i--; // We removed a node so we need to decrement i so it still points at the next child.
+ }
+ }
+ }
+
+ }
+
+ /*
+ function linkVideoTimestamps()
+ {
+
+ var commentElement = document.getElementsByClassName("Linkify");
+ console.log("linkVideoTimestamps function");
+ console.log(commentElement);
+ console.log(commentElement.length);
+ console.log(commentElement[0]);
+ for ( var i = 0; i < commentElement.length; i++)
+ {
+ console.log("i: " + i);
+ for ( var j = 0; j < commentElement[i].childNodes.length; j++)
+ {
+ //commentElement[i].childNodes[j].nodeValue = commentElement[i].childNodes[j].nodeValue.replace(/(?!]*?>)(-)?((\d|\d\d)(:))?(\d|\d\d)(:)(\d\d)(?![^<]*?<\/a>)/g, "$1$3$4$5$6$7");
+ console.log("j: " + j);
+ var splitTimestamp = null;
+
+ if(commentElement[i].childNodes[j].nodeName == "#text") // Only check text nodes for timestamps
+ {
+ console.log(commentElement[i].childNodes[j].nodeValue);
+ splitTimestamp = commentElement[i].childNodes[j].nodeValue.split(/([\d]{0,2}:?[\d]{1,2}:[\d]{2})/g);
+ }
+
+ if(splitTimestamp != null && splitTimestamp.length > 1) // If array size is 1 we know that there were no matches.
+ {
+ console.log("splitTimestamp checked");
+ console.log(splitTimestamp[0]);
+
+ var insertCount = 0;
+ var currentNode = j;
+
+ for ( var k = 0; k < splitTimestamp.length; k++)
+ {
+ console.log("k: " + k);
+ if(splitTimestamp[k] != "") // Split produces empty arrary elements if match is at the end or begining of string. Ignore them.
+ {
+
+ var matchTimestamp = splitTimestamp[k].match(/([\d]{0,2}:)?([\d]{1,2}):([\d]{2})/);
+ if(matchTimestamp != null)
+ {
+ var commentNode = document.createElement("a");
+ commentNode.onclick = getTimestampLink(matchTimestamp);
+ commentNode.href = "javascript:undefined";
+ commentNode.title = "Go to video timestamp " + matchTimestamp[0];
+ commentNode.appendChild(document.createTextNode(matchTimestamp[0]));
+
+
+
+ }
+ else
+ {
+ var commentNode = document.createTextNode(splitTimestamp[k]);
+ }
+
+ if(commentElement[i].childNodes[j+1] != undefined)
+ {
+ commentElement[i].insertBefore(commentNode, commentElement[i].childNodes[j+1]);
+ }
+ else
+ {
+ commentElement[i].appendChild(commentNode);
+ }
+ j++; // We inserted a new child so we need to increment j so it still points at the next child.
+ }
+ }
+
+ commentElement[i].removeChild(commentElement[i].childNodes[currentNode]); // Remove the node we replaced with timestamp link
+ j--; // We removed a node so we need to decrement j so it still points at the next child.
+
+ }
+
+
+ //.replace(/[\d]{0,2}:?[\d]{1,2}:[\d]{2}/g, "timestamp.");
+ //commentElement[i].childNodes[j].nodeValue
+ // Add anchor element instead of altering text
+ }
+
+ /*
+ while(commentElement[i].children[1].children[j].tagName != "DIV")
+ {
+ //console.log("Comment: "+i+", Line: "+j)
+ //commentElement[i].children[1].children[j].innerHTML = commentElement[i].children[1].children[j].innerHTML.replace(/(?!]*?>)((\d|\d\d)(:))?(\d|\d\d)(:)(\d\d)(?![^<]*?<\/a>)/g, "$2$3$4$5$6");
+
+ commentElement[i].children[1].children[j].innerHTML = commentElement[i].children[1].children[j].innerHTML.replace(/(?!]*?>)(-)?((\d|\d\d)(:))?(\d|\d\d)(:)(\d\d)(?![^<]*?<\/a>)/g, "$1$3$4$5$6$7");
+ j++;
+
+ //1 is $1, 2 is $2, 3 is $3, 4 is $4, 5 is $5, 6 is $6, 7 is $7, //regex parts for testing
+ }
+
+ // Check for comment replies
+ j++;
+ //console.log(commentElement[i].children[1].children[j]);
+ if(commentElement[i].children[1].children[j] != undefined)
+ {
+ //console.log(commentElement[i].children[1].children[j].tagName);
+ if(commentElement[i].children[1].children[j].tagName == "FORM")
+ {
+ j++;
+ }
+
+ if(commentElement[i].children[1].children[j].children[0] != undefined)
+ {
+ //console.log(commentElement[i].children[1].children[j].children.length+" comment Replies Detected");
+ var commentReplies = commentElement[i].children[1].children[j].children;
+ linkVideoTimestamps(commentReplies);
+ }
+ }
+
+
+ }
+
+
+ }
+ */
+
+ function getTimestampLink (matchTimestamp)
+ {
+ return function()
+ {
+ var videoID = document.getElementsByTagName("video")[0].id;
+ document.getElementsByClassName('video-container')[0].scrollIntoView(false);
+ document.getElementById(videoID).currentTime=(((matchTimestamp[1] != undefined)?parseInt(matchTimestamp[1]):0 * 3600) + (parseInt(matchTimestamp[2]) * 60) + parseInt(matchTimestamp[3]));
+ document.getElementById(videoID).play();
+ //console.log(((matchTimestamp[1] != undefined)?parseInt(matchTimestamp[1]):0 * 3600));
+ }
+
+ }
+
+
+
+ /*
+ var controls = document.getElementsByClassName("controls")[0];
+
+ // If there is more than 1 page of comments
+ if(controls != undefined)
+ {
+ controls.addEventListener('click', function() {
+ setTimeout(function() {
+ var commentsList = document.getElementsByClassName("comments-list");
+ var comment = commentsList[0].children;
+ linkVideoTimestamps(comment);
+ }, 7000);
+ });
+ }
+ */
+
}
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
index fac749e..bb2ca7e 100644
--- a/manifest.json
+++ b/manifest.json
@@ -14,5 +14,5 @@
"description": "Enhancements for the Rooster Teeth family of websites.",
"name": "Enhanced RT",
"author": "Patrick Maher",
- "version": "2.0.6"
+ "version": "3.0.0"
}
\ No newline at end of file