Greasy Fork is available in English.

MangaDex Follows

Manage your follows page

// ==UserScript==
// @name         MangaDex Follows
// @namespace    https://greasyfork.org/es/scripts/411685-mangadex-follows
// @version      1.3.7.2
// @description  Manage your follows page
// @author       Australis
// @match        https://mangadex.org/*
// @exclude      https://mangadex.org/chapter/*
// @grant        GM_addStyle
// ==/UserScript==

GM_addStyle(".checkit::before {content: \"❌❌ \";}")

const debug = false

function log(string){
    if(debug) console.log(string)
}

log("Executing");

function LoadLists(input){
    let dalist = []
    try{
        if(localStorage.getItem(input)) dalist = JSON.parse(localStorage.getItem(input))
        log(input+" loaded")
    }
    catch(e){
        log("failed to load "+input)
    }
    return dalist
}

series = LoadLists('series')
const blacklist = LoadLists('blacklist')
const whitelist = LoadLists('whitelist')
const gap = LoadLists('gap')
var enhance;
try{
    if(localStorage.getItem("enhance") != null) enhance = JSON.parse(localStorage.getItem("enhance"))
    else enhance = true
}
catch(e){
    enhance = true
}

checker = []
let nodes = []

function Checker(node){
    if(checker.length == 0) checker = [node]
    else checker.push(node)
    log(node)
}

function CleanChecker(id,r){
    try{
        if(nodes.lenght == 0) nodes.push([id,[r]])
        else{
            add = true
            for(let n of nodes){
                log("a node")
                if(n[0] == id) {
                    log("existing node")
                    n[1].push(r)
                    add = false
                }
            }
            if(add) nodes.push([id,[r]])
        }
    }catch(e){
        log("CleanChecker error: "+e)
    }
}

function Decider(){
    log("Decider")
    for(let n of nodes){
        if(n[1].length > 1){
            log("deciding")
            var save_c = 100000
            var save_v = 100000
            var save_r = false
            var best = []
            log(n[1])
            for(let m of n[1]){
//                 log("save_c "+save_c)
                let dataset = m.children[2].childNodes[1].dataset
                log("chapter "+dataset.chapter)
                if(dataset.volume*1){
                    if(save_v > dataset.volume*1){
                        save_v = dataset.volume*1
                        save_c = dataset.chapter*1
                        save_r = m
                        best = []
                    }
                    else if(save_c > dataset.chapter*1){
                        log("next one?")
                        save_c = dataset.chapter*1
                        save_r = m
                        best = []
                    }
                    else if(save_c == dataset.chapter*1){
                        log("same")
                        if(!best.includes(save_r)) best.push(save_r)
                        if(!best.includes(m)) best.push(m)
                    }
                }
                else{
                    if(save_c > dataset.chapter*1){
                        log("next one?")
                        save_c = dataset.chapter*1
                        save_r = m
                        best = []
                    }
                    else if(save_c == dataset.chapter*1){
                        log("same")
                        if(!best.includes(save_r)) best.push(save_r)
                        if(!best.includes(m)) best.push(m)
                    }
                    else log("no coincidence")
                }
            }
            if(best.length){
                for(let b of best) CleanCheckerB(n[0]*1,b)
            }
            else CleanCheckerB(n[0]*1,save_r)
        }
        else {
            CleanCheckerB(n[0]*1,n[1][0])
        }
    }
    return true
}

function CleanCheckerB(id,row){
    try{
        for(var x=checker.length-1; x>=0; x--){
            if(checker[x][0] == id && checker[x][1] == row) checker.splice(x,1)
        }
    }catch(e){
        log("CleanChecker error: "+e)
        checker = []
    }
}

function Ahead(){
    try{
        if(checker.length){
            for(c of checker){
                let dataset = c[1].children[2].childNodes[1].dataset
                if(dataset.mangaId){
                    if(c[1].getElementsByClassName("chapter_mark_read_button grey")[0]) c[1].getElementsByClassName("chapter_mark_read_button grey")[0].setAttribute("class","chapter_mark_read_button")
                    else log(c)
                    if(c[1].getElementsByClassName("chapter_mark_read_button")[0]) c[1].getElementsByClassName("chapter_mark_read_button")[0].setAttribute("style","color: red")
                    else log(c)
                }
            }
        }
        checker = []
    }catch(e){
        log(e)
        log(c)
    }
}

function FS(array, number){//FindSeries
    return array.findIndex(q => q[0]*1 == number*1)
}

