// ==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 = ''; //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 '; }