Greasy Fork is available in English.

bilipager

人类能用的B站分P列表

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         bilipager
// @namespace    http://s.xmcp.ml/
// @version      0.3.3
// @description  人类能用的B站分P列表
// @author       xmcp
// @match        *://www.bilibili.com/video/*
// @supportURL   https://github.com/xmcp/bilipager
// @contributionURL https://s.xmcp.ml/pakkujs/donate.png
// @grant        none
// ==/UserScript==

const ZINDEX_NORMAL=114514;
const ZINDEX_FULLSCREEN=2147483647;
const WIDTH=350;
const ANIMATION_TIME_MS=200;
const CSSTEXT=`
.bilipager-list::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}
.bilipager-list::-webkit-scrollbar-track {
    background-color: rgba(255,255,255,.3);
}
.bilipager-list::-webkit-scrollbar-thumb {
    background-color: rgba(128,128,128,.6);
}
.bilipager-list::-webkit-scrollbar-thumb:active {
    background-color: rgba(128,128,128,1);
}

.bilipager-list:empty, .bilipager-popover:empty {
    display: none;
}

.bilipager-list {
    width: ${WIDTH}px;
    position: fixed;
    height: 100%;
    background-color: rgba(225,225,225,.9);
    top: 0;
    left: -${WIDTH-1}px;
    opacity: 0;
    z-index: ${ZINDEX_FULLSCREEN};
    box-sizing: border-box;
    padding: 2em 0;
    overflow-y: auto;
    word-break: break-all;
    transition: left ${ANIMATION_TIME_MS}ms ease-out, opacity ${ANIMATION_TIME_MS}ms ease-out;
}
.bilipager-list:hover, .bilipager-list.hover {
    left: 0;
    opacity: 1;
}

.bilipager-list p {
    overflow: hidden;
    padding: .5em .3em .5em .5em;
    cursor: pointer;
    white-space: nowrap;
    transition: padding .2s ease;
}

.bilipager-list p code {
    font-family: Consolas, Courier, monospace;
}

.bilipager-list p span {
    font-size: 1.2em;
}

.bilipager-list p:hover {
    background-color: rgba(255,255,255,.8);
    white-space: normal;
    padding: .5em 0 .5em .8em;
    box-shadow: 0 1px 25px rgba(0,0,0,.3);
}

.bilipager-list p.bilipager-curp {
    background-color: black;
    color: white;
}

.bilipager-list p.animation {
    color: black;
    -webkit-animation: page-switch 1s ease;
            animation: page-switch 1s ease;
}

@-webkit-keyframes page-switch {
    0%   {box-shadow: 0 1px 25px rgba(0,0,0,.3);   background-color: rgba(255,255,255,.8);}
    20%  {box-shadow: 0 1px 25px rgba(0,0,255,.5); background-color: rgba(205,205,255,1); }
    50%  {box-shadow: 0 1px 25px rgba(0,0,255,.5); background-color: rgba(205,205,255,1); }
    100% {box-shadow: 0 1px 25px rgba(0,0,0,.3);   background-color: rgba(255,255,255,.8);}
}
@keyframes page-switch {
    0%   {box-shadow: 0 1px 25px rgba(0,0,0,.3);   background-color: rgba(255,255,255,.8);}
    20%  {box-shadow: 0 1px 25px rgba(0,0,255,.5); background-color: rgba(205,205,255,1); }
    50%  {box-shadow: 0 1px 25px rgba(0,0,255,.5); background-color: rgba(205,205,255,1); }
    100% {box-shadow: 0 1px 25px rgba(0,0,0,.3);   background-color: rgba(255,255,255,.8);}
}

.bilipager-popover {
    min-width: 150px;
    position: absolute;
    height: 1.7em;
    line-height: 1.7em;
    font-size: 1.2em;
    padding: 0 .5em;
    background-color: black;
    color: white;
    top: 42px;
    left: 10px;
    z-index: ${ZINDEX_NORMAL};
    border-radius: 3px;
    word-break: break-all;
    white-space: nowrap;
}

.bilipager-popover:before {
    content: "";
    position: absolute;
    width: 0;
    height: 0;
    top: 50%;
    left: -4px;
    margin-top: -5px;
    border-width: 5px 5px 5px 0;
    border-color: transparent;
    border-right-color: black;
    border-style: solid;
}
`;