//add titles from follows
if(document.URL.includes('mangadex.org/follows/manga')){
    series_col = document.getElementsByClassName("manga-entry border-bottom");
    for(var s of series_col){
        var row = s.getElementsByClassName("row m-0")[1];
        var name = row.children[0].innerText;
        var state = row.children[2].innerText;
        var id = s.dataset.id;
        var node = [id,name,state,0,0]
        var add = true;
        if(series){
            for(var m of series){
                if(m[0] === id){
                    add = false;
                    if(m[2] !== state) m[2] = state;
                }
            }
            if(add) series.push(node);
        }
        else series = [node]
    }
    localStorage.setItem('series',JSON.stringify(series))
}

else if(document.URL.includes('mangadex.org/follows')){
    //read chapters

    row = document.getElementsByClassName("chapter-container")[0].children;
    function Hide(DataSet){
        for(var b of blacklist){
            if(b[0] == DataSet.mangaId && b[1] == DataSet.group) return true
        }
        return false
    }
    function OnlyThis(DataSet){
        for(var w of whitelist){
            if(w[0] == DataSet.mangaId && w[1] != DataSet.group) return 0
            if(w[0] == DataSet.mangaId && w[1] == DataSet.group) return 1
        }
        return 2
    }

    let changeH = false
    let changeO = false
    function Process(){
        for(var r of row){
            let dataset = r.children[2].childNodes[1].dataset;
            if(dataset.mangaId){
                let manga_id = dataset.mangaId*1;
                if(enhance) try{
                    if(Hide(dataset)) {
                        title = r.children[0].innerHTML
                        r.setAttribute("style","display: none")
                        changeH = true
                    }
                    else if(changeH){
                        title2 = r.children[0].innerHTML
                        if(r.children[0].classList.contains("d-md-flex")) r.children[0].innerHTML = title
                        title = title2
                        changeH = false
                    }
                    if(!OnlyThis(dataset)) {
                        title = r.children[0].innerHTML
                        r.setAttribute("style","display: none")
                        changeO = true
                    }
                    else if(changeO){
                        title2 = r.children[0].innerHTML
                        if(r.children[0].classList.contains("d-md-flex")) r.children[0].innerHTML = title
                        title = title2
                        changeO = false
                    }
                }catch(e){
                    log("enhance error, "+e)
                }
                try{
                    pointer = FS(series,manga_id)
                    if(series[pointer][3].toString().includes("v")){//if is divided by volume
                        if(series[pointer][3].toString() == "0v0") r.children[0].classList.value += " checkit"
                        log("a volume one, "+series[FS(series,manga_id)][3])
                        q = series[pointer][3].split("v")
                        vol = q[0]
                        chap = q[1]
                        if(r.innerHTML.includes("mark_unread")){
                            if(chap*1 < dataset.chapter*1 && vol*1 == dataset.volume*1) {
                                log("new chapter")
                                series[pointer][3] = dataset.volume+"v"+dataset.chapter;
                            }
                            if(vol < dataset.volume*1) {
                                log("new volume")
                                series[pointer][3] = dataset.volume+"v"+dataset.chapter;
                            }
                        }
                        else if(enhance){
                            if((chap*1 >= dataset.chapter*1 && vol*1 == dataset.volume*1) || vol*1 > dataset.volume*1){ //a duplicate
                                r.getElementsByClassName("chapter_mark_read_button grey")[0].setAttribute("class","chapter_mark_read_button")
                                if(gap.findIndex(q => q[0]*1 == manga_id) >= 0){
                                    let lgap = gap[gap.findIndex(q => q[0]*1 == dataset.mangaId)][1]
                                    log("a gapped one: ",lgap)
                                    log("current chapter: "+dataset.volume+"v"+dataset.chapter)
                                    if(chap*1 >= lgap[0].split("v")[1] && vol*1>= lgap[0].split("v")[0] &&
                                       lgap[1].split("v")[1] >= dataset.chapter*1 && vol*1<= lgap[1].split("v")[0]) r.getElementsByClassName("chapter_mark_read_button")[0].setAttribute("style","color: green")
                                }
                                else if(!(dataset.title.toLowerCase().includes("extra") || dataset.title.toLowerCase().includes("omake"))){
                                    r.getElementsByClassName("chapter_mark_read_button")[0].setAttribute("style","color: blue")
                                }
                                else r.getElementsByClassName("chapter_mark_read_button")[0].setAttribute("style","color: green")
                            }
                            else{//a new one
                                if(chap*1 < dataset.chapter*1+1.11 && vol*1 == dataset.volume*1){//skipped chapter
                                    Checker([manga_id,r])
                                }
                                if(chap*1 < dataset.chapter*1 && vol*1 == dataset.volume*1 && dataset.chapter*1 <= chap*1+1.11){//next chapter
                                    //                             CleanChecker(manga_id)
                                    CleanChecker(manga_id,r)
                                }
                            }
                        }
                    }
                    else{//if not divided by volume
                        this_last = series[FS(series,manga_id)][3]*1
                        if(r.innerHTML.includes("mark_unread")){
                            if(this_last < dataset.chapter*1) series[FS(series,manga_id)][3] = dataset.chapter*1;
                        }
                        else if(enhance){
                            if(this_last == 0) r.children[0].classList.value += " checkit"
                            if(this_last >= dataset.chapter*1){ //a duplicate
                                log("a duplicate")
                                r.getElementsByClassName("chapter_mark_read_button grey")[0].setAttribute("class","chapter_mark_read_button")
                                if(gap.findIndex(q => q[0]*1 == manga_id) >= 0){
                                    let lgap = gap[gap.findIndex(q => q[0]*1 == dataset.mangaId)][1]
                                    log("a gapped one: ",lgap)
                                    log("current chapter: "+dataset.chapter)
                                    if(dataset.chapter*1 >= lgap[0] &&
                                       lgap[1] >= dataset.chapter*1) r.getElementsByClassName("chapter_mark_read_button")[0].setAttribute("style","color: green")
                                }
                                else if(dataset.title.toLowerCase().includes("extra") || dataset.title.toLowerCase().includes("omake") || (dataset.chapter*1)%1 == 0.5){
                                    r.getElementsByClassName("chapter_mark_read_button")[0].setAttribute("style","color: green")
                                }
                                else r.getElementsByClassName("chapter_mark_read_button")[0].setAttribute("style","color: blue")
                            }
                            else{//a new one
                                if(this_last != 0
                                   && this_last < dataset.chapter*1+1.11){//skipped chapter
                                    //                             if((dataset.chapter*1)%1 && series[FS(series,manga_id)][3]*1+0.1 <= dataset.chapter*1) log("skipped parted chapter")
                                    Checker([manga_id,r])
                                }
                                if(this_last < dataset.chapter*1
                                   && dataset.chapter*1 <= this_last+1.11){//next chapter
                                    if((dataset.chapter*1)%1 && dataset.chapter*1 == Math.round((this_last+0.1+Number.EPSILON)*10)/10) {//Math.round((18.3+0.1+Number.EPSILON)*10)/10
                                        log("next parted chapter")
                                        CleanChecker(manga_id,r)
                                    }
                                    else if((dataset.chapter*1)%1 && dataset.chapter*1 == this_last+0.5) {
                                        log("next extra chapter")
                                        CleanChecker(manga_id,r)
                                    }
                                    else if((dataset.chapter*1)%1 && this_last-this_last%1 < dataset.chapter*1-(dataset.chapter*1)%1
                                            && dataset.chapter*1 == this_last-this_last%1+1.1){
                                        log("next new parted chapter")
                                        CleanChecker(manga_id,r)
                                    }
                                    else if((dataset.chapter*1)%1 == 0) {
                                        log("regular next chapter")
                                        CleanChecker(manga_id,r)
                                    }
                                }
                            }
                        }
                    }

                }catch(e){
                    //series not included
                    log("series not included?\n"+e)

                    log(dataset.mangaId+" "+r.children[0].innerText)
                    let this_last = 0
                    if(r.innerHTML.includes("mark_unread")) this_last = dataset.chapter*1;
                    if(FS(series,dataset.mangaId) == -1) series.push([dataset.mangaId,r.children[0].innerText,' Reading',this_last,dataset.timestamp])
                }
            }//end if
        }//end for
        return true
    }
    if(Process()) Process() //a second one to reduce false positives
    if(Decider()) Ahead()
    localStorage.setItem('series',JSON.stringify(series))
}

