碧蓝幻想书签

none

  1. // ==UserScript==
  2. // @name 碧蓝幻想书签
  3. // @namespace https://github.com/biuuu/gbf-bookmark
  4. // @version 0.2.8
  5. // @description none
  6. // @author biuuu
  7. // @match *://game.granbluefantasy.jp/*
  8. // @match *://gbf.game.mbga.jp/*
  9. // @run-at document-start
  10. // @supportURL https://github.com/biuuu/gbf-bookmark/issues
  11. // ==/UserScript==
  12. (function () {
  13. 'use strict';
  14.  
  15. var list = [
  16. {
  17. url: "#mypage",
  18. name: "首页",
  19. index: 3,
  20. background: "#297fc8"
  21. },
  22. {
  23. name: "共斗",
  24. url: "#coopraid",
  25. background: "#ffeb3b",
  26. index: 4
  27. },
  28. {
  29. name: "未确认",
  30. url: "#quest/assist/unclaimed",
  31. background: "#8dc3dd",
  32. index: 5
  33. },
  34. {
  35. url: "#quest/assist",
  36. name: "副本列表",
  37. index: 7,
  38. background: "#c96883"
  39. },
  40. {
  41. name: "活动副本",
  42. url: "#quest/assist/event",
  43. background: "#297fc8",
  44. index: 8,
  45. parent: 0
  46. },
  47. {
  48. name: "Fate",
  49. url: "#quest/fate",
  50. background: "#efb983",
  51. index: 9
  52. },
  53. {
  54. url: "#sidestory",
  55. name: "SIDE STORY",
  56. index: 10,
  57. background: "#eee3c8"
  58. },
  59. {
  60. name: "塔罗首页",
  61. url: "#arcarum2",
  62. background: "#259a80",
  63. index: 11,
  64. parent: 0
  65. },
  66. {
  67. name: "收藏的任务",
  68. url: "none",
  69. background: "#b51e22",
  70. index: 12,
  71. parent: 0
  72. },
  73. {
  74. url: "back",
  75. name: "后退",
  76. index: 16,
  77. background: "#FFEB3B"
  78. },
  79. {
  80. url: "reload",
  81. name: "刷新",
  82. index: 18,
  83. background: "#de3a7c"
  84. },
  85. {
  86. name: "欧罗巴",
  87. url: "#quest/supporter/303161/1/0/523",
  88. background: "#efcdce",
  89. index: 9,
  90. parent: 12
  91. },
  92. {
  93. name: "军神",
  94. url: "#quest/supporter/303181/1/0/525",
  95. background: "#20a48f",
  96. index: 10,
  97. parent: 12
  98. },
  99. {
  100. name: "湿婆",
  101. url: "#quest/supporter/303151/1/0/522",
  102. background: "#731dc9",
  103. index: 11,
  104. parent: 12
  105. },
  106. {
  107. name: "神盾",
  108. url: "#quest/supporter/303171/1/0/524",
  109. background: "#d51330",
  110. index: 12,
  111. parent: 12
  112. },
  113. {
  114. name: "梅塔特隆",
  115. url: "#quest/supporter/303191/1/0/526",
  116. background: "#f8fdfe",
  117. index: 13,
  118. parent: 12
  119. },
  120. {
  121. name: "阿凡达",
  122. url: "#quest/supporter/303221/1/0/527",
  123. background: "#400040",
  124. index: 14,
  125. parent: 12
  126. }
  127. ];
  128.  
  129. let data = {
  130. list: list
  131. };
  132.  
  133. const getLocalData = () => {
  134. try {
  135. let str = localStorage.getItem('gbf-bookmark:data');
  136.  
  137. if (str) {
  138. let obj = JSON.parse(str);
  139.  
  140. if (obj && obj.length) {
  141. data.list = obj.sort((prev, next) => {
  142. const prevParent = (prev.parent | 0) * 100;
  143. const nextParent = (next.parent | 0) * 100;
  144. return prev.index + prevParent - (next.index + nextParent);
  145. });
  146. }
  147. }
  148. } catch (e) {}
  149. };
  150.  
  151. getLocalData();
  152.  
  153. const config = {
  154. position: 'left',
  155. hideDelay: 10,
  156. animation: true,
  157. margin: 4,
  158. size: 2,
  159. align: 'left',
  160. mixed: 'yes'
  161. };
  162.  
  163. const getLocalConfig = () => {
  164. try {
  165. let _config = JSON.parse(localStorage.getItem('gbf-bookmark:config'));
  166.  
  167. if (_config) {
  168. if (_config.hideDelay) {
  169. _config.hideDelay = _config.hideDelay | 0;
  170. }
  171.  
  172. if (_config.margin) {
  173. _config.margin = _config.margin | 0;
  174. }
  175.  
  176. Object.assign(config, _config);
  177. }
  178. } catch (e) {}
  179. };
  180.  
  181. getLocalConfig();
  182.  
  183. const applyConfig = () => {
  184. const cont = document.getElementById('gbf-bookmark-lacia');
  185.  
  186. if (config.position === 'left') {
  187. cont.classList.remove('bookmark-right');
  188. } else {
  189. cont.classList.add('bookmark-right');
  190. }
  191.  
  192. if (config.mixed === 'yes') {
  193. cont.classList.remove('not-mixed-bookmark');
  194. } else {
  195. cont.classList.add('not-mixed-bookmark');
  196. }
  197.  
  198. cont.classList.remove('align-left-bookmark', 'align-center-bookmark', 'align-right-bookmark');
  199. cont.classList.add("align-".concat(config.align, "-bookmark"));
  200. cont.classList.remove('autohide-bookmark', 'keep-bookmark', 'full-bookmark');
  201. cont.classList.remove('keep-bookmark');
  202.  
  203. if (config.hideDelay === 0) {
  204. cont.classList.add('autohide-bookmark');
  205. } else if (config.hideDelay === -1) {
  206. cont.classList.add('keep-bookmark');
  207. } else if (config.hideDelay === -2) {
  208. cont.classList.add('full-bookmark');
  209. }
  210.  
  211. cont.style.opacity = null;
  212.  
  213. if (!config.animation) {
  214. cont.classList.add('bookmark-remove-anime');
  215. } else {
  216. cont.classList.remove('bookmark-remove-anime');
  217. }
  218.  
  219. cont.classList.remove('size-1', 'size-2', 'size-3');
  220. cont.classList.add("size-".concat(config.size));
  221. let styleTag = document.getElementById('style-gbf-bookmark');
  222.  
  223. if (!styleTag) {
  224. styleTag = document.createElement('style');
  225. styleTag.id = 'style-gbf-bookmark';
  226. document.body.appendChild(styleTag);
  227. }
  228.  
  229. let width = 67;
  230. if (config.size === 1) width = 84;
  231. if (config.size === 3) width = 59;
  232. let left = width - config.margin;
  233. if (left > width) left = width;
  234. if (left < 0) left = 0;
  235. styleTag.innerHTML = "\n body #gbf-bookmark-lacia".concat(config.position === 'right' ? '.bookmark-right' : '', " {\n ").concat(config.position, ": -").concat(left, "px;\n }\n ");
  236. };
  237.  
  238. const initIpt = () => {
  239. const iptPosition = document.getElementById('ipt-position-bookmark');
  240. const iptHidedelay = document.getElementById('ipt-hidedelay-bookmark');
  241. const iptMargin = document.getElementById('ipt-margin-bookmark');
  242. const iptAnimation = document.getElementById('ipt-animation-bookmark');
  243. const iptSize = document.getElementById('ipt-size-bookmark');
  244. const iptAlign = document.getElementById('ipt-align-bookmark');
  245. const iptMixed = document.getElementById('ipt-mixed-bookmark');
  246. iptPosition.value = config.position;
  247. iptHidedelay.value = config.hideDelay;
  248. iptMargin.value = config.margin;
  249. iptAnimation.value = config.animation ? 'open' : 'close';
  250. iptSize.value = config.size;
  251. iptAlign.value = config.align;
  252. iptMixed.value = config.mixed;
  253. };
  254.  
  255. const saveConfig = () => {
  256. try {
  257. localStorage.setItem('gbf-bookmark:config', JSON.stringify(config));
  258. } catch (e) {}
  259. };
  260.  
  261. const fontColor = rgb => {
  262. let str = rgb.slice(1);
  263. let r, g, b;
  264.  
  265. if (str.length === 6) {
  266. r = parseInt(str.slice(0, 2), 16);
  267. g = parseInt(str.slice(2, 4), 16);
  268. b = parseInt(str.slice(4, 6), 16);
  269. } else {
  270. r = str.slice(0, 1);
  271. r = parseInt("".concat(r).concat(r), 16);
  272. g = str.slice(1, 2);
  273. g = parseInt("".concat(g).concat(g), 16);
  274. b = str.slice(2, 3);
  275. b = parseInt("".concat(b).concat(b), 16);
  276. }
  277.  
  278. const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
  279.  
  280. if (luminance > 0.7) {
  281. return '#000';
  282. } else {
  283. return '#fff';
  284. }
  285. };
  286.  
  287. const colors = ['#ff972d', '#297fc8', '#5fc829', '#FFEB3B', '#c96883', '#8dc3dd', '#ffffff', '#eee3c8', '#009688', '#4CAF50', '#8BC34A', '#CDDC39', '#FFEB3B', '#FFC107', '#FF9800', '#FF5722', '#607D8B'];
  288.  
  289. const randomColor = () => {
  290. return colors[Math.floor(Math.random() * colors.length)];
  291. };
  292.  
  293. const tagList = list => {
  294. const _list = [];
  295. const temp = [...list];
  296. temp.forEach((item, index) => {
  297. item._index = index;
  298. });
  299. const sl = temp.sort((prev, next) => {
  300. return prev.index - next.index;
  301. });
  302. const pList = sl.filter(item => !item.parent);
  303.  
  304. _list.push(pList);
  305.  
  306. const sList = sl.filter(item => item.parent).sort((prev, next) => prev.parent - next.parent);
  307. const subMap = new Map();
  308. sList.forEach(item => {
  309. const pid = parseInt(item.parent, 10);
  310.  
  311. if (!subMap.has(pid)) {
  312. const pItem = pList.find(pitem => pitem.index === pid) || {};
  313. const bg = pItem.background || '#9E9E9E';
  314. const fc = fontColor(bg);
  315. subMap.set(pid, {
  316. index: _list.length,
  317. color: fc,
  318. bg: bg
  319. });
  320.  
  321. _list.push([item]);
  322. } else {
  323. const {
  324. index
  325. } = subMap.get(pid);
  326.  
  327. _list[index].push(item);
  328. }
  329. });
  330. return [_list, subMap];
  331. };
  332.  
  333. const tagHtml = (item, index) => {
  334. const bg = item.background || '#297fc8';
  335. const color = item.color || fontColor(bg);
  336. return "<div style=\"background-color:".concat(bg, ";color:").concat(color, "\"\n class=\"paper-shadow2 bookmark-tag\"><div class=\"idx-tag\"><span>").concat(item.index, "</span></div>\n <span class=\"edit-tag\" data-index=\"").concat(item._index, "\">\u6539</span><span class=\"delete-tag\" data-index=\"").concat(item._index, "\">\u5220</span>\n ").concat(item.name || 'NoName', "</div>");
  337. };
  338.  
  339. const renderTag = () => {
  340. let html = '';
  341. const [list, subMap] = tagList(data.list);
  342. list[0].forEach((item, index) => {
  343. html += "".concat(tagHtml(item, index));
  344. });
  345. html = "<div class=\"box-tag\">".concat(html, "</div>");
  346.  
  347. for (let [pid, obj] of subMap) {
  348. const {
  349. index,
  350. color,
  351. bg
  352. } = obj;
  353. html += "<div class=\"box-tag\" style=\"border-color:".concat(bg, "\"><span class=\"sub-index\" style=\"color:").concat(color, ";background:").concat(bg, "\">").concat(pid, "</span>");
  354. list[index].forEach(item => {
  355. html += "".concat(tagHtml(item, index));
  356. });
  357. html += "</div>";
  358. }
  359.  
  360. return html;
  361. };
  362.  
  363. const renderList = () => {
  364. let html = '';
  365. let parentIds = [];
  366. const bookmarks = data.list;
  367.  
  368. if (bookmarks.length) {
  369. const childBookmarks = bookmarks.filter(item => !!item.parent);
  370. const parentList = bookmarks.filter(item => !item.parent);
  371. const childList = new Map();
  372. childBookmarks.forEach(item => {
  373. if (!childList.has(item.parent)) {
  374. childList.set(item.parent, []);
  375. }
  376.  
  377. childList.get(item.parent).push(item);
  378. });
  379. childList.forEach((list, pid) => {
  380. const item = parentList.find(obj => obj.index === pid);
  381. if (item) list.unshift(item);
  382. });
  383. parentIds = [...childList.keys()];
  384.  
  385. const makeList = bkmks => {
  386. const indexList = bkmks.map(item => item.index);
  387. let maxIndex = Math.max(...indexList);
  388. if (maxIndex > 100) maxIndex = 100;
  389. if (maxIndex < 30) maxIndex = 30;
  390. const list = new Array(maxIndex).fill({});
  391. indexList.forEach((tag, idx) => {
  392. list[tag - 1] = bkmks[idx];
  393. });
  394. return list;
  395. };
  396.  
  397. const renderHtml = (list, parent) => {
  398. let str = '';
  399. list.forEach(item => {
  400. if (item.url) {
  401. const bg = item.background || '#297fc8';
  402. const color = item.color || fontColor(bg);
  403. let className = "bookmark-item-lacia paper-shadow";
  404.  
  405. if (parent && (!item.parent || item.index === parent)) {
  406. className += ' bookmark-item-parent';
  407. }
  408.  
  409. if (item.url === 'reload') {
  410. str += "<a style=\"background-color:".concat(bg, ";color:").concat(color, "\" class=\"").concat(className, "\" onclick=\"location.reload()\"><div>").concat(item.name || 'NoName', "</div></a>");
  411. } else if (item.url === 'back') {
  412. str += "<a style=\"background-color:".concat(bg, ";color:").concat(color, "\" class=\"").concat(className, "\" onclick=\"history.back()\"><div>").concat(item.name || 'NoName', "</div></a>");
  413. } else if (item.url === 'back&forward') {
  414. str += "<a style=\"background-color:".concat(bg, ";color:").concat(color, "\" class=\"").concat(className, "\" onclick=\"history.back();setTimeout(() => history.forward(), 100)\"><div>").concat(item.name || 'NoName', "</div></a>");
  415. } else if (item.url === 'none') {
  416. str += "<a style=\"background-color:".concat(bg, ";color:").concat(color, "\" class=\"").concat(className, "\"><div>").concat(item.name || 'NoName', "</div></a>");
  417. } else if (item.url === 'forward') {
  418. str += "<a style=\"background-color:".concat(bg, ";color:").concat(color, "\" class=\"").concat(className, "\" onclick=\"history.forward()\"><div>").concat(item.name || 'NoName', "</div></a>");
  419. } else {
  420. str += "<a style=\"background-color:".concat(bg, ";color:").concat(color, "\" class=\"").concat(className, "\" href=\"").concat(item.url, "\"><div>").concat(item.name || 'NoName', "</div></a>");
  421. }
  422. } else {
  423. str += "<div class=\"bookmark-item-lacia\"></div>";
  424. }
  425. });
  426. return "<div class=\"bookmark-container".concat(parent ? " bookmark-container-sub" : '', "\">").concat(str, "</div>");
  427. };
  428.  
  429. childList.forEach((list, parent) => {
  430. html += renderHtml(makeList(list), parent);
  431. });
  432. html += renderHtml(makeList(parentList), 0);
  433. }
  434.  
  435. let css = '';
  436. parentIds.forEach(id => {
  437. css += ".bookmark-container-".concat(id, " {display:none}\n .bookmark-container-").concat(id, ":hover {display:none}\n ");
  438. });
  439. html = "<style>".concat(css, "</style>").concat(html);
  440. return html;
  441. };
  442.  
  443. const setIndex = () => {
  444. let index = 1;
  445. data.list.forEach(item => {
  446. if (item.index === index) {
  447. index = item.index + 1;
  448. }
  449. });
  450. return index;
  451. };
  452.  
  453. const renderAll = () => {
  454. document.getElementById('bookmark-cont').innerHTML = renderTag();
  455. document.getElementById('gbf-bookmark-lacia').innerHTML = renderList();
  456. };
  457.  
  458. const saveData = () => {
  459. try {
  460. localStorage.setItem('gbf-bookmark:data', JSON.stringify(data.list));
  461. } catch (e) {}
  462. };
  463.  
  464. const tryDownload = (content, filename) => {
  465. const eleLink = document.createElement('a');
  466. eleLink.download = filename;
  467. eleLink.style.display = 'none';
  468. const blob = new Blob([content], {
  469. type: 'text/csv'
  470. });
  471. eleLink.href = URL.createObjectURL(blob);
  472. document.body.appendChild(eleLink);
  473. eleLink.click();
  474. document.body.removeChild(eleLink);
  475. };
  476.  
  477. const css = "\n#gbf-bookmark-lacia {\n position: fixed;\n left: 0;\n top: 0;\n width: 2px;\n height: 100%;\n z-index: 9999999;\n left: -65px;\n pointer-events: none;\n transition: left 0.1s, right 0.1s;\n display: flex;\n}\n#gbf-bookmark-lacia.align-left-bookmark .bookmark-item-lacia {\n text-align: left;\n}\n#gbf-bookmark-lacia.align-center-bookmark .bookmark-item-lacia {\n text-align: center;\n}\n#gbf-bookmark-lacia.align-right-bookmark .bookmark-item-lacia {\n text-align: right;\n}\n.bookmark-container {\n position: absolute;\n left: 0;\n right: 0;\n z-index: 1;\n}\n.bookmark-container-sub {\n z-index: 2;\n}\n.bookmark-container-sub .bookmark-item-lacia {\n opacity: 0;\n pointer-events: none;\n}\n.bookmark-container-sub .bookmark-item-lacia.bookmark-item-parent {\n pointer-events: auto;\n}\n.bookmark-container-sub:hover {\n order: -1;\n}\n.bookmark-container-sub:hover .bookmark-item-lacia {\n opacity: 1;\n pointer-events: auto;\n}\n.bookmark-container-sub:hover ~ .bookmark-container {\n opacity: 0;\n}\n.bookmark-container-sub:hover ~ .bookmark-container-sub {\n pointer-events: none;\n display: none;\n}\n.bookmark-container-sub .bookmark-item-lacia:not(a) {\n width: 15px;\n padding: 0;\n}\n#gbf-bookmark-lacia.size-1 .bookmark-container-sub .bookmark-item-lacia:not(a) {\n width: 20px;\n padding: 0;\n}\n#gbf-bookmark-lacia.size-3 .bookmark-container-sub .bookmark-item-lacia:not(a) {\n width: 10px;\n padding: 0;\n}\n#show-setting-bookmark {\n position: fixed;\n top: 0;\n left: 0;\n width: 10px;\n height: 10px;\n z-index: 1000000;\n cursor: pointer;\n}\n#gbf-bookmark-lacia.bookmark-remove-anime,\n#gbf-bookmark-lacia.bookmark-remove-anime a.bookmark-item-lacia {\n transition: none;\n}\n#gbf-bookmark-lacia.autohide-bookmark {\n opacity: 0;\n}\n#gbf-bookmark-lacia.full-bookmark a.bookmark-item-lacia:nth-child(2n) {\n padding-right: 10px;\n}\n#gbf-bookmark-lacia.not-mixed-bookmark a.bookmark-item-lacia:nth-child(2n){\n padding-right: 8px;\n}\n#gbf-bookmark-lacia.not-mixed-bookmark:hover a.bookmark-item-lacia:nth-child(2n){\n padding-right: 8px;\n}\n#gbf-bookmark-lacia:not(.full-bookmark):hover {\n left: 0;\n}\n#gbf-bookmark-lacia.autohide-bookmark:hover {\n opacity: 1;\n}\n#gbf-bookmark-lacia:hover .bookmark-item-lacia {\n box-shadow: none;\n}\n#gbf-bookmark-lacia.size-1 .bookmark-item-lacia {\n width: 26px;\n height: 30px;\n line-height: 30px;\n padding-left: 11px;\n}\n#gbf-bookmark-lacia.size-1 .bookmark-item-lacia {\n width: 69px;\n font-size: 11px;\n}\n#gbf-bookmark-lacia.size-3 .bookmark-item-lacia {\n width: 18px;\n height: 20px;\n line-height: 20px;\n padding-left: 6px;\n}\n#gbf-bookmark-lacia.size-3 .bookmark-item-lacia {\n width: 44px;\n font-size: 7px;\n}\n.bookmark-item-lacia {\n width: 42px;\n height: 24px;\n line-height: 24px;\n padding-left: 8px;\n padding-right: 8px;\n box-sizing: content-box;\n display: block;\n position: relative;\n pointer-events: auto;\n}\n.bookmark-item-child {\n display: none;\n}\n#gbf-bookmark-lacia:hover a.bookmark-item-lacia:nth-child(2n) {\n padding-right: 10px;\n}\na.bookmark-item-lacia:focus {\n outline: 0;\n}\na.bookmark-item-lacia {\n width: 52px;\n background-color: #fff;\n text-decoration: none;\n white-space: nowrap;\n color: #000;\n font-size: 9px;\n font-family: -apple-system, -apple-system-font, \"Microsoft JHengHei\", HelveticaNeue, \"Helvetica Neue\", Helvetica, sans-serif;\n font-weight: 100;\n cursor: pointer;\n pointer-events: auto;\n z-index: 1;\n box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.25);\n transition: left 0.3s, right 0.3s, box-shadow 0.3s, filter 0.3s;\n}\n.bookmark-item-lacia>div {\n text-overflow: ellipsis;\n overflow: hidden;\n height: 100%;\n}\na.bookmark-item-lacia:hover {\n filter: brightness(0.9);\n}\na.bookmark-item-lacia:active {\n filter: brightness(0.8);\n mix-blend-mode: multiply;\n}\na.bookmark-item-lacia:active:before, a.bookmark-item-lacia:active:after {\n display: none;\n}\n.paper-shadow:before, .paper-shadow:after {\n\tcontent: '';\n position: absolute;\n z-index: 1;\n\tleft: 0;\n\tbox-shadow: 0 0 10px rgba(0,0,0,0.35);\n\tborder-radius: 50%;\n\twidth: 100%;\n\theight: 20px;\n\tdisplay: none;\n}\n.paper-shadow:before {\n\tdisplay: block;\n\ttop: 0px;\n\tclip: rect(-40px auto 0 auto);\n}\n.paper-shadow:after {\n\tdisplay: block;\n\tbottom: 0px;\n\tclip: rect(20px auto 40px auto);\n}\n#gbf-bookmark-lacia.bookmark-right {\n left: auto;\n right: -65px;\n}\n#gbf-bookmark-lacia.bookmark-right:not(.full-bookmark):hover {\n right: 0;\n left: auto;\n}\n#gbf-bookmark-lacia.bookmark-right .bookmark-item-lacia {\n float: right;\n}\n.paper-shadow.dark-shadow:before,.paper-shadow.dark-shadow:after {\n box-shadow: 0 0 10px rgb(0, 0, 0, 0.5);\n}\n#gbf-bookmark-setting {\n position: fixed;\n z-index: 9999999;\n width: 280px;\n padding-bottom: 30px;\n min-height: 290px;\n max-height: calc(100% - 200px);\n top: 60px;\n left: 20px;\n background: #fffbe1;\n font-family: -apple-system, -apple-system-font, \"Microsoft JHengHei\", HelveticaNeue, \"Helvetica Neue\", Helvetica, sans-serif;\n font-weight: 100;\n display: none;\n}\n#gbf-bookmark-setting.show-setting {\n display: block;\n}\n#gbf-bookmark-setting .s-paper {\n position: absolute;\n bottom: -2px;\n width: calc(100% - 2px);\n left: 1px;\n height: 2px;\n background: #e8e4cb;\n}\n.tab-bookmark-setting {\n position: absolute;\n height: 24px;\n line-height: 24px;\n background: #e8e4cb;\n top: -24px;\n left: 1px;\n padding: 0 20px;\n font-size: 10px;\n z-index: 0;\n letter-spacing: 0.2em;\n cursor: pointer;\n}\n.tab-bookmark-setting:after {\n display: none;\n}\n.option-bookmark {\n left: 76px;\n}\n.option-bookmark.active-bookmark {\n left: 75px;\n}\n.active-bookmark {\n z-index: 2;\n background: #fffbe1;\n height: 25px;\n line-height: 25px;\n padding: 0 21px;\n left: 0px;\n}\n.footer-bookmark-setting {\n position: absolute;\n bottom: 0;\n width: 100%;\n left: 0;\n padding: 10px 0;\n text-align: center;\n}\n.footer-bookmark-setting .btn-bookmark {\n margin: 0 10px;\n}\n.btn-bookmark {\n padding: 4px 12px;\n font-size: 8px;\n cursor: pointer;\n display: inline-block;\n box-shadow: 0 0 1px rgba(0,0,0,0.05);\n background-color: #FFEB3B;\n}\n.btn-bookmark:hover {\n background-color: #fff280;\n}\n.btn-bookmark:active {\n background-color: #fff492;\n}\n.btn-bookmark.btn-add {\n padding: 2px 8px;\n color: #fff;\n background-color: #8BC34A;\n box-shadow: 0 1px 2px rgba(0,0,0,0.2);\n}\n.btn-bookmark.btn-add:after,.btn-bookmark.btn-add:before {\n display: none;\n}\n.btn-bookmark.btn-add:hover {\n filter: brightness(0.95);\n}\n.btn-bookmark.btn-add:active {\n filter: brightness(0.9);\n}\n.toolbar-bookmark {\n display: flex;\n justify-content: space-between;\n}\n.toolbar-bookmark .toolbar-right {\n display: flex;\n}\n.toolbar-bookmark .toolbar-right .btn-bookmark.btn-add {\n background: #03A9F4;\n margin-left: 10px;\n}\n.setting-box-bookmark {\n padding: 10px;\n display: none;\n}\n.setting-box-bookmark.box-active {\n display: block;\n}\n#bookmark-cont {\n margin: 4px 0;\n margin-right: -4px;\n overflow-y: auto;\n max-height: 320px;\n}\n#bookmark-cont .box-tag {\n border: 1px solid #9E9E9E;\n position: relative;\n display: flex;\n flex-wrap: wrap;\n margin-bottom: 8px;\n margin-right: 4px;\n padding: 4px;\n}\n#bookmark-cont .sub-index {\n font-size: 10px;\n box-shadow: 0 0 2px rgba(0,0,0,0.1);\n width: 16px;\n height: 16px;\n display: flex;\n z-index: 1;\n position: absolute;\n align-items: center;\n justify-content: center;\n right: -1px;\n top: -1px;\n}\n#bookmark-cont::-webkit-scrollbar {\n display: block;\n width: 4px;\n background: #e4eaa4;\n border-radius: 2px;\n}\n#bookmark-cont::-webkit-scrollbar-thumb {\n background: #8BC34A;\n border-radius: 2px;\n}\n.setting-box-bookmark .bookmark-tag {\n padding: 4px 12px;\n margin: 4px;\n font-size: 10px;\n}\n.setting-box-bookmark .idx-tag {\n position: absolute;\n left: 2px;\n top: 2px;\n font-size: 6px;\n padding: 0 2px;\n}\n.setting-box-bookmark .idx-tag-parent {\n position: absolute;\n right: 2px;\n bottom: 2px;\n font-size: 6px;\n padding: 0 2px;\n text-decoration: underline;\n}\n.setting-box-bookmark .edit-tag, .setting-box-bookmark .delete-tag {\n position: absolute;\n height: 100%;\n font-size: 8px;\n top: 0;\n right: 0;\n background: #FF9800;\n display: none;\n justify-content: center;\n align-items: center;\n width: 20px;\n color: #fff;\n cursor: pointer;\n}\n.setting-box-bookmark .edit-tag:hover, .setting-box-bookmark .delete-tag:hover {\n filter: brightness(0.9);\n}\n.setting-box-bookmark .edit-tag {\n right: 20px;\n background: #2196F3;\n}\n.bookmark-tag:hover .edit-tag, .bookmark-tag:hover .delete-tag {\n display: inline-flex;\n}\n.paper-shadow2 {\n position: relative;\n}\n.paper-shadow2:before, .paper-shadow2:after {\n z-index: -1;\n position: absolute;\n content: '';\n bottom: 5px;\n width: calc(50% - 1px);\n height: 8px;\n background: rgb(0, 0, 0, 0);\n box-shadow: 0px 5px 2px 0px rgba(0, 0, 0, 0.38);\n}\n.paper-shadow2:before {\n transform: rotate(-3deg);\n left: 1px;\n}\n.paper-shadow2:after {\n transform: rotate(3deg);\n right: 1px;\n}\n#gbf-bookmark-tagmodal {\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n width: 200px;\n background-color: #03A9F4;\n font-size: 9px;\n padding: 0 10px;\n box-shadow: 0 0 1px 0.1px rgba(0,0,0,0.2);\n display: none;\n}\n#gbf-bookmark-tagmodal.bookmark-active {\n display: block;\n}\n#gbf-bookmark-tagmodal > div {\n margin: 10px 0;\n text-align: center;\n display: flex;\n justify-content: center;\n}\n#gbf-bookmark-tagmodal .btn-bookmark {\n margin: 0 10px;\n background: #fff;\n}\n#gbf-bookmark-tagmodal .btn-bookmark:hover {\n background: #f3f3f3;\n}\n.setting-option-bookmark {\n font-size: 9px;\n max-height: 320px;\n overflow: auto;\n}\n.setting-option-bookmark>div {\n margin: 10px 0;\n padding: 0 10px;\n}\n.setting-option-bookmark .btn-bookmark {\n background: #03A9F4;\n color: #fff;\n}\n#gbf-bookmark-setting .label-setting, #gbf-bookmark-setting .label-tagmodal {\n background: #fff;\n height: 20px;\n line-height: 20px;\n padding: 0 8px;\n width: 40px;\n display: inline-block;\n margin-right: 10px;\n}\n#gbf-bookmark-setting .label-setting,\n#gbf-bookmark-setting .ipt-setting-bookmark {\n height: 18px;\n line-height: 18px;\n}\n.ipt-setting-cont, .ipt-tagmodal-cont {\n display: inline-block;\n}\n.setting-option-bookmark .hint-bookmark {\n display: block;\n margin-top: 10px;\n color: #777;\n width: 188px;\n font-weight: normal;\n}\n#gbf-bookmark-setting .ipt-setting-bookmark, #gbf-bookmark-setting .ipt-tagmodal {\n background: #fff;\n height: 20px;\n line-height: 20px;\n padding: 0 0 0 8px;\n margin: 0;\n border: 0;\n width: 112px;\n color: #666;\n}\n#gbf-bookmark-setting .ipt-setting-bookmark::placeholder, .ipt-tagmodal::placeholder {\n color: #aaa;\n}\n#gbf-bookmark-setting .ipt-setting-bookmark:focus, .ipt-tagmodal:focus {\n outline: 0;\n}\n";
  478.  
  479. function tempalte() {
  480. const html = "\n <style>".concat(css, "</style>\n <div id=\"show-setting-bookmark\"></div>\n <div id=\"gbf-bookmark-lacia\">").concat(renderList(), "</div>\n <div id=\"gbf-bookmark-setting\" class=\"paper-shadow dark-shadow\">\n <div class=\"tab-bookmark-setting active-bookmark paper-shadow\">\u4E66\u7B7E</div>\n <div class=\"tab-bookmark-setting option-bookmark paper-shadow\">\u9009\u9879</div>\n <div class=\"setting-box-bookmark box-active\">\n <div class=\"toolbar-bookmark\">\n <div id=\"btn-add-bookmark\" class=\"btn-bookmark btn-add paper-shadow2\">\u6DFB\u52A0</div>\n <div class=\"toolbar-right\">\n <input type=\"file\" style=\"display:none\" id=\"ipt-import-bookmark\" accept=\".json\">\n <label for=\"ipt-import-bookmark\" id=\"btn-import-bookmark\" class=\"btn-bookmark btn-add paper-shadow2\">\u5BFC\u5165</label>\n <div id=\"btn-export-bookmark\" class=\"btn-bookmark btn-add paper-shadow2\">\u5BFC\u51FA</div>\n </div>\n </div>\n <div id=\"bookmark-cont\">").concat(renderTag(), "</div>\n </div>\n <div class=\"setting-box-bookmark setting-option-bookmark\">\n <div>\n <span class=\"label-setting paper-shadow2\">\u4F4D\u7F6E</span>\n <div class=\"paper-shadow2 ipt-setting-cont\">\n <select id=\"ipt-position-bookmark\" class=\"ipt-setting-bookmark\">\n <option value=\"left\">\u5DE6\u8FB9</option>\n <option value=\"right\">\u53F3\u8FB9</option>\n </select>\n </div>\n </div>\n <div>\n <span class=\"label-setting paper-shadow2\">\u8FB9\u8DDD</span>\n <div class=\"paper-shadow2 ipt-setting-cont\">\n <input id=\"ipt-margin-bookmark\" class=\"ipt-setting-bookmark\" value=\"2\" type=\"number\" min=\"0\" max=\"100\">\n </div>\n </div>\n <div>\n <span class=\"label-setting paper-shadow2\">\u6587\u5B57</span>\n <div class=\"paper-shadow2 ipt-setting-cont\">\n <select id=\"ipt-align-bookmark\" class=\"ipt-setting-bookmark\">\n <option value=\"left\">\u5DE6\u5BF9\u9F50</option>\n <option value=\"center\">\u5C45\u4E2D</option>\n <option value=\"right\">\u53F3\u5BF9\u9F50</option>\n </select>\n </div>\n </div>\n <div>\n <span class=\"label-setting paper-shadow2\">\u52A8\u753B</span>\n <div class=\"paper-shadow2 ipt-setting-cont\">\n <select id=\"ipt-animation-bookmark\" class=\"ipt-setting-bookmark\">\n <option value=\"open\">\u542F\u7528</option>\n <option value=\"close\">\u7981\u6B62</option>\n </select>\n </div>\n </div>\n <div>\n <span class=\"label-setting paper-shadow2\">\u5C3A\u5BF8</span>\n <div class=\"paper-shadow2 ipt-setting-cont\">\n <select id=\"ipt-size-bookmark\" class=\"ipt-setting-bookmark\">\n <option value=\"1\">\u5927</option>\n <option value=\"2\">\u4E2D</option>\n <option value=\"3\">\u5C0F</option>\n </select>\n </div>\n </div>\n <div>\n <span class=\"label-setting paper-shadow2\">\u5BF9\u9F50\u4E66\u7B7E</span>\n <div class=\"paper-shadow2 ipt-setting-cont\">\n <select id=\"ipt-mixed-bookmark\" class=\"ipt-setting-bookmark\">\n <option value=\"no\">\u662F</option>\n <option value=\"yes\">\u5426</option>\n </select>\n </div>\n </div>\n <div>\n <span class=\"label-setting paper-shadow2\">\u81EA\u52A8\u9690\u85CF</span>\n <div class=\"paper-shadow2 ipt-setting-cont\">\n <input id=\"ipt-hidedelay-bookmark\" class=\"ipt-setting-bookmark\" value=\"10\" type=\"number\" min=\"-2\" max=\"60\">\n </div>\n <span class=\"hint-bookmark\">\u7B49\u5F85\u6307\u5B9A\u79D2\u6570\u540E\u81EA\u52A8\u9690\u85CF\uFF0C\u8BBE\u4E3A0\u76F4\u63A5\u9690\u85CF\uFF0C\u8BBE\u4E3A-1\u5219\u59CB\u7EC8\u663E\u793A\u3002\u5982\u9700\u59CB\u7EC8\u5F39\u51FA\u4E66\u7B7E\u680F\uFF0C\u628A\u81EA\u52A8\u9690\u85CF\u8BBE\u4E3A-2\uFF0C\u5E76\u628A\u8FB9\u8DDD\u8C03\u5230100\u3002</span>\n </div>\n <div><div class=\"btn-bookmark paper-shadow2\" id=\"btn-save-setting\">\u4FDD\u5B58</div></div>\n </div>\n <div class=\"footer-bookmark-setting\">\n <div class=\"btn-bookmark paper-shadow2\" id=\"btn-close-bookmark\">\u5173\u95ED</div>\n </div>\n <div id=\"gbf-bookmark-tagmodal\" class=\"paper-shadow\">\n <div>\n <span class=\"label-tagmodal paper-shadow2\">\u4E66\u7B7E\u540D</span>\n <div class=\"paper-shadow2 ipt-tagmodal-cont\"><input id=\"ipt-name-bookmark\" class=\"ipt-tagmodal\" placeholder=\"\u8BF7\u8F93\u5165\u4E66\u7B7E\u7684\u540D\u5B57\" type=\"text\"></div>\n </div>\n <div>\n <span class=\"label-tagmodal paper-shadow2\">\u7F51\u5740</span>\n <div class=\"paper-shadow2 ipt-tagmodal-cont\"><input id=\"ipt-url-bookmark\" class=\"ipt-tagmodal\" placeholder=\"\u8BF7\u8F93\u5165\u4E66\u7B7E\u5730\u5740\" type=\"text\"></div>\n </div>\n <div>\n <span class=\"label-tagmodal paper-shadow2\">\u989C\u8272</span>\n <div class=\"paper-shadow2 ipt-tagmodal-cont\"><input id=\"ipt-bgcolor-bookmark\" class=\"ipt-tagmodal\" value=\"#00BCD4\" type=\"color\"></div>\n </div>\n <div>\n <span class=\"label-tagmodal paper-shadow2\">\u5E8F\u53F7</span>\n <div class=\"paper-shadow2 ipt-tagmodal-cont\"><input id=\"ipt-index-bookmark\" class=\"ipt-tagmodal\" min=\"1\" max=\"100\" type=\"number\"></div>\n </div>\n <div>\n <span class=\"label-tagmodal paper-shadow2\">\u7236\u4E66\u7B7E</span>\n <div class=\"paper-shadow2 ipt-tagmodal-cont\"><input id=\"ipt-parent-bookmark\" class=\"ipt-tagmodal\" min=\"0\" max=\"100\" type=\"number\"></div>\n </div>\n <div>\n <div class=\"btn-bookmark paper-shadow2\" id=\"btn-save-tagmodal\">\u4FDD\u5B58</div>\n <div class=\"btn-bookmark paper-shadow2\" id=\"btn-close-tagmodal\">\u53D6\u6D88</div>\n </div>\n </div>\n <div class=\"s-paper\"></div>\n </div>\n ");
  481. return html;
  482. }
  483.  
  484. function event () {
  485. const tabs = document.querySelectorAll('#gbf-bookmark-setting .tab-bookmark-setting');
  486. const boxes = document.querySelectorAll('#gbf-bookmark-setting .setting-box-bookmark');
  487. tabs.forEach((tab, index) => {
  488. tab.addEventListener('click', function () {
  489. if (!tab.classList.contains('active-bookmark')) {
  490. tab.classList.add('active-bookmark');
  491.  
  492. if (index === 0) {
  493. tabs[1].classList.remove('active-bookmark');
  494. boxes[1].classList.remove('box-active');
  495. } else {
  496. tabs[0].classList.remove('active-bookmark');
  497. boxes[0].classList.remove('box-active');
  498. }
  499.  
  500. boxes[index].classList.add('box-active');
  501. }
  502. });
  503. });
  504. const setting = document.querySelector('#gbf-bookmark-setting');
  505. const closeBtn = document.querySelector('#btn-close-bookmark');
  506. const bookmark = document.querySelector('#gbf-bookmark-lacia');
  507. const btnShowSetting = document.querySelector('#show-setting-bookmark');
  508.  
  509. bookmark.oncontextmenu = function (e) {
  510. e.preventDefault();
  511. };
  512.  
  513. bookmark.addEventListener('mouseup', function (e) {
  514. if (e.button === 2) {
  515. showSetting();
  516. }
  517. });
  518. btnShowSetting.addEventListener('click', function () {
  519. showSetting();
  520. });
  521.  
  522. const hideSetting = () => {
  523. setting.classList.remove('show-setting');
  524. };
  525.  
  526. const showSetting = () => setting.classList.toggle('show-setting');
  527.  
  528. closeBtn.addEventListener('click', hideSetting);
  529. const btnModalClose = document.querySelector('#btn-close-tagmodal');
  530. const tagModal = document.querySelector('#gbf-bookmark-tagmodal');
  531. const btnAddBookmark = document.querySelector('#btn-add-bookmark');
  532. const btnSaveTag = document.querySelector('#btn-save-tagmodal');
  533. const iptName = document.querySelector('#ipt-name-bookmark');
  534. const iptUrl = document.querySelector('#ipt-url-bookmark');
  535. const iptBgcolor = document.querySelector('#ipt-bgcolor-bookmark');
  536. const iptIndex = document.querySelector('#ipt-index-bookmark');
  537. const iptParent = document.querySelector('#ipt-parent-bookmark');
  538. btnModalClose.addEventListener('click', function () {
  539. tagModal.classList.remove('bookmark-active');
  540. });
  541. const tagModalStatus = {
  542. type: 'add',
  543. index: 1
  544. };
  545. btnAddBookmark.addEventListener('click', function () {
  546. tagModal.classList.add('bookmark-active');
  547. iptName.value = '';
  548. iptUrl.value = location.hash || '';
  549. iptBgcolor.value = randomColor();
  550. iptIndex.value = setIndex();
  551. iptParent.value = 0;
  552. tagModalStatus.type = 'add';
  553. });
  554. btnSaveTag.addEventListener('click', function () {
  555. const url = iptUrl.value;
  556. const name = iptName.value || url.replace(/^#/, '');
  557. if (!url.trim()) return alert('缺少书签地址');
  558. const background = iptBgcolor.value;
  559. const index = iptIndex.value | 0;
  560. const parent = iptParent.value | 0;
  561.  
  562. if (tagModalStatus.type === 'add') {
  563. data.list.push({
  564. name,
  565. url,
  566. background,
  567. index,
  568. parent
  569. });
  570. } else {
  571. data.list[tagModalStatus.index] = {
  572. name,
  573. url,
  574. background,
  575. index,
  576. parent
  577. };
  578. }
  579.  
  580. tagModal.classList.remove('bookmark-active');
  581. renderAll();
  582. saveData();
  583. });
  584. const bookmarkCont = document.querySelector('#bookmark-cont');
  585. bookmarkCont.addEventListener('click', function (e) {
  586. const elemt = e.target;
  587.  
  588. if (elemt.classList.contains('edit-tag')) {
  589. tagModalStatus.type = 'edit';
  590. const index = tagModalStatus.index = elemt.dataset.index | 0;
  591. const item = data.list[index];
  592. tagModal.classList.add('bookmark-active');
  593. iptName.value = item.name || '';
  594. iptUrl.value = item.url || '';
  595. iptBgcolor.value = item.background || randomColor();
  596. iptIndex.value = item.index || setIndex();
  597. iptParent.value = item.parent | 0;
  598. } else if (elemt.classList.contains('delete-tag')) {
  599. if (!confirm('确定要删除这个书签吗?')) return;
  600. const index = elemt.dataset.index | 0;
  601. data.list.splice(index, 1);
  602. renderAll();
  603. saveData();
  604. }
  605. });
  606. const btnSaveSetting = document.querySelector('#btn-save-setting');
  607. const iptPosition = document.getElementById('ipt-position-bookmark');
  608. const iptHidedelay = document.getElementById('ipt-hidedelay-bookmark');
  609. const iptMargin = document.getElementById('ipt-margin-bookmark');
  610. const iptAnimation = document.getElementById('ipt-animation-bookmark');
  611. const iptSize = document.getElementById('ipt-size-bookmark');
  612. const iptAlign = document.getElementById('ipt-align-bookmark');
  613. const iptMixed = document.getElementById('ipt-mixed-bookmark');
  614. btnSaveSetting.addEventListener('click', function () {
  615. config.position = iptPosition.value;
  616. config.hideDelay = iptHidedelay.value | 0;
  617. config.margin = iptMargin.value | 0;
  618. config.animation = iptAnimation.value === 'open';
  619. config.size = iptSize.value | 0;
  620. config.align = iptAlign.value;
  621. config.mixed = iptMixed.value;
  622. applyConfig();
  623. saveConfig();
  624. alert('保存成功');
  625. });
  626. const btnImport = document.getElementById('btn-import-bookmark');
  627. const btnExport = document.getElementById('btn-export-bookmark');
  628. const iptImport = document.getElementById('ipt-import-bookmark');
  629. iptImport.addEventListener('change', function () {
  630. const files = this.files;
  631.  
  632. if (files.length) {
  633. var reader = new FileReader();
  634.  
  635. reader.onload = e => {
  636. try {
  637. const obj = JSON.parse(e.target.result);
  638. data.list = obj.data;
  639. Object.assign(config, obj.config);
  640. applyConfig();
  641. initIpt();
  642. saveConfig();
  643. renderAll();
  644. saveData();
  645. alert('导入成功');
  646. } catch (err) {
  647. console.error(err);
  648. alert("\u5BFC\u5165\u5931\u8D25 ".concat(err.message));
  649. }
  650. };
  651.  
  652. reader.readAsText(files[0]);
  653. }
  654. });
  655. btnExport.addEventListener('click', function () {
  656. try {
  657. const obj = {
  658. data: data.list,
  659. config: config
  660. };
  661. tryDownload(JSON.stringify(obj, null, 2), 'GBF-Bookmark-Config.json');
  662. } catch (e) {
  663. console.error(e);
  664. }
  665. });
  666. }
  667.  
  668. const recordTime = () => {
  669. localStorage.setItem('gbf-bookmark:time', Date.now());
  670. };
  671.  
  672. const getTime = () => {
  673. let time = 0;
  674.  
  675. try {
  676. const _time = parseInt(localStorage.getItem('gbf-bookmark:time'), 10);
  677.  
  678. if (_time) time = _time;
  679. } catch (e) {}
  680.  
  681. return time;
  682. };
  683.  
  684. const parentElmt = () => {
  685. // let elmt = document.getElementById('mobage-game-container')
  686. // if (!elmt) elmt = document.body
  687. // return elmt
  688. return document.body;
  689. };
  690.  
  691. const sleep = time => {
  692. return new Promise((resolve, reject) => {
  693. setTimeout(resolve, time);
  694. });
  695. };
  696.  
  697. const waitDeviceRatio = async () => {
  698. if (typeof deviceRatio === 'number') {
  699. return deviceRatio;
  700. } else {
  701. await sleep(100);
  702. return await waitDeviceRatio();
  703. }
  704. };
  705.  
  706. const applyRatio = async () => {
  707. await waitDeviceRatio();
  708. const elemt1 = document.getElementById('show-setting-bookmark');
  709. const elemt2 = document.getElementById('gbf-bookmark-lacia');
  710. const elemt3 = document.getElementById('gbf-bookmark-setting');
  711. elemt1.style.zoom = deviceRatio;
  712. elemt2.style.zoom = deviceRatio;
  713. elemt3.style.zoom = deviceRatio;
  714. };
  715.  
  716. const main = () => {
  717. try {
  718. const html = tempalte(data.list);
  719. parentElmt().insertAdjacentHTML('beforeend', html);
  720. const container = document.getElementById('gbf-bookmark-lacia');
  721. const time = getTime();
  722. let hideTimer;
  723.  
  724. const delayHide = () => {
  725. if (config.hideDelay <= 0) return;
  726. clearTimeout(hideTimer);
  727. hideTimer = setTimeout(() => {
  728. container.style.opacity = 0;
  729. }, config.hideDelay * 1000);
  730. };
  731.  
  732. container.addEventListener('mouseenter', function () {
  733. if (config.hideDelay <= 0) return;
  734. recordTime();
  735. clearTimeout(hideTimer);
  736. container.style.opacity = 1;
  737. });
  738. container.addEventListener('mouseleave', function () {
  739. if (config.hideDelay <= 0) return;
  740. recordTime();
  741. delayHide();
  742. });
  743. event();
  744. initIpt();
  745. applyConfig();
  746.  
  747. if (Date.now() - time > config.hideDelay * 1000 && config.hideDelay > 0) {
  748. container.style.opacity = 0;
  749. } else {
  750. delayHide();
  751. }
  752.  
  753. applyRatio();
  754. } catch (e) {
  755. console.error(e);
  756. }
  757. };
  758.  
  759. let win = window.unsafeWindow || window;
  760.  
  761. if (win.document.readyState != 'loading') {
  762. main();
  763. } else {
  764. win.addEventListener('DOMContentLoaded', main);
  765. }
  766.  
  767. }());

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址