(function() {
    'use strict';

    let list_root=document.createElement('div');
    list_root.className='bilipager-list';
    list_root.addEventListener('mousewheel',function(e) {
        e.stopPropagation();
    });

    let popover=document.createElement('div');
    popover.className='bilipager-popover';
    popover.addEventListener('mouseover',function(e) {
        list_root.classList.add('hover');
        setTimeout(function() {
            list_root.classList.remove('hover');
        },ANIMATION_TIME_MS+10);
    });

    let playlist_cache={};

    function format_duration(d) {
        function pad(t) {
            return (''+t).padStart(2,'0');
        }
        return d<3600 ?
            (Math.floor(d/60)+':'+pad(d%60)) :
            (Math.floor(d/3600)+':'+pad(Math.floor((d%3600)/60))+':'+pad(d%60));
    }

    function reload_ui(aid) {
        if(!playlist_cache[aid]) {
            playlist_cache[aid]=fetch('https://api.bilibili.com/x/player/pagelist?aid='+aid).then(res=>res.json());
        }
        playlist_cache[aid].then(function(plist) {
            list_root.textContent='';
            popover.textContent='';

            console.log('!!',plist);
            if(plist.data.length<=1) return;

            plist.data.forEach(function(p) {
                let li=document.createElement('p');

                let li_1=document.createElement('code');
                li_1.textContent=`[${p.page}] ${format_duration(p.duration)} `;
                li.appendChild(li_1);
                let li_2=document.createElement('span');
                li_2.textContent=`${p.part}`;
                li.appendChild(li_2);

                li.addEventListener('click',function() {
                    li.classList.add('animation');

                    const ind_10=Math.floor((p.page-1)/10)*10+1;
                    const ind_30=Math.floor((p.page-1)/30)*30+1;

                    function paginate_failed() {
                        //alert('pagination failed');
                        location.href='//www.bilibili.com/video/av'+aid+'/?p='+p.page;
                    }

                    for(const pager_30 of document.querySelectorAll('#multi_page .more-box li')) {
                        if(pager_30.textContent.startsWith(ind_30+'-')) {
                            pager_30.click();
                            setTimeout(function() {
                                for(const pager_10 of document.querySelectorAll('#multi_page .paging li')) {
                                    if(pager_10.textContent.startsWith(ind_10+'-')) {
                                        pager_10.click();
                                        setTimeout(function() {
                                            const paginate_link=document.querySelector(`a.router-link-active[href="/video/av${aid}/?p=${p.page}"]`);
                                            if(paginate_link) {
                                                console.log('switch: pagniate link');
                                                paginate_link.click();
                                                return;
                                            }
                                            paginate_failed();
                                        },1);
                                        return;
                                    }
                                }
                                paginate_failed();
                            },1);
                            return;
                        }
                    }
                    paginate_failed();
                });
                list_root.appendChild(li);

                if(p.cid===parseInt(window.cid)) {
                    li.className='bilipager-curp';
                    if(li.scrollIntoViewIfNeeded) {
                        li.scrollIntoViewIfNeeded();
                    } else {
                        li.scrollIntoView(false);
                    }
                    popover.textContent=`[${p.page}/${plist.data.length}] ${p.part}`;
                }
            });
        });
    }

    function setup_listener() {
        function onfschange(e) {
            const elem=document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.body;
            if(list_root.parentNode!==elem) {
                if(list_root.parentNode) {
                    list_root.parentNode.removeChild(list_root);
                }
                elem.appendChild(list_root);
            }
        }
        document.addEventListener('fullscreenchange',onfschange);
        document.addEventListener('webkitfullscreenchange',onfschange);
        document.addEventListener('mozfullscreenchange',onfschange);

        addEventListener('message',function(e) {
            if(e.data.type==='pakku_event_danmaku_loaded') {
                reload_ui(window.aid);
            }
        });
    }

    if(window.aid) {
        let cssobj=document.createElement('style');
        cssobj.textContent=CSSTEXT;
        document.head.appendChild(cssobj);
        document.body.appendChild(list_root);
        document.body.appendChild(popover);
        setup_listener();
        reload_ui(window.aid);
    }
})();