hitomi.la_zh-TW

這是在 hitomi.la 網站上運作的腳本,主要是將網頁中的類型、語言、分類標籤和系列英語部分換成中文,以便於了解作品的資訊。

  1. // ==UserScript==
  2. // @name hitomi.la_zh-TW
  3. // @namespace hitomi.la TW
  4. // @description 這是在 hitomi.la 網站上運作的腳本,主要是將網頁中的類型、語言、分類標籤和系列英語部分換成中文,以便於了解作品的資訊。
  5. // @version 13.4
  6. // @include *://hitomi.la/*
  7. // @compatible chrome >=55
  8. // @icon https://ltn.hitomi.la/apple-touch-icon-57x57.png
  9. // ==/UserScript==
  10.  
  11. const TranslatioDataURL = "https://raw.githubusercontent.com/zxc129567142/hitomi.la_zh-TW/master/TranslatioData.min.json";
  12. let topbar = {},
  13. booktypes = {},
  14. lang = {},
  15. bookseries = {},
  16. booktags = {},
  17. // 修改 Daily 的值能夠改變更新翻譯數據的頻率
  18. // 預設值 7
  19. Daily = 7,
  20. nowTime = (new Date).getTime(),
  21. TimeD = 0,
  22. url = location.pathname; // 變數 url 設成當前網址路徑部分
  23.  
  24. const tEng = {
  25. // 將標題轉成網址格式
  26. h3ToURL: str => {
  27. str = str.toLowerCase();
  28. return (str === "recently added") ? "index" : str // encodeURI(str).replace(/\./g, "%2E").replace(/\-/g, "%2D");
  29. },
  30. // 簡單判斷翻譯工作區
  31. tocht: (chgThis, txt, cht) => {
  32. if (chgThis.textContent.match(txt)) {
  33. chgThis.title = txt;
  34. chgThis.textContent = cht
  35. }
  36. },
  37. // 用於 頂部分類類型
  38. topbar: topbar_obj => {
  39. const topbartext = topbar_obj.textContent;
  40. if (topbar[topbartext]) {
  41. topbar_obj.title = topbartext;
  42. topbar_obj.textContent = topbar[topbartext];
  43. }
  44. },
  45.  
  46. //用於 頂部語言
  47. //
  48. //var lang = {
  49. // lang_eng: {
  50. // "cht": lang_cht,
  51. // "url": lang_url
  52. // },
  53. //}
  54.  
  55. topbarLang: lang_obj => {
  56. const toplangtext = lang_obj.textContent;
  57. const h3 = document.querySelector("h3");
  58. const Title_h3 = h3.getAttribute("title") || h3.textContent;
  59. const weburl = url.match("\/(galleries|manga|anime|doujinshi|gamecg|cg)\/");
  60. if (!lang[toplangtext]) {
  61. console.log(toplangtext);
  62. return false
  63. }
  64. const lang_url = lang[toplangtext].url;
  65.  
  66. // console.log(lang_obj.innerHTML.match(lang_url) , lang_obj.innerHTML === toplangtext);
  67. const RegExpUrl = new RegExp((tEng.h3ToURL(Title_h3) === "index" && lang_url === "all") ? "^\/$" : "(" + tEng.h3ToURL(Title_h3) + "\-" + lang_url + ")", "g");
  68. if (RegExpUrl.test(lang_obj.getAttribute("href")) || weburl) {
  69. lang_obj.title = toplangtext + " \( " + lang_url + " \)";
  70. lang_obj.textContent = lang[toplangtext].cht;
  71. }
  72. },
  73. //用於 語言
  74. lang: lang_obj => {
  75. const langText = lang_obj.textContent;
  76. if (lang[langText]) {
  77. lang_obj.title = langText + " \(" + lang[langText].url + "\)";
  78. lang_obj.textContent = lang[langText].cht;
  79. return;
  80. }
  81. lang_obj.title = langText.toUpperCase();
  82. },
  83. //用於 類型
  84. types: types_obj => {
  85. const typeText = types_obj.textContent.replace(/(^\s+)|(\s+$)/g, "");
  86. if (booktypes[typeText]) {
  87. types_obj.title = typeText;
  88. types_obj.textContent = booktypes[typeText];
  89. return;
  90. }
  91. types_obj.title = typeText.toUpperCase();
  92. },
  93. //用於 系列
  94. series: series_obj => {
  95. const seriesText = series_obj.textContent;
  96. if (bookseries[seriesText]) {
  97. series_obj.title = seriesText;
  98. series_obj.textContent = bookseries[seriesText];
  99. return;
  100. }
  101. series_obj.title = seriesText.toUpperCase();
  102. },
  103. //用於 標籤
  104. tags: tags_obj => {
  105. const tagText = tags_obj.textContent;
  106. if (booktags[tagText]) {
  107. tags_obj.title = tagText;
  108. tags_obj.textContent = booktags[tagText];
  109. return;
  110. }
  111. tags_obj.title = tagText.toUpperCase();
  112. }
  113. };
  114.  
  115. (function () {
  116. "use strict";
  117. localStorage.setItem("hitomi.la_zh-TW", "loading");
  118.  
  119. // 只要有任何一個不存在就重新下載 json 檔
  120. if (!localStorage.hasOwnProperty("LastUpdata") ||
  121. !localStorage.hasOwnProperty("topbar") ||
  122. !localStorage.hasOwnProperty("booktypes") ||
  123. !localStorage.hasOwnProperty("lang") ||
  124. !localStorage.hasOwnProperty("bookseries") ||
  125. !localStorage.hasOwnProperty("booktags")) {
  126. // 缺少
  127. gtd(true);
  128. } else {
  129. // 完整
  130. TimeD = (nowTime - localStorage.getItem("LastUpdata")) / 1000;
  131. Daily = Daily * 24 * 3600;
  132. if (TimeD > Daily) {
  133. // 資訊完整 但 達到資料更新時間
  134. gtd(true);
  135. } else {
  136. topbar = JSON.parse(localStorage.getItem("topbar"));
  137. booktypes = JSON.parse(localStorage.getItem("booktypes"));
  138. lang = JSON.parse(localStorage.getItem("lang"));
  139. bookseries = JSON.parse(localStorage.getItem("bookseries"));
  140. booktags = JSON.parse(localStorage.getItem("booktags"));
  141.  
  142. _TopBottom();
  143. }
  144. }
  145.  
  146. function gtd(autoUpdata) {
  147. localStorage.setItem("LastUpdata", nowTime);
  148. fetch(TranslatioDataURL + "?_=" + nowTime, {cache: "no-cache"})
  149. .then(r => r.json())
  150. .then(data => {
  151. localStorage.setItem("topbar", JSON.stringify(data.topbar));
  152. localStorage.setItem("booktypes", JSON.stringify(data.booktypes));
  153. localStorage.setItem("lang", JSON.stringify(data.lang));
  154. localStorage.setItem("bookseries", JSON.stringify(data.bookseries));
  155. localStorage.setItem("booktags", JSON.stringify(data.booktags));
  156.  
  157. topbar = JSON.parse(localStorage.getItem("topbar"));
  158. booktypes = JSON.parse(localStorage.getItem("booktypes"));
  159. lang = JSON.parse(localStorage.getItem("lang"));
  160. bookseries = JSON.parse(localStorage.getItem("bookseries"));
  161. booktags = JSON.parse(localStorage.getItem("booktags"));
  162.  
  163. localStorage.setItem("nowSeriesNum", Object.keys(bookseries).length);
  164. localStorage.setItem("nowTagsNum", Object.keys(booktags).length);
  165.  
  166. if (autoUpdata) {
  167. console.log("資料更新成功");
  168. _TopBottom();
  169. } else {
  170. console.log("手動資料更新成功");
  171. $(".navbar nav").append("<div id=\"Notice\"><span>翻譯資料更新成功</span></div><style>#Notice{background-color:rgba(204, 255, 255, 0.9);border-radius:10px;border-top-right-radius:0;border-top-left-radius:0;position:fixed;top:-50px;left:50%;transform:translate(-50%,0);animation:Notice 1s linear}#Notice span{color:#666;display:block;font-weight:bold;margin:10px 63px}@keyframes Notice {0%{top:-50px}35%{top:0}85%{top:0}100%{top:-50px}}</style>");
  172. }
  173. })
  174. .catch(e => {
  175. console.log("資料取得失敗");
  176. $(".navbar nav").append("<div id=\"Notice\"><span>資料取得失敗</span></div><style>#Notice{background-color:rgba(255, 204, 204, 0.9);border-radius:10px;border-top-right-radius:0;border-top-left-radius:0;position:fixed;top:-50px;left:50%;transform:translate(-50%,0);animation:Notice 2s linear}#Notice span{color:#666;display:block;font-weight:bold;margin:10px 63px}@keyframes Notice {0%{top:-50px}35%{top:0}85%{top:0}100%{top:-50px}}</style>");
  177. throw new Error(e);
  178. });
  179. }
  180.  
  181. // 變數 LoadingStatus 0 為正在載入
  182. // 1 為載入完成
  183. // let LoadingStatus = 0;
  184.  
  185. // 是否在"全部系列"
  186. let inallsatc = false;
  187. // WaitLoad() 等待載入
  188. function WaitLoad() {
  189. const loader_content = $("#loader-content");
  190. const gallery_content = $(".gallery-content");
  191. if (loader_content.length == 1 || gallery_content.children().length === 0) {
  192. if (loader_content.attr("style") == "display: none;" && gallery_content.children().length > 0) {
  193. // 這是給搜尋頁面用的
  194. window.setTimeout(()=>{RunTranslation();}, 150);
  195. } else {
  196. Timeout();
  197. }
  198. } else {
  199. window.setTimeout(()=>{RunTranslation();}, 200);
  200. }
  201. }
  202.  
  203. // Timeout()
  204. // 正規表達式 /all(tags|artists|series|characters)|reader/ (在字串中搜索"all"、"reader"字串)
  205. // 若 hitomi.la 為"全部"和"閱讀"頁面則一百五十毫秒後呼叫 RunTranslation()
  206. // 若是則二百五十毫秒後呼叫 WaitLoad()
  207. function Timeout() {
  208. // 變數 regex 用來儲存正規表示式
  209. const regex = /all(tags|artists|series|characters)|reader/;
  210. if (url.match(regex)) {
  211. window.setTimeout(()=>{RunTranslation()}, 150);
  212. } else {
  213. window.setTimeout(()=>{WaitLoad()}, 250);
  214. }
  215. }
  216.  
  217. // RunTranslation()
  218. // 依序呼叫 _ModifyCSS() _ADRemove() _HotKey()
  219. let YouPosition;
  220.  
  221. function RunTranslation() {
  222. document.querySelector(".navbar")
  223. .insertAdjacentHTML("beforeend","<a id=\"TIMER\" style=\"color: rgb(255, 255, 255);font-weight: bold;\"></a>");
  224.  
  225. YouPosition = url.split("\/")[1].split(/\-|\./);
  226. switch (YouPosition[0]) {
  227. case "manga":
  228. case "anime":
  229. case "doujinshi":
  230. case "gamecg":
  231. case "cg":
  232. case "galleries": {
  233. console.log("========= 畫廊資訊區 =========");
  234. setTimeout(() => {
  235. _TranslationH3();
  236. document.querySelectorAll(".tags")[1].parentElement.classList.add("relatedtags");
  237. _TranslatioGalleries();
  238. _TranslatioGalleriesInfo();
  239. }, 50);
  240. break;
  241. }
  242. case "reader": {
  243. console.log("========= 畫廊閱讀區 =========");
  244. setTimeout(() => {
  245. _TranslationReader();
  246. }, 10);
  247. break;
  248. }
  249. case "alltags": {
  250. console.log("========= 全部-標籤 =========");
  251. _TranslationAll();
  252. break;
  253. }
  254. case "allartists": {
  255. console.log("========= 全部-畫家 =========");
  256. _TranslationAll();
  257. break;
  258. }
  259. case "allseries": {
  260. console.log("========= 全部-系列 =========");
  261. _TranslationAll();
  262. _TranslationAllSeries();
  263. break;
  264. }
  265. case "allcharacters": {
  266. console.log("========= 全部-角色 =========");
  267. _TranslationAll();
  268. break;
  269. }
  270. case "search": {
  271. console.log("========= 搜索區 =========");
  272. setTimeout(() => {
  273. _TranslationSearchH3();
  274. _TranslatioGalleries();
  275. _TranslationSearch();
  276. _HotKey();
  277. }, 10);
  278. break;
  279. }
  280. default: {
  281. console.log("========= ♥♥♥♥♥ =========");
  282. setTimeout(() => {
  283. _TranslationH3();
  284. _TranslationOrderBy();
  285. _TranslatioGalleries();
  286. }, 10);
  287. }
  288. }
  289. if (url.search("reader") < 0) _ModifyCSS();
  290. _ADRemove();
  291. if (url.search("search") < 0) _HotKey();
  292. localStorage.setItem("hitomi.la_zh-TW", "success");
  293. }
  294.  
  295. function _TopBottom() {
  296. _TranslationTopInfo();
  297. if (url.search("reader") < 0) {
  298. const GreasyForkIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3ggEBCQHM3fXsAAAAVdJREFUOMudkz2qwkAUhc/goBaGJBgUtBCZyj0ILkpwAW7Bws4yO3AHLiCtEFD8KVREkoiFxZzX5A2KGfN4F04zMN+ce+5c4LMUgDmANYBnrnV+plBSi+FwyHq9TgA2LQpvCiEiABwMBtzv95RSfoNEHy8DYBzHrNVqVEr9BWKcqNFoxF6vx3a7zc1mYyC73a4MogBg7vs+z+czO50OW60Wt9stK5UKp9Mpj8cjq9WqDTBHnjAdxzGQZrPJw+HA31oulzbAWgLoA0CWZVBKIY5jzGYzdLtdE9DlcrFNrY98zobqOA6TJKHW2jg4nU5sNBpFDp6mhVe5rsvVasUwDHm9Xqm15u12o+/7Hy0gD8KatOd5vN/v1FozTVN6nkchxFuI6hsAAIMg4OPxMJCXdtTbR7JJCMEgCJhlGUlyPB4XfumozInrupxMJpRSRtZlKoNYl+m/6/wDuWAjtPfsQuwAAAAASUVORK5CYII="
  299. const NeocitiesIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURSgwPSkxPisyPiw0QS82QzE0QDA4RDE4RTQ8SDU9STlBTTtCTj5FUT9HUkQ8RkFIVElQW0pRXE1TXlxGTU9VYFddZ1ddaFlgaltha2NJT2tMUnRQVH9UV2FmcGNpcmtwenR4gXh9hXyBiX6Di49bXJBcXJhfX7FqZr5vasNxbMlzbcp0bsx1b852b899d9B2cNF3cdJ4cdF6c9R5ctR5c9R6c9R6dIKGjoWGjYuAhYiMk42SmJGKkJGVnJSXnpuepJ6ip6GDhamssa2wtbO1urO2u7S2urS2u7u+wsyLh8ORj9iJg9uQituSjNyUj92Xkd2ZlN6cl9+fmuChneWxrOayruazr+azsOe2surAvevCv8rMz9HT1dPV1+Lj5OTm5/bk4vnt7Pnu7fPz9PX19fb29/f3+Prx8fry8vz29vz49/n5+fr6+v36+v77+/z8/Pz9/f7+/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIHOprIAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNv1OCegAAAExSURBVDhPzZJXU8JAGEWzESyggIK9odgVFaOxi4q9994r2P3+/4Ob3UtkNpnR8cnzkLl779k8ZKKxH1AE33DMgwgUYYloChEowhnRPCJwCouI4JdCoV8SvCQ6L8ahQEyWoCUfyIXb5qwQeRfFzcHmcYbo+nDj5EkUz34IjeKY2RoyzN301dqgYe5/iqo8RxiPzgwYnPVV69k7Gp3lZWWOUMJaE9Yk6athDQ4h3IOV0xlwEbzt9isSLcxF0Ku7s3tHwE1gel1cCl1hXroIzNvWb+3xWp4dwnSMM7HMd3NlxMoLiiB53DbMvVcciCogRD5QEKV3jr73ex8EbfIFFf/gbwhEd006BMaKSiVlF0SnIZlD+fK2EGz+/EfZ/BNhDhEoQopoDBEogqe+Kg8RKIIKY1+/n4FUrpnHnQAAAABJRU5ErkJggg=="
  300. $(".container").append("<style>div#lang-drop{width:135px;padding-top:13px;}ul#lang-list a{display:block}</style>");
  301. $(".navbar>nav>ul").append("<li id=\"cht_help\"><a title=\"hitomi.la_zh-TW\">腳本問題 <img src=\"//ltn.hitomi.la/down-arrow.png\"></a><div id=\"cht_help_drop\"><ul id=\"cht_help_list\"><li><span>系列翻譯數:" + localStorage.getItem("nowSeriesNum") + "</span></li><li><span>標籤翻譯數:" + localStorage.getItem("nowTagsNum") + "</span></li><li><a id=\"update\">手動更新數據</a></li><li><a href=\"https://goo.gl/iurbA6\" target=\"_blank\">中文化問題</a></li><li><hr></li><li><a href=\"https://greasyfork.org/zh-TW/scripts/23864-hitomi-la-zh-tw\" target=\"_blank\"><img src='" + GreasyForkIcon + "' alt=\"greasyfork icon\" >Greasy Fork</a></li><li><a href=\"https://zxc129567142.neocities.org/hitomi_la_zh_tw/index.html\" target=\"_blank\"><img src='" + NeocitiesIcon + "'>Neocities</a></li></ul></div></li>");
  302. $(".navbar>nav").append("<style>#cht_help_drop{display:none;position:absolute;margin:0px;padding:0px 15px;padding-top:13px;z-index:99999;background-color:#29313d;left:0px;right:0px;max-height:500px;width:155px;}#cht_help:hover #cht_help_drop{display:block;}#cht_help_list li{color:#aaa;display:block;position:relative;margin-bottom:10px;}#cht_help_list a,#cht_help_list span{color:inherit;display:block;padding:0px;text-decoration:none;text-transform:none;font-weight:normal;}#cht_help_list a{cursor:pointer;}#cht_help_list a:hover{color:#fff;font-weight:bold;}#cht_help_list span{cursor:default;}#cht_help_list img{vertical-align:middle;margin-right:5px;width:20px;}#cht_help_list svg{margin-right:5px;}</style>");
  303. }
  304. _TranslationBottomDonate();
  305. $("#update").one('click', () => {
  306. gtd(false);
  307. });
  308. Timeout();
  309. }
  310.  
  311. //翻譯上方的導覽列
  312. function _TranslationTopInfo() {
  313. //頂部分類類型
  314. $(".navbar a").each((i, v) => {
  315. tEng.topbar(v);
  316. });
  317.  
  318. //頂部語言
  319. const lang = document.querySelector("li#lang>a")
  320. if (lang){
  321. if (lang.textContent.trim() === "language") lang.innerHTML = "語言 <img src='//ltn.hitomi.la/down-arrow.png'>";
  322. }
  323.  
  324.  
  325. const interval = setInterval(() => {
  326. const lang_list = document.querySelectorAll("#lang-list a");
  327. if (lang_list.length > 1) {
  328. clearInterval(interval);
  329. for (const item of lang_list) {
  330. // console.log(item);
  331. tEng.topbarLang(item);
  332. }
  333. }
  334. }, 500 )
  335.  
  336. //頂部搜尋
  337. if ($(".header-table").length > 0) {
  338. $("button#search-button").text("搜尋");
  339. let search_hint = "你可以使用組合條件 \"female:yuri -female:futanari\",此範例會尋找含有 \"yuri\" 但不含 \"futanari\"。"
  340. search_hint += "\n當要輸入帶有空白的標籤使用 \"_\" 字符。"
  341. search_hint += "\n更多範例:"
  342. search_hint += "\n\"series:kantai_collection type:doujinshi female:big_breasts\",會尋找含有 \"系列:艦隊收藏\"、\"類型:同人誌\"、\"巨乳 ♀\" "
  343. search_hint += "\n\"type:artistcg female:milf -male:yaoi language:chinese\",會尋找含有 \"類型:美術 CG\"、\"熟女 ♀\"、\"語言:中文\" 但不包含 \"男同(BL) ♂\" "
  344. search_hint += "\n\"artist:andou_tomoya -type:gamecg series:love_live\",會尋找含有 \"畫家:Andou Tomoya\"、\"系列:Love Live\" 但不包含 \"類型:遊戲 CG\" "
  345. $(".search-input#search").attr("title", search_hint);
  346. }
  347. }
  348.  
  349. //翻譯畫廊相關
  350. function _TranslatioGalleries() {
  351. //分類
  352. const cata = {
  353. "Series": "系列",
  354. "Type": "類型",
  355. "Language": "語言",
  356. "Tags": "標籤",
  357. "Group": "群組",
  358. "Characters": "角色",
  359. }
  360. document.querySelectorAll("tr td:nth-of-type(1)").forEach(v => {
  361. const text = v.textContent
  362.  
  363. switch (text) {
  364. case "Series":
  365. if (v.nextElementSibling.firstElementChild)
  366. v.nextElementSibling.firstElementChild.className = "comma-list";
  367. case "Type":
  368. case "Language":
  369. case "Tags":
  370. case "Group":
  371. case "Characters":
  372. v.title = text;
  373. v.textContent = cata[text];
  374. break;
  375. default: {
  376. console.log("例外 分類: " + text);
  377. }
  378. }
  379. });
  380.  
  381. //語言
  382. document.querySelectorAll("tr:nth-of-type(3) td:nth-of-type(2) a")
  383. .forEach(item => {
  384. tEng.lang(item);
  385. })
  386.  
  387. //類型
  388. document.querySelectorAll("tr:nth-child(2) td:nth-child(2) a")
  389. .forEach(item => {
  390. tEng.types(item);
  391. })
  392.  
  393. //系列
  394. document.querySelectorAll("table .comma-list a")
  395. .forEach(item => {
  396. tEng.series(item);
  397. })
  398.  
  399. //標籤
  400. document.querySelectorAll(".relatedtags a")
  401. .forEach(item => {
  402. tEng.tags(item);
  403. })
  404.  
  405. //當群組、系列、語言為"N/A"
  406. document.querySelectorAll("tr:not(:last-of-type) td:nth-of-type(2)")
  407. .forEach(item => {
  408. tEng.tocht(item, "N/A", "無");
  409. })
  410.  
  411. //當作者名為"N/A"
  412. document.querySelectorAll("div.artist-list")
  413. .forEach(item => {
  414. tEng.tocht(item, "N/A", "無");
  415. })
  416.  
  417. }
  418.  
  419. //翻譯畫廊資訊頁面
  420. function _TranslatioGalleriesInfo() {
  421. //資訊頁面作者名為"N/A"
  422. document.querySelectorAll("h2")
  423. .forEach(item => {
  424. tEng.tocht(item, "N/A", "無");
  425. })
  426.  
  427. //資訊頁面
  428. document.querySelectorAll(".cover-column h1").forEach( item => {
  429. switch (item.textContent) {
  430. case "Download":
  431. item.textContent = "下載"
  432. break;
  433. case "Read Online":
  434. item.textContent = "線上閱讀"
  435. break;
  436. default:
  437. break;
  438. }
  439. });
  440.  
  441. }
  442.  
  443. //翻譯h3標題
  444. function _TranslationH3() {
  445. //區塊h3標題
  446. const h3 = document.querySelector("div.list-title h3")
  447. switch (h3.textContent) {
  448. case "Recently Added": {
  449. tEng.tocht(h3, "Recently Added", "最近更新");
  450. break;
  451. }
  452. case "Popular": {
  453. tEng.tocht(h3, "Popular", "熱門度");
  454. break;
  455. }
  456. case "Related Galleries": {
  457. tEng.tocht(h3, "Related Galleries", "相關畫廊");
  458. break;
  459. }
  460. default: {
  461. console.log(h3.textContent);
  462. }
  463. }
  464. }
  465.  
  466. //翻譯搜尋頁h3標題
  467. function _TranslationSearchH3() {
  468. //區塊h3標題
  469. const h3 = $("div.list-title h3");
  470. const engTxt = h3.text();
  471. const chtTxt = engTxt.replace("Results", "個結果");
  472. h3.attr("title", engTxt).text(chtTxt);
  473. }
  474.  
  475. //翻譯搜尋頁
  476. function _TranslationSearch() {
  477. const pag_top = $(".page-top a")
  478. if (pag_top.length === 0) {
  479. const search_message = document.querySelector(".gallery-content .search-message");
  480. if (search_message.textContent == "No results") search_message.textContent = "無結果";
  481. return;
  482. }
  483.  
  484. pag_top.one("click", () => {
  485. setTimeout(function _Search() {
  486. const loader_content = document.getElementById("loader-content");
  487. if (!loader_content) return;
  488. if (loader_content.style.display == "none" && $(".gallery-content").children().length > 0) {
  489. _TranslatioGalleries();
  490. _ModifyCSS();
  491. _HotKey();
  492. _TranslationSearch();
  493. } else {
  494. setTimeout(() => { _Search() }, 150);
  495. }
  496. }, 50);
  497. });
  498. }
  499.  
  500. //翻譯"全部"頁面
  501. function _TranslationAll() {
  502. //"全部"頁面大標題
  503. let count = 0;
  504. let satc = [
  505. ["tags", "artists", "series", "characters"],
  506. ["標籤", "畫家", "系列", "角色"]
  507. ],
  508. atoz = ["123", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"],
  509. allh3 = $("div.list-title h3");
  510. inallsatc = true;
  511. for (let S = 0; S < satc[0].length; S++) {
  512. if (allh3.text().match(satc[0][S]) == satc[0][S]) {
  513. for (let A = 0; A < atoz.length; A++) {
  514. if (allh3.text().substr(-1) == atoz[A].substr(-1) && allh3.text().substr(0, 3) === "All") {
  515. allh3.text("全部字首 " + atoz[A] + " 的" + satc[1][S]);
  516. count++
  517. }
  518. }
  519. }
  520. }
  521. console.log(count);
  522. }
  523.  
  524. //翻譯"全部"系列
  525. function _TranslationAllSeries() {
  526. //"全部"系列
  527. const ul_post = document.querySelectorAll("ul.posts a")
  528. if (ul_post.length > 0 && url.search("allseries") > 0) {
  529. ul_post.forEach(item => {
  530. tEng.series(item);
  531. });
  532. }
  533. }
  534.  
  535. //翻譯閱讀頁面
  536. function _TranslationReader() {
  537. document.querySelectorAll(".brand")
  538. .forEach(item => {
  539. tEng.tocht(item, "Gallery Info", "畫廊資訊");
  540. });
  541.  
  542. document.querySelectorAll(".navbar-nav a")
  543. .forEach((item)=>{
  544. const itemText = item.textContent.trim()
  545. const itemID = item.id
  546.  
  547. if (itemText === "Next") item.innerHTML = "<i class='icon-chevron-left icon-white'></i>下一頁";
  548. if (itemText === "Prev") item.innerHTML = "上一頁<i class='icon-chevron-right icon-whitee'></i>";
  549. if (itemText === "Fullscreen") item.innerHTML = "<i class='icon-fullscreen icon-white'></i>全螢幕";
  550. if (itemText === "Full Spread") item.innerHTML = "<i class='icon-pause icon-white'></i>全頁";
  551. if (itemText === "Single Page") item.innerHTML = "<i class='icon-stop icon-white'></i>單頁";
  552. if (itemID === "fitVertical") item.innerHTML = "切合<i class='icon-resize-vertical icon-white'></i>";
  553. if (itemID === "fitHorizontal") item.innerHTML = "切合<i class='icon-resize-horizontal icon-white'></i>";
  554. });
  555.  
  556. document.querySelectorAll(".input-medium option")
  557. .forEach(item => {
  558. tEng.tocht(item, item.innerHTML, "第 " + item.value + " 頁");
  559. });
  560. }
  561.  
  562. //翻譯底部官方贊助
  563. function _TranslationBottomDonate() {
  564. //底部贊助
  565. const donate = document.querySelector("div.donate");
  566. if (!donate) return;
  567. const donateHTML = donate.querySelectorAll(".rss-icon")
  568.  
  569. let cloneRSS = "";
  570. if (donateHTML.length > 0) cloneRSS = donate.innerHTML.replace(donate.textContent, "");
  571. if (donate.innerHTML.match("Donate BTC")) donate.innerHTML = cloneRSS + donate.textContent.replace("Donate BTC","贊助 BTC");
  572. }
  573.  
  574. //翻譯排序方式
  575. function _TranslationOrderBy() {
  576. const header_option = document.querySelectorAll("div.header-sort-select option")
  577.  
  578. header_option.forEach(itme => {
  579. tEng.tocht(itme, "Order by:", "排序方式");
  580. tEng.tocht(itme, "Date Added", "日期");
  581. tEng.tocht(itme, "Popularity", "熱門度");
  582. });
  583.  
  584. }
  585.  
  586. //修改CSS
  587. function _ModifyCSS() {
  588. const container = $(".container")
  589. container.append(
  590. inallsatc?
  591. "<style>h3{margin-top:5px;margin-bottom:5px;padding-left:0px;}div.top-content{padding-top:20px}.page-content ul{color:#d47972}</style>"
  592. :
  593. "<style>h3{margin-bottom:5px;padding-left:80px;}div.top-content{padding-top:15px}</style>"
  594. );
  595.  
  596. $("div.gallery-info").find("tr").children("td:first-child").css("width", "50px");
  597.  
  598. const djContent = document.querySelectorAll("div.dj-content")
  599. for (const content of djContent) {
  600.  
  601. }
  602. $("div.dj-content").each((i, v) => {
  603. const item = $(v)
  604. const item_a = item.find("a").last()
  605. if (item.parent().find("h1 a").attr("href") === item_a.attr("href")) {
  606. item_a.css("display", "none");
  607. }
  608. item.find("li.hidden-list-item").removeClass("hidden-list-item");
  609. item.find("tr td:first-child").css("width", "50px");
  610. });
  611. }
  612.  
  613. //額外-廣告
  614. function _ADRemove() {
  615. const els = document.querySelectorAll("div[class*='hitomi'],div[id*='hitomi'],div[style*='z-index'],div[style*='position'],iframe")
  616. for (const el of els) el.remove();
  617. }
  618.  
  619. // 額外-熱鍵
  620. // 參考:Danbooru(https://danbooru.donmai.us/static/keyboard_shortcuts)
  621. // 重複執行
  622. function _HotKey() {
  623. console.log("[_HotKey Init]");
  624. let page = $("html"),
  625. pagClass = "",
  626. pageIndex = 0,
  627. First_page = 1,
  628. End_page = 0,
  629. Scroll_Length = 50,
  630. Break_HotKey = false;
  631.  
  632. let getEl, findEl, Next_pageIndex, Previous_pageIndex;
  633.  
  634. // 搜尋頁面有問題
  635. // 搜尋頁面 : 其他頁面
  636. pagClass = (url.search("search") > 0) ? ".page-top" : ".page-container"
  637.  
  638. const pag = document.querySelector(pagClass);
  639.  
  640. if (pag) {
  641. getEl = pag.querySelectorAll("li");
  642. findEl = [...getEl].filter((b) => b.childElementCount === 0 && b.textContent.search(/\d+/) === 0);
  643. pageIndex = parseInt(findEl[0].textContent);
  644. End_page = parseInt(pag.querySelector("li:last-child").textContent);
  645. localStorage.setItem("pageIndex", pageIndex);
  646.  
  647. if(pageIndex < End_page) pag.querySelector(`a[href$='${pageIndex + 1}']`).classList.add("Next_pageIndex");
  648. if(pageIndex > First_page) pag.querySelector(`a[href$='${(pageIndex - 1 === 1 && pagClass === ".page-container") ? decodeURI(location.pathname) : `${pageIndex - 1}`}']`).classList.add("Previous_pageIndex");
  649. Next_pageIndex = pag.querySelector("a.Next_pageIndex");
  650. Previous_pageIndex = pag.querySelector("a.Previous_pageIndex");
  651. }
  652.  
  653. document.body.onkeyup = function (e) {
  654. let _pI = parseInt(localStorage.getItem("pageIndex"))
  655. if (document.querySelectorAll("#query-input:focus").length > 0) Break_HotKey = true;
  656. switch (e.key) {
  657. case "ContextMenu":
  658. case "Control":
  659. case "Shift":
  660. case "Alt":
  661. case "Tab":
  662. case "Meta":
  663. Break_HotKey = true;
  664. return false;
  665. case "D":
  666. case "d":
  667. case "ArrowRight": //下一頁
  668. if (End_page > _pI && !Break_HotKey && Next_pageIndex) {
  669. Next_pageIndex.click();
  670. }
  671. Break_HotKey = false;
  672. break;
  673. case "A":
  674. case "a":
  675. case "ArrowLeft": //上一頁
  676. if (First_page < _pI && !Break_HotKey && Previous_pageIndex) {
  677. Previous_pageIndex.click();
  678. }
  679. Break_HotKey = false;
  680. break;
  681. case "W":
  682. case "w":
  683. case "S":
  684. case "s":
  685. Scroll_Length = 50;
  686. Break_HotKey = false;
  687. break;
  688. case "H":
  689. case "h": //回首頁
  690. if (!Break_HotKey) {
  691. $("div#logo a")[0].click();
  692. }
  693. Break_HotKey = false;
  694. break;
  695. case "Q":
  696. case "q": //搜索
  697. if (!url.match("(\/reader\/)") && !Break_HotKey) {
  698. page.stop().animate({
  699. scrollTop: 0,
  700. }, 200, "linear", () => {
  701. $("#query-input").focus();
  702. });
  703. }
  704. Break_HotKey = false;
  705. break;
  706. default:
  707. Break_HotKey = false;
  708. }
  709. }
  710.  
  711. document.body.onkeydown = function (e) {
  712. if (document.querySelectorAll("#query-input:focus").length > 0) Break_HotKey = true;
  713. switch (e.key) {
  714. case "ContextMenu":
  715. case "Control":
  716. case "Shift":
  717. case "Alt":
  718. case "Tab":
  719. case "Meta":
  720. Break_HotKey = true;
  721. return false;
  722. case "W":
  723. case "w": //向上滾動
  724. if (page.scrollTop() > 0 && !Break_HotKey) {
  725. page.stop().animate({
  726. scrollTop: page.scrollTop() - Scroll_Length,
  727. }, 100, "linear");
  728. Scroll_Length += 5;
  729. } else { //網頁到頂
  730. break;
  731. }
  732. Break_HotKey = false;
  733. break;
  734. case "S":
  735. case "s": //向下滾動
  736. if (page.scrollTop() + $(window).height() < page.outerHeight() && !Break_HotKey) {
  737. page.stop().animate({
  738. scrollTop: page.scrollTop() + Scroll_Length,
  739. }, 100, "linear");
  740. Scroll_Length += 5;
  741. } else { //網頁到底
  742. break;
  743. }
  744. Break_HotKey = false;
  745. break;
  746. default:
  747. Break_HotKey = false;
  748. }
  749. };
  750. }
  751.  
  752.  
  753. })();