轻小说阅读器

修改自pppploi8的通用阅读器,为“真白萌”和“哔哩轻小说”提供阅读模式

  1. // ==UserScript==
  2. // @name 轻小说阅读器
  3. // @version 0.9.1
  4. // @description 修改自pppploi8的通用阅读器,为“真白萌”和“哔哩轻小说”提供阅读模式
  5. // @require https://update.greasyfork.org/scripts/501723/1416523/font-ch-en.js
  6. // @author Y_C_Z
  7. // @match https://masiro.me/*
  8. // @match https://www.linovelib.com/*
  9. // @match https://www.bilinovel.com/*
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM_deleteValue
  13. // @grant GM_listValues
  14. // @grant GM_registerMenuCommand
  15. // @grant unsafeWindow
  16. // @namespace https://greasyfork.org/users/1335970
  17. // ==/UserScript==
  18. (function() {
  19. var voices = [];
  20. var $ = function(selector){
  21. return document.querySelector(selector);
  22. }
  23. var isSupportFontFamily = function (fontFamily) {//判断浏览器是否支持字体
  24. if (typeof fontFamily != 'string') {
  25. return false;
  26. }
  27. var defaultFontFamily = 'Arial';
  28. if (fontFamily.toLowerCase() == defaultFontFamily.toLowerCase()) {
  29. return true;
  30. }
  31. var defaultLetter = 'a';
  32. var defaultFontSize = 100;
  33. // 使用该字体绘制的canvas
  34. var width = 100, height = 100;
  35. var canvas = document.createElement('canvas');
  36. var context = canvas.getContext('2d');
  37. canvas.width = width;
  38. canvas.height = height;
  39. // 全局一致的绘制设定
  40. context.textAlign = 'center';
  41. context.fillStyle = 'black';
  42. context.textBaseline = 'middle';
  43. var getFontData = function (fontFamily) {
  44. // 清除
  45. context.clearRect(0, 0, width, height);
  46. // 设置字体
  47. context.font = defaultFontSize + 'px ' + fontFamily + ', ' + defaultFontFamily;
  48. context.fillText(defaultLetter, width / 2, height / 2);
  49. var data = context.getImageData(0, 0, width, height).data;
  50. return [].slice.call(data).filter(function(value) {
  51. return value != 0;
  52. });
  53. };
  54. return getFontData(defaultFontFamily).join('') !== getFontData(fontFamily).join('');
  55. };
  56. GM_registerMenuCommand("设置", () => {//打开设置窗口
  57. voices = getVoice();//第一次获取到的是空值
  58. addDialog();
  59. var arrFont = dataFont['windows'].concat(dataFont['OS X'], dataFont['office'], dataFont['open']);//获取浏览器可用字体
  60. var fontFamilyoption = '<option value="">默认</option>';
  61. arrFont.forEach(function (obj) {
  62. var fontFamily = obj.en;
  63. if (isSupportFontFamily(fontFamily)) {
  64. fontFamilyoption = fontFamilyoption + '<option value="'+ fontFamily +'">'+ obj.ch +'</option>';
  65. }
  66. });
  67. $("#fontSelect").innerHTML = fontFamilyoption;
  68. setTimeout(function() {
  69. var voiceSelect = document.getElementById('voiceSelect');//注入浏览器可用语音
  70. voices = getVoice();
  71. voices.forEach(function(voice) {
  72. var option = document.createElement('option');
  73. option.value = voice.name;
  74. option.textContent = voice.name;
  75. voiceSelect.appendChild(option);
  76. });
  77. if (GM_getValue('voice') != undefined){
  78. $("#voiceSelect").value = GM_getValue('voice');
  79. }
  80. },0);
  81. if (GM_getValue('ttsbutton') != undefined){
  82. $("input[name='listen']").checked = GM_getValue('ttsbutton');
  83. }else if(window.SpeechSynthesisUtterance){
  84. $("input[name='listen']").checked = true;
  85. }else{
  86. $("input[name='listen']").checked = false;
  87. }
  88. if (GM_getValue('totopbutton') != undefined){
  89. $("input[name='scrollToTop']").checked = GM_getValue('totopbutton');
  90. }else{
  91. $("input[name='scrollToTop']").checked = true;
  92. }
  93. if (GM_getValue('fontFamily') != undefined){
  94. $("#fontSelect").value = GM_getValue('fontFamily');
  95. }
  96. $("#rateInput").value = GM_getValue('rateInput',1);
  97. if(!window.SpeechSynthesisUtterance){
  98. $("input[name='listen']").disabled = true;
  99. $("#voiceSelect").disabled = true;
  100. $("#rateInput").disabled = true;
  101. }
  102. const dialog = document.getElementById('myDialog');
  103. dialog.showModal();
  104. $('#configreset').onclick = function(){
  105. $("input[name='listen']").checked = true;
  106. $("input[name='scrollToTop']").checked = true;
  107. $("#fontSelect").value = '';
  108. $("#voiceSelect").value = '';
  109. $("#rateInput").value = 1;
  110. }
  111. $('#closeDialog').onclick = function(){
  112. if ($("input[name='listen']").checked == false) {//听书按钮
  113. $("._er-tts") && ($("._er-tts").style.display = 'none');
  114. GM_setValue('ttsbutton',false);
  115. }else{
  116. $("._er-tts") && ($("._er-tts").style.display = 'block');
  117. GM_setValue('ttsbutton',true);
  118. }
  119. if ($("input[name='scrollToTop']").checked == false) {//回到顶部按钮
  120. $(".toTop") && ($(".toTop").style.display = 'none');
  121. GM_setValue('totopbutton',false);
  122. }else{
  123. $(".toTop") && ($(".toTop").style.display = 'block');
  124. GM_setValue('totopbutton',true);
  125. }
  126. $("._er-title") && ($("._er-title").style.fontFamily = $("#fontSelect").value);//字体设置
  127. $(".translator") && ($(".translator").style.fontFamily = $("#fontSelect").value);
  128. $("._er-content") && ($("._er-content").style.fontFamily = $("#fontSelect").value);
  129. GM_setValue('fontFamily',$("#fontSelect").value);//保存字体
  130. GM_setValue('voice',$("#voiceSelect").value);//保存语音选择
  131. var rate = parseFloat($("#rateInput").value);
  132. if (rate>10) rate=10;
  133. else if (rate<0.1) rate=0.1;
  134. GM_setValue('rateInput',rate);//保存语速
  135. dialog.remove();
  136. }
  137. });
  138. var blackList = {"masiro.me": true,"www.linovelib.com": true,"www.bilinovel.com": true};
  139. if (location.host == "www.linovelib.com" || location.host == "www.bilinovel.com") {//尝试通过Cloudflare
  140. document.cookie = '__gpi_opt_out=1;';
  141. document.cookie = 'cf_clearance=MHioFTJ3.DT_FjBcW1pGr7CzIvtm9Z29VMbB7d_TLgE-1721550888-1.0.1.1-7FSsg2Gpn9Y1x36Iq.eXyN60H2j.X2HXp_zPYRj17l0d4gzbOQw24ZSptWj.ktb8QTjubE5qO1Vz2YnTmPxAeQ;';
  142. var start=1;
  143. var end=10;
  144. window.onload = function() {
  145. var t1 = setInterval(function(){
  146. for (var n=0;n<10;++n){
  147. $(".adsbygoogle") && $(".adsbygoogle").remove();
  148. }
  149. $("#bottomads") && $("#bottomads").remove();
  150. $("script[src*='adsbygoogle.js']") && $("script[src*='adsbygoogle.js']").remove();
  151. $("script[src*='g.doubleclick.net']") && $("script[src*='g.doubleclick.net']").remove();
  152. $("div[id*='google_ads']") && $("div[id*='google_ads']").remove();
  153. $("div[data-google-query-id]") && $("div[data-google-query-id]").remove();
  154. start++;
  155. if (start>=end ){
  156. clearInterval(t1);
  157. }
  158. },1000);
  159. };
  160. }
  161. // 通用解析模板
  162. function parseContentAndTitle(){
  163. var mainDom = null;
  164. function findMainDom(doms){
  165. for(var i=0;i<doms.length;i++){
  166. var dom = doms[i];
  167. if (dom.classList.contains("nvl-content") || dom.id === "TextContent" || dom.id === "acontent"){//真白萌||哔哩轻小说PC||哔哩轻小说手机端
  168. mainDom = dom;
  169. }
  170. findMainDom(dom.children||[]);
  171. }
  172. }
  173. findMainDom(document.body.children);
  174. var newTitle = '';
  175. var title = document.title;
  176. var textToRemove1 = "真白萌 | ";
  177. var textToRemove2 = " _哔哩轻小说";
  178. title = title.replace(textToRemove1, "").replace(textToRemove2, "");
  179. switch (location.host){
  180. case 'www.bilinovel.com':
  181. var atitle = document.querySelector('#atitle');
  182. if (atitle) {
  183. newTitle = atitle.textContent;
  184. } else {
  185. newTitle = title;
  186. }
  187. break;
  188. default:
  189. // 选择“哔哩轻小说PC”中id为"mlfy_main_text"的元素
  190. var mlfyMainTextElement = document.querySelector("#mlfy_main_text");
  191. if (mlfyMainTextElement) {
  192. // 获取第一个<h1>元素
  193. var firstH1Element = mlfyMainTextElement.querySelector("h1");
  194. if (firstH1Element) {
  195. newTitle = firstH1Element.textContent;
  196. } else {
  197. newTitle = title;
  198. }
  199. } else {
  200. newTitle = title;
  201. }
  202. break;
  203. }
  204. if (mainDom){
  205. return {content: mainDom.innerText, title: newTitle};
  206. }
  207. }
  208. function parsePageUp(){
  209. var reg, text;
  210. var href = "";
  211. var i = 0;
  212. var as = document.querySelectorAll('a');
  213. switch (location.host){
  214. case 'www.bilinovel.com':
  215. return ReadParams.url_previous;
  216. break;
  217. default:
  218. reg = /上一章|上一篇|上一页|上一话|navigation-prev/;
  219. for(i=0;i<as.length;i++){
  220. text = as[i].outerHTML;
  221. href = (as[i].attributes.href && as[i].attributes.href.value) || (as[i].dataset && as[i].dataset.url);
  222. if (text && reg.test(text.trim()) && href && href != "#" && href.indexOf("javascript:") !== 0){
  223. return href;
  224. }
  225. }
  226. break;
  227. }
  228. }
  229. function parsePageDown(){
  230. var reg, text;
  231. var href = "";
  232. var i = 0;
  233. var as = document.querySelectorAll('a');
  234. switch (location.host){
  235. case 'www.bilinovel.com':
  236. return ReadParams.url_next;
  237. break;
  238. default:
  239. reg = /下一章|下一篇|下一页|下一话|navigation-next/;
  240. for(i=0;i<as.length;i++){
  241. text = as[i].outerHTML;
  242. href = (as[i].attributes.href && as[i].attributes.href.value) || (as[i].dataset && as[i].dataset.url);
  243. if (text && reg.test(text.trim()) && href && href != "#" && href.indexOf("javascript:") !== 0){
  244. return href;
  245. }
  246. }
  247. break;
  248. }
  249. }
  250. function parsePageIndex(){
  251. var as = document.querySelectorAll('a');
  252. var reg = /目录/;
  253. switch (location.host){
  254. case 'www.bilinovel.com':
  255. return ReadParams.url_index;
  256. break;
  257. default:
  258. for(var i=0;i<as.length;i++){
  259. var text = as[i].innerText;
  260. var href = as[i].attributes.href && as[i].attributes.href.value;
  261. if (text && text.length <= 10 && reg.test(text.trim()) && href && href != "#" && href.indexOf("javascript:") !== 0){
  262. return href;
  263. }
  264. }
  265. break;
  266. }
  267. }
  268. var fontsize = parseInt(localStorage["_er_fontsize"] || 0);
  269. var padding = parseInt(localStorage["_er_padding"] || 10);
  270. var autoplay = false;
  271. if (localStorage['_er-autoplay'] === 'true'){
  272. autoplay = true;
  273. }
  274. delete localStorage['_er-autoplay'];
  275. if (top.window !== window) return; // iframe内的网页不展示按钮,也不支持进入阅读模式
  276. if (localStorage['_er-enable'] === 'true'){
  277. localStorage['_er-enable'] = 'false';
  278. checkAndCreateReader(true);
  279. } else if (blackList[location.host] == true){
  280. // 创建阅读模式悬浮按钮
  281. $('body').children[0].insertAdjacentHTML('beforeBegin', '<button id="_er-entryReadMode" style="' +
  282. ' position: fixed;' +
  283. ' right: 50px;' +
  284. ' bottom: 50px;' +
  285. ' background-color: rgba(255,255,255,0.5);' +
  286. ' backdrop-filter: blur(1px);' +
  287. ' border: 0px solid black;' +
  288. ' border-radius: 10px;' +
  289. ' box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);' +
  290. ' padding: 0 5px;' +
  291. ' height: 50px;' +
  292. ' overflow: auto;' +
  293. ' font-size: 14px;' +
  294. ' color: black;' +
  295. ' z-index: 201901272210;">进入阅读模式</button>');
  296. $('#_er-entryReadMode').onclick = checkAndCreateReader;
  297. }
  298. function checkAndCreateReader(notAlert){
  299. // 通过调用通用模板尝试是否能够成功匹配到阅读内容
  300. var content = parseContentAndTitle();
  301. if (content && content.content){
  302. content.pageup = parsePageUp();
  303. content.pagedown = parsePageDown();
  304. content.pageindex = parsePageIndex();
  305. createReader(content);
  306. }else{
  307. if (notAlert !== true){
  308. alert('当前页面解析失败,无法进入阅读模式!');
  309. }
  310. }
  311. }
  312. function setTheme(theme) {
  313. switch(theme) {
  314. case 'black':
  315. $('._er').style.backgroundColor = 'black';
  316. $('._er-title').style.color = 'lightgrey';
  317. $('._er-content').style.color = 'lightgrey';
  318. $('.translator').style.color = 'lightgrey';
  319. document.querySelectorAll('.buttonBottom').forEach(function(element) {
  320. element.style.color = 'lightgrey';
  321. element.style.border = '0.5px solid lightgrey';
  322. });
  323. document.querySelectorAll('.buttonTop').forEach(function(element) {
  324. element.style.color = 'lightgrey';
  325. });
  326. document.querySelectorAll('.exit').forEach(function(element) {
  327. element.style.setProperty('box-shadow', '0px 4px 8px rgba(255, 255, 255, 0.2)');
  328. element.style.setProperty('background-color', 'rgb(59,59,59)');
  329. element.style.setProperty('color', 'white');
  330. });
  331. document.querySelectorAll('.toTop').forEach(function(element) {
  332. element.style.setProperty('box-shadow', '0px 4px 8px rgba(255, 255, 255, 0.2)');
  333. element.style.setProperty('background-color', 'rgb(59,59,59)');
  334. element.style.setProperty('color', 'white');
  335. });
  336. document.querySelectorAll('._er-tts').forEach(function(element) {
  337. element.style.setProperty('box-shadow', '0px 4px 8px rgba(255, 255, 255, 0.2)');
  338. element.style.setProperty('background-color', 'rgb(59,59,59)');
  339. element.style.setProperty('color', 'white');
  340. });
  341. break;
  342. case 'OliveDrab':
  343. $('._er').style.backgroundColor = '#D3E1D0';
  344. $('._er-title').style.color = 'black';
  345. $('._er-content').style.color = 'black';
  346. break;
  347. case 'Khaki':
  348. $('._er').style.backgroundColor = '#F6F2E7';
  349. $('._er-title').style.color = 'black';
  350. $('._er-content').style.color = 'black';
  351. break;
  352. case 'blue':
  353. $('._er').style.backgroundColor = '#D3E5F9';
  354. $('._er-title').style.color = 'black';
  355. $('._er-content').style.color = 'black';
  356. break;
  357. case 'white':
  358. $('._er').style.backgroundColor = 'white';
  359. $('._er-title').style.color = 'black';
  360. $('._er-content').style.color = 'black';
  361. $('.translator').style.color = 'black';
  362. document.querySelectorAll('.buttonBottom').forEach(function(element) {
  363. element.style.border = '0.5px solid black';
  364. element.style.color = 'black';
  365. });
  366. document.querySelectorAll('.buttonTop').forEach(function(element) {
  367. element.style.border = '1px solid black';
  368. element.style.color = 'black';
  369. });
  370. document.querySelectorAll('.exit').forEach(function(element) {
  371. element.style.setProperty('box-shadow', '0px 4px 8px rgba(0, 0, 0, 0.2)');
  372. element.style.setProperty('background-color', 'rgb(239,239,239)');
  373. element.style.setProperty('color', 'black');
  374. });
  375. document.querySelectorAll('.toTop').forEach(function(element) {
  376. element.style.setProperty('box-shadow', '0px 4px 8px rgba(0, 0, 0, 0.2)');
  377. element.style.setProperty('background-color', 'rgb(239,239,239)');
  378. element.style.setProperty('color', 'black');
  379. });
  380. document.querySelectorAll('._er-tts').forEach(function(element) {
  381. element.style.setProperty('box-shadow', '0px 4px 8px rgba(0, 0, 0, 0.2)');
  382. element.style.setProperty('background-color', 'rgb(239,239,239)');
  383. element.style.setProperty('color', 'black');
  384. });
  385. break;
  386. }
  387. localStorage['_er-theme'] = theme;
  388. $('._er').dataset['theme'] = theme;
  389. }
  390. function setSimplemode(simplemode, contentHtml) {//简繁切换
  391. switch(simplemode) {
  392. case 'simple':
  393. contentHtml = traditionalized(contentHtml);
  394. break;
  395. case 'traditional':
  396. contentHtml = simplized(contentHtml);
  397. break;
  398. }
  399. localStorage['_er-simplemode'] = simplemode;
  400. $('._er').dataset['simplemode'] = simplemode;
  401. return contentHtml;
  402. }
  403. // 创建阅读器
  404. function createReader(content){
  405. voices = getVoice();//首次返回空串
  406. document.documentElement.style.overflow = 'hidden';
  407. $('#_er-entryReadMode') && $('#_er-entryReadMode').remove();
  408. addClassAndDom();
  409. if (window.SpeechSynthesisUtterance){
  410. $('#_er-tts').style.display = 'block';
  411. }
  412. if (GM_getValue('ttsbutton')==0){//本地缓存的设置
  413. document.querySelector('._er-tts').style.display = 'none';
  414. }
  415. if (GM_getValue('totopbutton')==0){
  416. document.querySelector('.toTop').style.display = 'none';
  417. }
  418. $("._er-title").style.fontFamily = GM_getValue('fontFamily',);
  419. $(".translator").style.fontFamily = GM_getValue('fontFamily',);
  420. $("._er-content").style.fontFamily = GM_getValue('fontFamily',);
  421. if (hasCSSRule('#TextContent p:last-of-type')||hasCSSRule('#acontent p:last-of-type, .bcontent p:last-of-type')) {//针对哔哩轻小说最后一段转码的情况
  422. addCSSRule('._er-content p:last-of-type', 'font-family: "read" !important;');
  423. }
  424. if (localStorage['_er-theme']) {
  425. setTheme(localStorage['_er-theme']);
  426. }
  427. $('._er-title').innerText = content.title;
  428. var contentArr = content.content.split('\n');
  429. var contentHtml = '';
  430. for(var i=0;i<contentArr.length;i++){
  431. var line = contentArr[i];
  432. if (line){
  433. contentHtml += '<p style="text-indent: 2em; margin-bottom: 1em;">' + line + '</p>';
  434. }
  435. }
  436. $('._er-content').innerHTML = contentHtml;
  437. if (location.host == "masiro.me") {
  438. var translatorInfoElm = document.getElementById('translator-info-elm');
  439. var translator = translatorInfoElm.textContent.trim();
  440. $('.translator').innerHTML = translator;
  441. $('.translator').style.display = 'block';
  442. }
  443. if (localStorage['_er-simplemode']) {
  444. $('._er-content').innerHTML=setSimplemode(localStorage['_er-simplemode'],$('._er-content').innerHTML);
  445. $('._er-title').innerHTML=setSimplemode(localStorage['_er-simplemode'],$('._er-title').innerHTML);
  446. $('.translator').innerHTML=setSimplemode(localStorage['_er-simplemode'],$('.translator').innerHTML);
  447. }
  448. var spanNodes = document.querySelectorAll('._er-content p');
  449. for(i=0;i<spanNodes.length;i++){
  450. spanNodes[i].onclick = function(){
  451. if ($('#_er-tts').innerText == '听书'){
  452. for(var j=0;j<spanNodes.length;j++){
  453. spanNodes[j].classList.remove('_er-none');
  454. spanNodes[j].classList.remove('_er-current');
  455. }
  456. this.classList.add('_er-none');
  457. }
  458. }
  459. }
  460. // 挂接键盘事件,实现键盘上下左右切换阅读功能
  461. $('body').onkeydown = function(e){
  462. e.stopPropagation();
  463. switch(e.keyCode || e.which || e.charCode){
  464. case 38: // up
  465. if (e.ctrlKey) {
  466. $('._er').scrollTop = $('._er').scrollTop - (document.documentElement.clientHeight - 24)
  467. } else {
  468. toPrevReadPos();
  469. updateReadPos();
  470. }
  471. break;
  472. case 40: // down
  473. if (e.ctrlKey) {
  474. $('._er').scrollTop = $('._er').scrollTop + (document.documentElement.clientHeight - 24);
  475. } else {
  476. toNextReadPos();
  477. updateReadPos();
  478. }
  479. break;
  480. case 37: // left
  481. if (e.ctrlKey) {
  482. toPrevPage();
  483. } else {
  484. $('._er').scrollTop = $('._er').scrollTop - (document.documentElement.clientHeight - 24)
  485. }
  486. break;
  487. case 39: // right
  488. if (e.ctrlKey) {
  489. toNextPage()
  490. } else {
  491. $('._er').scrollTop = $('._er').scrollTop + (document.documentElement.clientHeight - 24);
  492. }
  493. break;
  494. default:
  495. return true;
  496. }
  497. return false;
  498. function toPrevPage(){
  499. if (content.pageup){
  500. localStorage['_er-enable'] = 'true';
  501. location.href = content.pageup;
  502. }else{
  503. alert('很抱歉,没有匹配到上一页!');
  504. }
  505. }
  506. function toNextPage(){
  507. if (content.pagedown){
  508. localStorage['_er-enable'] = 'true';
  509. location.href = content.pagedown;
  510. }else{
  511. alert('很抱歉,没有匹配到下一页!');
  512. }
  513. }
  514. };
  515. $('._er-content').onclick = function(e){ // 适用于墨水屏的左右点击无动画翻页
  516. var x = e.pageX;
  517. var width = document.documentElement.clientWidth;
  518. if (x <= width*0.2){ // 前翻一页
  519. $('._er').scrollTop = $('._er').scrollTop - (document.documentElement.clientHeight - 24)
  520. }else if(x >= width*0.8){ // 后翻一页
  521. $('._er').scrollTop = $('._er').scrollTop + (document.documentElement.clientHeight - 24);
  522. }
  523. }
  524. var erpageindex = document.querySelectorAll('#_er-pageindex');
  525. for (i = 0; i < erpageindex.length; i++) {
  526. erpageindex[i].onclick = function() {
  527. if (content.pageindex) {
  528. location.href = content.pageindex;
  529. } else {
  530. alert('很抱歉,没有匹配到目录!');
  531. }
  532. };
  533. }
  534. $('#_er-switch-theme').onclick = function(){
  535. var current = $('._er').dataset['theme'] || 'white';
  536. var themeList = ['white', 'Khaki', 'blue', 'OliveDrab', 'black'];
  537. var index = themeList.indexOf(current);
  538. if (index === -1) index = 0;
  539. index++;
  540. if (index >= themeList.length) {
  541. index = 0;
  542. }
  543. setTheme(themeList[index]);
  544. }
  545. var pressTimer;//定时器
  546. var touchpressTimer;//触摸定时器
  547. var isLongPress = false; // 长按标记
  548. $('#_er-simplemode').addEventListener('touchstart', function() {//触摸屏
  549. touchpressTimer = setTimeout(function() {
  550. isLongPress = true;
  551. localStorage['_er-simplemode'] = '';
  552. $('._er-content').innerHTML = contentHtml;
  553. $('._er-title').innerText = content.title;
  554. if (location.host == "masiro.me") {
  555. $('.translator').innerHTML = translator;
  556. }
  557. }, 500);
  558. });
  559. $('#_er-simplemode').addEventListener('touchend', function() {
  560. clearTimeout(touchpressTimer);
  561. });
  562. $('#_er-simplemode').addEventListener('mousedown', function() {//PC
  563. pressTimer = setTimeout(function() {
  564. isLongPress = true;
  565. localStorage['_er-simplemode'] = '';
  566. $('._er-content').innerHTML = contentHtml;
  567. $('._er-title').innerText = content.title;
  568. if (location.host == "masiro.me") {
  569. $('.translator').innerHTML = translator;
  570. }
  571. }, 500);
  572. });
  573. $('#_er-simplemode').addEventListener('mouseup', function() {
  574. clearTimeout(pressTimer);
  575. if (!isLongPress) {
  576. var current = $('._er').dataset['simplemode'] || 'traditional';
  577. var simplemodeList = ['simple', 'traditional'];
  578. var index = simplemodeList.indexOf(current);
  579. if (index === -1) index = 0;
  580. index++;
  581. if (index >= simplemodeList.length) {
  582. index = 0;
  583. }
  584. $('._er-content').innerHTML=setSimplemode(simplemodeList[index],$('._er-content').innerHTML);
  585. $('.translator').innerHTML=setSimplemode(simplemodeList[index],$('.translator').innerHTML);
  586. $('._er-title').innerHTML=setSimplemode(simplemodeList[index],$('._er-title').innerHTML);
  587. } else {
  588. $('._er').dataset['simplemode'] = '';
  589. current = $('._er').dataset['simplemode'] || 'traditional';
  590. simplemodeList = ['simple', 'traditional'];
  591. index = simplemodeList.indexOf(current);;
  592. }
  593. isLongPress = false;
  594. var spanNodes = document.querySelectorAll('._er-content p');
  595. for(i=0;i<spanNodes.length;i++){//重新为每一段添加点击事件
  596. spanNodes[i].onclick = function(){
  597. if ($('#_er-tts').innerText == '听书'){
  598. for(var j=0;j<spanNodes.length;j++){
  599. spanNodes[j].classList.remove('_er-none');
  600. spanNodes[j].classList.remove('_er-current');
  601. }
  602. this.classList.add('_er-none');
  603. }
  604. }
  605. }
  606. });
  607. var erpageup = document.querySelectorAll('#_er-pageup');
  608. for (i = 0; i < erpageup.length; i++) {
  609. erpageup[i].onclick = function() {
  610. if (content.pageup) {
  611. localStorage['_er-enable'] = 'true';
  612. location.href = content.pageup;
  613. } else {
  614. alert('很抱歉,没有匹配到上一页!');
  615. }
  616. };
  617. }
  618. var erpagedown = document.querySelectorAll('#_er-pagedown');
  619. for (i = 0; i < erpagedown.length; i++) {
  620. erpagedown[i].onclick = function() {
  621. if (content.pagedown) {
  622. localStorage['_er-enable'] = 'true';
  623. location.href = content.pagedown;
  624. } else {
  625. alert('很抱歉,没有匹配到下一页!');
  626. }
  627. };
  628. }
  629. $('#_er-pagedown').dataset['nexturl'] = content.pagedown;
  630. setFontSize();
  631. setPadding();
  632. // 按钮事件处理
  633. $('#_er-close').onclick = removeDom;
  634. $('#_er-font-plus').onclick = function(){
  635. fontsize += 2;
  636. setFontSize();
  637. };
  638. $('#_er-font-minus').onclick = function(){
  639. fontsize -= 2;
  640. setFontSize();
  641. };
  642. $('#_er-border').onclick= function() {
  643. padding = padding == 10 ? 5 : 10;
  644. setPadding();
  645. }
  646. $('#_er-toTop').onclick= function() {
  647. document.querySelector('._er').scrollTop = 0;
  648. }
  649. $('#_er-tts').onclick = function(){
  650. if (this.dataset['pause'] === 'true'){
  651. // 开始播放
  652. this.innerText = '停止';
  653. this.dataset['pause'] = 'false';
  654. playNextText();
  655. }else{
  656. this.innerText = '听书';
  657. this.dataset['pause'] = 'true';
  658. }
  659. };
  660. if (autoplay){
  661. autoplay = false;
  662. $('#_er-tts').innerText = '停止';
  663. $('#_er-tts').dataset['pause'] = 'false';
  664. playNextText();
  665. }else{
  666. $('#_er-tts').dataset['pause'] = 'true';
  667. }
  668. }
  669. // 听书功能
  670. function playNextText(){
  671. updateReadPos();
  672. var current = $('._er-current');
  673. var ernone = $('._er-none');
  674. var playText = '';
  675. if (current){
  676. playText = current.innerText;
  677. }else if(ernone) {
  678. playText = ernone.innerText;
  679. ernone.classList.add('_er-current');
  680. ernone.classList.remove('_er-none');
  681. }else{
  682. playText = $('._er-title').innerText;
  683. }
  684. if (playText){
  685. var utterThis = new SpeechSynthesisUtterance();
  686. utterThis.text = playText;
  687. if (GM_getValue('voice') != undefined) {
  688. var selectedVoiceName = GM_getValue('voice');
  689. voices = getVoice();
  690. var selectedVoice = voices.find(function(voice) {
  691. return voice.name === selectedVoiceName;
  692. });
  693. if (selectedVoice) {
  694. utterThis.voice = selectedVoice;
  695. }
  696. }
  697. utterThis.rate = GM_getValue('rateInput',1);
  698. utterThis.onerror = function(){
  699. $('#_er-tts').dataset['pause'] = 'true';
  700. alert("TTS语音转换文字出现异常,听书已停止运行!");
  701. };
  702. utterThis.onend = function(){
  703. toNextReadPos();
  704. if (!$('._er-current')){
  705. var nextUrl = $('#_er-pagedown').dataset['nexturl'];
  706. console.log(nextUrl);
  707. if (nextUrl){
  708. localStorage['_er-autoplay'] = 'true';
  709. localStorage['_er-enable'] = 'true';
  710. location.href = nextUrl;
  711. }
  712. return;
  713. }
  714. if ($('#_er-tts').dataset['pause'] === 'false'){
  715. playNextText();
  716. }
  717. };
  718. speechSynthesis.speak(utterThis);
  719. }else{
  720. toNextReadPos();
  721. playNextText();
  722. }
  723. }
  724. function toNextReadPos(){
  725. var current = $('._er-current');
  726. var nextSpan = null;
  727. if (current){
  728. nextSpan = current.nextElementSibling;
  729. while(nextSpan && nextSpan.nodeName !== 'P'){
  730. nextSpan = nextSpan.nextElementSibling;
  731. }
  732. }else{
  733. nextSpan = $('._er-content p');
  734. }
  735. if (current) current.classList.remove('_er-current');
  736. if (nextSpan) nextSpan.classList.add('_er-current');
  737. }
  738. function toPrevReadPos(){
  739. var current = $('._er-current');
  740. var prevSpan = null;
  741. if (current){
  742. prevSpan = current.previousElementSibling;
  743. while(prevSpan && prevSpan.nodeName !== 'P'){
  744. prevSpan = prevSpan.previousElementSibling;
  745. }
  746. }
  747. if (current) current.classList.remove('_er-current');
  748. if (prevSpan) prevSpan.classList.add('_er-current');
  749. }
  750. function updateReadPos(){
  751. if ($('._er-current')) {
  752. $('._er').scrollTop = $('._er-current').offsetTop - (document.documentElement.clientHeight / 2);
  753. }
  754. }
  755. function getVoice() {//获取可用语音
  756. if (window.SpeechSynthesisUtterance){
  757. voices = speechSynthesis.getVoices();
  758. }
  759. var chineseVoices = voices.filter(function(voice) {
  760. return voice.lang.startsWith('zh');
  761. });
  762. return chineseVoices;
  763. }
  764. function setFontSize(){
  765. localStorage["_er_fontsize"] = fontsize;
  766. $('._er-title').style.fontSize = (20+fontsize) + 'px';
  767. $('._er-title').style.lineHeight = ((20+fontsize)*1.5) + 'px';
  768. $('._er-content').style.fontSize = (14+fontsize) + 'px';
  769. $('._er-content').style.lineHeight = ((14+fontsize)*1.5) + 'px';
  770. $('.translator').style.fontSize = (10+fontsize) + 'px';
  771. $('.translator').style.lineHeight = ((10+fontsize)*1.5) + 'px';
  772. }
  773. function setPadding() {
  774. localStorage["_er_padding"] = padding;
  775. $('._er-content').style.padding = '10px ' + padding + '%';
  776. }
  777. function hasCSSRule(selector) {
  778. // 获取所有的样式表
  779. const styleSheets = document.styleSheets;
  780. for (let i = 0; i < styleSheets.length; i++) {
  781. const rules = styleSheets[i].cssRules || styleSheets[i].rules; // 兼容不同浏览器
  782. if (rules) {
  783. for (let j = 0; j < rules.length; j++) {
  784. if (rules[j].selectorText === selector) {
  785. return true;
  786. }
  787. }
  788. }
  789. }
  790. return false;
  791. }
  792. function addCSSRule(selector, styles) {
  793. const styleSheet = document.styleSheets[0];
  794. const rule = `${selector} { ${styles} }`;
  795. styleSheet.insertRule(rule, styleSheet.cssRules.length);
  796. }
  797. var oldOverflow = '';
  798. var oldOnKeyDown = $('body').onkeydown;
  799. function removeDom(){
  800. var erScrollTop = document.querySelector('._er').scrollTop;
  801. var erScrollHeight = document.querySelector('._er').scrollHeight;
  802. var erClientHeight = document.documentElement.clientHeight;
  803. var scrollPercentage = (erScrollTop / (erScrollHeight - erClientHeight)) * 100;
  804. $('._er').remove();
  805. document.documentElement.style.overflow = 'auto';
  806. $('body').style.overflow = oldOverflow;
  807. $('body').onkeydown = oldOnKeyDown;
  808. $('body').children[0].insertAdjacentHTML('beforeBegin', '<button id="_er-entryReadMode" style="' +
  809. ' position: fixed;' +
  810. ' right: 50px;' +
  811. ' bottom: 50px;' +
  812. ' background-color: rgba(255,255,255,0.5);' +
  813. ' backdrop-filter: blur(1px);' +
  814. ' border: 0px solid black;' +
  815. ' border-radius: 10px;' +
  816. ' box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);' +
  817. ' padding: 0 5px;' +
  818. ' height: 50px;' +
  819. ' overflow: auto;' +
  820. ' font-size: 14px;' +
  821. ' color: black;' +
  822. ' z-index: 201901272210;">进入阅读模式</button>');
  823. $('#_er-entryReadMode').onclick = checkAndCreateReader;
  824. setTimeout(function() {
  825. var restoredScrollTop = ((erScrollHeight - erClientHeight) * (scrollPercentage / 100));
  826. window.scrollTo(0, restoredScrollTop);
  827. }, 0);
  828. }
  829. function addClassAndDom(){
  830. var originalScrollTop = window.pageYOffset;
  831. var originalScrollHeight = document.documentElement.scrollHeight;
  832. var originalClientHeight = document.documentElement.clientHeight;
  833. var scrollPercentage = (originalScrollTop / (originalScrollHeight - originalClientHeight)) * 100;
  834. oldOverflow = $('body').style.overflow;
  835. $('body').style.overflow = 'hidden';
  836. $('body').children[0].insertAdjacentHTML('beforeBegin',
  837. '<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no"><div class="_er">' +
  838. ' <button type="button" id="_er-tts" class="_er-tts">听书</button>' +
  839. ' <div class="_er-tools" style="margin-top:0;">' +
  840. ' <button type="button" id="_er-pageup" class="buttonBottom" style="width:50%; margin: 0;">上一页</button>' +
  841. ' <button type="button" id="_er-pageindex" class="buttonBottom" style="padding: 5px 40px; margin: 0;">目录</button>' +
  842. ' <button type="button" id="_er-pagedown" class="buttonBottom" style="width:50%; margin: 0;">下一页</button>' +
  843. ' </div>' +
  844. ' <div class="_er-tools">' +
  845. ' <button type="button" id="_er-switch-theme" class="buttonTop">切换主题</button>' +
  846. ' <button type="button" id="_er-font-plus" class="buttonTop">字号+</button>' +
  847. ' <button type="button" id="_er-font-minus" class="buttonTop">字号-</button>' +
  848. ' <button type="button" id="_er-border" class="buttonTop">边距</button>' +
  849. ' <button type="button" id="_er-simplemode" class="buttonTop">简 / 繁</button>' +
  850. ' <button type="button" id="_er-toTop" class="toTop">' +
  851. ' <span class="first-line">回到</span>' +
  852. ' <span class="second-line">顶部</span>' +
  853. ' </button>' +
  854. ' <button type="button" id="_er-close" class="exit">退出</button>' +
  855. ' </div>' +
  856. ' <div class="_er-title"></div>' +
  857. ' <div class="translator"></div>' +
  858. ' <div class="_er-content">' +
  859. ' </div>' +
  860. ' <div class="_er-tools">' +
  861. ' <button type="button" id="_er-pageup" class="buttonBottom" style="width: 50%;">上一页</button>' +
  862. ' <button type="button" id="_er-pageindex" class="buttonBottom" style="padding: 5px 40px;">目录</button>' +
  863. ' <button type="button" id="_er-pagedown" class="buttonBottom" style="width: 50%;">下一页</button>' +
  864. ' </div>' +
  865. '</div>');
  866. if (!document.querySelector('#_er-styles')) {
  867. $('body').children[0].insertAdjacentHTML('beforeBegin',
  868. '<style id="_er-styles">' +
  869. '* {' +
  870. '-webkit-user-select: none; /* Safari */' +
  871. '-moz-user-select: none; /* Firefox */' +
  872. '-ms-user-select: none; /* IE 10+ */' +
  873. 'user-select: none; /* 标准语法 */' +
  874. '}' +
  875. '._er{' +
  876. ' position: fixed;' +
  877. ' left: 0;' +
  878. ' right: 0;' +
  879. ' top: 0;' +
  880. ' bottom: 0;' +
  881. ' overflow-y: auto;' +
  882. ' overflow-x: hidden;' +
  883. ' background-color: white;' +
  884. ' z-index: 201901272211;' +
  885. '}' +
  886. '._er-title{' +
  887. ' text-align: center;' +
  888. ' font-size: 20px;' +
  889. ' line-height: 30px;' +
  890. ' font-weight: 900;' +
  891. ' padding: 10px 10%;' +
  892. ' color: black;' +
  893. '}' +
  894. '.translator{' +
  895. ' text-align: center;' +
  896. ' font-size: 10px;' +
  897. ' line-height: 15px;' +
  898. ' padding: 0 10% 10px;' +
  899. ' color: black;' +
  900. ' display: none;' +
  901. '}' +
  902. '._er-content{' +
  903. ' padding: 10px 10%;' +
  904. ' font-size: 14px;' +
  905. ' line-height: 21px;' +
  906. ' color: black;' +
  907. ' word-break:break-all' +
  908. '}' +
  909. '._er-tools{' +
  910. ' margin-top: 10px;' +
  911. ' margin-bottom: 10px;' +
  912. ' text-align: center;' +
  913. ' display: flex;' +
  914. ' justify-content: center;' +
  915. '}' +
  916. '.buttonTop{' +
  917. ' cursor: pointer;' +
  918. ' color: black;' +
  919. ' background-color: rgba(255,255,255,0.5);' +
  920. ' border: 1px solid black;' +
  921. ' padding: 5px 8px;' +
  922. ' margin: 8px 5px 0;' +
  923. ' border-radius: 10px;' +
  924. ' white-space: nowrap;' +
  925. '}' +
  926. '.buttonTop:hover{' +
  927. ' background-color: rgba(255,255,255,0.9);' +
  928. '}' +
  929. '.buttonTop:active{' +
  930. ' background-color: rgba(255,255,255,0.7);' +
  931. '}' +
  932. '.buttonBottom{' +
  933. ' cursor: pointer;' +
  934. ' color: black;' +
  935. ' background-color: rgba(255,255,255,0);' +
  936. ' border: 0.5px solid black;' +
  937. ' padding: 5px 50px;' +
  938. ' margin: 20px 0 80px;' +
  939. ' font-size: 20px;' +
  940. ' white-space: nowrap;' +
  941. '}' +
  942. '.buttonBottom:hover{' +
  943. ' background-color: rgba(255,255,255,0.8);' +
  944. '}' +
  945. '.buttonBottom:active{' +
  946. ' background-color: rgba(255,255,255,0.5);' +
  947. '}' +
  948. '.toTop{' +
  949. ' width: 50px;' +
  950. ' height: 50px;' +
  951. ' position: fixed;' +
  952. ' right: 15px;' +
  953. ' bottom: 80px;' +
  954. ' z-index: 201901272212;' +
  955. ' color: black;' +
  956. ' border: 0px solid black;' +
  957. ' box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);' +
  958. ' opacity: 0.8;' +
  959. ' cursor: pointer;' +
  960. ' border-radius: 25px;' +
  961. ' font-size: 14px;' +
  962. ' padding: 0;' +
  963. ' display: flex;' +
  964. ' flex-direction: column;' +
  965. ' align-items: center;' +
  966. ' justify-content: center;' +
  967. '}' +
  968. '.first-line,' +
  969. '.second-line {' +
  970. ' display: inline-block;' +
  971. ' white-space: nowrap;' +
  972. '}' +
  973. '.exit{' +
  974. ' width: 50px;' +
  975. ' height: 50px;' +
  976. ' position: fixed;' +
  977. ' right: 15px;' +
  978. ' bottom: 15px;' +
  979. ' z-index: 201901272212;' +
  980. ' color: black;' +
  981. ' border: 0px solid black;' +
  982. ' box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);' +
  983. ' opacity: 0.8;' +
  984. ' cursor: pointer;' +
  985. ' border-radius: 25px;' +
  986. ' font-size: 14px;' +
  987. ' padding: 0;' +
  988. ' white-space: nowrap;' +
  989. '}' +
  990. '._er-tts {' +
  991. ' width: 50px;' +
  992. ' height: 50px;' +
  993. ' position: fixed;' +
  994. ' left: 15px;' +
  995. ' bottom: 15px;' +
  996. ' z-index: 201901272212;' +
  997. ' color: black;' +
  998. ' border: 0px solid black;' +
  999. ' box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);' +
  1000. ' opacity: 0.8;' +
  1001. ' cursor: pointer;' +
  1002. ' border-radius: 25px;' +
  1003. ' font-size: 14px;' +
  1004. ' padding: 0;' +
  1005. ' white-space: nowrap;' +
  1006. ' display: none;' +
  1007. '}' +
  1008. '._er-current{' +
  1009. ' background-color: yellow;' +
  1010. ' color: black;' +
  1011. '}' +
  1012. '._er-none{' +
  1013. '}' +
  1014. '</style>');
  1015. }
  1016. setTimeout(function() {
  1017. var restoredScrollTop = ((originalScrollHeight - originalClientHeight) * (scrollPercentage / 100));
  1018. document.querySelector('._er').scrollTop = restoredScrollTop;
  1019. }, 0);
  1020. }
  1021. function addDialog(){
  1022. if (!document.querySelector('#myDialog')) {
  1023. $('body').children[0].insertAdjacentHTML('beforeBegin',
  1024. '<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no"><dialog id="myDialog">' +
  1025. ' <h2>设置</h2>' +
  1026. ' <div class="checkbox-container">' +
  1027. ' <div class="congfigcheckbox">' +
  1028. ' <label>' +
  1029. ' <input type="checkbox" name="scrollToTop" value="1"> 回到顶部按钮' +
  1030. ' </label>' +
  1031. ' </div>' +
  1032. ' <div class="congfigcheckbox">' +
  1033. ' <label>' +
  1034. ' <input type="checkbox" name="listen" value="1"> 听书按钮' +
  1035. ' </label>' +
  1036. ' </div>' +
  1037. ' <div class="font-selector">' +
  1038. ' <label for="fontSelect">选择字体样式:</label>' +
  1039. ' <select id="fontSelect">' +
  1040. ' </select>' +
  1041. ' </div>' +
  1042. ' <div class="voice-selector">' +
  1043. ' <label for="voiceSelect">选择听书语音:</label>' +
  1044. ' <select id="voiceSelect">' +
  1045. ' </select>' +
  1046. ' </div>' +
  1047. ' <div class="rate-input">' +
  1048. ' <label for="rateInput">设置朗读语速:</label>' +
  1049. ' <input type="number" id="rateInput" min="0.1" max="10" step="0.05">' +
  1050. ' </div>' +
  1051. ' </div>' +
  1052. ' <div class="configbutton">' +
  1053. ' <button id="configreset">重置</button>' +
  1054. ' <button id="closeDialog" style="margin-left: 80px;">确定</button>' +
  1055. ' </div>' +
  1056. '</dialog>');
  1057. }
  1058. if (!document.querySelector('#dialog-styles')) {
  1059. $('body').children[0].insertAdjacentHTML('beforeBegin',
  1060. '<style id="dialog-styles">' +
  1061. '#myDialog {' +
  1062. ' padding: 20px;' +
  1063. ' margin: 0;' +
  1064. ' background-color: #f2f2f2;' +
  1065. ' border: 1px solid #ccc;' +
  1066. ' border-radius: 10px;' +
  1067. ' box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);' +
  1068. ' font-family: Arial, sans-serif;' +
  1069. ' display: flex;' +
  1070. ' flex-direction: column;' +
  1071. ' align-items: center;' +
  1072. ' position: fixed;' +
  1073. ' top: 50%;' +
  1074. ' left: 50%;' +
  1075. ' transform: translate(-50%, -50%);' +
  1076. '}' +
  1077. '#myDialog::backdrop {' +
  1078. ' background: rgba(30,30,30,0.2);' +
  1079. ' backdrop-filter: blur(3px);' +
  1080. '}' +
  1081. '#myDialog h2 {' +
  1082. ' margin-top: 0;' +
  1083. ' font-size: 24px;' +
  1084. ' font-weight: bold;' +
  1085. ' margin-bottom: 12px;' +
  1086. ' line-height: 1.5;' +
  1087. '}' +
  1088. '.checkbox-container {' +
  1089. ' display: flex;' +
  1090. ' flex-direction: column;' +
  1091. ' align-items: flex-start;' +
  1092. '}' +
  1093. '.congfigcheckbox {' +
  1094. ' margin-bottom: 10px;' +
  1095. '}' +
  1096. '.font-selector,.voice-selector,.rate-input {' +
  1097. ' margin-bottom: 20px;' +
  1098. ' display: block;' +
  1099. '}' +
  1100. '.font-selector label,.voice-selector label,.rate-input label {' +
  1101. ' font-size: 16px;' +
  1102. ' font-weight: bold;' +
  1103. ' margin: 0 10px 0 0;' +
  1104. ' color: #333;' +
  1105. '}' +
  1106. '.font-selector select,.voice-selector select,.rate-input input {' +
  1107. ' font-size: 16px;' +
  1108. ' padding: 5px;' +
  1109. ' border: 1px solid #ccc;' +
  1110. ' border-radius: 4px;' +
  1111. ' background-color: #fff;' +
  1112. ' cursor: pointer;' +
  1113. ' transition: border-color 0.3s ease;' +
  1114. ' color: black;' +
  1115. ' max-width: 150px;' +
  1116. '}' +
  1117. '.font-selector select,.voice-selector select,.rate-input input:hover {' +
  1118. ' border-color: #007BFF;' +
  1119. '}' +
  1120. '.font-selector select,.voice-selector select,.rate-input input:focus {' +
  1121. ' outline: none;' +
  1122. ' border-color: #007BFF;' +
  1123. ' box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);' +
  1124. '}' +
  1125. '.congfigcheckbox label {' +
  1126. ' display: block;' +
  1127. ' margin: 0 0 10px;' +
  1128. ' font-size: 16px;' +
  1129. ' padding: 0 ;' +
  1130. ' font-weight: normal;' +
  1131. '}' +
  1132. '.congfigcheckbox input[type="checkbox"] {' +
  1133. ' border: 1px solid #B4B4B4;' +
  1134. ' padding: 1px;' +
  1135. ' margin: 3px;' +
  1136. ' width: 16px;' +
  1137. ' height: 16px;' +
  1138. ' background: none;' +
  1139. ' cursor: pointer;' +
  1140. ' visibility: visible;' +
  1141. ' position: static;' +
  1142. ' vertical-align: middle;' +
  1143. '}' +
  1144. '.configbutton {' +
  1145. ' display: flex;' +
  1146. ' justify-content: space-between;' +
  1147. '}' +
  1148. '#myDialog button {' +
  1149. ' padding: 8px 16px;' +
  1150. ' background-color: #4CAF50;' +
  1151. ' color: #fff;' +
  1152. ' border: none;' +
  1153. ' border-radius: 4px;' +
  1154. ' cursor: pointer;' +
  1155. ' font-size: 14px;' +
  1156. '}' +
  1157. '#myDialog button:hover {' +
  1158. ' background-color: #45a049;' +
  1159. '}' +
  1160. '</style>');
  1161. }
  1162. }
  1163.  
  1164. function ftPYStr(){
  1165. return '錒皚藹礙愛噯嬡璦曖靄諳銨鵪骯襖奧媼驁鰲壩罷鈀擺敗唄頒辦絆鈑幫綁鎊謗剝飽寶報鮑鴇齙輩貝鋇狽備憊鵯賁錛繃筆畢斃幣閉蓽嗶潷鉍篳蹕邊編貶變辯辮芐緶籩標驃颮飆鏢鑣鰾鱉別癟瀕濱賓擯儐繽檳殯臏鑌髕鬢餅稟撥缽鉑駁餑鈸鵓補鈽財參蠶殘慚慘燦驂黲蒼艙倉滄廁側冊測惻層詫鍤儕釵攙摻蟬饞讒纏鏟產闡顫囅諂讖蕆懺嬋驏覘禪鐔場嘗長償腸廠暢倀萇悵閶鯧鈔車徹硨塵陳襯傖諶櫬磣齔撐稱懲誠騁棖檉鋮鐺癡遲馳恥齒熾飭鴟沖衝蟲寵銃疇躊籌綢儔幬讎櫥廚鋤雛礎儲觸處芻絀躕傳釧瘡闖創愴錘綞純鶉綽輟齪辭詞賜鶿聰蔥囪從叢蓯驄樅湊輳躥竄攛錯銼鹺達噠韃帶貸駘紿擔單鄲撣膽憚誕彈殫賧癉簞當擋黨蕩檔讜碭襠搗島禱導盜燾燈鄧鐙敵滌遞締糴詆諦綈覿鏑顛點墊電巔鈿癲釣調銚鯛諜疊鰈釘頂錠訂鋌丟銩東動棟凍崠鶇竇犢獨讀賭鍍瀆櫝牘篤黷鍛斷緞籪兌隊對懟鐓噸頓鈍燉躉奪墮鐸鵝額訛惡餓諤堊閼軛鋨鍔鶚顎顓鱷誒兒爾餌貳邇鉺鴯鮞發罰閥琺礬釩煩販飯訪紡鈁魴飛誹廢費緋鐨鯡紛墳奮憤糞僨豐楓鋒風瘋馮縫諷鳳灃膚輻撫輔賦復負訃婦縛鳧駙紱紼賻麩鮒鰒釓該鈣蓋賅桿趕稈贛尷搟紺岡剛鋼綱崗戇鎬睪誥縞鋯擱鴿閣鉻個紇鎘潁給亙賡綆鯁龔宮鞏貢鉤溝茍構購夠詬緱覯蠱顧詁轂鈷錮鴣鵠鶻剮掛鴰摑關觀館慣貫詿摜鸛鰥廣獷規歸龜閨軌詭貴劊匭劌媯檜鮭鱖輥滾袞緄鯀鍋國過堝咼幗槨蟈鉿駭韓漢闞絎頡號灝顥閡鶴賀訶闔蠣橫轟鴻紅黌訌葒閎鱟壺護滬戶滸鶘嘩華畫劃話驊樺鏵懷壞歡環還緩換喚瘓煥渙奐繯鍰鯇黃謊鰉揮輝毀賄穢會燴匯諱誨繪詼薈噦澮繢琿暉葷渾諢餛閽獲貨禍鈥鑊擊機積饑跡譏雞績緝極輯級擠幾薊劑濟計記際繼紀訐詰薺嘰嚌驥璣覬齏磯羈蠆躋霽鱭鯽夾莢頰賈鉀價駕郟浹鋏鎵蟯殲監堅箋間艱緘繭檢堿鹼揀撿簡儉減薦檻鑒踐賤見鍵艦劍餞漸濺澗諫縑戔戩瞼鶼筧鰹韉將漿蔣槳獎講醬絳韁膠澆驕嬌攪鉸矯僥腳餃繳絞轎較撟嶠鷦鮫階節潔結誡屆癤頜鮚緊錦僅謹進晉燼盡勁荊莖巹藎饉縉贐覲鯨驚經頸靜鏡徑痙競凈剄涇逕弳脛靚糾廄舊鬮鳩鷲駒舉據鋸懼劇詎屨櫸颶鉅鋦窶齟鵑絹錈鐫雋覺決絕譎玨鈞軍駿皸開凱剴塏愾愷鎧鍇龕閌鈧銬顆殼課騍緙軻鈳錁頷墾懇齦鏗摳庫褲嚳塊儈鄶噲膾寬獪髖礦曠況誆誑鄺壙纊貺虧巋窺饋潰匱蕢憒聵簣閫錕鯤擴闊蠐蠟臘萊來賴崍徠淶瀨賚睞錸癩籟藍欄攔籃闌蘭瀾讕攬覽懶纜爛濫嵐欖斕鑭襤瑯閬鋃撈勞澇嘮嶗銠鐒癆樂鰳鐳壘類淚誄縲籬貍離鯉禮麗厲勵礫歷瀝隸儷酈壢藶蒞蘺嚦邐驪縭櫪櫟轢礪鋰鸝癘糲躒靂鱺鱧倆聯蓮連鐮憐漣簾斂臉鏈戀煉練蘞奩瀲璉殮褳襝鰱糧涼兩輛諒魎療遼鐐繚釕鷯獵臨鄰鱗凜賃藺廩檁轔躪齡鈴靈嶺領綾欞蟶鯪餾劉瀏騮綹鎦鷚龍聾嚨籠壟攏隴蘢瀧瓏櫳朧礱樓婁摟簍僂蔞嘍嶁鏤瘺耬螻髏蘆盧顱廬爐擄鹵虜魯賂祿錄陸壚擼嚕閭瀘淥櫨櫓轤輅轆氌臚鸕鷺艫鱸巒攣孿灤亂臠孌欒鸞鑾掄輪倫侖淪綸論圇蘿羅邏鑼籮騾駱絡犖玀濼欏腡鏍驢呂鋁侶屢縷慮濾綠櫚褸鋝嘸媽瑪碼螞馬罵嗎嘜嬤榪買麥賣邁脈勱瞞饅蠻滿謾縵鏝顙鰻貓錨鉚貿麼沒鎂門悶們捫燜懣鍆錳夢瞇謎彌覓冪羋謐獼禰綿緬澠靦黽廟緲繆滅憫閩閔緡鳴銘謬謨驀饃歿鏌謀畝鉬吶鈉納難撓腦惱鬧鐃訥餒內擬膩鈮鯢攆輦鯰釀鳥蔦裊聶嚙鑷鎳隉蘗囁顢躡檸獰寧擰濘苧嚀聹鈕紐膿濃農儂噥駑釹諾儺瘧歐鷗毆嘔漚謳慪甌盤蹣龐拋皰賠轡噴鵬紕羆鈹騙諞駢飄縹頻貧嬪蘋憑評潑頗釙撲鋪樸譜鏷鐠棲臍齊騎豈啟氣棄訖蘄騏綺榿磧頎頏鰭牽釬鉛遷簽謙錢鉗潛淺譴塹僉蕁慳騫繾槧鈐槍嗆墻薔強搶嬙檣戧熗錆鏘鏹羥蹌鍬橋喬僑翹竅誚譙蕎繰磽蹺竊愜鍥篋欽親寢鋟輕氫傾頃請慶撳鯖瓊窮煢蛺巰賕蟣鰍趨區軀驅齲詘嶇闃覷鴝顴權勸詮綣輇銓卻鵲確闋闕愨讓饒擾繞蕘嬈橈熱韌認紉飪軔榮絨嶸蠑縟銣顰軟銳蜆閏潤灑薩颯鰓賽傘毿糝喪騷掃繅澀嗇銫穡殺剎紗鎩鯊篩曬釃刪閃陜贍繕訕姍騸釤鱔墑傷賞坰殤觴燒紹賒攝懾設厙灄畬紳審嬸腎滲詵諗瀋聲繩勝師獅濕詩時蝕實識駛勢適釋飾視試謚塒蒔弒軾貰鈰鰣壽獸綬樞輸書贖屬術樹豎數攄紓帥閂雙誰稅順說碩爍鑠絲飼廝駟緦鍶鷥聳慫頌訟誦擻藪餿颼鎪蘇訴肅謖穌雖隨綏歲誶孫損筍蓀猻縮瑣鎖嗩脧獺撻闥鉈鰨臺態鈦鮐攤貪癱灘壇譚談嘆曇鉭錟頇湯燙儻餳鐋鏜濤絳討韜鋱騰謄銻題體屜緹鵜闐條糶齠鰷貼鐵廳聽烴銅統慟頭鈄禿圖釷團摶頹蛻飩脫鴕馱駝橢籜鼉襪媧膃彎灣頑萬紈綰網輞韋違圍為濰維葦偉偽緯謂衛諉幃闈溈潿瑋韙煒鮪溫聞紋穩問閿甕撾蝸渦窩臥萵齷嗚鎢烏誣無蕪吳塢霧務誤鄔廡憮嫵騖鵡鶩錫犧襲習銑戲細餼鬩璽覡蝦轄峽俠狹廈嚇硤鮮纖賢銜閑顯險現獻縣餡羨憲線莧薟蘚峴獫嫻鷴癇蠔秈躚廂鑲鄉詳響項薌餉驤緗饗蕭囂銷曉嘯嘵瀟驍綃梟簫協挾攜脅諧寫瀉謝褻擷紲纈鋅釁興陘滎兇洶銹繡饈鵂虛噓須許敘緒續詡頊軒懸選癬絢諼鉉鏇學謔澩鱈勛詢尋馴訓訊遜塤潯鱘壓鴉鴨啞亞訝埡婭椏氬閹煙鹽嚴巖顏閻艷厭硯彥諺驗厴贗儼兗讞懨閆釅魘饜鼴鴦楊揚瘍陽癢養樣煬瑤搖堯遙窯謠藥軺鷂鰩爺頁業葉靨謁鄴曄燁醫銥頤遺儀蟻藝億憶義詣議誼譯異繹詒囈嶧飴懌驛縊軼貽釔鎰鐿瘞艤蔭陰銀飲隱銦癮櫻嬰鷹應纓瑩螢營熒蠅贏穎塋鶯縈鎣攖嚶瀅瀠瓔鸚癭頦罌喲擁傭癰踴詠鏞優憂郵鈾猶誘蕕銪魷輿魚漁娛與嶼語獄譽預馭傴俁諛諭蕷崳飫閾嫗紆覦歟鈺鵒鷸齬鴛淵轅園員圓緣遠櫞鳶黿約躍鑰粵悅閱鉞鄖勻隕運蘊醞暈韻鄆蕓惲慍紜韞殞氳雜災載攢暫贊瓚趲鏨贓臟駔鑿棗責擇則澤賾嘖幘簀賊譖贈綜繒軋鍘閘柵詐齋債氈盞斬輾嶄棧戰綻譫張漲帳賬脹趙詔釗蟄轍鍺這謫輒鷓貞針偵診鎮陣湞縝楨軫賑禎鴆掙睜猙爭幀癥鄭證諍崢鉦錚箏織職執紙摯擲幟質滯騭櫛梔軹輊贄鷙螄縶躓躑觶鐘終種腫眾鍾謅軸皺晝驟紂縐豬諸誅燭矚囑貯鑄駐佇櫧銖專磚轉賺囀饌顳樁莊裝妝壯狀錐贅墜綴騅縋諄準著濁諑鐲茲資漬諮緇輜貲眥錙齜鯔蹤總縱傯鄒諏騶鯫詛組鏃鉆纘躦鱒翺並蔔沈醜澱鬥範幹臯矽櫃後夥稭傑訣誇裏淩麽黴撚淒扡聖屍擡塗窪餵汙鍁鹹蠍彜湧遊籲禦願嶽雲竈紮劄築於誌註雕訁譾郤猛氹阪壟堖垵墊檾蕒葤蓧蒓菇槁摣咤唚哢噝噅撅劈謔襆嶴脊仿僥獁麅餘餷饊饢楞怵懍爿漵灩濫瀦寧糸絝緔瑉梘棬案橰櫫軲軤賫膁腖飈煆溜湣渺碸滾瞘鈈鉕鋣銱鋥鋶鐦鐧鍩鍀鍃錇鎄鎇鎿鐝鑥鑹鑔穭鶓鶥鸌癧屙瘂臒襇繈耮顬蟎麯鮁鮃鮎鯗鯝鯴鱝鯿鰠鰵鱅鞽韝齇';
  1166. }
  1167. function charPYStr(){
  1168. return '锕皑蔼碍爱嗳嫒瑷暧霭谙铵鹌肮袄奥媪骜鳌坝罢钯摆败呗颁办绊钣帮绑镑谤剥饱宝报鲍鸨龅辈贝钡狈备惫鹎贲锛绷笔毕毙币闭荜哔滗铋筚跸边编贬变辩辫苄缏笾标骠飑飙镖镳鳔鳖别瘪濒滨宾摈傧缤槟殡膑镔髌鬓饼禀拨钵铂驳饽钹鹁补钸财参蚕残惭惨灿骖黪苍舱仓沧厕侧册测恻层诧锸侪钗搀掺蝉馋谗缠铲产阐颤冁谄谶蒇忏婵骣觇禅镡场尝长偿肠厂畅伥苌怅阊鲳钞车彻砗尘陈衬伧谌榇碜龀撑称惩诚骋枨柽铖铛痴迟驰耻齿炽饬鸱冲冲虫宠铳畴踌筹绸俦帱雠橱厨锄雏础储触处刍绌蹰传钏疮闯创怆锤缍纯鹑绰辍龊辞词赐鹚聪葱囱从丛苁骢枞凑辏蹿窜撺错锉鹾达哒鞑带贷骀绐担单郸掸胆惮诞弹殚赕瘅箪当挡党荡档谠砀裆捣岛祷导盗焘灯邓镫敌涤递缔籴诋谛绨觌镝颠点垫电巅钿癫钓调铫鲷谍叠鲽钉顶锭订铤丢铥东动栋冻岽鸫窦犊独读赌镀渎椟牍笃黩锻断缎簖兑队对怼镦吨顿钝炖趸夺堕铎鹅额讹恶饿谔垩阏轭锇锷鹗颚颛鳄诶儿尔饵贰迩铒鸸鲕发罚阀珐矾钒烦贩饭访纺钫鲂飞诽废费绯镄鲱纷坟奋愤粪偾丰枫锋风疯冯缝讽凤沣肤辐抚辅赋复负讣妇缚凫驸绂绋赙麸鲋鳆钆该钙盖赅杆赶秆赣尴擀绀冈刚钢纲岗戆镐睾诰缟锆搁鸽阁铬个纥镉颍给亘赓绠鲠龚宫巩贡钩沟苟构购够诟缑觏蛊顾诂毂钴锢鸪鹄鹘剐挂鸹掴关观馆惯贯诖掼鹳鳏广犷规归龟闺轨诡贵刽匦刿妫桧鲑鳜辊滚衮绲鲧锅国过埚呙帼椁蝈铪骇韩汉阚绗颉号灏颢阂鹤贺诃阖蛎横轰鸿红黉讧荭闳鲎壶护沪户浒鹕哗华画划话骅桦铧怀坏欢环还缓换唤痪焕涣奂缳锾鲩黄谎鳇挥辉毁贿秽会烩汇讳诲绘诙荟哕浍缋珲晖荤浑诨馄阍获货祸钬镬击机积饥迹讥鸡绩缉极辑级挤几蓟剂济计记际继纪讦诘荠叽哜骥玑觊齑矶羁虿跻霁鲚鲫夹荚颊贾钾价驾郏浃铗镓蛲歼监坚笺间艰缄茧检碱硷拣捡简俭减荐槛鉴践贱见键舰剑饯渐溅涧谏缣戋戬睑鹣笕鲣鞯将浆蒋桨奖讲酱绛缰胶浇骄娇搅铰矫侥脚饺缴绞轿较挢峤鹪鲛阶节洁结诫届疖颌鲒紧锦仅谨进晋烬尽劲荆茎卺荩馑缙赆觐鲸惊经颈静镜径痉竞净刭泾迳弪胫靓纠厩旧阄鸠鹫驹举据锯惧剧讵屦榉飓钜锔窭龃鹃绢锩镌隽觉决绝谲珏钧军骏皲开凯剀垲忾恺铠锴龛闶钪铐颗壳课骒缂轲钶锞颔垦恳龈铿抠库裤喾块侩郐哙脍宽狯髋矿旷况诓诳邝圹纩贶亏岿窥馈溃匮蒉愦聩篑阃锟鲲扩阔蛴蜡腊莱来赖崃徕涞濑赉睐铼癞籁蓝栏拦篮阑兰澜谰揽览懒缆烂滥岚榄斓镧褴琅阆锒捞劳涝唠崂铑铹痨乐鳓镭垒类泪诔缧篱狸离鲤礼丽厉励砾历沥隶俪郦坜苈莅蓠呖逦骊缡枥栎轹砺锂鹂疠粝跞雳鲡鳢俩联莲连镰怜涟帘敛脸链恋炼练蔹奁潋琏殓裢裣鲢粮凉两辆谅魉疗辽镣缭钌鹩猎临邻鳞凛赁蔺廪檩辚躏龄铃灵岭领绫棂蛏鲮馏刘浏骝绺镏鹨龙聋咙笼垄拢陇茏泷珑栊胧砻楼娄搂篓偻蒌喽嵝镂瘘耧蝼髅芦卢颅庐炉掳卤虏鲁赂禄录陆垆撸噜闾泸渌栌橹轳辂辘氇胪鸬鹭舻鲈峦挛孪滦乱脔娈栾鸾銮抡轮伦仑沦纶论囵萝罗逻锣箩骡骆络荦猡泺椤脶镙驴吕铝侣屡缕虑滤绿榈褛锊呒妈玛码蚂马骂吗唛嬷杩买麦卖迈脉劢瞒馒蛮满谩缦镘颡鳗猫锚铆贸麽没镁门闷们扪焖懑钔锰梦眯谜弥觅幂芈谧猕祢绵缅渑腼黾庙缈缪灭悯闽闵缗鸣铭谬谟蓦馍殁镆谋亩钼呐钠纳难挠脑恼闹铙讷馁内拟腻铌鲵撵辇鲶酿鸟茑袅聂啮镊镍陧蘖嗫颟蹑柠狞宁拧泞苎咛聍钮纽脓浓农侬哝驽钕诺傩疟欧鸥殴呕沤讴怄瓯盘蹒庞抛疱赔辔喷鹏纰罴铍骗谝骈飘缥频贫嫔苹凭评泼颇钋扑铺朴谱镤镨栖脐齐骑岂启气弃讫蕲骐绮桤碛颀颃鳍牵钎铅迁签谦钱钳潜浅谴堑佥荨悭骞缱椠钤枪呛墙蔷强抢嫱樯戗炝锖锵镪羟跄锹桥乔侨翘窍诮谯荞缲硗跷窃惬锲箧钦亲寝锓轻氢倾顷请庆揿鲭琼穷茕蛱巯赇虮鳅趋区躯驱龋诎岖阒觑鸲颧权劝诠绻辁铨却鹊确阕阙悫让饶扰绕荛娆桡热韧认纫饪轫荣绒嵘蝾缛铷颦软锐蚬闰润洒萨飒鳃赛伞毵糁丧骚扫缫涩啬铯穑杀刹纱铩鲨筛晒酾删闪陕赡缮讪姗骟钐鳝墒伤赏垧殇觞烧绍赊摄慑设厍滠畲绅审婶肾渗诜谂渖声绳胜师狮湿诗时蚀实识驶势适释饰视试谥埘莳弑轼贳铈鲥寿兽绶枢输书赎属术树竖数摅纾帅闩双谁税顺说硕烁铄丝饲厮驷缌锶鸶耸怂颂讼诵擞薮馊飕锼苏诉肃谡稣虽随绥岁谇孙损笋荪狲缩琐锁唢睃獭挞闼铊鳎台态钛鲐摊贪瘫滩坛谭谈叹昙钽锬顸汤烫傥饧铴镗涛绦讨韬铽腾誊锑题体屉缇鹈阗条粜龆鲦贴铁厅听烃铜统恸头钭秃图钍团抟颓蜕饨脱鸵驮驼椭箨鼍袜娲腽弯湾顽万纨绾网辋韦违围为潍维苇伟伪纬谓卫诿帏闱沩涠玮韪炜鲔温闻纹稳问阌瓮挝蜗涡窝卧莴龌呜钨乌诬无芜吴坞雾务误邬庑怃妩骛鹉鹜锡牺袭习铣戏细饩阋玺觋虾辖峡侠狭厦吓硖鲜纤贤衔闲显险现献县馅羡宪线苋莶藓岘猃娴鹇痫蚝籼跹厢镶乡详响项芗饷骧缃飨萧嚣销晓啸哓潇骁绡枭箫协挟携胁谐写泻谢亵撷绁缬锌衅兴陉荥凶汹锈绣馐鸺虚嘘须许叙绪续诩顼轩悬选癣绚谖铉镟学谑泶鳕勋询寻驯训讯逊埙浔鲟压鸦鸭哑亚讶垭娅桠氩阉烟盐严岩颜阎艳厌砚彦谚验厣赝俨兖谳恹闫酽魇餍鼹鸯杨扬疡阳痒养样炀瑶摇尧遥窑谣药轺鹞鳐爷页业叶靥谒邺晔烨医铱颐遗仪蚁艺亿忆义诣议谊译异绎诒呓峄饴怿驿缢轶贻钇镒镱瘗舣荫阴银饮隐铟瘾樱婴鹰应缨莹萤营荧蝇赢颖茔莺萦蓥撄嘤滢潆璎鹦瘿颏罂哟拥佣痈踊咏镛优忧邮铀犹诱莸铕鱿舆鱼渔娱与屿语狱誉预驭伛俣谀谕蓣嵛饫阈妪纡觎欤钰鹆鹬龉鸳渊辕园员圆缘远橼鸢鼋约跃钥粤悦阅钺郧匀陨运蕴酝晕韵郓芸恽愠纭韫殒氲杂灾载攒暂赞瓒趱錾赃脏驵凿枣责择则泽赜啧帻箦贼谮赠综缯轧铡闸栅诈斋债毡盏斩辗崭栈战绽谵张涨帐账胀赵诏钊蛰辙锗这谪辄鹧贞针侦诊镇阵浈缜桢轸赈祯鸩挣睁狰争帧症郑证诤峥钲铮筝织职执纸挚掷帜质滞骘栉栀轵轾贽鸷蛳絷踬踯觯钟终种肿众锺诌轴皱昼骤纣绉猪诸诛烛瞩嘱贮铸驻伫槠铢专砖转赚啭馔颞桩庄装妆壮状锥赘坠缀骓缒谆准着浊诼镯兹资渍谘缁辎赀眦锱龇鲻踪总纵偬邹诹驺鲰诅组镞钻缵躜鳟翱并卜沉丑淀斗范干皋硅柜后伙秸杰诀夸里凌么霉捻凄扦圣尸抬涂洼喂污锨咸蝎彝涌游吁御愿岳云灶扎札筑于志注凋讠谫郄猛凼坂垅垴埯埝苘荬荮莜莼菰藁揸吒吣咔咝咴噘噼嚯幞岙嵴彷徼犸狍馀馇馓馕愣憷懔丬溆滟滥潴甯纟绔绱珉枧桊案槔橥轱轷赍肷胨飚煅熘愍淼砜磙眍钚钷铘铞锃锍锎锏锘锝锪锫锿镅镎镢镥镩镲稆鹋鹛鹱疬疴痖癯裥襁耢颥螨麴鲅鲆鲇鲞鲴鲺鲼鳊鳋鳘鳙鞒鞴齄';
  1169. }
  1170. function traditionalized(cc){
  1171. var str='';
  1172. for(var i=0;i<cc.length;i++){
  1173. if(charPYStr().indexOf(cc.charAt(i))!=-1){
  1174. str+=ftPYStr().charAt(charPYStr().indexOf(cc.charAt(i)));
  1175. }else{
  1176. str+=cc.charAt(i);
  1177. }
  1178. }
  1179. return str;
  1180. }
  1181.  
  1182. function simplized(cc){
  1183. if(!cc){return ""};
  1184. var str='';
  1185. for(var i=0;i<cc.length;i++){
  1186. if(ftPYStr().indexOf(cc.charAt(i))!=-1) str+=charPYStr().charAt(ftPYStr().indexOf(cc.charAt(i)));
  1187. else str+=cc.charAt(i);
  1188. }
  1189. return str;
  1190. }
  1191. })();