跳转到内容

MediaWiki:Gadget-UnihanTooltips.js:修订间差异

勤求古训,博采众方
创建页面,内容为“本小工具可以將[[Template:僻字]]的提示由原來的title提示改為元素式彈出提示,使觸控式裝置可以觀看有關提示:​ (function() { // 使用MediaWiki的Cookie方法 const dontLoad = mw.util.getParamValue("UTdontload"); if (dontLoad && !isNaN(dontLoad)) { mw.cookie.set("UTdontload", "1", { path: "/", expires: parseInt(dontLoad) }); } if (mw.cookie.get("UTdontload") === "1") return; (function()…”
 
无编辑摘要
第2行: 第2行:
   本小工具可以將[[Template:僻字]]的提示由原來的title提示改為元素式彈出提示,使觸控式裝置可以觀看有關提示
   本小工具可以將[[Template:僻字]]的提示由原來的title提示改為元素式彈出提示,使觸控式裝置可以觀看有關提示
*/
*/
(function() {
(function() {
     // 使用MediaWiki的Cookie方法
     // 使用MediaWiki的Cookie方法
第20行: 第19行:


         // 更可靠的触摸检测
         // 更可靠的触摸检测
        const isTouchscreen = mw.config.get('wgDisplayResolution') === 'mobile' ||  
const isTouchscreen = window.matchMedia('(hover: none), (pointer: coarse)').matches ||
                            'ontouchstart' in document.documentElement;
                            mw.config.get('wgDisplayResolution') === 'mobile' ||  
                            'ontouchstart' in document.documentElement;
         const timerLength = isTouchscreen ? 0 : 200;
         const timerLength = isTouchscreen ? 0 : 200;
        // 添加CSS样式
        mw.util.addCSS(`
            .unihantooltip {
                position: absolute;
                z-index: 999;
                background: #fff;
                border: 1px solid #ccc;
                padding: 5px;
                border-radius: 3px;
                box-shadow: 0 2px 5px rgba(0,0,0,0.2);
                opacity: 0;
                transition: opacity 0.1s;
            }
            .unihantooltip.UHflipped {
                top: auto !important;
                bottom: 12px;
            }
        `);


         $(".inline-unihan").each(function() {
         $(".inline-unihan").each(function() {
第85行: 第66行:
                     if (!tooltipNode || tooltipNode.parentNode !== bodyContent) {
                     if (!tooltipNode || tooltipNode.parentNode !== bodyContent) {
                         requestAnimationFrame(() => {
                         requestAnimationFrame(() => {
                             $(bodyContent).on("click touchstart", function closeHandler(e) {
                             const closeHandler = (e) => {
                                 const target = e.target || e.srcElement;
                                 const target = e.target || e.srcElement;
                                 let currentElement = target;
                                 let currentElement = target;
第98行: 第79行:
                                     $(bodyContent).off("click touchstart", closeHandler);
                                     $(bodyContent).off("click touchstart", closeHandler);
                                 }
                                 }
                             });
                             };
                           
                            $(bodyContent).on("click touchstart", closeHandler);
                         });
                         });
                     }
                     }
第127行: 第110行:
                         if (!isTouchscreen) {
                         if (!isTouchscreen) {
                             $(tooltipNode).on("mouseenter", show)
                             $(tooltipNode).on("mouseenter", show)
                                           .on("mouseleave", hide);
                                           .on("mouseleave", () => hide(element));
                         }
                         }
                    } else {
                        $(tooltipNode).empty().append(tooltipContent);
                     }
                     }


第134行: 第119行:
                      
                      
                     const position = $(element).position();
                     const position = $(element).position();
                     const viewport = mw.util.getViewportDimensions();
                     const viewport = {
                        width: document.documentElement.clientWidth,
                        height: document.documentElement.clientHeight
                    };
                   
                     let top = position.top - tooltipNode.offsetHeight;
                     let top = position.top - tooltipNode.offsetHeight;
                     let left = position.left - 7;
                     let left = position.left - 7;
第152行: 第141行:
                     $(tooltipNode).css({
                     $(tooltipNode).css({
                         top: Math.max(0, top),
                         top: Math.max(0, top),
                         left: Math.max(0, left)
                         left: Math.max(0, left),
                     });
                        opacity: 0 // 初始设置为透明以准备动画
                     }).stop().animate({ opacity: 1 }, 100);
                 }, timerLength);
                 }, timerLength);
             });
             });

2025年11月2日 (日) 17:53的版本

