stream4chan

Click the button to stream all webms in a 4chan thread

目前為 2016-10-19 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         stream4chan
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Click the button to stream all webms in a 4chan thread
// @author       Lauchlan105
// @match        http://boards.4chan.org/*/thread/*
// @grant        none
// ==/UserScript==


//Settings Header
countStep = 1;
modalSettings_auto = '<li class="SFC-li"><input id="stream4chan-auto?" class="SFC-input" type="checkbox" checked> Play Automatically</li>';
modalSettings_webms = '<li class="SFC-li"><input id="stream4chan-webms?" class="SFC-input" type="checkbox" checked> Play Webms</li>';
modalSettings_gifs = '<li class="SFC-li"><input id="stream4chan-gifs?" class="SFC-input" type="checkbox" checked> Play Gifs</li>';
modalSettings_loopAll = '<li class="SFC-li"><input id="stream4chan-loopAll?" class="SFC-input" type="checkbox" checked> Loop whole thread</li>';
modalSettings_shuffle = '<li class="SFC-li" style="display: none;"><input id="stream4chan-shuffle?" class="SFC-input" type="checkbox"> Randomize</li>';
modalSettings_duration = '<li class="SFC-li"><input id="stream4chan-duration?" class="SFC-input" type="number" min="' + countStep + '" max="60" value="3" step="' + countStep + '"> Gif Duration (Seconds)</li>';
    modalSettings = '<ul id="stream4chan-settings" class="SFC-settings">' + modalSettings_auto + modalSettings_webms + modalSettings_gifs + modalSettings_loopAll + modalSettings_shuffle + modalSettings_duration + '</ul>';

//Content Table
modalContent = '<div id="stream4chan-content" class="SFC-content"></div>';
modalContent_Left = '<th id="stream4chan-prev" class="SFC_th_left SFC_arrow"></th>';
modalContent_Right = '<th id="stream4chan-next" class="SFC_th_right SFC_arrow"></th>';
modalContent_Mid = '<th class="SFC_th_mid">' + modalSettings + modalContent + '</th>';
    modalTable = '<table id="stream4chan-table" class="SFC_table"><tr class="SFC_table_row">' + modalContent_Left + modalContent_Mid + modalContent_Right + '</tr></table>';

//Main Div
startBtn = '<input id="stream4chan-start" style="margin-left:1em;" type="button" value="Run Slideshow" >';
resumeBtn = '<input id="stream4chan-continue" style="margin-left:1em;" type="button" value="Resume Slideshow" >';
modalMain = '<div id="stream4chan-modal" class="SFC-modal">' + modalTable + '</div>';

//CSS
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; }';
settingsLiCSS = '.SFC-li { display: inline-block; padding-left: 1em; color:#9d9393;}';
settingsInputCSS = '.SFC-input { margin: 0em; padding: 0em; padding-top: 0.3em; width: auto;  }';
AllSettingsCSS = settingsCSS + settingsLiCSS + settingsInputCSS;

//table
tableCSS = '.SFC_table { max-height: 100vh; min-height: 100vh; max-width: 100vw; min-width: 100vw; } ';
tableRowCSS = '.SFC_table_row { vertical-align: top; }';
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; }';
leftCSS = '.SFC_th_left { transform: rotate(180deg); }' + '.SFC_th_left:hover { background-color:rgba(255, 255, 255, 0.6); }';
rightCSS = '.SFC_th_right {  }' + '.SFC_th_right:hover { background-color:rgba(255, 255, 255, 0.6); }';
midCSS = '.SFC_th_mid { height: 100vh;  }';
allTableCSS = tableCSS + tableRowCSS + arrowCSS + leftCSS + rightCSS + midCSS;

mediaCSS = '.SFC-media { width: 100%; }';
contentCSS = '.SFC-content { display: block; color: white; }';
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);}';
allModalCSS = mediaCSS + contentCSS + modalCSS;

allCSS = '<style>' + allModalCSS + allTableCSS + AllSettingsCSS + '</style>';

//Media Elements
gifDiv = '<img id="stream4chan-gif" class="SFC-media" src="" alt="Stream4chan - Gif not loaded!">';
webmDiv = '<video id="stream4chan-webm" class="SFC-media" src="" controls autoplay></video>';