if(document.URL.includes('/title/')){
    log("title")
    var follow_stat = document.getElementsByClassName("btn-group")[0].childNodes[0].childNodes[0].className;
    let mangaId = document.URL.split("/")[4]*1
    function ProcVol(){
        try{
            for(let t of temp){
                [lastv,lastc] = last.split("v")
                if(t.dataset != null){
                    let dataset = t.dataset;
                    let manga_id = dataset.mangaId;
                    let vol = dataset.volume*1
                    if(process && lastc == dataset.chapter*1 && lastv == vol){
                        if(!t.innerHTML.includes("mark_unread")){
                            last = "0v0"
                            log("reset")
                        }
                        else process = false
                    }
                    if(t.innerHTML.includes("mark_unread")) {
                        if(lastc < dataset.chapter*1 && lastv == vol) {//a new read chapter from same volume
                            last = vol+"v"+dataset.chapter
                            process = false
                            series[FS(series,manga_id)][3] = last;
                        }
                        if(lastv < vol){//a new volume is read
                            log("new volume")
                            last = vol+"v"+dataset.chapter
                            series[FS(series,manga_id)][3] = last;
                        }
                        if(time < dataset.timestamp*1){
                            time = dataset.timestamp*1
                            series[FS(series,manga_id)][4] = dataset.timestamp*1
                        }
                    }
                }//end if
            }//end for
            log("done ProcVol, current last: "+last)
            localStorage.setItem('series',JSON.stringify(series))
        }catch(e){
            log("ProcVol error\n"+e)
        }
    }
    function Chapters(){
        try{
            if(last.toString().includes("v")){//is parted as independent chapters per volume
                ProcVol()
            }
            else{//is default
                for(let t of temp){
                    if(t.dataset != null){
                        let dataset = t.dataset;
                        let manga_id = dataset.mangaId;
                        let timestamp = dataset.timestamp
                        if(dataset.volume != null) {
                            vol = dataset.volume*1
                        }
                        else {
                            vol = 10000-1
                        }
                        if(checkvol && cvol > vol && cvol != 10000) {//volume change and not first iteration
                            if(cchp <= dataset.chapter*1){ //if it's not a successive chapter
                                log("volume!!")
                                checkvol = false
                                last = "0v0"
                                ProcVol()
                            }
                        }
                        if(!last.toString().includes("v")){
                            if(process && last == dataset.chapter*1){
                                if(!t.innerHTML.includes("mark_unread")){
                                    last = 0
                                    log("reset")
                                }
                                else process = false
                            }
                            if(t.innerHTML.includes("mark_unread")) {
                                if(last < dataset.chapter*1) {
                                    process = false
                                    last = dataset.chapter*1;
                                    series[FS(series,manga_id)][3] = dataset.chapter*1;
                                }
                                if(time < dataset.timestamp*1){
                                    time = dataset.timestamp*1
                                    series[FS(series,manga_id)][4] = dataset.timestamp*1
                                }
                            }
                            cvol = vol
                            cchp = dataset.chapter*1
                        }//end if
                    }//end if
                }//end for
                log("new last: "+last)
                localStorage.setItem('series',JSON.stringify(series))
                log("OK");
            }//end else
        }catch(e){
            log("Chapters error\n"+e)
        }
    }
    var temp = document.getElementsByClassName("chapter-row d-flex row no-gutters p-2 align-items-center border-bottom odd-row");
    var last = 0
    var time = 0
    var pos = FS(series,mangaId)
    if(pos >= 0) {
        last = series[pos][3]
        if(series[pos].length == 4) series[pos].push(time)
        else time = series[pos][4]
    }
    log("old last: "+last)
    process = true
    var cvol = 10000
    var cchp = 0
    checkvol = true
    let state = document.getElementsByClassName("btn dropdown-toggle")[0].getElementsByClassName("d-none d-xl-inline")[0].innerText
    let name = document.title.split(" (Title)")[0]
    let id = document.URL.split("/")[4]
    let node = [id,name,state,last,time]
    let add = true;
    let z = FS(series,id)
    if(z == -1){
        series.push(node)
        log(name+" added to series")
    }
    else{
        if(series[z][2] !== state) series[z][2] = state;
    }
    if(!follow_stat.includes("fa-bookmark")){
        Chapters()
    }
}