/*
  本小工具可以將[[Template:僻字]]的提示由原來的title提示改為元素式彈出提示,使觸控式裝置可以觀看有關提示
*/
(function() {
    // 使用MediaWiki的Cookie方法
    const dontLoad = mw.util.getParamValue("UTdontload");
    if (dontLoad && !isNaN(dontLoad)) {
        mw.cookie.set("UTdontload", "1", { path: "/", expires: parseInt(dontLoad) });
    }
    if (mw.cookie.get("UTdontload") === "1") return;

    (function() {
        // 使用MediaWiki提供的content容器
        const bodyContent = mw.util.$content || document.body;
        const canonicalNamespace = mw.config.get('wgCanonicalNamespace');
        
        // 只在这些命名空间运行
        if (!['', 'Project', 'Help'].includes(canonicalNamespace)) return;

        // 更可靠的触摸检测
	const isTouchscreen = window.matchMedia('(hover: none), (pointer: coarse)').matches ||
                            mw.config.get('wgDisplayResolution') === 'mobile' || 
                            'ontouchstart' in document.documentElement;
        const timerLength = isTouchscreen ? 0 : 200;

        $(".inline-unihan").each(function() {
            let tooltipNode = null;
            let hideTimer = null;
            let showTimer = null;

            function hide(refLink) {
                if (tooltipNode && tooltipNode.parentNode === bodyContent) {
                    hideTimer = setTimeout(() => {
                        $(tooltipNode).animate({
                            opacity: 0
                        }, 100, function() {
                            if (tooltipNode && tooltipNode.parentNode) {
                                tooltipNode.parentNode.removeChild(tooltipNode);
                            }
                        });
                    }, isTouchscreen ? 16 : 100);
                }
            }

            function show() {
                if (!tooltipNode.parentNode || tooltipNode.parentNode.nodeType === 11) {
                    bodyContent.appendChild(tooltipNode);
                }
                $(tooltipNode).stop().animate({
                    opacity: 1
                }, 100);
                clearTimeout(hideTimer);
            }

            // 保存原始title并清空
            const originalTitle = this.title;
            this.title = "";

            // 使用jQuery的on方法代替hover
            $(this).on(isTouchscreen ? 'click' : 'mouseenter mouseleave', function(e) {
                const element = this;
                
                if (isTouchscreen && e.type === 'click') {
                    e.preventDefault();
                    
                    if (!tooltipNode || tooltipNode.parentNode !== bodyContent) {
                        requestAnimationFrame(() => {
                            const closeHandler = (e) => {
                                const target = e.target || e.srcElement;
                                let currentElement = target;
                                
                                while (currentElement && !currentElement.classList.contains("unihantooltip")) {
                                    currentElement = currentElement.parentNode;
                                }
                                
                                if (!currentElement) {
                                    clearTimeout(showTimer);
                                    hide(element);
                                    $(bodyContent).off("click touchstart", closeHandler);
                                }
                            };
                            
                            $(bodyContent).on("click touchstart", closeHandler);
                        });
                    }
                }

                if (e.type === 'mouseleave') {
                    clearTimeout(showTimer);
                    hide(this);
                    return;
                }

                showTimer && clearTimeout(showTimer);
                showTimer = setTimeout(() => {
                    const tooltipContent = $("<ul class='reflist'></ul>");
                    const lines = originalTitle.split("\n");
                    
                    lines.forEach(line => {
                        if (line.trim()) {
                            tooltipContent.append($("<li></li>").text(line)).append("<br>");
                        }
                    });

                    if (!tooltipNode) {
                        tooltipNode = document.createElement("div");
                        tooltipNode.className = "unihantooltip";
                        $(tooltipNode).append(tooltipContent);
                        
                        if (!isTouchscreen) {
                            $(tooltipNode).on("mouseenter", show)
                                          .on("mouseleave", () => hide(element));
                        }
                    } else {
                        $(tooltipNode).empty().append(tooltipContent);
                    }

                    show();
                    
                    const position = $(element).position();
                    const viewport = {
                        width: document.documentElement.clientWidth,
                        height: document.documentElement.clientHeight
                    };
                    
                    let top = position.top - tooltipNode.offsetHeight;
                    let left = position.left - 7;

                    // 边界检测
                    if (top < 0) {
                        $(tooltipNode).addClass("UHflipped");
                        top = position.top + $(element).outerHeight();
                    } else {
                        $(tooltipNode).removeClass("UHflipped");
                    }

                    if (left + tooltipNode.offsetWidth > viewport.width) {
                        left = viewport.width - tooltipNode.offsetWidth - 10;
                    }

                    $(tooltipNode).css({
                        top: Math.max(0, top),
                        left: Math.max(0, left),
                        opacity: 0 // 初始设置为透明以准备动画
                    }).stop().animate({ opacity: 1 }, 100);
                }, timerLength);
            });
        });
    })();
})();