This commit is contained in:
parent
e2cfdb3a0c
commit
162adfbe16
@ -82,7 +82,8 @@
|
|||||||
id="top-bar"
|
id="top-bar"
|
||||||
class="transition-all duration-200 absolute z-10 bg-gray-100 dark:bg-gray-800 w-full px-2"
|
class="transition-all duration-200 absolute z-10 bg-gray-100 dark:bg-gray-800 w-full px-2"
|
||||||
>
|
>
|
||||||
<div class="w-full h-32 flex items-center justify-around relative">
|
<div class="max-h-[75vh] w-full flex flex-col items-center justify-around relative dark:text-white">
|
||||||
|
<div class="h-32">
|
||||||
<div class="text-gray-500 absolute top-6 left-4 flex flex-col gap-4">
|
<div class="text-gray-500 absolute top-6 left-4 flex flex-col gap-4">
|
||||||
<a href="#">
|
<a href="#">
|
||||||
<svg
|
<svg
|
||||||
@ -152,6 +153,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="toc" class="w-full text-center max-h-[50%] overflow-scroll no-scrollbar"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
@ -66,6 +66,56 @@ function populateMetadata(data) {
|
|||||||
authorEl.innerText = data.author;
|
authorEl.innerText = data.author;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the Table of Contents
|
||||||
|
**/
|
||||||
|
function populateTOC() {
|
||||||
|
if (!currentReader.book.navigation.toc) {
|
||||||
|
console.warn("[populateTOC] No TOC");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tocEl = document.querySelector("#toc");
|
||||||
|
if (!tocEl) {
|
||||||
|
console.warn("[populateTOC] No TOC Element");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the Table of Contents
|
||||||
|
let parsedTOC = currentReader.book.navigation.toc.reduce((agg, item) => {
|
||||||
|
let sectionTitle = item.label.trim();
|
||||||
|
agg.push({ title: sectionTitle, href: item.href });
|
||||||
|
if (item.subitems.length == 0) {
|
||||||
|
return agg;
|
||||||
|
}
|
||||||
|
|
||||||
|
let allSubSections = item.subitems.map(item => {
|
||||||
|
let itemTitle = item.label.trim();
|
||||||
|
if (sectionTitle != "") {
|
||||||
|
itemTitle = sectionTitle + " - " + item.label.trim();
|
||||||
|
}
|
||||||
|
return { title: itemTitle, href: item.href };
|
||||||
|
});
|
||||||
|
agg.push(...allSubSections);
|
||||||
|
|
||||||
|
return agg;
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
// Add Table of Contents to DOM
|
||||||
|
let listEl = document.createElement("ul");
|
||||||
|
listEl.classList.add("m-4")
|
||||||
|
parsedTOC.forEach(item => {
|
||||||
|
let listItem = document.createElement("li");
|
||||||
|
listItem.style.cursor = "pointer";
|
||||||
|
listItem.addEventListener("click", () => {
|
||||||
|
currentReader.rendition.display(item.href);
|
||||||
|
});
|
||||||
|
listItem.textContent = item.title;
|
||||||
|
listEl.appendChild(listItem);
|
||||||
|
});
|
||||||
|
tocEl.appendChild(listEl);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the main reader class. All functionality is wrapped in this class.
|
* This is the main reader class. All functionality is wrapped in this class.
|
||||||
* Responsible for handling gesture / clicks, flushing progress & activity,
|
* Responsible for handling gesture / clicks, flushing progress & activity,
|
||||||
@ -439,6 +489,7 @@ class EBookReader {
|
|||||||
// ------------------------------------------------ //
|
// ------------------------------------------------ //
|
||||||
// ----------------- Swipe Helpers ---------------- //
|
// ----------------- Swipe Helpers ---------------- //
|
||||||
// ------------------------------------------------ //
|
// ------------------------------------------------ //
|
||||||
|
let disablePagination = false;
|
||||||
let touchStartX,
|
let touchStartX,
|
||||||
touchStartY,
|
touchStartY,
|
||||||
touchEndX,
|
touchEndX,
|
||||||
@ -459,25 +510,38 @@ class EBookReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Swipe Left
|
// Swipe Left
|
||||||
if (touchEndX + drasticity < touchStartX) {
|
if (!disablePagination && touchEndX + drasticity < touchStartX) {
|
||||||
nextPage();
|
nextPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swipe Right
|
// Swipe Right
|
||||||
if (touchEndX - drasticity > touchStartX) {
|
if (!disablePagination && touchEndX - drasticity > touchStartX) {
|
||||||
prevPage();
|
prevPage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSwipeDown() {
|
function handleSwipeDown() {
|
||||||
if (bottomBar.classList.contains("bottom-0"))
|
if (bottomBar.classList.contains("bottom-0")) {
|
||||||
bottomBar.classList.remove("bottom-0");
|
bottomBar.classList.remove("bottom-0");
|
||||||
else topBar.classList.add("top-0");
|
disablePagination = false;
|
||||||
|
} else {
|
||||||
|
topBar.classList.add("top-0");
|
||||||
|
populateTOC()
|
||||||
|
disablePagination = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSwipeUp() {
|
function handleSwipeUp() {
|
||||||
if (topBar.classList.contains("top-0")) topBar.classList.remove("top-0");
|
if (topBar.classList.contains("top-0")) {
|
||||||
else bottomBar.classList.add("bottom-0");
|
topBar.classList.remove("top-0");
|
||||||
|
disablePagination = false;
|
||||||
|
|
||||||
|
const tocEl = document.querySelector("#toc");
|
||||||
|
if (tocEl) tocEl.innerHTML = "";
|
||||||
|
} else {
|
||||||
|
bottomBar.classList.add("bottom-0");
|
||||||
|
disablePagination = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.rendition.hooks.render.register(function (doc, data) {
|
this.rendition.hooks.render.register(function (doc, data) {
|
||||||
@ -523,8 +587,8 @@ class EBookReader {
|
|||||||
// Handle Event
|
// Handle Event
|
||||||
if (yCoord < top) handleSwipeDown();
|
if (yCoord < top) handleSwipeDown();
|
||||||
else if (yCoord > bottom) handleSwipeUp();
|
else if (yCoord > bottom) handleSwipeUp();
|
||||||
else if (xCoord < left) prevPage();
|
else if (!disablePagination && xCoord < left) prevPage();
|
||||||
else if (xCoord > right) nextPage();
|
else if (!disablePagination && xCoord > right) nextPage();
|
||||||
else {
|
else {
|
||||||
bottomBar.classList.remove("bottom-0");
|
bottomBar.classList.remove("bottom-0");
|
||||||
topBar.classList.remove("top-0");
|
topBar.classList.remove("top-0");
|
||||||
@ -670,6 +734,9 @@ class EBookReader {
|
|||||||
// Close Top Bar
|
// Close Top Bar
|
||||||
document.querySelector(".close-top-bar").addEventListener("click", () => {
|
document.querySelector(".close-top-bar").addEventListener("click", () => {
|
||||||
topBar.classList.remove("top-0");
|
topBar.classList.remove("top-0");
|
||||||
|
|
||||||
|
const tocEl = document.querySelector("#toc");
|
||||||
|
if (tocEl) tocEl.innerHTML = "";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -949,10 +1016,16 @@ class EBookReader {
|
|||||||
**/
|
**/
|
||||||
async getXPathFromCFI(cfi) {
|
async getXPathFromCFI(cfi) {
|
||||||
// Get DocFragment (Spine Index)
|
// Get DocFragment (Spine Index)
|
||||||
let startCFI = cfi.replace("epubcfi(", "");
|
let cfiBaseMatch = cfi.match(/\(([^!]+)/);
|
||||||
|
if (!cfiBaseMatch) {
|
||||||
|
console.error("[getXPathFromCFI] No CFI Match");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
let startCFI = cfiBaseMatch[1];
|
||||||
|
|
||||||
let docFragmentIndex =
|
let docFragmentIndex =
|
||||||
this.book.spine.spineItems.find((item) =>
|
this.book.spine.spineItems.find((item) =>
|
||||||
startCFI.startsWith(item.cfiBase),
|
item.cfiBase == startCFI
|
||||||
).index + 1;
|
).index + 1;
|
||||||
|
|
||||||
// Base Progress
|
// Base Progress
|
||||||
@ -1029,10 +1102,6 @@ class EBookReader {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match Item Index
|
|
||||||
let indexMatch = xpath.match(/\.(\d+)$/);
|
|
||||||
let itemIndex = indexMatch ? parseInt(indexMatch[1]) : 0;
|
|
||||||
|
|
||||||
// Get Spine Item
|
// Get Spine Item
|
||||||
let spinePosition = parseInt(fragMatch[1]) - 1;
|
let spinePosition = parseInt(fragMatch[1]) - 1;
|
||||||
let sectionItem = this.book.spine.get(spinePosition);
|
let sectionItem = this.book.spine.get(spinePosition);
|
||||||
@ -1124,6 +1193,11 @@ class EBookReader {
|
|||||||
let element = docSearch.iterateNext() || derivedSelectorElement;
|
let element = docSearch.iterateNext() || derivedSelectorElement;
|
||||||
let cfi = sectionItem.cfiFromElement(element);
|
let cfi = sectionItem.cfiFromElement(element);
|
||||||
|
|
||||||
|
// Hack - epub.js crashes sometimes when its a bare section with no element
|
||||||
|
// so just return the first.
|
||||||
|
if (cfi.endsWith("!/)"))
|
||||||
|
cfi = cfi.slice(0, -1) + "0)"
|
||||||
|
|
||||||
return { cfi, element };
|
return { cfi, element };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1271,14 +1345,3 @@ class EBookReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", initReader);
|
document.addEventListener("DOMContentLoaded", initReader);
|
||||||
|
|
||||||
// WIP
|
|
||||||
async function getTOC() {
|
|
||||||
let toc = currentReader.book.navigation.toc;
|
|
||||||
|
|
||||||
// Alternatively:
|
|
||||||
// let nav = await currentReader.book.loaded.navigation;
|
|
||||||
// let toc = nav.toc;
|
|
||||||
|
|
||||||
currentReader.rendition.display(nav.toc[10].href);
|
|
||||||
}
|
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user