Greasy Fork

来自缓存

Greasy Fork is available in English.

bilibili关灯

bilibili关灯(把被新版B站藏起来的关灯按钮揪出来,在关闭弹幕按钮左边,还可以用快捷键,默认'A')、非全屏滚轮音量控制、弹幕控制快捷操作等

当前为 2021-08-18 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         bilibili关灯
// @namespace    hhh2000
// @version      0.9.4
// @description  bilibili关灯(把被新版B站藏起来的关灯按钮揪出来,在关闭弹幕按钮左边,还可以用快捷键,默认'A')、非全屏滚轮音量控制、弹幕控制快捷操作等
// @author       hhh2000
// @include      http*://www.bilibili.com/video/av*
// @include      http*://www.bilibili.com/video/BV*
// @include      http*://www.bilibili.com/watchlater/*
// @include      http*://www.bilibili.com/medialist/play/*
// @include      http*://www.bilibili.com/bangumi/play/ep*
// @include      http*://www.bilibili.com/bangumi/play/ss*
// @include      http*://bangumi.bilibili.com/anime/*/play*
// @include      http*://bangumi.bilibili.com/movie/*
// @exclude      http*://bangumi.bilibili.com/movie/
// @require      https://cdn.staticfile.org/jquery/1.12.4/jquery.min.js
// @run-at       document-end
// @grant        none
// ==/UserScript==

