Anime Website Buttons Plus

A script that adds buttons on Anime Planet, MAL and Anilist for searching various sites.

当前为 2020-03-26 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @author Deathwing
  3. // @name Anime Website Buttons Plus
  4. // @include https://www.anime-planet.com/anime/*
  5. // @include http://myanimelist.net/anime/*
  6. // @include https://myanimelist.net/anime/*
  7. // @include https://anilist.co/anime/*
  8. // @exclude https://www.anime-planet.com/anime/
  9. // @exclude https://www.anime-planet.com/anime/all?name=*
  10. // @exclude https://www.anime-planet.com/anime/recommendations/*
  11. // @description A script that adds buttons on Anime Planet, MAL and Anilist for searching various sites.
  12. // @version 2.500
  13. // @grant GM_setValue
  14. // @grant GM_getValue
  15. // @grant GM_listValues
  16. // @grant GM_deleteValue
  17. // @namespace https://greasyfork.org/users/18375
  18. // ==/UserScript==
  19.  
  20.  
  21. //Find h1
  22. var header;
  23. var host = document.location.host;
  24. var malHost = 'myanimelist.net';
  25. var apHost = 'www.anime-planet.com';
  26. var alHost = 'anilist.co';
  27.  
  28. var hideList = [];
  29.  
  30. var buttDivLeft = 0;
  31. var autoHide = GM_getValue('setting:autoHide', false);
  32.  
  33. var iconEyeGray = 'https://previews.dropbox.com/p/thumb/AAuWCCOL6JyGmMweL1F-_5DiAS2zJYRa5Lir0SbwC5DvS_0nQEwjuJvONWL8a5aBxxvBhMbmATHXk6HOq_p16qq_FCjHezpZK-WG59CrRBfTl2mY7-e1lE-Ce2r1JEgpQFmo0LllAXnpcbeH7-68AxkfuMN4g6ChfpHCoaX7r9YH8MCQVu01ect1cCdqHDYlJBqgRWUrbTjwrlIlV9Y545Eldz5Xp948EIoHnNVeov_ybS2u-oGDZWwFtN5FLGCtJTyXK2sLylpQ8cvH7DVl0DAVcGO0YF6_RqIwbCpt-yCS58gfClH3lTEmPKunqrBwfNQe0SxXvyXTr-1GbCDiP_Lq/p.png?size=2048x1536&size_mode=3';
  34. var iconEye = 'https://previews.dropbox.com/p/thumb/AAvAf0hVyAwc9SRprGbA731CezYJ5amifW_2ApUxlRa0i98WlQoS13M3EQNGLv9kNTHsle6RsiUTlNZPtimWZM1ccs4i0orerrn0SwuPcsaGnU0cKho2IWWE-mEAhhoh779w04r8yWqJrAZZcYiy1mLZINV6SKIRq797-RW0gsZXZ8tgvcWa_nIAF2cpttnklJ93I0h2FFtmlrdX7WCzUBo2eML71mGMfRebI4b9wYnfFNT_77xWPeA1RoOaFLkYBKWF3wIsfnSCVGjodq_yHC6xjJJ2mwSbiRxuTO0glpiiT0AGN3hUTD0th5IbY5EPF-R4H1zPJMnPScAKax9RlrW5/p.png?fv_content=true&size_mode=5';
  35. var arrowIcon = 'https://previews.dropbox.com/p/thumb/AAu9RWVjB27yYf1IBTB2kIUi34QfZswYDWKQ4e5_vutzZSLP6q0ju6FtFEo6uqIoRbIy3yS2DxS6iiKhJP7rwtbbaWmNqdFBA1gmw4Xk7wAU3stUxDgxTXfGPW5lAI6af3ndevX2PRm4aqPcE_jcvWtP6CdKGOCW08b1ej4dxF6i62M97T96fered6dQYu7xw8HtuXsuHG1wndmjr71iwgGYOa40ucoHunZ-SkPiUqy6PQkG3frzFn8fTvaee1gR_8Jx5Be_lwh3A9so8ZvCaODcjuJYL54OzfUm9o19jKbpWVEnDQuwMIACydwIbxmRxy8IOtPzVm303mOT8Y1rONnT/p.png?size=2048x1536&size_mode=3';
  36. var editIcon = 'https://previews.dropbox.com/p/thumb/AAs_uEIlA0XGqQKA3-9SaVvSNTEfLD9T59ZRlYGPzHmrabhLYbrFL_7v07jrFvFwmHhfCyYTmwFjeC-00XVF7LE4zkSnA7q1f_dvUrhH-M9rDEL7ZaqzQLC_2lO3oxevjm235o8NS3R3-fBVijSrtHcdKgG_0B3FnCEYM5LHkvZO6P0HbrQQ2gmwo4m4JE4EbD44oSCMXcGqy0kU5kzBtKFgbP57Cv-k9HHw3SnNNsFiPC9HGRIiYA9PhCAjxFzy8gRFJlWwR5V7iIJJq9-ImQ_FLxlX_bn27k7IexLJvWHaf4UmK3nifCisIb0oMVUeyBfBhXd04kIVfmwFnwXgjnud/p.png?size=2048x1536&size_mode=3';
  37.  
  38.  
  39. if (host === apHost) {
  40. header = getHeader("#siteContainer h1");
  41. main();
  42. }
  43. else if (host === malHost) {
  44. header = getHeader('#contentWrapper span span');
  45. main();
  46. }
  47. else if (host === alHost) {
  48. getAlHeader();
  49. }
  50.  
  51. function getAlHeader() {
  52. header = getHeader('div.content h1');
  53.  
  54. if (header) {
  55. main();
  56. }
  57. else {
  58. setTimeout(getAlHeader, 500);
  59. }
  60. }
  61.  
  62. function getHeader(atr) {
  63. return document.querySelector(atr);
  64. }
  65.  
  66.  
  67. function main() {
  68.  
  69. //Cut anime name
  70. var animeName;
  71.  
  72. if (host === apHost) {
  73. animeName = getAnimeName();
  74. }
  75. else if (host === malHost) {
  76. animeName = header.childNodes[0].nodeValue;
  77. }
  78. else if (host === alHost) {
  79. animeName = getAnimeName();
  80. }
  81.  
  82.  
  83. function getAnimeName() {
  84. return header.textContent.trim();
  85. }
  86.  
  87.  
  88. function creteButton(icon, searchUrl, title, isStock) {
  89. var buttImg = createHTMLElement("img", null, null, [{ n: 'style', v: 'width:16px;height:16px;margin-right:2px;' }]);
  90.  
  91. if (icon) {
  92. buttImg.src = icon;
  93. }
  94. else {
  95. buttImg.src = getIconUrl(searchUrl);
  96. }
  97.  
  98. var button = createHTMLElement("a", null, 'animeButton', [{ n: 'id', v: `animeButton${makeButtonId(title)}` },
  99. { n: 'href', v: searchUrl }, { n: 'target', v: "_blank" }, { n: 'title', v: title }]);
  100.  
  101. if (isStock) {
  102. button.className += ' stockButton';
  103. }
  104. button.appendChild(buttImg);
  105. return button;
  106. }
  107.  
  108. //Set buttons with information
  109.  
  110. var buttonCounter = 0;
  111.  
  112. //MAL Button
  113. var icon = '';
  114. var searchUrl = 'http://myanimelist.net/anime.php?q=' + animeName;
  115. var title = "Search MyAnimeList";
  116.  
  117. var malButton = creteButton(icon, searchUrl, title, true);
  118.  
  119.  
  120. //Anilist Button
  121. searchUrl = 'https://anilist.co/search/anime?search=' + animeName + '&sort=SEARCH_MATCH';
  122. title = "Search Anilist";
  123.  
  124. var alButton = creteButton(icon, searchUrl, title, true);
  125.  
  126.  
  127. //Anime-Planet Button
  128. searchUrl = 'https://www.anime-planet.com/anime/all?name=' + animeName;
  129. title = "Search Anime-Planet";
  130.  
  131. var apButton = creteButton(icon, searchUrl, title, true);
  132.  
  133.  
  134. //YouTube Button
  135. searchUrl = 'https://www.youtube.com/results?search_query=' + animeName + " trailer";
  136. title = 'YouTube Trailer';
  137.  
  138. var ytButton = creteButton(icon, searchUrl, title, true);
  139.  
  140.  
  141. //Google Images button
  142. searchUrl = 'https://www.google.com/search?tbm=isch&biw=&bih=&gbv=2&q=' + animeName;
  143. title = "Search with Google Images";
  144.  
  145. var giButton = creteButton(icon, searchUrl, title, true);
  146.  
  147.  
  148. //Nyaa button
  149. searchUrl = 'https://nyaa.si/?f=0&c=0_0&q=' + animeName;
  150. title = "Search Nyaa";
  151.  
  152. var nyButton = creteButton(icon, searchUrl, title, true);
  153.  
  154.  
  155. //KissAnime button
  156. searchUrl = 'https://kissanime.ru/Search/Anime?keyword=' + animeName;
  157. title = "Search KissAnime";
  158.  
  159. var kaButton = creteButton(icon, searchUrl, title, true);
  160.  
  161.  
  162. //Edit button
  163. title = "Edit Custom Buttons";
  164.  
  165. var arrowButtonImg = createHTMLElement('img', null, 'arrowButton', [{ n: 'src', v: arrowIcon }, { n: 'title', v: title },
  166. { n: 'style', v: 'width:16px;height:16px;transition: all 0.3s linear 0s;left:-18px;position: relative;' }]);
  167. var editButtonImg = createHTMLElement('img', null, 'editButton', [{ n: 'src', v: editIcon }, { n: 'title', v: title },
  168. { n: 'style', v: 'width:16px;height:16px;transition: all 0.3s linear 0s;opacity:0;' }]);
  169. var editButton = createHTMLElement('div', null, null, [{ n: 'style', v: 'width:16px;height:16px;margin-right:2px;display:inline;' }]);
  170.  
  171. if (!autoHide) {
  172. editButtonImg.style.opacity = '1';
  173. arrowButtonImg.style.opacity = '0';
  174. }
  175.  
  176. header.addEventListener('mouseover', showEditButton);
  177. header.addEventListener('mouseout', hideEditButton);
  178.  
  179. appendChildren(editButton, [editButtonImg, arrowButtonImg]);
  180.  
  181. editButton.addEventListener('click', editButtonHandler);
  182.  
  183.  
  184. var customButtons = [];
  185. var customButtonsObj = [];
  186.  
  187. if (!(GM_listValues()).includes('setting:buttonsNames')) {
  188. var values = GM_listValues();
  189. for (var i = 0; i < values.length; i++) {
  190. if (!values[i].includes('setting:')) {
  191. customButtonsObj.push(JSON.parse(GM_getValue(values[i])));
  192. GM_deleteValue(values[i]);
  193. }
  194. }
  195.  
  196. setAnimeButtonsToStorage(customButtonsObj);
  197. }
  198. else {
  199. customButtonsObj = getAnimeButtonsFromStorage();
  200. }
  201.  
  202. customButtonsObj.forEach((b) => {
  203. customButtons.push(creteButton(b.icon, b.url.replace('ANIMENAME', animeName), b.title));
  204. });
  205.  
  206.  
  207.  
  208. //Add Website Buttons
  209. if (host === apHost) {
  210. appendButtons([malButton, alButton]);
  211. }
  212. else if (host === alHost) {
  213. appendButtons([malButton, apButton]);
  214. }
  215. else if (host === malHost) {
  216. appendButtons([apButton, alButton]);
  217. }
  218.  
  219.  
  220. function appendButtons(buttonsArray) {
  221. header.appendChild(document.createTextNode(" "));
  222.  
  223. var otherButtons = [ytButton, giButton, nyButton, kaButton];
  224. var allButtons = buttonsArray.concat(otherButtons, customButtons, editButton);
  225. var buttonsDiv = createHTMLElement('div', null, 'animeButtons', [{ n: 'style', v: 'position:relative;transition: all 0.4s cubic-bezier(0.79, 0.88, 0.16, 0.98) 0s;' }]);
  226. var outerButtonsDiv = createHTMLElement('div', null, null, [{ n: 'style', v: 'display:inline-block;position:relative;overflow:hidden;' }]);
  227.  
  228. outerButtonsDiv.appendChild(buttonsDiv);
  229. appendChildren(buttonsDiv, allButtons);
  230.  
  231. allButtons.forEach((b) => {
  232. if (b.id !== '') {
  233. hideList.push({ bId: b.id, h: 'show' });
  234. }
  235. });
  236.  
  237. header.appendChild(outerButtonsDiv);
  238.  
  239. getHideList();
  240. hideButtons();
  241. addButtonPopup();
  242. hideEditButton();
  243. }
  244.  
  245.  
  246.  
  247.  
  248. function getHideList() {
  249. var hideListNew;
  250. if ((GM_listValues()).includes('hideList')) {
  251. hideListNew = GM_getValue('hideList', '[]');
  252. GM_deleteValue('hideList');
  253. }
  254. else {
  255. hideListNew = GM_getValue('setting:hideList', '[]');
  256. }
  257.  
  258. if (!hideListNew || hideListNew === undefined || hideListNew === 'undefined') {
  259. hideListNew = '[]';
  260. }
  261. concatHideList(JSON.parse(hideListNew));
  262. }
  263.  
  264. function concatHideList(v) {
  265. v.forEach(b => {
  266. var item = hideList.find(n => n.bId === b.bId);
  267. if (item) { return Object.assign(item, b); }
  268. hideList.push(b);
  269. });
  270. }
  271.  
  272. function hideButtons() {
  273. buttDivLeft = 0;
  274.  
  275. hideList.forEach((o) => {
  276. var button = document.querySelector(`#${o.bId}`);
  277.  
  278. if (button) {
  279. if (o.h === 'show') {
  280. button.style.display = '';
  281. buttDivLeft++;
  282. }
  283. else if (o.h === 'hide') {
  284. button.style.display = 'none';
  285. }
  286. }
  287. });
  288. }
  289.  
  290. function makeButtonId(buttonName) {
  291. var result = 0;
  292. for (var i = 0; i < buttonName.length; i++) {
  293. result += buttonName.charCodeAt(i);
  294. }
  295.  
  296. result *= buttonName.charCodeAt(buttonName.length - 1);
  297.  
  298. return result;
  299. }
  300.  
  301.  
  302. function editButtonHandler(e) {
  303. togglePopup(true);
  304. }
  305.  
  306. function getPopup() {
  307. return document.querySelector('.buttonPopup');
  308. }
  309.  
  310. function showEditButton() {
  311. var editButton = document.querySelector('.editButton');
  312.  
  313. if (autoHide) {
  314. var arrowButton = document.querySelector('.arrowButton');
  315. var buttonsDiv = header.firstElementChild.firstElementChild;
  316. buttonsDiv.style.left = '0%';
  317. arrowButton.style.opacity = '0';
  318. }
  319.  
  320. editButton.style.opacity = '1';
  321. }
  322.  
  323. function hideEditButton() {
  324. var editButton = document.querySelector('.editButton');
  325.  
  326. if (autoHide) {
  327. var buttonsDiv = header.firstElementChild.firstElementChild;
  328. var arrowButton = document.querySelector('.arrowButton');
  329. buttonsDiv.style.left = `-${buttDivLeft * 18}px`;
  330. arrowButton.style.opacity = '1';
  331. }
  332.  
  333. editButton.style.opacity = '0';
  334. }
  335.  
  336. function addAndCancelButtonsHandler(e) {
  337. var targetEl = e.target;
  338.  
  339. if (targetEl.className === 'addButton') {
  340. addButtonLogic(GM_listValues());
  341. }
  342. else if (targetEl.className === 'cancelButton') {
  343. togglePopup(false);
  344. }
  345. else if (targetEl.className === 'deleteButton') {
  346. GM_deleteValue(document.querySelector('.titleInput').value);
  347. togglePopup(false);
  348. }
  349. }
  350.  
  351. function addAndEditTabButtonsHandler(e) {
  352. var target = e.target;
  353.  
  354. if (target.className.includes('Text')) {
  355. target = e.target.parentElement;
  356. }
  357.  
  358. if (target.className === 'addTab' && target.style.color === 'white') {
  359. var editTab = target.parentElement.children[1];
  360. hideTabSection(editTab, target);
  361. }
  362. else if (target.className === 'editTab' && target.style.color === 'white') {
  363. var addTab = target.parentElement.firstElementChild;
  364. hideTabSection(addTab, target);
  365. }
  366. }
  367.  
  368. function hideTabSection(toHide, toShow) {
  369. toHide.style.color = 'white';
  370. toHide.style.backgroundColor = '#d8d8d8';
  371. toShow.style.color = 'black';
  372. toShow.style.backgroundColor = 'white';
  373.  
  374. var sectionToHide;
  375. var sectionToShow;
  376.  
  377. if (toHide.className === 'addTab') {
  378. sectionToHide = document.querySelector('.addSection');
  379. sectionToShow = document.querySelector('.editSection');
  380. }
  381. else {
  382. sectionToHide = document.querySelector('.editSection');
  383. sectionToShow = document.querySelector('.addSection');
  384. }
  385.  
  386. sectionToHide.style.opacity = '0';
  387.  
  388. setTimeout(() => {
  389. sectionToHide.style.display = 'none';
  390. }, 200);
  391.  
  392. setTimeout(() => {
  393. sectionToShow.style.display = 'block';
  394. setTimeout(() => sectionToShow.style.opacity = '1', 50);
  395. }, 200);
  396. }
  397.  
  398. function togglePopup(v) {
  399. var popUp = getPopup();
  400.  
  401. if (v) {
  402. header.removeEventListener('mouseout', hideEditButton);
  403. popUp.style.opacity = '1';
  404. popUp.style.top = '50%';
  405. }
  406. else {
  407. header.addEventListener('mouseout', hideEditButton);
  408. hideEditButton();
  409. popUp.style.opacity = '0';
  410. popUp.style.top = '-100%';
  411. }
  412. }
  413.  
  414. function getAnimeButtonsFromStorage() {
  415. return JSON.parse(GM_getValue('setting:buttonsNames', '[]'));
  416. }
  417.  
  418. function setAnimeButtonsToStorage(buttonsNames) {
  419. GM_setValue('setting:buttonsNames', JSON.stringify(buttonsNames));
  420. }
  421.  
  422. function addButtonLogic(valuesList) {
  423. var titleField = document.querySelector('.titleInput');
  424. var searchField = document.querySelector('.URLInput');
  425. var iconField = document.querySelector('.iconInput');
  426.  
  427. var buttonsNames = getAnimeButtonsFromStorage();
  428.  
  429. if (titleField.value === '') {
  430. toggleMsgBox(true, 'Title cannot be empty!', false);
  431. }
  432. else if (searchField.value === '') {
  433. toggleMsgBox(true, 'Search URL cannot be empty!', false);
  434. }
  435. else if (buttonsNames.find((o) => o.title === titleField.value)) {
  436. toggleMsgBox(true, 'Button with the same name already exists!', false);
  437. }
  438. else {
  439. if (iconField.value === '') {
  440. iconField.value = getIconUrl(searchField.value);
  441. }
  442.  
  443. var newButton = {
  444. title: titleField.value,
  445. url: searchField.value,
  446. icon: iconField.value
  447. };
  448.  
  449. buttonsNames.push(newButton);
  450.  
  451. setAnimeButtonsToStorage(buttonsNames);
  452.  
  453. toggleMsgBox(true, `Button ${titleField.value} added succsessfully! Reload to see it!`, true);
  454.  
  455. hideList.push({ bId: `animeButton${makeButtonId(titleField.value)}`, h: 'show' });
  456. GM_setValue('setting:hideList', JSON.stringify(hideList));
  457.  
  458. titleField.value = '';
  459. searchField.value = '';
  460. iconField.value = '';
  461. }
  462. }
  463.  
  464. function getIconUrl(fromUrl) {
  465. var regex = /(?:https?:\/\/)(w{0,3}\.?[\s\S]+?\.\w+)\//;
  466. var result = '';
  467.  
  468. if (regex.test(fromUrl)) {
  469. result = `https://www.google.com/s2/favicons?domain=${fromUrl.match(regex)[1]}`;
  470. }
  471.  
  472. return result;
  473. }
  474.  
  475. function toggleMsgBox(toggle, msg, showReload) {
  476. var msgBox = document.querySelector('.addMsgBox');
  477.  
  478. if (msg) {
  479. msgBox.firstElementChild.textContent = msg;
  480. }
  481.  
  482. if (showReload) {
  483. msgBox.children[1].style.display = 'inline';
  484. }
  485. else {
  486. msgBox.children[1].style.display = 'none';
  487. }
  488.  
  489. if (toggle) {
  490. msgBox.style.opacity = '1';
  491. msgBox.style.bottom = '15%';
  492. }
  493. else {
  494. msgBox.style.opacity = '0';
  495. setTimeout(() => { msgBox.style.bottom = '150%'; }, 250);
  496. }
  497. }
  498.  
  499. function hideAndDeleteHandler(e) {
  500. var target = e.target;
  501. var buttParent = target.parentElement;
  502. var button = document.querySelector(`#${buttParent.className}`);
  503.  
  504. if (target.className === "removeButton") {
  505. button.remove();
  506. target.parentElement.remove();
  507. var buttonsObjs = getAnimeButtonsFromStorage();
  508. buttonsObjs = buttonsObjs.filter((o) => buttParent.textContent !== o.title);
  509. setAnimeButtonsToStorage(buttonsObjs);
  510. hideList = hideList.filter(obj => obj.bId !== button.id);
  511.  
  512. GM_setValue('setting:hideList', JSON.stringify(hideList));
  513. }
  514. else if (target.className === 'hideButton') {
  515. if (button.style.display === 'none') {
  516. button.style.display = '';
  517. concatHideList([{ bId: button.id, h: 'show' }]);
  518. target.setAttribute('src', iconEye);
  519. }
  520. else {
  521. button.style.display = 'none';
  522. concatHideList([{ bId: button.id, h: 'hide' }]);
  523. target.setAttribute('src', iconEyeGray);
  524. }
  525.  
  526. GM_setValue('setting:hideList', JSON.stringify(hideList));
  527.  
  528. hideButtons();
  529. }
  530. }
  531.  
  532. function msgButtonsHandler(e) {
  533. var target = e.target;
  534.  
  535. if (target.className === 'reloadButton') {
  536. location.reload();
  537. }
  538. else if (target.className === 'closeButton') {
  539. toggleMsgBox(false);
  540. }
  541. }
  542.  
  543. function settingsHandler(e) {
  544. var target = e.target;
  545.  
  546. if (target.className === 'editCheckbox') {
  547. autoHide = target.checked;
  548. GM_setValue('setting:autoHide', autoHide);
  549. }
  550. }
  551.  
  552. function popupClickHandler(e) {
  553. if (!e.target.className.includes('infoBox')) {
  554. var infoBoxes = document.querySelectorAll('.infoBox');
  555. infoBoxes.forEach(b => {
  556. if (b.style.opacity === '1') {
  557. hideInfoBox(b);
  558. }
  559. });
  560. }
  561. }
  562.  
  563. function URLQuestionmarkHandler(e) {
  564. showInfoBox(e.target.parentElement.lastElementChild);
  565. var iconInfoBox = document.querySelector('.iconInfoBox');
  566. hideInfoBox(iconInfoBox);
  567. }
  568.  
  569. function iconQuestionmarkHandler(e) {
  570. showInfoBox(e.target.parentElement.lastElementChild);
  571. var URLInfoBox = document.querySelector('.URLInfoBox');
  572. hideInfoBox(URLInfoBox);
  573. }
  574.  
  575. function hideInfoBox(infoBox) {
  576. infoBox.style.opacity = '0';
  577. setTimeout(() => infoBox.style.display = 'none', 300);
  578. }
  579.  
  580. function showInfoBox(infoBox) {
  581. infoBox.style.display = 'inline-block';
  582. setTimeout(() => infoBox.style.opacity = '1', 100);
  583. }
  584.  
  585. function addButtonPopup() {
  586. var questionmarkIcon = 'https://previews.dropbox.com/p/thumb/AAs9PpoNBbIv4yP0RKqnNKTZEYjDtwtWT-24ZkhGOTR9w-CeCdnwqQFvjYSk4YJM8SPo7Pi85ndYpE5ZsJ85Zysho9UfAcqaVYATZ_2UW-y7JtKdKiu1Y7jmPVb9Gv5fRLw20phAXqhEx7EbC6JsRkBvZ6aujPDiiEg8-X0F41jb-wFJ-DW9vrSMOVGyM4dHIxaQNcuCcESUAc6sCfD9Y7iKR3SVd7tWfcAp9SquCdf6aFTIOVXNASu_jFM35cRNpPOQ-i3kO32mPLs98SGDNjszVPGsCBeUKQE6BKnKMb_PVT7l-rx6C1QY6W_VejIUHOtt7_ID4xuFjgLqGSNRpfC6/p.png?size=2048x1536&size_mode=3';
  587.  
  588. var style = 'margin:auto;text-align: center;display:block;margin-bottom: 5px;';
  589. var popUp = createHTMLElement('div', null, 'buttonPopup', [{ n: 'style', v: 'position:absolute;top:-100%;left:50%;margin-top:-280px;margin-left:-200px;background-color:white;width:400px;height:560px;box-shadow: 0 0 15px rgba(0, 0, 0, 0.4);border-radius: 8px;font-size:medium;z-index:9999;opacity:0;transition: all 0.7s cubic-bezier(0.45, -0.24, 0.43, 1.14) 0s;' }]);
  590.  
  591. var tabs = createHTMLElement('div', null, 'popupTabs', [{ n: 'style', v: 'width: 100%;height: 40px;' }]);
  592. var addTab = createHTMLElement('div', null, 'addTab', [{ n: 'style', v: 'height: 100%;width: 50%;background-color: white;left: 50%;border-top-left-radius: 8px;text-align: center;transition: all 0.2s linear 0s;' }]);
  593. var textTabsStyle = 'position: relative;top: 11px;font-weight: bold;';
  594. var addTabText = createHTMLElement('div', 'ADD', 'addTabText', [{ n: 'style', v: textTabsStyle }]);
  595. addTab.appendChild(addTabText);
  596.  
  597. var editTab = createHTMLElement('div', null, 'editTab', [{ n: 'style', v: 'top: -40px;height: 100%;width: 50%;background-color: #d8d8d8;left: 50%;position: relative;border-top-right-radius: 8px;text-align: center;color: white;transition: all 0.2s linear 0s;' }]);
  598. var editTabText = createHTMLElement('div', 'EDIT', 'editTabText', [{ n: 'style', v: textTabsStyle }]);
  599. editTab.appendChild(editTabText);
  600.  
  601. appendChildren(tabs, [addTab, editTab]);
  602.  
  603. var addSection = createHTMLElement('div', null, 'addSection', [{ n: 'style', v: 'height:100%;width:100%;transition: all 0.2s linear 0s;' }]);
  604. var addSectionTitle = createHTMLElement('h2', 'ADD CUSTOM BUTTON', null, [{ n: 'style', v: style + 'margin-top: 25px' }]);
  605. var title = createHTMLElement('h3', 'Title', null, [{ n: 'style', v: style + 'margin-top: 20px' }]);
  606. var titleInput = createHTMLElement('input', null, 'titleInput', [{ n: 'placeholder', v: 'Button title' }, { n: 'style', v: style }]);
  607. var URLTitle = createHTMLElement('h3', 'Search URL', null, [{ n: 'style', v: style + 'margin-top: 20px' }]);
  608. var URLQm = createHTMLElement('img', null, 'URLQuestionmark questionmark', [{ n: 'src', v: questionmarkIcon }, { n: 'style', v: 'heaight:16px;width:16px;margin-left:5px;' }]);
  609. var URLInfoBox = createHTMLElement('div', 'To get the search URL first go the site you want to add and search the term "ANIMENAME" in the search field. Then copy the full URL (including http://) in the field below. (exaple: https://myanimelist.net/search/all?q=ANIMENAME)', 'URLInfoBox infoBox', [{ n: 'style', v: 'width: 90%;display: inline-block;position: absolute;margin-left: 10px;background-color: white;border-radius: 8px;box-shadow: rgba(0,0,0, 0.3) 0px 0px 10px;transition: opacity 0.3s linear;opacity: 0;padding: 10px;font-weight: normal;font-size: medium;' }]);
  610. appendChildren(URLTitle, [URLQm, URLInfoBox]);
  611. var URLInput = createHTMLElement('input', null, 'URLInput', [{ n: 'placeholder', v: 'Search URL' }, { n: 'style', v: style + 'width:80%' }]);
  612. var iconTitle = createHTMLElement('h3', 'Icon URL', null, [{ n: 'style', v: style + 'margin-top: 20px' }]);
  613. var iconQm = createHTMLElement('img', null, 'iconQuestionmark questionmark', [{ n: 'src', v: questionmarkIcon }, { n: 'style', v: 'heaight:16px;width:16px;margin-left:5px;' }]);
  614. var iconInfoBox = createHTMLElement('div', null, 'iconInfoBox infoBox', [{ n: 'style', v: 'width: 90%;display: inline-block;position: absolute;margin-left: 10px;background-color: white;border-radius: 8px;box-shadow: rgba(0,0,0, 0.3) 0px 0px 10px;transition: opacity 0.3s linear;opacity: 0;padding: 10px;font-weight: normal;font-size: medium;' }]);
  615. iconInfoBox.innerHTML = '(<b>Leave empty for automatic icon parse</b>)<br />Link to icon for the button. <br />The easiest way to get it is to copy this link "https://www.google.com/s2/favicons?domain=" and place the website url at the end (example: https://www.google.com/s2/favicons?domain=myanimelist.net).';
  616. appendChildren(iconTitle, [iconQm, iconInfoBox]);
  617. var iconInput = createHTMLElement('input', null, 'iconInput', [{ n: 'placeholder', v: 'Icon URL' }, { n: 'style', v: style + 'width:80%' }]);
  618.  
  619. var msgBoxDiv = createHTMLElement('div', null, 'addMsgBox', [{ n: 'style', v: 'width: 86%;position: absolute;margin-left: 7%;bottom: 150%;background-color: white;border-radius: 8px;box-shadow: rgba(0,0,0, 0.4) 0px 0px 15px;text-align: center;transition: opacity 0.2s linear;opacity:0' }]);
  620. var msgText = createHTMLElement('div', 'Button added succsessfully! Reload to see it!', 'addMgsText', [{ n: 'style', v: 'margin: 10px;' }]);
  621. var reloadButton = createHTMLElement('button', 'RELOAD', 'reloadButton', [{ n: 'style', v: 'margin: 10px;margin-right:0px;width:90px;' }]);
  622. var closeButton = createHTMLElement('button', 'CLOSE', 'closeButton', [{ n: 'style', v: 'margin: 10px;width:90px;' }]);
  623. appendChildren(msgBoxDiv, [msgText, reloadButton, closeButton]);
  624.  
  625. var buttonsDiv = createHTMLElement('div', null, 'addAndCancelButtons', [{ n: 'style', v: style + 'bottom:10px;position:absolute;width:100%' }]);
  626. var addButton = createHTMLElement('button', 'ADD', 'addButton', [{ n: 'style', v: 'width:90px;margin:5px' }]);
  627. var cancelButton = createHTMLElement('button', 'CANCEL', 'cancelButton', [{ n: 'style', v: 'width:90px;margin:5px' }]);
  628.  
  629. var editSection = createHTMLElement('div', null, 'editSection', [{ n: 'style', v: 'height:100%;width:100%;display:none;transition: all 0.2s linear 0s;' }]);
  630. var editSectionTitle = createHTMLElement('h2', 'EDIT CUSTOM BUTTONS', null, [{ n: 'style', v: style + 'margin-top: 25px' }]);
  631. var animeButtonsList = createHTMLElement('ul', null, 'buttonsList', [{ n: 'style', v: 'list-style: none;margin-top: 25px;padding-left: 40px;overflow: hidden;overflow-y: auto;height: 340px;' }]);
  632. var animeButtons = document.querySelectorAll('.animeButton');
  633.  
  634. var settingsDiv = createHTMLElement('div', null, 'settingsDiv', [{ n: 'style', v: 'padding: 0px 30px;' }]);
  635. var hideEditCheckbox = createHTMLElement('input', null, 'editCheckbox', [{ n: 'id', v: 'editCheckbox' }, { n: 'type', v: 'checkbox' }, { n: 'value', v: 'editCheckbox' }]);
  636.  
  637. if (autoHide){
  638. hideEditCheckbox.setAttribute('checked', true);
  639. }
  640. var hideEditCheckboxLabel = createHTMLElement('label', 'Auto hide buttons (show on mouseover)', null, [{ n: 'for', v: 'editCheckbox' }, { n: 'style', v: 'padding-left:5px;' }]);
  641. appendChildren(settingsDiv, [hideEditCheckbox, hideEditCheckboxLabel]);
  642.  
  643. var editButtonsDiv = createHTMLElement('div', null, 'addAndCancelButtons', [{ n: 'style', v: style + 'bottom:10px;position:absolute;width:100%' }]);
  644. var cancelButtonEdit = createHTMLElement('button', 'CLOSE', 'cancelButton', [{ n: 'style', v: 'width:90px;margin:5px' }]);
  645. editButtonsDiv.appendChild(cancelButtonEdit);
  646.  
  647. createAndAppendEditListEntry(animeButtonsList, animeButtons);
  648.  
  649. popUp.appendChild(tabs);
  650. appendChildren(buttonsDiv, [addButton, cancelButton]);
  651. appendChildren(addSection, [addSectionTitle, title, titleInput, URLTitle, URLInput, iconTitle, iconInput, msgBoxDiv, buttonsDiv]);
  652.  
  653. appendChildren(editSection, [editSectionTitle, animeButtonsList, settingsDiv, editButtonsDiv]);
  654.  
  655. appendChildren(popUp, [addSection, editSection]);
  656. var html = document.querySelector('html');
  657. html.appendChild(popUp);
  658.  
  659. buttonsDiv.addEventListener('click', addAndCancelButtonsHandler);
  660. editButtonsDiv.addEventListener('click', addAndCancelButtonsHandler);
  661. tabs.addEventListener('click', addAndEditTabButtonsHandler);
  662. animeButtonsList.addEventListener('click', hideAndDeleteHandler);
  663. msgBoxDiv.addEventListener('click', msgButtonsHandler);
  664. settingsDiv.addEventListener('click', settingsHandler);
  665. URLQm.addEventListener('mouseover', URLQuestionmarkHandler);
  666. iconQm.addEventListener('mouseover', iconQuestionmarkHandler);
  667. popUp.addEventListener('click', popupClickHandler);
  668. }
  669.  
  670. function createAndAppendEditListEntry(animeButtonsList, animeButtons) {
  671. animeButtons.forEach((b) => {
  672. var listEl = createHTMLElement('li', null, b.id, [{ n: 'style', v: 'width:90%;margin-top:5px;border-bottom-style: inset;border-bottom-width: thin;' }]);
  673. var imgUrl = b.firstElementChild.getAttribute('src');
  674. var img = createHTMLElement('img', null, null, [{ n: 'src', v: imgUrl }, { n: 'style', v: 'width: 16px;height: 16px;' }]);
  675. var hideIcon = createHTMLElement('img', null, 'hideButton', [{ n: 'src', v: iconEye }, { n: 'title', v: 'Toggle Hide' }, { n: 'style', v: 'height:16px;width:16px;position: relative;left: 82%;' }]);
  676. var removeIcon = createHTMLElement('img', null, 'removeButton', [{ n: 'src', v: 'https://previews.dropbox.com/p/thumb/AAv_J1gX163dhysBBA0GBSGRBMMdRoTT2EVqs_xTg5PdES0EF5geKh9gJg0kCbmtTGSzjkZFZQ6qCVpKFmUKobTWUTYu-t6yYVdWg_ldZE8GBUfXu0NWx3q0RfyeelWLgApIOskJParENLlfHXLyKT_FeTPtESh3rNqWCr-7iY1v_snaIZo5WsajqOSeUoJ3jS6M0_lD_PN410Xv-hUbqlNejWUNJDoWz9nkQdhzLX3bFpErrb75jnys7fwG8NV0YYL-HDOKCOFnh0MCviaq_r-YeioUpcwdxVXv9AnHdgsfGnTSmfVdgY6oG5nk0IOjDfYs_R9-3zcOz5pClF6-9uM6/p.png?fv_content=true&size_mode=5' }, { n: 'title', v: 'DELETE' }, { n: 'style', v: 'height:16px;width:16px;position: relative;left: 85%;' }]);
  677. var span = createHTMLElement('span', b.getAttribute('title'), null, [{ n: 'style', v: 'margin-left:5px;bottom: 2px;position: relative;right: 16px;' }]);
  678.  
  679. if (b.style.display === 'none') {
  680. hideIcon.setAttribute('src', iconEyeGray);
  681. }
  682.  
  683. appendChildren(listEl, [img, hideIcon, span]);
  684.  
  685. if (!b.className.includes('stockButton')) {
  686. listEl.insertBefore(removeIcon, span);
  687. span.style.right = '32px';
  688. }
  689. animeButtonsList.appendChild(listEl);
  690. });
  691. }
  692.  
  693. function createHTMLElement(tag, textContent, className, attributes) {
  694. var element = document.createElement(tag);
  695.  
  696. if (className) {
  697. element.className = className;
  698. }
  699. if (textContent) {
  700. element.textContent = textContent;
  701. }
  702. if (attributes) {
  703. attributes.forEach((a) => {
  704. element.setAttribute(a.n, a.v);
  705. });
  706. }
  707.  
  708. return element;
  709. }
  710.  
  711. function appendChildren(element, children) {
  712. children.forEach((c) => {
  713. element.appendChild(c);
  714. });
  715. }
  716. }