Youtube Player Speed Slider

Add Speed Slider to Youtube Player Settings

目前为 2016-11-25 提交的版本。查看 最新版本

// ==UserScript==
// @name         Youtube Player Speed Slider
// @namespace    youtube_player_speed_slider
// @version      0.1.3
// @description  Add Speed Slider to Youtube Player Settings
// @author       Łukasz and Witold
// @match        https://*.youtube.com/*
// @grant        none
// ==/UserScript==

var yts = {};

yts.option = {
    timeoutBuild: 500,
    timeoutRemove: 1000,
    lastClick: 0
};

yts.elements = {
    menu : null,
    speedMenu: null,
    slider: null,
    sliderLabel: null
};

yts.modules = [
    'setting',
    'i18'
];

/*************************************
 *          TRANSLATION              *
 ************************************/
yts.i18 = {};

yts.i18.dic = {
    pl: {
        'Speed': 'Szybkość',
        'Annotation': 'Adnotacje',
        'Settings': 'Ustawienia'
    },
    en: {
        'Speed': 'Speed',
        'Annotation': 'Annotation',
        'Settings': 'Settings'
    },
    de: {
        'Speed' : 'Geschwindigkeit',
        'Annotation': '',
        'Settings': 'Einstellungen'
    },
    fr:{
        'Speed':'Vitesse',
        'Annotation':'',
        'Settings':'Paramètres'
    }
};

yts.i18.opt = {
    lang: 'en',
    default: 'en',
    map:{
        pl: 'pl',
        pl_pl: 'pl',
        en: 'en',
        en_gb: 'en',
        de: 'de',
        fr: 'fr'
    }
};

yts.i18.init = function () {
    yts.i18.opt.lang = yts.i18.getLang();
};

yts.i18.getLang = function () {
    var lang = yts.i18.filter(yts.setting.get('lang'));
    if(lang !== '' && yts.i18.isAllow(lang)){
        return yts.i18.map(lang);
    }

    lang = yts.i18.filter(yts.dom.get('html').getAttribute('lang'));
    if(lang !== '' && yts.i18.isAllow(lang)){
        return yts.i18.map(lang);
    }

    return yts.i18.opt.default;
};

yts.i18.isAllow = function (lang) {
    return yts.i18.opt.map.hasOwnProperty(lang);
};

yts.i18.t = function (pattern) {
    if(yts.i18.dic[yts.i18.opt.lang].hasOwnProperty(pattern)){
        return yts.i18.dic[yts.i18.opt.lang][pattern];
    }
    else {
        return pattern;
    }
};

yts.i18.filter = function (lang) {
    return lang ? lang.replace('-', '_').toLowerCase() : '';
};

yts.i18.map = function (lang) {
    return  yts.i18.opt.map[lang]
};


/*************************************
 *          INIT                     *
 ************************************/
yts.init = function () {
    yts.player.update();
    yts.modules.forEach(function (module) {
        yts[module].init();
    });
    yts.option.lastClick = (new Date()).getTime();
    yts.dom.event(document, "spfdone", yts.player.update);
    yts.menu.reopen();
    yts.buildApp();
};

yts.buildApp = function () {
    yts.elements.menu = yts.dom.get('.ytp-panel-menu');
    if (yts.elements.menu !== null) {
        setTimeout(yts.menu.removeDefaultSpeed, yts.option.timeoutRemove);

        yts.menu.build();
        yts.annot.init();
    }
    else {
        setTimeout(yts.buildApp, yts.option.timeoutBuild);
    }
};


/*************************************
 *          MENU                    *
 ************************************/
yts.menu = {};

yts.menu.build = function () {
    yts.slider.build();

    var speedMenu = yts.dom.new('div', {
        'className': 'ytp-menuitem'
    });

    var right = yts.dom.new('div', {
        'className': 'ytp-menuitem-content'
    });

    yts.elements.sliderLabel = yts.dom.new('div', {
        'className': 'ytp-menuitem-label'
    });

    yts.slider.updateLabel(1);
    speedMenu.appendChild(yts.elements.sliderLabel);
    speedMenu.appendChild(right.appendChild(yts.elements.slider));
    yts.elements.menu.appendChild(speedMenu);
    yts.menu.event();
};

yts.menu.event = function () {
    yts.elements.menu.addEventListener('click', yts.menu.click);
};

yts.menu.removeDefaultSpeed = function(){
    var switchers = yts.dom.getOpt(".ytp-menuitem", {role:'menuitemcheckbox'});
    switchers[switchers.length-1].nextElementSibling.style.display = 'none';
};

yts.menu.reopen = function () {
    var settings_button = yts.dom.get(".ytp-settings-button");
    settings_button.click();
    settings_button.click();
};

yts.menu.click = function () {
    yts.option.lastClick = (new Date()).getTime();
};

/*************************************
 *          SLIDER                   *
 ************************************/
yts.slider = {};

yts.slider.build = function () {
    yts.elements.slider = yts.dom.new('input', {
        'className': '',
        'type': 'range',
        'min': 0.5,
        'max': 4,
        'step': 0.1,
        'value': 1
    });
    yts.dom.event(yts.elements.slider, 'change', yts.slider.change);
    yts.dom.event(yts.elements.slider, 'input', yts.slider.move);
};

