// ==UserScript==
// @name stream4chan
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Click the button to stream all webms in a 4chan thread
// @author Lauchlan105
// @match http://boards.4chan.org/*/thread/*
// @grant none
// @downloadURL none
// ==/UserScript==
//Main
(function() {
createElements();
initElements();
startEvents();
})();
function createElements(){
//Script Settings
countStep = 1; //Duration step
debugOn = false;
hiddenPrints = [];
var checked = 'checked';
var notChecked = '';
var autoPlayDefault = checked;
var playWebmsDefault = checked;
var playGifsDefault = checked;
var loopThreadDefault = checked;
var randomDefault = notChecked;
var durationDefault = '3'; //seconds
//Settings Header
var modalSettings_auto = '
Play Automatically';
var modalSettings_webms = ' Play Webms';
var modalSettings_gifs = ' Play Gifs';
var modalSettings_loopAll = ' Loop whole thread';
var modalSettings_shuffle = '';
var modalSettings_random = ' Random';
var modalSettings_duration = ' Gif Duration (Seconds)';
var modalSettings = '' + modalSettings_auto + modalSettings_webms + modalSettings_gifs + modalSettings_loopAll + modalSettings_shuffle + modalSettings_random + modalSettings_duration + '
';
//Content Table
var modalContent = '';
var modalContent_Left = ' | ';
var modalContent_Right = ' | ';
var modalContent_Mid = '' + modalSettings + modalContent + ' | ';
var modalTable = '' + modalContent_Left + modalContent_Mid + modalContent_Right + '
';
//Main Div
var startBtn = '';
var resumeBtn = '';
var modalMain = '' + modalTable + '
';
//CSS
var settingsCSS = '.SFC-settings { opacity: 0.35; display: inline-block; list-style-type: none; width:100%; top: 0; height: 25px; margin: 0em; padding: 0em } .SFC-settings:hover { opacity: 1; }';
var settingsLiCSS = '.SFC-li { display: inline-block; padding-left: 1em; color:#9d9393;}';
var settingsInputCSS = '.SFC-input { margin: 0em; padding: 0em; padding-top: 0.3em; width: auto; }';
var AllSettingsCSS = settingsCSS + settingsLiCSS + settingsInputCSS;
//table
var tableCSS = '.SFC_table { max-height: 100vh; min-height: 100vh; max-width: 100vw; min-width: 100vw; } ';
var tableRowCSS = '.SFC_table_row { vertical-align: top; }';
var arrowCSS = '.SFC_arrow { width: 15px; padding: 15px; height: 100%; background-image: url("http://www.dsetechnology.co.uk/images/disclose-arrow.png"); background-repeat: no-repeat; background-position: center; background-color: rgba(255, 255, 255, 0); background-size: contain; }';
var leftCSS = '.SFC_th_left { transform: rotate(180deg); }' + '.SFC_th_left:hover { background-color:rgba(255, 255, 255, 0.6); }';
var rightCSS = '.SFC_th_right { }' + '.SFC_th_right:hover { background-color:rgba(255, 255, 255, 0.6); }';
var midCSS = '.SFC_th_mid { height: 100vh; }';
var allTableCSS = tableCSS + tableRowCSS + arrowCSS + leftCSS + rightCSS + midCSS;
var mediaCSS = '.SFC-media { width: 100%; }';
var contentCSS = '.SFC-content { display: block; color: white; }';
var modalCSS = ' .SFC-modal { display: none; height: 100vh; width: 100vw; position: fixed; z-index: 1; left: 0; top: 0; background-color: rgba(0,0,0,0.75); -webkit-box-shadow: inset 0px 0px 71px 41px rgba(0,0,0,0.75); -moz-box-shadow: inset 0px 0px 71px 41px rgba(0,0,0,0.75); box-shadow: inset 0px 0px 71px 41px rgba(0,0,0,0.75);}';
var allModalCSS = mediaCSS + contentCSS + modalCSS;
var allCSS = '';
//Add start and resume buttons
var nav = document.getElementsByClassName('navLinks desktop');
for(var i = 0; i < nav.length; i++){
debug('adding button to nav ' + i);
var span = document.createElement('span');
span.innerHTML = startBtn + resumeBtn;
span.className = 'stream4chan-start';
span.style.display = nav[i].style.display;
nav[i].parentNode.insertBefore(span, nav[i]);
nav[i].parentNode.insertBefore(document.getElementById('op'), nav[i]);
}
//add the modal to start of thread
var target = document.getElementsByClassName('thread');
for(i = 0; i < target.length; i++){
target[i].innerHTML = (modalMain + allCSS) + target[i].innerHTML;
}
}
function initElements(){
modal = document.getElementById('stream4chan-modal');
if(!modal){ debug('Modal not found!'); }
table = document.getElementById('stream4chan-table');
if(!table){ debug('Table not found!'); }
settings = document.getElementById('stream4chan-settings');
if(!settings){ debug('Settings not found!'); }
content = document.getElementById('stream4chan-content');
if(!content){ debug('Content not found!'); }
//Interactable Elements
prevButton = document.getElementById('stream4chan-prev');
if(!prevButton){ debug('Previous Button not found!'); }
nextButton = document.getElementById('stream4chan-next');
if(!nextButton){ debug('Next Button not found!'); }
startButton = document.getElementById('stream4chan-start');
if(!startButton){ debug('Start Button could not be found!');}
resumeButton = document.getElementById('stream4chan-resume');
if(!resumeButton){ debug('Resume Button could not be found!');}
autoplay = document.getElementById('stream4chan-auto?');
if(!autoplay){ debug('Autoplay checkbox not found!');}
playWebms = document.getElementById('stream4chan-webms?');
if(!playWebms){ debug('Player Webms input not found!');}
playGifs = document.getElementById('stream4chan-gifs?');
if(!playGifs){ debug('Player Gifs input not found!');}
loop = document.getElementById('stream4chan-loopAll?');
if(!loop){ debug('"loopAll" could not be found!'); }
random = document.getElementById('stream4chan-random?');
if(!random){ debug('"random" could not be found!'); }
shuffle = document.getElementById('stream4chan-shuffle?');
if(!shuffle){ debug('"shuffle" could not be found!'); }
duration = document.getElementById('stream4chan-duration?');
if(!duration){ debug('Gif duration input not found!');}
currentVideo = 'start';
currentTime = 0;
currentTimeout = setTimeout(0);
modalOn = false;
shuffled = false;
//hrefs = document.getElementsByClassName('fileThumb');
hrefs = [];
backup = [];
preload(hrefs);
}
function startEvents(){
window.onresize = function(){ setDimensions(contentExists()); };
window.onclick = function(event){if (event.target.id == 'stream4chan-content'){ stop(); }};
window.onkeydown = function(event){
event.target.blur();
if(!toggleDebug(event)){
//up arrow
if(event.keyCode == 38 && modalOn){
val = parseInt(duration.value, 10);
max = parseInt(duration.max, 10);
val += countStep;
if(val > max){ val = max; }
duration.value = val;
}
//Down arrow
if(event.keyCode == 40 && modalOn){
val = parseInt(duration.value, 10);
min = parseInt(duration.min, 10);
val -= countStep;
if(val < min){ val = min; }
duration.value = val;
}
}
};
window.onkeyup = function(event){
event.target.blur();
if(modalOn){
//left arrow
if(event.keyCode == 37){
previousVideo();
}
//right arrow
if(event.keyCode == 39){
nextVideo();
}
//Escape key
if(event.keyCode == 27){
stop();
}
//W key
if(event.keyCode == 87){
playWebms.checked = !playWebms.checked;
}
//G key
if(event.keyCode == 71){
playGifs.checked = !playGifs.checked;
}
//A key
if(event.keyCode == 65){
autoplay.checked = !autoplay.checked;
applyAutoplay();
}
//L key
if(event.keyCode == 76){
loopAll.checked = !loopAll.checked;
}
//R key
if(event.keyCode == 82){
random.checked = !random.checked;
if(random.checked){
shuffleArr();
}else{
unshuffleArr();
}
}
//S key
if(event.keyCode == 83){
if(shuffle.value === ' shuffle '){
shuffleArr();
}else{
unshuffleArr();
}
}
//Space key
if(event.keyCode == 32){
if(contentExists()){
pauseContent();
}else{
start(currentVideo, currentTime);
}
}
}
};
startButton.onclick = function(){ start(); };
resumeButton.onclick = function(){ start(currentVideo, currentTime); };
autoplay.onclick = function(){ applyAutoplay(); };
random.onclick = function(){
if(random.checked){
shuffleArr();
}else{
unshuffleArr();
}
};
prevButton.onclick = function(){ previousVideo(); };
nextButton.onclick = function(){ nextVideo(); };
shuffle.onclick = function(){
if(shuffle.value === ' unshuffle '){
unshuffleArr();
}else{
shuffleArr();
}
};
}
function displayModal(state){
var body = document.getElementsByTagName('body');
if(state === true){
debug('Show Modal');
modalOn = state;
modal.style.display = 'block';
//removes scoll bar
for(i = 0; i < body.length; i++){
if(body[i]){ body[i].style.overflow = "hidden"; }
}
}else if(state === false){
debug('Hide Modal');
modalOn = state;
modal.style.display = 'none';
//removes scoll bar
for(i = 0; i < body.length; i++){
if(body[i]){ body[i].style.overflow = "scroll"; }
}
}else{
if(modalOn){
debug('Hide Modal');
modal.style.display = 'none';
//removes scoll bar
for(i = 0; i < body.length; i++){
if(body[i]){ body[i].style.overflow = "scroll"; }
}
}else{
debug('Show Modal');
modal.style.display = 'block';
//removes scoll bar
for(i = 0; i < body.length; i++){
if(body[i]){ body[i].style.overflow = "hidden"; }
}
}
modalOn = !modalOn;
}
}
function start(crntVid, crntTime){
var newStart = (!crntVid && (crntVid !== 0));
currentVideo = !newStart ? crntVid-1 : 'start';
currentTime = crntTime ? crntTime : 0;
//resume if starting from the beginning
if(newStart){ unshuffleArr(); }
displayModal(true);
nextVideo();
}
function stop(){
if(contentExists()){
currentTime = contentExists('webm') ? contentExists('webm').currentTime : 0;
pauseContent();
}
content.innerHTML = '';
displayModal(false);
}
function nextVideo(){
pauseContent();
if(currentVideo === 'start'){ currentVideo = -1; }
//While the href can't be played
do{
currentVideo++;
if(loop.checked){
currentVideo = currentVideo % hrefs.length;
}
var temp = noContentToDisplay();
if(temp){
stop();
displayModal(true);
content.innerHTML = temp;
return;
}
}while(!canPlay(hrefs[currentVideo]));
playContent(hrefs[currentVideo]);
//add events for next video
applyAutoplay();
}
function previousVideo(){
debug('Function: previousVideo');
pauseContent();
if(currentVideo === 'start'){ currentVideo = 0; }
//While the href can't be played
do{
currentVideo--;
if(loop.checked){
if(currentVideo === -1){ currentVideo = hrefs.length -1;}
}
var temp = noContentToDisplay();
if(temp){
stop();
displayModal(true);
content.innerHTML = temp;
return;
}
}while(!canPlay(hrefs[currentVideo]));
playContent(hrefs[currentVideo]);
//add events for next video
applyAutoplay();
}
function playContent(currentContent){
debug('Function: playContent');
content.innerHTML = '';
if(random.checked){ shuffleArr(); }
content.appendChild(currentContent);
setDimensions(contentExists());
if(contentExists('webm')){
contentExists('webm').currentTime = currentTime;
currentTime = 0;
contentExists('webm').play();
}
//if(contentExists('gif')){ setTimeout(function(){}, duration.value); }
}
function pauseContent(){
debug('Function: pauseContent');
var x = contentExists('webm');
if(x){
x.removeEventListener('ended', nextVideo, false);
x.loop = true;
x.pause();
}
clearTimeout(currentTimeout);
content.innerHTML = 'Paused';
}
function canPlay(currentContent){
return ( (playGifs.checked && (getFileExt(currentContent.src) === 'gif')) || (playWebms.checked && (getFileExt(currentContent.src) === 'webm')) );
}
function getFileExt(input){
temp = input.toString();
return temp.substr(temp.lastIndexOf('.') + 1);
}
function preload(arr){
debug('Function: preload');
var temp = document.getElementsByClassName('fileThumb');
var x = null;
for (i = 0; i < temp.length; i++){
debug(' intitializing element: ' + temp[i]);
if(getFileExt(temp[i]) == 'gif'){
x = document.createElement('img');
x.setAttribute("id", "stream4chan-gif");
}else if (getFileExt(temp[i]) == 'webm'){
x = document.createElement('video');
x.setAttribute("id", "stream4chan-webm");
x.setAttribute("controls","");
x.setAttribute("loop","");
x.loop = true;
x.setAttribute("autoplay","");
x.autoplay = false;
x.setAttribute("ended","");
x.ended = false;
}
x.setAttribute("src",temp[i]);
x.setAttribute("style", "height: 100%; width: auto;");
arr.push(x);
backup.push(x);
}
}
function debug(text){
if(debugOn){
console.log(text);
}else{
hiddenPrints.push(text);
}
}
function toggleDebug(e) {
var evtobj = window.event? event : e;
if (!e || evtobj.keyCode == 68 && evtobj.ctrlKey && evtobj.altKey && evtobj.shiftKey){
debug('Function: toggleDebug');
if(debugOn){
console.log('##Debug Off##');
debugOn = false;
}else{
console.log('##Debug On##');
debugOn = true;
for(var i = 0; i < hiddenPrints.length; i++){
debug(hiddenPrints[i]);
}
hiddenPrints = [];
}
return true;
}
return false;
}
function setDimensions(e){
debug('Function: setDimensions');
content.style.height = window.innerHeight - settings.offsetHeight + 'px';
if(e){
if(e.offsetHeight > (window.innerHeight - settings.offsetHeight)){
debug(' Content was taller');
e.style.height = '100%';
e.style.width = 'auto';
}
if(e.offsetWidth > (window.innerWidth - (prevButton.offsetWidth + nextButton.offsetWidth))){
debug(' Content was wider');
e.style.height = 'auto';
e.style.width = '100%';
e.style.margin = ((content.offsetHeight - e.offsetHeight - settings.offsetHeight)/2) + 'px 0px';
}
}
}
function contentExists(type){
debug('Function: contentExists');
if(type){
return document.getElementById('stream4chan-' + type);
}else{
var div = document.getElementById('stream4chan-webm');
if(!div){ div = document.getElementById('stream4chan-gif'); }
return div;
}
}
function thereAre(type){
debug('Function: thereAre');
if(type){
for(i = 0; i < hrefs.length; i++){
if(getFileExt(hrefs[i].src) === type){
return true;
}
}
}
debug(' Error: argument not passed to function');
return false;
}
function noContentToDisplay(){
debug('Function: noContentToDisplay');
var text = false;
//End and display modal if nothing can play
if(!playGifs.checked && !playWebms.checked){
text = 'Nothing selected to play';
}
//End and display modal if nothing can play
if(!thereAre('gif') && (playGifs.checked && !playWebms.checked)){
text = 'No gifs!';
}
//End and display modal if nothing can play
if(!thereAre('webm') && (!playGifs.checked && playWebms.checked)){
text = 'No Webms!';
}
//End and display modal if nothing can play
if(!thereAre('gif') && !thereAre('webm')){
text = 'No Gifs or Webs';
}
//End and display modal if out of range
if( 0 > currentVideo || currentVideo > hrefs.length-1){
text = 'End of Thread';
if(currentVideo < 0){ text = 'Start of thread'; }
}
if(text){ debug(' Returning: '+ text); }
return text;
}
function applyAutoplay(){
debug('Function: applyAutoplay');
var x = contentExists();
debug(' ' + getFileExt(x.src) + ' event listener is ' + autoplay.checked);
clearTimeout();
if(getFileExt(x.src) === 'webm'){
x.loop = !autoplay.checked;
x.removeEventListener('ended', nextVideo, false);
if(autoplay.checked){
x.addEventListener('ended', nextVideo, false);
}
}
if(getFileExt(x.src) === 'gif' && autoplay.checked){
currentTimeout = setTimeout(nextVideo, duration.value*1000);
}
}
function shuffleArr() {
debug('Function: shuffleArr');
var j, x, i;
for (i = hrefs.length; i; i--) {
j = Math.floor(Math.random() * i);
x = hrefs[i - 1];
hrefs[i - 1] = hrefs[j];
hrefs[j] = x;
}
shuffled = true;
shuffle.value = ' unshuffle ';
}
function unshuffleArr() {
debug('Function: unshuffleArr');
hrefs = backup.slice();
if(contentExists()){
for(var i = 0; i < hrefs.length; i++){
if(hrefs[i].src === contentExists().src){
currentVideo = i;
break;
}
}
}
shuffled = false;
shuffle.value = ' shuffle ';
}