stream4chan

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

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

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

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

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

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

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

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         stream4chan
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Click the button to stream all webms in a 4chan thread
// @author       Lauchlan105
// @match        http://boards.4chan.org/*/thread/*
// @grant        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 = '<input id="stream4chan-auto?" class="SFC-input" type="checkbox" ' + autoPlayDefault + '> Play Automatically';
    var modalSettings_webms = '<input id="stream4chan-webms?" class="SFC-input" type="checkbox" ' + playWebmsDefault + '> Play Webms';
    var modalSettings_gifs = '<input id="stream4chan-gifs?" class="SFC-input" type="checkbox" ' + playGifsDefault + '> Play Gifs';
    var modalSettings_loopAll = '<input id="stream4chan-loopAll?" class="SFC-input" type="checkbox" ' + loopThreadDefault + '> Loop whole thread';
    var modalSettings_shuffle = '<input id="stream4chan-shuffle?" class="SFC-input" type="button" value=" shuffle ">';
    var modalSettings_random = '<input id="stream4chan-random?" class="SFC-input" type="checkbox" ' + randomDefault + '> Random';
    var modalSettings_duration = '<input id="stream4chan-duration?" class="SFC-input" type="number" min="' + countStep + '" max="60" value="' + durationDefault + '" step="' + countStep + '"> Gif Duration (Seconds)';
    var modalSettings_exit = '<div id="SFC-exit" class="SFC-li SFC-exit"></div>';
    var modalSettings = '<div id="stream4chan-settings" class="SFC-settings">' + modalSettings_auto + modalSettings_webms + modalSettings_gifs + modalSettings_loopAll + modalSettings_shuffle + modalSettings_random + modalSettings_duration + modalSettings_exit + '</div>';

/*
    var modalSettings_auto = '<li class="SFC-li"><input id="stream4chan-auto?" class="SFC-input" type="checkbox" ' + autoPlayDefault + '> Play Automatically</li>';
    var modalSettings_webms = '<li class="SFC-li"><input id="stream4chan-webms?" class="SFC-input" type="checkbox" ' + playWebmsDefault + '> Play Webms</li>';
    var modalSettings_gifs = '<li class="SFC-li"><input id="stream4chan-gifs?" class="SFC-input" type="checkbox" ' + playGifsDefault + '> Play Gifs</li>';
    var modalSettings_loopAll = '<li class="SFC-li"><input id="stream4chan-loopAll?" class="SFC-input" type="checkbox" ' + loopThreadDefault + '> Loop whole thread</li>';
    var modalSettings_shuffle = '<li class="SFC-li"><input id="stream4chan-shuffle?" class="SFC-input" type="button" value=" shuffle "></li>';
    var modalSettings_random = '<li class="SFC-li"><input id="stream4chan-random?" class="SFC-input" type="checkbox" ' + randomDefault + '> Random</li>';
    var modalSettings_exit = '<li class="SFC-li SFC-exit"></li>';
    var modalSettings_duration = '<li class="SFC-li"><input id="stream4chan-duration?" class="SFC-input" type="number" min="' + countStep + '" max="60" value="' + durationDefault + '" step="' + countStep + '"> Gif Duration (Seconds)</li>';
    var modalSettings = '<ul id="stream4chan-settings" class="SFC-settings">' + modalSettings_auto + modalSettings_webms + modalSettings_gifs + modalSettings_loopAll + modalSettings_shuffle + modalSettings_random + modalSettings_duration + modalSettings_exit + '</ul>';
*/
    //Content Table
    var modalContent = '<div id="stream4chan-content" class="SFC-content"></div>';
    var modalContent_Left = '<th id="stream4chan-prev" class="SFC_th_left SFC_arrow"></th>';
    var modalContent_Right = '<th id="stream4chan-next" class="SFC_th_right SFC_arrow"></th>';
    var modalContent_Mid = '<th class="SFC_th_mid">' + modalSettings + modalContent + '</th>';
    var modalTable = '<table id="stream4chan-table" class="SFC_table"><tr class="SFC_table_row">' + modalContent_Left + modalContent_Mid + modalContent_Right + '</tr></table>';

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

    //CSS
    var settingsCSS = '.SFC-settings { opacity: 0.35; display: inline-block; list-style-type: none; width:100%; top: 0; height: auto; margin: 0em; padding-top: 0.5em; color:#9d9393; }';
    var hoverCSS = '.SFC-settings:hover { opacity: 1; } .SFC-settings:last-child:hover { opacity: 0; }';
    var settingsInputCSS = '.SFC-input { margin: 0em 0em 0em 1.5em; padding: 0em;  }';
    var settingsExitCSS = '.SFC-exit { float: right; height: 28px; width: 28px; background-image: url("https://upload.wikimedia.org/wikipedia/commons/thumb/7/72/VisualEditor_-_Icon_-_Close_-_white.svg/2000px-VisualEditor_-_Icon_-_Close_-_white.svg.png"); background-size: contain; }';
    var AllSettingsCSS = settingsCSS + hoverCSS + settingsInputCSS + settingsExitCSS;

    //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 = '<style>' + allModalCSS + allTableCSS + AllSettingsCSS + '</style>';


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

    exit = document.getElementById('SFC-exit');
    if(!exit){ debug('Exit 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('webm')){
                    if(hrefs[currentVideo].paused){
                        hrefs[currentVideo].play();
                    }else{
                        hrefs[currentVideo].pause();
                    }
                }
            }
        }
    };

    exit.onclick = function(){ stop(); };
    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*2) + 'px';
    if(e){
        if(e.offsetHeight > (window.innerHeight - settings.offsetHeight*2)){
            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%';
        }

        if(content.offsetHeight > e.offsetHeight){
            e.style.marginTop = ((content.offsetHeight - e.offsetHeight)/2) + 'px';
            e.style.marginBottom = ((content.offsetHeight - e.offsetHeight)/2) + 'px';
        }else{
            e.style.marginTop = '0px';
            e.style.marginBottom = '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 ';
}