diff options
author | Andrew Dolgov <[email protected]> | 2021-09-17 21:53:37 +0300 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2021-09-17 21:53:37 +0300 |
commit | 4fd9b8f2b5a98bfcde57970b48fed2488a80f356 (patch) | |
tree | 51e0ce9cd61c24916b7d5820ee69e74bd3e76aac /lib/epub.js/src/pagelist.js | |
parent | d0cd10f08286be33306336fe8c4cac26ea7ce637 (diff) |
add in master snapshot of epubjs
Diffstat (limited to 'lib/epub.js/src/pagelist.js')
-rw-r--r-- | lib/epub.js/src/pagelist.js | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/lib/epub.js/src/pagelist.js b/lib/epub.js/src/pagelist.js new file mode 100644 index 0000000..6de82f6 --- /dev/null +++ b/lib/epub.js/src/pagelist.js @@ -0,0 +1,274 @@ +import EpubCFI from "./epubcfi"; +import { + qs, + qsa, + querySelectorByType, + indexOfSorted, + locationOf +} from "./utils/core"; + +/** + * Page List Parser + * @param {document} [xml] + */ +class PageList { + constructor(xml) { + this.pages = []; + this.locations = []; + this.epubcfi = new EpubCFI(); + + this.firstPage = 0; + this.lastPage = 0; + this.totalPages = 0; + + this.toc = undefined; + this.ncx = undefined; + + if (xml) { + this.pageList = this.parse(xml); + } + + if(this.pageList && this.pageList.length) { + this.process(this.pageList); + } + } + + /** + * Parse PageList Xml + * @param {document} xml + */ + parse(xml) { + var html = qs(xml, "html"); + var ncx = qs(xml, "ncx"); + + if(html) { + return this.parseNav(xml); + } else if(ncx){ + return this.parseNcx(xml); + } + + } + + /** + * Parse a Nav PageList + * @private + * @param {node} navHtml + * @return {PageList.item[]} list + */ + parseNav(navHtml){ + var navElement = querySelectorByType(navHtml, "nav", "page-list"); + var navItems = navElement ? qsa(navElement, "li") : []; + var length = navItems.length; + var i; + var list = []; + var item; + + if(!navItems || length === 0) return list; + + for (i = 0; i < length; ++i) { + item = this.item(navItems[i]); + list.push(item); + } + + return list; + } + + parseNcx(navXml) { + var list = []; + var i = 0; + var item; + var pageList; + var pageTargets; + var length = 0; + + pageList = qs(navXml, "pageList"); + if (!pageList) return list; + + pageTargets = qsa(pageList, "pageTarget"); + length = pageTargets.length; + + if (!pageTargets || pageTargets.length === 0) { + return list; + } + + for (i = 0; i < length; ++i) { + item = this.ncxItem(pageTargets[i]); + list.push(item); + } + + return list; + } + + ncxItem(item) { + var navLabel = qs(item, "navLabel"); + var navLabelText = qs(navLabel, "text"); + var pageText = navLabelText.textContent; + var content = qs(item, "content"); + + var href = content.getAttribute("src"); + var page = parseInt(pageText, 10); + + return { + "href": href, + "page": page, + }; + } + + /** + * Page List Item + * @private + * @param {node} item + * @return {object} pageListItem + */ + item(item){ + var content = qs(item, "a"), + href = content.getAttribute("href") || "", + text = content.textContent || "", + page = parseInt(text), + isCfi = href.indexOf("epubcfi"), + split, + packageUrl, + cfi; + + if(isCfi != -1) { + split = href.split("#"); + packageUrl = split[0]; + cfi = split.length > 1 ? split[1] : false; + return { + "cfi" : cfi, + "href" : href, + "packageUrl" : packageUrl, + "page" : page + }; + } else { + return { + "href" : href, + "page" : page + }; + } + } + + /** + * Process pageList items + * @private + * @param {array} pageList + */ + process(pageList){ + pageList.forEach(function(item){ + this.pages.push(item.page); + if (item.cfi) { + this.locations.push(item.cfi); + } + }, this); + this.firstPage = parseInt(this.pages[0]); + this.lastPage = parseInt(this.pages[this.pages.length-1]); + this.totalPages = this.lastPage - this.firstPage; + } + + /** + * Get a PageList result from a EpubCFI + * @param {string} cfi EpubCFI String + * @return {number} page + */ + pageFromCfi(cfi){ + var pg = -1; + + // Check if the pageList has not been set yet + if(this.locations.length === 0) { + return -1; + } + + // TODO: check if CFI is valid? + + // check if the cfi is in the location list + // var index = this.locations.indexOf(cfi); + var index = indexOfSorted(cfi, this.locations, this.epubcfi.compare); + if(index != -1) { + pg = this.pages[index]; + } else { + // Otherwise add it to the list of locations + // Insert it in the correct position in the locations page + //index = EPUBJS.core.insert(cfi, this.locations, this.epubcfi.compare); + index = locationOf(cfi, this.locations, this.epubcfi.compare); + // Get the page at the location just before the new one, or return the first + pg = index-1 >= 0 ? this.pages[index-1] : this.pages[0]; + if(pg !== undefined) { + // Add the new page in so that the locations and page array match up + //this.pages.splice(index, 0, pg); + } else { + pg = -1; + } + + } + return pg; + } + + /** + * Get an EpubCFI from a Page List Item + * @param {string | number} pg + * @return {string} cfi + */ + cfiFromPage(pg){ + var cfi = -1; + // check that pg is an int + if(typeof pg != "number"){ + pg = parseInt(pg); + } + + // check if the cfi is in the page list + // Pages could be unsorted. + var index = this.pages.indexOf(pg); + if(index != -1) { + cfi = this.locations[index]; + } + // TODO: handle pages not in the list + return cfi; + } + + /** + * Get a Page from Book percentage + * @param {number} percent + * @return {number} page + */ + pageFromPercentage(percent){ + var pg = Math.round(this.totalPages * percent); + return pg; + } + + /** + * Returns a value between 0 - 1 corresponding to the location of a page + * @param {number} pg the page + * @return {number} percentage + */ + percentageFromPage(pg){ + var percentage = (pg - this.firstPage) / this.totalPages; + return Math.round(percentage * 1000) / 1000; + } + + /** + * Returns a value between 0 - 1 corresponding to the location of a cfi + * @param {string} cfi EpubCFI String + * @return {number} percentage + */ + percentageFromCfi(cfi){ + var pg = this.pageFromCfi(cfi); + var percentage = this.percentageFromPage(pg); + return percentage; + } + + /** + * Destroy + */ + destroy() { + this.pages = undefined; + this.locations = undefined; + this.epubcfi = undefined; + + this.pageList = undefined; + + this.toc = undefined; + this.ncx = undefined; + } +} + +export default PageList; |