stream4chan

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

当前为 2016-10-19 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 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;
    }
}