bgm-tv-hover-more-info

在讨论贴中添加一个悬浮窗显示条目信息

当前为 2021-12-28 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name bgm-tv-hover-more-info
  3. // @name:zh 鼠标指向条目链接时显示更多信息
  4. // @namespace https://trim21.me/
  5. // @description 在讨论贴中添加一个悬浮窗显示条目信息
  6. // @version 0.0.5
  7. // @author Trim21 <i@trim21.me>
  8. // @source https://github.com/Trim21/bgm-tv-hover-info
  9. // @supportURL https://github.com/Trim21/bgm-tv-hover-info/issues
  10. // @license MIT
  11. // @match https://bgm.tv/group/topic/*
  12. // @match https://bangumi.tv/group/topic/*
  13. // @match https://chii.in/group/topic/*
  14. // @require https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js
  15. // @run-at document-end
  16. // ==/UserScript==
  17.  
  18.  
  19. /******/ (() => { // webpackBootstrap
  20. /******/ "use strict";
  21. var __webpack_exports__ = {};
  22.  
  23. ;// CONCATENATED MODULE: external "$"
  24. const external_$_namespaceObject = $;
  25. ;// CONCATENATED MODULE: ./src/index.ts
  26.  
  27. const style = `
  28. <style>
  29. .d-block {
  30. display: block;
  31. }
  32. .d-flex {
  33. display: flex;
  34. }
  35.  
  36. #popup {
  37. width: 30em;
  38. /*height: 15em;*/
  39. flex: auto;
  40. background: white;
  41. border: solid 1px black;
  42. position: absolute;
  43. padding: 0.5em;
  44. border-radius: 0.2em;
  45. }
  46. .tag .name {
  47. /*background-color: dodgerblue;*/
  48. /*color: white;*/
  49. }
  50.  
  51. .popup-tags{
  52. display: block;
  53. }
  54.  
  55. .tag {
  56. border-radius: 0.2em;
  57. border: solid 1px gray;
  58. padding: 0 0.3em;
  59. }
  60.  
  61. .image {
  62. padding-right: 2px;
  63. }
  64.  
  65. </style>
  66. `;
  67.  
  68. function createPopup(subject) {
  69. var _subject$images;
  70.  
  71. let rank = '';
  72.  
  73. if (subject.rating.rank) {
  74. rank = `<p class="rateInfo">
  75. <span class="starstop-s"><span class="starlight stars${Math.round(subject.rating.score)}"></span></span>
  76. <small class="fade">${subject.rating.score}</small> <span class="tip_j">(${subject.rating.total}人评分)</span>
  77. </p>`;
  78. }
  79.  
  80. let tags = '';
  81.  
  82. if (subject.tags.length) {
  83. tags = "<div class='popup-tags'>" + subject.tags.sort((a, b) => b.count - a.count).slice(0, 10).map(value => `<span class="tag"><span class="name">${value.name}</span> <small>${value.count}</small></span>`).join('\n');
  84. tags += '</div>';
  85. }
  86.  
  87. return `
  88. <div class="d-flex">
  89. <span class="image d-block">
  90. <img src="${(_subject$images = subject.images) === null || _subject$images === void 0 ? void 0 : _subject$images.small}" class="cover" alt="${subject.name}">
  91. </span>
  92. <div class="d-block">
  93. <h3>${subject.name}</h3>
  94. <small class="grey">${subject.name_cn}</small>
  95. <p class="info tip"> ${subject.summary} </p>
  96. </div>
  97. </div>
  98.  
  99. ${rank}
  100.  
  101. ${tags}
  102. `;
  103. }
  104.  
  105. async function main() {
  106. console.log(GM.info.script.name);
  107. external_$_namespaceObject('head').append(style);
  108. external_$_namespaceObject('a').each((i, e) => {
  109. if (isBangumiSubjectHref(external_$_namespaceObject(e).attr('href'))) {
  110. external_$_namespaceObject(e).on('mouseover', hoverHandler).on('mouseleave', leaveHandler);
  111. }
  112. });
  113. }
  114.  
  115. function isBangumiSubjectHref(s) {
  116. if (!(s !== null && s !== void 0 && s.length)) return false;
  117. return s.startsWith('https://bgm.tv/subject/') || s.startsWith('https://bangumi.tv/subject/') || s.startsWith('https://chii.in/subject/');
  118. }
  119.  
  120. async function leaveHandler() {
  121. external_$_namespaceObject('#popup').remove();
  122. console.log('leave');
  123. }
  124.  
  125. async function hoverHandler() {
  126. const e = external_$_namespaceObject(this);
  127. const href = e.attr('href');
  128.  
  129. if (!href) {
  130. return;
  131. }
  132.  
  133. const url = new URL(href);
  134. const offset = e.offset();
  135. external_$_namespaceObject('body').append('<div id="popup"> loading </div>');
  136. const popup = external_$_namespaceObject('#popup').css({
  137. left: offset.left,
  138. top: offset.top + 40,
  139. position: 'absolute',
  140. 'z-index': 1000
  141. });
  142. const subjectID = url.pathname.split('/').pop();
  143.  
  144. if (!subjectID) {
  145. return;
  146. }
  147.  
  148. const res = await fetch(`https://api.bgm.tv/v0/subjects/${subjectID}`);
  149.  
  150. if (res.status > 400) {
  151. popup.html('not found');
  152. return;
  153. }
  154.  
  155. const data = await res.json();
  156. let html = createPopup(data);
  157.  
  158. if (res.redirected) {
  159. html = '条目被合并到此条目' + html;
  160. }
  161.  
  162. popup.html(html);
  163. }
  164.  
  165. main().catch(console.error);
  166. /******/ })()
  167. ;