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

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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

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

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,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];

View file

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

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

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

View file

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

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