'use strict';
hhh_lightoff_main = {
    init() {
        var //
            ver,
            fps,
            h5Player,
            is_in_biliplayer;
        const [BILI_2_X, BILI_3_X, ALL] = ['bili_2.x', 'bili_3.x', 'all'];
        var //切换番剧和一般视频class
            bb = {},
            bb_type = '',
            bb_config = {
                bb_class_data: {  //其实这样不方便调试
                    //'player':{BILI_2_X:'.player', [BILI_3_X]:'.bpx-player'}, //main

                    'playTipWrap':{[BILI_2_X]  :'.bilibili-player-dm-tip-wrap', [BILI_3_X]:'.bpx-player-video-perch'}, //paly/pause
                    'fullScreen':{[BILI_2_X]   :'.bilibili-player-video-btn-fullscreen', [BILI_3_X]:'.squirtle-video-fullscreen.squirtle-video-item'}, //全屏
                    'webFullScreen':{[BILI_2_X]:'.bilibili-player-video-web-fullscreen', [BILI_3_X]:'.squirtle-video-pagefullscreen.squirtle-video-item'}, //网页全屏
                    'wideScreen':{[BILI_2_X]   :'.bilibili-player-video-btn-widescreen', [BILI_3_X]:'.squirtle-video-widescreen.squirtle-video-item'}, //宽屏

                    //弹幕
                    'danmukuTopClose':{[BILI_2_X]:'.bilibili-player-block-filter-type[data-name=ctlbar_danmuku_top_close]', [BILI_3_X]:'.bpx-player-block-filter-type.bpx-player-block-typeTop.bpx-player-active'}, //顶部弹幕
                    'danmukuTop'     :{[BILI_2_X]:'.bilibili-player-block-filter-type[ftype=top]', [BILI_3_X]:'.bpx-player-block-filter-type.bpx-player-block-typeTop'}, //顶部弹幕
                    'danmukuBottomClose':{[BILI_2_X]:'.bilibili-player-block-filter-type[data-name=ctlbar_danmuku_bottom_close]', [BILI_3_X]:'.bpx-player-block-filter-type.bpx-player-block-typeBottom.bpx-player-active'}, //底部弹幕
                    'danmukuBottom'     :{[BILI_2_X]:'.bilibili-player-block-filter-type[ftype=bottom]', [BILI_3_X]:'.bpx-player-block-filter-type.bpx-player-block-typeBottom'}, //底部弹幕
                    'progressVal'   :{[ALL]:'.bui-progress-val'}, //弹幕透明度读数
                    'progressWrap'  :{[ALL]:'.bui-progress-wrap'}, //弹幕透明度进度条
                    'settingOpacity':{[BILI_2_X]:'.bilibili-player-setting-opacity', [BILI_3_X]:'.bpx-player-dm-setting-ui-opacity'}, //弹幕透明度
                    'settingArea'   :{[BILI_2_X]:'.bilibili-player-setting-area', [BILI_3_X]:'.bpx-player-dm-setting-ui-area'}, //显示区域
                    'settingFs'     :{[BILI_2_X]:'.bilibili-player-video-danmaku-setting-left-fs input', [BILI_3_X]:'.bpx-player-dm-setting-left-fs input'}, //弹幕随屏幕缩放

                    //音量
                    'volumeHint'    :{[BILI_2_X]:'.bilibili-player-volumeHint', [BILI_3_X]:'.bpx-player-volume-hint'}, //音量显示
                    'volumeHintText':{[BILI_2_X]:'.bilibili-player-volumeHint-text', [BILI_3_X]:'.bpx-player-volume-hint-text'}, //音量显示百分比读数
                    'volumeHintIcon':{[BILI_2_X]:'.bilibili-player-volumeHint-icon', [BILI_3_X]:'.bpx-player-volume-hint-icon'}, //音量显示图标
                    'volumebarWrp'  :{[BILI_2_X]:'.bilibili-player-video-volumebar-wrp', [BILI_3_X]:'.squirtle-volume-bar-wrap'}, //音量条
                    'volumeNum'     :{[BILI_2_X]:'.bilibili-player-video-volume-num', [BILI_3_X]:'.squirtle-volume-num'}, //音量读数

                    //视频速度
                    'videoSpeedActive':{[BILI_2_X]:'.bilibili-player-video-btn-speed-menu-list.bilibili-player-active', [BILI_3_X]:'.squirtle-speed-select-list .squirtle-select-item.active'}, //视频速度
                    'videoSpeed':{[BILI_2_X]:'.bilibili-player-video-btn-speed-menu-list', [BILI_3_X]:'.squirtle-speed-select-list .squirtle-select-item'}, //视频速度
                    'videoSpeedName':{[BILI_2_X]:'.bilibili-player-video-btn-speed-name', [BILI_3_X]:'.squirtle-select-result.squirtle-speed-select-result'}, //视频速度

                    //弹幕设置等
                    'switchBody':{[ALL]:'.bui-switch-body'}, //系统关灯css设置
                    'switchDot':{[ALL]:'.bui-switch-dot'}, //系统弹幕设置按钮wrap进度条拖动点
                    'switchInput':{[ALL]:'.bui-switch-input'}, //弹幕设置switch按钮
                    'danmakuRoot':{[BILI_2_X]:'.bilibili-player-video-danmaku-root', [BILI_3_X]:'.bpx-player-dm-root'}, //系统弹幕设置条
                    'danmakuSwitch':{[BILI_2_X]:'.bilibili-player-video-danmaku-switch', [BILI_3_X]:'.bpx-player-dm-switch'}, //关闭弹幕按钮
                    'danmakuSetting':{[BILI_2_X]:'.bilibili-player-video-danmaku-setting', [BILI_3_X]:'bpx-player-dm-setting'}, //系统弹幕设置按钮
                    'danmakuSettingWrap':{[BILI_2_X]:'.bilibili-player-video-danmaku-setting-wrap', [BILI_3_X]:'.bpx-player-dm-setting-wrap'}, //系统弹幕设置按钮wrap
                    'videoWrap':{[BILI_2_X]:'.bilibili-player-video-wrap', [BILI_3_X]:'.bpx-player-video-area'}, //播放wrap
                    'videoContextMenu':{[BILI_2_X]:'.bilibili-player-video-wrap', [BILI_3_X]:'.bpx-player-video-perch'}, //播放contextmenu
                    'video':{[BILI_2_X]:'.bilibili-player-video', [BILI_3_X]:'.bpx-player-video-wrap'}, //播放
                    'videoTopMask':{[BILI_2_X]:'.bilibili-player-video-top-mask', [BILI_3_X]:'.bpx-player-top-mask'}, //全屏时鼠标悬停时产生的顶端mask

                    //系统设置等
                    'playArea':{[ALL]:'.bilibili-player-area'}, //哔哩哔哩播放器
                    'playVideo':{[BILI_2_X]:'.bilibili-player-video-btn'}, //系统设置
                    'playSetting':{[BILI_2_X]:'.bilibili-player-video-btn-setting'}, //系统播放设置
                    'playSettingWrap':{[BILI_2_X]:'.bilibili-player-video-btn-setting-wrap'}, //系统播放设置wrap
                    'playSettingAutoplay':{[BILI_2_X]:'.bilibili-player-video-btn-setting-left-autoplay input', [BILI_3_X]: '.squirtle-setting-autoplay'}, //自动播放
                    'playSettingRepeatInput':{[BILI_2_X]:'.bilibili-player-video-btn-setting-left-repeat input', [BILI_3_X]:'.squirtle-setting-loop'}, //洗脑循环按钮
                    'playSettingLightoff':{[BILI_2_X]:'.bilibili-player-video-btn-setting-right-others-content-lightoff input', [BILI_3_X]:'.squirtle-single-setting-other-choice.squirtle-lightoff'}, //关灯按钮
                    'bpxStateLightOff':{[BILI_3_X]:'.bpx-state-light-off'}, //关灯bpx

                    //右键菜单
                    'playerContextMenu':{[BILI_2_X]:'.bilibili-player-context-menu-container.black.bilibili-player-context-menu-origin', [BILI_3_X]:'.bpx-player-contextmenu.bpx-player-black'}, //右键菜单
                    'hotkeyPanel':{[BILI_2_X]:'.bilibili-player-hotkey-panel', [BILI_3_X]:'.bpx-player-hotkey-area'}, //快捷键说明面板
                    'videoInfo':{[BILI_2_X]:'.bilibili-player-video-info', [BILI_3_X]:'.bpx-player-info'}, //视频统计信息
                    'videoInfoClose':{[BILI_2_X]:'.bilibili-player-video-info-close', [BILI_3_X]:'.bpx-player-info-close'}, //视频统计信息关闭按钮
                    'videoInfoContainer':{[BILI_2_X]:'.bilibili-player-video-info-container', [BILI_3_X]:'.bpx-player-info-container'}, //视频统计信息
                    'videoInfoShow':{[BILI_2_X]:'.bilibili-player-video-info-container active', [BILI_3_X]:'.bpx-player-info-container'}, //视频统计信息面板显示
                    'DOMNodeInsertedVideoInfoShow':{[BILI_2_X]:'.bilibili-player-video-info-container active', [BILI_3_X]:'.info-line'}, //
                },
                set_bb(_bb_type) {
                    bb_type = _bb_type;
                    for(var k in this.bb_class_data){
                        var class_str = this.bb_class_data[k][bb_type] || this.bb_class_data[k][[ALL]];
                        bb[k] = class_str;
                    }
                }
           };

        const [ON, OFF] = [true, false];
        var //config
            keycode = {
                'left': 37,
                'right': 39,
                'up': 38,
                'down': 40,
                'space': 32,
                'enter': 13,
            },
            config = {
                //一些主要开关设置
                sets: {},
                getCheckboxSetting(key) {
                    return this.sets[key]['status'];
                },
                saveCheckboxSetting() {
                    for(var o in this){
                        if(o.indexOf('b_') === 0){
                            var op = this[o]['options'];
                            for(var k in op){
                                this.sets[k] = op[k];
                            }
                        }
                    }
                },
                b_playerCheckbox: {
                    options: {
                        lightOffWhenPlaying: { text: '播放时自动关灯', status: OFF },
                        lightOnWhenPause: { text: '暂停时自动开灯', status: OFF },
                        autoPlay: { text: '自动播放', status: OFF, fn: '', tips: '' },
                        lightOff: { text: '自动关灯', status: OFF, tips: '' },
                        volumeControlWhenNonFullScreen: { text: '非全屏滚轮音量调节', status: ON, tips: '' },
                        volumeControlWhenPause: { text: '非全屏暂停时滚轮音量调节', status: ON, tips: '' },
                        danmuOpacityControl: { text: '滚轮弹幕透明度控制', status: ON, tips: '' }, //ctrl+滚轮
                        removeVideoTopMask: { text: '去掉顶部mask', status: ON, tips: '' },
                        //不显示有明显变化的提示,关灯、关弹幕等,因为对有些人来说这些操作变化明显可见,提示反而多余且遮挡屏幕
                        hotKeyHint: { text: '快捷键屏幕提示', status: OFF, tips: '' },

                        dblclickFullScreen: { text: '双击或中键全屏', status: ON, tips: '' },
                        videoRepeat: { text: '洗脑循环', status: OFF, tips: '' },
                        rememberVideoRepeat: { text: '记忆洗脑循环', status: ON, tips: '' }, //优先级低于videoRepeat
                        keyVideoSpeed: { text: '键盘调节视频速度', status: ON, tips: '' },
                    },
                    btn: '设置'
                },
                //快捷键
                QDs: {}, //未使用
                getQD(key) {
                    return this.QDs[key];
                }, //未使用
                saveQD() {
                    for (let [key, { value, text }] of Object.entries(this.hotKeyMenu)) {
                        this.QDs[key] = {value: value, keyCode: value.charCodeAt(), text: text};
                    }
                }, //未使用
                hotKeyMenu: {  //只是右键菜单的数据,如需改动快捷键改run函数
                    'lightOff': { value: 'A', text: '关灯/开灯', },
                    'webFullscreen': { value: 'W', text: '网页全屏', },
                    'widescreen': { value: 'Q', text: '宽屏模式', },
                    'danmu': { value: 'D', text: '弹幕/关闭弹幕', },
                    'danmuTopBottom': { value: 'T/B', text: '顶部/底部弹幕', },
                    'videoRepeat': { value: 'R', text: '洗脑循环', },
                    'addsubDanmuOpacity': { value: 'Z/C', text: '减增弹幕透明度10%', },
                    'danmuArea': { value: '1、2、3、4、5', text: '弹幕显示区域 1/4屏~不限', },
                    // 'quarterArea': { value: '1', text: '1/4屏', },
                    // 'halfArea': { value: '2', text: '半屏', },
                    // 'threeQuarterArea': { value: '3', text: '3/4屏', },
                    // 'nonOverArea': { value: '4', text: '不重叠', },
                    // 'fullArea': { value: '5', text: '不限', },
                    'wheelDanmuOpacity': { value: 'Ctrl + 滚轮', text: '增减弹幕透明度5%', },
                    'fastForwardBackward30s': { value: 'Ctrl + ←/→', text: '快进/快退30s', },
                    '1/FPS': { value: 'Shift + ←/→', text: '逐帧操作', },
                    'keyVideoSpeed': { value: 'Ctrl + ↑/↓', text: '调节视频速度', },
                    'dblclickFullScreen': { value: '双击/中键', text: '双击或中键全屏', },
                },
            };

        function log(e) {console.log(e)}
        function dir(e) {console.dir(e)}
        function waitForNode(nodeSelector, callback, times) {
            if(times < 0) return;
            var node = nodeSelector();
            if (node) {
                callback(node);
            } else {
                times-=1;
                setTimeout(function() { waitForNode(nodeSelector, callback, times); }, 100);
            }
        }
        function waitForTrue(ifTrue, callback) {
            if (ifTrue()) {
                callback();
            } else {
                setTimeout(function() { waitForTrue(ifTrue, callback); }, 100);
            }
        }
        function is_fullscreen() {
            if(bb_type === BILI_2_X){ return player.isFullScreen() }
            else if(bb_type === BILI_3_X){ return $('.bpx-player-container').attr('data-screen') === 'web' || $('.bpx-player-container').attr('data-screen') === 'full' }  //normal wide web full
        }
        function fullscreen() { $(bb['fullScreen']).click() }
        function web_fullscreen() { $(bb['webFullScreen']).click() }
        function wide_screen() { $(bb['wideScreen']).click() }
        function is_lightoff() {
            if (bb_type === BILI_2_X) { return !player.getPlayerState().lightOn }
            else if(bb_type === BILI_3_X) { return $(bb['playSettingLightoff']).hasClass('active') }
        }
        function is_danmaku_show(){
            return $(bb['danmakuSwitch']+' '+bb['switchInput']+':last')[0].checked;
        }
        function lightoff() {
            $(bb['playSettingLightoff']).click()
        }
        //关灯按钮样式
        function lightoff_btn_css() {
            var body_brgb = 'rgb(160, 130, 110)';
            var dot_crgb = 'rgb(230, 200, 180)';
            var dot_brgb = 'rgb(50, 50, 50)';
            var dark_rgb = 'rgb(77, 77, 77)';
            if ($('#hhh_lightoff '+bb['switchInput'])[0].checked === false) {  //关灯
                $('#hhh_lightoff '+bb['switchBody']+':first').css('background-color', dark_rgb);
                $('#hhh_lightoff '+bb['switchBody']+':first>'+bb['switchDot']).css('color', dark_rgb);
            }
            else {
                $('#hhh_lightoff '+bb['switchBody']+':first').css('background-color', body_brgb);
                $('#hhh_lightoff '+bb['switchBody']+':first>'+bb['switchDot']).css({'color': dot_crgb, 'background-color': dot_brgb});
            }
        }
        //关灯按钮
        function lightoff_btn() {
            lightoff();
            if(is_lightoff() === $('#hhh_lightoff '+bb['switchInput'])[0].checked) {  //checked==true开灯 false关灯
                $('#hhh_lightoff '+bb['switchInput'])[0].checked = !$('#hhh_lightoff '+bb['switchInput'])[0].checked;
            }
            lightoff_btn_css();
        }

        //模拟B站音量调节
        //2.X版本可以直接调用系统函数window.player.volume(),但不能直接使用H5Player.volume
        //3.X版本去掉了window.player.volume(),但H5Player.volume功能发生变动,基本等价于window.player.volume()
        function volume(v, is_show_hint=true){
            function volume_bar(v){  //未使用
                if(v === undefined) return;
                v = v<0? 0: v>1? 1: v;
                $('.bilibili-player-video-volume-num').text(Math.round(v*100));
                $('.bilibili-player-video-volumebar-wrp .bui-bar.bui-bar-normal')[0].style.transform = `scaleY(${v})`;
                $('.bilibili-player-video-volumebar-wrp .bui-thumb')[0].style.transform = `translateY(${-48*v}px)`;
                v === 0? $('.bilibili-player-video-btn.bilibili-player-video-btn-volume').addClass('video-state-volume-min'): $('.bilibili-player-video-btn.bilibili-player-video-btn-volume').removeClass('video-state-volume-min')
            }
            function volume_hint_bar(v){
                if(v === undefined) return;
                v = v<0? 0: v>1? 1: v;
                var $volumeHintIcon = $(`#hhh_volumeHint ${bb['volumeHintIcon']}`);
                var volumeHintIconClassName = bb['volumeHintIcon'].substr(1);

                if(bb_type === BILI_2_X){
                    if(v <= 0) $volumeHintIcon.attr('class', `${volumeHintIconClassName} video-state-volume-min`);
                    else if(v >= 1) $volumeHintIcon.attr('class', `${volumeHintIconClassName} video-state-volume-max`);
                    else $volumeHintIcon.attr('class', volumeHintIconClassName);
                } else{
                    if(v <= 0){
                        $volumeHintIcon.find('.bpx-common-svg-icon:last').css('display','block');
                        $volumeHintIcon.find('.bpx-common-svg-icon:first').css('display','none');
                    } else{
                        $volumeHintIcon.find('.bpx-common-svg-icon:last').css('display','none');
                        $volumeHintIcon.find('.bpx-common-svg-icon:first').css('display','block');
                    }
                }

                if(v <= 0) showHint(this, '#hhh_volumeHint', '静音');
                else showHint(this, '#hhh_volumeHint', Math.round(v*100)+'%');
            }
            if(v === undefined) return h5Player.volume;
            v = v<0? 0: v>1? 1: v;
            bb_type === BILI_2_X? player.volume(v): h5Player.volume = v;
            if(is_show_hint === true) volume_hint_bar(h5Player.volume);
            return h5Player.volume;
        }

        //显示提示
        function showHint(parent, selector_str, text){
            $(bb['volumeHint']).css({"visibility":"visible"})
            $(bb['volumeHint']).css('display', 'none');  //隐藏所有提示,避免提示重叠
            $(`${selector_str}>${bb['volumeHintText']}`).text(text);  //百分比显示
            var Hint = $(selector_str);  //显示及渐隐效果(抄bilibili^^)
            clearTimeout(parent.showHintTimer),
                Hint.stop().css("opacity", 1).show(),
                parent.showHintTimer = window.setTimeout((function() {
                Hint.animate({
                    opacity: 0
                }, 300, (function() {
                    $(this).hide()
                }))
            }
            ), 1e3)
        }

        //非全屏滚轮音量调节 0~1 (b站默认滚轮操作某些情况会失效,一并处理全屏情况)
        //两个参数指定屏幕范围(按百分比),第三个参数表示滚动一下增加的音量百分比,参数四表示暂停时是否调解
        function wheel_volumeHint(screenLeft=0.3, screenRight=0.7, delta=3, isPauseVolume){
            $(bb['videoWrap']).off('mousewheel.hhh_volumeHint');
            $(bb['videoWrap']).on('mousewheel.hhh_volumeHint', function(e){
                if(e.ctrlKey || e.altKey || e.shiftKey) return;
                //缺省屏幕百分比参数,默认0.3~0.7
                screenLeft = (screenLeft<0 || screenLeft>1)? 0.3: screenLeft;
                screenRight = (screenRight<0 || screenRight>1)? 0.7: screenRight;
                //缺省音量百分比,默认3
                delta = (delta<1 || delta>100)? 3: delta;

                //非暂停(可选) && 鼠标在屏幕指定位置时处理
                var pauseState = isPauseVolume ||  h5Player.paused === true;
                var Rect = $(bb['videoWrap'])[0].getBoundingClientRect();
                var offsetX = e.originalEvent.x - Rect.x;
                var inLimit = offsetX > Rect.width*screenLeft && offsetX < Rect.width*screenRight;

                if(is_fullscreen() || (pauseState && inLimit)) {
                    //阻止页面滚动 && 阻止冒泡
                    e.preventDefault();
                    e.stopPropagation();
                    var wheelDelta = e.originalEvent.wheelDelta;
                    var v = volume();
                    if(wheelDelta >= 120) {  //向上滚动,减少音量
                        volume((v+(delta/100)).toFixed(3));
                    } else if(wheelDelta <= -120) {  //向下滚动,增大音量
                        volume((v-(delta/100)).toFixed(3));
                    }
                }
            });
        }

        /*
         * 控制进度条
         * .bilibili-player-setting-opacity 透明度
         * .bilibili-player-setting-area 显示区域
         * .bilibili-player-setting-speedplus 弹幕速度 等
         * 利用系统mousedown事件
         * 0 ~ 100
         */
        function set_progress(selector_str, percent){
            var selector = document.querySelector(selector_str);
            var e1 = new MouseEvent('mousedown'); var e2 = new MouseEvent('mouseup');

            function calc_bar_len(percent, bar_width){
                var p = percent - 10;
                p = p<0? 0: p>90? 90: p;
                return p*bar_width/90;  //进度条对应百分比的系统算法
            }

            if(bb_type === BILI_3_X) $('.squirtle-controller-wrap').css({"display":"flex"});
            $(bb['danmakuSettingWrap']).css({"display":"block"});

            var selector_rect = selector.getClientRects();
            var clientX = selector_rect[0].left + calc_bar_len(percent, $(`${selector_str} ${bb['progressWrap']}`).innerWidth());
            e1.initMouseEvent('mousedown',1,1,window,1,0,0,clientX,0,0,0,0,0,0,null);
            e2.initMouseEvent('mouseup'  ,1,1,window,1,0,0,clientX,0,0,0,0,0,0,null);
            selector.dispatchEvent(e1); selector.dispatchEvent(e2);

            $(bb['danmakuSettingWrap']).css({"display":"none"});
            if(bb_type === BILI_3_X) $('.squirtle-controller-wrap').css({"display":"none"});

            $(bb['danmakuSetting']).mouseleave();  //激活设置,记忆进度条位置
            return $(`${selector_str} ${bb['progressVal']}`).text();
        }

        /*
         * 调节透明度
         * 利用系统mousedown事件
         * '正数': right,  '负数': left,  -100 ~ +100
         */
        function adjust_progress(selector_str, inc_percent){
            var curr_percent = Number($(`${selector_str} ${bb['progressVal']}`).text().slice(0,-1));
            return set_progress(selector_str, curr_percent + inc_percent);
        }

        //滚轮调节弹幕透明度(ctrl),参数表示滚动一下增加的透明度百分比
        function wheel_opacity(delta=5){
            $(bb['videoWrap']).off('mousewheel.hhh_opacity');
            $(bb['videoWrap']).on('mousewheel.hhh_opacity', function(e){
                if(e.ctrlKey === true) {
                    //阻止页面滚动 && 阻止冒泡
                    e.preventDefault();
                    e.stopPropagation();
                    //缺省透明度百分比,默认5
                    delta = (delta<1 || delta>100)? 5: delta;
                    var wheelDelta = e.originalEvent.wheelDelta;
                    var opacity;
                    if(wheelDelta >= 120) {  //向上滚动,增大透明度
                        opacity = adjust_progress(bb['settingOpacity'], delta);
                    } else if(wheelDelta <= -120) {  //向下滚动,减少透明度
                        opacity = adjust_progress(bb['settingOpacity'], -delta);
                    }
                    if(opacity !== undefined) showHint(document, '#hhh_opacityHint', '透 '+opacity);
                }
            });
        }

        //添加右键菜单自定义快捷键说明2.X
        function add_custom_hotkey_menu_2_X(custom_hotkey) {
            //主class名,去掉"."
            var hotkey_panel_class = 'bilibili-player-hotkey-panel';

            //生成自定义快捷键说明页面
            (function add_custom_hotkey(){
                $(bb['videoWrap'])[0].addEventListener('DOMNodeInserted', function(e) {
                    let $target = $(e.target);
                    if($target.hasClass(`${hotkey_panel_class}-container active`)) {
                        this.removeEventListener('DOMNodeInserted', arguments.callee);
                        var $hotkey = $target.attr('class', `${hotkey_panel_class}-container`);  //去掉 active 隐藏
                        $hotkey.clone(true,true).insertBefore($hotkey).attr({'class': '','id': 'sys_hotkey_panel'}).css('display', 'none');
                        $hotkey.clone(true,true).insertBefore($hotkey).attr({'class': '','id': 'hhh_hotkey_panel'}).css('display', 'none');

                        (function set_custom_hotkey($hotkey, hotkey) {
                            var $hotkey_panel = $hotkey.find(`.${hotkey_panel_class}:first`);
                            var $hotkey_item  = $hotkey.find(`.${hotkey_panel_class}-item:first`);
                            $hotkey_panel.empty();
                            for (let [key, { value, text }] of Object.entries(hotkey)) {
                                $hotkey_item.clone().appendTo($hotkey_panel);
                                var $hotkey_key = $hotkey_panel.find(`.${hotkey_panel_class}-key:last`);
                                $hotkey_key.text(value);
                                $hotkey_key.next().text(text);
                            }
                        })($('#hhh_hotkey_panel'), custom_hotkey);
                    }
                });
            })();
            //右键菜单弹出时添加项
            (function add_menu(){
                $('#bilibiliPlayer')[0].addEventListener('DOMSubtreeModified', function(e) {
                    let $target = $(e.target);
                    if($target.hasClass('bilibili-player-context-menu-container black bilibili-player-context-menu-origin') &&  $target[0].id === '') {  //还有一个id = __sizzle__
                        this.removeEventListener('DOMSubtreeModified', arguments.callee);

                        let $li_sys_hotkey = $target.find('a:contains("快捷键说明"):first').parent();  //返回li,XXX: 此时contains("快捷键说明")多于一个
                        let $a_hhh_hotkey = $target.find('a:contains("快捷键说明(bilibili关灯)")');
                        var $li_hhh_hotkey = ($a_hhh_hotkey.length && $a_hhh_hotkey.parent()) || $li_sys_hotkey.clone(false, false).insertAfter($li_sys_hotkey).css('display', '').find('a').text('快捷键说明(bilibili关灯)');  //插入自定义快捷键

                        $li_sys_hotkey.find('a').one('click', function(){
                            $('#sys_hotkey_panel').clone(true,true).replaceAll($(`.${hotkey_panel_class}-container:last`)).attr({'id': '', 'class': `${hotkey_panel_class}-container`, 'style': ''});
                        });
                        $li_hhh_hotkey.one('click', function(){
                            $('#hhh_hotkey_panel').clone(true,true).replaceAll($(`.${hotkey_panel_class}-container:last`)).attr({'id': '', 'class': `${hotkey_panel_class}-container`, 'style': ''});
                        });

                        add_menu();
                    }
                });
            })();

            //模拟右键菜单消息,激活菜单DOM
            let evt = new MouseEvent('contextmenu', { clientX:-9999, clientY:-9999 });
            $(bb['videoWrap'])[0].dispatchEvent(evt);

            //模拟点击菜单,激活热键菜单DOM
            evt = new MouseEvent('click',{ bubbles:true });
            $('.bilibili-player-context-menu-container.black.bilibili-player-context-menu-origin a:contains("快捷键说明")')[0].dispatchEvent(evt);
        }

        //添加右键菜单自定义快捷键说明3.X
        function add_custom_hotkey_menu_3_X(custom_hotkey) {
            //主class名,去掉"."
            var player_hotkey_class = 'bpx-player-hotkey';

            //生成自定义快捷键说明页面
            (function add_custom_hotkey(){
                $(bb['videoWrap'])[0].addEventListener('DOMNodeInserted', function(e) {
                    let $target = $(e.target);
                    if($target.hasClass(`${player_hotkey_class}-area`)) {
                        this.removeEventListener('DOMNodeInserted', arguments.callee);

                        var $hotkey = $target.css('display', 'none');
                        $hotkey.clone(true,true).insertBefore($hotkey).attr({'class': '','id': 'sys_hotkey_panel'}).css('display', 'none');
                        $hotkey.clone(true,true).insertBefore($hotkey).attr({'class': '','id': 'hhh_hotkey_panel'}).css('display', 'none');
                        $hotkey.css('visibility', 'hidden');

                        $('#sys_hotkey_panel .bpx-player-hotkey-close').click(function(){ $(this).parent().css('display', 'none') });  //jquery问题,clone失败,自定义关闭按钮事件
                        $('#hhh_hotkey_panel .bpx-player-hotkey-close').click(function(){ $(this).parent().css('display', 'none') });  //jquery问题,clone失败,自定义关闭按钮事件

                        (function set_custom_hotkey($hotkey, hotkey) {
                            var $hotkey_panel = $hotkey.find(`.${player_hotkey_class}-list:first`);
                            var $hotkey_item  = $hotkey.find(`.${player_hotkey_class}-item:first`);
                            $hotkey_panel.empty();
                            for (let [key, { value, text }] of Object.entries(hotkey)) {
                                $hotkey_item.clone().appendTo($hotkey_panel);
                                var $hotkey_key = $hotkey_panel.find(`.${player_hotkey_class}-key:last`);
                                $hotkey_key.text(value);
                                $hotkey_key.next().text(text);
                            }
                        })($('#hhh_hotkey_panel'), custom_hotkey);
                    }
                });
            })();
            //右键菜单弹出时添加项
            (function add_menu(){
                $('#bilibili-player')[0].addEventListener('DOMSubtreeModified', function(e) {
                    let $target = $(e.target);
                    if($target.hasClass('bpx-player-contextmenu bpx-player-black') &&  $target[0].id === '') {  //还有一个id = __sizzle__
                        this.removeEventListener('DOMSubtreeModified', arguments.callee);

                        if($target.find('li:contains("快捷键说明"):first').length === 1) {
                            var $li_sys_hotkey = $target.find('li:contains("快捷键说明"):first');  //XXX: 此时contains("快捷键说明")多于一个
                            var $li_hhh_hotkey = $li_sys_hotkey.clone(false, false).insertAfter($li_sys_hotkey).css('display', '').text('快捷键说明(bilibili关灯)');

                            $li_sys_hotkey.mousedown(function(){
                                $('#sys_hotkey_panel').clone(true,true).replaceAll($(`.${player_hotkey_class}-area:last`)).attr({'id': '', 'class': `${player_hotkey_class}-area`, 'style': ''});
                            });
                            $li_hhh_hotkey.mousedown(function(){
                                $('#hhh_hotkey_panel').clone(true,true).replaceAll($(`.${player_hotkey_class}-area:last`)).attr({'id': '', 'class': `${player_hotkey_class}-area`, 'style': ''});
                            });
                        }

                        add_menu();
                    }
                });
            })();

            //模拟右键菜单消息,激活菜单DOM
            let evt = new MouseEvent('contextmenu', { clientX:-9999, clientY:-9999 });
            $(bb['videoWrap'])[0].dispatchEvent(evt);

            //模拟点击菜单,激活热键菜单DOM
            evt = new MouseEvent('mousedown',{ bubbles:true });
            $(`.bpx-player-contextmenu.bpx-player-black li:contains("快捷键说明")`)[0].dispatchEvent(evt);
        }

        //添加右键菜单自定义快捷键说明
        function add_custom_hotkey_menu(hotKeyMenu) {
            if(bb_type === BILI_2_X) add_custom_hotkey_menu_2_X(hotKeyMenu);
            else add_custom_hotkey_menu_3_X(hotKeyMenu);
        }

        //取得版本号
        function get_ver() {
            if(bb_type === BILI_2_X) ver = player.getVersion().version;
            else ver = $('.bpx-common-opacity-60').text().split('-')[0];
        }

        //取得视频FPS(Frames Per Second)
        function get_video_fps() {
            $(bb['videoWrap'])[0].addEventListener('DOMNodeInserted', function(e) {
                //插入info面板时截取fps值
                if($(e.target).hasClass(bb['DOMNodeInsertedVideoInfoShow'].substr(1))) {
                    this.removeEventListener('DOMNodeInserted', arguments.callee);

                    let $video_info_close = $(bb['videoInfoClose']);
                    $video_info_close.click();  //模拟关闭统计信息面板,2.X版本一次即可关掉
                    $video_info_close.click();  //3.X版本执行两次才能关掉面板,保险起见3次
                    $video_info_close.click();  //估计是点击事件开始太快,系统未能处理,也可能3.X测试版自己的问题

                    //text中取得fps值
                    var get_title_text = function(title) { return $(bb['videoInfoContainer']).find(`.info-title:contains("${title}")`).next().text(); }
                    fps = Number(get_title_text('Resolution').match(/\d+\.\d+/)) || Number(get_title_text('FPS')) || 30;
                }
            })

            //模拟右键菜单消息,激活菜单DOM
            let evt = new MouseEvent('contextmenu', { clientX:-9999, clientY:-9999 });
            $(bb['videoContextMenu'])[0].dispatchEvent(evt);

            //模拟点击菜单,激活热键菜单DOM
            if(bb_type === BILI_2_X){
                let evt = new MouseEvent('click',{ bubbles:true });
                $(`${bb['playerContextMenu']} a:contains("视频统计信息")`)[0].dispatchEvent(evt);
            }
            else if(bb_type === BILI_3_X) {
                let evt = new MouseEvent('mousedown',{ bubbles:true });
                $(`${bb['playerContextMenu']} li:contains("视频统计信息")`)[0].dispatchEvent(evt);
            }
        }

        //笨办法,激活系统音量设置,复制volumeHint DOM
        function pick_volume_hint(){
            var original_volume = h5Player.volume;
            //监视提取提示DOM
            $(bb['videoWrap'])[0].addEventListener('DOMNodeInserted', function(e) {
                if($(e.target).hasClass(bb['volumeHint'].substr(1))) {
                    this.removeEventListener('DOMNodeInserted', arguments.callee);

                    volume(original_volume);  //模拟鼠标拖动无法按1%精确控制音量,系统自身限制或者说bug

                    //添加 volumeHint wordsHint opacityHint DOM
                    $(bb['volumeHint']).clone().appendTo(bb['videoWrap']).attr('id','hhh_volumeHint');

                    $('#hhh_volumeHint').clone().appendTo(bb['videoWrap']).attr('id','hhh_wordsHint').css({'opacity': 0, 'display': 'none'}).find(bb['volumeHintIcon']).remove();
                    $('#hhh_wordsHint').clone().appendTo(bb['videoWrap']).attr('id','hhh_opacityHint');

                    if(bb_type === BILI_2_X){
                        $('#hhh_wordsHint').css({'width':'auto','margin-left':'0px','padding-left':'8px','padding-right':'15px','transform':'translate(-50%)'})
                                           .find(bb['volumeHintText']).css({'width': 'auto', 'padding-left': '10px'});
                        $('#hhh_opacityHint').find(bb['volumeHintText']).css({'padding-right': '6px'});
                    }
                    else{
                        $('#hhh_wordsHint, #hhh_opacityHint').find(bb['volumeHintText']).css({'padding': '0 10px'});
                    }

                    //隐藏提示
                    $(bb['volumeHint']).css({"visibility":"hidden"});
                }
            });
            //激活系统音量设置,以复制volumeHint DOM
            let evt = new KeyboardEvent('keydown', { keyCode:keycode['up'] });
            window.dispatchEvent(evt);
        }

        //快进时显示醒目进度条
        function dynamicProgress(dynamicHeight, staticHeight){
            if(bb_type === BILI_2_X) {
                if ($('.bilibili-player-area').hasClass('progress-shadow-show') === true) {
                    $('.bilibili-player-video-progress-shadow .bui-track-video-progress').css('cssText', `height:${dynamicHeight}px !important`);
                    clearTimeout(document.showVideoProgress);
                    document.showVideoProgress = window.setTimeout((function() { $('.bilibili-player-video-progress-shadow .bui-track-video-progress').css('cssText', `height:${staticHeight}px !important`); }), 2000);
                }
            } else {
                if($('.bpx-player-container').hasClass('bpx-state-no-cursor') === true) {
                    $('.squirtle-progress-buffer').css({'height': `${dynamicHeight/2}px`});
                    $('.squirtle-progress-timeline').css({'height': `${dynamicHeight/2}px`});
                    $('.squirtle-progress-totalline').css({'height': `${dynamicHeight/2}px`});
                    clearTimeout(document.showVideoProgress);
                    document.showVideoProgress = window.setTimeout((function() {
                        $('.squirtle-progress-buffer').css({'height': `${staticHeight}px`});
                        $('.squirtle-progress-timeline').css({'height': `${staticHeight}px`});
                        $('.squirtle-progress-totalline').css({'height': `${staticHeight}px`});
                    }), 2000);
                }
            }
        }

        //视频速度
        function video_select_speed(level) {
            let data_x = ['0.5x', '0.75x', '1.0x', '1.25x', '1.5x', '2.0x'];
            let curr_x = $(bb['videoSpeedActive']).text();
            let x = data_x[data_x.indexOf(curr_x) + level];
            if(x !== undefined) $(`${bb["videoSpeed"]}:contains("${x}")`).click();
            showHint(parent, '#hhh_wordsHint', $(bb['videoSpeedName']).text());
        }

        //主程序
        function run(){

            //防止重复加载
            if ($('#hhh_lightoff').length === 1) return;

            //bpx test
            function bpx_test(){
                log('-------------------');
                log('ver: '+ver);
                log('fps: '+fps);
                log('------h5Player-----');
                dir(h5Player);
                log('currentTime  : '+h5Player.currentTime);
                log('duration     : '+h5Player.duration);
                log('playbackRate : '+h5Player.playbackRate);
                log('volume       : '+h5Player.volume);
                log('paused       : '+h5Player.paused);
                log('pause()      : '+'h5Player.pause()');
                log('videoHeight  : '+h5Player.videoHeight);
                log('videoWidth   : '+h5Player.videoWidth);
                log('-------------------');
            }

            /*-----------------------------------
             *初始化等
             *----------------------------------*/
            //保存设置信息 && 快捷键信息
            config.saveCheckboxSetting();

            //取得h5 video
            h5Player = bb_type === BILI_2_X ? ($(`${bb['video']} video`)[0] || $(`${bb['video']} bwp-video`)[0]) : $(`${bb['video']} video`)[0];

            //插入关灯按钮
            $(`${bb['danmakuSwitch']}:first`).clone().prependTo(`${bb['danmakuRoot']}:first`)[0].id = 'hhh_lightoff';
            $(`#hhh_lightoff ${bb['switchDot']}`)[0].innerHTML = '灯';

            //初始化关灯按钮
            lightoff_btn_css();

            //激活系统弹幕设置,以此调用系统网页全屏等
            $(bb['danmakuSetting']).mouseenter().mouseleave();

            //激活系统播放设置,以此调用系统关灯等
            //去掉mouseleave(),否则如果太快执行mouseleave()无法激活关灯class,应该是mouseenter()未执行完就被mouseleave打断了
            $(`${bb['playVideo']}${bb['playSetting']}`).mouseenter();

            //避免显示设置页面
            waitForNode(() => document.querySelector(bb['playSettingWrap']), (node) => {
                $(node).css({"visibility":"hidden"});  //visible
            })

            //解决因为激活关灯class,导致全屏时滚轮操作(系统自带)无法调节音量的问题
            waitForTrue(()=> $(bb['playSettingWrap']).css('display') === 'block', () => {
                $(bb['playSettingWrap']).css('display', 'none').css('visibility', 'visible');
            });

            //取得视频fps
            get_video_fps();

            //取得版本号
            get_ver();

            //激活系统提示添加音量等自定义提示DOM
            pick_volume_hint();

            //添加自定义快捷键说明到右键菜单
            add_custom_hotkey_menu(config.hotKeyMenu);

            /*-----------------------------------
             *事件等
             *----------------------------------*/
            //点击关灯
            $(`#hhh_lightoff ${bb['switchInput']}:first`).click(function(){ lightoff_btn() });

            //双击或中键全屏
            if(config.getCheckboxSetting('dblclickFullScreen') === ON) {
                $(bb['playTipWrap']).dblclick(function(){ web_fullscreen() });
                $(bb['playTipWrap']).mousedown(function(e){
                    if(e.button === 1 || e.button === 4 || e.button === 3) {
                        e.preventDefault(); e.stopPropagation();
                        web_fullscreen();
                    }
                });
            }

            //判断当前鼠标点击焦点
            $('#app').click(function(e){
                if(e.originalEvent === undefined) return;
                let path = e.originalEvent.path;
                is_in_biliplayer = false;
                $(path).each(function(){
                    if(this.id === 'bilibiliPlayer') { is_in_biliplayer = true; return; }
                })
            })

            //非全屏滚轮音量调节
            //两个参数指定屏幕范围(按百分比),第三个参数表示滚动一下增加的音量百分比,参数四表示暂停时是否调节
            if(config.getCheckboxSetting('volumeControlWhenNonFullScreen') === ON) wheel_volumeHint(0.30, 0.70, 3, config.getCheckboxSetting('volumeControlWhenPause'));

            //因为遮挡弹幕,去掉全屏时鼠标悬停时产生的顶端mask
            if(config.getCheckboxSetting('removeVideoTopMask') === ON) $(bb['videoTopMask']).removeClass();

            //播放关灯,暂停开灯
            h5Player.addEventListener('play', () => config.getCheckboxSetting('lightOffWhenPlaying') === ON && !is_lightoff() && lightoff_btn());
            h5Player.addEventListener('pause', () => config.getCheckboxSetting('lightOnWhenPause') === ON && is_lightoff() && lightoff_btn());

            function set_value(key, value){ localStorage.setItem(key, value) }
            function get_value(key, default_value){ return localStorage.getItem(key) || default_value }

            //记忆洗脑循环
            if(config.getCheckboxSetting('rememberVideoRepeat') === ON && config.getCheckboxSetting('videoRepeat') !== ON) {
                $(bb['playSettingRepeatInput'])[0].checked = JSON.parse(get_value('hhh-rememberVideoRepeat', $(bb['playSettingRepeatInput'])[0].checked));  //localStorage只能保存字符串
                $(bb['playSettingRepeatInput']).click(function() {
                    set_value('hhh-rememberVideoRepeat', $(bb['playSettingRepeatInput'])[0].checked);
                });
            };

            //自动运行
            if(config.getCheckboxSetting('autoPlay') === ON && $(bb['playSettingAutoplay'])[0].checked === false) $(bb['playSettingAutoplay']).click();//开启自动播放
            if(config.getCheckboxSetting('videoRepeat') === ON) $(bb['playSettingRepeatInput']).click();  //开启洗脑循环
            if(config.getCheckboxSetting('lightOff') === ON) lightoff_btn();  //自动关灯

            //滚轮调节弹幕透明度(ctrl),参数表示滚动一下增加的透明度百分比,默认5
            if(config.getCheckboxSetting('danmuOpacityControl') === ON) wheel_opacity(5);

            //键盘关灯等
            var parent = document;
            var is_show_hint = config.getCheckboxSetting('hotKeyHint');
            $(document).off('keydown.hhh_lightoff');
            $(document).on('keydown.hhh_lightoff',function(e){
                if(e.shiftKey && (e.keyCode === keycode['left'] || e.keyCode === keycode['right'])) {  //逐帧 shift+ left/right
                    h5Player.pause();
                    h5Player.currentTime = e.keyCode === keycode['left']? h5Player.currentTime - 1/fps: h5Player.currentTime + 1/fps;
                } else if(e.ctrlKey && (e.keyCode === keycode['left'] || e.keyCode === keycode['right'])) {  //+ -30s ctrl+ left/right
                    h5Player.currentTime = e.keyCode === keycode['left']? h5Player.currentTime - 30: h5Player.currentTime + 30;
                    dynamicProgress(16, 2);
                } else if(e.ctrlKey && (e.keyCode === keycode['up'] || e.keyCode === keycode['down'])) {  //+ -播放速度
                    if(config.getCheckboxSetting('keyVideoSpeed') === OFF) return;
                    window.setTimeout((function() {  //长按时保持DOM更新
                        e.keyCode === keycode['up']? video_select_speed(1): video_select_speed(-1);
                    }),10);
                } else if(e.ctrlKey && e.keyCode === keycode['enter']) {  //全屏
                    fullscreen();
                }

                //以下不使用功能键
                if(e.ctrlKey || e.altKey || e.shiftKey) return;

                if(e.keyCode === 'A'.charCodeAt()){  //开关灯
                    is_show_hint && (is_lightoff() ? showHint(parent, '#hhh_wordsHint', '开灯') : showHint(parent, '#hhh_wordsHint', '关灯'));
                    lightoff_btn();
                } else if(e.keyCode === 'W'.charCodeAt()) {  //网页全屏
                    web_fullscreen();
                } else if(e.keyCode === 'Q'.charCodeAt()) {  //宽屏模式
                    is_fullscreen() ? web_fullscreen() : wide_screen();
                } else if(e.keyCode === 'D'.charCodeAt()) {  //开关弹幕
                    $(bb['danmakuSwitch']+' '+bb['switchInput']+':last').click();
                    is_show_hint && (is_danmaku_show() === true ? showHint(parent, '#hhh_wordsHint', '开弹幕') : showHint(parent, '#hhh_wordsHint', '关弹幕'));
                } else if(e.keyCode === 'T'.charCodeAt()) {  //开关顶部弹幕
                    $(bb['danmukuTopClose']).length === 0 ? showHint(parent, '#hhh_wordsHint', '关闭顶部弹幕') : showHint(parent, '#hhh_wordsHint', '打开顶部弹幕');
                    $(bb['danmukuTop']).click();
                } else if(e.keyCode === 'B'.charCodeAt()) {  //开关底部弹幕
                    $(bb['danmukuBottomClose']).length === 0 ? showHint(parent, '#hhh_wordsHint', '关闭底部弹幕') : showHint(parent, '#hhh_wordsHint', '打开底部弹幕');
                    $(bb['danmukuBottom']).click();
                } else if(e.keyCode === 'S'.charCodeAt()) {  //弹幕随屏幕缩放
                    $(bb['settingFs'])[0].checked === false ? showHint(parent, '#hhh_wordsHint', '弹幕随屏幕缩放') : showHint(parent, '#hhh_wordsHint', '弹幕不随屏幕缩放');
                    $(bb['settingFs']).click();
                } else if(e.keyCode === 'R'.charCodeAt()) {  //开关洗脑循环
                    $(bb['playSettingRepeatInput']).click();
                } else if(e.keyCode === 'Z'.charCodeAt() || e.keyCode === 'C'.charCodeAt()) {  //+ -弹幕透明度
                    let inc_percent = e.keyCode === 'Z'.charCodeAt()? -10: 10;
                    window.setTimeout((function() {  //长按时保持DOM更新
                        let opacity = adjust_progress(bb['settingOpacity'], inc_percent);
                        showHint(parent, '#hhh_opacityHint', '透 ' + opacity);
                    }),10);
                } else if(e.keyCode >= '1'.charCodeAt() && e.keyCode <= '5'.charCodeAt()) {  //弹幕显示区域
                    var area_text = {0:'1/4屏',25:'半屏',50:'3/4屏',75:'不重叠',100:'不限'};
                    var percent = (e.keyCode - '1'.charCodeAt()) * 25;  //((0~4)*25)%
                    set_progress(bb['settingArea'], percent);
                    showHint(parent, '#hhh_wordsHint', area_text[percent]);
                } else if(e.keyCode === keycode['left'] || e.keyCode === keycode['right']){  //快进时显示醒目进度条
                    dynamicProgress(16, 2);
                } else if(e.keyCode === keycode['up'] || e.keyCode === keycode['down']) { //隐藏所有提示,避免提示重叠
                    $(bb['volumeHint']).css({"visibility":"visible"})
                    $(bb['volumeHint']).css('display', 'none');
                } else if(e.keyCode === keycode['space']) {  //空格键2.X版本不合理,改成和3.X版本一样
                    if(bb_type===BILI_2_X){
                        if(is_in_biliplayer === false) e.stopPropagation();
                    }
                } else if(e.keyCode === 'X'.charCodeAt()) {  //TEST 显示、隐藏video-control
                    if($(bb['playArea']).hasClass('video-control-show') === true) $(bb['videoWrap']).mouseout();
                    else $(bb['videoWrap']).mousemove();
                } else if(e.keyCode === 'V'.charCodeAt()) {  //TEST
                    //if(bb_type===BILI_3_X) $('.bpx-player-dm-setting-wrap').css('display','block');
                    $('.bilibili-player-video-danmaku-setting-wrap').css('display','block');
                    //$('.bilibili-player-area.video-state-blackside').attr('class', 'bilibili-player-area video-state-blackside video-state-pause video-control-show');
                }else{
                    //console.dir(e);
                }
            });


            //TEST
            bpx_test();

        }

        //初始化
        function init() {
            console.clear();
            new MutationObserver((mutations, observer) => {
                mutations.forEach(mutation => {
                    const target = mutation.target;
                    const stage = mutation.previousSibling && target.getAttribute('stage');
                    if(stage === '1' && $('.bilibili-player-video-wrap').length === 1){  //2.X
                        log("2.X加载完毕");
                        bb_config.set_bb(BILI_2_X);
                        run();
                    } else if(typeof target.className === 'string' && target.className === 'squirtle-fullscreen-wrap squirtle-block-wrap' && $('.bpx-player-video-area').length === 1) {  //3.X  pbp-tip
                        log("3.X加载完毕");
                        bb_config.set_bb(BILI_3_X);
                        run();
                    }
                });
            }).observe(document.body, {
                childList: true,
                subtree: true,
            });
        }

        init();
    }
}

hhh_lightoff_main.init();