### Project Management Commands Source: https://github.com/futurepress/epub.js/blob/master/README.md Commands for installing dependencies, starting the reader, and running tests. ```javascript npm install ``` ```javascript npm start ``` ```javascript npm test ``` -------------------------------- ### Continuous Rendering Setup Source: https://github.com/futurepress/epub.js/blob/master/examples/hypothesis-continuous.html Initializes EPUB.js to render a book in a continuous, scrolled layout. Requires the EPUB.js library to be loaded. ```javascript var book = ePub("https://s3.amazonaws.com/epubjs/books/alice/OPS/package.opf"); var rendition = book.renderTo(document.body, { method: "continuous", flow: "scrolled-continuous", width: "60%" }); var displayed = rendition.display(); ``` -------------------------------- ### Rendition Lifecycle and Rendering Source: https://github.com/futurepress/epub.js/blob/master/documentation/md/API.md Methods for initializing, attaching, and starting the rendering process of the EPUB. ```APIDOC ## attachTo ### Description Call to attach the container to an element in the DOM. Container must be attached before rendering can begin. ### Parameters #### Path Parameters - **element** (element) - Required - The DOM element to attach to. ### Response - **Promise** - Resolves when attached. ## start ### Description Start the rendering process. ### Response - **Promise** - Resolves when rendering has started. ``` -------------------------------- ### Hook System (started) Source: https://github.com/futurepress/epub.js/blob/master/documentation/md/API.md Provides a mechanism for injecting and managing asynchronous functions that execute before a process completes. ```APIDOC ## Hook Hooks allow for injecting functions that must all complete in order before finishing They will execute in parallel but all must finish before continuing Functions may return a promise if they are async. ### Parameters - `context` (any) - scope of this ### Examples ```javascript this.content = new EPUBJS.Hook(this); ``` ## register Adds a function to be run before a hook completes ### Examples ```javascript this.content.register(function(){...}); ``` ## trigger Triggers a hook to run all functions ### Examples ```javascript this.content.trigger(args).then(function(){...}); ``` ``` -------------------------------- ### Load EPUB Locations and Setup Slider Source: https://github.com/futurepress/epub.js/blob/master/examples/locations.html Handles loading EPUB locations, either from stored data or by generating them. It then sets up a range slider for navigation and attaches event listeners for user interaction. ```javascript book.ready.then(function(){ // Load in stored locations from json or local storage var key = book.key()+'-locations'; var stored = localStorage.getItem(key); if (stored) { return book.locations.load(stored); } else { // Or generate the locations on the fly // Can pass an option number of chars to break sections by // default is 150 chars return book.locations.generate(1600); } }) .then(function(locations){ controls.style.display = "block"; slider.setAttribute("type", "range"); slider.setAttribute("min", 0); slider.setAttribute("max", 100); // slider.setAttribute("max", book.locations.total+1); slider.setAttribute("step", 1); slider.setAttribute("value", 0); slider.addEventListener("change", slide, false); slider.addEventListener("mousedown", function(){ mouseDown = true; }, false); slider.addEventListener("mouseup", function(){ mouseDown = false; }, false); // Wait for book to be rendered to get current page displayed.then(function(){ // Get the current CFI var currentLocation = rendition.currentLocation(); // Get the Percentage (or location) from that CFI var currentPage = book.locations.percentageFromCfi(currentLocation.start.cfi); slider.value = currentPage; currentPage.value = currentPage; }); controls.appendChild(slider); currentPage.addEventListener("change", function(){ var cfi = book.locations.cfiFromPercentage(currentPage.value/100); rendition.display(cfi); }, false); // Listen for location changed event, get percentage from CFI rendition.on('relocated', function(location){ var percent = book.locations.percentageFromCfi(location.start.cfi); var percentage = Math.floor(percent * 100); if(!mouseDown) { slider.value = percentage; } currentPage.value = percentage; console.log(location); }); // Save out the generated locations to JSON localStorage.setItem(book.key()+'-locations', book.locations.save()); }); ``` -------------------------------- ### Instantiate Book with options Source: https://github.com/futurepress/epub.js/blob/master/documentation/md/API.md Create a new Book instance, passing configuration options such as replacement strategies for assets. ```javascript new Book("/path/to/book.epub", {}) ``` ```javascript new Book({ replacements: "blobUrl" }) ``` -------------------------------- ### Initialize a Book Source: https://github.com/futurepress/epub.js/wiki/Updating-to-v0.3-from-v0.2 Load an EPUB file by providing the path to the OPF file. ```js var book = ePub("url/to/book/package.opf"); ``` -------------------------------- ### Initialize and Configure EPUB.js Rendition Source: https://github.com/futurepress/epub.js/blob/master/examples/themes.html Sets up the book instance, renders it to a viewer element with a continuous manager, and configures navigation, event listeners, and theme management. ```javascript var currentSectionIndex = 8; // Load the opf var book = ePub("https://s3.amazonaws.com/epubjs/books/alice/OPS/package.opf"); var rendition = book.renderTo("viewer", { width: "100%", height: 600, manager: "continuous" }); rendition.display("chapter_007.xhtml"); var title = document.getElementById("title"); var next = document.getElementById("next"); next.addEventListener("click", function(e){ rendition.next(); e.preventDefault(); }, false); var prev = document.getElementById("prev"); prev.addEventListener("click", function(e){ rendition.prev(); e.preventDefault(); }, false); var keyListener = function(e){ // Left Key if ((e.keyCode || e.which) == 37) { rendition.prev(); } // Right Key if ((e.keyCode || e.which) == 39) { rendition.next(); } }; rendition.on("keyup", keyListener); document.addEventListener("keyup", keyListener, false); rendition.on("rendered", function(section){ var nextSection = section.next(); var prevSection = section.prev(); var current = book.navigation.get(section.href); if (current) { title.textContent = current.label; } if(nextSection) { next.textContent = "›"; } else { next.textContent = ""; } if(prevSection) { prev.textContent = "‹"; } else { prev.textContent = ""; } }); rendition.on("relocated", function(location){ console.log(location); }); rendition.themes.register("dark", "themes.css"); rendition.themes.register("light", "themes.css"); rendition.themes.register("tan", "themes.css"); rendition.themes.default({ h2: { 'font-size': '32px', color: 'purple' }, p: { "margin": '10px' } }); rendition.themes.select("tan"); rendition.themes.fontSize("140%"); ``` -------------------------------- ### Viewport Management Source: https://github.com/futurepress/epub.js/blob/master/documentation/md/API.md Methods for getting or setting the viewport element, including its dimensions and scaling properties. ```APIDOC ## viewport ### Description Get or Set the viewport element. ### Parameters #### Request Body - **options** (object)? - Optional configuration object for the viewport. - **options.width** (string)? - The desired width of the viewport. - **options.height** (string)? - The desired height of the viewport. - **options.scale** (string)? - The scaling factor for the viewport. - **options.minimum** (string)? - The minimum scaling factor. - **options.maximum** (string)? - The maximum scaling factor. - **options.scalable** (string)? - Whether the viewport is scalable. ``` -------------------------------- ### Initialize EPUB.js Book and Continuous Rendition Source: https://github.com/futurepress/epub.js/blob/master/examples/continuous-spreads.html Sets up the book instance and configures the rendition manager for continuous paginated display. ```javascript var params = URLSearchParams && new URLSearchParams(document.location.search.substring(1)); var url = params && params.get("url") && decodeURIComponent(params.get("url")); var currentSectionIndex = (params && params.get("loc")) ? params.get("loc") : undefined; // Load the opf window.book = ePub(url || "https://s3.amazonaws.com/moby-dick/moby-dick.epub"); var rendition = book.renderTo("viewer", { manager: "continuous", flow: "paginated", width: "100%", height: 600 }); var displayed = rendition.display(currentSectionIndex); displayed.then(function(renderer){ // -- do stuff }); ``` -------------------------------- ### Utility Functions Source: https://github.com/futurepress/epub.js/blob/master/documentation/md/API.md Functions for resolving relative URLs, getting resource URLs, and substituting URLs within content. ```APIDOC ## relativeTo ### Description Resolve all resources URLs relative to an absolute URL. ### Method Not specified (likely a static method or function) ### Endpoint Not applicable (function call) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - `absolute` (string) - The absolute URL to resolve to. - `resolver` (resolver?) - The resolver object. ### Returns - `Array` - An array with relative URLs. ## get ### Description Get a URL for a resource. ### Method Not specified (likely a static method or function) ### Endpoint Not applicable (function call) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - `path` (string) - The path to the resource. ### Returns - `string` - The URL for the resource. ## substitute ### Description Substitute URLs in content, with replacements, relative to a URL if provided. ### Method Not specified (likely a static method or function) ### Endpoint Not applicable (function call) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - `content` (string) - The content with URLs to substitute. - `url` (string?) - The URL to resolve to, if provided. ### Returns - `string` - The content with URLs substituted. ``` -------------------------------- ### Initialize and Load an EPUB Book Source: https://context7.com/futurepress/epub.js/llms.txt Create a Book instance from various sources like URLs, ArrayBuffers, or Blobs. Use the ready promise to access metadata once the book is fully loaded. ```javascript // Load from URL var book = ePub("https://s3.amazonaws.com/moby-dick/moby-dick.epub"); // Load with options var book = ePub("/path/to/book.epub", { requestCredentials: true, requestHeaders: { "Authorization": "Bearer token" }, encoding: "binary", replacements: "blobUrl" // 'base64', 'blobUrl', or 'none' }); // Load from ArrayBuffer fetch("/path/to/book.epub") .then(response => response.arrayBuffer()) .then(data => { var book = ePub(data); }); // Wait for book to be fully loaded book.ready.then(function() { console.log("Book metadata:", book.packaging.metadata); console.log("Book title:", book.packaging.metadata.title); console.log("Book author:", book.packaging.metadata.creator); }); // Handle loading error book.opened.catch(function(error) { console.error("Failed to open book:", error); }); ``` -------------------------------- ### Initialize and Configure EPUB.js Viewer Source: https://github.com/futurepress/epub.js/blob/master/examples/manifest.html Sets up the EPUB.js book instance, renders it to a viewer element, and attaches event listeners for navigation and keyboard controls. ```javascript var src = window.location.search ? window.location.search.replace("?href=", '') : "https://readium2.now.sh/pub/L2hvbWUvbm93dXNlci9zcmMvbWlzYy9lcHVicy9jaGlsZHJlbnMtbGl0ZXJhdHVyZS5lcHVi/manifest.json" ; var book = ePub(src); var rendition = book.renderTo("viewer", { width: "100%", height: 600 }); rendition.display(); var title = document.getElementById("title"); var next = document.getElementById("next"); next.addEventListener("click", function(e){ rendition.next(); e.preventDefault(); }, false); var prev = document.getElementById("prev"); prev.addEventListener("click", function(e){ rendition.prev(); e.preventDefault(); }, false); var keyListener = function(e){ // Left Key if ((e.keyCode || e.which) == 37) { rendition.prev(); } // Right Key if ((e.keyCode || e.which) == 39) { rendition.next(); } }; rendition.on("keyup", keyListener); document.addEventListener("keyup", keyListener, false); var navigation = document.getElementById("navigation"); var opener = document.getElementById("opener"); opener.addEventListener("click", function(e){ navigation.classList.remove("closed"); e.preventDefault(); }, false); var closer = document.getElementById("closer"); closer.addEventListener("click", function(e){ navigation.classList.add("closed"); e.preventDefault(); }, false); book.loaded.navigation.then(function(toc){ var $nav = document.getElementById("toc"), docfrag = document.createDocumentFragment(); var addTocItems = function (parent, tocItems) { var $ul = document.createElement("ul"); tocItems.forEach(function(chapter) { var item = document.createElement("li"); var link = document.createElement("a"); link.textContent = chapter.label; link.href = chapter.href; item.appendChild(link); if (chapter.subitems) { addTocItems(item, chapter.subitems) } link.onclick = function(){ var url = link.getAttribute("href"); rendition.display(url); navigation.classList.add("closed"); return false; }; $ul.appendChild(item); }); parent.appendChild($ul); }; addTocItems(docfrag, toc); $nav.appendChild(docfrag); if ($nav.offsetHeight + 60 < window.innerHeight) { $nav.classList.add("fixed"); } }); book.loaded.metadata.then(function(meta){ var $title = document.getElementById("title"); var $author = document.getElementById("author"); var $cover = document.getElementById("cover"); $title.textContent = meta.title; $author.textContent = meta.creator; if (book.archive) { book.archive.createUrl(book.cover) .then(function (url) { $cover.src = url; }) } else { $cover.src = book.cover; } }); rendition.on("rendered", function(section){ var nextSection = section.next(); var prevSection = section.prev(); if(nextSection) { next.textContent = "›"; } else { next.textContent = ""; } if(prevSection) { prev.textContent = "‹"; } else { prev.textContent = ""; } }); rendition.on("relocated", function(location){ var current = book.navigation.get(location.href); if (current) { title.textContent = current.label; } console.log(location); }); window.addEventListener("unload", function () { this.book.destroy(); }); ``` -------------------------------- ### Get a canonical link to a path Source: https://github.com/futurepress/epub.js/blob/master/documentation/md/API.md Obtain a canonical link for a given path within the EPUB. This is useful for consistent referencing. ```javascript book.canonical(path) ``` -------------------------------- ### Initialize EPUB Viewer and Navigation Source: https://github.com/futurepress/epub.js/blob/master/examples/highlights.html Loads an EPUB file and sets up basic viewer and navigation controls. Ensure the 'viewer' element exists in your HTML. ```javascript var book = ePub("https://s3.amazonaws.com/moby-dick/OPS/package.opf"); var rendition = book.renderTo("viewer", { width: "100%", height: 600, ignoreClass: 'annotator-hl', manager: "continuous" }); var displayed = rendition.display(6); // Navigation loaded book.loaded.navigation.then(function(toc){ // console.log(toc); }); var next = document.getElementById("next"); next.addEventListener("click", function(){ rendition.next(); }, false); var prev = document.getElementById("prev"); prev.addEventListener("click", function(){ rendition.prev(); }, false); ``` -------------------------------- ### Rendered Location Range (location) Source: https://github.com/futurepress/epub.js/blob/master/documentation/md/API.md Represents a range within a rendered EPUB, including start and end points with detailed location information. ```APIDOC ## location A Rendered Location Range ### Properties - `start` (object) - `index` (string) - `href` (string) - `displayed` (object) - `page` (number) - `total` (number) - `cfi` (EpubCFI) - `location` (number) - `percentage` (number) - `end` (object) - `index` (string) - `href` (string) - `displayed` (object) - `page` (number) - `total` (number) - `cfi` (EpubCFI) - `location` (number) - `percentage` (number) - `atStart` (boolean) - `atEnd` (boolean) ``` -------------------------------- ### Get a Section from the Book's Spine Source: https://github.com/futurepress/epub.js/blob/master/documentation/md/API.md Retrieve a Section object from the book's spine using a target identifier. This is an alias for `book.spine.get`. ```javascript book.section(target) ``` -------------------------------- ### Initialize and Configure EPUB.js Reader Source: https://github.com/futurepress/epub.js/blob/master/examples/mathml.html Sets up the book instance, configures the rendition with spread support, and handles navigation events. ```javascript var params = URLSearchParams && new URLSearchParams(document.location.search.substring(1)); var url = params && params.get("url") && decodeURIComponent(params.get("url")); var currentSectionIndex = (params && params.get("loc")) ? params.get("loc") : undefined; // Load the opf var book = ePub(url || "http://epubjs.org/books/linear-algebra.epub"); var rendition = book.renderTo("viewer", { width: "100%", height: 600, spread: "always", allowScriptedContent: true }); rendition.display(currentSectionIndex); book.ready.then(() => { var next = document.getElementById("next"); next.addEventListener("click", function(e){ book.package.metadata.direction === "rtl" ? rendition.prev() : rendition.next(); e.preventDefault(); }, false); var prev = document.getElementById("prev"); prev.addEventListener("click", function(e){ book.package.metadata.direction === "rtl" ? rendition.next() : rendition.prev(); e.preventDefault(); }, false); var keyListener = function(e){ // Left Key if ((e.keyCode || e.which) == 37) { book.package.metadata.direction === "rtl" ? rendition.next() : rendition.prev(); } // Right Key if ((e.keyCode || e.which) == 39) { book.package.metadata.direction === "rtl" ? rendition.prev() : rendition.next(); } }; rendition.on("keyup", keyListener); document.addEventListener("keyup", keyListener, false); }) var title = document.getElementById("title"); rendition.on("rendered", function(section){ var current = book.navigation && book.navigation.get(section.href); if (current) { var $select = document.getElementById("toc"); var $selected = $select.querySelector("option[selected]"); if ($selected) { $selected.removeAttribute("selected"); } var $options = $select.querySelectorAll("option"); for (var i = 0; i < $options.length; ++i) { let selected = $options[i].getAttribute("ref") === current.href; if (selected) { $options[i].setAttribute("selected", ""); } } } }); rendition.on("relocated", function(location){ console.log(location); var next = book.package.metadata.direction === "rtl" ? document.getElementById("prev") : document.getElementById("next"); var prev = book.package.metadata.direction === "rtl" ? document.getElementById("next") : document.getElementById("prev"); if (location.atEnd) { next.style.visibility = "hidden"; } else { next.style.visibility = "visible"; } if (location.atStart) { prev.style.visibility = "hidden"; } else { prev.style.visibility = "visible"; } }); rendition.on("layout", function(layout) { let viewer = document.getElementById("viewer"); if (layout.spread) { viewer.classList.remove('single'); } else { viewer.classList.add('single'); } }); window.addEventListener("unload", function () { console.log("unloading"); this.book.destroy(); }); book.loaded.navigation.then(function(toc){ var $select = document.getElementById("toc"), docfrag = document.createDocumentFragment(); toc.forEach(function(chapter) { var option = document.createElement("option"); option.textContent = chapter.label; option.setAttribute("ref", chapter.href); docfrag.appendChild(option); }); $select.appendChild(docfrag); $select.onchange = function(){ var index = $select.selectedIndex, url = $select.options[index].getAttribute("ref"); rendition.display(url); return false; }; }); rendition.hooks.content.register(function (content) { let section = book.section(content.sectionIndex); let mathml = section.properties.includes("mathml"); if (mathml) { return content.addScript('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-MML-AM_CHTML'); } }); ``` -------------------------------- ### Handle Navigation Button Visibility Source: https://github.com/futurepress/epub.js/blob/master/examples/legacy.html Responds to the 'relocated' event to show or hide navigation buttons (next/prev) based on whether the book is at the start or end. ```javascript rendition.on("relocated", function(location){ console.log(location); var next = book.package.metadata.direction === "rtl" ? document.getElementById("prev") : document.getElementById("next"); var prev = book.package.metadata.direction === "rtl" ? document.getElementById("next") : document.getElementById("prev"); if (location.atEnd) { next.style.visibility = "hidden"; } else { next.style.visibility = "visible"; } if (location.atStart) { prev.style.visibility = "hidden"; } else { prev.style.visibility = "visible"; } }); ``` -------------------------------- ### Initialize EPUB Viewer and Navigation Source: https://github.com/futurepress/epub.js/blob/master/examples/locations.html Loads an EPUB file, sets up the rendition, and initializes navigation controls including next/previous buttons and a slider for seeking. It also handles keyboard navigation. ```javascript var controls = document.getElementById("controls"); var currentPage = document.getElementById("current-percent"); var slider = document.createElement("input"); var slide = function(){ var cfi = book.locations.cfiFromPercentage(slider.value / 100); rendition.display(cfi); }; var mouseDown = false; // Load the opf var book = ePub("https://s3.amazonaws.com/moby-dick/moby-dick.epub"); var rendition = book.renderTo("viewer", { width: "100%", height: 600 }); var displayed = rendition.display(); var title = document.getElementById("title"); var next = document.getElementById("next"); next.addEventListener("click", function(e){ rendition.next(); e.preventDefault(); }, false); var prev = document.getElementById("prev"); prev.addEventListener("click", function(e){ rendition.prev(); e.preventDefault(); }, false); var keyListener = function(e){ // Left Key if ((e.keyCode || e.which) == 37) { rendition.prev(); } // Right Key if ((e.keyCode || e.which) == 39) { rendition.next(); } }; rendition.on("keyup", keyListener); document.addEventListener("keyup", keyListener, false); ``` -------------------------------- ### Handle EPUB Relocated Event Source: https://github.com/futurepress/epub.js/blob/master/examples/embedded.html This event handler is triggered when the user navigates to a new location within the EPUB. It logs the CFI of the start of the new location. ```javascript rendition.on("relocated", function(location){ // console.log("locationChanged", location) console.log("locationChanged start", location.start.cfi) // console.log("locationChanged end", location.end.cfi) }); ``` -------------------------------- ### Add Single Script using Content Hook Source: https://github.com/futurepress/epub.js/blob/master/examples/hooks.html Registers a content hook to add a single script to the EPUB's content. This example uses jQuery. ```javascript rendition.hooks.content.register(function(contents){ return contents.addScript("https://code.jquery.com/jquery-2.1.4.min.js") .then(function(){ // init code }); }); ``` -------------------------------- ### Initialize EPUB and Render Source: https://github.com/futurepress/epub.js/blob/master/examples/offline.html Initializes an EPUB book instance with a specified storage name and renders it to a viewer element. Resources are added to storage after rendering. ```javascript var book = ePub("https://s3.amazonaws.com/moby-dick/", { store: "epubjs-test" }); var rendition = book.renderTo("viewer", { width: "100%", height: 600 }); var displayed = rendition.display(); displayed.then(function(renderer){ // Add all resources to the store // Add `true` to force re-saving resources book.storage.add(book.resources, true).then(() => { console.log("stored"); }) }); ``` -------------------------------- ### Initialize and Navigate EPUB.js Book Source: https://github.com/futurepress/epub.js/blob/master/examples/archived.html Initializes an EPUB book from a URL, renders it to a container, and sets up event listeners for navigation. ```javascript var book = ePub("https://s3.amazonaws.com/moby-dick/moby-dick.epub"); var rendition = book.renderTo("viewer", { width: "100%", height: 600 }); var displayed = rendition.display(); displayed.then(function(renderer){ // -- do stuff }); // Navigation loaded book.loaded.navigation.then(function(toc){ // console.log(toc); }); var next = document.getElementById("next"); next.addEventListener("click", function(){ rendition.next(); }, false); var prev = document.getElementById("prev"); prev.addEventListener("click", function(){ rendition.prev(); }, false); var keyListener = function(e){ // Left Key if ((e.keyCode || e.which) == 37) { rendition.prev(); } // Right Key if ((e.keyCode || e.which) == 39) { rendition.next(); } }; rendition.on("keyup", keyListener); document.addEventListener("keyup", keyListener, false); ``` -------------------------------- ### Register a Content Hook in Epub.js Source: https://github.com/futurepress/epub.js/blob/master/README.md This example shows how to register a hook to manipulate chapter contents after they are loaded and parsed. The hook can return a promise to block until its operations are complete. ```javascript rendition.hooks.content.register(function(contents, view) { var elements = contents.document.querySelectorAll('[video]'); var items = Array.prototype.slice.call(elements); items.forEach(function(item){ // do something with the video item }); }) ``` -------------------------------- ### Create a new Book instance Source: https://github.com/futurepress/epub.js/blob/master/documentation/md/API.md Instantiate a new Book object by providing the EPUB URL or path and optional configuration options. ```javascript ePub("/path/to/book.epub", {}) ``` -------------------------------- ### Generate and Load Locations Source: https://context7.com/futurepress/epub.js/llms.txt Generate locations for an EPUB to track reading progress. Locations can be generated once and saved for faster subsequent loads. This example uses localStorage to store generated locations. ```javascript var book = ePub("https://s3.amazonaws.com/moby-dick/moby-dick.epub"); var rendition = book.renderTo("viewer", { width: "100%", height: 600 }); rendition.display(); book.ready.then(function() { var key = book.key() + '-locations'; var stored = localStorage.getItem(key); if (stored) { // Load previously generated locations return book.locations.load(stored); } else { // Generate locations (1600 chars per location) return book.locations.generate(1600); } }).then(function(locations) { console.log("Total locations:", book.locations.length()); // Save locations for next time localStorage.setItem(book.key() + '-locations', book.locations.save()); }); // Track current position rendition.on("relocated", function(location) { var percent = book.locations.percentageFromCfi(location.start.cfi); console.log("Progress:", Math.floor(percent * 100) + "%"); console.log("Current page:", location.start.displayed.page); console.log("Total pages in section:", location.start.displayed.total); console.log("At start:", location.atStart); console.log("At end:", location.atEnd); }); // Navigate to percentage function goToPercentage(percent) { var cfi = book.locations.cfiFromPercentage(percent / 100); rendition.display(cfi); } // Get current location var currentLocation = rendition.currentLocation(); console.log("Start CFI:", currentLocation.start.cfi); console.log("End CFI:", currentLocation.end.cfi); ``` -------------------------------- ### Initialize and Render Book Source: https://github.com/futurepress/epub.js/blob/master/README.md Create a new ePub instance and render it to the specified DOM element. ```html ``` -------------------------------- ### Initialize and Navigate EPUB.js Book Source: https://github.com/futurepress/epub.js/blob/master/examples/renderless.html Initializes a book instance from a package document URL and sets up event listeners for navigation and TOC selection. ```javascript var $viewer = document.getElementById("viewer"); var $next = document.getElementById("next"); var $prev = document.getElementById("prev"); var currentSection; var currentSectionIndex = 6; var book = ePub("https://s3.amazonaws.com/epubjs/books/moby-dick/OPS/package.opf"); book.loaded.navigation.then(function(toc){ var $select = document.getElementById("toc"), docfrag = document.createDocumentFragment(); toc.forEach(function(chapter) { var option = document.createElement("option"); option.textContent = chapter.label; option.ref = chapter.href; docfrag.appendChild(option); }); $select.appendChild(docfrag); $select.onchange = function(){ var index = $select.selectedIndex, url = $select.options[index].ref; display(url); return false; }; book.opened.then(function(){ display(currentSectionIndex); }); $next.addEventListener("click", function(){ var displayed = display(currentSectionIndex+1); if(displayed) currentSectionIndex++; }, false); $prev.addEventListener("click", function(){ var displayed = display(currentSectionIndex-1); if(displayed) currentSectionIndex--; }, false); function display(item){ var section = book.spine.get(item); if(section) { currentSection = section; section.render().then(function(html){ // $viewer.srcdoc = html; $viewer.innerHTML = html; }); } return section; } }); ``` -------------------------------- ### Load EPUB and Get Text by Range Source: https://github.com/futurepress/epub.js/blob/master/examples/contents.html Use this snippet to load an EPUB file and extract text content from a specific CFI range. Ensure the EPUB.js library is included and an element with the ID 'viewer' exists in your HTML. ```javascript var $viewer = document.getElementById("viewer"); var book = ePub("https://s3.amazonaws.com/epubjs/books/moby-dick/OPS/package.opf"); book.ready.then(function(){ book.getRange("epubcfi(/6/14[xchapter_001]!/4/2,/2/2/2[c001s0000]/1:0,/8/2[c001p0003]/1:663)").then(function(range) { let text = range.toString() console.log(text); $viewer.textContent = text; }); }); ``` -------------------------------- ### Get Text from Saved CFI Range and Display Highlights Source: https://github.com/futurepress/epub.js/blob/master/examples/highlights.html Retrieves the text content corresponding to a saved CFI range, creates a list item to display the CFI and the text, and adds functionality to remove the highlight. This is useful for displaying a list of annotations. ```javascript var highlights = document.getElementById('highlights'); rendition.on("selected", function(cfiRange) { book.getRange(cfiRange).then(function (range) { var text; var li = document.createElement('li'); var a = document.createElement('a'); var remove = document.createElement('a'); var textNode; if (range) { text = range.toString(); textNode = document.createTextNode(text); a.textContent = cfiRange; a.href = "#" + cfiRange; a.onclick = function () { rendition.display(cfiRange); }; remove.textContent = "remove"; remove.href = "#" + cfiRange; remove.onclick = function () { rendition.annotations.remove(cfiRange); return false; }; li.appendChild(a); li.appendChild(textNode); li.appendChild(remove); highlights.appendChild(li); } }) }); ``` -------------------------------- ### Initialize EPUB.js Book and Rendition Source: https://github.com/futurepress/epub.js/blob/master/examples/swipe.html Loads an EPUB file from a URL and initializes the rendition manager with pagination settings. ```javascript // Load the opf var book = ePub("https://s3.amazonaws.com/epubjs/books/moby-dick/OPS/package.opf"); var rendition = book.renderTo("viewer", { manager: "continuous", flow: "paginated", width: "100%", height: "100%", snap: true }); var displayed = rendition.display("chapter_001.xhtml"); displayed.then(function(renderer){ // -- do stuff }); ``` -------------------------------- ### Load and Render EPUB with Navigation Source: https://github.com/futurepress/epub.js/blob/master/examples/hooks.html Initializes an EPUB book, renders it to a viewer, and sets up event listeners for next and previous page navigation. Requires an HTML element with the ID 'viewer' for rendering. ```javascript var currentSectionIndex = 8; // Load the opf var book = ePub("https://s3.amazonaws.com/epubjs/books/moby-dick/OPS/package.opf"); var rendition = book.renderTo("viewer", { flow: "scrolled-doc" }); rendition.display("chapter_001.xhtml"); var next = document.getElementById("next"); next.addEventListener("click", function(e){ rendition.next(); e.preventDefault(); }, false); var prev = document.getElementById("prev"); prev.addEventListener("click", function(e){ rendition.prev(); e.preventDefault(); }, false); ``` -------------------------------- ### Load and Display EPUB with EPUB.js Source: https://github.com/futurepress/epub.js/blob/master/examples/toc.html Initializes the EPUB viewer, loads an EPUB from a URL, and renders it. Requires HTML elements with IDs 'viewer', 'next', and 'prev'. ```javascript var $viewer = document.getElementById("viewer"); var $next = document.getElementById("next"); var $prev = document.getElementById("prev"); var currentSectionIndex = 9; // Load the opf var book = ePub("https://s3.amazonaws.com/moby-dick/OPS/package.opf"); var rendition = book.renderTo("viewer", { flow: "scrolled-doc", width: 600, height: 400}); var displayed = rendition.display(currentSectionIndex); book.loaded.navigation.then(function(toc){ var $select = document.getElementById("toc"), docfrag = document.createDocumentFragment(); toc.forEach(function(chapter) { var option = document.createElement("option"); option.textContent = chapter.label; option.ref = chapter.href; docfrag.appendChild(option); }); $select.appendChild(docfrag); $select.onchange = function(){ var index = $select.selectedIndex, url = $select.options[index].ref; rendition.display(url); return false; }; }); ``` -------------------------------- ### EPUB Rendering and Navigation Source: https://github.com/futurepress/epub.js/blob/master/examples/hypothesis.html Initialize EPUB.js, render the book to a viewer, and set up navigation controls for next and previous pages. ```javascript // Load the opf var params = URLSearchParams && new URLSearchParams(document.location.search.substring(1)); var url = params && params.get("url") && decodeURIComponent(params.get("url")); // Load the opf var book = ePub(url || window.location.protocol + "//s3.amazonaws.com/epubjs.org/books/moby-dick-hypothesis-demo.epub"); var rendition = book.renderTo("viewer", { flow: "scrolled-doc", ignoreClass: "annotator-hl" }); // var hash = window.location.hash.slice(2); var loc = window.location.href.indexOf("?loc="); if (loc > -1) { var href = window.location.href.slice(loc + 5); var hash = decodeURIComponent(href); } rendition.display(hash || undefined); var next = document.getElementById("next"); next.addEventListener("click", function(e){ window.scrollTo(0,0); rendition.next(); e.preventDefault(); }, false); var prev = document.getElementById("prev"); prev.addEventListener("click", function(e){ window.scrollTo(0,0); rendition.prev(); e.preventDefault(); }, false); ``` -------------------------------- ### Build Epub.js for Distribution Source: https://github.com/futurepress/epub.js/blob/master/README.md Run this command to generate a new build of Epub.js. For continuous building, use 'npm run watch'. ```javascript npm run prepare ``` ```javascript npm run watch ``` -------------------------------- ### Include Dependencies Source: https://github.com/futurepress/epub.js/blob/master/README.md Include JSZip before the Epub.js library when working with archived .epub files. ```html ``` ```html ``` -------------------------------- ### EPUB Navigation and Event Handling Source: https://github.com/futurepress/epub.js/blob/master/examples/spreads.html Sets up event listeners for navigation buttons (next/prev) and keyboard input to control EPUB rendering. It also handles updates to navigation elements based on the current view and layout. ```javascript book.ready.then(function() { var next = document.getElementById("next"); next.addEventListener("click", function(e){ book.package.metadata.direction === "rtl" ? rendition.prev() : rendition.next(); e.preventDefault(); }, false); var prev = document.getElementById("prev"); prev.addEventListener("click", function(e){ book.package.metadata.direction === "rtl" ? rendition.next() : rendition.prev(); e.preventDefault(); }, false); var keyListener = function(e){ // Left Key if ((e.keyCode || e.which) == 37) { book.package.metadata.direction === "rtl" ? rendition.next() : rendition.prev(); } // Right Key if ((e.keyCode || e.which) == 39) { book.package.metadata.direction === "rtl" ? rendition.prev() : rendition.next(); } }; rendition.on("keyup", keyListener); document.addEventListener("keyup", keyListener, false); }); ``` ```javascript var title = document.getElementById("title"); rendition.on("rendered", function(section){ var current = book.navigation && book.navigation.get(section.href); if (current) { var $select = document.getElementById("toc"); var $selected = $select.querySelector("option\[selected\]"); if ($selected) { $selected.removeAttribute("selected"); } var $options = $select.querySelectorAll("option"); for (var i = 0; i < $options.length; ++i) { let selected = $options[i].getAttribute("ref") === current.href; if (selected) { $options[i].setAttribute("selected", ""); } } } }); ``` ```javascript rendition.on("relocated", function(location){ console.log(location); var next = book.package.metadata.direction === "rtl" ? document.getElementById("prev") : document.getElementById("next"); var prev = book.package.metadata.direction === "rtl" ? document.getElementById("next") : document.getElementById("prev"); if (location.atEnd) { next.style.visibility = "hidden"; } else { next.style.visibility = "visible"; } if (location.atStart) { prev.style.visibility = "hidden"; } else { prev.style.visibility = "visible"; } }); ``` ```javascript rendition.on("layout", function(layout) { let viewer = document.getElementById("viewer"); if (layout.spread) { viewer.classList.remove('single'); } else { viewer.classList.add('single'); } }); ``` ```javascript window.addEventListener("unload", function () { console.log("unloading"); this.book.destroy(); }); ``` -------------------------------- ### Load and Render EPUB with Annotator Source: https://github.com/futurepress/epub.js/blob/master/examples/annotator.html Initializes EPUB.js, renders the book to a specified div, and integrates the Annotator library. Requires jQuery and Annotator scripts and CSS. Customizes mouse position tracking for annotations. ```javascript // Load the opf var book = ePub("https://s3.amazonaws.com/moby-dick/OPS/package.opf"); var rendition = book.renderTo("viewer", { width: "100%", height: 600, ignoreClass: 'annotator-hl' }); var displayed = rendition.display(3); // Navigation loaded book.loaded.navigation.then(function(toc){ // console.log(toc); }); var next = document.getElementById("next"); next.addEventListener("click", function(){ rendition.next(); }, false); var prev = document.getElementById("prev"); prev.addEventListener("click", function(){ rendition.prev(); }, false); var keyListener = function(e){ // Left Key if ((e.keyCode || e.which) == 37) { rendition.prev(); } // Right Key if ((e.keyCode || e.which) == 39) { rendition.next(); } }; rendition.on("keyup", keyListener); document.addEventListener("keyup", keyListener, false); rendition.on("relocated", function(location){ // console.log(location); }); rendition.hooks.render.register(function (view) { var adder = [ ['.annotator-adder, .annotator-outer', [['position', 'fixed']]] ]; view.addScript('https://cdn.jsdelivr.net/jquery/3.0.0-beta1/jquery.min.js'). then(function () { return view.addScript('https://cdn.jsdelivr.net/annotator/1.2.9/annotator-full.min.js'); }). then(function () { return view.addCss('https://cdn.jsdelivr.net/annotator/1.2.9/annotator.min.css'); }). then(function () { view.addStylesheetRules(adder); view.window.Annotator.Util.mousePosition = function(event) { var body = view.document.body; // var offset = view.position(); return { top: event.pageY, left: event.pageX }; }; var ann = new view.window.Annotator(view.document.body); }) }) ``` -------------------------------- ### Handle Navigation Events Source: https://github.com/futurepress/epub.js/blob/master/examples/swipe.html Sets up event listeners for UI buttons and keyboard inputs to navigate through the book. ```javascript // Navigation loaded book.loaded.navigation.then(function(toc){ // console.log(toc); }); var next = document.getElementById("next"); next.addEventListener("click", function(){ rendition.next(); }, false); var prev = document.getElementById("prev"); prev.addEventListener("click", function(){ rendition.prev(); }, false); document.addEventListener("keyup", function(e){ // Left Key if ((e.keyCode || e.which) == 37) { rendition.prev(); } // Right Key if ((e.keyCode || e.which) == 39) { rendition.next(); } }, false); // $(window).on( "swipeleft", function( event ) { // rendition.next(); // }); // // $(window).on( "swiperight", function( event ) { // rendition.prev(); // }); ``` -------------------------------- ### Navigation Event Listeners Source: https://github.com/futurepress/epub.js/blob/master/examples/offline.html Sets up event listeners for 'next' and 'prev' buttons, and keyboard events (left/right arrow keys) to navigate through the EPUB. ```javascript var next = document.getElementById("next"); next.addEventListener("click", function(){ rendition.next(); }, false); var prev = document.getElementById("prev"); prev.addEventListener("click", function(){ rendition.prev(); }, false); var keyListener = function(e){ // Left Key if ((e.keyCode || e.which) == 37) { rendition.prev(); } // Right Key if ((e.keyCode || e.which) == 39) { rendition.next(); } }; rendition.on("keyup", keyListener); document.addEventListener("keyup", keyListener, false); ``` -------------------------------- ### Configure Hypothes.is for EPUB.js Source: https://github.com/futurepress/epub.js/blob/master/examples/hypothesis-spreads.html Sets up the Hypothes.is configuration object to manage sidebar visibility and layout-triggered navigation updates. ```javascript window.hypothesisConfig = function () { return { openSidebar: false, enableMultiFrameSupport: true, onLayoutChange: function(state) { var nav = document.getElementById("navigation"); if (state.expanded === true) { nav.classList.remove("open"); } } }; }; ``` -------------------------------- ### Initialize and Render EPUB (Scrolled Document) Source: https://github.com/futurepress/epub.js/blob/master/examples/single-full.html Loads an EPUB from a URL and renders it to a 'viewer' div using the 'scrolled-doc' flow. Handles initial display based on the URL hash and sets up event listeners for next/previous page navigation. ```javascript var book = ePub("https://s3.amazonaws.com/moby-dick/moby-dick.epub"); var rendition = book.renderTo("viewer", { flow: "scrolled-doc" }); var hash = window.location.hash.slice(2); console.log(hash); rendition.display(hash || undefined); ``` -------------------------------- ### Register and Select Themes Source: https://context7.com/futurepress/epub.js/llms.txt Register CSS stylesheets or rule objects to dynamically switch between themes. This allows for runtime styling of the EPUB content. ```javascript var book = ePub("https://s3.amazonaws.com/epubjs/books/alice/OPS/package.opf"); var rendition = book.renderTo("viewer", { width: "100%", height: 600, manager: "continuous" }); rendition.display(); // Register themes from CSS files rendition.themes.register("dark", "/themes/dark.css"); rendition.themes.register("light", "/themes/light.css"); rendition.themes.register("sepia", "/themes/sepia.css"); // Register theme as CSS rules object rendition.themes.register("custom", { "body": { "background-color": "#f4f4f4", "color": "#333" }, "h1, h2, h3": { "color": "#1a1a1a" }, "a": { "color": "#0066cc" } }); // Set default styles rendition.themes.default({ "body": { "font-family": "Georgia, serif", "line-height": "1.6" }, "p": { "margin": "10px 0" } }); // Select active theme rendition.themes.select("dark"); // Change font size rendition.themes.fontSize("120%"); // Change font family rendition.themes.font("Helvetica, Arial, sans-serif"); // Override specific CSS property rendition.themes.override("color", "#333", true); // true = !important ``` -------------------------------- ### EPUB Rendering and Pagination with EPUB.js Source: https://github.com/futurepress/epub.js/blob/master/examples/marks.html Loads an EPUB, renders it to a specified element, and sets up navigation controls for moving between pages. Includes event listeners for 'next' and 'prev' buttons, as well as keyboard input. ```javascript var book = ePub("https://s3.amazonaws.com/moby-dick/OPS/package.opf"); var rendition = book.renderTo("viewer", { width: "100%", height: 600 }); var displayed = rendition.display(6); // Navigation loaded book.loaded.navigation.then(function(toc){ // console.log(toc); }); var next = document.getElementById("next"); next.addEventListener("click", function(){ rendition.next(); }, false); var prev = document.getElementById("prev"); prev.addEventListener("click", function(){ rendition.prev(); }, false); var keyListener = function(e){ // Left Key if ((e.keyCode || e.which) == 37) { rendition.prev(); } // Right Key if ((e.keyCode || e.which) == 39) { rendition.next(); } }; rendition.on("keyup", keyListener); document.addEventListener("keyup", keyListener, false); rendition.on("relocated", function(location){ // console.log(location); }); ``` -------------------------------- ### Initialize a Hook Source: https://github.com/futurepress/epub.js/blob/master/documentation/md/API.md Creates a new instance of the Hook class with the provided context. ```javascript this.content = new EPUBJS.Hook(this); ```