mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-04 15:09:16 +02:00
handle compressed epubs
This commit is contained in:
parent
0cfaa9cf2e
commit
cb813ab927
26 changed files with 5593 additions and 4871 deletions
562
build/epub.js
562
build/epub.js
|
@ -1,4 +1,4 @@
|
|||
/*! FuturePress - v0.1.0 - 2013-06-30 */
|
||||
/*! FuturePress - v0.1.0 - 2013-07-08 */
|
||||
|
||||
var EPUBJS = EPUBJS || {};
|
||||
EPUBJS.VERSION = "0.1.5";
|
||||
|
@ -21,7 +21,7 @@ EPUBJS.Book = function(bookPath, options){
|
|||
spreads: true,
|
||||
responsive: true,
|
||||
version: 1,
|
||||
restore: false
|
||||
restore: true
|
||||
});
|
||||
|
||||
this.settings.EPUBJSVERSION = EPUBJS.VERSION;
|
||||
|
@ -73,7 +73,7 @@ EPUBJS.Book = function(bookPath, options){
|
|||
}
|
||||
|
||||
// Likewise if an element is present start rendering process
|
||||
if(this.settings.element) {
|
||||
if(bookPath && this.settings.element) {
|
||||
this.opened.then(function(){
|
||||
this.rendered = this.renderTo(el);
|
||||
});
|
||||
|
@ -87,30 +87,46 @@ EPUBJS.Book = function(bookPath, options){
|
|||
|
||||
|
||||
//-- Check bookUrl and start parsing book Assets or load them from storage
|
||||
|
||||
EPUBJS.Book.prototype.open = function(bookPath, forceReload){
|
||||
var book = this,
|
||||
saved = this.isSaved(bookPath),
|
||||
opened;
|
||||
|
||||
this.settings.bookPath = bookPath;
|
||||
|
||||
//-- Get a absolute URL from the book path
|
||||
this.bookUrl = this.urlFrom(bookPath);
|
||||
|
||||
// console.log("saved", saved, !forceReload)
|
||||
//-- Remove the previous settings and reload
|
||||
if(forceReload){
|
||||
this.removeSavedSettings();
|
||||
}
|
||||
|
||||
//-- Check for a saved settings object, with the same url and version
|
||||
if(this.isSaved()){
|
||||
|
||||
if(saved && !forceReload){
|
||||
//-- Apply settings, keeping newer ones
|
||||
this.applySavedSettings();
|
||||
}
|
||||
|
||||
if(this.settings.contained || this.isContained(bookPath)){
|
||||
|
||||
if(this.settings.restore){
|
||||
|
||||
this.settings.contained = this.contained = true;
|
||||
|
||||
this.bookUrl = '';
|
||||
|
||||
// return; //-- TODO: this need to be fixed and tested before enabling
|
||||
opened = this.unarchive(bookPath).then(function(){
|
||||
|
||||
if(saved && book.settings.restore && !forceReload){
|
||||
return book.restore();
|
||||
}else{
|
||||
return book.unpack();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
if(saved && this.settings.restore && !forceReload){
|
||||
//-- Will load previous package json, or re-unpack if error
|
||||
opened = this.restore();
|
||||
|
||||
|
||||
}else{
|
||||
|
||||
//-- Get package information from epub opf
|
||||
|
@ -118,21 +134,6 @@ EPUBJS.Book.prototype.open = function(bookPath, forceReload){
|
|||
|
||||
}
|
||||
|
||||
} else if(this.settings.contained || this.isContained(this.bookUrl)){
|
||||
|
||||
|
||||
this.settings.contained = this.contained = true;
|
||||
this.settings.restore = true;
|
||||
|
||||
return; //-- TODO: this need to be fixed and tested before enabling
|
||||
opened = this.unarchive(this.bookUrl).then(function(){
|
||||
return book.unpack();
|
||||
});
|
||||
|
||||
}else{
|
||||
|
||||
//-- Get package information from epub opf
|
||||
opened = book.unpack();
|
||||
}
|
||||
|
||||
//-- If there is network connection, store the books contents
|
||||
|
@ -164,7 +165,6 @@ EPUBJS.Book.prototype.unpack = function(containerPath){
|
|||
}).
|
||||
then(function(contents){
|
||||
|
||||
|
||||
book.contents = contents;
|
||||
|
||||
book.manifest = book.contents.manifest;
|
||||
|
@ -173,7 +173,7 @@ EPUBJS.Book.prototype.unpack = function(containerPath){
|
|||
book.metadata = book.contents.metadata;
|
||||
|
||||
book.cover = book.contents.cover = book.settings.contentsPath + contents.coverPath;
|
||||
|
||||
|
||||
book.spineNodeIndex = book.contents.spineNodeIndex = contents.spineNodeIndex;
|
||||
|
||||
book.ready.manifest.resolve(book.contents.manifest);
|
||||
|
@ -192,8 +192,9 @@ EPUBJS.Book.prototype.unpack = function(containerPath){
|
|||
}).then(function(toc){
|
||||
book.toc = book.contents.toc = toc;
|
||||
book.ready.toc.resolve(book.contents.toc);
|
||||
// book.saveSettings();
|
||||
}).then(null, function(error) {
|
||||
console.log("Error:", error)
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
|
||||
|
@ -237,9 +238,10 @@ EPUBJS.Book.prototype.networkListeners = function(){
|
|||
|
||||
//-- Choose between a request from store or a request from network
|
||||
EPUBJS.Book.prototype.loadXml = function(url){
|
||||
|
||||
if(this.settings.storage) {
|
||||
if(this.settings.fromStorage) {
|
||||
return this.storage.getXml(url);
|
||||
} else if(this.settings.contained) {
|
||||
return this.zip.getXml(url);
|
||||
}else{
|
||||
return EPUBJS.core.request(url, 'xml');
|
||||
}
|
||||
|
@ -255,7 +257,7 @@ EPUBJS.Book.prototype.urlFrom = function(bookPath){
|
|||
|
||||
|
||||
|
||||
if(bookPath[bookPath.length - 1] != "/") bookPath += "/";
|
||||
// if(bookPath[bookPath.length - 1] != "/") bookPath += "/";
|
||||
|
||||
//-- 1. Check if url is absolute
|
||||
if(absolute){
|
||||
|
@ -275,18 +277,19 @@ EPUBJS.Book.prototype.urlFrom = function(bookPath){
|
|||
}
|
||||
|
||||
|
||||
EPUBJS.Book.prototype.unarchive = function(bookPath){
|
||||
var unzipped;
|
||||
|
||||
EPUBJS.Book.prototype.unarchive = function(bookPath){
|
||||
var book = this,
|
||||
unarchived;
|
||||
|
||||
//-- Must use storage
|
||||
if(this.settings.storage == false ){
|
||||
this.settings.storage = true;
|
||||
this.storage = new fileStorage.storage();
|
||||
}
|
||||
// if(this.settings.storage == false ){
|
||||
// this.settings.storage = true;
|
||||
// this.storage = new fileStorage.storage();
|
||||
// }
|
||||
|
||||
unzipped = new EPUBJS.Unarchiver(bookPath);
|
||||
|
||||
return unzipped;
|
||||
this.zip = new EPUBJS.Unarchiver();
|
||||
|
||||
return this.zip.openZip(bookPath);
|
||||
}
|
||||
|
||||
//-- Checks if url has a .epub or .zip extension
|
||||
|
@ -302,8 +305,8 @@ EPUBJS.Book.prototype.isContained = function(bookUrl){
|
|||
}
|
||||
|
||||
//-- Checks if the book setting can be retrieved from localStorage
|
||||
EPUBJS.Book.prototype.isSaved = function() {
|
||||
var bookKey = this.bookUrl + ":" + this.settings.version,
|
||||
EPUBJS.Book.prototype.isSaved = function(bookPath) {
|
||||
var bookKey = bookPath + ":" + this.settings.version,
|
||||
storedSettings = localStorage.getItem(bookKey);
|
||||
|
||||
if( !localStorage ||
|
||||
|
@ -316,7 +319,7 @@ EPUBJS.Book.prototype.isSaved = function() {
|
|||
|
||||
//-- Remove save book settings
|
||||
EPUBJS.Book.prototype.removeSavedSettings = function() {
|
||||
var bookKey = this.bookUrl + ":" + this.settings.version;
|
||||
var bookKey = this.settings.bookPath + ":" + this.settings.version;
|
||||
|
||||
localStorage.removeItem(bookKey);
|
||||
|
||||
|
@ -324,16 +327,15 @@ EPUBJS.Book.prototype.removeSavedSettings = function() {
|
|||
}
|
||||
|
||||
EPUBJS.Book.prototype.applySavedSettings = function() {
|
||||
var bookKey = this.bookUrl + ":" + this.settings.version;
|
||||
var bookKey = this.settings.bookPath + ":" + this.settings.version;
|
||||
stored = JSON.parse(localStorage.getItem(bookKey));
|
||||
|
||||
|
||||
if(EPUBJS.VERSION != stored.EPUBJSVERSION) return false;
|
||||
|
||||
this.settings = _.defaults(this.settings, stored);
|
||||
this.settings = _.defaults(this.settings, stored);
|
||||
}
|
||||
|
||||
EPUBJS.Book.prototype.saveSettings = function(){
|
||||
var bookKey = this.bookUrl + ":" + this.settings.version;
|
||||
var bookKey = this.settings.bookPath + ":" + this.settings.version;
|
||||
|
||||
if(this.render) {
|
||||
this.settings.previousLocationCfi = this.render.currentLocationCfi;
|
||||
|
@ -344,7 +346,7 @@ EPUBJS.Book.prototype.saveSettings = function(){
|
|||
}
|
||||
|
||||
EPUBJS.Book.prototype.saveContents = function(){
|
||||
var contentsKey = this.settings.contentsPath + ":" + this.settings.version;
|
||||
var contentsKey = this.settings.bookPath + ":contents:" + this.settings.version;
|
||||
|
||||
localStorage.setItem(contentsKey, JSON.stringify(this.contents));
|
||||
|
||||
|
@ -371,7 +373,7 @@ EPUBJS.Book.prototype.renderTo = function(el){
|
|||
|
||||
EPUBJS.Book.prototype.startDisplay = function(){
|
||||
var display;
|
||||
if( this.settings.previousLocationCfi) {
|
||||
if( this.settings.restore && this.settings.previousLocationCfi) {
|
||||
|
||||
display = this.displayChapter(this.settings.previousLocationCfi);
|
||||
|
||||
|
@ -385,13 +387,13 @@ EPUBJS.Book.prototype.startDisplay = function(){
|
|||
EPUBJS.Book.prototype.restore = function(){
|
||||
|
||||
var book = this,
|
||||
contentsKey = this.settings.contentsPath + ":" + this.settings.version,
|
||||
contentsKey = this.settings.bookPath + ":contents:" + this.settings.version,
|
||||
promise = new RSVP.Promise(),
|
||||
fetch = ['manifest', 'spine', 'metadata', 'cover', 'toc', 'spineNodeIndex', 'spineIndexByURL'],
|
||||
reject = false,
|
||||
fromStore = localStorage.getItem(contentsKey);
|
||||
|
||||
if(this.settings.contentsPath && fromStore){
|
||||
|
||||
if(fromStore != 'undefined'){
|
||||
this.contents = JSON.parse(fromStore);
|
||||
|
||||
fetch.forEach(function(item){
|
||||
|
@ -402,12 +404,9 @@ EPUBJS.Book.prototype.restore = function(){
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
if(reject || !fromStore || !this.contents ){
|
||||
|
||||
this.removeSavedSettings();
|
||||
|
||||
return this.unpack();
|
||||
if(reject || !fromStore || !this.contents || !this.settings.contentsPath){
|
||||
// this.removeSavedSettings();
|
||||
return this.open(this.settings.bookPath, true);
|
||||
|
||||
}else{
|
||||
this.ready.manifest.resolve(this.manifest);
|
||||
|
@ -415,7 +414,6 @@ EPUBJS.Book.prototype.restore = function(){
|
|||
this.ready.metadata.resolve(this.metadata);
|
||||
this.ready.cover.resolve(this.cover);
|
||||
this.ready.toc.resolve(this.toc);
|
||||
|
||||
promise.resolve();
|
||||
return promise;
|
||||
}
|
||||
|
@ -469,7 +467,8 @@ EPUBJS.Book.prototype.displayChapter = function(chap, end){
|
|||
}
|
||||
|
||||
|
||||
if(!this.settings.storage) {
|
||||
if(!this.settings.fromStorage &&
|
||||
!this.settings.contained) {
|
||||
render.then(function(){
|
||||
book.preloadNextChapter();
|
||||
});
|
||||
|
@ -600,7 +599,7 @@ EPUBJS.Book.prototype.setStyle = function(style, val, prefixed) {
|
|||
EPUBJS.Book.prototype.removeStyle = function(style, val, prefixed) {
|
||||
this.renderer.removeStyle(style);
|
||||
|
||||
delete this.settings.styles[style] = '';
|
||||
delete this.settings.styles[style];
|
||||
}
|
||||
|
||||
|
||||
|
@ -622,19 +621,26 @@ EPUBJS.Book.prototype.getHooks = function(){
|
|||
|
||||
//-- Hooks allow for injecting async functions that must all complete before continuing
|
||||
// Functions must have a callback as their first argument.
|
||||
EPUBJS.Book.prototype.registerHook = function(type, toAdd){
|
||||
var that = this;
|
||||
EPUBJS.Book.prototype.registerHook = function(type, toAdd, toFront){
|
||||
var book = this;
|
||||
|
||||
if(typeof(this.hooks[type]) != "undefined"){
|
||||
|
||||
if(typeof(toAdd) === "function"){
|
||||
this.hooks[type].push(toAdd);
|
||||
if(toFront) {
|
||||
this.hooks[type].unshift(toAdd);
|
||||
}else{
|
||||
this.hooks[type].push(toAdd);
|
||||
}
|
||||
}else if(Array.isArray(toAdd)){
|
||||
toAdd.forEach(function(hook){
|
||||
that.hooks[type].push(hook);
|
||||
if(toFront) {
|
||||
book.hooks[type].unshift(hook);
|
||||
}else{
|
||||
book.hooks[type].push(hook);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}else{
|
||||
//-- Allows for undefined hooks, but maybe this should error?
|
||||
this.hooks[type] = [func];
|
||||
|
@ -685,9 +691,12 @@ EPUBJS.Chapter.prototype.contents = function(store){
|
|||
|
||||
EPUBJS.Chapter.prototype.url = function(store){
|
||||
var promise = new RSVP.Promise();
|
||||
|
||||
|
||||
if(store){
|
||||
return store.getUrl(href);
|
||||
if(!this.tempUrl) {
|
||||
this.tempUrl = store.getUrl(this.href);
|
||||
}
|
||||
return this.tempUrl;
|
||||
}else{
|
||||
promise.resolve(this.href); //-- this is less than ideal but keeps it a promise
|
||||
return promise;
|
||||
|
@ -706,6 +715,14 @@ EPUBJS.Chapter.prototype.getPages = function(num){
|
|||
EPUBJS.Chapter.prototype.getID = function(){
|
||||
return this.ID;
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.unload = function(store){
|
||||
|
||||
if(this.tempUrl && store) {
|
||||
store.revokeUrl(this.tempUrl);
|
||||
this.tempUrl = false;
|
||||
}
|
||||
}
|
||||
var EPUBJS = EPUBJS || {};
|
||||
EPUBJS.core = {}
|
||||
|
||||
|
@ -744,7 +761,7 @@ EPUBJS.core.request = function(url, type) {
|
|||
|
||||
function handler() {
|
||||
if (this.readyState === this.DONE) {
|
||||
if (this.status === 200) {
|
||||
if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls
|
||||
var r;
|
||||
|
||||
if(type == 'xml'){
|
||||
|
@ -987,6 +1004,28 @@ EPUBJS.core.addScript = function(src, callback, target) {
|
|||
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.core.resolveUrl = function(base, path) {
|
||||
var url,
|
||||
segments = [],
|
||||
folders = base.split("/"),
|
||||
paths;
|
||||
|
||||
folders.pop();
|
||||
|
||||
paths = path.split("/");
|
||||
paths.forEach(function(p){
|
||||
if(p === ".."){
|
||||
folders.pop();
|
||||
}else{
|
||||
segments.push(p);
|
||||
}
|
||||
});
|
||||
|
||||
url = folders.concat(segments);
|
||||
|
||||
return url.join("/");
|
||||
}
|
||||
|
||||
EPUBJS.EpubCFI = function(cfiStr){
|
||||
if(cfiStr) return this.parse(cfiStr);
|
||||
|
@ -1018,7 +1057,7 @@ EPUBJS.EpubCFI.prototype.generateFragment = function(element, chapter) {
|
|||
parts.push((part.index + 1) * 2);
|
||||
|
||||
if(part.id &&
|
||||
part.id.slice(0, 7) != "@EPUBJS") { //-- ignore internal @EPUBJS ids
|
||||
part.id.slice(0, 6) != "EPUBJS") { //-- ignore internal @EPUBJS ids
|
||||
|
||||
parts.push("[" + part.id + "]");
|
||||
}
|
||||
|
@ -1139,6 +1178,7 @@ EPUBJS.EpubCFI.prototype.getElement = function(cfi, doc) {
|
|||
part = sections.shift();
|
||||
|
||||
if(part.id){
|
||||
console.log(part.id)
|
||||
element = cfi.doc.querySelector("#" + part.id);
|
||||
}else{
|
||||
|
||||
|
@ -1259,17 +1299,17 @@ EPUBJS.Parser.prototype.container = function(containerXml){
|
|||
|
||||
EPUBJS.Parser.prototype.package = function(packageXml, baseUrl){
|
||||
var parse = this;
|
||||
|
||||
|
||||
if(baseUrl) this.baseUrl = baseUrl;
|
||||
|
||||
var metadataNode = packageXml.querySelector("metadata"),
|
||||
manifestNode = packageXml.querySelector("manifest"),
|
||||
spineNode = packageXml.querySelector("spine");
|
||||
|
||||
|
||||
var manifest = parse.manifest(manifestNode),
|
||||
tocPath = parse.findTocPath(manifestNode),
|
||||
coverPath = parse.findCoverPath(manifestNode);
|
||||
|
||||
|
||||
var spineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode);
|
||||
|
||||
var spine = parse.spine(spineNode, manifest);
|
||||
|
@ -1293,13 +1333,13 @@ EPUBJS.Parser.prototype.package = function(packageXml, baseUrl){
|
|||
//-- Find TOC NCX: media-type="application/x-dtbncx+xml" href="toc.ncx"
|
||||
EPUBJS.Parser.prototype.findTocPath = function(manifestNode){
|
||||
var node = manifestNode.querySelector("item[media-type='application/x-dtbncx+xml']");
|
||||
return node.getAttribute('href');
|
||||
return node ? node.getAttribute('href') : false;
|
||||
}
|
||||
|
||||
//-- Find Cover: <item properties="cover-image" id="ci" href="cover.svg" media-type="image/svg+xml" />
|
||||
EPUBJS.Parser.prototype.findCoverPath = function(manifestNode){
|
||||
var node = manifestNode.querySelector("item[properties='cover-image']");
|
||||
return node.getAttribute('href');
|
||||
return node ? node.getAttribute('href') : false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1455,13 +1495,15 @@ EPUBJS.Renderer = function(book) {
|
|||
}
|
||||
|
||||
book.registerHook("beforeChapterDisplay",
|
||||
[this.replaceLinks.bind(this), this.replaceResources.bind(this)]);
|
||||
[this.replaceLinks.bind(this),
|
||||
this.replaceResources.bind(this),
|
||||
this.replaceHead.bind(this)], true);
|
||||
|
||||
|
||||
this.crossBrowserColumnCss();
|
||||
|
||||
this.epubcfi = new EPUBJS.EpubCFI();
|
||||
|
||||
|
||||
this.initialize();
|
||||
this.listeners();
|
||||
}
|
||||
|
@ -1490,9 +1532,13 @@ EPUBJS.Renderer.prototype.listeners = function(){
|
|||
|
||||
EPUBJS.Renderer.prototype.chapter = function(chapter){
|
||||
var renderer = this,
|
||||
store = this.settings.stored ? this.store : false;
|
||||
store = false;
|
||||
|
||||
if(this.book.settings.contained) store = this.book.zip;
|
||||
// if(this.settings.stored) store = this.storage;
|
||||
|
||||
if(this.currentChapter) {
|
||||
this.currentChapter.unload();
|
||||
this.trigger("book:chapterDestroyed");
|
||||
}
|
||||
|
||||
|
@ -1629,6 +1675,8 @@ EPUBJS.Renderer.prototype.setIframeSrc = function(url){
|
|||
|
||||
renderer.calcPages();
|
||||
|
||||
promise.resolve(renderer);
|
||||
|
||||
renderer.currentLocationCfi = renderer.getPageCfi();
|
||||
|
||||
renderer.trigger("book:chapterDisplayed");
|
||||
|
@ -1637,7 +1685,7 @@ EPUBJS.Renderer.prototype.setIframeSrc = function(url){
|
|||
|
||||
});
|
||||
|
||||
promise.resolve(renderer);
|
||||
|
||||
// that.afterLoaded(that);
|
||||
|
||||
|
||||
|
@ -1686,6 +1734,7 @@ EPUBJS.Renderer.prototype.formatSpread = function(){
|
|||
|
||||
this.spreadWidth = (this.colWidth + this.gap) * divisor;
|
||||
|
||||
if(this.bodyEl) this.bodyEl.style.margin = 0;
|
||||
// this.bodyEl.style.fontSize = localStorage.getItem("fontSize") || "medium";
|
||||
|
||||
//-- Clear Margins
|
||||
|
@ -1768,7 +1817,7 @@ EPUBJS.Renderer.prototype.calcPages = function() {
|
|||
this.totalWidth = this.docEl.scrollWidth;
|
||||
|
||||
this.displayedPages = Math.ceil(this.totalWidth / this.spreadWidth);
|
||||
|
||||
|
||||
this.currentChapter.pages = this.displayedPages;
|
||||
}
|
||||
|
||||
|
@ -1812,6 +1861,8 @@ EPUBJS.Renderer.prototype.prevPage = function(){
|
|||
|
||||
EPUBJS.Renderer.prototype.chapterEnd = function(){
|
||||
this.page(this.displayedPages);
|
||||
|
||||
this.currentLocationCfi = this.getPageCfi();
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.setLeft = function(leftPos){
|
||||
|
@ -1819,9 +1870,186 @@ EPUBJS.Renderer.prototype.setLeft = function(leftPos){
|
|||
this.doc.defaultView.scrollTo(leftPos, 0)
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.replace = function(query, func, callback){
|
||||
var items, resources, count;
|
||||
|
||||
items = this.doc.querySelectorAll(query);
|
||||
resources = Array.prototype.slice.call(items);
|
||||
count = resources.length;
|
||||
|
||||
resources.forEach(function(item){
|
||||
|
||||
func(item, function(){
|
||||
count--;
|
||||
if(count <= 0 && callback) callback();
|
||||
});
|
||||
|
||||
}.bind(this));
|
||||
|
||||
if(count === 0) callback();
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.determineStore = function(callback){
|
||||
if(this.book.fromStorage) {
|
||||
|
||||
//-- Filesystem api links are relative, so no need to replace them
|
||||
if(this.book.storage.getStorageType() == "filesystem") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.book.store;
|
||||
|
||||
} else if(this.book.contained) {
|
||||
|
||||
return this.book.zip;
|
||||
|
||||
} else {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//-- Replaces links in head, such as stylesheets
|
||||
EPUBJS.Renderer.prototype.replaceHead = function(callback){
|
||||
var srcs, resources, count, oldUrls,
|
||||
newUrls = {},
|
||||
unarchiver = this,
|
||||
store = this.determineStore(),
|
||||
replaceUrl = function(link, url){
|
||||
link.setAttribute("href", url);
|
||||
link.onload = function(){
|
||||
count--;
|
||||
if(count <= 0) finished();
|
||||
}
|
||||
},
|
||||
finished = function() {
|
||||
|
||||
if(callback) callback();
|
||||
|
||||
_.each(oldUrls, function(url){
|
||||
store.revokeUrl(url);
|
||||
});
|
||||
|
||||
unarchiver.urlCache = newUrls;
|
||||
};
|
||||
|
||||
if(!store) {
|
||||
if(callback) callback();
|
||||
return false;
|
||||
}
|
||||
|
||||
srcs = this.doc.head.querySelectorAll('[href]');
|
||||
resources = Array.prototype.slice.call(srcs);
|
||||
count = resources.length;
|
||||
|
||||
if(!this.urlCache) this.urlCache = {};
|
||||
oldUrls = _.clone(this.urlCache);
|
||||
|
||||
resources.forEach(function(link){
|
||||
var src = link.getAttribute("href"),
|
||||
full = this.book.settings.contentsPath + src;
|
||||
|
||||
|
||||
if(full in oldUrls){
|
||||
replaceUrl(link, oldUrls[full]);
|
||||
newUrls[full] = oldUrls[full];
|
||||
delete oldUrls[full];
|
||||
}else{
|
||||
|
||||
//-- Handle replacing urls in CSS
|
||||
if(link.getAttribute("rel") === "stylesheet") {
|
||||
store.getText(full).then(function(text){
|
||||
var url;
|
||||
|
||||
unarchiver.replaceUrlsInCss(full, text).then(function(newText){
|
||||
var _URL = window.URL || window.webkitURL || window.mozURL;
|
||||
|
||||
var blob = new Blob([newText], { "type" : "text\/css" }),
|
||||
url = _URL.createObjectURL(blob);
|
||||
|
||||
replaceUrl(link, url);
|
||||
newUrls[full] = url;
|
||||
|
||||
}, function(e) {console.error(e)});
|
||||
|
||||
});
|
||||
}else{
|
||||
store.getUrl(full).then(function(url){
|
||||
replaceUrl(link, url);
|
||||
newUrls[full] = url;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}.bind(this));
|
||||
|
||||
if(count === 0) finished();
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.replaceUrlsInCss = function(base, text){
|
||||
var promise = new RSVP.Promise(),
|
||||
promises = [],
|
||||
store = this.determineStore(),
|
||||
matches = text.match(/url\(\'?\"?([^\'|^\"]*)\'?\"?\)/g);
|
||||
|
||||
matches.forEach(function(str){
|
||||
var full = EPUBJS.core.resolveUrl(base, str.replace(/url\(|[|\)|\'|\"]/g, ''));
|
||||
replaced = store.getUrl(full).then(function(url){
|
||||
text = text.replace(str, 'url("'+url+'")');
|
||||
}, function(e) {console.error(e)} );
|
||||
|
||||
promises.push(replaced);
|
||||
});
|
||||
|
||||
RSVP.all(promises).then(function(){
|
||||
promise.resolve(text);
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
/*
|
||||
//-- Replaces links in head, such as stylesheets
|
||||
EPUBJS.Renderer.prototype.replaceCss = function(callback){
|
||||
var styleSheets = this.doc.styleSheets,
|
||||
store = this.determineStore(),
|
||||
rules = [];
|
||||
|
||||
_.each(styleSheets, function(sheet){
|
||||
_.each(sheet.cssRules, function(rule, index){
|
||||
if(rule.type == 5) {
|
||||
//url("../fonts/STIXGeneral.otf")
|
||||
// if()
|
||||
var urlString = rule.cssText.match(/url\(\'?\"?([^\'|^\"]*)\'?\"?\)/),
|
||||
full;
|
||||
// rule.cssText = ""
|
||||
// console.log(rule.style.src, rule.style[3])
|
||||
// console.log(urlString)
|
||||
|
||||
if(urlString[1]){
|
||||
full = "OPS/" + urlString[1].slice(3);
|
||||
store.getUrl(full).then(function(url){
|
||||
var newRule = rule.cssText.replace(/url\(\'?\"?([^\'|^\"]*)\'?\"?\)/, 'url("'+url+'")');
|
||||
sheet.deleteRule(index)
|
||||
sheet.insertRule(newRule, false);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//-- Replaces the relative links within the book to use our internal page changer
|
||||
EPUBJS.Renderer.prototype.replaceLinks = function(callback){
|
||||
var hrefs = this.doc.querySelectorAll('[href]'),
|
||||
var hrefs = this.doc.querySelectorAll('a'),
|
||||
links = Array.prototype.slice.call(hrefs),
|
||||
that = this;
|
||||
|
||||
|
@ -1830,7 +2058,7 @@ EPUBJS.Renderer.prototype.replaceLinks = function(callback){
|
|||
href = link.getAttribute("href"),
|
||||
relative = href.search("://"),
|
||||
fragment = href[0] == "#";
|
||||
|
||||
|
||||
if(relative != -1){
|
||||
|
||||
link.setAttribute("target", "_blank");
|
||||
|
@ -1851,30 +2079,35 @@ EPUBJS.Renderer.prototype.replaceLinks = function(callback){
|
|||
//-- Replaces assets src's to point to stored version if browser is offline
|
||||
EPUBJS.Renderer.prototype.replaceResources = function(callback){
|
||||
var srcs, resources, count;
|
||||
|
||||
//-- No need to replace if there is network connectivity
|
||||
//-- also Filesystem api links are relative, so no need to replace them
|
||||
if((this.book.online && !this.book.contained) || EPUBJS.storage.getStorageType() == "filesystem") {
|
||||
var store = this.determineStore();
|
||||
|
||||
if(!store) {
|
||||
if(callback) callback();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
srcs = this.doc.querySelectorAll('[src]');
|
||||
resources = Array.prototype.slice.call(srcs);
|
||||
count = resources.length;
|
||||
|
||||
|
||||
resources.forEach(function(link){
|
||||
var src = link.getAttribute("src"),
|
||||
full = this.book.basePath + src;
|
||||
full = this.book.settings.contentsPath + src;
|
||||
|
||||
EPUBJS.storage.get(full, function(url){
|
||||
link.setAttribute("src", url);
|
||||
count--;
|
||||
if(count <= 0 && callback) callback();
|
||||
store.getUrl(full).then(function(url){
|
||||
// link.setAttribute("src", url);
|
||||
link.src = url;
|
||||
|
||||
link.onload = function(){
|
||||
count--;
|
||||
if(count <= 0 && callback) callback();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
}.bind(this));
|
||||
|
||||
|
||||
if(count === 0) callback();
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.page = function(pg){
|
||||
|
@ -1886,7 +2119,7 @@ EPUBJS.Renderer.prototype.page = function(pg){
|
|||
// localStorage.setItem("chapterPos", pg);
|
||||
return true;
|
||||
}
|
||||
console.log("false", pg, this.displayedPages)
|
||||
|
||||
//-- Return false if page is greater than the total
|
||||
return false;
|
||||
}
|
||||
|
@ -1974,7 +2207,7 @@ EPUBJS.Renderer.prototype.getPageCfi = function(){
|
|||
this.visibileEl = this.findFirstVisible(prevEl);
|
||||
|
||||
if(!this.visibileEl.id) {
|
||||
this.visibileEl.id = "@EPUBJS-PAGE-" + this.chapterPos;
|
||||
this.visibileEl.id = "EPUBJS-PAGE-" + this.chapterPos;
|
||||
}
|
||||
|
||||
this.pageIds[this.chapterPos] = this.visibileEl.id;
|
||||
|
@ -2026,52 +2259,127 @@ EPUBJS.Renderer.prototype.isElementVisible = function(el){
|
|||
}
|
||||
|
||||
|
||||
EPUBJS.Renderer.prototype.height = function(el){
|
||||
return this.docEl.offsetHeight;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-- Enable binding events to parser
|
||||
RSVP.EventTarget.mixin(EPUBJS.Renderer.prototype);
|
||||
|
||||
EPUBJS.Unarchiver = function(url, callback){
|
||||
this.libPath = EPUBJS.filePath + "libs/";
|
||||
EPUBJS.Unarchiver = function(url){
|
||||
|
||||
|
||||
this.libPath = EPUBJS.filePath + "zip/";
|
||||
this.zipUrl = url;
|
||||
this.callback = callback;
|
||||
this.loadLib(function(){
|
||||
this.getZip(this.zipUrl);
|
||||
}.bind(this));
|
||||
this.loadLib()
|
||||
this.urlCache = {};
|
||||
|
||||
this.zipFs = new zip.fs.FS();
|
||||
|
||||
return this.promise;
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.loadLib = function(callback){
|
||||
if(typeof(zip) != "undefined") callback();
|
||||
if(typeof(zip) == "undefined") console.error("Zip lib not loaded");
|
||||
|
||||
/*
|
||||
//-- load script
|
||||
EPUBJS.core.loadScript(this.libPath+"zip.js", function(){
|
||||
//-- Tell zip where it is located
|
||||
zip.workerScriptsPath = this.libPath;
|
||||
callback();
|
||||
}.bind(this));
|
||||
*/
|
||||
// console.log(this.libPath)
|
||||
zip.workerScriptsPath = this.libPath;
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.getZip = function(zipUrl){
|
||||
var xhr = new EPUBJS.core.loadFile(zipUrl);
|
||||
|
||||
xhr.succeeded = function(file) {
|
||||
this.getEntries(file, this.toStorage.bind(this));
|
||||
}.bind(this);
|
||||
|
||||
xhr.failed = this.failed;
|
||||
|
||||
xhr.start();
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.getEntries = function(file, callback){
|
||||
zip.createReader(new zip.BlobReader(file), function(zipReader) {
|
||||
zipReader.getEntries(callback);
|
||||
EPUBJS.Unarchiver.prototype.openZip = function(zipUrl, callback){
|
||||
var promise = new RSVP.Promise();
|
||||
var zipFs = this.zipFs;
|
||||
zipFs.importHttpContent(zipUrl, false, function() {
|
||||
promise.resolve(zipFs);
|
||||
}, this.failed);
|
||||
|
||||
return promise
|
||||
}
|
||||
|
||||
// EPUBJS.Unarchiver.prototype.getXml = function(url){
|
||||
// var unarchiver = this,
|
||||
// request;
|
||||
// return this.getUrl(url, 'application/xml').
|
||||
// then(function(newUrl){
|
||||
// request = EPUBJS.core.request(newUrl, 'xml');
|
||||
// //-- Remove temp url after use
|
||||
// request.then(function(uri){
|
||||
// unarchiver.revokeUrl(uri);
|
||||
// });
|
||||
// return request
|
||||
// });
|
||||
//
|
||||
// }
|
||||
EPUBJS.Unarchiver.prototype.getXml = function(url){
|
||||
|
||||
return this.getText(url).
|
||||
then(function(text){
|
||||
var parser = new DOMParser();
|
||||
return parser.parseFromString(text, "application/xml");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.getUrl = function(url, mime){
|
||||
var unarchiver = this;
|
||||
var promise = new RSVP.Promise();
|
||||
var entry = this.zipFs.find(url);
|
||||
var _URL = window.URL || window.webkitURL || window.mozURL;
|
||||
|
||||
if(!entry) console.error(url);
|
||||
|
||||
if(url in this.urlCache) {
|
||||
promise.resolve(this.urlCache[url]);
|
||||
return promise;
|
||||
}
|
||||
|
||||
entry.getBlob(mime || zip.getMimeType(entry.name), function(blob){
|
||||
var tempUrl = _URL.createObjectURL(blob);
|
||||
promise.resolve(tempUrl);
|
||||
unarchiver.urlCache[url] = tempUrl;
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.getText = function(url){
|
||||
var unarchiver = this;
|
||||
var promise = new RSVP.Promise();
|
||||
var entry = this.zipFs.find(url);
|
||||
var _URL = window.URL || window.webkitURL || window.mozURL;
|
||||
|
||||
if(!entry) console.error(url);
|
||||
|
||||
|
||||
entry.getText(function(text){
|
||||
promise.resolve(text);
|
||||
}, null, null, 'ISO-8859-1');
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.revokeUrl = function(url){
|
||||
var _URL = window.URL || window.webkitURL || window.mozURL;
|
||||
var fromCache = unarchiver.urlCache[url];
|
||||
console.log("revoke", fromCache);
|
||||
if(fromCache) _URL.revokeObjectURL(fromCache);
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.failed = function(error){
|
||||
console.log("Error:", error);
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.afterSaved = function(error){
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*! FuturePress - v0.1.0 - 2013-06-30 */
|
||||
/*! FuturePress - v0.1.0 - 2013-07-08 */
|
||||
|
||||
EPUBJS.Hooks.register("beforeChapterDisplay").endnotes = function(callback, chapter){
|
||||
|
||||
|
@ -156,44 +156,51 @@ EPUBJS.Hooks.register("beforeChapterDisplay").endnotes = function(callback, chap
|
|||
}
|
||||
|
||||
EPUBJS.Hooks.register("beforeChapterDisplay").smartimages = function(callback, chapter){
|
||||
|
||||
var image = chapter.doc.querySelectorAll('img'),
|
||||
items = Array.prototype.slice.call(image),
|
||||
iheight = chapter.doc.body.getBoundingClientRect().height,
|
||||
var images = chapter.doc.querySelectorAll('img'),
|
||||
items = Array.prototype.slice.call(images),
|
||||
iheight = chapter.height(),//chapter.doc.body.getBoundingClientRect().height,
|
||||
oheight;
|
||||
|
||||
items.forEach(function(item){
|
||||
|
||||
function size() {
|
||||
var itemRect = item.getBoundingClientRect(),
|
||||
height = itemRect.height,
|
||||
top = itemRect.top;
|
||||
|
||||
iheight = chapter.iframe.height;
|
||||
rectHeight = itemRect.height,
|
||||
top = itemRect.top,
|
||||
oHeight = item.getAttribute('data-height'),
|
||||
height = oHeight || rectHeight,
|
||||
newHeight;
|
||||
|
||||
iheight = chapter.height();
|
||||
if(top < 0) top = 0;
|
||||
|
||||
if(height + top >= iheight) {
|
||||
|
||||
if(top < iheight/2) {
|
||||
item.style.maxHeight = iheight - top + "px";
|
||||
newHeight = iheight - top;
|
||||
item.style.maxHeight = newHeight + "px";
|
||||
item.style.width= "auto";
|
||||
}else{
|
||||
|
||||
item.style.maxHeight = (height < iheight ? height : iheight) + "px";
|
||||
height = (height < iheight ? height : iheight);
|
||||
item.style.maxHeight = newHeight + "px";
|
||||
item.style.marginTop = iheight - top + "px";
|
||||
item.style.width= "auto";
|
||||
}
|
||||
|
||||
item.setAttribute('data-height', newHeight);
|
||||
|
||||
}else{
|
||||
item.style.removeProperty('max-height');
|
||||
item.style.removeProperty('margin-top');
|
||||
}
|
||||
}
|
||||
|
||||
item.addEventListener('load', size, false);
|
||||
|
||||
chapter.on("book:resized", size);
|
||||
|
||||
chapter.on("book:chapterDestroyed", function(){
|
||||
item.removeEventListener('load', size);
|
||||
chapter.off("book:resized", size);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*! FuturePress - v0.1.0 - 2013-06-30 */
|
||||
/*! FuturePress - v0.1.0 - 2013-07-08 */
|
||||
|
||||
var EPUBJSR = EPUBJSR || {};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
EPUBJS.filePath = "js/";
|
||||
fileStorage.filePath = EPUBJS.filePath + "libs/";
|
||||
|
||||
EPUBJSR.app.init("moby-dick");
|
||||
EPUBJSR.app.init("moby-dick/");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
2
demo/js/epub.min.js
vendored
2
demo/js/epub.min.js
vendored
File diff suppressed because one or more lines are too long
2
demo/js/hooks.min.js
vendored
2
demo/js/hooks.min.js
vendored
|
@ -1 +1 @@
|
|||
EPUBJS.Hooks.register("beforeChapterDisplay").endnotes=function(e,t){var n=t.doc.querySelectorAll("a[href]"),r=Array.prototype.slice.call(n),i="epub:type",s="noteref",o={};r.forEach(function(e){function d(){var n,r=t.iframe.height,i=t.iframe.width,s,f,l=225;p||(f=a.cloneNode(!0),p=f.querySelector("p")),o[u]||(o[u]=document.createElement("div"),o[u].setAttribute("class","popup"),pop_content=document.createElement("div"),o[u].appendChild(pop_content),pop_content.appendChild(p),pop_content.setAttribute("class","pop_content"),t.bodyEl.appendChild(o[u]),o[u].addEventListener("mouseover",v,!1),o[u].addEventListener("mouseout",m,!1),t.book.listenUntil("book:pageChanged","book:chapterDestroy",g),t.book.listenUntil("book:pageChanged","book:chapterDestroy",m)),f=o[u],itemRect=e.getBoundingClientRect(),c=itemRect.left,h=itemRect.top,f.classList.add("show"),popRect=f.getBoundingClientRect(),f.style.left=c-popRect.width/2+"px",f.style.top=h+"px",l>r/2.5&&(l=r/2.5,pop_content.style.maxHeight=l+"px"),popRect.height+h>=r-25?(f.style.top=h-popRect.height+"px",f.classList.add("above")):f.classList.remove("above"),c-popRect.width<=0?(f.style.left=c+"px",f.classList.add("left")):f.classList.remove("left"),c+popRect.width/2>=i?(f.style.left=c-300+"px",popRect=f.getBoundingClientRect(),f.style.left=c-popRect.width+"px",popRect.height+h>=r-25?(f.style.top=h-popRect.height+"px",f.classList.add("above")):f.classList.remove("above"),f.classList.add("right")):f.classList.remove("right")}function v(){o[u].classList.add("on")}function m(){o[u].classList.remove("on")}function g(){setTimeout(function(){o[u].classList.remove("show")},100)}var n=e.getAttribute(i),r,u,a,f,l,c,h,p;if(n!=s)return;r=e.getAttribute("href"),u=r.replace("#",""),a=t.doc.getElementById(u),e.addEventListener("mouseover",d,!1),e.addEventListener("mouseout",g,!1)}),e&&e()},EPUBJS.Hooks.register("beforeChapterDisplay").smartimages=function(e,t){var n=t.doc.querySelectorAll("img"),r=Array.prototype.slice.call(n),i=t.doc.body.getBoundingClientRect().height,s;r.forEach(function(e){function n(){var n=e.getBoundingClientRect(),r=n.height,s=n.top;i=t.iframe.height,r+s>=i?s<i/2?(e.style.maxHeight=i-s+"px",e.style.width="auto"):(e.style.maxHeight=(r<i?r:i)+"px",e.style.marginTop=i-s+"px",e.style.width="auto"):(e.style.removeProperty("max-height"),e.style.removeProperty("margin-top"))}t.on("book:resized",n),t.on("book:chapterDestroyed",function(){t.off("book:resized",n)}),n()}),e&&e()},EPUBJS.Hooks.register("beforeChapterDisplay").transculsions=function(e,t){var n=t.doc.querySelectorAll("[transclusion]"),r=Array.prototype.slice.call(n);r.forEach(function(e){function l(){u=i,a=s,u>t.colWidth&&(f=t.colWidth/u,u=t.colWidth,a*=f),r.width=u,r.height=a}var n=e.getAttribute("ref"),r=document.createElement("iframe"),i=e.getAttribute("width"),s=e.getAttribute("height"),o=e.parentNode,u=i,a=s,f;l(),t.book.listenUntil("book:resized","book:chapterDestroy",l),r.src=n,o.replaceChild(r,e)}),e&&e()};
|
||||
EPUBJS.Hooks.register("beforeChapterDisplay").endnotes=function(e,t){var n=t.doc.querySelectorAll("a[href]"),r=Array.prototype.slice.call(n),i="epub:type",s="noteref",o={};r.forEach(function(e){function d(){var n,r=t.iframe.height,i=t.iframe.width,s,f,l=225;p||(f=a.cloneNode(!0),p=f.querySelector("p")),o[u]||(o[u]=document.createElement("div"),o[u].setAttribute("class","popup"),pop_content=document.createElement("div"),o[u].appendChild(pop_content),pop_content.appendChild(p),pop_content.setAttribute("class","pop_content"),t.bodyEl.appendChild(o[u]),o[u].addEventListener("mouseover",v,!1),o[u].addEventListener("mouseout",m,!1),t.book.listenUntil("book:pageChanged","book:chapterDestroy",g),t.book.listenUntil("book:pageChanged","book:chapterDestroy",m)),f=o[u],itemRect=e.getBoundingClientRect(),c=itemRect.left,h=itemRect.top,f.classList.add("show"),popRect=f.getBoundingClientRect(),f.style.left=c-popRect.width/2+"px",f.style.top=h+"px",l>r/2.5&&(l=r/2.5,pop_content.style.maxHeight=l+"px"),popRect.height+h>=r-25?(f.style.top=h-popRect.height+"px",f.classList.add("above")):f.classList.remove("above"),c-popRect.width<=0?(f.style.left=c+"px",f.classList.add("left")):f.classList.remove("left"),c+popRect.width/2>=i?(f.style.left=c-300+"px",popRect=f.getBoundingClientRect(),f.style.left=c-popRect.width+"px",popRect.height+h>=r-25?(f.style.top=h-popRect.height+"px",f.classList.add("above")):f.classList.remove("above"),f.classList.add("right")):f.classList.remove("right")}function v(){o[u].classList.add("on")}function m(){o[u].classList.remove("on")}function g(){setTimeout(function(){o[u].classList.remove("show")},100)}var n=e.getAttribute(i),r,u,a,f,l,c,h,p;if(n!=s)return;r=e.getAttribute("href"),u=r.replace("#",""),a=t.doc.getElementById(u),e.addEventListener("mouseover",d,!1),e.addEventListener("mouseout",g,!1)}),e&&e()},EPUBJS.Hooks.register("beforeChapterDisplay").smartimages=function(e,t){var n=t.doc.querySelectorAll("img"),r=Array.prototype.slice.call(n),i=t.height(),s;r.forEach(function(e){function n(){var n=e.getBoundingClientRect(),r=n.height,s=n.top,o=e.getAttribute("data-height"),u=o||r,a;i=t.height(),s<0&&(s=0),u+s>=i?(s<i/2?(a=i-s,e.style.maxHeight=a+"px",e.style.width="auto"):(u=u<i?u:i,e.style.maxHeight=a+"px",e.style.marginTop=i-s+"px",e.style.width="auto"),e.setAttribute("data-height",a)):(e.style.removeProperty("max-height"),e.style.removeProperty("margin-top"))}e.addEventListener("load",n,!1),t.on("book:resized",n),t.on("book:chapterDestroyed",function(){e.removeEventListener("load",n),t.off("book:resized",n)}),n()}),e&&e()},EPUBJS.Hooks.register("beforeChapterDisplay").transculsions=function(e,t){var n=t.doc.querySelectorAll("[transclusion]"),r=Array.prototype.slice.call(n);r.forEach(function(e){function l(){u=i,a=s,u>t.colWidth&&(f=t.colWidth/u,u=t.colWidth,a*=f),r.width=u,r.height=a}var n=e.getAttribute("ref"),r=document.createElement("iframe"),i=e.getAttribute("width"),s=e.getAttribute("height"),o=e.parentNode,u=i,a=s,f;l(),t.book.listenUntil("book:resized","book:chapterDestroy",l),r.src=n,o.replaceChild(r,e)}),e&&e()};
|
1
demo/js/libs/inflate.min.js
vendored
Normal file
1
demo/js/libs/inflate.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
demo/js/libs/zip.min.js
vendored
2
demo/js/libs/zip.min.js
vendored
File diff suppressed because one or more lines are too long
BIN
demo/moby-dick.epub
Normal file
BIN
demo/moby-dick.epub
Normal file
Binary file not shown.
|
@ -20,11 +20,11 @@
|
|||
|
||||
document.onreadystatechange = function () {
|
||||
if (document.readyState == "complete") {
|
||||
EPUBJS.filePath = "../src/";
|
||||
EPUBJS.filePath = "../libs/";
|
||||
fileStorage.filePath = "../libs/fileStorage/workers/";
|
||||
|
||||
EPUBJS.VERSION = "0.1.5";
|
||||
EPUBJSR.app.init('/demo/moby-dick');
|
||||
EPUBJSR.app.init('/demo/moby-dick.epub');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -32,6 +32,14 @@
|
|||
|
||||
<!--<script async src="epubjs/libs/jquery.touchy.min.js"></script>-->
|
||||
|
||||
<!-- zip -->
|
||||
<script src="../libs/zip/zip.js"></script>
|
||||
<script src="../libs/zip/zip-fs.js"></script>
|
||||
<script src="../libs/zip/zip-ext.js"></script>
|
||||
<script src="../libs/zip/inflate.js"></script>
|
||||
<script src="../libs/zip/mime-types.js"></script>
|
||||
|
||||
|
||||
<!-- Render -->
|
||||
<script src="../libs/underscore/underscore.js"></script>
|
||||
<script src="../libs/rsvp/rsvp.js"></script>
|
||||
|
@ -56,6 +64,8 @@
|
|||
<script async src="../reader/utils.js"></script>
|
||||
<script async src="../reader/app.js"></script>
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="sidebar">
|
||||
|
|
3
grunt.js
3
grunt.js
|
@ -19,7 +19,8 @@ module.exports = function(grunt) {
|
|||
'demo/js/epub.min.js': ['libs/underscore/underscore-min.js', 'libs/rsvp/rsvp.min.js', 'build/epub.js'],
|
||||
'demo/js/reader.min.js': 'build/reader.js',
|
||||
'demo/js/hooks.min.js': 'build/hooks.js',
|
||||
'demo/js/libs/zip.min.js': ['libs/zip/*.js']
|
||||
'demo/js/libs/zip.min.js': ['libs/zip/*.js'],
|
||||
'demo/js/libs/inflate.min.js': ['libs/zip/inflate.js']
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,42 +1,49 @@
|
|||
EPUBJS.Hooks.register("beforeChapterDisplay").smartimages = function(callback, chapter){
|
||||
|
||||
var image = chapter.doc.querySelectorAll('img'),
|
||||
items = Array.prototype.slice.call(image),
|
||||
iheight = chapter.doc.body.getBoundingClientRect().height,
|
||||
var images = chapter.doc.querySelectorAll('img'),
|
||||
items = Array.prototype.slice.call(images),
|
||||
iheight = chapter.height(),//chapter.doc.body.getBoundingClientRect().height,
|
||||
oheight;
|
||||
|
||||
items.forEach(function(item){
|
||||
|
||||
function size() {
|
||||
var itemRect = item.getBoundingClientRect(),
|
||||
height = itemRect.height,
|
||||
top = itemRect.top;
|
||||
|
||||
iheight = chapter.iframe.height;
|
||||
rectHeight = itemRect.height,
|
||||
top = itemRect.top,
|
||||
oHeight = item.getAttribute('data-height'),
|
||||
height = oHeight || rectHeight,
|
||||
newHeight;
|
||||
|
||||
iheight = chapter.height();
|
||||
if(top < 0) top = 0;
|
||||
|
||||
if(height + top >= iheight) {
|
||||
|
||||
if(top < iheight/2) {
|
||||
item.style.maxHeight = iheight - top + "px";
|
||||
newHeight = iheight - top;
|
||||
item.style.maxHeight = newHeight + "px";
|
||||
item.style.width= "auto";
|
||||
}else{
|
||||
|
||||
item.style.maxHeight = (height < iheight ? height : iheight) + "px";
|
||||
height = (height < iheight ? height : iheight);
|
||||
item.style.maxHeight = newHeight + "px";
|
||||
item.style.marginTop = iheight - top + "px";
|
||||
item.style.width= "auto";
|
||||
}
|
||||
|
||||
item.setAttribute('data-height', newHeight);
|
||||
|
||||
}else{
|
||||
item.style.removeProperty('max-height');
|
||||
item.style.removeProperty('margin-top');
|
||||
}
|
||||
}
|
||||
|
||||
item.addEventListener('load', size, false);
|
||||
|
||||
chapter.on("book:resized", size);
|
||||
|
||||
chapter.on("book:chapterDestroyed", function(){
|
||||
item.removeEventListener('load', size);
|
||||
chapter.off("book:resized", size);
|
||||
});
|
||||
|
||||
|
|
4215
libs/zip/deflate.js
4215
libs/zip/deflate.js
File diff suppressed because it is too large
Load diff
4332
libs/zip/inflate.js
4332
libs/zip/inflate.js
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,31 @@
|
|||
/*
|
||||
Copyright (c) 2013 Gildas Lormeau. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var table = {
|
||||
"application" : {
|
||||
|
@ -807,7 +835,7 @@
|
|||
"x-pict" : [ "pic", "pct" ],
|
||||
"x-tga" : "tga",
|
||||
"cis-cod" : "cod",
|
||||
"pipeg" : "jfif"
|
||||
"pipeg" : "jfif",
|
||||
},
|
||||
"message" : {
|
||||
"rfc822" : [ "eml", "mime", "mht", "mhtml", "nws" ]
|
||||
|
@ -966,7 +994,8 @@
|
|||
})();
|
||||
|
||||
zip.getMimeType = function(filename) {
|
||||
return mimeTypes[filename.split(".").pop()] || "application/octet-stream";
|
||||
var defaultValue = "application/octet-stream";
|
||||
return filename && mimeTypes[filename.split(".").pop().toLowerCase()] || defaultValue;
|
||||
};
|
||||
|
||||
})();
|
||||
|
|
241
libs/zip/zip-ext.js
Normal file
241
libs/zip/zip-ext.js
Normal file
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
Copyright (c) 2013 Gildas Lormeau. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
var ERR_HTTP_RANGE = "HTTP Range not supported.";
|
||||
|
||||
var Reader = zip.Reader;
|
||||
var Writer = zip.Writer;
|
||||
|
||||
var ZipDirectoryEntry;
|
||||
|
||||
var appendABViewSupported;
|
||||
try {
|
||||
appendABViewSupported = new Blob([ new DataView(new ArrayBuffer(0)) ]).size === 0;
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
function HttpReader(url) {
|
||||
var that = this;
|
||||
|
||||
function getData(callback, onerror) {
|
||||
var request;
|
||||
if (!that.data) {
|
||||
request = new XMLHttpRequest();
|
||||
request.addEventListener("load", function() {
|
||||
if (!that.size)
|
||||
that.size = Number(request.getResponseHeader("Content-Length"));
|
||||
that.data = new Uint8Array(request.response);
|
||||
callback();
|
||||
}, false);
|
||||
request.addEventListener("error", onerror, false);
|
||||
request.open("GET", url);
|
||||
request.responseType = "arraybuffer";
|
||||
request.send();
|
||||
} else
|
||||
callback();
|
||||
}
|
||||
|
||||
function init(callback, onerror) {
|
||||
var request = new XMLHttpRequest();
|
||||
request.addEventListener("load", function() {
|
||||
that.size = Number(request.getResponseHeader("Content-Length"));
|
||||
callback();
|
||||
}, false);
|
||||
request.addEventListener("error", onerror, false);
|
||||
request.open("HEAD", url);
|
||||
request.send();
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
getData(function() {
|
||||
callback(new Uint8Array(that.data.subarray(index, index + length)));
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
HttpReader.prototype = new Reader();
|
||||
HttpReader.prototype.constructor = HttpReader;
|
||||
|
||||
function HttpRangeReader(url) {
|
||||
var that = this;
|
||||
|
||||
function init(callback, onerror) {
|
||||
var request = new XMLHttpRequest();
|
||||
request.addEventListener("load", function() {
|
||||
that.size = Number(request.getResponseHeader("Content-Length"));
|
||||
if (request.getResponseHeader("Accept-Ranges") == "bytes")
|
||||
callback();
|
||||
else
|
||||
onerror(ERR_HTTP_RANGE);
|
||||
}, false);
|
||||
request.addEventListener("error", onerror, false);
|
||||
request.open("HEAD", url);
|
||||
request.send();
|
||||
}
|
||||
|
||||
function readArrayBuffer(index, length, callback, onerror) {
|
||||
var request = new XMLHttpRequest();
|
||||
request.open("GET", url);
|
||||
request.responseType = "arraybuffer";
|
||||
request.setRequestHeader("Range", "bytes=" + index + "-" + (index + length - 1));
|
||||
request.addEventListener("load", function() {
|
||||
callback(request.response);
|
||||
}, false);
|
||||
request.addEventListener("error", onerror, false);
|
||||
request.send();
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
readArrayBuffer(index, length, function(arraybuffer) {
|
||||
callback(new Uint8Array(arraybuffer));
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
HttpRangeReader.prototype = new Reader();
|
||||
HttpRangeReader.prototype.constructor = HttpRangeReader;
|
||||
|
||||
function ArrayBufferReader(arrayBuffer) {
|
||||
var that = this;
|
||||
|
||||
function init(callback, onerror) {
|
||||
that.size = arrayBuffer.byteLength;
|
||||
callback();
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
callback(new Uint8Array(arrayBuffer.slice(index, index + length)));
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
ArrayBufferReader.prototype = new Reader();
|
||||
ArrayBufferReader.prototype.constructor = ArrayBufferReader;
|
||||
|
||||
function ArrayBufferWriter() {
|
||||
var array, that = this;
|
||||
|
||||
function init(callback, onerror) {
|
||||
array = new Uint8Array();
|
||||
callback();
|
||||
}
|
||||
|
||||
function writeUint8Array(arr, callback, onerror) {
|
||||
var tmpArray = new Uint8Array(array.length + arr.length);
|
||||
tmpArray.set(array);
|
||||
tmpArray.set(arr, array.length);
|
||||
array = tmpArray;
|
||||
callback();
|
||||
}
|
||||
|
||||
function getData(callback) {
|
||||
callback(array.buffer);
|
||||
}
|
||||
|
||||
that.init = init;
|
||||
that.writeUint8Array = writeUint8Array;
|
||||
that.getData = getData;
|
||||
}
|
||||
ArrayBufferWriter.prototype = new Writer();
|
||||
ArrayBufferWriter.prototype.constructor = ArrayBufferWriter;
|
||||
|
||||
function FileWriter(fileEntry, contentType) {
|
||||
var writer, that = this;
|
||||
|
||||
function init(callback, onerror) {
|
||||
fileEntry.createWriter(function(fileWriter) {
|
||||
writer = fileWriter;
|
||||
callback();
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
function writeUint8Array(array, callback, onerror) {
|
||||
var blob = new Blob([ appendABViewSupported ? array : array.buffer ], {
|
||||
type : contentType
|
||||
});
|
||||
writer.onwrite = function() {
|
||||
writer.onwrite = null;
|
||||
callback();
|
||||
};
|
||||
writer.onerror = onerror;
|
||||
writer.write(blob);
|
||||
}
|
||||
|
||||
function getData(callback) {
|
||||
fileEntry.file(callback);
|
||||
}
|
||||
|
||||
that.init = init;
|
||||
that.writeUint8Array = writeUint8Array;
|
||||
that.getData = getData;
|
||||
}
|
||||
FileWriter.prototype = new Writer();
|
||||
FileWriter.prototype.constructor = FileWriter;
|
||||
|
||||
zip.FileWriter = FileWriter;
|
||||
zip.HttpReader = HttpReader;
|
||||
zip.HttpRangeReader = HttpRangeReader;
|
||||
zip.ArrayBufferReader = ArrayBufferReader;
|
||||
zip.ArrayBufferWriter = ArrayBufferWriter;
|
||||
|
||||
if (zip.fs) {
|
||||
ZipDirectoryEntry = zip.fs.ZipDirectoryEntry;
|
||||
ZipDirectoryEntry.prototype.addHttpContent = function(name, URL, useRangeHeader) {
|
||||
function addChild(parent, name, params, directory) {
|
||||
if (parent.directory)
|
||||
return directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new zip.fs.ZipFileEntry(parent.fs, name, params, parent);
|
||||
else
|
||||
throw "Parent entry is not a directory.";
|
||||
}
|
||||
|
||||
return addChild(this, name, {
|
||||
data : URL,
|
||||
Reader : useRangeHeader ? HttpRangeReader : HttpReader
|
||||
});
|
||||
};
|
||||
ZipDirectoryEntry.prototype.importHttpContent = function(URL, useRangeHeader, onend, onerror) {
|
||||
this.importZip(useRangeHeader ? new HttpRangeReader(URL) : new HttpReader(URL), onend, onerror);
|
||||
};
|
||||
zip.fs.FS.prototype.importHttpContent = function(URL, useRangeHeader, onend, onerror) {
|
||||
this.entries = [];
|
||||
this.root = new ZipDirectoryEntry(this);
|
||||
this.root.importHttpContent(URL, useRangeHeader, onend, onerror);
|
||||
};
|
||||
}
|
||||
|
||||
})();
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (c) 2012 Gildas Lormeau. All rights reserved.
|
||||
Copyright (c) 2013 Gildas Lormeau. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
@ -30,23 +30,20 @@
|
|||
|
||||
var CHUNK_SIZE = 512 * 1024;
|
||||
|
||||
var FileWriter = zip.FileWriter, //
|
||||
TextWriter = zip.TextWriter, //
|
||||
var TextWriter = zip.TextWriter, //
|
||||
BlobWriter = zip.BlobWriter, //
|
||||
Data64URIWriter = zip.Data64URIWriter, //
|
||||
Reader = zip.Reader, //
|
||||
TextReader = zip.TextReader, //
|
||||
BlobReader = zip.BlobReader, //
|
||||
Data64URIReader = zip.Data64URIReader, //
|
||||
HttpRangeReader = zip.HttpRangeReader, //
|
||||
HttpReader = zip.HttpReader, //
|
||||
createReader = zip.createReader, //
|
||||
createWriter = zip.createWriter;
|
||||
|
||||
function ZipBlobReader(entry) {
|
||||
var that = this, blobReader;
|
||||
|
||||
function init(callback, onerror) {
|
||||
function init(callback) {
|
||||
this.size = entry.uncompressedSize;
|
||||
callback();
|
||||
}
|
||||
|
@ -92,7 +89,6 @@
|
|||
var index = 0;
|
||||
|
||||
function next() {
|
||||
var child = entry.children[index];
|
||||
index++;
|
||||
if (index < entry.children.length)
|
||||
process(entry.children[index]);
|
||||
|
@ -209,10 +205,10 @@
|
|||
}, onerror);
|
||||
}
|
||||
|
||||
function getFileEntry(fileEntry, entry, onend, onprogress, totalSize, checkCrc32) {
|
||||
var currentIndex = 0, rootEntry;
|
||||
function getFileEntry(fileEntry, entry, onend, onprogress, onerror, totalSize, checkCrc32) {
|
||||
var currentIndex = 0;
|
||||
|
||||
function process(fileEntry, entry, onend, onprogress, totalSize) {
|
||||
function process(fileEntry, entry, onend, onprogress, onerror, totalSize) {
|
||||
var childIndex = 0;
|
||||
|
||||
function addChild(child) {
|
||||
|
@ -221,7 +217,7 @@
|
|||
process(childFileEntry, child, function() {
|
||||
childIndex++;
|
||||
processChild();
|
||||
}, onprogress, totalSize);
|
||||
}, onprogress, onerror, totalSize);
|
||||
}
|
||||
|
||||
if (child.directory)
|
||||
|
@ -232,7 +228,7 @@
|
|||
fileEntry.getFile(child.name, {
|
||||
create : true
|
||||
}, function(file) {
|
||||
child.getData(new FileWriter(file, zip.getMimeType(child.name)), nextChild, function(index, max) {
|
||||
child.getData(new zip.FileWriter(file, zip.getMimeType(child.name)), nextChild, function(index) {
|
||||
if (onprogress)
|
||||
onprogress(currentIndex + index, totalSize);
|
||||
}, checkCrc32);
|
||||
|
@ -249,11 +245,11 @@
|
|||
|
||||
processChild();
|
||||
}
|
||||
|
||||
|
||||
if (entry.directory)
|
||||
process(fileEntry, entry, onend, onprogress, totalSize);
|
||||
process(fileEntry, entry, onend, onprogress, onerror, totalSize);
|
||||
else
|
||||
entry.getData(new FileWriter(fileEntry, zip.getMimeType(entry.name)), onend, onprogress, checkCrc32);
|
||||
entry.getData(new zip.FileWriter(fileEntry, zip.getMimeType(entry.name)), onend, onprogress, checkCrc32);
|
||||
}
|
||||
|
||||
function resetFS(fs) {
|
||||
|
@ -328,7 +324,7 @@
|
|||
getFileEntry : function(fileEntry, onend, onprogress, onerror, checkCrc32) {
|
||||
var that = this;
|
||||
initReaders(that, function() {
|
||||
getFileEntry(fileEntry, that, onend, onprogress, getTotalSize(that), checkCrc32);
|
||||
getFileEntry(fileEntry, that, onend, onprogress, onerror, getTotalSize(that), checkCrc32);
|
||||
}, onerror);
|
||||
},
|
||||
moveTo : function(target) {
|
||||
|
@ -377,8 +373,8 @@
|
|||
|
||||
ZipFileEntry.prototype = ZipFileEntryProto = new ZipEntry();
|
||||
ZipFileEntryProto.constructor = ZipFileEntry;
|
||||
ZipFileEntryProto.getText = function(onend, onprogress, checkCrc32) {
|
||||
this.getData(new TextWriter(), onend, onprogress, checkCrc32);
|
||||
ZipFileEntryProto.getText = function(onend, onprogress, checkCrc32, encoding) {
|
||||
this.getData(new TextWriter(encoding), onend, onprogress, checkCrc32);
|
||||
};
|
||||
ZipFileEntryProto.getBlob = function(mimeType, onend, onprogress, checkCrc32) {
|
||||
this.getData(new BlobWriter(mimeType), onend, onprogress, checkCrc32);
|
||||
|
@ -421,12 +417,6 @@
|
|||
Writer : Data64URIWriter
|
||||
});
|
||||
};
|
||||
ZipDirectoryEntryProto.addHttpContent = function(name, URL, useRangeHeader) {
|
||||
return addChild(this, name, {
|
||||
data : URL,
|
||||
Reader : useRangeHeader ? HttpRangeReader : HttpReader
|
||||
});
|
||||
};
|
||||
ZipDirectoryEntryProto.addFileEntry = function(fileEntry, onend, onerror) {
|
||||
addFileEntry(this, fileEntry, onend, onerror);
|
||||
};
|
||||
|
@ -442,9 +432,6 @@
|
|||
ZipDirectoryEntryProto.importData64URI = function(dataURI, onend, onerror) {
|
||||
this.importZip(new Data64URIReader(dataURI), onend, onerror);
|
||||
};
|
||||
ZipDirectoryEntryProto.importHttpContent = function(URL, useRangeHeader, onend, onerror) {
|
||||
this.importZip(useRangeHeader ? new HttpRangeReader(URL) : new HttpReader(URL), onend, onerror);
|
||||
};
|
||||
ZipDirectoryEntryProto.exportBlob = function(onend, onprogress, onerror) {
|
||||
this.exportZip(new BlobWriter("application/zip"), onend, onprogress, onerror);
|
||||
};
|
||||
|
@ -452,7 +439,7 @@
|
|||
this.exportZip(new TextWriter(), onend, onprogress, onerror);
|
||||
};
|
||||
ZipDirectoryEntryProto.exportFileEntry = function(fileEntry, onend, onprogress, onerror) {
|
||||
this.exportZip(new FileWriter(fileEntry, "application/zip"), onend, onprogress, onerror);
|
||||
this.exportZip(new zip.FileWriter(fileEntry, "application/zip"), onend, onprogress, onerror);
|
||||
};
|
||||
ZipDirectoryEntryProto.exportData64URI = function(onend, onprogress, onerror) {
|
||||
this.exportZip(new Data64URIWriter("application/zip"), onend, onprogress, onerror);
|
||||
|
@ -524,10 +511,6 @@
|
|||
resetFS(this);
|
||||
this.root.importData64URI(dataURI, onend, onerror);
|
||||
},
|
||||
importHttpContent : function(URL, useRangeHeader, onend, onerror) {
|
||||
resetFS(this);
|
||||
this.root.importHttpContent(URL, useRangeHeader, onend, onerror);
|
||||
},
|
||||
exportBlob : function(onend, onprogress, onerror) {
|
||||
this.root.exportBlob(onend, onprogress, onerror);
|
||||
},
|
||||
|
@ -543,9 +526,11 @@
|
|||
};
|
||||
|
||||
zip.fs = {
|
||||
FS : FS
|
||||
FS : FS,
|
||||
ZipDirectoryEntry : ZipDirectoryEntry,
|
||||
ZipFileEntry : ZipFileEntry
|
||||
};
|
||||
|
||||
|
||||
zip.getMimeType = function() {
|
||||
return "application/octet-stream";
|
||||
};
|
||||
|
|
334
libs/zip/zip.js
334
libs/zip/zip.js
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (c) 2012 Gildas Lormeau. All rights reserved.
|
||||
Copyright (c) 2013 Gildas Lormeau. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
@ -36,24 +36,19 @@
|
|||
var ERR_WRITE_DATA = "Error while writing file data.";
|
||||
var ERR_READ_DATA = "Error while reading file data.";
|
||||
var ERR_DUPLICATED_NAME = "File already exists.";
|
||||
var ERR_HTTP_RANGE = "HTTP Range not supported.";
|
||||
var CHUNK_SIZE = 512 * 1024;
|
||||
|
||||
var INFLATE_JS = "inflate.js";
|
||||
var DEFLATE_JS = "deflate.js";
|
||||
|
||||
var BlobBuilder = obj.WebKitBlobBuilder || obj.MozBlobBuilder || obj.MSBlobBuilder || obj.BlobBuilder;
|
||||
|
||||
var TEXT_PLAIN = "text/plain";
|
||||
|
||||
var MESSAGE_EVENT = "message";
|
||||
|
||||
var appendABViewSupported;
|
||||
|
||||
function isAppendABViewSupported() {
|
||||
if (typeof appendABViewSupported == "undefined") {
|
||||
var blobBuilder;
|
||||
blobBuilder = new BlobBuilder();
|
||||
blobBuilder.append(getDataHelper(0).view);
|
||||
appendABViewSupported = blobBuilder.getBlob().size == 0;
|
||||
}
|
||||
return appendABViewSupported;
|
||||
try {
|
||||
appendABViewSupported = new Blob([ new DataView(new ArrayBuffer(0)) ]).size === 0;
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
function Crc32() {
|
||||
|
@ -113,9 +108,10 @@
|
|||
var that = this, blobReader;
|
||||
|
||||
function init(callback, onerror) {
|
||||
var blobBuilder = new BlobBuilder();
|
||||
blobBuilder.append(text);
|
||||
blobReader = new BlobReader(blobBuilder.getBlob("text/plain"));
|
||||
var blob = new Blob([ text ], {
|
||||
type : TEXT_PLAIN
|
||||
});
|
||||
blobReader = new BlobReader(blob);
|
||||
blobReader.init(function() {
|
||||
that.size = blobReader.size;
|
||||
callback();
|
||||
|
@ -136,7 +132,7 @@
|
|||
function Data64URIReader(dataURI) {
|
||||
var that = this, dataStart;
|
||||
|
||||
function init(callback, onerror) {
|
||||
function init(callback) {
|
||||
var dataEnd = dataURI.length;
|
||||
while (dataURI.charAt(dataEnd - 1) == "=")
|
||||
dataEnd--;
|
||||
|
@ -145,7 +141,7 @@
|
|||
callback();
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
function readUint8Array(index, length, callback) {
|
||||
var i, data = getDataHelper(length);
|
||||
var start = Math.floor(index / 3) * 4;
|
||||
var end = Math.ceil((index + length) / 3) * 4;
|
||||
|
@ -166,7 +162,7 @@
|
|||
function BlobReader(blob) {
|
||||
var that = this;
|
||||
|
||||
function init(callback, onerror) {
|
||||
function init(callback) {
|
||||
this.size = blob.size;
|
||||
callback();
|
||||
}
|
||||
|
@ -187,93 +183,6 @@
|
|||
BlobReader.prototype = new Reader();
|
||||
BlobReader.prototype.constructor = BlobReader;
|
||||
|
||||
function HttpReader(url) {
|
||||
var that = this;
|
||||
|
||||
function getData(callback, onerror) {
|
||||
var request;
|
||||
if (!that.data) {
|
||||
request = new XMLHttpRequest();
|
||||
request.addEventListener("load", function() {
|
||||
if (!that.size)
|
||||
that.size = Number(request.getResponseHeader("Content-Length"));
|
||||
that.data = new Uint8Array(request.response);
|
||||
callback();
|
||||
}, false);
|
||||
request.addEventListener("error", onerror, false);
|
||||
request.open("GET", url);
|
||||
request.responseType = "arraybuffer";
|
||||
request.send();
|
||||
} else
|
||||
callback();
|
||||
}
|
||||
|
||||
function init(callback, onerror) {
|
||||
var request = new XMLHttpRequest();
|
||||
request.addEventListener("load", function() {
|
||||
that.size = Number(request.getResponseHeader("Content-Length"));
|
||||
callback();
|
||||
}, false);
|
||||
request.addEventListener("error", onerror, false);
|
||||
request.open("HEAD", url);
|
||||
request.send();
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
getData(function() {
|
||||
callback(new Uint8Array(that.data.subarray(index, index + length)));
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
HttpReader.prototype = new Reader();
|
||||
HttpReader.prototype.constructor = HttpReader;
|
||||
|
||||
function HttpRangeReader(url) {
|
||||
var that = this;
|
||||
|
||||
function init(callback, onerror) {
|
||||
var request = new XMLHttpRequest();
|
||||
request.addEventListener("load", function() {
|
||||
that.size = Number(request.getResponseHeader("Content-Length"));
|
||||
if (request.getResponseHeader("Accept-Ranges") == "bytes")
|
||||
callback();
|
||||
else
|
||||
onerror(ERR_HTTP_RANGE);
|
||||
}, false);
|
||||
request.addEventListener("error", onerror, false);
|
||||
request.open("HEAD", url);
|
||||
request.send();
|
||||
}
|
||||
|
||||
function readArrayBuffer(index, length, callback, onerror) {
|
||||
var request = new XMLHttpRequest();
|
||||
request.open("GET", url);
|
||||
request.responseType = "arraybuffer";
|
||||
request.setRequestHeader("Range", "bytes=" + index + "-" + (index + length - 1));
|
||||
request.addEventListener("load", function() {
|
||||
callback(request.response);
|
||||
}, false);
|
||||
request.addEventListener("error", onerror, false);
|
||||
request.send();
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
readArrayBuffer(index, length, function(arraybuffer) {
|
||||
callback(new Uint8Array(arraybuffer));
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
HttpRangeReader.prototype = new Reader();
|
||||
HttpRangeReader.prototype.constructor = HttpRangeReader;
|
||||
|
||||
// Writers
|
||||
|
||||
function Writer() {
|
||||
|
@ -282,26 +191,30 @@
|
|||
callback(this.data);
|
||||
};
|
||||
|
||||
function TextWriter() {
|
||||
var that = this, blobBuilder;
|
||||
function TextWriter(encoding) {
|
||||
var that = this, blob;
|
||||
|
||||
function init(callback, onerror) {
|
||||
blobBuilder = new BlobBuilder();
|
||||
function init(callback) {
|
||||
blob = new Blob([], {
|
||||
type : TEXT_PLAIN
|
||||
});
|
||||
callback();
|
||||
}
|
||||
|
||||
function writeUint8Array(array, callback, onerror) {
|
||||
blobBuilder.append(isAppendABViewSupported() ? array : array.buffer);
|
||||
function writeUint8Array(array, callback) {
|
||||
blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
|
||||
type : TEXT_PLAIN
|
||||
});
|
||||
callback();
|
||||
}
|
||||
|
||||
function getData(callback) {
|
||||
function getData(callback, onerror) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
callback(e.target.result);
|
||||
};
|
||||
reader.onerror = onerror;
|
||||
reader.readAsText(blobBuilder.getBlob("text/plain"));
|
||||
reader.readAsText(blob, encoding);
|
||||
}
|
||||
|
||||
that.init = init;
|
||||
|
@ -314,12 +227,12 @@
|
|||
function Data64URIWriter(contentType) {
|
||||
var that = this, data = "", pending = "";
|
||||
|
||||
function init(callback, onerror) {
|
||||
function init(callback) {
|
||||
data += "data:" + (contentType || "") + ";base64,";
|
||||
callback();
|
||||
}
|
||||
|
||||
function writeUint8Array(array, callback, onerror) {
|
||||
function writeUint8Array(array, callback) {
|
||||
var i, delta = pending.length, dataString = pending;
|
||||
pending = "";
|
||||
for (i = 0; i < (Math.floor((delta + array.length) / 3) * 3) - delta; i++)
|
||||
|
@ -344,53 +257,25 @@
|
|||
Data64URIWriter.prototype = new Writer();
|
||||
Data64URIWriter.prototype.constructor = Data64URIWriter;
|
||||
|
||||
function FileWriter(fileEntry, contentType) {
|
||||
var writer, that = this;
|
||||
|
||||
function init(callback, onerror) {
|
||||
fileEntry.createWriter(function(fileWriter) {
|
||||
writer = fileWriter;
|
||||
callback();
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
function writeUint8Array(array, callback, onerror) {
|
||||
var blobBuilder = new BlobBuilder();
|
||||
blobBuilder.append(isAppendABViewSupported() ? array : array.buffer);
|
||||
writer.onwrite = function() {
|
||||
writer.onwrite = null;
|
||||
callback();
|
||||
};
|
||||
writer.onerror = onerror;
|
||||
writer.write(blobBuilder.getBlob(contentType));
|
||||
}
|
||||
|
||||
function getData(callback) {
|
||||
fileEntry.file(callback);
|
||||
}
|
||||
|
||||
that.init = init;
|
||||
that.writeUint8Array = writeUint8Array;
|
||||
that.getData = getData;
|
||||
}
|
||||
FileWriter.prototype = new Writer();
|
||||
FileWriter.prototype.constructor = FileWriter;
|
||||
|
||||
function BlobWriter(contentType) {
|
||||
var blobBuilder, that = this;
|
||||
var blob, that = this;
|
||||
|
||||
function init(callback, onerror) {
|
||||
blobBuilder = new BlobBuilder();
|
||||
function init(callback) {
|
||||
blob = new Blob([], {
|
||||
type : contentType
|
||||
});
|
||||
callback();
|
||||
}
|
||||
|
||||
function writeUint8Array(array, callback, onerror) {
|
||||
blobBuilder.append(isAppendABViewSupported() ? array : array.buffer);
|
||||
function writeUint8Array(array, callback) {
|
||||
blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
|
||||
type : contentType
|
||||
});
|
||||
callback();
|
||||
}
|
||||
|
||||
function getData(callback) {
|
||||
callback(blobBuilder.getBlob(contentType));
|
||||
callback(blob);
|
||||
}
|
||||
|
||||
that.init = init;
|
||||
|
@ -406,13 +291,12 @@
|
|||
var chunkIndex = 0, index, outputSize;
|
||||
|
||||
function onflush() {
|
||||
worker.removeEventListener("message", onmessage, false);
|
||||
worker.removeEventListener(MESSAGE_EVENT, onmessage, false);
|
||||
onend(outputSize);
|
||||
}
|
||||
|
||||
function onmessage(event) {
|
||||
var message = event.data, data = message.data;
|
||||
|
||||
if (message.onappend) {
|
||||
outputSize += data.length;
|
||||
writer.writeUint8Array(data, function() {
|
||||
|
@ -453,7 +337,7 @@
|
|||
}
|
||||
|
||||
outputSize = 0;
|
||||
worker.addEventListener("message", onmessage, false);
|
||||
worker.addEventListener(MESSAGE_EVENT, onmessage, false);
|
||||
step();
|
||||
}
|
||||
|
||||
|
@ -528,13 +412,13 @@
|
|||
}
|
||||
|
||||
function onmessage() {
|
||||
worker.removeEventListener("message", onmessage, false);
|
||||
worker.removeEventListener(MESSAGE_EVENT, onmessage, false);
|
||||
launchWorkerProcess(worker, reader, writer, 0, reader.size, ondeflateappend, onprogress, ondeflateend, onreaderror, onwriteerror);
|
||||
}
|
||||
|
||||
if (obj.zip.useWebWorkers) {
|
||||
worker = new Worker(obj.zip.workerScriptsPath + DEFLATE_JS);
|
||||
worker.addEventListener("message", onmessage, false);
|
||||
worker.addEventListener(MESSAGE_EVENT, onmessage, false);
|
||||
worker.postMessage({
|
||||
init : true,
|
||||
level : level
|
||||
|
@ -589,29 +473,8 @@
|
|||
return out;
|
||||
}
|
||||
|
||||
function decodeUTF8(str_data) {
|
||||
var tmp_arr = [], i = 0, ac = 0, c1 = 0, c2 = 0, c3 = 0;
|
||||
|
||||
str_data += '';
|
||||
|
||||
while (i < str_data.length) {
|
||||
c1 = str_data.charCodeAt(i);
|
||||
if (c1 < 128) {
|
||||
tmp_arr[ac++] = String.fromCharCode(c1);
|
||||
i++;
|
||||
} else if (c1 > 191 && c1 < 224) {
|
||||
c2 = str_data.charCodeAt(i + 1);
|
||||
tmp_arr[ac++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
|
||||
i += 2;
|
||||
} else {
|
||||
c2 = str_data.charCodeAt(i + 1);
|
||||
c3 = str_data.charCodeAt(i + 2);
|
||||
tmp_arr[ac++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
||||
i += 3;
|
||||
}
|
||||
}
|
||||
|
||||
return tmp_arr.join('');
|
||||
function decodeUTF8(string) {
|
||||
return decodeURIComponent(escape(string));
|
||||
}
|
||||
|
||||
function getString(bytes) {
|
||||
|
@ -630,7 +493,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
function readCommonHeader(entry, data, index, centralDirectory) {
|
||||
function readCommonHeader(entry, data, index, centralDirectory, onerror) {
|
||||
entry.version = data.view.getUint16(index, true);
|
||||
entry.bitFlag = data.view.getUint16(index + 2, true);
|
||||
entry.compressionMethod = data.view.getUint16(index + 4, true);
|
||||
|
@ -697,7 +560,7 @@
|
|||
onerror(ERR_BAD_FORMAT);
|
||||
return;
|
||||
}
|
||||
readCommonHeader(that, data, 4);
|
||||
readCommonHeader(that, data, 4, false, onerror);
|
||||
dataOffset = that.offset + 30 + that.filenameLength + that.extraFieldLength;
|
||||
writer.init(function() {
|
||||
if (that.compressionMethod === 0)
|
||||
|
@ -708,18 +571,28 @@
|
|||
}, onreaderror);
|
||||
};
|
||||
|
||||
function seekEOCDR(offset, entriesCallback) {
|
||||
reader.readUint8Array(reader.size - offset, offset, function(bytes) {
|
||||
var dataView = getDataHelper(bytes.length, bytes).view;
|
||||
if (dataView.getUint32(0) != 0x504b0506) {
|
||||
seekEOCDR(offset + 1, entriesCallback);
|
||||
} else {
|
||||
entriesCallback(dataView);
|
||||
}
|
||||
}, function() {
|
||||
onerror(ERR_READ);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
getEntries : function(callback) {
|
||||
if (reader.size < 22) {
|
||||
onerror(ERR_BAD_FORMAT);
|
||||
return;
|
||||
}
|
||||
reader.readUint8Array(reader.size - 22, 22, function(bytes) {
|
||||
var dataView = getDataHelper(bytes.length, bytes).view, datalength, fileslength;
|
||||
if (dataView.getUint32(0) != 0x504b0506) {
|
||||
onerror(ERR_BAD_FORMAT);
|
||||
return;
|
||||
}
|
||||
// look for End of central directory record
|
||||
seekEOCDR(22, function(dataView) {
|
||||
var datalength, fileslength;
|
||||
datalength = dataView.getUint32(16, true);
|
||||
fileslength = dataView.getUint16(8, true);
|
||||
reader.readUint8Array(datalength, reader.size - datalength, function(bytes) {
|
||||
|
@ -730,7 +603,7 @@
|
|||
onerror(ERR_BAD_FORMAT);
|
||||
return;
|
||||
}
|
||||
readCommonHeader(entry, data, index + 6, true);
|
||||
readCommonHeader(entry, data, index + 6, true, onerror);
|
||||
entry.commentLength = data.view.getUint16(index + 32, true);
|
||||
entry.directory = ((data.view.getUint8(index + 38) & 0x10) == 0x10);
|
||||
entry.offset = data.view.getUint32(index + 42, true);
|
||||
|
@ -748,8 +621,6 @@
|
|||
}, function() {
|
||||
onerror(ERR_READ);
|
||||
});
|
||||
}, function() {
|
||||
onerror(ERR_READ);
|
||||
});
|
||||
},
|
||||
close : function(callback) {
|
||||
|
@ -762,26 +633,7 @@
|
|||
// ZipWriter
|
||||
|
||||
function encodeUTF8(string) {
|
||||
var n, c1, enc, utftext = [], start = 0, end = 0, stringl = string.length;
|
||||
for (n = 0; n < stringl; n++) {
|
||||
c1 = string.charCodeAt(n);
|
||||
enc = null;
|
||||
if (c1 < 128)
|
||||
end++;
|
||||
else if (c1 > 127 && c1 < 2048)
|
||||
enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);
|
||||
else
|
||||
enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);
|
||||
if (enc != null) {
|
||||
if (end > start)
|
||||
utftext += string.slice(start, end);
|
||||
utftext += enc;
|
||||
start = end = n + 1;
|
||||
}
|
||||
}
|
||||
if (end > start)
|
||||
utftext += string.slice(start, stringl);
|
||||
return utftext;
|
||||
return unescape(encodeURIComponent(string));
|
||||
}
|
||||
|
||||
function getBytes(str) {
|
||||
|
@ -792,7 +644,7 @@
|
|||
}
|
||||
|
||||
function createZipWriter(writer, onerror, dontDeflate) {
|
||||
var worker, files = [], filenames = [], datalength = 0;
|
||||
var worker, files = {}, filenames = [], datalength = 0;
|
||||
|
||||
function terminate(callback, message) {
|
||||
if (worker)
|
||||
|
@ -828,7 +680,7 @@
|
|||
header.view.setUint32(0, 0x14000808);
|
||||
if (options.version)
|
||||
header.view.setUint8(0, options.version);
|
||||
if (!dontDeflate && options.level != 0)
|
||||
if (!dontDeflate && options.level !== 0 && !options.directory)
|
||||
header.view.setUint16(4, 0x0800);
|
||||
header.view.setUint16(6, (((date.getHours() << 6) | date.getMinutes()) << 5) | date.getSeconds() / 2, true);
|
||||
header.view.setUint16(8, ((((date.getFullYear() - 1980) << 4) | (date.getMonth() + 1)) << 5) | date.getDate(), true);
|
||||
|
@ -836,7 +688,6 @@
|
|||
data = getDataHelper(30 + filename.length);
|
||||
data.view.setUint32(0, 0x504b0304);
|
||||
data.array.set(header.array, 4);
|
||||
data.array.set([], 30); // FIXME: remove when chrome 18 will be stable (14: OK, 16: KO, 17: OK)
|
||||
data.array.set(filename, 30);
|
||||
datalength += data.array.length;
|
||||
writer.writeUint8Array(data.array, callback, onwriteerror);
|
||||
|
@ -867,13 +718,15 @@
|
|||
name = name.trim();
|
||||
if (options.directory && name.charAt(name.length - 1) != "/")
|
||||
name += "/";
|
||||
if (files[name])
|
||||
throw ERR_DUPLICATED_NAME;
|
||||
if (files.hasOwnProperty(name)) {
|
||||
onerror(ERR_DUPLICATED_NAME);
|
||||
return;
|
||||
}
|
||||
filename = getBytes(encodeUTF8(name));
|
||||
filenames.push(name);
|
||||
writeHeader(function() {
|
||||
if (reader)
|
||||
if (dontDeflate || options.level == 0)
|
||||
if (dontDeflate || options.level === 0)
|
||||
copy(reader, writer, 0, reader.size, true, writeFooter, onprogress, onreaderror, onwriteerror);
|
||||
else
|
||||
worker = deflate(reader, writer, options.level, writeFooter, onprogress, onreaderror, onwriteerror);
|
||||
|
@ -888,14 +741,14 @@
|
|||
writeFile();
|
||||
},
|
||||
close : function(callback) {
|
||||
var data, length = 0, index = 0;
|
||||
filenames.forEach(function(name) {
|
||||
var file = files[name];
|
||||
var data, length = 0, index = 0, indexFilename, file;
|
||||
for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {
|
||||
file = files[filenames[indexFilename]];
|
||||
length += 46 + file.filename.length + file.comment.length;
|
||||
});
|
||||
}
|
||||
data = getDataHelper(length + 22);
|
||||
filenames.forEach(function(name) {
|
||||
var file = files[name];
|
||||
for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {
|
||||
file = files[filenames[indexFilename]];
|
||||
data.view.setUint32(index, 0x504b0102);
|
||||
data.view.setUint16(index + 4, 0x1400);
|
||||
data.array.set(file.headerArray, index + 6);
|
||||
|
@ -906,7 +759,7 @@
|
|||
data.array.set(file.filename, index + 46);
|
||||
data.array.set(file.comment, index + 46 + file.filename.length);
|
||||
index += 46 + file.filename.length + file.comment.length;
|
||||
});
|
||||
}
|
||||
data.view.setUint32(index, 0x504b0506);
|
||||
data.view.setUint16(index + 8, filenames.length, true);
|
||||
data.view.setUint16(index + 10, filenames.length, true);
|
||||
|
@ -921,42 +774,13 @@
|
|||
};
|
||||
}
|
||||
|
||||
if (typeof BlobBuilder == "undefined") {
|
||||
BlobBuilder = function() {
|
||||
var that = this, blobParts;
|
||||
|
||||
function initBlobParts() {
|
||||
if (!blobParts) {
|
||||
blobParts = [ new Blob() ]
|
||||
}
|
||||
}
|
||||
|
||||
that.append = function(data) {
|
||||
initBlobParts();
|
||||
blobParts.push(data);
|
||||
};
|
||||
that.getBlob = function(contentType) {
|
||||
initBlobParts();
|
||||
if (blobParts.length > 1 || blobParts[0].type != contentType) {
|
||||
blobParts = [ contentType ? new Blob(blobParts, {
|
||||
type : contentType
|
||||
}) : new Blob(blobParts) ];
|
||||
}
|
||||
return blobParts[0];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
obj.zip = {
|
||||
Reader : Reader,
|
||||
Writer : Writer,
|
||||
BlobReader : BlobReader,
|
||||
HttpReader : HttpReader,
|
||||
HttpRangeReader : HttpRangeReader,
|
||||
Data64URIReader : Data64URIReader,
|
||||
TextReader : TextReader,
|
||||
BlobWriter : BlobWriter,
|
||||
FileWriter : FileWriter,
|
||||
Data64URIWriter : Data64URIWriter,
|
||||
TextWriter : TextWriter,
|
||||
createReader : function(reader, callback, onerror) {
|
||||
|
|
46
server.js
Normal file
46
server.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var connect = require('connect'),
|
||||
colors = require('colors'),
|
||||
argv = require('optimist').argv,
|
||||
portfinder = require('portfinder');
|
||||
|
||||
var port = argv.p,
|
||||
logger = argv.l || "dev",
|
||||
silent = argv.s,
|
||||
log = console.log;
|
||||
|
||||
if (!argv.p) {
|
||||
portfinder.basePort = 8080;
|
||||
portfinder.getPort(function (err, port) {
|
||||
if (err) throw err;
|
||||
listen(port);
|
||||
});
|
||||
} else {
|
||||
listen(port);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function listen(port) {
|
||||
var server = connect();
|
||||
server.use(connect.static(__dirname))
|
||||
|
||||
if(!silent) server.use(connect.logger(logger))
|
||||
|
||||
server.listen(port);
|
||||
|
||||
log('Starting up Server, serving '.yellow
|
||||
+ __dirname.green
|
||||
+ ' on port: '.yellow
|
||||
+ port.toString().cyan);
|
||||
log('Hit CTRL-C to stop the server');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
process.on('SIGINT', function () {
|
||||
log('http-server stopped.'.red);
|
||||
process.exit();
|
||||
});
|
148
src/book.js
148
src/book.js
|
@ -13,7 +13,7 @@ EPUBJS.Book = function(bookPath, options){
|
|||
spreads: true,
|
||||
responsive: true,
|
||||
version: 1,
|
||||
restore: false
|
||||
restore: true
|
||||
});
|
||||
|
||||
this.settings.EPUBJSVERSION = EPUBJS.VERSION;
|
||||
|
@ -65,7 +65,7 @@ EPUBJS.Book = function(bookPath, options){
|
|||
}
|
||||
|
||||
// Likewise if an element is present start rendering process
|
||||
if(this.settings.element) {
|
||||
if(bookPath && this.settings.element) {
|
||||
this.opened.then(function(){
|
||||
this.rendered = this.renderTo(el);
|
||||
});
|
||||
|
@ -79,30 +79,46 @@ EPUBJS.Book = function(bookPath, options){
|
|||
|
||||
|
||||
//-- Check bookUrl and start parsing book Assets or load them from storage
|
||||
|
||||
EPUBJS.Book.prototype.open = function(bookPath, forceReload){
|
||||
var book = this,
|
||||
saved = this.isSaved(bookPath),
|
||||
opened;
|
||||
|
||||
this.settings.bookPath = bookPath;
|
||||
|
||||
//-- Get a absolute URL from the book path
|
||||
this.bookUrl = this.urlFrom(bookPath);
|
||||
|
||||
// console.log("saved", saved, !forceReload)
|
||||
//-- Remove the previous settings and reload
|
||||
if(forceReload){
|
||||
this.removeSavedSettings();
|
||||
}
|
||||
|
||||
//-- Check for a saved settings object, with the same url and version
|
||||
if(this.isSaved()){
|
||||
|
||||
if(saved && !forceReload){
|
||||
//-- Apply settings, keeping newer ones
|
||||
this.applySavedSettings();
|
||||
}
|
||||
|
||||
if(this.settings.contained || this.isContained(bookPath)){
|
||||
|
||||
if(this.settings.restore){
|
||||
|
||||
this.settings.contained = this.contained = true;
|
||||
|
||||
this.bookUrl = '';
|
||||
|
||||
// return; //-- TODO: this need to be fixed and tested before enabling
|
||||
opened = this.unarchive(bookPath).then(function(){
|
||||
|
||||
if(saved && book.settings.restore && !forceReload){
|
||||
return book.restore();
|
||||
}else{
|
||||
return book.unpack();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
if(saved && this.settings.restore && !forceReload){
|
||||
//-- Will load previous package json, or re-unpack if error
|
||||
opened = this.restore();
|
||||
|
||||
|
||||
}else{
|
||||
|
||||
//-- Get package information from epub opf
|
||||
|
@ -110,21 +126,6 @@ EPUBJS.Book.prototype.open = function(bookPath, forceReload){
|
|||
|
||||
}
|
||||
|
||||
} else if(this.settings.contained || this.isContained(this.bookUrl)){
|
||||
|
||||
|
||||
this.settings.contained = this.contained = true;
|
||||
this.settings.restore = true;
|
||||
|
||||
return; //-- TODO: this need to be fixed and tested before enabling
|
||||
opened = this.unarchive(this.bookUrl).then(function(){
|
||||
return book.unpack();
|
||||
});
|
||||
|
||||
}else{
|
||||
|
||||
//-- Get package information from epub opf
|
||||
opened = book.unpack();
|
||||
}
|
||||
|
||||
//-- If there is network connection, store the books contents
|
||||
|
@ -156,7 +157,6 @@ EPUBJS.Book.prototype.unpack = function(containerPath){
|
|||
}).
|
||||
then(function(contents){
|
||||
|
||||
|
||||
book.contents = contents;
|
||||
|
||||
book.manifest = book.contents.manifest;
|
||||
|
@ -165,7 +165,7 @@ EPUBJS.Book.prototype.unpack = function(containerPath){
|
|||
book.metadata = book.contents.metadata;
|
||||
|
||||
book.cover = book.contents.cover = book.settings.contentsPath + contents.coverPath;
|
||||
|
||||
|
||||
book.spineNodeIndex = book.contents.spineNodeIndex = contents.spineNodeIndex;
|
||||
|
||||
book.ready.manifest.resolve(book.contents.manifest);
|
||||
|
@ -184,8 +184,9 @@ EPUBJS.Book.prototype.unpack = function(containerPath){
|
|||
}).then(function(toc){
|
||||
book.toc = book.contents.toc = toc;
|
||||
book.ready.toc.resolve(book.contents.toc);
|
||||
// book.saveSettings();
|
||||
}).then(null, function(error) {
|
||||
console.log("Error:", error)
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
|
||||
|
@ -229,9 +230,10 @@ EPUBJS.Book.prototype.networkListeners = function(){
|
|||
|
||||
//-- Choose between a request from store or a request from network
|
||||
EPUBJS.Book.prototype.loadXml = function(url){
|
||||
|
||||
if(this.settings.storage) {
|
||||
if(this.settings.fromStorage) {
|
||||
return this.storage.getXml(url);
|
||||
} else if(this.settings.contained) {
|
||||
return this.zip.getXml(url);
|
||||
}else{
|
||||
return EPUBJS.core.request(url, 'xml');
|
||||
}
|
||||
|
@ -247,7 +249,7 @@ EPUBJS.Book.prototype.urlFrom = function(bookPath){
|
|||
|
||||
|
||||
|
||||
if(bookPath[bookPath.length - 1] != "/") bookPath += "/";
|
||||
// if(bookPath[bookPath.length - 1] != "/") bookPath += "/";
|
||||
|
||||
//-- 1. Check if url is absolute
|
||||
if(absolute){
|
||||
|
@ -267,18 +269,19 @@ EPUBJS.Book.prototype.urlFrom = function(bookPath){
|
|||
}
|
||||
|
||||
|
||||
EPUBJS.Book.prototype.unarchive = function(bookPath){
|
||||
var unzipped;
|
||||
|
||||
EPUBJS.Book.prototype.unarchive = function(bookPath){
|
||||
var book = this,
|
||||
unarchived;
|
||||
|
||||
//-- Must use storage
|
||||
if(this.settings.storage == false ){
|
||||
this.settings.storage = true;
|
||||
this.storage = new fileStorage.storage();
|
||||
}
|
||||
// if(this.settings.storage == false ){
|
||||
// this.settings.storage = true;
|
||||
// this.storage = new fileStorage.storage();
|
||||
// }
|
||||
|
||||
unzipped = new EPUBJS.Unarchiver(bookPath);
|
||||
|
||||
return unzipped;
|
||||
this.zip = new EPUBJS.Unarchiver();
|
||||
|
||||
return this.zip.openZip(bookPath);
|
||||
}
|
||||
|
||||
//-- Checks if url has a .epub or .zip extension
|
||||
|
@ -294,8 +297,8 @@ EPUBJS.Book.prototype.isContained = function(bookUrl){
|
|||
}
|
||||
|
||||
//-- Checks if the book setting can be retrieved from localStorage
|
||||
EPUBJS.Book.prototype.isSaved = function() {
|
||||
var bookKey = this.bookUrl + ":" + this.settings.version,
|
||||
EPUBJS.Book.prototype.isSaved = function(bookPath) {
|
||||
var bookKey = bookPath + ":" + this.settings.version,
|
||||
storedSettings = localStorage.getItem(bookKey);
|
||||
|
||||
if( !localStorage ||
|
||||
|
@ -308,7 +311,7 @@ EPUBJS.Book.prototype.isSaved = function() {
|
|||
|
||||
//-- Remove save book settings
|
||||
EPUBJS.Book.prototype.removeSavedSettings = function() {
|
||||
var bookKey = this.bookUrl + ":" + this.settings.version;
|
||||
var bookKey = this.settings.bookPath + ":" + this.settings.version;
|
||||
|
||||
localStorage.removeItem(bookKey);
|
||||
|
||||
|
@ -316,16 +319,15 @@ EPUBJS.Book.prototype.removeSavedSettings = function() {
|
|||
}
|
||||
|
||||
EPUBJS.Book.prototype.applySavedSettings = function() {
|
||||
var bookKey = this.bookUrl + ":" + this.settings.version;
|
||||
var bookKey = this.settings.bookPath + ":" + this.settings.version;
|
||||
stored = JSON.parse(localStorage.getItem(bookKey));
|
||||
|
||||
|
||||
if(EPUBJS.VERSION != stored.EPUBJSVERSION) return false;
|
||||
|
||||
this.settings = _.defaults(this.settings, stored);
|
||||
this.settings = _.defaults(this.settings, stored);
|
||||
}
|
||||
|
||||
EPUBJS.Book.prototype.saveSettings = function(){
|
||||
var bookKey = this.bookUrl + ":" + this.settings.version;
|
||||
var bookKey = this.settings.bookPath + ":" + this.settings.version;
|
||||
|
||||
if(this.render) {
|
||||
this.settings.previousLocationCfi = this.render.currentLocationCfi;
|
||||
|
@ -336,7 +338,7 @@ EPUBJS.Book.prototype.saveSettings = function(){
|
|||
}
|
||||
|
||||
EPUBJS.Book.prototype.saveContents = function(){
|
||||
var contentsKey = this.settings.contentsPath + ":" + this.settings.version;
|
||||
var contentsKey = this.settings.bookPath + ":contents:" + this.settings.version;
|
||||
|
||||
localStorage.setItem(contentsKey, JSON.stringify(this.contents));
|
||||
|
||||
|
@ -363,7 +365,7 @@ EPUBJS.Book.prototype.renderTo = function(el){
|
|||
|
||||
EPUBJS.Book.prototype.startDisplay = function(){
|
||||
var display;
|
||||
if( this.settings.previousLocationCfi) {
|
||||
if( this.settings.restore && this.settings.previousLocationCfi) {
|
||||
|
||||
display = this.displayChapter(this.settings.previousLocationCfi);
|
||||
|
||||
|
@ -377,13 +379,13 @@ EPUBJS.Book.prototype.startDisplay = function(){
|
|||
EPUBJS.Book.prototype.restore = function(){
|
||||
|
||||
var book = this,
|
||||
contentsKey = this.settings.contentsPath + ":" + this.settings.version,
|
||||
contentsKey = this.settings.bookPath + ":contents:" + this.settings.version,
|
||||
promise = new RSVP.Promise(),
|
||||
fetch = ['manifest', 'spine', 'metadata', 'cover', 'toc', 'spineNodeIndex', 'spineIndexByURL'],
|
||||
reject = false,
|
||||
fromStore = localStorage.getItem(contentsKey);
|
||||
|
||||
if(this.settings.contentsPath && fromStore){
|
||||
|
||||
if(fromStore != 'undefined'){
|
||||
this.contents = JSON.parse(fromStore);
|
||||
|
||||
fetch.forEach(function(item){
|
||||
|
@ -394,12 +396,9 @@ EPUBJS.Book.prototype.restore = function(){
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
if(reject || !fromStore || !this.contents ){
|
||||
|
||||
this.removeSavedSettings();
|
||||
|
||||
return this.unpack();
|
||||
if(reject || !fromStore || !this.contents || !this.settings.contentsPath){
|
||||
// this.removeSavedSettings();
|
||||
return this.open(this.settings.bookPath, true);
|
||||
|
||||
}else{
|
||||
this.ready.manifest.resolve(this.manifest);
|
||||
|
@ -407,7 +406,6 @@ EPUBJS.Book.prototype.restore = function(){
|
|||
this.ready.metadata.resolve(this.metadata);
|
||||
this.ready.cover.resolve(this.cover);
|
||||
this.ready.toc.resolve(this.toc);
|
||||
|
||||
promise.resolve();
|
||||
return promise;
|
||||
}
|
||||
|
@ -461,7 +459,8 @@ EPUBJS.Book.prototype.displayChapter = function(chap, end){
|
|||
}
|
||||
|
||||
|
||||
if(!this.settings.storage) {
|
||||
if(!this.settings.fromStorage &&
|
||||
!this.settings.contained) {
|
||||
render.then(function(){
|
||||
book.preloadNextChapter();
|
||||
});
|
||||
|
@ -592,7 +591,7 @@ EPUBJS.Book.prototype.setStyle = function(style, val, prefixed) {
|
|||
EPUBJS.Book.prototype.removeStyle = function(style, val, prefixed) {
|
||||
this.renderer.removeStyle(style);
|
||||
|
||||
delete this.settings.styles[style] = '';
|
||||
delete this.settings.styles[style];
|
||||
}
|
||||
|
||||
|
||||
|
@ -614,19 +613,26 @@ EPUBJS.Book.prototype.getHooks = function(){
|
|||
|
||||
//-- Hooks allow for injecting async functions that must all complete before continuing
|
||||
// Functions must have a callback as their first argument.
|
||||
EPUBJS.Book.prototype.registerHook = function(type, toAdd){
|
||||
var that = this;
|
||||
EPUBJS.Book.prototype.registerHook = function(type, toAdd, toFront){
|
||||
var book = this;
|
||||
|
||||
if(typeof(this.hooks[type]) != "undefined"){
|
||||
|
||||
if(typeof(toAdd) === "function"){
|
||||
this.hooks[type].push(toAdd);
|
||||
if(toFront) {
|
||||
this.hooks[type].unshift(toAdd);
|
||||
}else{
|
||||
this.hooks[type].push(toAdd);
|
||||
}
|
||||
}else if(Array.isArray(toAdd)){
|
||||
toAdd.forEach(function(hook){
|
||||
that.hooks[type].push(hook);
|
||||
if(toFront) {
|
||||
book.hooks[type].unshift(hook);
|
||||
}else{
|
||||
book.hooks[type].push(hook);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}else{
|
||||
//-- Allows for undefined hooks, but maybe this should error?
|
||||
this.hooks[type] = [func];
|
||||
|
|
|
@ -20,9 +20,12 @@ EPUBJS.Chapter.prototype.contents = function(store){
|
|||
|
||||
EPUBJS.Chapter.prototype.url = function(store){
|
||||
var promise = new RSVP.Promise();
|
||||
|
||||
|
||||
if(store){
|
||||
return store.getUrl(href);
|
||||
if(!this.tempUrl) {
|
||||
this.tempUrl = store.getUrl(this.href);
|
||||
}
|
||||
return this.tempUrl;
|
||||
}else{
|
||||
promise.resolve(this.href); //-- this is less than ideal but keeps it a promise
|
||||
return promise;
|
||||
|
@ -40,4 +43,12 @@ EPUBJS.Chapter.prototype.getPages = function(num){
|
|||
|
||||
EPUBJS.Chapter.prototype.getID = function(){
|
||||
return this.ID;
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.unload = function(store){
|
||||
|
||||
if(this.tempUrl && store) {
|
||||
store.revokeUrl(this.tempUrl);
|
||||
this.tempUrl = false;
|
||||
}
|
||||
}
|
24
src/core.js
24
src/core.js
|
@ -36,7 +36,7 @@ EPUBJS.core.request = function(url, type) {
|
|||
|
||||
function handler() {
|
||||
if (this.readyState === this.DONE) {
|
||||
if (this.status === 200) {
|
||||
if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls
|
||||
var r;
|
||||
|
||||
if(type == 'xml'){
|
||||
|
@ -279,3 +279,25 @@ EPUBJS.core.addScript = function(src, callback, target) {
|
|||
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.core.resolveUrl = function(base, path) {
|
||||
var url,
|
||||
segments = [],
|
||||
folders = base.split("/"),
|
||||
paths;
|
||||
|
||||
folders.pop();
|
||||
|
||||
paths = path.split("/");
|
||||
paths.forEach(function(p){
|
||||
if(p === ".."){
|
||||
folders.pop();
|
||||
}else{
|
||||
segments.push(p);
|
||||
}
|
||||
});
|
||||
|
||||
url = folders.concat(segments);
|
||||
|
||||
return url.join("/");
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ EPUBJS.EpubCFI.prototype.generateFragment = function(element, chapter) {
|
|||
parts.push((part.index + 1) * 2);
|
||||
|
||||
if(part.id &&
|
||||
part.id.slice(0, 7) != "@EPUBJS") { //-- ignore internal @EPUBJS ids
|
||||
part.id.slice(0, 6) != "EPUBJS") { //-- ignore internal @EPUBJS ids
|
||||
|
||||
parts.push("[" + part.id + "]");
|
||||
}
|
||||
|
@ -149,6 +149,7 @@ EPUBJS.EpubCFI.prototype.getElement = function(cfi, doc) {
|
|||
part = sections.shift();
|
||||
|
||||
if(part.id){
|
||||
console.log(part.id)
|
||||
element = cfi.doc.querySelector("#" + part.id);
|
||||
}else{
|
||||
|
||||
|
|
|
@ -18,17 +18,17 @@ EPUBJS.Parser.prototype.container = function(containerXml){
|
|||
|
||||
EPUBJS.Parser.prototype.package = function(packageXml, baseUrl){
|
||||
var parse = this;
|
||||
|
||||
|
||||
if(baseUrl) this.baseUrl = baseUrl;
|
||||
|
||||
var metadataNode = packageXml.querySelector("metadata"),
|
||||
manifestNode = packageXml.querySelector("manifest"),
|
||||
spineNode = packageXml.querySelector("spine");
|
||||
|
||||
|
||||
var manifest = parse.manifest(manifestNode),
|
||||
tocPath = parse.findTocPath(manifestNode),
|
||||
coverPath = parse.findCoverPath(manifestNode);
|
||||
|
||||
|
||||
var spineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode);
|
||||
|
||||
var spine = parse.spine(spineNode, manifest);
|
||||
|
@ -52,13 +52,13 @@ EPUBJS.Parser.prototype.package = function(packageXml, baseUrl){
|
|||
//-- Find TOC NCX: media-type="application/x-dtbncx+xml" href="toc.ncx"
|
||||
EPUBJS.Parser.prototype.findTocPath = function(manifestNode){
|
||||
var node = manifestNode.querySelector("item[media-type='application/x-dtbncx+xml']");
|
||||
return node.getAttribute('href');
|
||||
return node ? node.getAttribute('href') : false;
|
||||
}
|
||||
|
||||
//-- Find Cover: <item properties="cover-image" id="ci" href="cover.svg" media-type="image/svg+xml" />
|
||||
EPUBJS.Parser.prototype.findCoverPath = function(manifestNode){
|
||||
var node = manifestNode.querySelector("item[properties='cover-image']");
|
||||
return node.getAttribute('href');
|
||||
return node ? node.getAttribute('href') : false;
|
||||
}
|
||||
|
||||
|
||||
|
|
242
src/renderer.js
242
src/renderer.js
|
@ -15,13 +15,15 @@ EPUBJS.Renderer = function(book) {
|
|||
}
|
||||
|
||||
book.registerHook("beforeChapterDisplay",
|
||||
[this.replaceLinks.bind(this), this.replaceResources.bind(this)]);
|
||||
[this.replaceLinks.bind(this),
|
||||
this.replaceResources.bind(this),
|
||||
this.replaceHead.bind(this)], true);
|
||||
|
||||
|
||||
this.crossBrowserColumnCss();
|
||||
|
||||
this.epubcfi = new EPUBJS.EpubCFI();
|
||||
|
||||
|
||||
this.initialize();
|
||||
this.listeners();
|
||||
}
|
||||
|
@ -50,9 +52,13 @@ EPUBJS.Renderer.prototype.listeners = function(){
|
|||
|
||||
EPUBJS.Renderer.prototype.chapter = function(chapter){
|
||||
var renderer = this,
|
||||
store = this.settings.stored ? this.store : false;
|
||||
store = false;
|
||||
|
||||
if(this.book.settings.contained) store = this.book.zip;
|
||||
// if(this.settings.stored) store = this.storage;
|
||||
|
||||
if(this.currentChapter) {
|
||||
this.currentChapter.unload();
|
||||
this.trigger("book:chapterDestroyed");
|
||||
}
|
||||
|
||||
|
@ -189,6 +195,8 @@ EPUBJS.Renderer.prototype.setIframeSrc = function(url){
|
|||
|
||||
renderer.calcPages();
|
||||
|
||||
promise.resolve(renderer);
|
||||
|
||||
renderer.currentLocationCfi = renderer.getPageCfi();
|
||||
|
||||
renderer.trigger("book:chapterDisplayed");
|
||||
|
@ -197,7 +205,7 @@ EPUBJS.Renderer.prototype.setIframeSrc = function(url){
|
|||
|
||||
});
|
||||
|
||||
promise.resolve(renderer);
|
||||
|
||||
// that.afterLoaded(that);
|
||||
|
||||
|
||||
|
@ -246,6 +254,7 @@ EPUBJS.Renderer.prototype.formatSpread = function(){
|
|||
|
||||
this.spreadWidth = (this.colWidth + this.gap) * divisor;
|
||||
|
||||
if(this.bodyEl) this.bodyEl.style.margin = 0;
|
||||
// this.bodyEl.style.fontSize = localStorage.getItem("fontSize") || "medium";
|
||||
|
||||
//-- Clear Margins
|
||||
|
@ -328,7 +337,7 @@ EPUBJS.Renderer.prototype.calcPages = function() {
|
|||
this.totalWidth = this.docEl.scrollWidth;
|
||||
|
||||
this.displayedPages = Math.ceil(this.totalWidth / this.spreadWidth);
|
||||
|
||||
|
||||
this.currentChapter.pages = this.displayedPages;
|
||||
}
|
||||
|
||||
|
@ -372,6 +381,8 @@ EPUBJS.Renderer.prototype.prevPage = function(){
|
|||
|
||||
EPUBJS.Renderer.prototype.chapterEnd = function(){
|
||||
this.page(this.displayedPages);
|
||||
|
||||
this.currentLocationCfi = this.getPageCfi();
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.setLeft = function(leftPos){
|
||||
|
@ -379,9 +390,186 @@ EPUBJS.Renderer.prototype.setLeft = function(leftPos){
|
|||
this.doc.defaultView.scrollTo(leftPos, 0)
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.replace = function(query, func, callback){
|
||||
var items, resources, count;
|
||||
|
||||
items = this.doc.querySelectorAll(query);
|
||||
resources = Array.prototype.slice.call(items);
|
||||
count = resources.length;
|
||||
|
||||
resources.forEach(function(item){
|
||||
|
||||
func(item, function(){
|
||||
count--;
|
||||
if(count <= 0 && callback) callback();
|
||||
});
|
||||
|
||||
}.bind(this));
|
||||
|
||||
if(count === 0) callback();
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.determineStore = function(callback){
|
||||
if(this.book.fromStorage) {
|
||||
|
||||
//-- Filesystem api links are relative, so no need to replace them
|
||||
if(this.book.storage.getStorageType() == "filesystem") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.book.store;
|
||||
|
||||
} else if(this.book.contained) {
|
||||
|
||||
return this.book.zip;
|
||||
|
||||
} else {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//-- Replaces links in head, such as stylesheets
|
||||
EPUBJS.Renderer.prototype.replaceHead = function(callback){
|
||||
var srcs, resources, count, oldUrls,
|
||||
newUrls = {},
|
||||
unarchiver = this,
|
||||
store = this.determineStore(),
|
||||
replaceUrl = function(link, url){
|
||||
link.setAttribute("href", url);
|
||||
link.onload = function(){
|
||||
count--;
|
||||
if(count <= 0) finished();
|
||||
}
|
||||
},
|
||||
finished = function() {
|
||||
|
||||
if(callback) callback();
|
||||
|
||||
_.each(oldUrls, function(url){
|
||||
store.revokeUrl(url);
|
||||
});
|
||||
|
||||
unarchiver.urlCache = newUrls;
|
||||
};
|
||||
|
||||
if(!store) {
|
||||
if(callback) callback();
|
||||
return false;
|
||||
}
|
||||
|
||||
srcs = this.doc.head.querySelectorAll('[href]');
|
||||
resources = Array.prototype.slice.call(srcs);
|
||||
count = resources.length;
|
||||
|
||||
if(!this.urlCache) this.urlCache = {};
|
||||
oldUrls = _.clone(this.urlCache);
|
||||
|
||||
resources.forEach(function(link){
|
||||
var src = link.getAttribute("href"),
|
||||
full = this.book.settings.contentsPath + src;
|
||||
|
||||
|
||||
if(full in oldUrls){
|
||||
replaceUrl(link, oldUrls[full]);
|
||||
newUrls[full] = oldUrls[full];
|
||||
delete oldUrls[full];
|
||||
}else{
|
||||
|
||||
//-- Handle replacing urls in CSS
|
||||
if(link.getAttribute("rel") === "stylesheet") {
|
||||
store.getText(full).then(function(text){
|
||||
var url;
|
||||
|
||||
unarchiver.replaceUrlsInCss(full, text).then(function(newText){
|
||||
var _URL = window.URL || window.webkitURL || window.mozURL;
|
||||
|
||||
var blob = new Blob([newText], { "type" : "text\/css" }),
|
||||
url = _URL.createObjectURL(blob);
|
||||
|
||||
replaceUrl(link, url);
|
||||
newUrls[full] = url;
|
||||
|
||||
}, function(e) {console.error(e)});
|
||||
|
||||
});
|
||||
}else{
|
||||
store.getUrl(full).then(function(url){
|
||||
replaceUrl(link, url);
|
||||
newUrls[full] = url;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}.bind(this));
|
||||
|
||||
if(count === 0) finished();
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.replaceUrlsInCss = function(base, text){
|
||||
var promise = new RSVP.Promise(),
|
||||
promises = [],
|
||||
store = this.determineStore(),
|
||||
matches = text.match(/url\(\'?\"?([^\'|^\"]*)\'?\"?\)/g);
|
||||
|
||||
matches.forEach(function(str){
|
||||
var full = EPUBJS.core.resolveUrl(base, str.replace(/url\(|[|\)|\'|\"]/g, ''));
|
||||
replaced = store.getUrl(full).then(function(url){
|
||||
text = text.replace(str, 'url("'+url+'")');
|
||||
}, function(e) {console.error(e)} );
|
||||
|
||||
promises.push(replaced);
|
||||
});
|
||||
|
||||
RSVP.all(promises).then(function(){
|
||||
promise.resolve(text);
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
/*
|
||||
//-- Replaces links in head, such as stylesheets
|
||||
EPUBJS.Renderer.prototype.replaceCss = function(callback){
|
||||
var styleSheets = this.doc.styleSheets,
|
||||
store = this.determineStore(),
|
||||
rules = [];
|
||||
|
||||
_.each(styleSheets, function(sheet){
|
||||
_.each(sheet.cssRules, function(rule, index){
|
||||
if(rule.type == 5) {
|
||||
//url("../fonts/STIXGeneral.otf")
|
||||
// if()
|
||||
var urlString = rule.cssText.match(/url\(\'?\"?([^\'|^\"]*)\'?\"?\)/),
|
||||
full;
|
||||
// rule.cssText = ""
|
||||
// console.log(rule.style.src, rule.style[3])
|
||||
// console.log(urlString)
|
||||
|
||||
if(urlString[1]){
|
||||
full = "OPS/" + urlString[1].slice(3);
|
||||
store.getUrl(full).then(function(url){
|
||||
var newRule = rule.cssText.replace(/url\(\'?\"?([^\'|^\"]*)\'?\"?\)/, 'url("'+url+'")');
|
||||
sheet.deleteRule(index)
|
||||
sheet.insertRule(newRule, false);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//-- Replaces the relative links within the book to use our internal page changer
|
||||
EPUBJS.Renderer.prototype.replaceLinks = function(callback){
|
||||
var hrefs = this.doc.querySelectorAll('[href]'),
|
||||
var hrefs = this.doc.querySelectorAll('a'),
|
||||
links = Array.prototype.slice.call(hrefs),
|
||||
that = this;
|
||||
|
||||
|
@ -390,7 +578,7 @@ EPUBJS.Renderer.prototype.replaceLinks = function(callback){
|
|||
href = link.getAttribute("href"),
|
||||
relative = href.search("://"),
|
||||
fragment = href[0] == "#";
|
||||
|
||||
|
||||
if(relative != -1){
|
||||
|
||||
link.setAttribute("target", "_blank");
|
||||
|
@ -411,30 +599,35 @@ EPUBJS.Renderer.prototype.replaceLinks = function(callback){
|
|||
//-- Replaces assets src's to point to stored version if browser is offline
|
||||
EPUBJS.Renderer.prototype.replaceResources = function(callback){
|
||||
var srcs, resources, count;
|
||||
|
||||
//-- No need to replace if there is network connectivity
|
||||
//-- also Filesystem api links are relative, so no need to replace them
|
||||
if((this.book.online && !this.book.contained) || EPUBJS.storage.getStorageType() == "filesystem") {
|
||||
var store = this.determineStore();
|
||||
|
||||
if(!store) {
|
||||
if(callback) callback();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
srcs = this.doc.querySelectorAll('[src]');
|
||||
resources = Array.prototype.slice.call(srcs);
|
||||
count = resources.length;
|
||||
|
||||
|
||||
resources.forEach(function(link){
|
||||
var src = link.getAttribute("src"),
|
||||
full = this.book.basePath + src;
|
||||
full = this.book.settings.contentsPath + src;
|
||||
|
||||
EPUBJS.storage.get(full, function(url){
|
||||
link.setAttribute("src", url);
|
||||
count--;
|
||||
if(count <= 0 && callback) callback();
|
||||
store.getUrl(full).then(function(url){
|
||||
// link.setAttribute("src", url);
|
||||
link.src = url;
|
||||
|
||||
link.onload = function(){
|
||||
count--;
|
||||
if(count <= 0 && callback) callback();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
}.bind(this));
|
||||
|
||||
|
||||
if(count === 0) callback();
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.page = function(pg){
|
||||
|
@ -446,7 +639,7 @@ EPUBJS.Renderer.prototype.page = function(pg){
|
|||
// localStorage.setItem("chapterPos", pg);
|
||||
return true;
|
||||
}
|
||||
console.log("false", pg, this.displayedPages)
|
||||
|
||||
//-- Return false if page is greater than the total
|
||||
return false;
|
||||
}
|
||||
|
@ -534,7 +727,7 @@ EPUBJS.Renderer.prototype.getPageCfi = function(){
|
|||
this.visibileEl = this.findFirstVisible(prevEl);
|
||||
|
||||
if(!this.visibileEl.id) {
|
||||
this.visibileEl.id = "@EPUBJS-PAGE-" + this.chapterPos;
|
||||
this.visibileEl.id = "EPUBJS-PAGE-" + this.chapterPos;
|
||||
}
|
||||
|
||||
this.pageIds[this.chapterPos] = this.visibileEl.id;
|
||||
|
@ -586,6 +779,11 @@ EPUBJS.Renderer.prototype.isElementVisible = function(el){
|
|||
}
|
||||
|
||||
|
||||
EPUBJS.Renderer.prototype.height = function(el){
|
||||
return this.docEl.offsetHeight;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,43 +1,113 @@
|
|||
EPUBJS.Unarchiver = function(url, callback){
|
||||
this.libPath = EPUBJS.filePath + "libs/";
|
||||
EPUBJS.Unarchiver = function(url){
|
||||
|
||||
|
||||
this.libPath = EPUBJS.filePath + "zip/";
|
||||
this.zipUrl = url;
|
||||
this.callback = callback;
|
||||
this.loadLib(function(){
|
||||
this.getZip(this.zipUrl);
|
||||
}.bind(this));
|
||||
this.loadLib()
|
||||
this.urlCache = {};
|
||||
|
||||
this.zipFs = new zip.fs.FS();
|
||||
|
||||
return this.promise;
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.loadLib = function(callback){
|
||||
if(typeof(zip) != "undefined") callback();
|
||||
if(typeof(zip) == "undefined") console.error("Zip lib not loaded");
|
||||
|
||||
/*
|
||||
//-- load script
|
||||
EPUBJS.core.loadScript(this.libPath+"zip.js", function(){
|
||||
//-- Tell zip where it is located
|
||||
zip.workerScriptsPath = this.libPath;
|
||||
callback();
|
||||
}.bind(this));
|
||||
*/
|
||||
// console.log(this.libPath)
|
||||
zip.workerScriptsPath = this.libPath;
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.getZip = function(zipUrl){
|
||||
var xhr = new EPUBJS.core.loadFile(zipUrl);
|
||||
|
||||
xhr.succeeded = function(file) {
|
||||
this.getEntries(file, this.toStorage.bind(this));
|
||||
}.bind(this);
|
||||
|
||||
xhr.failed = this.failed;
|
||||
|
||||
xhr.start();
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.getEntries = function(file, callback){
|
||||
zip.createReader(new zip.BlobReader(file), function(zipReader) {
|
||||
zipReader.getEntries(callback);
|
||||
EPUBJS.Unarchiver.prototype.openZip = function(zipUrl, callback){
|
||||
var promise = new RSVP.Promise();
|
||||
var zipFs = this.zipFs;
|
||||
zipFs.importHttpContent(zipUrl, false, function() {
|
||||
promise.resolve(zipFs);
|
||||
}, this.failed);
|
||||
|
||||
return promise
|
||||
}
|
||||
|
||||
// EPUBJS.Unarchiver.prototype.getXml = function(url){
|
||||
// var unarchiver = this,
|
||||
// request;
|
||||
// return this.getUrl(url, 'application/xml').
|
||||
// then(function(newUrl){
|
||||
// request = EPUBJS.core.request(newUrl, 'xml');
|
||||
// //-- Remove temp url after use
|
||||
// request.then(function(uri){
|
||||
// unarchiver.revokeUrl(uri);
|
||||
// });
|
||||
// return request
|
||||
// });
|
||||
//
|
||||
// }
|
||||
EPUBJS.Unarchiver.prototype.getXml = function(url){
|
||||
|
||||
return this.getText(url).
|
||||
then(function(text){
|
||||
var parser = new DOMParser();
|
||||
return parser.parseFromString(text, "application/xml");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.getUrl = function(url, mime){
|
||||
var unarchiver = this;
|
||||
var promise = new RSVP.Promise();
|
||||
var entry = this.zipFs.find(url);
|
||||
var _URL = window.URL || window.webkitURL || window.mozURL;
|
||||
|
||||
if(!entry) console.error(url);
|
||||
|
||||
if(url in this.urlCache) {
|
||||
promise.resolve(this.urlCache[url]);
|
||||
return promise;
|
||||
}
|
||||
|
||||
entry.getBlob(mime || zip.getMimeType(entry.name), function(blob){
|
||||
var tempUrl = _URL.createObjectURL(blob);
|
||||
promise.resolve(tempUrl);
|
||||
unarchiver.urlCache[url] = tempUrl;
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.getText = function(url){
|
||||
var unarchiver = this;
|
||||
var promise = new RSVP.Promise();
|
||||
var entry = this.zipFs.find(url);
|
||||
var _URL = window.URL || window.webkitURL || window.mozURL;
|
||||
|
||||
if(!entry) console.error(url);
|
||||
|
||||
|
||||
entry.getText(function(text){
|
||||
promise.resolve(text);
|
||||
}, null, null, 'ISO-8859-1');
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.revokeUrl = function(url){
|
||||
var _URL = window.URL || window.webkitURL || window.mozURL;
|
||||
var fromCache = unarchiver.urlCache[url];
|
||||
console.log("revoke", fromCache);
|
||||
if(fromCache) _URL.revokeObjectURL(fromCache);
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.failed = function(error){
|
||||
console.log("Error:", error);
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
EPUBJS.Unarchiver.prototype.afterSaved = function(error){
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue