内容展开显示

展开鼠标下方的内容。

目前為 2023-10-27 提交的版本,檢視 最新版本

// ==UserScript==
// @name        内容展开显示
// @namespace   hzhbest
// @include     *://*/*
// @description    展开鼠标下方的内容。
// @version     0.2
// @run-at      document-end
// @license     GNU GPLv3
// ==/UserScript==

(function () {

    'use strict';
    var videotimeout, popuptimeout, mvouttimeout;
    var popuptime, mvouttime, clstime;
    var curelem;
    var topbox, expbox, closebtn;
    var firstopen, vsrc, mt = "";
    var padding = 3;
    let css = `
		.expand_box{display: none; position: absolute; max-height: 98%; max-width: 95%; height: auto; overflow-y: auto; scrollbar-width: thin; background: #ececec; border: 1px solid #a8a8a8; box-shadow: 0 0 5px #222; z-index: 10000; padding: ${padding}px;}
        .expand_box.shown{display: block !important;}
        .expand_box_clb{opacity: 0.05; position: absolute; top: 0; right: 0; font: Arial 16px; height: 18px; line-height:16px; border: 1px solid #737373; background: #f4f4f4;}
        .expand_box_clb:hover{opacity: 1;}
	`;

    // 设置选项 ===
    popuptimeout = 0.5;	// 鼠标悬停弹出延时(秒)
    mvouttimeout = 1;	// 鼠标移出关闭延时(秒)
    //videotimeout = 3;	// 视频播放完后自动关闭延时(秒);钉住时不关闭
    // 设置选项 ||=

    document.body.addEventListener('mouseover', texpand, false);
    addCSS(css);
    topbox = creaElemIn('div', document.body);
    topbox.className = 'expand_box';
    closebtn = creaElemIn('div', topbox);
    closebtn.className = 'expand_box_clb';
    closebtn.innerHTML = 'X';
    expbox = creaElemIn('div', topbox);
    firstopen = false;

    topbox.addEventListener('mouseleave', (event) => {
        console.log("41mouseleave:", event.target);
        firstopen = false;
        mvouttime = setTimeout(() => {
            if (!firstopen) reset();
        }, mvouttimeout * 1000);
    }, false);
    topbox.addEventListener('mousemove', () => {
        clearTimeout(mvouttime);
    }, false);
    closebtn.addEventListener('click', reset, false);

    function texpand(event) {
        if (!event.shiftKey) {
            return;
        }
        let tnode = event.target;
        if (tnode !== curelem) {
            clearTimeout(popuptime);
        }
        if (!tnode.textContent && !tnode.src && !window.getComputedStyle(tnode).backgroundImage) {
            return;
        } console.log(tnode.nodeName, tnode);
        if (!!tnode.textContent && tnode.nodeName == "A") {
            var tnodestyle = window.getComputedStyle(tnode);
            var fontsize = Number(tnodestyle.fontSize.replace('px', ''));
            var linehght = Number(tnodestyle.lineHeight.replace('px', ''));
            var pos = getTrueSize(tnode);
            var lineChrCnt = Math.floor(pos.w / fontsize);
            var lineCnt = Math.ceil(tnode.textContent.length / lineChrCnt);

            if (pos.h < linehght * lineCnt) {
                pos.h = linehght * lineCnt;
                popuptime = setTimeout(() => {
                    expandtext(tnode, pos);
                }, popuptimeout * 1000);
            }
        } else if (window.getComputedStyle(tnode).overflow !== "visible") {
            var pos = getTrueSize(tnode);
            popuptime = setTimeout(() => {
                expandtext(tnode, pos);
            }, popuptimeout * 1000);
        }


        /*         if (tnode.nodeName == 'DIV' && tnode.className.indexOf('detail_wbtext_') == 0) {
                    btnexpand = tnode.querySelector('span.expand');
                } else if (tnode.nodeName == 'P' && tnode.className == 'txt') {
                    btnexpand = tnode.querySelector('a[action-type="fl_unfold"]');
                } else if (true || !/weibo\.com\/\d{10}\/[a-z0-9A-Z]{9}\??/.test(location.href)) {
                    var tvnode = getVideoBox(tnode, event);
                    //console.log('tvnode159: ', tvnode);
                    if (!!tvnode) {
                        popuptime = setTimeout(() => {
                            expandvideo(tvnode, event);
                        }, popuptimeout * 1000);
                        //console.log("167:", exptime, tvnode);
                    } else {
                        //console.log("181c:", exptime);
                        clearTimeout(popuptime);
                    }
                } */
        curelem = tnode;
    }

    function reset() {
        topbox.classList.remove('shown');

    }

    function expandtext(tnode, posiz) {
        firstopen = true;
        expbox.innerHTML = tnode.innerHTML;
        var tnodestyle = window.getComputedStyle(tnode);
        var fontsize = Number(tnodestyle.fontSize.replace('px', ''));
        var linehigh = Number(tnodestyle.lineHeight.replace('px', ''));
        var wh = window.innerHeight;
        var ww = window.innerWidth;
        var etop = Math.max(posiz.t - padding, wh * 0.02);
        var eheight = Math.min(wh * 0.94 - etop, posiz.h);
        var ewidth = posiz.w;
        var eleft = Math.max(ww * 0.02, Math.min(ww * 0.98 - posiz.w, posiz.l)) - padding;
        
        topbox.classList.add('shown');
        expbox.style = `line-height: ${linehigh}px; font-size: ${fontsize}px;`;
        topbox.style = `height: ${eheight}px; width: ${ewidth}px; top: ${etop + window.scrollY}px; left: ${eleft}px; `;
    }

/*     function getVideoBox(elem, event) {
        var velem, telem;
        if (!!elem) {
            if (elem.nodeName == 'VIDEO') {
                velem = elem;
            } else {
                telem = elem.parentNode.querySelector('video');
                if (!!telem && isCursorInElem(telem, event)) {
                    velem = telem;
                }
            }
            if (!!velem && velem.parentNode.nodename !== 'a' && velem.parentNode.id !== "__wb_fbox") {
                return velem;
            }
        }
        return false;
    } */

/*     function expandvideo(vnode, event) {
        //快捷展开动图
        if (vsrc == vnode.src) {
            return;
        }
        clearTimeout(clstime);
        fbox.src = vnode.src;
        vsrc = fbox.src;
        fbox.controls = true;
        bbox.style.display = "block";
        // let mx = event.screenX, my = event.screenY;
        // mx -= 50;
        // my = 10; //Math.min(my - 50, window.innerHeight - fbox.offsetHeight - 50);console.log('fboxh2: ', fbox.offsetHeight);
        bbox.style.top = 40 + "px";
        bbox.style.right = 50 + "px";

        vnode.addEventListener('mouseleave', (event) => {
            //console.log("222c:", exptime);
            clearTimeout(popuptime);
        }, false);
    } */

    function creaElemIn(tagname, destin) {	//在 destin 内末尾创建元素 tagname
        let theElem = destin.appendChild(document.createElement(tagname));
        return theElem;
    }

    function addCSS(css, cssid) {
        let stylenode = creaElemIn('style', document.getElementsByTagName('head')[0]);
        stylenode.textContent = css;
        stylenode.type = 'text/css';
        stylenode.id = cssid || '';
    }

    function isCursorInElem(elem, event) {
        var x = Number(event.clientX) // 鼠标相对屏幕横坐标
        var y = Number(event.clientY) // 鼠标相对屏幕纵坐标

        var elemLeft = Number(elem.getBoundingClientRect().left) // obj相对屏幕的横坐标
        var elemRight = Number(
            elem.getBoundingClientRect().left + elem.clientWidth
        ) // obj相对屏幕的横坐标+width

        var elemTop = Number(elem.getBoundingClientRect().top) // obj相对屏幕的纵坐标
        var elemBottom = Number(
            elem.getBoundingClientRect().top + elem.clientHeight
        ) // obj相对屏幕的纵坐标+height

        return (x > elemLeft && x < elemRight && y > elemTop && y < elemBottom);
    }

    function getTrueSize(elem, posiz) {
        if (!posiz) {
            var p = elem.getBoundingClientRect();
            posiz = {
                w: p.width,
                h: p.height,
                t: p.top,
                l: p.left
            };
        }
        var pp = elem.parentNode.getBoundingClientRect();
        if (pp.width >= posiz.w && pp.height >= posiz.h && pp.top <= posiz.t && pp.left <= posiz.l) {
            return posiz;
        } else {
            return getTrueSize(elem.parentNode, {
                w: Math.min(posiz.w, pp.width),
                h: Math.min(posiz.h, pp.height),
                t: Math.max(posiz.t, pp.top),
                l: Math.max(posiz.l, pp.left)
            });
        }
    }

})();