1
0
Fork 0
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:
Fred Chasen 2013-07-08 22:24:51 -07:00
parent 0cfaa9cf2e
commit cb813ab927
26 changed files with 5593 additions and 4871 deletions

View file

@ -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,27 +87,43 @@ 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.restore){
if(this.settings.contained || this.isContained(bookPath)){
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();
@ -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;
@ -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){
@ -276,17 +278,18 @@ EPUBJS.Book.prototype.urlFrom = function(bookPath){
EPUBJS.Book.prototype.unarchive = function(bookPath){
var unzipped;
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);
this.zip = new EPUBJS.Unarchiver();
return unzipped;
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);
}
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"){
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];
@ -687,7 +693,10 @@ 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'){
@ -988,6 +1005,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{
@ -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,7 +1495,9 @@ 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();
@ -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
@ -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;
@ -1851,10 +2079,9 @@ 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;
var store = this.determineStore();
//-- 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") {
if(!store) {
if(callback) callback();
return false;
}
@ -1865,16 +2092,22 @@ EPUBJS.Renderer.prototype.replaceResources = function(callback){
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);
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){

View file

@ -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);
});

View file

@ -1,4 +1,4 @@
/*! FuturePress - v0.1.0 - 2013-06-30 */
/*! FuturePress - v0.1.0 - 2013-07-08 */
var EPUBJSR = EPUBJSR || {};

View file

@ -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

File diff suppressed because one or more lines are too long

View file

@ -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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
demo/moby-dick.epub Normal file

Binary file not shown.

View file

@ -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">

View file

@ -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']
}
});

View file

@ -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);
});

View file

