" +
"\"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:" +
"
Custom folders
Marking all chapters of a Manga as read/unread
Start reading button
" +
"
Automatic Chapter Preloading
" +
"
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 = '
Bug Fix: Folders with many entries now have a scroll wheel. Before the entries would overflow out of the screen
" +
"
Bug Fix/Improvement: Before Mark As Read/Unread would apply only to one page of chapters (The page that is being visited). This wasn't really a bug " +
"as It was an oversight by me while making the script not including this feature.
Feature (per request).
Continue reading: " +
"Start reading button now has a secondary feature (accessed by the new dropdown) that allows the user to continue where he left off. Important to note: " +
"The script determines the chapter qualification based on the read/unread markers seen on the chapter list. Meaning you have to be logged in and follow the manga.
" +
"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.
The Folders window/box now has the same width as all other windows.
" +
"
Scrolling through the site while any MD+ windows are open is now disabled.
" +
"
Bug fix: Now saving titles to folders only up to the ID of the link making it independent from title changes and immune to entry duplicating.
" +
"
Changed the Userscript's description and added links to the Userscript's GreasyFork page " +
"in the About and Change Log sections.
" +
"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:" +
"
Custom folders: You can make folders and add your chosen titles to It.
Mark all chapters of a Manga as read/unread: " +
"Saves you the trouble of having to mark all chapters individually.
Start reading button: Goes to the first chapter of a Manga without having to scroll or switch pages.
" +
"
Automatic Chapter Preloading: Whenever you are in the reader (and are logged into your MD Account) the chapter will automatically start preloading. " +
"You can turn this feature on/off in th Options Menu.
" +
"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 = '
' +
'
' +
'
' +
' Change Log
' +
'
' +
'
' + text + '
' +
'' +
'
';
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 = '
Create New Folder
'
let otherFolders = "";
let edit_btn = '
' +
'
';
let delete_btn = '
' +
'
';
for (let i = 0; i < folders.length; i++){
otherFolders = otherFolders + '
' +
' ' + folders[i].name + '
' + 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 + '
(*) Automatically starts preloading chapter when in the reader. Only works for logged-in users.
'
let options = //'
' +
'
' +
'
' +
'
' +
' Mangadex Plus 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 + '
' + folders.folders[i].name + '
';
}
return html;
}
let bar = '
' +
'' +
'
' +
listFolders() +
'
' +
'
 ';
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 = '
' +
'' +
'
' +
'
' +
' Read
' +
'
' +
' Unread
' +
'
' +
'
 ';
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 = '