// ==UserScript== // @name Mangadex Plus // @namespace https://greasyfork.org/users/553660 // @icon https://mangadex.org/images/misc/navbar.svg // @version 1.2 // @description Adds extra features to Mangadex. These include: Custom Folders for Manga, Start Reading Button, Mark all Chapters as read/unread Button, Automatic Chapter Preloading & more to come! // @author Mr. M // @match https://mangadex.org/* // @grant GM_setValue // @grant GM_getValue // @grant GM_listValues // @grant GM_deleteValue // @downloadURL none // ==/UserScript== (function() { 'use strict'; /* Global values */ const domain = window.location.hostname; const url = window.location; const nVer = "1.2"; const current_user = document.getElementsByClassName("navbar-nav")[1].childNodes[3].childNodes[1].getAttribute("href").split("/")[2]; /* Debug override */ //var thumbnails_enabled = true; // Enable/Disable thumbnails feature //var thumbnails_ban = false; // Disable Thumb picture downloads var title_entry_duplication = false; // true = allow dupes /* Global functions */ // Get the domain from the visiting website function url_domain(data) { var a = document.createElement('a'); a.href = data; return a.hostname; } // Add a global CSS style by inputting a String function addGlobalStyle(css) { var head, style; head = document.getElementsByTagName('head')[0]; if (!head) { return; } style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = css; head.appendChild(style); } // Get site subpage name/directory from provided url function getSubPage(directoryIndex){ let url = document.location.href; var segment = url.replace(/^https?:\/\//, '').split('/')[directoryIndex]; return segment; } // Get current Url function currentUrl(){ return document.location.href; } /* Storage defaults */ let first_time; if (GM_getValue("first_time") != "false"){ first_time = false; GM_setValue("first_time", "false"); //GM_setValue("folders_index", 0); let folders = {"folders" : []}; GM_setValue("folders", JSON.stringify(folders)); let options = {"options" : [{"preloading" : 0}]}; GM_setValue("options", JSON.stringify(options)); alert("Thank you for installing Mangadex Plus! Please go to Settings -> About to learn more about Mangadex Plus!") } // Version check (last version / newest version) if (GM_getValue("version") != nVer && first_time == undefined){ GM_setValue("version", nVer); GM_setValue("update_notif", "true") alert("A feature update is here! MD+ has been updated to " + GM_getValue("version") + "! Check Change Log in MD+ Settings for more info!"); } var red_badge; if (GM_getValue("update_notif") == "true"){ GM_setValue("notif_badge", ' ! ') } else{ GM_setValue("notif_badge", '') } /* Site functions */ // Startup functions function startup(){ if (getSubPage(1) == "title"){ main("title"); } else if (getSubPage(1) == "chapter"){ main("chapter") } else{ main("other"); } } /* HTML Elements */ // Color categorizing CSS classes -> "badge" || "text" + "-" + "success"/"danger"/"primary"/nothing //let friends_icon = ''; //red_badge = ' ! '; //let green_badge = ' ! '; //let msg_icon = ''; let container = document.getElementsByTagName("body")[0]; let pageMask = '
'; let closeButton = ''; /* Functions and features */ function main(level){ let menuButton = ''; if (level == "title" || (level == "chapter" || level == "other")){ function mainButton(){ container.insertAdjacentHTML("afterbegin", menuButton); addGlobalStyle("#menuButton { position: fixed; z-index: 99999; top: 10px; right: 15px; list-style-type: none; border-radius: 0.25rem; padding: unset;}"); addGlobalStyle("p.dropdown-item { margin: 0px; }"); folders(); settings(); options(); } mainButton(); } if (level == "title"){ function cardButtons(){ } cardButtons(); actionsBar(); } if (level == "chapter"){ function readerFeatures(){ preload(); } readerFeatures(); } } function closeMenu(){ addGlobalStyle(".plus-entries-box { height: unset; overflow-y: unset;}"); try{ for(let i = 0; i < document.getElementsByClassName("plus-box").length; i++){ document.getElementsByClassName("plus-box")[i].remove(); } } catch(e){ console.log(e) throw e; } try{ for(let j = 0; j < document.getElementsByClassName("page-mask").length; j++){ document.getElementsByClassName("page-mask")[j].remove(); } for(let k = 0; k < document.getElementsByClassName("plus-clsBtn").length; k++){ document.getElementsByClassName("plus-clsBtn")[k].remove(); } addGlobalStyle("body { overflow: unset;"); } catch(e){ console.log(e) } try{ document.getElementsByClassName("plus-options-window")[0].remove(); document.getElementsByClassName("page-mask")[0].remove(); document.getElementsByClassName("plus-clsBtn")[0].remove(); addGlobalStyle("body { overflow: unset;"); } catch(e){ //console.log(e) } } function settings(){ let notes = "(*) This will restore default values for options.
" + "(**) This will wipe all Storage data (Folders and entries).
" + "(***) This will restore default values for options and wipe storage (Folders and entries)." let items = ''; function openSettingsMenu(){ container.insertAdjacentHTML("afterbegin", items); addGlobalStyle("div.plus-box { position: fixed !important; right: 700px !important; left: 700px !important; top: 100px !important; z-index: 100001;}"); container.insertAdjacentHTML("afterbegin", pageMask); addGlobalStyle(".page-mask { background: rgba(0, 0, 0, 0.5); position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 100000;}"); container.insertAdjacentHTML("afterbegin", closeButton); addGlobalStyle(".plus-clsBtn { right: 150px !important; position: fixed !important; z-index: 100000; width: auto; color: white; background-color: #444;}"); document.getElementsByClassName("page-mask")[0].addEventListener("click", closeMenu); document.getElementsByClassName("plus-clsBtn")[0].addEventListener("click", closeMenu); document.getElementsByClassName("plus-reset-wipe")[0].addEventListener("click", function(){resetMDP("rw")}); document.getElementsByClassName("plus-reset")[0].addEventListener("click", function(){resetMDP("r")}); document.getElementsByClassName("plus-wipe")[0].addEventListener("click", function(){resetMDP("w")}); document.getElementsByClassName("plus-change-log")[0].addEventListener("click", changeLog); document.getElementsByClassName("plus-about")[0].addEventListener("click", about); document.getElementsByClassName("plus-close")[0].addEventListener("click", closeMenu); addGlobalStyle("body { overflow: hidden;"); } function about(){ let text = "Welcome to Mangadex Plus!

" + "\"What is Mangadex Plus?\"
Mangadex Plus is a Userscript that adds some useful features to Mangadex.

" + "\"What are these Useful features you speak of?\"
These currently include:

" + "" + "

For more info on the features head to the Change Log. As of now these are all but more features will be added through time.

" + "\"I really want a feature to be added to this script! Do you take suggestions?\"
I do so Welcomely. Please go to the GreasyFork page of this Userscript and add a suggestion there.

" + "\"Hey! I found a bug! Where can I report It?\"
Please report bugs on the GreasyFork page of this Userscript" + " and I'll do my best to fix them ASAP.

" + '

To remove the red badge ( ! ) please reload the page.'; let element = '

'; closeMenu(); container.insertAdjacentHTML("afterbegin", element); addGlobalStyle("div.plus-box { position: fixed !important; right: 700px !important; left: 700px !important; top: 100px !important; z-index: 100001;}"); container.insertAdjacentHTML("afterbegin", pageMask); addGlobalStyle(".page-mask { background: rgba(0, 0, 0, 0.5); position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 100000;}"); container.insertAdjacentHTML("afterbegin", closeButton); addGlobalStyle(".plus-clsBtn { right: 150px !important; position: fixed !important; z-index: 100000; width: auto; color: white; background-color: #444;}"); document.getElementsByClassName("plus-back-settings")[0].addEventListener("click", function(){closeMenu(); settings(); openSettingsMenu();}); document.getElementsByClassName("page-mask")[0].addEventListener("click", closeMenu); document.getElementsByClassName("plus-clsBtn")[0].addEventListener("click", closeMenu); document.getElementsByClassName("plus-close")[0].addEventListener("click", closeMenu); addGlobalStyle("body { overflow: hidden;"); } function changeLog(){ GM_setValue("update_notif", "false"); //GM_setValue("notif_badge", "") let text = "Version 1.2 (10-Dec-2020)

" + "Bug fixes and improvements.

Feature (per request).

" + "Regarding the Continue Reading button: In the future, I hope to add various types of chapter qualification determination. (Specifically: The reading progress indicator present on the title's page). " + "While I have new features in the works I can't always work on them (either busy or lazy) nor can I release them because of their instability. " + "But smaller feature requests like the one today can be prioritized and posted quicker. So If you also have any feel free to request them!" + "

To remove the red badge ( ! ) please reload the page.

" + "
Version 1.1 (3-Nov-2020)

" + "Bug fixes and improvements.

" + "I found out that mangadex is soon updating their API to v2 which will hopefully allow me to add some interesting features to the script. " + "I won't release these features (or even start coding) them for now because they are likely to break/stop working after the API is updated." + "
Mangadex Plus version 1.0 is here! (3-Oct-2020)

" + "The very first version brings these features to the table:

" + "

" + "I am planning on improving the current features and adding new ones. If you have a suggestion/bug report please let me know on the " + "Userscript's GreasyFork page forum."; let element = '

'; closeMenu(); container.insertAdjacentHTML("afterbegin", element); addGlobalStyle("div.plus-box { position: fixed !important; right: 700px !important; left: 700px !important; top: 100px !important; z-index: 100001;}"); container.insertAdjacentHTML("afterbegin", pageMask); addGlobalStyle(".page-mask { background: rgba(0, 0, 0, 0.5); position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 100000;}"); container.insertAdjacentHTML("afterbegin", closeButton); addGlobalStyle(".plus-clsBtn { right: 150px !important; position: fixed !important; z-index: 100000; width: auto; color: white; background-color: #444;}"); document.getElementsByClassName("plus-back-settings")[0].addEventListener("click", function(){closeMenu(); openSettingsMenu();}); document.getElementsByClassName("page-mask")[0].addEventListener("click", closeMenu); document.getElementsByClassName("plus-clsBtn")[0].addEventListener("click", closeMenu); document.getElementsByClassName("plus-close")[0].addEventListener("click", closeMenu); addGlobalStyle("body { overflow: hidden;"); } function resetMDP(level){ function prompt(level){ let text_rw = "WARNING: By confirming this you will DELETE ALL Your Mangadex Plus saved data! This includes options and folders! \nAre you sure you want to proceed?"; let text_r = "WARNING: By confirming this you will RESET ALL Your Mangadex Plus options to Default values! \nAre you sure you want to proceed?"; let text_w = "WARNING: By confirming this you will WIPE ALL Your Mangadex Plus folders and It's Entries! \nAre you sure you want to proceed?"; if (level == "rw"){ if (confirm(text_rw)) { resets("rw"); } } else if (level == "r"){ if (confirm(text_r)) { resets("r"); } } else if (level == "w"){ if (confirm(text_w)) { resets("w"); } } } prompt(level); } function checkKey(e) { e = e || window.event; if (e.keyCode == '27' || e.keyCode == '27') { closeMenu(); } } document.onkeydown = checkKey; document.getElementsByClassName("plus-settings")[0].addEventListener("click", openSettingsMenu); } function folders(){ function getFolders(){ let folders = (JSON.parse(GM_getValue("folders"))).folders; let backFolder = '' let createFolder = '' let otherFolders = ""; let edit_btn = ''; let delete_btn = ''; for (let i = 0; i < folders.length; i++){ otherFolders = otherFolders + '
' + edit_btn + delete_btn + '
'; } return backFolder + otherFolders + createFolder; } function folderItems(index){ let backFolder = '' let folders = (JSON.parse(GM_getValue("folders"))).folders; let folder_name = (JSON.parse(GM_getValue("folders"))).folders[index].name; let delete_btn = '

' + '

'; let html = ""; for (let i = 0; i < (folders[index].entries).length; i++){ html = html + '

' + ' ' + folders[index].entries[i].title + '

' + delete_btn + '
'; } html = backFolder + html; return ''; } function createFolder(){ if (editing_busy == false){ editing_busy = true; function writeFolder(){ let value = "" + document.getElementsByClassName("folderInput")[0].value; let folders = JSON.parse(GM_getValue("folders")); folders.folders[folders.folders.length] = {"name" : value + "", "entries" : []}; GM_setValue("folders", JSON.stringify(folders)); editing_busy = false; } let option = document.getElementsByClassName("dropdown-item plus-createFolder")[0]; option.innerHTML = ''; document.getElementsByClassName("plus-createFolder")[0].removeEventListener("click", createFolder); function checkKey(e) { e = e || window.event; if (e.keyCode == '13') { writeFolder(); closeMenu(); openFoldersMenu(); document.onkeydown = null } } document.onkeydown = checkKey; document.getElementsByClassName("folderInput")[0].addEventListener("onsubmit", writeFolder); document.getElementsByClassName("folderInput")[0].select(); } } function refreshFolders(){ return ''; } function openFoldersMenu(){ container.insertAdjacentHTML("afterbegin", refreshFolders()); addGlobalStyle("div.plus-box { position: fixed !important; right: 700px !important; left: 700px !important; top: 100px !important; z-index: 100001;}"); addGlobalStyle(".plus-disabled{ color: #555}"); addGlobalStyle(".plus-disabled:hover{ background-color: unset; color: #555}"); container.insertAdjacentHTML("afterbegin", pageMask); addGlobalStyle(".page-mask { background: rgba(0, 0, 0, 0.5); position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 100000;}"); container.insertAdjacentHTML("afterbegin", closeButton); addGlobalStyle(".plus-clsBtn { right: 150px !important; position: fixed !important; z-index: 100000; width: auto; color: white; background-color: #444;}"); document.getElementsByClassName("page-mask")[0].addEventListener("click", closeMenu); document.getElementsByClassName("plus-clsBtn")[0].addEventListener("click", closeMenu); document.getElementsByClassName("plus-createFolder")[0].addEventListener("click", createFolder); document.getElementsByClassName("plus-close")[0].addEventListener("click", closeMenu); let folders = (JSON.parse(GM_getValue("folders"))).folders; for (let i = 0; i < folders.length; i++){ document.getElementsByClassName("folder_" + i)[0].parentNode.addEventListener("click", function(){browseFolder(i)}); document.getElementsByClassName("plus-delete-folder")[i].addEventListener("click", function(){deleteFolder(i)}); document.getElementsByClassName("plus-edit-folder")[i].addEventListener("click", function(){editFolder(i)}); } addGlobalStyle("body { overflow: hidden;"); } function browseFolder(index){ closeMenu(); container.insertAdjacentHTML("afterbegin", folderItems(index)); addGlobalStyle("div.plus-box { position: fixed !important; right: 700px !important; left: 700px !important; top: 100px !important; z-index: 100001;}"); container.insertAdjacentHTML("afterbegin", pageMask); addGlobalStyle(".page-mask { background: rgba(0, 0, 0, 0.5); position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 100000;}"); container.insertAdjacentHTML("afterbegin", closeButton); addGlobalStyle(".plus-clsBtn { right: 150px !important; position: fixed !important; z-index: 100000; width: auto; color: white; background-color: #444;}"); document.getElementsByClassName("plus-back")[0].addEventListener("click", function(){closeMenu();openFoldersMenu();}) document.getElementsByClassName("page-mask")[0].addEventListener("click", closeMenu); document.getElementsByClassName("plus-clsBtn")[0].addEventListener("click", closeMenu); document.getElementsByClassName("plus-close")[0].addEventListener("click", closeMenu); let folders = (JSON.parse(GM_getValue("folders"))).folders[index].entries; for (let i = 0; i < folders.length; i++){ document.getElementsByClassName("plus-delete-entry")[i].addEventListener("click", function(){deleteEntry(index, i)}); } if (folders.length > 14){ addGlobalStyle(".plus-entries-box { height: 500px; overflow-y: scroll;}"); } addGlobalStyle("body { overflow: hidden;"); } function deleteFolder(index){ let folder = JSON.parse(GM_getValue("folders")); function prompt(){ if(confirm("Folder " + folder.folders[index].name + " will be deleted. Proceed?")){ folder.folders.splice(index, 1); GM_setValue("folders", JSON.stringify(folder)); closeMenu(); openFoldersMenu(); } } prompt(); } function deleteEntry(folder, entry){ let folders = JSON.parse(GM_getValue("folders")); function prompt(){ if(confirm("\"" + folders.folders[folder].entries[entry].title + "\" will be removed from this Folder. Proceed?")){ folders.folders[folder].entries.splice(entry, 1); GM_setValue("folders", JSON.stringify(folders)); closeMenu(); browseFolder(folder); } } prompt(); } let editing_busy = false; // For folder name editing function editFolder(index){ if (editing_busy == false){ editing_busy = true; function writeFolder(){ let value = "" + document.getElementsByClassName("folderInput")[0].value; let folders = JSON.parse(GM_getValue("folders")); folders.folders[index].name = value; GM_setValue("folders", JSON.stringify(folders)); editing_busy = false; } let folder = JSON.parse(GM_getValue("folders")); let option = document.getElementsByClassName("folder_" + index)[0].parentNode; option.innerHTML = ''; document.getElementsByClassName("folderInput")[0].value = "" + folder.folders[index].name var el = document.getElementsByClassName('folderInput')[0].parentNode, elClone = el.cloneNode(true); el.parentNode.replaceChild(elClone, el); function checkKey(e) { e = e || window.event; if (e.keyCode == '13') { writeFolder(); closeMenu(); openFoldersMenu(); document.onkeydown = null } } document.onkeydown = checkKey; document.getElementsByClassName("folderInput")[0].addEventListener("onsubmit", writeFolder); document.getElementsByClassName("folderInput")[0].select(); } } function checkKey(e) { e = e || window.event; if (e.keyCode == '27' || e.keyCode == '27') { closeMenu(); } } document.onkeydown = checkKey; document.getElementsByClassName("plus-folders")[0].addEventListener("click", openFoldersMenu); addGlobalStyle("p.dropdown-item { overflow: hidden;}"); addGlobalStyle(".plus-delete-folder:hover { color: #f00;}"); addGlobalStyle(".plus-delete-entry:hover { color: #f00;}"); } function options(){ var temp_storage = { "preloading" : JSON.parse(GM_getValue("options")).options[0].preloading } var style = window.getComputedStyle(document.getElementById('homepage_settings_modal')); addGlobalStyle(".plus-options-window {position: fixed; left: 0px !important; right: 0px !important; width: 800px !important; margin-left: auto; margin-right: auto; margin-top: 100px; margin-bottom: auto;)"); addGlobalStyle(".modal-footer{display: block;}"); let preloading = '
' + '' + '
' + '' + '
' + '
'; let notes = '

(*) Automatically starts preloading chapter when in the reader. Only works for logged-in users.

' let options = //''; function listeners(){ //Listeners for options buttons for(let i = 0; i < document.getElementsByClassName("plus-preloading-options")[0].getElementsByTagName("a").length; i++){ document.getElementsByClassName("plus-preloading-options")[0].getElementsByTagName("a")[i].addEventListener("click", function(){selectOption("preloading", i)}); } document.getElementsByClassName("plus-options-save")[0].addEventListener("click", saveOptions); } function openOptionsMenu(){ container.insertAdjacentHTML("afterbegin", options); addGlobalStyle("div.plus-box { position: fixed !important; right: 700px !important; left: 700px !important; top: 100px !important; z-index: 100001;}"); container.insertAdjacentHTML("afterbegin", pageMask); addGlobalStyle(".page-mask { background: rgba(0, 0, 0, 0.5); position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 100000;}"); container.insertAdjacentHTML("afterbegin", closeButton); addGlobalStyle(".plus-clsBtn { right: 150px !important; position: fixed !important; z-index: 100000; width: auto; color: white; background-color: #444;}"); document.getElementsByClassName("page-mask")[0].addEventListener("click", closeMenu); document.getElementsByClassName("plus-clsBtn")[0].addEventListener("click", closeMenu); document.getElementsByClassName("plus-close")[0].addEventListener("click", closeMenu); addGlobalStyle("body { overflow: hidden;"); loadOptions(); listeners(); } function checkKey(e) { e = e || window.event; if (e.keyCode == '27' || e.keyCode == '27') { closeMenu(); } } let sample_options = { "options" : [ { "preloading" : 0 } ] } function saveOptions(){ GM_setValue("options", "{\"options\":[" + JSON.stringify(temp_storage) + "]}") location.reload() } function loadOptions(){ var options = JSON.parse(GM_getValue("options")); let preloading = options.options[0].preloading; selectOption("preloading", preloading); } function selectOption(option, index){ if(option == "preloading"){ let val; for(let i = 0; i < document.getElementsByClassName("plus-preloading-options")[0].getElementsByTagName("a").length; i++){ try{ document.getElementsByClassName("plus-preloading-options")[0].getElementsByTagName("a")[i].classList.remove('selected'); document.getElementsByClassName("plus-preloading-options")[0].getElementsByTagName("a")[i].classList.remove('active'); val = document.getElementsByClassName("plus-preloading-options")[0].getElementsByTagName("a")[index].childNodes[1].innerHTML; } catch(e){/*Nothing*/} } document.getElementsByClassName("plus-preloading-options")[0].getElementsByTagName("a")[index].classList.add("active"); document.getElementsByClassName("plus-preloading-options")[0].getElementsByTagName("a")[index].classList.add("selected"); document.getElementsByClassName("plus-preloading-selected")[0].innerHTML = val; temp_storage.preloading = index; } } document.onkeydown = checkKey; document.getElementsByClassName("plus-options")[0].addEventListener("click", openOptionsMenu); } function actionsBar(){ function makeBar(){ let bar = '
' + '
Mangadex+ Actions:
' + '
' + '
' + '
'; var position = document.getElementsByClassName("col-xl-9 col-lg-8 col-md-7")[0]; position.insertAdjacentHTML("beforeend", bar); } function addToFolder(){ function addEntry(index){ let folders = JSON.parse(GM_getValue("folders")); let link = "https://" + domain + "/title/" + getSubPage(2); let pass = true; for(let i = 0; i < folders.folders[index].entries.length; i++){ try{ if(link == folders.folders[index].entries[i].link){ pass = false; } } catch(e){ alert(3) if (e == TypeError){ pass = true; } } } if (pass || title_entry_duplication){ folders.folders[index].entries[folders.folders[index].entries.length] = {"title": "" + document.getElementsByClassName("card-header")[0].childNodes[3].innerHTML, "link" : "" + link}; GM_setValue("folders","" + JSON.stringify(folders)); } } function listFolders(){ let folders = JSON.parse(GM_getValue("folders")); let html = ""; for (let i = 0; i < folders.folders.length; i++){ html = html + ''; } return html; } let bar = '
' + '' + '' + '
 '; let position2 = document.getElementsByClassName("plus-actionbar")[0]; position2.insertAdjacentHTML("beforeend", bar); let folders = JSON.parse(GM_getValue("folders")); for (let i = 0; i < folders.folders.length; i++){ document.getElementsByClassName("plus-add-folder-" + i)[0].addEventListener("click", function(){addEntry(i)}); } function reloadFolders(){ let index = document.getElementsByClassName("plus-actions-folders")[0].childNodes.length for(let i = 0; i < index; i++){ document.getElementsByClassName("plus-add-folder-" + i)[0].remove(); } let position3 = document.getElementsByClassName("plus-actions-folders")[0]; position3.insertAdjacentHTML("afterbegin", listFolders()); let folders = JSON.parse(GM_getValue("folders")); for (let i = 0; i < folders.folders.length; i++){ document.getElementsByClassName("plus-add-folder-" + i)[0].addEventListener("click", function(){addEntry(i)}); } } document.getElementsByClassName("plus-folder-trigger")[0].addEventListener("click", reloadFolders); } function markAs(){ function mark(para){ document.getElementsByClassName("plus-read-pos")[0].classList.remove("fa-eye"); document.getElementsByClassName("plus-read-pos")[0].classList.add("fa-spinner"); document.getElementsByClassName("plus-read-pos")[0].classList.add("fa-pulse"); let api = "https://mangadex.org/api/v2/user/" + current_user + "/marker"; // API link for posting request to change read status let manga = document.location.href.split("/")[4]; // Current manga id let api2 = "https://mangadex.org/api/v2/manga/" + manga + "/chapters"; // API link for chapter ID's of this manga async function getChapters(){ // Gets all english chapters var chapters_ = []; let response = await fetch(api2); var data = await response.json(); var length = data.data.chapters.length; for (let i = 0; i < length; i++){ if (await data.data.chapters[length-i-1].language == "gb"){ await chapters_.push(data.data.chapters[length-i-1].id); } } return chapters_; } let param; getChapters().then(x => { var chapters_ = x; async function post(chapters_, check){ // Posting the request to the API (check -> if it's the last request and passes page reload if it is) // post body data param = { read : para, chapters : chapters_ }; // request options options = { method: 'POST', body: JSON.stringify(param), headers: { 'Content-Type': 'application/json' //Mangadex requires this } } // send POST request fetch(api, options) .then(res => res.json()) .then(res => console.log(res)) .then(function(){if(check == true){ document.location.reload() //Reloads page so the changes can be seen } } ); } async function countHandler(chapters_){ // Mangadex API limits 100 changes per request. This handles making enough requests of which the maximum is 100 let len = (parseInt(chapters_.length/100)+1) if (chapters_.length > 100){ for(let i = 0; i < len; i++){ if(i == len-1){ await post(chapters_, true) } else{ await post(chapters_, false); chapters_.splice(0, 100); } } } else{ await post(chapters_, true) } } countHandler(chapters_); }) } let mark_button = '
' + '' + '' + '
 '; let position2 = document.getElementsByClassName("plus-actionbar")[0]; position2.insertAdjacentHTML("beforeend", mark_button); document.getElementsByClassName("plus-mark-read")[0].addEventListener("click", function(){mark(true)}); document.getElementsByClassName("plus-mark-unread")[0].addEventListener("click", function(){mark(false)}); } function startReading(){ let manga_id = getSubPage(2); let chapter_id = ""; let api_url = "https://mangadex.org/api/v2/manga/" + manga_id + "/chapters"; async function getapi(url) { let response = await fetch(url); var data = await response.json(); var data2 = ""; var length = data.data.chapters.length; for(let i = 0; i < length; i++){ if (await data.data.chapters[length-i-1].language == "gb"){ data2 = await data.data.chapters[length-i-1].id; break; } } return data2 } getapi(api_url).then(x => { chapter_id = x; let link = "https://mangadex.org/chapter/" + chapter_id; // let mark_button = ''; let link2 = ""; let container = document.getElementsByClassName("chapter-container ")[0]; for(let i = 1; i < container.children.length; i++){ if(!container.children[i].children[0].children[0].children[0].children[0].classList.contains("grey")){ link2 = container.children[i-1].children[0].children[0].children[1].children[0].attributes.href.value; } } let mark_button = '
' + '' + '' + '
'; var position2 = document.getElementsByClassName("plus-actionbar")[0]; position2.insertAdjacentHTML("beforeend", mark_button); }); } makeBar(); addToFolder(); markAs(); startReading(); } function preload(){ async function doPreload(){ let index = 100; for (let i = 0; i < index; i++){ if (document.getElementById("preload-all").getAttribute("disabled") == ""){ await new Promise(r => setTimeout(r, 100)); } else{ document.getElementById("preload-all").click(); i = index; } } } let enabled = (JSON.parse(GM_getValue("options"))).options[0].preloading if (enabled == 0){ doPreload(); } function checkKey(e) { e = e || window.event; if (e.keyCode == '37' || e.keyCode == '39') { doPreload(); } } document.onkeydown = checkKey; document.getElementsByClassName("reader-images col-auto row no-gutters flex-nowrap m-auto text-center cursor-pointer directional constrained")[0].onclick = function(){doPreload()}; } function resets(level){ if(level == "r"){ let options = {"options" : [{"preloading" : 0}]}; GM_setValue("options", JSON.stringify(options)); location.reload(); } else if(level == "w"){ let folders = {"folders" : []}; GM_setValue("folders", JSON.stringify(folders)); location.reload(); } else if(level == "rw"){ let options = {"options" : [{"preloading" : 0}]}; GM_setValue("options", JSON.stringify(options)); let folders = {"folders" : []}; GM_setValue("folders", JSON.stringify(folders)); GM_deleteValue("first_time"); location.reload(); } } startup(); })();