if(document.URL.includes('mangadex.org/follows') && !document.URL.includes('mangadex.org/follows/manga')){
    let data = [['ID','Series name','Status','Last Read','Last Update']].concat(series);
    for(var d of data){
        if(d[1].includes("\"")) d[1] = d[1].replaceAll("\"","|")
        if(d[1].includes(";")) d[1] = d[1].replaceAll(";",":")
        if(d.length == 5) d[4] = Date(d[4])
        else d.push("Unknown")
    }

    // Building the CSV from the Data two-dimensional array
    // Each column is separated by ";" and new line "\n" for next row
    let csvContent = '';
    data.forEach(function(infoArray, index) {
        dataString = infoArray.join(';');
        csvContent += index < data.length ? dataString + '\n' : dataString;
    });

    // The download function takes a CSV string, the filename and mimeType as parameters
    // Scroll/look down at the bottom of this snippet to see how download is called
    let download = function(content, fileName, mimeType) {
        var a = document.createElement('a');
        mimeType = mimeType || 'application/octet-stream';

        if (navigator.msSaveBlob) { // IE10
            navigator.msSaveBlob(new Blob([content], {
                type: mimeType
            }), fileName);
        } else if (URL && 'download' in a) { //html5 A[download]
            a.href = URL.createObjectURL(new Blob([content], {
                type: mimeType
            }));
            a.setAttribute('download', fileName);
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
        } else {
            location.href = 'data:application/octet-stream,' + encodeURIComponent(content); // only this mime type is supported
        }
    }

    document.download = function(){download(csvContent, 'MangaDex.csv', 'text/csv;encoding:utf-8')}

    let boton = document.createElement("li")
    boton.setAttribute("class","nav-item")
    boton.setAttribute("href","#")
    boton.setAttribute("onclick","download()")
    boton.appendChild(document.createElement("a"))
    boton.children[0].setAttribute("class","nav-link")
    boton.children[0].appendChild(document.createElement("span"))
    boton.children[0].children[0].setAttribute("class","fas fa-download fa-fw")
    boton.children[0].children[0].setAttribute("aria-hidden","true")
    boton.children[0].appendChild(document.createElement("span"))
    boton.children[0].children[1].setAttribute("class","d-none d-md-inline")
    boton.children[0].children[1].innerText = "Export"
    document.getElementsByClassName("nav nav-tabs")[0].insertBefore(boton,document.getElementsByClassName("nav nav-tabs")[0].children[4])

    let boton2 = document.createElement("li")
    boton2.appendChild(document.createElement("a"))
    boton2.firstChild.setAttribute("class","nav-link")
    boton2.firstChild.innerText = "Script Options"
    boton2.firstChild.setAttribute("onclick","Show()")
    document.getElementsByClassName("nav nav-tabs")[0].insertBefore(boton2,document.getElementsByClassName("nav nav-tabs")[0].children[5])
}

