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 = window.matchMedia('(hover: none), (pointer: coarse)').matches ||  | |||
                            mw.config.get('wgDisplayResolution') === 'mobile' ||    | |||
                            'ontouchstart' in document.documentElement;  | |||
         const timerLength = isTouchscreen ? 0 : 200;  |          const timerLength = isTouchscreen ? 0 : 200;  | ||
         $(".inline-unihan").each(function() {  |          $(".inline-unihan").each(function() {  | ||
| 第85行: | 第66行: | ||
                     if (!tooltipNode || tooltipNode.parentNode !== bodyContent) {  |                      if (!tooltipNode || tooltipNode.parentNode !== bodyContent) {  | ||
                         requestAnimationFrame(() => {  |                          requestAnimationFrame(() => {  | ||
                             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 =   |                      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);
            });
        });
    })();
})();