Greasy Fork

来自缓存

Greasy Fork is available in English.

Bilibili av/bv link preview

鼠标置于av/bv/cv号链接上时弹出详细信息

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Bilibili av/bv link preview
// @name:zh-CN   Bilibili av/bv 链接预览
// @namespace    http://tampermonkey.net/
// @version      0.8
// @description  鼠标置于av/bv/cv号链接上时弹出详细信息
// @author       xdedss
// @match        https://www.bilibili.com/video/*
// @match        https://www.bilibili.com/read/*
// @grant        none
// @require     https://code.jquery.com/jquery-2.2.4.min.js
// ==/UserScript==

(function() {
    //可更改的设定
    var cover_width = 280; //窗口宽度
    var cover_padding = 15; //窗口padding
    var face_width = 20; //up头像大小
    var max_desc_length = 60; //视频描述长度

    var active_element = null;

    //获取元素坐标
    function getTop(e){
        var offset=e.offsetTop;
        if(e.offsetParent!=null) offset+=getTop(e.offsetParent);
        return offset;
    }
    function getLeft(e){
        var offset=e.offsetLeft;
        if(e.offsetParent!=null) offset+=getLeft(e.offsetParent);
        return offset;
    }

    function pad(num, n) {
        num = num.toString();
        var len = num.length;
        while(len < n) {
            num = "0" + num;
            len++;
        }
        return num;
    }
    function trimDesc(desc){
        if (desc.length < max_desc_length){
            return desc;
        }
        return desc.substr(0, max_desc_length - 10) + '...';
    }
    function formatDuration(seconds){
        var sec = seconds % 60;
        seconds -= sec;
        var min = (seconds / 60) % 60;
        seconds -= 60 * min;
        var hr = seconds / 3600;

        var res = `${pad(min, 2)}:${pad(sec, 2)}`;
        if (hr != 0){
            res = pad(hr, 2) + ':' + res;
        }
        return res;
    }
	function formatTime(timestamp) {
	    var date = new Date(timestamp * 1000);
	    var Y = pad(date.getFullYear(), 2);
	    var M = pad(date.getMonth() + 1, 2);
	    var D = pad(date.getDate(), 2);
	    var h = pad(date.getHours(), 2);
	    var m = pad(date.getMinutes(), 2);
	    var s = pad(date.getSeconds(), 2);
	    return `${Y}-${M}-${D} ${h}:${m}:${s}`;
	}
	function formatNumber(num){
	    if (num >= 10000){
	        return (Math.round(num / 1000) / 10.0) + '万';
	    }
	    return num + '';
	}

    //重设框的位置
    function initBox(e){
        if ($('#avbvinfo').length == 0){
            $('body').after(`<div id="avbvinfo" class="" style="z-index:2333;font-size:12px;position:absolute;left:20px;top:100px;max-width:${cover_width}px;padding:${cover_padding}px;display:none;box-shadow:0 2px 4px rgba(0,0,0,.16);border:1px solid #e5e9ef;border-radius:4px;background:#fff"></div>`);
        }
        $('#avbvinfo').css('left', Math.min($('body')[0].offsetWidth-cover_width-2*cover_padding, Math.floor(getLeft(e.target)+Math.max(15, e.target.offsetWidth * 0.1)))+'px')
            .css('top', Math.floor(getTop(e.target)+e.target.offsetHeight * 0.9)+'px').css('display','').html('...');
    }
    //隐藏
    function hideBox(){
        $('#avbvinfo').css('display', 'none').html('...');
        active_element = null;
    }
    //在框内显示内容
    function showBox(data){
        //console.log(data);
        if (data.code != 0) {
            $('#avbvinfo').html(`啊叻?视频不见了?<br>error ${data.code}&nbsp;&nbsp;&nbsp;${data.message}`);
            return;
        }
        data = data.data;
        $('#avbvinfo').html(`
av${data.aid} / ${data.bvid} / cid${data.cid}<br>
<b>${data.title.replace('"', "&quot;")}</b><br>
<span style="color:#666">${formatTime(data.pubdate)}</span><br>
<span style="color:#333" title="${data.desc.replace('"', "&quot;")}">${trimDesc(data.desc).replace('"', "&quot;")}</span><br>
<div style="">
    <img src="${data.owner.face}" width=${face_width}px style="border-radius:${face_width/2}px;display:inline"/>
    <a target="_blank" class="name" href="https://space.bilibili.com/${data.owner.mid}" style="vertical-align:top;line-height:${face_width}px;"><b>${data.owner.name}</b></a>
</div>
<table style="table-layout: fixed;width:100%;">
<tr>
<td style="text-align:center"><span title="${data.stat.view}"><i class="bilifont bili-icon_shipin_bofangshu"></i>${formatNumber(data.stat.view)}</span></td>
<td style="text-align:center"><span title="${data.stat.danmaku}"><i class="bilifont bili-icon_shipin_danmushu"></i>${formatNumber(data.stat.danmaku)}</span></td>
<td style="text-align:center"></td>
<td style="text-align:center"><span>${formatDuration(data.duration)}</span></td>
</tr>
</table>
<img id="playcover" onclick="$('#playframe').css('display','');$('#playcover').css('display','none')" src="${data.pic}" width=${cover_width}px/>
<iframe id="playframe" src="//player.bilibili.com/player.html?aid=${data.aid}" scrolling="yes" border="0" frameborder="no" framespacing="0" allowfullscreen="false" style="width: ${cover_width}px;display:none"> </iframe>
<table style="table-layout: fixed;width:100%;">
<tr>
<td style="text-align:center"><span title="${data.stat.like}"><i class="bilifont bili-icon_shipin_dianzanshu"></i>${formatNumber(data.stat.like)}</span></td>
<td style="text-align:center"><span title="${data.stat.coin}"><i class="bilifont bili-icon_shipin_yingbishu"></i>${formatNumber(data.stat.coin)}</span></td>
<td style="text-align:center"><span title="${data.stat.favorite}"><i class="bilifont bili-icon_shipin_shoucangshu"></i>${formatNumber(data.stat.favorite)}</span></td>
<td style="text-align:center"><span title="${data.stat.reply}"><i class="bilifont bili-icon_xinxi_pinglunshu"></i>${formatNumber(data.stat.reply)}</span></td>
</tr>
</table>
`);
    }
    function showBoxCv(data){
        if (data.code != 0) {
            $('#avbvinfo').html(`页面不存在或已被删除<br>error ${data.code}&nbsp;&nbsp;&nbsp;${data.message}`);
            return;
        }
        data = data.data;
        $('#avbvinfo').html(`
<b>${data.title.replace('"', "&quot;")}</b><br>
<div style="">
    <i class="bilifont bili-icon_xinxi_UPzhu"></i>
    <a target="_blank" class="name" href="https://space.bilibili.com/${data.mid}" style="vertical-align:top;line-height:${face_width}px"><b>${data.author_name}</b></a>
</div>
<span title="${data.stats.view}">${formatNumber(data.stats.view)}阅读</span>
<img id="playcover" src="${data.banner_url}" width=${cover_width}px/>
<table style="table-layout: fixed;width:100%;">
<tr>
<td style="text-align:center"><span title="${data.stats.like}"><i class="bilifont bili-icon_shipin_dianzanshu"></i>${formatNumber(data.stats.like)}</span></td>
<td style="text-align:center"><span title="${data.stats.coin}"><i class="bilifont bili-icon_shipin_yingbishu"></i>${formatNumber(data.stats.coin)}</span></td>
<td style="text-align:center"><span title="${data.stats.favorite}"><i class="bilifont bili-icon_shipin_shoucangshu"></i>${formatNumber(data.stats.favorite)}</span></td>
<td style="text-align:center"><span title="${data.stats.reply}"><i class="bilifont bili-icon_xinxi_pinglunshu"></i>${formatNumber(data.stats.reply)}</span></td>
</tr>
</table>
`);
    }

    //按av/bv号查询信息
    function queryAv(aid, callback){
        $.ajax({
            url: "https://api.bilibili.com/x/web-interface/view?aid=" + aid,
            success: callback
        });
    }
    function queryBv(bvid, callback){
        $.ajax({
            url: "https://api.bilibili.com/x/web-interface/view?bvid=" + bvid,
            success: callback
        });
    }
    function queryCv(cvid, callback){
        $.ajax({
            url: "https://api.bilibili.com/x/article/viewinfo?id=" + cvid,
            success: callback
        });
    }

    //鼠标监听
    function mouseoverAv(e){
        if (!e.target || !e.target.href) return;
        if (e.target != active_element){
            active_element = e.target;
            initBox(e);
            var aid = e.target.href.match(/av[0-9]+/)[0].replace('av', '');
            queryAv(aid, (d)=>showBox(d));
        }
    }
    function mouseoverBv(e){
        if (!e.target || !e.target.href) return;
        if (e.target != active_element){
            active_element = e.target;
            initBox(e);
            var bvid = e.target.href.match(/bv[0-9a-zA-Z]+/i)[0];
            queryBv(bvid, (d)=>showBox(d));
        }
    }
    function mouseoverCv(e){
        if (!e.target || !e.target.href) return;
        if (e.target != active_element){
            active_element = e.target;
            initBox(e);
            var cvid = e.target.href.match(/cv[0-9]+/)[0].replace('cv', '');
            queryCv(cvid, (d)=>showBoxCv(d));
        }
    }

    //给新出现的连接加监听
    function tryAddListeners(){
        $('a[href^="//www.bilibili.com/video/bv"][mark_avbvinfo!="true"]').mouseover(mouseoverBv).attr('mark_avbvinfo','true');
        $('a[href^="//www.bilibili.com/video/BV"][mark_avbvinfo!="true"]').mouseover(mouseoverBv).attr('mark_avbvinfo','true');
        $('a[href^="//www.bilibili.com/video/av"][mark_avbvinfo!="true"]').mouseover(mouseoverAv).attr('mark_avbvinfo','true');
        $('a[href^="//www.bilibili.com/read/cv"][mark_avbvinfo!="true"]').mouseover(mouseoverCv).attr('mark_avbvinfo','true');
    }

    //给新出现的元素加给新出现的连接加监听的监听
    function tryInit(){
        $('.btn-more[mark_avbvinfo!="true"]').click(()=>{window.setTimeout(tryAddListeners, 1500);}).attr('mark_avbvinfo','true');
        $('.tcd-number[mark_avbvinfo!="true"]').click(()=>{window.setTimeout(tryAddListeners, 1500);}).attr('mark_avbvinfo','true');

        $('body[mark_avbvinfo!="true"]').click((e)=>{
            hideBox();
        }).mouseenter((e)=>{
            //console.log(e.target)
            if (e.target != active_element){
                hideBox();
            }
        }).attr('mark_avbvinfo','true');
        tryAddListeners();
    }
    
    function delayedInit(){
        window.setTimeout(tryInit, 2*1000);
        window.setTimeout(tryInit, 4*1000);
        window.setTimeout(tryInit, 6*1000);
        window.setTimeout(tryInit, 10*1000);
    }

    $('body').click((e)=>{
        tryInit();
    });
    $('.comment-list ').mouseenter((e)=>{
        delayedInit()
    });
    
    delayedInit()

})();