function CreateMenu(){
    gg = document.createElement("style")
    gg.innerText = ".modal_row {display: grid;grid-gap: 5px;grid-template-columns: 20vw 20vw 5vw;}"
    gg.innerText+= ".modalX {display: none;position: fixed;z-index: 10;padding-top: 10vh;left: 0;top: 0;width: 99%; height: 100%; overflow: auto; background-color: rgb(0,0,0); background-color: rgba(0,0,0,0.4); color: white;}"
    gg.innerText+= ".modalo {position: relative;background-color: black;margin: auto;padding: 2vw;border: 1px solid #888;width: 80%;box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);-webkit-animation-name: animatetop;-webkit-animation-duration: 0.4s;animation-name: animatetop;animation-duration: 0.4s}"
    gg.innerText+= "@-webkit-keyframes animatetop {from {top:-300px; opacity:0} to {top:0; opacity:1}}"
    gg.innerText+= "@keyframes animatetop {from {top:-300px; opacity:0}to {top:0; opacity:1}}"
    gg.innerText+= ".closex {color: white;float: right;font-size: 28px;font-weight: bold;padding-right: 8vw;}"
    gg.innerText+= ".closex:hover,.close:focus {color: #000;text-decoration: none;cursor: pointer;}"
    gg.innerText+= ".half {width: 45%;display: inline-block;}"

    document.querySelector("head").appendChild(gg)

    modal = document.createElement("div")
    modal.setAttribute("class","modalX")
    modal.setAttribute("id","modalX")
//     modal.setAttribute("style","margin: auto;width: 70vw;")
    closer = document.createElement("span")
    closer.setAttribute("class","closex")
    closer.innerText = "×"
    closer.setAttribute("onclick","CloseThis()")
    modal.appendChild(closer)

    form = document.createElement("div")
    elem1 = document.createElement("div") //checkbox
    elem2 = document.createElement("div") //whitelist
    elem3 = document.createElement("div") //blacklist
    elem4 = document.createElement("div") //gap
    modbut = document.createElement("button") //save button
    canbut = document.createElement("button") //cancel button

    modt1 = document.createElement("h2") //title1
    modt1.setAttribute("title","series & group ID are the numbers in their URLs, after /title/ and /group/ respectively")
    modt1.innerText = "Whitelist elements"
    modt2 = document.createElement("h2") //title2
    modt2.setAttribute("title","series & group ID are the numbers in their URLs, after /title/ and /group/ respectively")
    modt2.innerText = "Blacklist elements"
    modt3 = document.createElement("h2") //title3
    modt3.setAttribute("title","series ID are the numbers after /title/ in their URL, and the gap has to include the chapters available between the gap")
    modt3.innerText = "Gap list elements"

    form.setAttribute("class","modalo")
    form.setAttribute("id","ScriptForm")
//     form.setAttribute("action","")

    elem1A = document.createElement("input")
    elem1A.setAttribute("type","checkbox")
    elem1A.setAttribute("id","enhancer")
    elem1A.setAttribute("name","enhancer")
    elem1A.setAttribute("style","margin:5px;")
    elem1A.setAttribute("checked",enhance)

    elem1B = document.createElement("label")
    elem1B.setAttribute("for","enhancer")
    elem1B.innerText = "\tHighlight unread chapters"
    elem1.appendChild(elem1A)
    elem1.appendChild(elem1B)

    elem2.setAttribute("id","whitelister")
    elem2.setAttribute("style","display:grid;grid-gap:5px;")

    modalrow1 = document.createElement("div")
    modalrow1.setAttribute("class","modal_row")
    title2A = document.createElement("span")
    title2B = document.createElement("span")
    title2A.innerText = "series ID"
    title2B.innerText = "group ID"
    modalrow1.appendChild(title2A)
    modalrow1.appendChild(title2B)
    elem2.appendChild(modt1)
    elem2.appendChild(modalrow1)

    function Row1(w){
        let modalrow2 = document.createElement("div")
        modalrow2.setAttribute("class","modal_row")
        let span2A = document.createElement("span")
        let input2A = document.createElement("input")
        input2A.setAttribute("type","number")
        input2A.setAttribute("name","mangaID")
        input2A.setAttribute("value",w[0])
        span2A.appendChild(input2A)
        let span2B = document.createElement("span")
        let input2B = document.createElement("input")
        input2B.setAttribute("type","number")
        input2B.setAttribute("name","groupID")
        input2B.setAttribute("value",w[1])
        span2B.appendChild(input2B)
        modalrow2.appendChild(span2A)
        modalrow2.appendChild(span2B)
        let del = document.createElement("p")
        del.innerText = "DELETE"
        del.setAttribute("onclick","this.parentElement.remove()")
        modalrow2.appendChild(del)
        return modalrow2
    }

    if(whitelist.length) for(let w of whitelist){
        elem2.appendChild(Row1(w))
//         let modalrow2 = document.createElement("div")
//         modalrow2.setAttribute("class","modal_row")
//         let span2A = document.createElement("span")
//         let input2A = document.createElement("input")
//         input2A.setAttribute("type","number")
//         input2A.setAttribute("name","mangaID")
//         input2A.setAttribute("value",w[0])
//         span2A.appendChild(input2A)
//         let span2B = document.createElement("span")
//         let input2B = document.createElement("input")
//         input2B.setAttribute("type","number")
//         input2B.setAttribute("name","groupID")
//         input2B.setAttribute("value",w[1])
//         span2B.appendChild(input2B)
//         modalrow2.appendChild(span2A)
//         modalrow2.appendChild(span2B)
//         let del = document.createElement("p")
//         del.innerText = "DELETE"
//         del.setAttribute("onclick","this.parentElement.remove()")
//         modalrow2.appendChild(del)
//         elem2.appendChild(modalrow2)
    }
//     else{
//         modalrow2 = document.createElement("div")
//         modalrow2.setAttribute("class","modal_row")
//     }
    add = document.createElement("p")
    add.setAttribute("id","adder")
    add.innerText = "ADD NEW"
    add.setAttribute("onclick","this.remove();AddWL(this)")
    elem2.appendChild(add)


    elem3.setAttribute("id","blacklister")
    elem3.appendChild(modt2)
    elem3.appendChild(modalrow1.cloneNode(true))
    if(blacklist.length) for(let b of blacklist){
        elem3.appendChild(Row1(b))
//         let modalrow2 = document.createElement("div")
//         modalrow2.setAttribute("class","modal_row")
//         let span2A = document.createElement("span")
//         let input2A = document.createElement("input")
//         input2A.setAttribute("type","number")
//         input2A.setAttribute("name","mangaID")
//         input2A.setAttribute("value",b[0])
//         span2A.appendChild(input2A)
//         let span2B = document.createElement("span")
//         let input2B = document.createElement("input")
//         input2B.setAttribute("type","number")
//         input2B.setAttribute("name","groupID")
//         input2B.setAttribute("value",b[1])
//         span2B.appendChild(input2B)
//         modalrow2.appendChild(span2A)
//         modalrow2.appendChild(span2B)
//         let del = document.createElement("p")
//         del.innerText = "DELETE"
//         del.setAttribute("onclick","this.parentElement.remove()")
//         modalrow2.appendChild(del)
//         elem3.appendChild(modalrow2)
    }
//     else{
//         modalrow2 = document.createElement("div")
//         modalrow2.setAttribute("class","modal_row")
//     }
    add = document.createElement("p")
    add.setAttribute("id","adder")
    add.innerText = "ADD NEW"
    add.setAttribute("onclick","this.remove();AddBL(this)")
    elem3.appendChild(add)

    elem4.setAttribute("id","gapper")
    modalrow1 = document.createElement("div")
    modalrow1.setAttribute("class","modal_row")
    let title4A = document.createElement("span")
    let title4B = document.createElement("span")
    let title4B1 = document.createElement("span")
    let title4B2 = document.createElement("span")
    title4B1.setAttribute("class","half")
    title4B2.setAttribute("class","half")
    title4A.innerText = "series ID"
    title4B1.innerText = "Gap start"
    title4B2.innerText = "Gap end"
    title4B.appendChild(title4B1)
    title4B.appendChild(title4B2)
    modalrow1.appendChild(title4A)
    modalrow1.appendChild(title4B)
    elem4.appendChild(modt3)
    elem4.appendChild(modalrow1)

    if(gap.length) for(let g of gap){
        let modalrow2 = document.createElement("div")
        modalrow2.setAttribute("class","modal_row")
        let span2A = document.createElement("span")
        let input2A = document.createElement("input")
        input2A.setAttribute("type","number")
        input2A.setAttribute("name","mangaIDgap")
        input2A.setAttribute("value",g[0])
        span2A.appendChild(input2A)
        let span2B = document.createElement("span")
        let span2B1 = document.createElement("span")
        let span2B2 = document.createElement("span")
        let input2B1 = document.createElement("input")
        input2B1.setAttribute("type","number")
        input2B1.setAttribute("class","half")
        input2B1.setAttribute("name","gap1")
        input2B1.setAttribute("value",g[1][0])
        span2B.appendChild(input2B1)
        span2B2 = document.createElement("span")
        let input2B2 = document.createElement("input")
        input2B2.setAttribute("type","number")
        input2B2.setAttribute("class","half")
        input2B2.setAttribute("name","gap2")
        input2B2.setAttribute("value",g[1][1])
        span2B.appendChild(input2B2)
        modalrow2.appendChild(span2A)
        modalrow2.appendChild(span2B)
        let del = document.createElement("p")
        del.innerText = "DELETE"
        del.setAttribute("onclick","this.parentElement.remove()")
        modalrow2.appendChild(del)
        elem4.appendChild(modalrow2)
    }
//     else{
//         modalrow2 = document.createElement("div")
//         modalrow2.setAttribute("class","modal_row")
//     }
    add = document.createElement("p")
    add.setAttribute("id","adder")
    add.innerText = "ADD NEW"
    add.setAttribute("onclick","this.remove();AddGap(this)")
    elem4.appendChild(add)

    form.appendChild(elem1)
    form.appendChild(elem2)
    form.appendChild(elem3)
    form.appendChild(elem4)

    modal.appendChild(form)

    buttons = document.createElement("div")
    modbut.setAttribute("onclick","UpdateValues()")
    modbut.innerText = "Save Changes & Reload"
    modbut.setAttribute("style","margin:auto;width:30%;display:block;")
    buttons.appendChild(modbut)

    canbut.setAttribute("onclick","CloseThis()")
    canbut.innerText = "Exit without Saving Changes"
    canbut.setAttribute("style","margin:auto;width:30%;display:block;")
    buttons.appendChild(canbut)
    form.appendChild(buttons)

    document.querySelector("body").appendChild(modal)
}

