// ==UserScript==
// @name Bilibili Auto Turnoff Barrage
// @namespace https://greasyfork.org/zh-CN/users/6065-hatn
// @version 0.2.19
// @description B站视频自动关闭弹幕:双击【t】键开/关切换
// @icon http://www.gravatar.com/avatar/10670da5cbd7779dcb70c28594abbe56?r=PG&s=92&default=identicon
// @include *.bilibili.com/video/av*
// @include *.bilibili.com/anime/*
// @require http://cdn.staticfile.org/jquery/2.1.1-rc2/jquery.min.js
// @copyright 2016, hatn
// @author hatn
// @run-at document-end
// @grant0 GM_xmlhttpRequest
// @grant0 GM_getValue
// @grant0 GM_setValue
// @grant0 GM_deleteValue
// @grant0 unsafeWindow
// ==/UserScript==
/**
*
* 功能:用于哔哩哔哩站(B站) 视频自动关闭弹幕
*
* 使用说明:
* 1、双击【t】: 开/关弹幕
* 2、双击【f】: 全屏切换
* 3、双击【p】: 播放/暂停
* 4、单击【Esc】: 全屏&播放 // Firefox双击Esc退出全屏
* 5、双击【k/l】: 切换前/后一分P
*
*/
/* ######### 参数设置 S ######### */
var config = {
auto_danmuku: 1, // 自动关闭弹幕 [1]开启(默认) [0]关闭
auto_widescreen: 1, // 自动宽屏 [1]开启(默认) [0]关闭
auto_playvedio: 0, // 自动播放 [1]开启 [0]关闭(默认)
auto_preventshade: 1, // 防挡字幕 [1]开启(默认) [0]关闭
auto_position: 1, // 自动定位播放器位置 [1]开启(默认) [0]关闭
keyboard_flag: 1, // 监听单/双击键盘事件 [1]单双击(默认) [2]双击 [3]单击 [0]关闭
css_flag: 1, // 额外的css样式 [1]开启(默认) [0]关闭 全屏时半透明弹幕栏和控制条
control_view: { // 悬浮视图
status: 0, // 显示视图 [1]开启 [0]关闭(默认)
float: 2, // 停靠位置 [1]左 [2]右(默认)
auto_hide: 0, // 操作后自动隐藏 [1]开启 [0]关闭(默认)
}
};
/* ######### 参数设置 E ######### */
var danmukuObj = {
/* 参数 */
cfg: {}, // 参数集
defaultCfg: {
auto_danmuku: 1,
auto_widescreen: 1,
auto_playvedio: 0,
auto_preventshade: 1,
auto_position: 1,
keyboard_flag: 1,
css_flag: 1,
control_view: {
status: 0,
float: 2,
auto_hide: 0
}
},
/* 按键参数 */
keyData: {
timenow: 0, // 上一按键时间
preKey: '', // 记忆前一按键
keepTime: 400, // 双击间隔
keyBtn: { // 双/单击按键对应动作
'0': { // global
'currPage': '#plist span.curPage',
'currPageBgm': 'ul.slider-list>li.v1-bangumi-list-part-child.cur:eq(0)',
'currNotPageBgm': 'ul.slider-list>li.v1-bangumi-list-part-child:not(.cur)',
'dealPageFunc': function(s, _act) {
var act = _act == 'prev' ? 'prev' : 'next';
if (/bangumi\./.test(location.href)) { // 番剧模式
var $curr_li = $(s.keyData.keyBtn[0].currPageBgm)[act]('li') || false;
if ($curr_li == false) return false;
$curr_li.click();
/** onclick事件失效(已被取消)直接模拟点击 li
var onclick = $('a[onclick]:eq(0)', $curr_li).attr('onclick') || false;
if (onclick != false) eval('unsafeWindow.' + onclick);*/
// 重新插入css样式到iframe 通过band的点击事件($curr_li.click)实现即可
//s.band('bangumi');
s.keyData.keyBtn[0].addCssIframe(s);
return true;
}
var href = $(s.keyData.keyBtn[0].currPage)[act]('a[href]').attr('href') || false;
if (href != false) location.href = href;
},
'addCssIframe': function(s) {
var selector = s.keyData.keyBtn['84'].selector;
var ii = 0;
var new_iframe_dom = setInterval(function() {
if (ii > 15) {
clearInterval(new_iframe_dom);
console.log('log: new_iframe_dom not found !');
}
if (s.checkIframe(selector, s.iframe_arr)) {
clearInterval(new_iframe_dom);
s.addCss(true);
setTimeout(function() {
//debugger;
s.band('bangumi_keyup');
s.autoAction();
}, 1000);
console.log('log: new_iframe_dom found !');
}
++ii;
}, 1000);
}
},
// 双击操作
'70': {'type': 'fullscreen', 'selector': '.bilibili-player-iconfont-fullscreen.icon-24fullscreen:eq(0)'},
'75': {
'type': 'prepage',
'function': function(keyData, s) {
s.keyData.keyBtn[0].dealPageFunc(s, 'prev');
},
},
'76': {
'type': 'nextpage',
'function': function(keyData, s) {
s.keyData.keyBtn[0].dealPageFunc(s, 'next');
},
},
'80': {
'type': 'playvedio',
'selector': 'div.bilibili-player-video-btn-start:eq(0)',
'player_box': '.player-wrapper',
'pause_btn': 'div.bilibili-player-video-btn-start.video-state-pause',
'function': function(keyData, s) {
if ($(keyData.pause_btn, s.dom_type).length > 0) return true;
$('html, body').animate({scrollTop: $(keyData.player_box).offset().top + 22}, 600);
}
},
'84': {
'type': 'danmuku',
'selector': 'div.bilibili-player-video-control div.bilibili-player-video-btn.bilibili-player-video-btn-danmaku',
'hide_danmu_set': '.bilibili-player-danmaku-setting-lite-panel',
'flag_off': 'div.bilibili-player-video-control div.bilibili-player-video-btn.bilibili-player-video-btn-danmaku.video-state-danmaku-off',
'function': function(keyData, s) {
$(keyData.hide_danmu_set, s.dom_type).hide(); // 模拟点击 + 隐藏弹幕设置面板
},
},
// 单击操作
'_27': {
'type': 'fullandplay',
'full_status': '#bilibiliPlayer.mode-fullscreen',
'function': function(keyData, s) {
//setTimeout(function() {
if ($(keyData.full_status, s.dom_type).length > 0) return false;
s.keyAction(70);
if ($(s.keyData.keyBtn[80].pause_btn, s.dom_type).length > 0) setTimeout(function() {s.keyAction(80);}, 450);
//}, 250);
},
},
// 自动操作(无按键)
'preventshade': { // 防挡字幕
'type': 'preventshade',
'selector': '[for="checkbox20"]'
},
'widescreen': { // 自动宽屏
'type': 'widescreen',
'selector': '.bilibili-player-video-btn-widescreen'
},
'automatic_positioning': { // 自动定位播放器
'type': 'automatic positioning',
'function': function (keyData, s) {
$('html, body').animate({scrollTop: $(s.keyData.keyBtn[80].player_box).offset().top + 22}, 600);
}
}
}
},
hash: null, // location.hash
dom_type: document, // 使用 document/iframe
iframe_arr: { // body体集合
bangumi: "iframe.player.bilibiliHtml5Player",
},
/* 初始化 */
init: function() {
var s = this;
s.band();
s.addCss();
s.autoAction();
s.controlView('add');
console.log('log: Bilibili Auto Turnoff Barrage, Run...');
},
/* 启动器 */
launcher: function(config) {
var s = this;
s.setParam(config);
var times = 100;
var ii = 0;
var preTimer = setInterval(function () {
++ii;
var selector = s.keyData.keyBtn['84'].selector; //'div.bilibili-player-video-btn.bilibili-player-video-btn-danmaku';
if ($(selector).length > 0 || s.checkIframe(selector, s.iframe_arr)) {
window.clearInterval(preTimer);
console.log('log: Try ' + ii + ' times!');
setTimeout(function() {
s.init(); // 延迟3秒执行
}, 3000);
return true;
}
if (--times < 0) {
window.clearInterval(preTimer) + console.log('err: time out!');
}
}, 600);
},
/* 检查各项iframe */
checkIframe: function(selector, iframe_arr) {
var s = this;
var $type;
for (var i in iframe_arr) {
$type = $(iframe_arr[i]);
if ($type.length > 0 && $(selector, $type.contents()).length > 0) {
s.dom_type = $type.contents();
return true;
}
}
return false;
},
/* 参数读取 */
setParam: function(config) {
var s = this;
config = typeof config == 'object' ? config : {};
$.extend(s.cfg, s.defaultCfg, config);
//s.dataMgr('get');
//s.cfg = {};
//s.dataMgr('set');
},
/* 全局css */
addCss: function(_onlyIframe) {
var s = this;
if (s.cfg.css_flag != 1 && s.cfg.control_view.status != 1) return false;
var onlyIframe = _onlyIframe || false; // 只插入到iframe
var playerCss = controlViewCss = '';
if (s.cfg.css_flag == 1) {
var playerCss = '#bilibiliPlayer.mode-fullscreen .bilibili-player-video-sendbar[style^="opacity: 1;"]{ background: rgba(0,0,0,0.3); bottom: 60px !important;} #bilibiliPlayer.mode-fullscreen .bilibili-player-video-control[style^="opacity: 1;"]{ border-color: rgba(255,255,255,.3); text-shadow: #333 1px 1px 3px; background: rgba(0,0,0,0.3); -moz-transform:scale(1,2);-webkit-transform:scale(1,2);bottom: 16px !important;}.bilibili-player-video-btn.bilibili-player-video-btn-color.relative~.bilibili-player-video-inputbar.focus, .bilibili-player-video-control .bpui-slider-tracker[name="slider"], #bilibiliPlayer.mode-fullscreen ul.bpui-selectmenu-list.bpui-selectmenu-list-left { background: 0; border-color: rgba(255,255,255,.3) !important; } .bilibili-player-video-progress-buffer { background: rgba(255,255,255, 0.3) !important; } #bilibiliPlayer.mode-fullscreen #bilibiliPlayer.mode-fullscreen ul.bpui-selectmenu-list.bpui-selectmenu-list-left>li, #bilibiliPlayer.mode-fullscreen .bilibili-player-danmaku-setting-lite, #bilibiliPlayer.mode-fullscreen .bilibili-player-video-volumebar-wrp, .bpui-selectmenu-list-row[data-selected] { background: rgba(0,0,0,0.3) !important; } #bilibiliPlayer.mode-fullscreen ul.bpui-selectmenu-list.bpui-selectmenu-list-left>li:not([data-selected="selected"]), #bilibiliPlayer.mode-fullscreen .bilibili-player-video-danmaku-input, #bilibiliPlayer.mode-fullscreen .bilibili-player-video-volume-num, #bilibiliPlayer.mode-fullscreen [name="time_textarea"], #bilibiliPlayer.mode-fullscreen .bilibili-player-danmaku-setting-lite-title, #bilibiliPlayer.mode-fullscreen .bpui-checkbox-text, #bilibiliPlayer.mode-fullscreen .bilibili-player-block-filter-label, #bilibiliPlayer.mode-fullscreen .row-title, #bilibiliPlayer.mode-fullscreen .js-action:not(.active)>.fontsize_selector, #bilibiliPlayer.mode-fullscreen .js-action:not(.active) .selection-name { color: #ccc !important; text-shadow: #333 1px 1px 3px; } #bilibiliPlayer.mode-fullscreen .bilibili-player-video-btn-send.bpui-component.bpui-button.button, #bilibiliPlayer.mode-fullscreen .bpui-slider-progress { background: rgba(0,161,214,0.6); border: 0; } #bilibiliPlayer.mode-fullscreen .bilibili-player-video-progress-buffer-range { background: rgba(138,220,237,0.6); } #bilibiliPlayer.mode-fullscreen .bilibili-player-video-volumebar.bpui-component.bpui-slider.bpui-slider-vertical { opacity: 0.6; } #bilibiliPlayer.mode-fullscreen .bilibili-player-video-volumebar-wrp, #bilibiliPlayer.mode-fullscreen .bilibili-player-video-float-panel.show, #bilibiliPlayer.mode-fullscreen .bilibili-player-video-float-quality-lists, #bilibiliPlayer.mode-fullscreen .bilibili-player-video-float-split, #bilibiliPlayer.mode-fullscreen .bilibili-player-danmaku-setting-lite-panel { border-color: rgba(255,255,255,.3) !important; } #bilibiliPlayer.mode-fullscreen .bilibili-player-mode-selection-container.active, #bilibiliPlayer.mode-fullscreen .bilibili-player-color-picker-container.active { background: rgba(0,0,0,0.3) !important; border-color: rgba(255,255,255,.3) !important; }';
var playerCssStr = '<style id="player-style">' + playerCss + ' </style>';
$(playerCssStr).appendTo($('body', s.dom_type));
}
if (onlyIframe == true) return false;
if (s.cfg.control_view.status == 1) {
var float = s.cfg.control_view.float == 1 ? 'left' : 'right';
var width = '45px';
controlViewCss = '#control-view-box { font-family: SimSun; z-index: 9999999999; cursor: pointer; position: fixed; opacity: 0.5; ' + float + ': 5px; top: 200px; width: ' + width + '; box-sizing:border-box; color: #fff; font-size: 13px; line-height: ' + width + '; } [data-cmd] { text-align: center; display: block; width: ' + width + '; height: ' + width + '; width: 100%; border-radius: 50%; } span[data-cmd] { background-color: rgb(248,142,139); } #control-view-box>ul { overflow-y: hidden; max-height: 0; width: 100%; clear: both; transition: 0.5s 0s max-height ease; } li[data-cmd] { margin-top: 5px; background-color: rgb(170,215,255); } #control-view-box.show>ul { max-height: 300px; } [data-cmd]:hover { background-color: rgb(68,216,128); } [data-cmd]:hover { background-color: rgb(69,218,132); }';
var controlViewCssStr = '<style id="controlViewCss-style">' + controlViewCss + ' </style>';
$(controlViewCssStr).appendTo($('body'));
}
},
/* 控制视图 */
controlView: function(_type) {
var s = this;
if (s.cfg.control_view.status != 1) return false;
var type_arr = ['switch', 'add', 'show', 'hide'];
var type = $.inArray(_type, type_arr) != -1 ? _type : type_arr[0];
var id = 'control-view-box';
var $s = $('#' + id);
if (type == 'add') {
if ($s.length >= 1) return false;
var html = '\
<div id="' + id + '" class="show">\
<span data-cmd="switch" title="收缩/展开">Bili</span>\
<ul>\
<li data-cmd="70" title="双击F/单击ESC">全屏</li>\
<li data-cmd="80" title="双击P">播/暂</li>\
<li data-cmd="84" title="双击T">弹幕</li>\
<li data-cmd="75" title="双击K">上一P</li>\
<li data-cmd="76" title="双击L">下一P</li>\
</ul>\
</div>';
$('body').append(html);
var windowHeight = document.documentElement.clientHeight;
var boxHeight = $('#control-view-box')[0].clientHeight;
var topHeight = parseInt((windowHeight - boxHeight) / 2) + 'px';
$('#control-view-box').css('top', topHeight);
} else if (type == 'switch') {
var flag = $s.hasClass('show');
flag ? $s.removeClass('show') : $s.addClass('show');
} else if (type == 'show') {
$s.addClass('show');
} else if (type == 'hide') {
$s.removeClass('show')
}
},
/* 事件绑定 */
band: function(type) {
var s = this;
var type = type || 'init';
if (type == 'init') {
$dom = s.dom_type == document ? $(document) : $(document).add(s.dom_type);
if (s.dom_type != document) {
s.hash = location.hash;
$(s.keyData.keyBtn[0].currPageBgm).on('click', function() {
var hash = location.hash;
console.log('log: ' + hash + ', ' + s.hash);
if (hash == s.hash) return false;
s.hash = hash;
s.keyData.keyBtn[0].addCssIframe(s);
});
}
keyupEvent($dom);
viewEvent(s);
/*} else if (type == 'bangumi') {
s.keyData.keyBtn[0].addCssIframe(s);*/
} else if (type == 'bangumi_keyup') {
var $dom = $(document).add(s.dom_type);
$dom.off('keyup'); // 重新绑定
keyupEvent($dom);
}
function keyupEvent($dom) {
s.cfg.keyboard_flag < 1 || $dom.on('keyup', function(event) {
if ($("input:focus, textarea:focus").length > 0) return false; // 焦点在输入框时 不响应按键事件
var keyCode = event.keyCode;
var double = doubleClick(keyCode);
var one_click = $.inArray(s.cfg.keyboard_flag, [1, 3]) != -1 ? true: false;
var double_click = $.inArray(s.cfg.keyboard_flag, [1, 2]) != -1 ? true: false;
if (double == false && one_click == true) { // 非双击
keyCode = '_' + keyCode;
if (typeof s.keyData.keyBtn[keyCode] == 'undefined') return false;
s.keyAction(keyCode);
} else if (double == true && typeof s.keyData.keyBtn[keyCode] != 'undefined' && double_click == true) {
s.keyAction(keyCode);
}
});
/* 双击判定 */
function doubleClick(keyCode) {
var timenow = (new Date()).getTime();
if (s.keyData.timenow == 0) {
s.keyData.timenow = timenow;
s.keyData.preKey = keyCode;
return false;
} else {
var intval = timenow - s.keyData.timenow;
if (intval < s.keyData.keepTime && s.keyData.preKey == keyCode) {
s.keyData.timenow = 0;
return true;
}
s.keyData.preKey = keyCode;
s.keyData.timenow = timenow;
}
return false;
}
}
/* 悬浮按钮 */
function viewEvent(s) {
s.cfg.control_view.status == 1 && $(document).on('click', '#control-view-box [data-cmd]', function() {
var cmd = $(this).data('cmd');
if (cmd == 'switch') {
s.controlView(); // swith
return true;
}
s.keyAction(cmd);
if (s.cfg.control_view.auto_hide == 1) s.controlView('hide');
});
}
},
/* 自动类操作 */
autoAction: function() {
var s = this;
if (s.cfg.auto_danmuku == 1) s.keyAction(84);
if (s.cfg.auto_playvedio == 1) s.keyAction(80);
if (s.cfg.auto_widescreen == 1) s.keyAction('widescreen');
if (s.cfg.auto_preventshade == 1) s.keyAction('preventshade');
if (s.cfg.auto_position == 1) s.keyAction('automatic_positioning');
},
/* 按键操作 */
keyAction: function(_keyCode) {
var s = this;
var keyCode = _keyCode || false;
if (keyCode == false || typeof s.keyData.keyBtn[keyCode] == 'undefined') return false;
var keyData = s.keyData.keyBtn[keyCode];
var selector = keyData.selector || false;
var subsidiary_func = keyData.function || false;
if (selector != false) $(selector, s.dom_type).click(); // 点击操作
if (subsidiary_func != false) subsidiary_func(keyData, s); // 附属操作
console.log('log: ' + s.keyData.keyBtn[keyCode].type + ' Action.');
},
/* 数据操作 */
dataMgr: function(act) {
var s = this;
var action = act == 'set' ? 'set' : 'get';
if (action == 'get') {
var cfgStr = GM_getValue('config');
if (typeof cfgStr == 'undefined' || cfgStr == '') {
s.cfg = s.defaultCfg;
return false;
}
var cfg_obj = JSON.parse(cfgStr);
$.extend(s.cfg, s.defaultCfg, cfg_obj); // 合并
} else {
var cfgStr = JSON.stringify(s.cfg);
GM_setValue('config', cfgStr);
}
}
};
danmukuObj.launcher(config);