@ -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:
@ -89,8 +89,6 @@
// Tree
// see definition of array dist_code below
var DIST_CODE_LEN = 512;
var _dist_code = [ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
@ -464,11 +462,6 @@
var STATIC_TREES = 1;
var DYN_TREES = 2;
// The three kinds of block type
var Z_BINARY = 0;
var Z_ASCII = 1;
var Z_UNKNOWN = 2;
var MIN_MATCH = 3;
var MAX_MATCH = 258;
var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
@ -488,7 +481,6 @@
var pending_buf_size; // size of pending_buf
// pending_out; // next pending byte to output to the stream
// pending; // nb of bytes in the pending buffer
// data_type; // UNKNOWN, BINARY or ASCII
var method; // STORED (for zip only) or DEFLATED
var last_flush; // value of flush param for previous deflate call
@ -1035,29 +1027,6 @@
last_eob_len = ltree[END_BLOCK * 2 + 1];
}
// Set the data type to ASCII or BINARY, using a crude approximation:
// binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
// IN assertion: the fields freq of dyn_ltree are set and the total of all
// frequencies does not exceed 64K (to fit in an int on 16 bit machines).
function set_data_type() {
var n = 0;
var ascii_freq = 0;
var bin_freq = 0;
while (n < 7) {
bin_freq += dyn_ltree[n * 2];
n++;
}
while (n < 128) {
ascii_freq += dyn_ltree[n * 2];
n++;
}
while (n < LITERALS) {
bin_freq += dyn_ltree[n * 2];
n++;
}
that.data_type = (bin_freq > (ascii_freq >>> 2) ? Z_BINARY : Z_ASCII) & 0xff;
}
// Flush the bit buffer and align the output on a byte boundary
function bi_windup() {
if (bi_valid > 8) {
@ -1075,7 +1044,6 @@
len, // its length
header // true if block header must be written
) {
var index = 0;
bi_windup(); // align on byte boundary
last_eob_len = 8; // enough lookahead for inflate
@ -1108,10 +1076,6 @@
// Build the Huffman trees unless a stored block is forced
if (level > 0) {
// Check if the file is ascii or binary
if (that.data_type == Z_UNKNOWN)
set_data_type();
// Construct the literal and distance trees
l_desc.build_tree(that);
@ -1643,7 +1607,6 @@
function deflateReset(strm) {
strm.total_in = strm.total_out = 0;
strm.msg = null; //
strm.data_type = Z_UNKNOWN;
that.pending = 0;
that.pending_out = 0;
@ -1928,8 +1891,6 @@
that.total_out = 0; // total nb of bytes output so far
// that.msg;
// that.dstate;
// that.data_type; // best guess about the data type: ascii or binary
}
ZStream.prototype = {
@ -2071,7 +2032,7 @@
return array;
};
that.flush = function() {
var err, ab, buffers = [], bufferIndex = 0, bufferSize = 0, array;
var err, buffers = [], bufferIndex = 0, bufferSize = 0, array;
do {
z.next_out_index = 0;
z.avail_out = bufsize;

View file

@ -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:
@ -51,9 +51,6 @@
var MANY = 1440;
var MAX_WBITS = 15; // 32K LZ77 window
var DEF_WBITS = MAX_WBITS;
// JZlib version : "1.0.2"
var Z_NO_FLUSH = 0;
var Z_FINISH = 4;
@ -432,8 +429,7 @@
InfTree.inflate_trees_fixed = function(bl, // literal desired/actual bit depth
bd, // distance desired/actual bit depth
tl,// literal/length tree result
td,// distance tree result
z // for memory allocation
td// distance tree result
) {
bl[0] = fixed_bl;
bd[0] = fixed_bd;
@ -735,7 +731,7 @@
return Z_OK;
}
that.init = function(bl, bd, tl, tl_index, td, td_index, z) {
that.init = function(bl, bd, tl, tl_index, td, td_index) {
mode = START;
lbits = /* (byte) */bl;
dbits = /* (byte) */bd;
@ -748,7 +744,6 @@
that.proc = function(s, z, r) {
var j; // temporary storage
var t; // temporary pointer
var tindex; // temporary pointer
var e; // extra bits or operation
var b = 0; // bit buffer
@ -1102,7 +1097,7 @@
}
};
that.free = function(z) {
that.free = function() {
// ZFREE(z, c);
};
@ -1298,8 +1293,8 @@
var tl = [ [] ]; // new Array(1);
var td = [ [] ]; // new Array(1);
InfTree.inflate_trees_fixed(bl, bd, tl, td, z);
codes.init(bl[0], bd[0], tl[0], 0, td[0], 0, z);
InfTree.inflate_trees_fixed(bl, bd, tl, td);
codes.init(bl[0], bd[0], tl[0], 0, td[0], 0);
// }
// {
@ -1533,7 +1528,6 @@
break;
}
var h;
var j, c;
t = bb[0];
@ -1647,7 +1641,7 @@
that.write = q;
return that.inflate_flush(z, r);
}
codes.init(bl_[0], bd_[0], hufts, tl_[0], hufts, td_[0], z);
codes.init(bl_[0], bd_[0], hufts, tl_[0], hufts, td_[0]);
// }
mode = CODES;
case CODES:
@ -2113,7 +2107,7 @@
return -1;
if (err != Z_OK && err != Z_STREAM_END)
throw "inflating: " + z.msg;
if ((nomoreinput || err == Z_STREAM_END) && (z.avail_out == data.length))
if ((nomoreinput || err == Z_STREAM_END) && (z.avail_in == data.length))
return -1;
if (z.next_out_index)
if (z.next_out_index == bufsize)

View file

@ -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
View 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);
};
}
})();

View file

@ -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);
@ -251,9 +247,9 @@
}
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,7 +526,9 @@
};
zip.fs = {
FS : FS
FS : FS,
ZipDirectoryEntry : ZipDirectoryEntry,
ZipFileEntry : ZipFileEntry
};
zip.getMimeType = function() {

View file

@ -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
View 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();
});

View file

@ -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,27 +79,43 @@ 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.restore){
if(this.settings.contained || this.isContained(bookPath)){
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();
@ -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;
@ -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){
@ -268,17 +270,18 @@ EPUBJS.Book.prototype.urlFrom = function(bookPath){
EPUBJS.Book.prototype.unarchive = function(bookPath){
var unzipped;
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);
this.zip = new EPUBJS.Unarchiver();
return unzipped;
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);
}
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"){
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];

View file

@ -22,7 +22,10 @@ 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;
@ -41,3 +44,11 @@ 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;
}
}

View file

@ -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("/");
}

View file

@ -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{

View file

@ -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;
}

View file

@ -15,7 +15,9 @@ 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();
@ -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
@ -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;
@ -411,10 +599,9 @@ 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;
var store = this.determineStore();
//-- 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") {
if(!store) {
if(callback) callback();
return false;
}
@ -425,16 +612,22 @@ EPUBJS.Renderer.prototype.replaceResources = function(callback){
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);
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;
}

View file

@ -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){