CreateMenu()

function NewRow1(){
    let modalrow2 = document.createElement("div")
    modalrow2.setAttribute("class","modal_row")
    let span2A = document.createElement("span")
    let input2A = document.createElement("input")
    input2A.setAttribute("type","number")
    input2A.setAttribute("name","mangaID")
    input2A.setAttribute("value",0)
    span2A.appendChild(input2A)
    let span2B = document.createElement("span")
    let input2B = document.createElement("input")
    input2B.setAttribute("type","number")
    input2B.setAttribute("name","groupID")
    input2B.setAttribute("value",0)
    span2B.appendChild(input2B)
    modalrow2.appendChild(span2A)
    modalrow2.appendChild(span2B)
    let del = document.createElement("p")
    del.innerText = "DELETE"
    del.setAttribute("onclick","this.parentElement.remove()")
    modalrow2.appendChild(del)
    return modalrow2
}

function NewRow2(){
    let modalrow2 = document.createElement("div")
    modalrow2.setAttribute("class","modal_row")
    let span2A = document.createElement("span")
    let input2A = document.createElement("input")
    input2A.setAttribute("type","number")
    input2A.setAttribute("name","mangaIDgap")
    input2A.setAttribute("value",0)
    span2A.appendChild(input2A)
    let span2B = document.createElement("span")
    let span2B1 = document.createElement("span")
    let span2B2 = document.createElement("span")
    let input2B1 = document.createElement("input")
    input2B1.setAttribute("type","number")
    input2B1.setAttribute("class","half")
    input2B1.setAttribute("name","gap1")
    input2B1.setAttribute("value",0)
    span2B.appendChild(input2B1)
    span2B2 = document.createElement("span")
    let input2B2 = document.createElement("input")
    input2B2.setAttribute("type","number")
    input2B2.setAttribute("class","half")
    input2B2.setAttribute("name","gap2")
    input2B2.setAttribute("value",0)
    span2B.appendChild(input2B2)
    modalrow2.appendChild(span2A)
    modalrow2.appendChild(span2B)
    let del = document.createElement("p")
    del.innerText = "DELETE"
    del.setAttribute("onclick","this.parentElement.remove()")
    modalrow2.appendChild(del)
    return modalrow2
}

