跳到导航
跳到搜索
注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。
- Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5或Ctrl-R(Mac为⌘-R)
- Google Chrome:按Ctrl-Shift-R(Mac为⌘-Shift-R)
- Internet Explorer或Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
- Opera:按 Ctrl-F5。
/* <nowiki> ← 避免被归类为有脚本错误的页面*/ // 当添加新类型浮层时,需要对应在“★”注释之后的部分添加代码 $(function (){ if (!['view', 'submit'].includes(mw.config.get('wgAction'))) return; var TOOLTIP_CACHE_BLOCK_ID = 'bili-tt-cache-block'; if (document.getElementById(TOOLTIP_CACHE_BLOCK_ID)) return; /* 避免重复调用 */ var TOOLTIP_CACHE_BLOCK = $(); var Link_CLASS_NAME = 'bili-tt'; var CACHE_TIME = 3600; // 解析内容保存在服务器和本地的缓存时间,单位是秒,如果内容不经常改的话,可以设长一些减少服务器压力,增加读取速度 var SMALL_SCREEN = window.innerWidth < 768; var actions = {}; actions.replace = function(block){ // 提取块中的第一个<a>的地址,并将整个块替换为<a> var inner_link = block.querySelector('a[href]'); // 获取块内的第一个a,获取其href和title,然后移除 if (!inner_link) return block; var link = document.createElement('a'); link.setAttribute('href', inner_link.getAttribute('href')); if (inner_link.innerHTML.trim() !== ""){ var span = document.createElement('span'); span.innerHTML = inner_link.innerHTML; inner_link.parentElement.insertBefore(span, inner_link); } inner_link.remove(); var attrs = block.attributes; for(var i = attrs.length - 1; i >= 0; i--){ // 转移各项属性 var attr = attrs[i]; block.removeAttributeNode(attr); link.setAttributeNode(attr); } link.innerHTML = block.innerHTML; block.parentElement.insertBefore(link, block); // 取代位置 block.remove(); return link; }; if (!SMALL_SCREEN){ actions.listen = function(link){ $(link).mouseenter(function(ev){ var $this = $(this); var $div = get_div($this); $this.data('event',ev); // 记录鼠标位置,用于在load_tooltip_lua后重新set_tt_position $div.show(); TOOLTIP_CACHE_BLOCK.show(); set_position($this); }).mouseleave(function(){ var $this = $(this); TOOLTIP_CACHE_BLOCK.hide(); get_div($this).hide(); }); }; actions.init = function(range){ // 添加缓存浮层的区域 if (TOOLTIP_CACHE_BLOCK.length === 0){ $("body").append('<div id="' + TOOLTIP_CACHE_BLOCK_ID + '"></div>'); TOOLTIP_CACHE_BLOCK = $('#' + TOOLTIP_CACHE_BLOCK_ID); } // 为所有浮层添加事件 $(range).find('.' + Link_CLASS_NAME).addBack('.' + Link_CLASS_NAME).each(function(){ actions.listen(actions.replace(this)); }); }; } else { actions.listen = function(link) { $(link).click(function(){ var $this = $(this); var $div = get_div($this); $div.show();// 显示对应的内容 TOOLTIP_CACHE_BLOCK.show(); $('#tt-modal').modal('show'); // 显示模态框 var $btn = $('#tt-modal-btn'); if ($this.attr('href')){ // 跳转按钮 $btn.attr('href', $this.attr('href')); $btn.show(); } else{ // 如果不是链接,隐藏按钮 $btn.hide(); } return false; }); }; actions.init = function(range){ if (TOOLTIP_CACHE_BLOCK.length === 0){ $("body").append('<div class="modal fade" id="tt-modal" tabindex="-1" role="dialog">' + '<div class="modal-dialog">' + '<div id="' + TOOLTIP_CACHE_BLOCK_ID + '">' + '</div>' + '<a id="tt-modal-btn" class="btn btn-primary">前往详情页</a>' + '</div>' + '</div>'); TOOLTIP_CACHE_BLOCK = $('#' + TOOLTIP_CACHE_BLOCK_ID); $('#tt-modal').click(function(){ $('#tt-modal').modal('hide'); // 任意位置点击后隐藏模态框 TOOLTIP_CACHE_BLOCK.children('.bili-tt-cache').hide(); }); } $(range).find('.' + Link_CLASS_NAME).addBack('.' + Link_CLASS_NAME).each(function(){ actions.listen(actions.replace(this)); }); }; } actions.init(document.getElementById('mw-content-text')); // 监听dom变动,为新插入的tt注册事件 new MutationObserver(function(mutationsList){ mutationsList.forEach(function(mutation){ if (mutation.addedNodes) mutation.addedNodes.forEach(actions.init); }); }).observe(document.getElementById('mw-content-text'), { childList: true, // 监视节点增删事件 subtree: true // 包含所有后代节点(而不只是子节点) }); function get_div($link){ var tt_type = get_data($link, 'type'); var tt_name = get_data($link, 'name').replace(' ', '_'); var $div = $(document.getElementById(get_div_id(tt_type,tt_name))); if ($div.length === 0){ $div = new_div($link, SMALL_SCREEN ? null : function(){set_position($link);}); } return $div; } function get_div_id(type, name){ return encodeURIComponent('tt-' + type + '-' + name).replace(/%/g,'.').replace(/[~'!()*]/g,'_'); } function get_data($node, name){ return $node.attr("data-" + name) || ""; } // 根据浮层大小和当前元素的位置,决定浮层的位置(尽量让浮层显示在屏幕中) function set_position($link) { var window_h = $(window).height(); var window_w = $(window).width(); var top = $link.offset().top - $(document).scrollTop(); var left = $link.offset().left; // 元素左侧绝对位置,若发生换行则为第二行的开始位置 var width = $link.outerWidth(); var parent = $link.parent(); var relativeLeft = $link[0].offsetLeft; // 元素第一行左侧相对于容器的位置 var ttWidth = TOOLTIP_CACHE_BLOCK.outerWidth(); var ttHeight = TOOLTIP_CACHE_BLOCK.outerHeight(); TOOLTIP_CACHE_BLOCK.css("left","unset"); TOOLTIP_CACHE_BLOCK.css("right","unset"); if (relativeLeft + width > parent.innerWidth()){ // 元素左侧相对偏移+元素外侧宽度>容器内侧宽度,发生换行 var mouseEvent = $link.data('event'); if (mouseEvent.clientX > window_w / 2){ // 鼠标在左侧 TOOLTIP_CACHE_BLOCK.css("right", window_w - (left + relativeLeft) + 10); // 元素第一行的左侧位置 } else { TOOLTIP_CACHE_BLOCK.css("left", mouseEvent.clientX + 10); // 鼠标滑入位置 } } else if (left > window_w / 2){ TOOLTIP_CACHE_BLOCK.css("right", window_w - left + 10); } else { TOOLTIP_CACHE_BLOCK.css("left", left + width + 10); } if (ttWidth > window_h){ top = 10; } else if (top + ttHeight > window_h){ top = window_h - ttHeight - 10; } TOOLTIP_CACHE_BLOCK.css("top", top); } // 生成浮层 function new_div($link, callback){ callback = callback || function(){}; var tt_type = get_data($link, 'type'); if (tt_type === 'child'){ $link.attr('data-name', Math.random().toString().replace('0.','')); } var tt_name = get_data($link, 'name').replace(' ', '_'); var $div = $('<div></div>'); $div.attr('id', get_div_id(tt_type,tt_name)).addClass('bili-tt-cache'); // 可以为每种type的浮层,写不同的占位文本 // 如果浮层内容简单,也可以直接将其内容使用js生成 switch (tt_type){ // 可以写多种类型 // ★添加类型时,需要在此处添加新的case来为不同类型指定未加载前的占位代码 // case 'test': // ... // break; case 'raw': $div.text(tt_name); break; case 'child': $link.children('.tt-child').show().appendTo($div); break; } $div.appendTo(TOOLTIP_CACHE_BLOCK); // 异步读取模板解析结果 // 如果提示框内容比较简单,则可以在上面用js直接生成,不需要在此处配置 var wikitext = ''; switch (tt_type.slice(0,1)){ case '@': // 模板 var template_name = tt_type.slice(1); wikitext = '{{' + template_name + '|' + tt_name.replace('_', '').replaceAll('\\n', '<br>') + '}}'; // 调用tt_type对应的模板,参数为tt_name break; case '$': // 模块 var module_name = tt_type.slice(1); wikitext = '{{#invoke:' + module_name + '|tooltip|' + tt_name + '}}'; // 调用tt_type对应模块的tooltip方法,参数为tt_name break; default: switch (tt_type){ case 'test': wikitext = '{{#if:1|test|' + tt_name + '}}'; break; case 'wikitext': wikitext = tt_name; break; } } if (wikitext){ $div.text('加载中...'); load_wikitext(wikitext, $div).then(callback); } else{ callback(); } return $div; } // 根据wikitext生成浮层内容 function load_wikitext(wikitext, $div, again) { // 文档:https://wiki.biligame.com/wiki/api.php?action=help&modules=parse return $.get('/soul_land_time_twist/api.php',{ action: "parse", // 解析 format: "json", // 返回内容的格式 disablelimitreport: true, // 不返回使用内存、时间信息 prop: "text", // 返回解析后的文本 contentmodel: "wikitext", // 内容模型 smaxage: CACHE_TIME, maxage: CACHE_TIME, text: wikitext, // 待解析文本 _: mw.config.get('debug') ? Date.now() : null // 调试时不使用缓存 }).then(function(result){ if (result && result.parse && result.parse.text){ $div.html(result.parse.text['*']); } else{ throw result; } })['catch'](function(error){ // 辣鸡解析器,不让我直接.catch if(again){ $div.text('读取失败'); console.log('获取"' + wikitext + '"失败', error); } else{ $div.text('再次尝试...'); return load_wikitext(wikitext, $div, true); } }); } }); /* </nowiki> */