//Main
(function() {
    injectNewElements();
    initVars();

    currentVideo = 0;
    window.onclick = function(event){if (event.target.id == 'stream4chan-content') { end(); }};
    window.onresize = function(){  };

    //event for key strokes
    document.onkeyup = function(event){

        //left arrow
        if(event.keyCode == 37 && document.getElementById('stream4chan-modal').style.display == 'block'){
            console.log(document.getElementById('stream4chan-modal').style.display);
            previousVideo();

        //right arrow
        }else if(event.keyCode == 39 && document.getElementById('stream4chan-modal').style.display == 'block'){
            console.log(document.getElementById('stream4chan-modal').style.display);
            nextVideo();

        //Escape key
        }else if(event.keyCode == 27 && document.getElementById('stream4chan-modal').style.display == 'block'){
            end();

        //W key
        }else if(event.keyCode == 87 && document.getElementById('stream4chan-modal').style.display == 'block'){
            playWebms.checked = !playWebms.checked;

        //G key
        }else if(event.keyCode == 71 && document.getElementById('stream4chan-modal').style.display == 'block'){
            playGifs.checked = !playGifs.checked;

        //A key
        }else if(event.keyCode == 65 && document.getElementById('stream4chan-modal').style.display == 'block'){
            autoplay.checked = !autoplay.checked;

        //L key
        }else if(event.keyCode == 76 && document.getElementById('stream4chan-modal').style.display == 'block'){
            loopAll.checked = !loopAll.checked;

        //R key
        }else if(event.keyCode == 82 && document.getElementById('stream4chan-modal').style.display == 'block'){
            random.checked = !random.checked;
        }else{
            //console.log(event.keyCode);
        }
    };
    document.onkeydown = function(event){
        //up arrow
        if(event.keyCode == 38 && document.getElementById('stream4chan-modal').style.display == 'block'){
            val = parseInt(duration.value, 10);
            max = parseInt(duration.max, 10);
            val += countStep;
            if(val > max){ val = max; }
            duration.value = val;

        //Down arrow
        }else if(event.keyCode == 40 && document.getElementById('stream4chan-modal').style.display == 'block'){
            val = parseInt(duration.value, 10);
            min = parseInt(duration.min, 10);
            val -= countStep;
            if(val < min){ val = min; }
            duration.value = val;
        }
    };
    
    startButton.onclick = function(){ start(); };
    resumeButton.onclick = function(){ initVars(); start(currentVideo, media.time); };
    autoplay.onclick = function(){ updateAutoplay(); };
    shuffle.onclick = function(){ initVars(); };
    prevBtn.onclick = function(){ previousVideo(); };
    nextBtn.onclick = function(){ nextVideo(); };
})();

//insert elements to html doc
function injectNewElements(){
    //add start slideshow button to navs
    var nav = document.getElementsByClassName("navLinks desktop");
    var i;
    if(nav){
        for(i = 0; i < nav.length; i++){
            nav[i].innerHTML += startBtn + resumeBtn;
        }
    }

    //add the modal to thread
    var target = document.getElementsByClassName('thread');
    for(i = 0; i < target.length; i++){
        target[i].innerHTML += modalMain + allCSS;
    }
}

//Assign the elemens that don't change to vars
function initVars(){
    modal = document.getElementById('stream4chan-modal');
    //if(!modal){ console.log('modal not found!');}

    startButton = document.getElementById('stream4chan-start');
    //if(!startButton){ console.log('Start button not found!');}

    resumeButton = document.getElementById('stream4chan-continue');
    //if(!resumeButton){ console.log('Resume button not found!');}

    table = document.getElementById('stream4chan-table');
    //if(!table){ console.log('table not found!');}

    prevBtn = document.getElementById('stream4chan-prev');
    //if(!prevBtn){ console.log('"Previous" button not found!');}

    content = document.getElementById('stream4chan-content');
    //if(!content){ console.log('content not found!');}

    nextBtn = document.getElementById('stream4chan-next');
    //if(!nextBtn){ console.log('"Next" button not found!');}

    media = document.getElementById('stream4chan-webm');
    if(!media){ media = document.getElementById('stream4chan-gif'); }
    //if(!media){ console.log('"Media" could not be found!'); }

    //Settings
    settings = document.getElementById('stream4chan-settings');
    //if(!settings){ console.log('"Settings" could not be found!'); }

    autoplay = document.getElementById('stream4chan-auto?');
    //if(!autoplay){ console.log('Autoplay checkbox not found!');}

    playWebms = document.getElementById('stream4chan-webms?');
    //if(!playWebms){ console.log('Player Webms input not found!');}

    playGifs = document.getElementById('stream4chan-gifs?');
    //if(!playGifs){ console.log('Player Gifs input not found!');}

    loopAll = document.getElementById('stream4chan-loopAll?');
    //if(!loopAll){ console.log('"loopAll" could not be found!'); }

    random = document.getElementById('stream4chan-shuffle?');
    //if(!random){ console.log('"random" could not be found!'); }

    playSelected = document.getElementById('stream4chan-playSelected?');
    //if(!playSelected){ console.log('"play selected" could not be found!'); }

    duration = document.getElementById('stream4chan-duration?');
    //if(!duration){ console.log('Gif duration input not found!');}

    //Misc
    currentTimeout = setTimeout(function(){}, (0));
    contentHrefs = document.getElementsByClassName("fileThumb");
    if(random.selected){ shuffle(contentHrefs); }
}