function NewButton(ToDo){
    add = document.createElement("p")
    add.setAttribute("id","adder")
    add.setAttribute("onclick",ToDo)
    add.innerText = "ADD NEW"
    return add
}

document.Show = function(){
    modalX.style.display = "block";
}

document.CloseThis = function(){
    modalX.style.display = "none";
}

document.AddWL = function(element){
    element.remove()
    elem2.appendChild(NewRow1())
    elem2.appendChild(NewButton("this.remove();AddWL(this)"))
}
document.AddBL = function(element){
    element.remove()
    elem3.appendChild(NewRow1())
    elem3.appendChild(NewButton("this.remove();AddBL(this)"))
}
document.AddGap = function(element){
    element.remove()
    elem4.appendChild(NewRow2())
    elem4.appendChild(NewButton("this.remove();AddGap(this)"))
}

document.UpdateValues = function() {
	log("Updating")
    var elements = document.getElementById("ScriptForm").children;
    log(elements)
    enhance = document.getElementById("ScriptForm").getElementsByTagName("input")[0].checked
    obj1 =[];
    obj2 =[];
    obj3 =[];
    let wl = elements[1].getElementsByClassName("modal_row")
    let bl = elements[2].getElementsByClassName("modal_row")
    let gl = elements[3].getElementsByClassName("modal_row")
    for(let i = 1; i < wl.length; i++){
        let inputs = wl[i].getElementsByTagName("input")
        obj1.push([inputs.mangaID.value*1,inputs.groupID.value*1])
    }
    for(let i = 1; i < bl.length; i++){
        let inputs = bl[i].getElementsByTagName("input")
        obj2.push([inputs.mangaID.value*1,inputs.groupID.value*1])
    }
    for(let j = 1; j < gl.length; j++){
        let spans = gl[j].getElementsByTagName("input")
        obj3.push([spans.mangaIDgap.value*1,[spans.gap1.value*1,spans.gap2.value*1]])
    }

    localStorage.setItem('whitelist',JSON.stringify(obj1));
    localStorage.setItem('blacklist',JSON.stringify(obj2));
    localStorage.setItem('gap',JSON.stringify(obj3));
    localStorage.setItem('enhance',JSON.stringify(enhance))
    location.reload()
}