Feature: Read marker functionality in manga page.

master
masterhc 1 year ago
parent 7d884e91b9
commit 7c67c5b122

@ -4,7 +4,6 @@ const FavoriteModel = require('../models/favorite.js');
const ChapterModel = require('../models/readChapter.js'); const ChapterModel = require('../models/readChapter.js');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const { isNullOrUndefined } = require('util');
exports.home = async (req,res)=> exports.home = async (req,res)=>
{ {
@ -45,7 +44,6 @@ exports.search = async (req, res)=>
const scanlatorB = b.scanlator.toLowerCase(); const scanlatorB = b.scanlator.toLowerCase();
return scanlatorA.localeCompare(scanlatorB); return scanlatorA.localeCompare(scanlatorB);
}) })
console.log(data[1].Results)
res.render('searchResults.ejs', {data}) res.render('searchResults.ejs', {data})
} }
@ -118,6 +116,7 @@ exports.manga = async (req, res)=>
{ {
manga.List[i]['completely'] = chaptersRead[j].completely manga.List[i]['completely'] = chaptersRead[j].completely
manga.List[i]['Read'] = true; manga.List[i]['Read'] = true;
manga.List[i]['_id'] = chaptersRead[j]._id;
} }
} }
} }
@ -127,8 +126,13 @@ exports.manga = async (req, res)=>
const sortedChapters = chaptersRead.sort((a, b) => a.chapterNum - b.chapterNum); const sortedChapters = chaptersRead.sort((a, b) => a.chapterNum - b.chapterNum);
const sortedAndFilteredChapters = sortedChapters.filter(item=> item.lastImageRead && !item.completely); const sortedAndFilteredChapters = sortedChapters.filter(item=> item.lastImageRead && !item.completely);
const lastChapterWithReadImages=sortedAndFilteredChapters.shift(); const lastChapterWithReadImages=sortedAndFilteredChapters.shift();
const chapterNumToContinue = getChapterNumToContinue(lastCompletelyRead, lastChapterWithReadImages); let chapterNumToContinue = getChapterNumToContinue(lastCompletelyRead, lastChapterWithReadImages, manga.List);
manga.List[chapterNumToContinue-1]['continue'] = true; if(!manga.List.some(item=> item.num==chapterNumToContinue)) chapterNumToContinue = Math.trunc(chapterNumToContinue);
let index = manga.List.indexOf(manga.List.filter(item=>
{
return item.num == chapterNumToContinue
})[0]);
manga.List[index]['continue'] = true;
} }
catch (error) catch (error)
{ {
@ -136,15 +140,19 @@ exports.manga = async (req, res)=>
} }
res.render('mangaPage.ejs', {data:{...manga, scanlator}}); res.render('mangaPage.ejs', {data:{...manga, scanlator}});
} }
function getChapterNumToContinue(lastCompletelyRead, lastChapterWithReadImages) function getChapterNumToContinue(lastCompletelyRead, lastChapterWithReadImages, List)
{ {
const firstIndex = List.indexOf(List.filter(item=>item.num == lastCompletelyRead.chapterNum)[0]);
if(lastCompletelyRead) if(lastCompletelyRead)
{ {
if(lastCompletelyRead.chapterNum < lastChapterWithReadImages.chapterNum) if(lastCompletelyRead.chapterNum < lastChapterWithReadImages.chapterNum)
{ {
return lastChapterWithReadImages.chapterNum; return lastChapterWithReadImages.chapterNum;
} }
return lastCompletelyRead.chapterNum+1; const chNum = lastCompletelyRead.chapterNum+1;
const secondIndex = List.indexOf(List.filter(item=>item.num == chNum)[0]);
if(secondIndex - firstIndex > 1) return List[firstIndex + 1].num;
return chNum
} }
return lastChapterWithReadImages.chapterNum; return lastChapterWithReadImages.chapterNum;
} }
@ -161,7 +169,7 @@ exports.chapter = async (req, res)=>
const latestChap = fs.readdirSync(`./public/Saved/${scanlator}/${title}`).length const latestChap = fs.readdirSync(`./public/Saved/${scanlator}/${title}`).length
const List = imgs.map(filename => {return `./Saved/${scanlator}/${title}/CH_${chapter}/${filename}`}); const List = imgs.map(filename => {return `./Saved/${scanlator}/${title}/CH_${chapter}/${filename}`});
const mangaLink = await new Chapter(scanlator, link, title, chapter).getMangaLink(); const mangaLink = await new Chapter(scanlator, link, title, chapter).getMangaLink();
return res.render('chapterPage.ejs', {data:{title,latestChap,scanlator, chapterNum:parseInt(chapter), mangaLink, List}}); return res.render('chapterPage.ejs', {data:{title,latestChap,scanlator, chapterNum:parseFloat(chapter), mangaLink, List}});
} }
//If it isn't make sure there is no bad params being passed //If it isn't make sure there is no bad params being passed
const scanlatorExists = await new Modules(scanlator).exists(); const scanlatorExists = await new Modules(scanlator).exists();
@ -181,7 +189,7 @@ exports.chapter = async (req, res)=>
{ {
return res.redirect('/') return res.redirect('/')
} }
res.render('chapterPage.ejs', {data:{...manga, scanlator, chapterNum:parseInt(chapter)}}); res.render('chapterPage.ejs', {data:{...manga, scanlator, chapterNum:parseFloat(chapter)}});
} }
exports.favorites = async (req, res)=> exports.favorites = async (req, res)=>
@ -313,7 +321,7 @@ exports.chapterNavInfo = async (req, res)=>
if(!scanlatorExists) return res.sendStatus(404); if(!scanlatorExists) return res.sendStatus(404);
const scanlatorHasTitle = await new Modules(scanlator).titleExists(title); const scanlatorHasTitle = await new Modules(scanlator).titleExists(title);
if(!scanlatorHasTitle) return res.sendStatus(404); if(!scanlatorHasTitle) return res.sendStatus(404);
let chapter = parseInt(req.params.chapter); let chapter = parseFloat(req.params.chapter);
let manga; let manga;
try try
{ {
@ -429,6 +437,8 @@ exports.errorPage = (req, res)=>
exports.chapterRead = async (req, res)=> exports.chapterRead = async (req, res)=>
{ {
const cookieStr = req.headers.cookie;
if(!cookieStr) return res.sendStatus(404);
const {scanlator, title, chapter, link} = req.params; const {scanlator, title, chapter, link} = req.params;
const scanlatorExists = await new Modules(scanlator).exists(); const scanlatorExists = await new Modules(scanlator).exists();
if(!scanlatorExists) return res.sendStatus(404); if(!scanlatorExists) return res.sendStatus(404);
@ -439,13 +449,21 @@ exports.chapterRead = async (req, res)=>
if(chapter > latestChap || chapter < 0) return res.sendStatus(404); if(chapter > latestChap || chapter < 0) return res.sendStatus(404);
const chap = new ChapterModel(); const chap = new ChapterModel();
let chapterNum = chapter; let chapterNum = chapter;
let chapterLink = List.filter(item=>item.num == chapterNum)[0].link; let chapFromList = List.filter(item=>item.num == chapterNum)[0];
let chapterLink = chapFromList.link;
let chapterDate = chapFromList.date;
if(!chapterLink) return res.sendStatus(404); if(!chapterLink) return res.sendStatus(404);
const _chapter = await new Chapter(scanlator, chapterLink,title, chapter).get(); const _chapter = await new Chapter(scanlator, chapterLink,title, chapterNum).get();
let lastImageRead = _chapter.List[_chapter.List.length-1]; let lastImageRead = _chapter.List[_chapter.List.length-1];
chap.lastImageRead = lastImageRead; chap.lastImageRead = lastImageRead;
const chaps = await ChapterModel.find({scanlator, title, link, chapterNum}); const chaps = await ChapterModel.find({scanlator, title, link, chapterNum});
if(chaps.length>0) return updateChapter(chaps[0],res, lastImageRead, true) if(chaps.length>0) updateChapter(chaps[0], lastImageRead, true);
_chapter['num'] = _chapter.chNum;
_chapter['date'] = chapterDate;
_chapter['Read'] = true;
_chapter['_id'] = chap._id;
_chapter['completely'] = true;
res.render('chapterButton.ejs', {chapter:_chapter, scanlator, title, link, shortCut:false});
chap.scanlator = scanlator; chap.scanlator = scanlator;
chap.title = title; chap.title = title;
chap.link = link; chap.link = link;
@ -453,12 +471,11 @@ exports.chapterRead = async (req, res)=>
chap.lastImageRead = lastImageRead; chap.lastImageRead = lastImageRead;
chap.completely = true; chap.completely = true;
chap.save() chap.save()
res.sendStatus(200);
} }
async function updateChapter(chap, res, lastImageRead, completely=false) async function updateChapter(chap,lastImageRead, completely=false,res)
{ {
await ChapterModel.findOneAndUpdate(chap._id,{completely, lastImageRead:lastImageRead}, {new:true}); await ChapterModel.findOneAndUpdate(chap._id,{completely, lastImageRead:lastImageRead}, {new:true});
res.sendStatus(200); if(res) return res.sendStatus(200)
} }
exports.chapterIncompleteRead = async (req,res)=> exports.chapterIncompleteRead = async (req,res)=>
{ {
@ -569,26 +586,7 @@ exports.continue = async (req, res)=>
return [...results, ...uniqueContinuationChapters, ...chaptersToStart]; return [...results, ...uniqueContinuationChapters, ...chaptersToStart];
} }
async function getNextChapter (chapter)
{
const {scanlator, link, title, chapterNum, _id } = chapter;
const manga = await new Manga(scanlator, link, title).get();
if((chapterNum+1)>manga.latestChap) return false;
const chapLink = manga.List.filter(item=>item.num == (chapterNum+1))[0].link
const nextChapter = await new Chapter(scanlator, chapLink, title, (chapterNum+1)).get();
let index = nextChapter.List.indexOf(chapter.lastImageRead)
const imgReadOutOfTotal = (index !=-1 ? index:0)+'/'+(nextChapter.List.length-1)
return {
...nextChapter,
_id,
mangaCoverImg:manga.img,
chapterNum:nextChapter.chNum,
lastImageRead:nextChapter.List[0],
completely:false,
imgReadOutOfTotal,
byPass:true
};
}
const chaptersToContinue = await getChaptersToContinue(); const chaptersToContinue = await getChaptersToContinue();
chaptersToContinue.sort((a, b) => { chaptersToContinue.sort((a, b) => {
@ -614,11 +612,49 @@ exports.continue = async (req, res)=>
} }
res.render('chaptersToContinue.ejs', {data:chaptersToContinue}); res.render('chaptersToContinue.ejs', {data:chaptersToContinue});
} }
async function getNextChapter (chapter)
{
const {scanlator, link, title, _id } = chapter;
let chapterNum = chapter.chapterNum;
const manga = await new Manga(scanlator, link, title).get();
if((chapterNum+1)>manga.latestChap) return false;
if(!manga.List.some(item=>item.num == (chapterNum+1))) chapterNum = Math.trunc(chapterNum);
const chapterFromList = manga.List.filter(item=>item.num == (chapterNum+1))[0]
const {date, num} = chapterFromList;
const nextChapter = await new Chapter(scanlator, chapterFromList.link, title, (chapterNum+1)).get();
let index = chapter.lastImageRead?nextChapter.List.indexOf(chapter.lastImageRead):-1;
const imgReadOutOfTotal = (index !=-1 ? index:0)+'/'+(nextChapter.List.length-1)
return {
...nextChapter,
num,
date,
_id,
mangaCoverImg:manga.img,
chapterNum:nextChapter.chNum,
lastImageRead:nextChapter.List[0],
completely:false,
imgReadOutOfTotal,
byPass:true
};
}
exports.chapterToContinue = async (req, res)=>
{
const {scanlator, mangaLink, title} = req.params;
const chaptersRead = await ChapterModel.find({scanlator, title}).then(res=>{return res});
let sorted = chaptersRead.sort((a,b)=>{return b.chapterNum-a.chapterNum});
const newChapter = await getNextChapter({scanlator, link:mangaLink, title,chapterNum:parseFloat(sorted[0].chapterNum), _id:null});
res.render('chapterButton.ejs',{chapter:newChapter, scanlator, title,shortCut:true})
}
exports.removeChapter = async (req, res)=> exports.removeChapter = async (req, res)=>
{ {
if(!isValidID(req.params.id)) return res.sendStatus(404) const cookieStr = req.headers.cookie;
const chapter = await ChapterModel.findOneAndDelete({_id:req.params.id}); if(!cookieStr) return res.sendStatus(404);
res.render('empty.ejs'); if(!isValidID(req.params.id)) return res.sendStatus(404);
const {link, scanlator, title, chapterNum} = await ChapterModel.findOneAndDelete({_id:req.params.id}).then(deleted=>{return deleted});
const {List} = await new Manga(scanlator, link, title).get();
const chapter = List.filter(item=>item.num == chapterNum)[0];
res.render('chapterButton.ejs', {chapter, scanlator, title, shortCut:false});
} }
exports.dashboard = async (req, res)=> exports.dashboard = async (req, res)=>
{ {

@ -396,6 +396,7 @@ button:hover
border-radius: 15px; border-radius: 15px;
margin-left: 10%; margin-left: 10%;
background-color: var(--lbg); background-color: var(--lbg);
margin-top: 8em;
} }
.infoCard > .infoText .infoCard > .infoText
{ {
@ -464,11 +465,21 @@ button:hover
border: 2px solid var(--border); border: 2px solid var(--border);
border-radius: 15px; border-radius: 15px;
background-color: var(--lbg); background-color: var(--lbg);
margin: 5px;
width: 130px; width: 130px;
height: 40px; height: 40px;
cursor: pointer; cursor: pointer;
position: relative;
top:-1.3em;
}
.chapterButtonWrapper
{
margin: 5px;
width: 140px;
height: 50px;
overflow: hidden;
} }
.chapterButton:hover .chapterButton:hover
{ {
border-color: var(--border-hover); border-color: var(--border-hover);
@ -486,7 +497,7 @@ button:hover
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height:100% height:100%;
} }
.chapterButton > a >.buttonWrapper > div > h4 , .chapterButton > a >.buttonWrapper > div > h4 ,
.chapterButton > a >.buttonWrapper > div > h5 .chapterButton > a >.buttonWrapper > div > h5
@ -499,7 +510,7 @@ button:hover
width:auto; width:auto;
color: var(--purple-heart-400); color: var(--purple-heart-400);
position: relative; position: relative;
left: 0.7em; left: 1em;
} }
.readMarkerComplete .readMarkerComplete
{ {
@ -1112,4 +1123,31 @@ button:hover
.accentColor .accentColor
{ {
color:var(--accent) color:var(--accent)
} }
.markAsRead
{
color: var(--text);
transform: scaleX(-1) rotate(90deg);
z-index: 2;
position: relative;
}
.markAsRead:hover
{
color:var(--accent);
}
.chapterSpacer
{
width: 1em;
height: 1em;
}
.hitbox
{
height:1.3em;
width:1.3em;
position: relative;
top:0.6em;
left:.4em;
z-index: 4;
}

@ -18,6 +18,7 @@ module.exports = (worker)=>
router.route('/manga/:scanlator/:link/:title').get(api.manga); router.route('/manga/:scanlator/:link/:title').get(api.manga);
router.route('/chapter/:scanlator/:link/:title/:chapter').get(api.chapter); router.route('/chapter/:scanlator/:link/:title/:chapter').get(api.chapter);
router.route('/removeChapter/:id').get(api.removeChapter) router.route('/removeChapter/:id').get(api.removeChapter)
router.route('/chaptertocontinue/:scanlator/:mangaLink/:title/').get(api.chapterToContinue);
router.route('/chapternavinfo/:scanlator/:mangaLink/:title/:chapter').get(api.chapterNavInfo); router.route('/chapternavinfo/:scanlator/:mangaLink/:title/:chapter').get(api.chapterNavInfo);
router.route('/dashboard').get(api.dashboard); router.route('/dashboard').get(api.dashboard);
router.route('/login').get(api.loginPage) router.route('/login').get(api.loginPage)

@ -16,116 +16,6 @@ mongoose.connection.on('connected', ()=>{console.log('MongoDB - Connected')})
(async ()=> (async ()=>
{ {
// const manga = await new Manga('Reaper-scans', 'https://reaper-scans.com/manga/kagurabachi/','Kagurabachi').get();
async function getChaptersToContinue()
{
const favs = await FavoriteModel.find();
const chaps = await ChapterModel.find();
const favMap = new Map(favs.map(fav => [`${fav.title}_${fav.scanlator}`, {latestComplete: null, incomplete: []}]));
const favoritesNotYetStarted = [];
// Filter chapters directly into their respective categories
chaps.forEach(chap =>
{
const key = `${chap.title}_${chap.scanlator}`;
if (favMap.has(key))
{
const group = favMap.get(key);
if (chap.completely) {
if (!group.latestComplete || chap.chapterNum > group.latestComplete.chapterNum) group.latestComplete = chap;
}
else
{
group.incomplete.push(chap);
}
}
});
favs.forEach((element) =>
{
const {title, scanlator} = element;
if (!chaps.some(chap => chap.title == title && chap.scanlator == scanlator)) {
favoritesNotYetStarted.push(element);
}
});
// Compile the results
let results = Array.from(favMap.values()).flatMap(group =>
group.latestComplete ? [group.latestComplete, ...group.incomplete] : group.incomplete
);
results = await Promise.all(results.map(async (chap) =>
{
if (!chap.completely) return chap;
let next = await getNextChapter(chap);
return next ? next : null;
}));
results = results.filter(chap => chap !== null);
// Filter to find unique chapters that are not completed
const uniqueContinuationChapters = chaps.filter(chap =>
{
return !chap.completely && !results.some(f => f.scanlator === chap.scanlator && f.title === chap.title)
});
const chaptersToStart = [];
for(var i = 0; i< favoritesNotYetStarted.length; i++)
{
const {title, link, scanlator} = favoritesNotYetStarted[i];
const {List, img} = await new Manga(scanlator, link, title).get();
let aux = {byPass:true, chapterNum:0};
const chap = await new Chapter(scanlator, List[0].link, title, List[0].num).get();
const imgReadOutOfTotal = 0+'/'+(chap.List.length-1)
aux = {...aux, ...chap, mangaCoverImg:img, imgReadOutOfTotal,lastImageRead:chap.List[0]}
chaptersToStart.push(aux);
}
return [...results, ...uniqueContinuationChapters, ...chaptersToStart];
}
async function getNextChapter (chapter)
{
const {scanlator, link, title, chapterNum, _id } = chapter;
const manga = await new Manga(scanlator, link, title).get();
if((chapterNum+1)>manga.latestChap) return false;
const chapLink = manga.List.filter(item=>item.num == (chapterNum+1))[0].link
const nextChapter = await new Chapter(scanlator, chapLink, title, (chapterNum+1)).get();
let index = nextChapter.List.indexOf(chapter.lastImageRead)
const imgReadOutOfTotal = (index !=-1 ? index:0)+'/'+(nextChapter.List.length-1)
return {
...nextChapter,
_id,
mangaCoverImg:manga.img,
chapterNum:nextChapter.chNum,
lastImageRead:nextChapter.List[0],
completely:false,
imgReadOutOfTotal,
byPass:true
};
}
const chaptersToContinue = await getChaptersToContinue();
chaptersToContinue.sort((a, b) => {
if (a.chapterNum === 0) return 1;
if (b.chapterNum === 0) return -1;
return a.chapterNum - b.chapterNum;
});
for(let i = 0; i<chaptersToContinue.length; i++)
{
if(chaptersToContinue[i].byPass) continue
if(!chaptersToContinue[i].mangaLink)
{
const {scanlator, link, title, chapterNum} = chaptersToContinue[i];
const {List, img} = await new Manga(scanlator, link, title).get();
if(!List.some(item=>item.num == chapterNum)) return;
let chapter = await new Chapter(scanlator,List[chapterNum-1].link, title,chapterNum).get();
chaptersToContinue[i].link = chapter.link;
let index = chapter.List.indexOf(chaptersToContinue[i].lastImageRead)
const imgReadOutOfTotal = (index !=-1 ? index:0)+'/'+(chapter.List.length-1)
let aux = {...chaptersToContinue[i]._doc, mangaCoverImg:img, imgReadOutOfTotal}
chaptersToContinue[i] = aux;
}
}
// console.log(chaptersToContinue)
const c = chaptersToContinue.filter(item=>item.title=='Kagurabachi').sort((a,b)=>a.chapterNum-b.chapterNum)
console.log(c)
// const chapter = await ChapterModel.findOneAndDelete({_id:'66251e66ab92b12ec150dad9'});
})(); })();

@ -1,4 +1,4 @@
<span class="material-symbols-outlined bookmark" hx-post="/bookmark/<%=scanlator%>/<%=title%>/<%= link %>" hx-trigger="click" hx-target="this" hx-swap="outerHTML"> <span class="material-symbols-outlined bookmark" hx-post="/bookmark/<%=scanlator%>/<%=title%>/<%= link %>" hx-trigger="click" hx-target="this" hx-swap="outerHTML">
bookmark_add bookmark
</span> </span>

@ -1,3 +1,9 @@
<span class="material-symbols-outlined bookmark fill " hx-post="/bookmark/<%=scanlator%>/<%=title%>/<%= id %> " hx-trigger="click" hx-target="this"hx-swap="outerHTML"> <span
class="material-symbols-outlined bookmark fill "
hx-post="/bookmark/<%=scanlator%>/<%=title%>/<%= id %> "
hx-trigger="click"
hx-target="this"
hx-swap="outerHTML"
>
bookmark bookmark
</span> </span>

@ -1,20 +1,43 @@
<div class="chapterButton"> <div
<a href="/chapter/<%=scanlator %>/<%=encodeURIComponent(chapter.link)%>/<%= title %>/<%= chapter.num %>" > class="chapterButtonWrapper chapterButton_<%= (new String(chapter.num)).replaceAll('.', '_') %><%= shortCut?'shortCut':'' %>"
<div class="buttonWrapper"> >
<% if(chapter.Read){ %> <div class="hitbox">
<span class="material-symbols-outlined readMarker <%= chapter.completely?'readMarkerComplete fill':'' %> ">
<% if(!chapter.Read){%>
<span
hx-post="/chapterRead/<%= scanlator %>/<%= encodeURIComponent(chapter.mangaLink) %>/<%= title %>/<%= chapter.num %>/"
hx-target=".chapterButton_<%= (new String(chapter.num)).replaceAll('.', '_') %>"
hx-swap="outerHTML"
class="material-symbols-outlined markAsRead"
>
new_label
</span>
<%} else { %>
<span
class="material-symbols-outlined readMarker <%= chapter.completely?'readMarkerComplete fill':'' %> "
hx-get="/removeChapter/<%= chapter._id %>"
hx-trigger="click"
hx-target=".chapterButton_<%= (new String(chapter.num)).replaceAll('.', '_') %>"
hx-swap="outerHTML"
>
beenhere beenhere
</span> </span>
<% } %> <% }%>
<div> </div>
<h4 class="chapterNum"> <div class="chapterButton" >
Chapter <%= chapter.num %> <a href="/chapter/<%=scanlator %>/<%=encodeURIComponent(chapter.link)%>/<%= title %>/<%= chapter.num %>" >
</h4> <div class="buttonWrapper">
<h5 class="date"> <div class="chapterSpacer readMarker_<%= scanlator.concat(title) %>"></div>
<%= chapter.date %> <div>
</h5> <h4 class="chapterNum">
Chapter <%= chapter.num %>
</h4>
<h5 class="date">
<%= chapter.date %>
</h5>
</div>
</div> </div>
</div> </a>
</a> </div>
</div> </div>

@ -1,17 +1,67 @@
<div class="shortcutWrapper"> <div class="shortcutWrapper">
<div> <div>
<p> First:</p> <p> First:</p>
<%- include('chapterButton.ejs', {chapter:List[0], scanlator, title}) %> <%- include('chapterButton.ejs', {chapter:List[0], scanlator, title, shortCut:true}) %>
</div> </div>
<%for(let i = 0; i<List.length; i++){if(List[i].continue) { %> <%for(let i = 0; i<List.length; i++){if(List[i].continue) { %>
<div> <div id="continueWrapper">
<p> Continue:</p> <p> Continue:</p>
<%- include('chapterButton.ejs', {chapter:List[i], scanlator, title}) %> <%- include('chapterButton.ejs', {chapter:List[i], scanlator, title,shortCut:true}) %>
</div> </div>
<%}}%> <%}}%>
<div> <div>
<p>Last:</p> <p>Last:</p>
<%- include('chapterButton.ejs', {chapter:List[List.length-1],}) %> <%- include('chapterButton.ejs', {chapter:List[List.length-1], scanlator, title,shortCut:true}) %>
</div> </div>
</div> </div>
<script>
clearVariablesChapterShortCut();
function clearVariablesChapterShortCut()
{
[
'classList',
'classListIndex',
'chapterNum'
].forEach((variable) =>
{
if (window.hasOwnProperty(variable))
{
delete window[variable];
}
});
}
function createListener()
{
document.getElementById('List').addEventListener('htmx:afterSwap', event=>
{
let classList = event.target.classList;
for(let i = 0; i<classList.length; i++)
{
if(classList[i].includes('chapterButton_'))
{
let classListIndex = Array.from(document.getElementById('continueWrapper').childNodes[3].classList).indexOf(classList[i]+'shortCut');
if(classListIndex!=-1)
{
// let chapterNum = classList[i].split('_')[1].split('shortCut')[0];
htmx.ajax('GET', `/chaptertocontinue/<%=scanlator%>/<%= encodeURIComponent(List[0].mangaLink)%>/<%=title%>`,'.'+classList[i]+'shortCut');
}
}
}
});
}
try {
createListener();
} catch (error) {
clearVariablesChapterShortCut();
createListener();
}
</script>

@ -19,11 +19,9 @@
</div> </div>
</div> </div>
<br> <br>
<%- include('chapterShortcutButtonRow.ejs', {...data}) %> <%- include('chapterShortcutButtonRow.ejs', {...data}) %>
<div class="list"> <div class="list" id="List">
<% data.List.forEach(chapter=>{%> <% data.List.forEach(chapter=>{%>
<%- include('chapterButton.ejs', {chapter, scanlator:data.scanlator, title:data.title}) %> <%- include('chapterButton.ejs', {chapter, scanlator:data.scanlator, title:data.title, _id:chapter._id, shortCut:false}) %>
<% }) %> <% }) %>
</div> </div>

@ -0,0 +1,6 @@
<span
class="material-symbols-outlined readMarker readMarkerComplete fill"
>
beenhere
</span>
Loading…
Cancel
Save