//start show
function start(position, time) {
    initVars();
    displayModal();

    currentTime = 0;
    currentVideo = 0;
    if(position){ currentVideo = position - 1; }
    if(time){ currentTime = time; }

    nextVideo();
}

//end show
function end() {
    initVars();
    modal.style.display = "none";

    var videoToPause = document.getElementById("stream4chan-webm");

    if(media){ currentTime = media.currentTime; }
    if(videoToPause){ videoToPause.pause(); }
    clearTimeout();

    var body = document.getElementsByTagName('body');
    for(i = 0; i < body.length; i++){
        if(body[i]){ body[i].style.overflow = "scroll"; }
    }
}

//Display the contents
function displayModal(){
    content.innerHTML = '';
    modal.style.display = "block";

    calcHeight();

    content.innerHTML = '<h1>No Video is Playing</h1>';

    var body = document.getElementsByTagName('body');
    for(i = 0; i < body.length; i++){
        if(body[i]){ body[i].style.overflow = "hidden"; }
    }
}

//Loads element based on URL
function displayVideo(href){
    filetype = getFiletype(href);
    media = document.getElementById("stream4chan-" + filetype);
    //create media if it's not there
    if(!media){
        if(filetype == 'gif'){
            content.innerHTML = gifDiv;
        }else if(filetype == 'webm'){
            content.innerHTML = webmDiv;
        }
        media = document.getElementById("stream4chan-" + filetype);
    }

    //change to new source, readjust the heigh, resume from last place
    media.src = href;
    initVars();
    calcHeight();
    if(filetype == 'webm'){
        media.onplay = function(){ calcHeight(); };
        media.currentTime = currentTime;
    }
}

//play next video
function nextVideo(){
    initVars();

    //If out of range
    if(0 > currentVideo || currentVideo > contentHrefs.length - 1){
        if(loopAll.checked){
            if(currentVideo < 0){
                currentVideo = contentHrefs.length - 1;
            }else{
                currentVideo = 0;
            }
        }else{
            console.log('out of range');
            end();
            displayModal();
            return;
        }
    }

    //Get filetype -> If its a gif and gifs are asked not to play -> return
    filetype = getFiletype(contentHrefs[currentVideo]);

    //skip if it can't play the current file
    if(!canPlay(currentVideo)){
       currentVideo++;
       nextVideo();
       return;
    }

    displayVideo(contentHrefs[currentVideo]);
    updateAutoplay();

    // increment the currentVideo
    currentVideo++;
}

//call next video when valid previous video is found
function previousVideo(){
    initVars();

    currentVideo--;
    while(currentVideo > -1){
        if(canPlay(currentVideo--)){ break; }
    }
    nextVideo();
}

//Returns true if current video is gif and gifs are selected etc
function canPlay(arrPosition){
    var currType = getFiletype(contentHrefs[arrPosition]);
    return !((currType == "gif" && !playGifs.checked) || (currType == "webm" && !playWebms.checked));
}

//Update timeouts and listeners to loop media
function updateAutoplay(){
    initVars();
    if(media){
        filename = getFiletype(media.src);

        if(filename == 'gif'){
            if(autoplay.checked){
                clearTimeout();
                currentTimeout = setTimeout(function(){
                    nextVideo();
                }, (duration.value*1000));
            }else{
                clearTimeout();
            }
        }else if(filename == 'webm'){
            media.loop = !autoplay.checked;
            clearTimeout();
            media.removeEventListener('ended', function(){ currentTime = 0; nextVideo();}, false);
            if(autoplay.checked){
                media.addEventListener('ended', function(){ currentTime = 0; nextVideo();}, false);
            }
        }else{
            console.log("Not a valid type! call to update autoplay");
        }
    }
    calcHeight();
}

//Clear Timeout functions to avoid related function calls
function clearTimeout(){
    if(currentTimeout){
        while(currentTimeout > 0){
            currentTimeout--;
            window.clearTimeout(currentTimeout);
        }
    }
}

//Return file extension type
function getFiletype(input){
    href = input.toString();
    return href.substr(href.lastIndexOf('.') + 1);
}

//Recalc height of content div to fit properly
function calcHeight(){
    initVars();
    content.style.height = window.innerHeight - settings.offsetHeight + "px";

    if(media){
        if(media.offsetHeight > (window.innerHeight - settings.offsetHeight)){
            media.style.height = '100%';
            media.style.width = 'auto';
        }

        if(media.offsetWidth > (window.innerWidth - (prevBtn.offsetWidth + nextBtn.offsetWidth))){
            media.style.width = '100%';
            media.style.height = 'auto';
        }
    }
}

//Shuffles the array of hrefs
function shuffle(input) {
    for (var i = input.length-1; i >=0; i--) {
        var randomIndex = Math.floor(Math.random()*(i+1));
        var itemAtIndex = input[randomIndex];

        input[randomIndex] = input[i];
        input[i] = itemAtIndex;
    }
}