yts.slider.move = function (event) {
    yts.slider.updateLabel(event.target.value);
};

yts.slider.change = function (event) {
    yts.player.duration(event.target.value);
};

yts.slider.updateLabel = function (val) {
    yts.elements.sliderLabel.innerHTML = yts.i18.t('Speed') + ': ' + parseFloat(val).toFixed(1);
};


/*************************************
 *          PLAYER                   *
 ************************************/
yts.player = {};

yts.player.update = function(){
    yts.elements.player = yts.dom.get('.html5-main-video')

};
yts.player.duration = function(value){
    yts.elements.player.playbackRate = value;
};


/*************************************
 *          ANNOTATION               *
 ************************************/
yts.annot = {};
yts.annot.init = function(){
    if(yts.setting.get('annot') !== 'on'){
        yts.observer.init(yts.elements.menu, yts.annot.change);
    }
};

yts.annot.change = function (mutation) {
    if(mutation.type == "attributes" && mutation.target.getAttribute('role')=="menuitemcheckbox"){
        yts.annot.switchOff();
    }
};

yts.annot.switchOff = function(){
    var switchers = yts.dom.getOpt(".ytp-menuitem", {role:'menuitemcheckbox'});
    if(switchers.length == 2){
        setTimeout(function (switcher) {
                if((new Date).getTime() - yts.option.lastClick > 1000 &&
                    switcher.getAttribute('aria-checked') == "true"){
                    switcher.click();
                }
            },
            500,
            switchers[1]
        );
    }
};

yts.annot.switchOffAlways = function(){
    yts.setting.set('annot', 'off');
    yts.annot.switchOff();
};

yts.annot.switchOn = function(){
    yts.setting.set('annot', 'on');
};



/*************************************
 *          COOKIE                   *
 ************************************/
yts.cookie ={};

yts.cookie.set = function (name, value, days) {
    days = days || 366;
    var d = new Date();
    d.setTime(d.getTime() + (days*24*60*60*1000));
    var expires = "expires="+ d.toUTCString();
    document.cookie = name + "=" + value + ";" + expires + ";path=/";
};

yts.cookie.get = function (name) {
    name += "=";
    var ca = document.cookie.split(';');
    for(var i = 0; i <ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') {
            c = c.substring(1);
        }
        if (c.indexOf(name) == 0) {
            return c.substring(name.length,c.length);
        }
    }
    return "";
};


/************************************
*                DOM                *
************************************/
yts.dom = {};

yts.dom.event = function (obj, event, callback) {
    obj.addEventListener(event, callback);
};

yts.dom.new = function (tag, option) {
    var element = document.createElement(tag);
    for (var param in option) {
        element[param] = option[param];
    }
    return element;
};

yts.dom.get = function (tselector, all) {
    all = all || false;
    var type = tselector.substring(0, 1);
    var selector = tselector.substring(1);
    var elements;
    if (type == "#") {
        return document.getElementById(selector);
    }
    else if (type == ".") {
        elements = document.getElementsByClassName(selector);
    }
    else{
        elements = document.querySelectorAll(tselector);
    }

    if (all) {
        return elements;
    }
    else {
        return elements.length ? elements[0] : null;
    }
};

yts.dom.getOpt = function(selector, option){
    var el = yts.dom.get(selector, true);
    var pass = [];
    var correct;
    for(var i =0; i< el.length; i++){
        correct = true;
        for(var prop in option){
            if(!yts.dom.has(el[i], prop, option[prop])){
                correct = false;
                break;
            }
        }
        if(correct){
            pass.push(el[i]);
        }
    }
    return pass;
};

yts.dom.has = function (elem, key, val) {
    if(elem.hasAttribute(key)){
        var attr = elem.getAttribute(key);
        if(val !== null){
            return attr == val;
        }
        return true;
    }
    return false;
};


/*************************************
 *          MENU OBSERVER            *
 ************************************/
yts.observer= {};

yts.observer.obj = null;

yts.observer.get = function () {
    return window.MutationObserver || window.WebKitMutationObserver;
};

yts.observer.init = function (element, callback) {
    var MutationObserver = yts.observer.get();
    if( MutationObserver ){
        var obs = new MutationObserver(function(mutations, observer){
            callback(mutations[0]);
        });

        obs.observe( element, {
            childList: true,
            subtree: true,
            attributes:true,
            characterData:true,
            attributeOldValue:true,
            characterDataOldValue:true
        });
    }
};


/*************************************
 *          SETTINGS                 *
 ************************************/
yts.setting = {};

yts.setting.settings = null;
yts.setting.init = function(){
    var cookie = yts.cookie.get('yts_s');
    yts.setting.settings = JSON.parse(cookie == '' ? '{}' : cookie);
};
yts.setting.set = function(key, val){
    yts.setting.settings[key] = val;
    yts.cookie.set('yts_s', JSON.stringify(yts.setting.settings));
};
yts.setting.get = function(kay){
    return yts.setting.settings.hasOwnProperty(kay) ?
        yts.setting.settings[kay] : null;
};

yts.init();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址