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 || {}; var EPUBJS = EPUBJS || {};
EPUBJS.VERSION = "0.1.5"; EPUBJS.VERSION = "0.1.5";
@ -21,7 +21,7 @@ EPUBJS.Book = function(bookPath, options){
spreads: true, spreads: true,
responsive: true, responsive: true,
version: 1, version: 1,
restore: false restore: true
}); });
this.settings.EPUBJSVERSION = EPUBJS.VERSION; this.settings.EPUBJSVERSION = EPUBJS.VERSION;
@ -73,7 +73,7 @@ EPUBJS.Book = function(bookPath, options){
} }
// Likewise if an element is present start rendering process // Likewise if an element is present start rendering process
if(this.settings.element) { if(bookPath && this.settings.element) {
this.opened.then(function(){ this.opened.then(function(){
this.rendered = this.renderTo(el); 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 //-- Check bookUrl and start parsing book Assets or load them from storage
EPUBJS.Book.prototype.open = function(bookPath, forceReload){ EPUBJS.Book.prototype.open = function(bookPath, forceReload){
var book = this, var book = this,
saved = this.isSaved(bookPath),
opened; opened;
this.settings.bookPath = bookPath;
//-- Get a absolute URL from the book path //-- Get a absolute URL from the book path
this.bookUrl = this.urlFrom(bookPath); this.bookUrl = this.urlFrom(bookPath);
// console.log("saved", saved, !forceReload)
//-- Remove the previous settings and reload //-- Remove the previous settings and reload
if(forceReload){ if(saved && !forceReload){
this.removeSavedSettings();
}
//-- Check for a saved settings object, with the same url and version
if(this.isSaved()){
//-- Apply settings, keeping newer ones //-- Apply settings, keeping newer ones
this.applySavedSettings(); 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 //-- Will load previous package json, or re-unpack if error
opened = this.restore(); 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 //-- If there is network connection, store the books contents
@ -164,7 +165,6 @@ EPUBJS.Book.prototype.unpack = function(containerPath){
}). }).
then(function(contents){ then(function(contents){
book.contents = contents; book.contents = contents;
book.manifest = book.contents.manifest; book.manifest = book.contents.manifest;
@ -192,8 +192,9 @@ EPUBJS.Book.prototype.unpack = function(containerPath){
}).then(function(toc){ }).then(function(toc){
book.toc = book.contents.toc = toc; book.toc = book.contents.toc = toc;
book.ready.toc.resolve(book.contents.toc); book.ready.toc.resolve(book.contents.toc);
// book.saveSettings();
}).then(null, function(error) { }).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 //-- Choose between a request from store or a request from network
EPUBJS.Book.prototype.loadXml = function(url){ EPUBJS.Book.prototype.loadXml = function(url){
if(this.settings.fromStorage) {
if(this.settings.storage) {
return this.storage.getXml(url); return this.storage.getXml(url);
} else if(this.settings.contained) {
return this.zip.getXml(url);
}else{ }else{
return EPUBJS.core.request(url, 'xml'); 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 //-- 1. Check if url is absolute
if(absolute){ if(absolute){
@ -276,17 +278,18 @@ EPUBJS.Book.prototype.urlFrom = function(bookPath){
EPUBJS.Book.prototype.unarchive = function(bookPath){ EPUBJS.Book.prototype.unarchive = function(bookPath){
var unzipped; var book = this,
unarchived;
//-- Must use storage //-- Must use storage
if(this.settings.storage == false ){ // if(this.settings.storage == false ){
this.settings.storage = true; // this.settings.storage = true;
this.storage = new fileStorage.storage(); // 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 //-- 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 //-- Checks if the book setting can be retrieved from localStorage
EPUBJS.Book.prototype.isSaved = function() { EPUBJS.Book.prototype.isSaved = function(bookPath) {
var bookKey = this.bookUrl + ":" + this.settings.version, var bookKey = bookPath + ":" + this.settings.version,
storedSettings = localStorage.getItem(bookKey); storedSettings = localStorage.getItem(bookKey);
if( !localStorage || if( !localStorage ||
@ -316,7 +319,7 @@ EPUBJS.Book.prototype.isSaved = function() {
//-- Remove save book settings //-- Remove save book settings
EPUBJS.Book.prototype.removeSavedSettings = function() { EPUBJS.Book.prototype.removeSavedSettings = function() {
var bookKey = this.bookUrl + ":" + this.settings.version; var bookKey = this.settings.bookPath + ":" + this.settings.version;
localStorage.removeItem(bookKey); localStorage.removeItem(bookKey);
@ -324,16 +327,15 @@ EPUBJS.Book.prototype.removeSavedSettings = function() {
} }
EPUBJS.Book.prototype.applySavedSettings = 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)); stored = JSON.parse(localStorage.getItem(bookKey));
if(EPUBJS.VERSION != stored.EPUBJSVERSION) return false; if(EPUBJS.VERSION != stored.EPUBJSVERSION) return false;
this.settings = _.defaults(this.settings, stored); this.settings = _.defaults(this.settings, stored);
} }
EPUBJS.Book.prototype.saveSettings = function(){ EPUBJS.Book.prototype.saveSettings = function(){
var bookKey = this.bookUrl + ":" + this.settings.version; var bookKey = this.settings.bookPath + ":" + this.settings.version;
if(this.render) { if(this.render) {
this.settings.previousLocationCfi = this.render.currentLocationCfi; this.settings.previousLocationCfi = this.render.currentLocationCfi;
@ -344,7 +346,7 @@ EPUBJS.Book.prototype.saveSettings = function(){
} }
EPUBJS.Book.prototype.saveContents = 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)); localStorage.setItem(contentsKey, JSON.stringify(this.contents));
@ -371,7 +373,7 @@ EPUBJS.Book.prototype.renderTo = function(el){
EPUBJS.Book.prototype.startDisplay = function(){ EPUBJS.Book.prototype.startDisplay = function(){
var display; var display;
if( this.settings.previousLocationCfi) { if( this.settings.restore && this.settings.previousLocationCfi) {
display = this.displayChapter(this.settings.previousLocationCfi); display = this.displayChapter(this.settings.previousLocationCfi);
@ -385,13 +387,13 @@ EPUBJS.Book.prototype.startDisplay = function(){
EPUBJS.Book.prototype.restore = function(){ EPUBJS.Book.prototype.restore = function(){
var book = this, var book = this,
contentsKey = this.settings.contentsPath + ":" + this.settings.version, contentsKey = this.settings.bookPath + ":contents:" + this.settings.version,
promise = new RSVP.Promise(), promise = new RSVP.Promise(),
fetch = ['manifest', 'spine', 'metadata', 'cover', 'toc', 'spineNodeIndex', 'spineIndexByURL'], fetch = ['manifest', 'spine', 'metadata', 'cover', 'toc', 'spineNodeIndex', 'spineIndexByURL'],
reject = false, reject = false,
fromStore = localStorage.getItem(contentsKey); fromStore = localStorage.getItem(contentsKey);
if(this.settings.contentsPath && fromStore){ if(fromStore != 'undefined'){
this.contents = JSON.parse(fromStore); this.contents = JSON.parse(fromStore);
fetch.forEach(function(item){ fetch.forEach(function(item){
@ -402,12 +404,9 @@ EPUBJS.Book.prototype.restore = function(){
}); });
} }
if(reject || !fromStore || !this.contents || !this.settings.contentsPath){
if(reject || !fromStore || !this.contents ){ // this.removeSavedSettings();
return this.open(this.settings.bookPath, true);
this.removeSavedSettings();
return this.unpack();
}else{ }else{
this.ready.manifest.resolve(this.manifest); this.ready.manifest.resolve(this.manifest);
@ -415,7 +414,6 @@ EPUBJS.Book.prototype.restore = function(){
this.ready.metadata.resolve(this.metadata); this.ready.metadata.resolve(this.metadata);
this.ready.cover.resolve(this.cover); this.ready.cover.resolve(this.cover);
this.ready.toc.resolve(this.toc); this.ready.toc.resolve(this.toc);
promise.resolve(); promise.resolve();
return promise; 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(){ render.then(function(){
book.preloadNextChapter(); book.preloadNextChapter();
}); });
@ -600,7 +599,7 @@ EPUBJS.Book.prototype.setStyle = function(style, val, prefixed) {
EPUBJS.Book.prototype.removeStyle = function(style, val, prefixed) { EPUBJS.Book.prototype.removeStyle = function(style, val, prefixed) {
this.renderer.removeStyle(style); 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 //-- Hooks allow for injecting async functions that must all complete before continuing
// Functions must have a callback as their first argument. // Functions must have a callback as their first argument.
EPUBJS.Book.prototype.registerHook = function(type, toAdd){ EPUBJS.Book.prototype.registerHook = function(type, toAdd, toFront){
var that = this; var book = this;
if(typeof(this.hooks[type]) != "undefined"){ if(typeof(this.hooks[type]) != "undefined"){
if(typeof(toAdd) === "function"){ if(typeof(toAdd) === "function"){
if(toFront) {
this.hooks[type].unshift(toAdd);
}else{
this.hooks[type].push(toAdd); this.hooks[type].push(toAdd);
}
}else if(Array.isArray(toAdd)){ }else if(Array.isArray(toAdd)){
toAdd.forEach(function(hook){ toAdd.forEach(function(hook){
that.hooks[type].push(hook); if(toFront) {
book.hooks[type].unshift(hook);
}else{
book.hooks[type].push(hook);
}
}); });
} }
}else{ }else{
//-- Allows for undefined hooks, but maybe this should error? //-- Allows for undefined hooks, but maybe this should error?
this.hooks[type] = [func]; this.hooks[type] = [func];
@ -687,7 +693,10 @@ EPUBJS.Chapter.prototype.url = function(store){
var promise = new RSVP.Promise(); var promise = new RSVP.Promise();
if(store){ if(store){
return store.getUrl(href); if(!this.tempUrl) {
this.tempUrl = store.getUrl(this.href);
}
return this.tempUrl;
}else{ }else{
promise.resolve(this.href); //-- this is less than ideal but keeps it a promise promise.resolve(this.href); //-- this is less than ideal but keeps it a promise
return promise; return promise;
@ -706,6 +715,14 @@ EPUBJS.Chapter.prototype.getPages = function(num){
EPUBJS.Chapter.prototype.getID = function(){ EPUBJS.Chapter.prototype.getID = function(){
return this.ID; return this.ID;
} }
EPUBJS.Chapter.prototype.unload = function(store){
if(this.tempUrl && store) {
store.revokeUrl(this.tempUrl);
this.tempUrl = false;
}
}
var EPUBJS = EPUBJS || {}; var EPUBJS = EPUBJS || {};
EPUBJS.core = {} EPUBJS.core = {}
@ -744,7 +761,7 @@ EPUBJS.core.request = function(url, type) {
function handler() { function handler() {
if (this.readyState === this.DONE) { if (this.readyState === this.DONE) {
if (this.status === 200) { if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls
var r; var r;
if(type == 'xml'){ 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){ EPUBJS.EpubCFI = function(cfiStr){
if(cfiStr) return this.parse(cfiStr); if(cfiStr) return this.parse(cfiStr);
} }
@ -1018,7 +1057,7 @@ EPUBJS.EpubCFI.prototype.generateFragment = function(element, chapter) {
parts.push((part.index + 1) * 2); parts.push((part.index + 1) * 2);
if(part.id && 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 + "]"); parts.push("[" + part.id + "]");
} }
@ -1139,6 +1178,7 @@ EPUBJS.EpubCFI.prototype.getElement = function(cfi, doc) {
part = sections.shift(); part = sections.shift();
if(part.id){ if(part.id){
console.log(part.id)
element = cfi.doc.querySelector("#" + part.id); element = cfi.doc.querySelector("#" + part.id);
}else{ }else{
@ -1293,13 +1333,13 @@ EPUBJS.Parser.prototype.package = function(packageXml, baseUrl){
//-- Find TOC NCX: media-type="application/x-dtbncx+xml" href="toc.ncx" //-- Find TOC NCX: media-type="application/x-dtbncx+xml" href="toc.ncx"
EPUBJS.Parser.prototype.findTocPath = function(manifestNode){ EPUBJS.Parser.prototype.findTocPath = function(manifestNode){
var node = manifestNode.querySelector("item[media-type='application/x-dtbncx+xml']"); 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" /> //-- Find Cover: <item properties="cover-image" id="ci" href="cover.svg" media-type="image/svg+xml" />
EPUBJS.Parser.prototype.findCoverPath = function(manifestNode){ EPUBJS.Parser.prototype.findCoverPath = function(manifestNode){
var node = manifestNode.querySelector("item[properties='cover-image']"); 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", 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.crossBrowserColumnCss();
@ -1490,9 +1532,13 @@ EPUBJS.Renderer.prototype.listeners = function(){
EPUBJS.Renderer.prototype.chapter = function(chapter){ EPUBJS.Renderer.prototype.chapter = function(chapter){
var renderer = this, 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) { if(this.currentChapter) {
this.currentChapter.unload();
this.trigger("book:chapterDestroyed"); this.trigger("book:chapterDestroyed");
} }
@ -1629,6 +1675,8 @@ EPUBJS.Renderer.prototype.setIframeSrc = function(url){
renderer.calcPages(); renderer.calcPages();
promise.resolve(renderer);
renderer.currentLocationCfi = renderer.getPageCfi(); renderer.currentLocationCfi = renderer.getPageCfi();
renderer.trigger("book:chapterDisplayed"); renderer.trigger("book:chapterDisplayed");
@ -1637,7 +1685,7 @@ EPUBJS.Renderer.prototype.setIframeSrc = function(url){
}); });
promise.resolve(renderer);
// that.afterLoaded(that); // that.afterLoaded(that);
@ -1686,6 +1734,7 @@ EPUBJS.Renderer.prototype.formatSpread = function(){
this.spreadWidth = (this.colWidth + this.gap) * divisor; this.spreadWidth = (this.colWidth + this.gap) * divisor;
if(this.bodyEl) this.bodyEl.style.margin = 0;
// this.bodyEl.style.fontSize = localStorage.getItem("fontSize") || "medium"; // this.bodyEl.style.fontSize = localStorage.getItem("fontSize") || "medium";
//-- Clear Margins //-- Clear Margins
@ -1812,6 +1861,8 @@ EPUBJS.Renderer.prototype.prevPage = function(){
EPUBJS.Renderer.prototype.chapterEnd = function(){ EPUBJS.Renderer.prototype.chapterEnd = function(){
this.page(this.displayedPages); this.page(this.displayedPages);
this.currentLocationCfi = this.getPageCfi();
} }
EPUBJS.Renderer.prototype.setLeft = function(leftPos){ EPUBJS.Renderer.prototype.setLeft = function(leftPos){
@ -1819,9 +1870,186 @@ EPUBJS.Renderer.prototype.setLeft = function(leftPos){
this.doc.defaultView.scrollTo(leftPos, 0) 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 //-- Replaces the relative links within the book to use our internal page changer
EPUBJS.Renderer.prototype.replaceLinks = function(callback){ EPUBJS.Renderer.prototype.replaceLinks = function(callback){
var hrefs = this.doc.querySelectorAll('[href]'), var hrefs = this.doc.querySelectorAll('a'),
links = Array.prototype.slice.call(hrefs), links = Array.prototype.slice.call(hrefs),
that = this; 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 //-- Replaces assets src's to point to stored version if browser is offline
EPUBJS.Renderer.prototype.replaceResources = function(callback){ EPUBJS.Renderer.prototype.replaceResources = function(callback){
var srcs, resources, count; var srcs, resources, count;
var store = this.determineStore();
//-- No need to replace if there is network connectivity if(!store) {
//-- also Filesystem api links are relative, so no need to replace them
if((this.book.online && !this.book.contained) || EPUBJS.storage.getStorageType() == "filesystem") {
if(callback) callback(); if(callback) callback();
return false; return false;
} }
@ -1865,16 +2092,22 @@ EPUBJS.Renderer.prototype.replaceResources = function(callback){
resources.forEach(function(link){ resources.forEach(function(link){
var src = link.getAttribute("src"), var src = link.getAttribute("src"),
full = this.book.basePath + src; full = this.book.settings.contentsPath + src;
EPUBJS.storage.get(full, function(url){ store.getUrl(full).then(function(url){
link.setAttribute("src", url); // link.setAttribute("src", url);
link.src = url;
link.onload = function(){
count--; count--;
if(count <= 0 && callback) callback(); if(count <= 0 && callback) callback();
}
}); });
}.bind(this)); }.bind(this));
if(count === 0) callback();
} }
EPUBJS.Renderer.prototype.page = function(pg){ EPUBJS.Renderer.prototype.page = function(pg){
@ -1886,7 +2119,7 @@ EPUBJS.Renderer.prototype.page = function(pg){
// localStorage.setItem("chapterPos", pg); // localStorage.setItem("chapterPos", pg);
return true; return true;
} }
console.log("false", pg, this.displayedPages)
//-- Return false if page is greater than the total //-- Return false if page is greater than the total
return false; return false;
} }
@ -1974,7 +2207,7 @@ EPUBJS.Renderer.prototype.getPageCfi = function(){
this.visibileEl = this.findFirstVisible(prevEl); this.visibileEl = this.findFirstVisible(prevEl);
if(!this.visibileEl.id) { 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; 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 //-- Enable binding events to parser
RSVP.EventTarget.mixin(EPUBJS.Renderer.prototype); RSVP.EventTarget.mixin(EPUBJS.Renderer.prototype);
EPUBJS.Unarchiver = function(url, callback){ EPUBJS.Unarchiver = function(url){
this.libPath = EPUBJS.filePath + "libs/";
this.libPath = EPUBJS.filePath + "zip/";
this.zipUrl = url; this.zipUrl = url;
this.callback = callback; this.loadLib()
this.loadLib(function(){ this.urlCache = {};
this.getZip(this.zipUrl);
}.bind(this)); this.zipFs = new zip.fs.FS();
return this.promise;
} }
EPUBJS.Unarchiver.prototype.loadLib = function(callback){ EPUBJS.Unarchiver.prototype.loadLib = function(callback){
if(typeof(zip) != "undefined") callback(); if(typeof(zip) == "undefined") console.error("Zip lib not loaded");
/*
//-- load script //-- load script
EPUBJS.core.loadScript(this.libPath+"zip.js", function(){ EPUBJS.core.loadScript(this.libPath+"zip.js", function(){
//-- Tell zip where it is located //-- Tell zip where it is located
zip.workerScriptsPath = this.libPath; zip.workerScriptsPath = this.libPath;
callback(); callback();
}.bind(this)); }.bind(this));
*/
// console.log(this.libPath)
zip.workerScriptsPath = this.libPath;
} }
EPUBJS.Unarchiver.prototype.getZip = function(zipUrl){ EPUBJS.Unarchiver.prototype.openZip = function(zipUrl, callback){
var xhr = new EPUBJS.core.loadFile(zipUrl); var promise = new RSVP.Promise();
var zipFs = this.zipFs;
xhr.succeeded = function(file) { zipFs.importHttpContent(zipUrl, false, function() {
this.getEntries(file, this.toStorage.bind(this)); promise.resolve(zipFs);
}.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);
}, this.failed); }, 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){ EPUBJS.Unarchiver.prototype.failed = function(error){
console.log("Error:", error); console.error(error);
} }
EPUBJS.Unarchiver.prototype.afterSaved = function(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){ 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){ EPUBJS.Hooks.register("beforeChapterDisplay").smartimages = function(callback, chapter){
var images = chapter.doc.querySelectorAll('img'),
var image = chapter.doc.querySelectorAll('img'), items = Array.prototype.slice.call(images),
items = Array.prototype.slice.call(image), iheight = chapter.height(),//chapter.doc.body.getBoundingClientRect().height,
iheight = chapter.doc.body.getBoundingClientRect().height,
oheight; oheight;
items.forEach(function(item){ items.forEach(function(item){
function size() { function size() {
var itemRect = item.getBoundingClientRect(), var itemRect = item.getBoundingClientRect(),
height = itemRect.height, rectHeight = itemRect.height,
top = itemRect.top; top = itemRect.top,
oHeight = item.getAttribute('data-height'),
iheight = chapter.iframe.height; height = oHeight || rectHeight,
newHeight;
iheight = chapter.height();
if(top < 0) top = 0;
if(height + top >= iheight) { if(height + top >= iheight) {
if(top < iheight/2) { if(top < iheight/2) {
item.style.maxHeight = iheight - top + "px"; newHeight = iheight - top;
item.style.maxHeight = newHeight + "px";
item.style.width= "auto"; item.style.width= "auto";
}else{ }else{
height = (height < iheight ? height : iheight);
item.style.maxHeight = (height < iheight ? height : iheight) + "px"; item.style.maxHeight = newHeight + "px";
item.style.marginTop = iheight - top + "px"; item.style.marginTop = iheight - top + "px";
item.style.width= "auto"; item.style.width= "auto";
} }
item.setAttribute('data-height', newHeight);
}else{ }else{
item.style.removeProperty('max-height'); item.style.removeProperty('max-height');
item.style.removeProperty('margin-top'); item.style.removeProperty('margin-top');
} }
} }
item.addEventListener('load', size, false);
chapter.on("book:resized", size); chapter.on("book:resized", size);
chapter.on("book:chapterDestroyed", function(){ chapter.on("book:chapterDestroyed", function(){
item.removeEventListener('load', size);
chapter.off("book:resized", 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 || {}; var EPUBJSR = EPUBJSR || {};

View file

@ -24,7 +24,7 @@
EPUBJS.filePath = "js/"; EPUBJS.filePath = "js/";
fileStorage.filePath = EPUBJS.filePath + "libs/"; 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 () { document.onreadystatechange = function () {
if (document.readyState == "complete") { if (document.readyState == "complete") {
EPUBJS.filePath = "../src/"; EPUBJS.filePath = "../libs/";
fileStorage.filePath = "../libs/fileStorage/workers/"; fileStorage.filePath = "../libs/fileStorage/workers/";
EPUBJS.VERSION = "0.1.5"; 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>--> <!--<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 --> <!-- Render -->
<script src="../libs/underscore/underscore.js"></script> <script src="../libs/underscore/underscore.js"></script>
<script src="../libs/rsvp/rsvp.js"></script> <script src="../libs/rsvp/rsvp.js"></script>
@ -56,6 +64,8 @@
<script async src="../reader/utils.js"></script> <script async src="../reader/utils.js"></script>
<script async src="../reader/app.js"></script> <script async src="../reader/app.js"></script>
</head> </head>
<body> <body>
<div id="sidebar"> <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/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/reader.min.js': 'build/reader.js',
'demo/js/hooks.min.js': 'build/hooks.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){ EPUBJS.Hooks.register("beforeChapterDisplay").smartimages = function(callback, chapter){
var images = chapter.doc.querySelectorAll('img'),
var image = chapter.doc.querySelectorAll('img'), items = Array.prototype.slice.call(images),
items = Array.prototype.slice.call(image), iheight = chapter.height(),//chapter.doc.body.getBoundingClientRect().height,
iheight = chapter.doc.body.getBoundingClientRect().height,
oheight; oheight;
items.forEach(function(item){ items.forEach(function(item){
function size() { function size() {
var itemRect = item.getBoundingClientRect(), var itemRect = item.getBoundingClientRect(),
height = itemRect.height, rectHeight = itemRect.height,
top = itemRect.top; top = itemRect.top,
oHeight = item.getAttribute('data-height'),
iheight = chapter.iframe.height; height = oHeight || rectHeight,
newHeight;
iheight = chapter.height();
if(top < 0) top = 0;
if(height + top >= iheight) { if(height + top >= iheight) {
if(top < iheight/2) { if(top < iheight/2) {
item.style.maxHeight = iheight - top + "px"; newHeight = iheight - top;
item.style.maxHeight = newHeight + "px";
item.style.width= "auto"; item.style.width= "auto";
}else{ }else{
height = (height < iheight ? height : iheight);
item.style.maxHeight = (height < iheight ? height : iheight) + "px"; item.style.maxHeight = newHeight + "px";
item.style.marginTop = iheight - top + "px"; item.style.marginTop = iheight - top + "px";
item.style.width= "auto"; item.style.width= "auto";
} }
item.setAttribute('data-height', newHeight);
}else{ }else{
item.style.removeProperty('max-height'); item.style.removeProperty('max-height');
item.style.removeProperty('margin-top'); item.style.removeProperty('margin-top');
} }
} }
item.addEventListener('load', size, false);
chapter.on("book:resized", size); chapter.on("book:resized", size);
chapter.on("book:chapterDestroyed", function(){ chapter.on("book:chapterDestroyed", function(){
item.removeEventListener('load', size);
chapter.off("book:resized", 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 Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
@ -89,8 +89,6 @@
// Tree // Tree
// see definition of array dist_code below // 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, 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, 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, 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 STATIC_TREES = 1;
var DYN_TREES = 2; 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 MIN_MATCH = 3;
var MAX_MATCH = 258; var MAX_MATCH = 258;
var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1); var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
@ -488,7 +481,6 @@
var pending_buf_size; // size of pending_buf var pending_buf_size; // size of pending_buf
// pending_out; // next pending byte to output to the stream // pending_out; // next pending byte to output to the stream
// pending; // nb of bytes in the pending buffer // pending; // nb of bytes in the pending buffer
// data_type; // UNKNOWN, BINARY or ASCII
var method; // STORED (for zip only) or DEFLATED var method; // STORED (for zip only) or DEFLATED
var last_flush; // value of flush param for previous deflate call var last_flush; // value of flush param for previous deflate call
@ -1035,29 +1027,6 @@
last_eob_len = ltree[END_BLOCK * 2 + 1]; 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 // Flush the bit buffer and align the output on a byte boundary
function bi_windup() { function bi_windup() {
if (bi_valid > 8) { if (bi_valid > 8) {
@ -1075,7 +1044,6 @@
len, // its length len, // its length
header // true if block header must be written header // true if block header must be written
) { ) {
var index = 0;
bi_windup(); // align on byte boundary bi_windup(); // align on byte boundary
last_eob_len = 8; // enough lookahead for inflate last_eob_len = 8; // enough lookahead for inflate
@ -1108,10 +1076,6 @@
// Build the Huffman trees unless a stored block is forced // Build the Huffman trees unless a stored block is forced
if (level > 0) { 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 // Construct the literal and distance trees
l_desc.build_tree(that); l_desc.build_tree(that);
@ -1643,7 +1607,6 @@
function deflateReset(strm) { function deflateReset(strm) {
strm.total_in = strm.total_out = 0; strm.total_in = strm.total_out = 0;
strm.msg = null; // strm.msg = null; //
strm.data_type = Z_UNKNOWN;
that.pending = 0; that.pending = 0;
that.pending_out = 0; that.pending_out = 0;
@ -1928,8 +1891,6 @@
that.total_out = 0; // total nb of bytes output so far that.total_out = 0; // total nb of bytes output so far
// that.msg; // that.msg;
// that.dstate; // that.dstate;
// that.data_type; // best guess about the data type: ascii or binary
} }
ZStream.prototype = { ZStream.prototype = {
@ -2071,7 +2032,7 @@
return array; return array;
}; };
that.flush = function() { that.flush = function() {
var err, ab, buffers = [], bufferIndex = 0, bufferSize = 0, array; var err, buffers = [], bufferIndex = 0, bufferSize = 0, array;
do { do {
z.next_out_index = 0; z.next_out_index = 0;
z.avail_out = bufsize; 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 Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
@ -51,9 +51,6 @@
var MANY = 1440; var MANY = 1440;
var MAX_WBITS = 15; // 32K LZ77 window
var DEF_WBITS = MAX_WBITS;
// JZlib version : "1.0.2" // JZlib version : "1.0.2"
var Z_NO_FLUSH = 0; var Z_NO_FLUSH = 0;
var Z_FINISH = 4; var Z_FINISH = 4;
@ -432,8 +429,7 @@
InfTree.inflate_trees_fixed = function(bl, // literal desired/actual bit depth InfTree.inflate_trees_fixed = function(bl, // literal desired/actual bit depth
bd, // distance desired/actual bit depth bd, // distance desired/actual bit depth
tl,// literal/length tree result tl,// literal/length tree result
td,// distance tree result td// distance tree result
z // for memory allocation
) { ) {
bl[0] = fixed_bl; bl[0] = fixed_bl;
bd[0] = fixed_bd; bd[0] = fixed_bd;
@ -735,7 +731,7 @@
return Z_OK; 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; mode = START;
lbits = /* (byte) */bl; lbits = /* (byte) */bl;
dbits = /* (byte) */bd; dbits = /* (byte) */bd;
@ -748,7 +744,6 @@
that.proc = function(s, z, r) { that.proc = function(s, z, r) {
var j; // temporary storage var j; // temporary storage
var t; // temporary pointer
var tindex; // temporary pointer var tindex; // temporary pointer
var e; // extra bits or operation var e; // extra bits or operation
var b = 0; // bit buffer var b = 0; // bit buffer
@ -1102,7 +1097,7 @@
} }
}; };
that.free = function(z) { that.free = function() {
// ZFREE(z, c); // ZFREE(z, c);
}; };
@ -1298,8 +1293,8 @@
var tl = [ [] ]; // new Array(1); var tl = [ [] ]; // new Array(1);
var td = [ [] ]; // new Array(1); var td = [ [] ]; // new Array(1);
InfTree.inflate_trees_fixed(bl, bd, tl, td, z); InfTree.inflate_trees_fixed(bl, bd, tl, td);
codes.init(bl[0], bd[0], tl[0], 0, td[0], 0, z); codes.init(bl[0], bd[0], tl[0], 0, td[0], 0);
// } // }
// { // {
@ -1533,7 +1528,6 @@
break; break;
} }
var h;
var j, c; var j, c;
t = bb[0]; t = bb[0];
@ -1647,7 +1641,7 @@
that.write = q; that.write = q;
return that.inflate_flush(z, r); 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; mode = CODES;
case CODES: case CODES:
@ -2113,7 +2107,7 @@
return -1; return -1;
if (err != Z_OK && err != Z_STREAM_END) if (err != Z_OK && err != Z_STREAM_END)
throw "inflating: " + z.msg; 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; return -1;
if (z.next_out_index) if (z.next_out_index)
if (z.next_out_index == bufsize) 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() { (function() {
var table = { var table = {
"application" : { "application" : {
@ -807,7 +835,7 @@
"x-pict" : [ "pic", "pct" ], "x-pict" : [ "pic", "pct" ],
"x-tga" : "tga", "x-tga" : "tga",
"cis-cod" : "cod", "cis-cod" : "cod",
"pipeg" : "jfif" "pipeg" : "jfif",
}, },
"message" : { "message" : {
"rfc822" : [ "eml", "mime", "mht", "mhtml", "nws" ] "rfc822" : [ "eml", "mime", "mht", "mhtml", "nws" ]
@ -966,7 +994,8 @@
})(); })();
zip.getMimeType = function(filename) { 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 Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
@ -30,23 +30,20 @@
var CHUNK_SIZE = 512 * 1024; var CHUNK_SIZE = 512 * 1024;
var FileWriter = zip.FileWriter, // var TextWriter = zip.TextWriter, //
TextWriter = zip.TextWriter, //
BlobWriter = zip.BlobWriter, // BlobWriter = zip.BlobWriter, //
Data64URIWriter = zip.Data64URIWriter, // Data64URIWriter = zip.Data64URIWriter, //
Reader = zip.Reader, // Reader = zip.Reader, //
TextReader = zip.TextReader, // TextReader = zip.TextReader, //
BlobReader = zip.BlobReader, // BlobReader = zip.BlobReader, //
Data64URIReader = zip.Data64URIReader, // Data64URIReader = zip.Data64URIReader, //
HttpRangeReader = zip.HttpRangeReader, //
HttpReader = zip.HttpReader, //
createReader = zip.createReader, // createReader = zip.createReader, //
createWriter = zip.createWriter; createWriter = zip.createWriter;
function ZipBlobReader(entry) { function ZipBlobReader(entry) {
var that = this, blobReader; var that = this, blobReader;
function init(callback, onerror) { function init(callback) {
this.size = entry.uncompressedSize; this.size = entry.uncompressedSize;
callback(); callback();
} }
@ -92,7 +89,6 @@
var index = 0; var index = 0;
function next() { function next() {
var child = entry.children[index];
index++; index++;
if (index < entry.children.length) if (index < entry.children.length)
process(entry.children[index]); process(entry.children[index]);
@ -209,10 +205,10 @@
}, onerror); }, onerror);
} }
function getFileEntry(fileEntry, entry, onend, onprogress, totalSize, checkCrc32) { function getFileEntry(fileEntry, entry, onend, onprogress, onerror, totalSize, checkCrc32) {
var currentIndex = 0, rootEntry; var currentIndex = 0;
function process(fileEntry, entry, onend, onprogress, totalSize) { function process(fileEntry, entry, onend, onprogress, onerror, totalSize) {
var childIndex = 0; var childIndex = 0;
function addChild(child) { function addChild(child) {
@ -221,7 +217,7 @@
process(childFileEntry, child, function() { process(childFileEntry, child, function() {
childIndex++; childIndex++;
processChild(); processChild();
}, onprogress, totalSize); }, onprogress, onerror, totalSize);
} }
if (child.directory) if (child.directory)
@ -232,7 +228,7 @@
fileEntry.getFile(child.name, { fileEntry.getFile(child.name, {
create : true create : true
}, function(file) { }, 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) if (onprogress)
onprogress(currentIndex + index, totalSize); onprogress(currentIndex + index, totalSize);
}, checkCrc32); }, checkCrc32);
@ -251,9 +247,9 @@
} }
if (entry.directory) if (entry.directory)
process(fileEntry, entry, onend, onprogress, totalSize); process(fileEntry, entry, onend, onprogress, onerror, totalSize);
else 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) { function resetFS(fs) {
@ -328,7 +324,7 @@
getFileEntry : function(fileEntry, onend, onprogress, onerror, checkCrc32) { getFileEntry : function(fileEntry, onend, onprogress, onerror, checkCrc32) {
var that = this; var that = this;
initReaders(that, function() { initReaders(that, function() {
getFileEntry(fileEntry, that, onend, onprogress, getTotalSize(that), checkCrc32); getFileEntry(fileEntry, that, onend, onprogress, onerror, getTotalSize(that), checkCrc32);
}, onerror); }, onerror);
}, },
moveTo : function(target) { moveTo : function(target) {
@ -377,8 +373,8 @@
ZipFileEntry.prototype = ZipFileEntryProto = new ZipEntry(); ZipFileEntry.prototype = ZipFileEntryProto = new ZipEntry();
ZipFileEntryProto.constructor = ZipFileEntry; ZipFileEntryProto.constructor = ZipFileEntry;
ZipFileEntryProto.getText = function(onend, onprogress, checkCrc32) { ZipFileEntryProto.getText = function(onend, onprogress, checkCrc32, encoding) {
this.getData(new TextWriter(), onend, onprogress, checkCrc32); this.getData(new TextWriter(encoding), onend, onprogress, checkCrc32);
}; };
ZipFileEntryProto.getBlob = function(mimeType, onend, onprogress, checkCrc32) { ZipFileEntryProto.getBlob = function(mimeType, onend, onprogress, checkCrc32) {
this.getData(new BlobWriter(mimeType), onend, onprogress, checkCrc32); this.getData(new BlobWriter(mimeType), onend, onprogress, checkCrc32);
@ -421,12 +417,6 @@
Writer : Data64URIWriter Writer : Data64URIWriter
}); });
}; };
ZipDirectoryEntryProto.addHttpContent = function(name, URL, useRangeHeader) {
return addChild(this, name, {
data : URL,
Reader : useRangeHeader ? HttpRangeReader : HttpReader
});
};
ZipDirectoryEntryProto.addFileEntry = function(fileEntry, onend, onerror) { ZipDirectoryEntryProto.addFileEntry = function(fileEntry, onend, onerror) {
addFileEntry(this, fileEntry, onend, onerror); addFileEntry(this, fileEntry, onend, onerror);
}; };
@ -442,9 +432,6 @@
ZipDirectoryEntryProto.importData64URI = function(dataURI, onend, onerror) { ZipDirectoryEntryProto.importData64URI = function(dataURI, onend, onerror) {
this.importZip(new Data64URIReader(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) { ZipDirectoryEntryProto.exportBlob = function(onend, onprogress, onerror) {
this.exportZip(new BlobWriter("application/zip"), onend, onprogress, onerror); this.exportZip(new BlobWriter("application/zip"), onend, onprogress, onerror);
}; };
@ -452,7 +439,7 @@
this.exportZip(new TextWriter(), onend, onprogress, onerror); this.exportZip(new TextWriter(), onend, onprogress, onerror);
}; };
ZipDirectoryEntryProto.exportFileEntry = function(fileEntry, 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) { ZipDirectoryEntryProto.exportData64URI = function(onend, onprogress, onerror) {
this.exportZip(new Data64URIWriter("application/zip"), onend, onprogress, onerror); this.exportZip(new Data64URIWriter("application/zip"), onend, onprogress, onerror);
@ -524,10 +511,6 @@
resetFS(this); resetFS(this);
this.root.importData64URI(dataURI, onend, onerror); 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) { exportBlob : function(onend, onprogress, onerror) {
this.root.exportBlob(onend, onprogress, onerror); this.root.exportBlob(onend, onprogress, onerror);
}, },
@ -543,7 +526,9 @@
}; };
zip.fs = { zip.fs = {
FS : FS FS : FS,
ZipDirectoryEntry : ZipDirectoryEntry,
ZipFileEntry : ZipFileEntry
}; };
zip.getMimeType = function() { 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 Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: 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_WRITE_DATA = "Error while writing file data.";
var ERR_READ_DATA = "Error while reading file data."; var ERR_READ_DATA = "Error while reading file data.";
var ERR_DUPLICATED_NAME = "File already exists."; var ERR_DUPLICATED_NAME = "File already exists.";
var ERR_HTTP_RANGE = "HTTP Range not supported.";
var CHUNK_SIZE = 512 * 1024; var CHUNK_SIZE = 512 * 1024;
var INFLATE_JS = "inflate.js"; var INFLATE_JS = "inflate.js";
var DEFLATE_JS = "deflate.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; var appendABViewSupported;
try {
function isAppendABViewSupported() { appendABViewSupported = new Blob([ new DataView(new ArrayBuffer(0)) ]).size === 0;
if (typeof appendABViewSupported == "undefined") { } catch (e) {
var blobBuilder;
blobBuilder = new BlobBuilder();
blobBuilder.append(getDataHelper(0).view);
appendABViewSupported = blobBuilder.getBlob().size == 0;
}
return appendABViewSupported;
} }
function Crc32() { function Crc32() {
@ -113,9 +108,10 @@
var that = this, blobReader; var that = this, blobReader;
function init(callback, onerror) { function init(callback, onerror) {
var blobBuilder = new BlobBuilder(); var blob = new Blob([ text ], {
blobBuilder.append(text); type : TEXT_PLAIN
blobReader = new BlobReader(blobBuilder.getBlob("text/plain")); });
blobReader = new BlobReader(blob);
blobReader.init(function() { blobReader.init(function() {
that.size = blobReader.size; that.size = blobReader.size;
callback(); callback();
@ -136,7 +132,7 @@
function Data64URIReader(dataURI) { function Data64URIReader(dataURI) {
var that = this, dataStart; var that = this, dataStart;
function init(callback, onerror) { function init(callback) {
var dataEnd = dataURI.length; var dataEnd = dataURI.length;
while (dataURI.charAt(dataEnd - 1) == "=") while (dataURI.charAt(dataEnd - 1) == "=")
dataEnd--; dataEnd--;
@ -145,7 +141,7 @@
callback(); callback();
} }
function readUint8Array(index, length, callback, onerror) { function readUint8Array(index, length, callback) {
var i, data = getDataHelper(length); var i, data = getDataHelper(length);
var start = Math.floor(index / 3) * 4; var start = Math.floor(index / 3) * 4;
var end = Math.ceil((index + length) / 3) * 4; var end = Math.ceil((index + length) / 3) * 4;
@ -166,7 +162,7 @@
function BlobReader(blob) { function BlobReader(blob) {
var that = this; var that = this;
function init(callback, onerror) { function init(callback) {
this.size = blob.size; this.size = blob.size;
callback(); callback();
} }
@ -187,93 +183,6 @@
BlobReader.prototype = new Reader(); BlobReader.prototype = new Reader();
BlobReader.prototype.constructor = BlobReader; 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 // Writers
function Writer() { function Writer() {
@ -282,26 +191,30 @@
callback(this.data); callback(this.data);
}; };
function TextWriter() { function TextWriter(encoding) {
var that = this, blobBuilder; var that = this, blob;
function init(callback, onerror) { function init(callback) {
blobBuilder = new BlobBuilder(); blob = new Blob([], {
type : TEXT_PLAIN
});
callback(); callback();
} }
function writeUint8Array(array, callback, onerror) { function writeUint8Array(array, callback) {
blobBuilder.append(isAppendABViewSupported() ? array : array.buffer); blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
type : TEXT_PLAIN
});
callback(); callback();
} }
function getData(callback) { function getData(callback, onerror) {
var reader = new FileReader(); var reader = new FileReader();
reader.onload = function(e) { reader.onload = function(e) {
callback(e.target.result); callback(e.target.result);
}; };
reader.onerror = onerror; reader.onerror = onerror;
reader.readAsText(blobBuilder.getBlob("text/plain")); reader.readAsText(blob, encoding);
} }
that.init = init; that.init = init;
@ -314,12 +227,12 @@
function Data64URIWriter(contentType) { function Data64URIWriter(contentType) {
var that = this, data = "", pending = ""; var that = this, data = "", pending = "";
function init(callback, onerror) { function init(callback) {
data += "data:" + (contentType || "") + ";base64,"; data += "data:" + (contentType || "") + ";base64,";
callback(); callback();
} }
function writeUint8Array(array, callback, onerror) { function writeUint8Array(array, callback) {
var i, delta = pending.length, dataString = pending; var i, delta = pending.length, dataString = pending;
pending = ""; pending = "";
for (i = 0; i < (Math.floor((delta + array.length) / 3) * 3) - delta; i++) for (i = 0; i < (Math.floor((delta + array.length) / 3) * 3) - delta; i++)
@ -344,53 +257,25 @@
Data64URIWriter.prototype = new Writer(); Data64URIWriter.prototype = new Writer();
Data64URIWriter.prototype.constructor = Data64URIWriter; 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) { function BlobWriter(contentType) {
var blobBuilder, that = this; var blob, that = this;
function init(callback, onerror) { function init(callback) {
blobBuilder = new BlobBuilder(); blob = new Blob([], {
type : contentType
});
callback(); callback();
} }
function writeUint8Array(array, callback, onerror) { function writeUint8Array(array, callback) {
blobBuilder.append(isAppendABViewSupported() ? array : array.buffer); blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
type : contentType
});
callback(); callback();
} }
function getData(callback) { function getData(callback) {
callback(blobBuilder.getBlob(contentType)); callback(blob);
} }
that.init = init; that.init = init;
@ -406,13 +291,12 @@
var chunkIndex = 0, index, outputSize; var chunkIndex = 0, index, outputSize;
function onflush() { function onflush() {
worker.removeEventListener("message", onmessage, false); worker.removeEventListener(MESSAGE_EVENT, onmessage, false);
onend(outputSize); onend(outputSize);
} }
function onmessage(event) { function onmessage(event) {
var message = event.data, data = message.data; var message = event.data, data = message.data;
if (message.onappend) { if (message.onappend) {
outputSize += data.length; outputSize += data.length;
writer.writeUint8Array(data, function() { writer.writeUint8Array(data, function() {
@ -453,7 +337,7 @@
} }
outputSize = 0; outputSize = 0;
worker.addEventListener("message", onmessage, false); worker.addEventListener(MESSAGE_EVENT, onmessage, false);
step(); step();
} }
@ -528,13 +412,13 @@
} }
function onmessage() { 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); launchWorkerProcess(worker, reader, writer, 0, reader.size, ondeflateappend, onprogress, ondeflateend, onreaderror, onwriteerror);
} }
if (obj.zip.useWebWorkers) { if (obj.zip.useWebWorkers) {
worker = new Worker(obj.zip.workerScriptsPath + DEFLATE_JS); worker = new Worker(obj.zip.workerScriptsPath + DEFLATE_JS);
worker.addEventListener("message", onmessage, false); worker.addEventListener(MESSAGE_EVENT, onmessage, false);
worker.postMessage({ worker.postMessage({
init : true, init : true,
level : level level : level
@ -589,29 +473,8 @@
return out; return out;
} }
function decodeUTF8(str_data) { function decodeUTF8(string) {
var tmp_arr = [], i = 0, ac = 0, c1 = 0, c2 = 0, c3 = 0; return decodeURIComponent(escape(string));
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 getString(bytes) { 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.version = data.view.getUint16(index, true);
entry.bitFlag = data.view.getUint16(index + 2, true); entry.bitFlag = data.view.getUint16(index + 2, true);
entry.compressionMethod = data.view.getUint16(index + 4, true); entry.compressionMethod = data.view.getUint16(index + 4, true);
@ -697,7 +560,7 @@
onerror(ERR_BAD_FORMAT); onerror(ERR_BAD_FORMAT);
return; return;
} }
readCommonHeader(that, data, 4); readCommonHeader(that, data, 4, false, onerror);
dataOffset = that.offset + 30 + that.filenameLength + that.extraFieldLength; dataOffset = that.offset + 30 + that.filenameLength + that.extraFieldLength;
writer.init(function() { writer.init(function() {
if (that.compressionMethod === 0) if (that.compressionMethod === 0)
@ -708,18 +571,28 @@
}, onreaderror); }, 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 { return {
getEntries : function(callback) { getEntries : function(callback) {
if (reader.size < 22) { if (reader.size < 22) {
onerror(ERR_BAD_FORMAT); onerror(ERR_BAD_FORMAT);
return; return;
} }
reader.readUint8Array(reader.size - 22, 22, function(bytes) { // look for End of central directory record
var dataView = getDataHelper(bytes.length, bytes).view, datalength, fileslength; seekEOCDR(22, function(dataView) {
if (dataView.getUint32(0) != 0x504b0506) { var datalength, fileslength;
onerror(ERR_BAD_FORMAT);
return;
}
datalength = dataView.getUint32(16, true); datalength = dataView.getUint32(16, true);
fileslength = dataView.getUint16(8, true); fileslength = dataView.getUint16(8, true);
reader.readUint8Array(datalength, reader.size - datalength, function(bytes) { reader.readUint8Array(datalength, reader.size - datalength, function(bytes) {
@ -730,7 +603,7 @@
onerror(ERR_BAD_FORMAT); onerror(ERR_BAD_FORMAT);
return; return;
} }
readCommonHeader(entry, data, index + 6, true); readCommonHeader(entry, data, index + 6, true, onerror);
entry.commentLength = data.view.getUint16(index + 32, true); entry.commentLength = data.view.getUint16(index + 32, true);
entry.directory = ((data.view.getUint8(index + 38) & 0x10) == 0x10); entry.directory = ((data.view.getUint8(index + 38) & 0x10) == 0x10);
entry.offset = data.view.getUint32(index + 42, true); entry.offset = data.view.getUint32(index + 42, true);
@ -748,8 +621,6 @@
}, function() { }, function() {
onerror(ERR_READ); onerror(ERR_READ);
}); });
}, function() {
onerror(ERR_READ);
}); });
}, },
close : function(callback) { close : function(callback) {
@ -762,26 +633,7 @@
// ZipWriter // ZipWriter
function encodeUTF8(string) { function encodeUTF8(string) {
var n, c1, enc, utftext = [], start = 0, end = 0, stringl = string.length; return unescape(encodeURIComponent(string));
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;
} }
function getBytes(str) { function getBytes(str) {
@ -792,7 +644,7 @@
} }
function createZipWriter(writer, onerror, dontDeflate) { function createZipWriter(writer, onerror, dontDeflate) {
var worker, files = [], filenames = [], datalength = 0; var worker, files = {}, filenames = [], datalength = 0;
function terminate(callback, message) { function terminate(callback, message) {
if (worker) if (worker)
@ -828,7 +680,7 @@
header.view.setUint32(0, 0x14000808); header.view.setUint32(0, 0x14000808);
if (options.version) if (options.version)
header.view.setUint8(0, 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(4, 0x0800);
header.view.setUint16(6, (((date.getHours() << 6) | date.getMinutes()) << 5) | date.getSeconds() / 2, true); 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); 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 = getDataHelper(30 + filename.length);
data.view.setUint32(0, 0x504b0304); data.view.setUint32(0, 0x504b0304);
data.array.set(header.array, 4); 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); data.array.set(filename, 30);
datalength += data.array.length; datalength += data.array.length;
writer.writeUint8Array(data.array, callback, onwriteerror); writer.writeUint8Array(data.array, callback, onwriteerror);
@ -867,13 +718,15 @@
name = name.trim(); name = name.trim();
if (options.directory && name.charAt(name.length - 1) != "/") if (options.directory && name.charAt(name.length - 1) != "/")
name += "/"; name += "/";
if (files[name]) if (files.hasOwnProperty(name)) {
throw ERR_DUPLICATED_NAME; onerror(ERR_DUPLICATED_NAME);
return;
}
filename = getBytes(encodeUTF8(name)); filename = getBytes(encodeUTF8(name));
filenames.push(name); filenames.push(name);
writeHeader(function() { writeHeader(function() {
if (reader) if (reader)
if (dontDeflate || options.level == 0) if (dontDeflate || options.level === 0)
copy(reader, writer, 0, reader.size, true, writeFooter, onprogress, onreaderror, onwriteerror); copy(reader, writer, 0, reader.size, true, writeFooter, onprogress, onreaderror, onwriteerror);
else else
worker = deflate(reader, writer, options.level, writeFooter, onprogress, onreaderror, onwriteerror); worker = deflate(reader, writer, options.level, writeFooter, onprogress, onreaderror, onwriteerror);
@ -888,14 +741,14 @@
writeFile(); writeFile();
}, },
close : function(callback) { close : function(callback) {
var data, length = 0, index = 0; var data, length = 0, index = 0, indexFilename, file;
filenames.forEach(function(name) { for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {
var file = files[name]; file = files[filenames[indexFilename]];
length += 46 + file.filename.length + file.comment.length; length += 46 + file.filename.length + file.comment.length;
}); }
data = getDataHelper(length + 22); data = getDataHelper(length + 22);
filenames.forEach(function(name) { for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {
var file = files[name]; file = files[filenames[indexFilename]];
data.view.setUint32(index, 0x504b0102); data.view.setUint32(index, 0x504b0102);
data.view.setUint16(index + 4, 0x1400); data.view.setUint16(index + 4, 0x1400);
data.array.set(file.headerArray, index + 6); data.array.set(file.headerArray, index + 6);
@ -906,7 +759,7 @@
data.array.set(file.filename, index + 46); data.array.set(file.filename, index + 46);
data.array.set(file.comment, index + 46 + file.filename.length); data.array.set(file.comment, index + 46 + file.filename.length);
index += 46 + file.filename.length + file.comment.length; index += 46 + file.filename.length + file.comment.length;
}); }
data.view.setUint32(index, 0x504b0506); data.view.setUint32(index, 0x504b0506);
data.view.setUint16(index + 8, filenames.length, true); data.view.setUint16(index + 8, filenames.length, true);
data.view.setUint16(index + 10, 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 = { obj.zip = {
Reader : Reader, Reader : Reader,
Writer : Writer, Writer : Writer,
BlobReader : BlobReader, BlobReader : BlobReader,
HttpReader : HttpReader,
HttpRangeReader : HttpRangeReader,
Data64URIReader : Data64URIReader, Data64URIReader : Data64URIReader,
TextReader : TextReader, TextReader : TextReader,
BlobWriter : BlobWriter, BlobWriter : BlobWriter,
FileWriter : FileWriter,
Data64URIWriter : Data64URIWriter, Data64URIWriter : Data64URIWriter,
TextWriter : TextWriter, TextWriter : TextWriter,
createReader : function(reader, callback, onerror) { 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, spreads: true,
responsive: true, responsive: true,
version: 1, version: 1,
restore: false restore: true
}); });
this.settings.EPUBJSVERSION = EPUBJS.VERSION; this.settings.EPUBJSVERSION = EPUBJS.VERSION;
@ -65,7 +65,7 @@ EPUBJS.Book = function(bookPath, options){
} }
// Likewise if an element is present start rendering process // Likewise if an element is present start rendering process
if(this.settings.element) { if(bookPath && this.settings.element) {
this.opened.then(function(){ this.opened.then(function(){
this.rendered = this.renderTo(el); 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 //-- Check bookUrl and start parsing book Assets or load them from storage
EPUBJS.Book.prototype.open = function(bookPath, forceReload){ EPUBJS.Book.prototype.open = function(bookPath, forceReload){
var book = this, var book = this,
saved = this.isSaved(bookPath),
opened; opened;
this.settings.bookPath = bookPath;
//-- Get a absolute URL from the book path //-- Get a absolute URL from the book path
this.bookUrl = this.urlFrom(bookPath); this.bookUrl = this.urlFrom(bookPath);
// console.log("saved", saved, !forceReload)
//-- Remove the previous settings and reload //-- Remove the previous settings and reload
if(forceReload){ if(saved && !forceReload){
this.removeSavedSettings();
}
//-- Check for a saved settings object, with the same url and version
if(this.isSaved()){
//-- Apply settings, keeping newer ones //-- Apply settings, keeping newer ones
this.applySavedSettings(); 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 //-- Will load previous package json, or re-unpack if error
opened = this.restore(); 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 //-- If there is network connection, store the books contents
@ -156,7 +157,6 @@ EPUBJS.Book.prototype.unpack = function(containerPath){
}). }).
then(function(contents){ then(function(contents){
book.contents = contents; book.contents = contents;
book.manifest = book.contents.manifest; book.manifest = book.contents.manifest;
@ -184,8 +184,9 @@ EPUBJS.Book.prototype.unpack = function(containerPath){
}).then(function(toc){ }).then(function(toc){
book.toc = book.contents.toc = toc; book.toc = book.contents.toc = toc;
book.ready.toc.resolve(book.contents.toc); book.ready.toc.resolve(book.contents.toc);
// book.saveSettings();
}).then(null, function(error) { }).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 //-- Choose between a request from store or a request from network
EPUBJS.Book.prototype.loadXml = function(url){ EPUBJS.Book.prototype.loadXml = function(url){
if(this.settings.fromStorage) {
if(this.settings.storage) {
return this.storage.getXml(url); return this.storage.getXml(url);
} else if(this.settings.contained) {
return this.zip.getXml(url);
}else{ }else{
return EPUBJS.core.request(url, 'xml'); 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 //-- 1. Check if url is absolute
if(absolute){ if(absolute){
@ -268,17 +270,18 @@ EPUBJS.Book.prototype.urlFrom = function(bookPath){
EPUBJS.Book.prototype.unarchive = function(bookPath){ EPUBJS.Book.prototype.unarchive = function(bookPath){
var unzipped; var book = this,
unarchived;
//-- Must use storage //-- Must use storage
if(this.settings.storage == false ){ // if(this.settings.storage == false ){
this.settings.storage = true; // this.settings.storage = true;
this.storage = new fileStorage.storage(); // 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 //-- 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 //-- Checks if the book setting can be retrieved from localStorage
EPUBJS.Book.prototype.isSaved = function() { EPUBJS.Book.prototype.isSaved = function(bookPath) {
var bookKey = this.bookUrl + ":" + this.settings.version, var bookKey = bookPath + ":" + this.settings.version,
storedSettings = localStorage.getItem(bookKey); storedSettings = localStorage.getItem(bookKey);
if( !localStorage || if( !localStorage ||
@ -308,7 +311,7 @@ EPUBJS.Book.prototype.isSaved = function() {
//-- Remove save book settings //-- Remove save book settings
EPUBJS.Book.prototype.removeSavedSettings = function() { EPUBJS.Book.prototype.removeSavedSettings = function() {
var bookKey = this.bookUrl + ":" + this.settings.version; var bookKey = this.settings.bookPath + ":" + this.settings.version;
localStorage.removeItem(bookKey); localStorage.removeItem(bookKey);
@ -316,16 +319,15 @@ EPUBJS.Book.prototype.removeSavedSettings = function() {
} }
EPUBJS.Book.prototype.applySavedSettings = 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)); stored = JSON.parse(localStorage.getItem(bookKey));
if(EPUBJS.VERSION != stored.EPUBJSVERSION) return false; if(EPUBJS.VERSION != stored.EPUBJSVERSION) return false;
this.settings = _.defaults(this.settings, stored); this.settings = _.defaults(this.settings, stored);
} }
EPUBJS.Book.prototype.saveSettings = function(){ EPUBJS.Book.prototype.saveSettings = function(){
var bookKey = this.bookUrl + ":" + this.settings.version; var bookKey = this.settings.bookPath + ":" + this.settings.version;
if(this.render) { if(this.render) {
this.settings.previousLocationCfi = this.render.currentLocationCfi; this.settings.previousLocationCfi = this.render.currentLocationCfi;
@ -336,7 +338,7 @@ EPUBJS.Book.prototype.saveSettings = function(){
} }
EPUBJS.Book.prototype.saveContents = 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)); localStorage.setItem(contentsKey, JSON.stringify(this.contents));
@ -363,7 +365,7 @@ EPUBJS.Book.prototype.renderTo = function(el){
EPUBJS.Book.prototype.startDisplay = function(){ EPUBJS.Book.prototype.startDisplay = function(){
var display; var display;
if( this.settings.previousLocationCfi) { if( this.settings.restore && this.settings.previousLocationCfi) {
display = this.displayChapter(this.settings.previousLocationCfi); display = this.displayChapter(this.settings.previousLocationCfi);
@ -377,13 +379,13 @@ EPUBJS.Book.prototype.startDisplay = function(){
EPUBJS.Book.prototype.restore = function(){ EPUBJS.Book.prototype.restore = function(){
var book = this, var book = this,
contentsKey = this.settings.contentsPath + ":" + this.settings.version, contentsKey = this.settings.bookPath + ":contents:" + this.settings.version,
promise = new RSVP.Promise(), promise = new RSVP.Promise(),
fetch = ['manifest', 'spine', 'metadata', 'cover', 'toc', 'spineNodeIndex', 'spineIndexByURL'], fetch = ['manifest', 'spine', 'metadata', 'cover', 'toc', 'spineNodeIndex', 'spineIndexByURL'],
reject = false, reject = false,
fromStore = localStorage.getItem(contentsKey); fromStore = localStorage.getItem(contentsKey);
if(this.settings.contentsPath && fromStore){ if(fromStore != 'undefined'){
this.contents = JSON.parse(fromStore); this.contents = JSON.parse(fromStore);
fetch.forEach(function(item){ fetch.forEach(function(item){
@ -394,12 +396,9 @@ EPUBJS.Book.prototype.restore = function(){
}); });
} }
if(reject || !fromStore || !this.contents || !this.settings.contentsPath){
if(reject || !fromStore || !this.contents ){ // this.removeSavedSettings();
return this.open(this.settings.bookPath, true);
this.removeSavedSettings();
return this.unpack();
}else{ }else{
this.ready.manifest.resolve(this.manifest); this.ready.manifest.resolve(this.manifest);
@ -407,7 +406,6 @@ EPUBJS.Book.prototype.restore = function(){
this.ready.metadata.resolve(this.metadata); this.ready.metadata.resolve(this.metadata);
this.ready.cover.resolve(this.cover); this.ready.cover.resolve(this.cover);
this.ready.toc.resolve(this.toc); this.ready.toc.resolve(this.toc);
promise.resolve(); promise.resolve();
return promise; 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(){ render.then(function(){
book.preloadNextChapter(); book.preloadNextChapter();
}); });
@ -592,7 +591,7 @@ EPUBJS.Book.prototype.setStyle = function(style, val, prefixed) {
EPUBJS.Book.prototype.removeStyle = function(style, val, prefixed) { EPUBJS.Book.prototype.removeStyle = function(style, val, prefixed) {
this.renderer.removeStyle(style); 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 //-- Hooks allow for injecting async functions that must all complete before continuing
// Functions must have a callback as their first argument. // Functions must have a callback as their first argument.
EPUBJS.Book.prototype.registerHook = function(type, toAdd){ EPUBJS.Book.prototype.registerHook = function(type, toAdd, toFront){
var that = this; var book = this;
if(typeof(this.hooks[type]) != "undefined"){ if(typeof(this.hooks[type]) != "undefined"){
if(typeof(toAdd) === "function"){ if(typeof(toAdd) === "function"){
if(toFront) {
this.hooks[type].unshift(toAdd);
}else{
this.hooks[type].push(toAdd); this.hooks[type].push(toAdd);
}
}else if(Array.isArray(toAdd)){ }else if(Array.isArray(toAdd)){
toAdd.forEach(function(hook){ toAdd.forEach(function(hook){
that.hooks[type].push(hook); if(toFront) {
book.hooks[type].unshift(hook);
}else{
book.hooks[type].push(hook);
}
}); });
} }
}else{ }else{
//-- Allows for undefined hooks, but maybe this should error? //-- Allows for undefined hooks, but maybe this should error?
this.hooks[type] = [func]; this.hooks[type] = [func];

View file

@ -22,7 +22,10 @@ EPUBJS.Chapter.prototype.url = function(store){
var promise = new RSVP.Promise(); var promise = new RSVP.Promise();
if(store){ if(store){
return store.getUrl(href); if(!this.tempUrl) {
this.tempUrl = store.getUrl(this.href);
}
return this.tempUrl;
}else{ }else{
promise.resolve(this.href); //-- this is less than ideal but keeps it a promise promise.resolve(this.href); //-- this is less than ideal but keeps it a promise
return promise; return promise;
@ -41,3 +44,11 @@ EPUBJS.Chapter.prototype.getPages = function(num){
EPUBJS.Chapter.prototype.getID = function(){ EPUBJS.Chapter.prototype.getID = function(){
return this.ID; 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() { function handler() {
if (this.readyState === this.DONE) { if (this.readyState === this.DONE) {
if (this.status === 200) { if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls
var r; var r;
if(type == 'xml'){ 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); parts.push((part.index + 1) * 2);
if(part.id && 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 + "]"); parts.push("[" + part.id + "]");
} }
@ -149,6 +149,7 @@ EPUBJS.EpubCFI.prototype.getElement = function(cfi, doc) {
part = sections.shift(); part = sections.shift();
if(part.id){ if(part.id){
console.log(part.id)
element = cfi.doc.querySelector("#" + part.id); element = cfi.doc.querySelector("#" + part.id);
}else{ }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" //-- Find TOC NCX: media-type="application/x-dtbncx+xml" href="toc.ncx"
EPUBJS.Parser.prototype.findTocPath = function(manifestNode){ EPUBJS.Parser.prototype.findTocPath = function(manifestNode){
var node = manifestNode.querySelector("item[media-type='application/x-dtbncx+xml']"); 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" /> //-- Find Cover: <item properties="cover-image" id="ci" href="cover.svg" media-type="image/svg+xml" />
EPUBJS.Parser.prototype.findCoverPath = function(manifestNode){ EPUBJS.Parser.prototype.findCoverPath = function(manifestNode){
var node = manifestNode.querySelector("item[properties='cover-image']"); 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", 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.crossBrowserColumnCss();
@ -50,9 +52,13 @@ EPUBJS.Renderer.prototype.listeners = function(){
EPUBJS.Renderer.prototype.chapter = function(chapter){ EPUBJS.Renderer.prototype.chapter = function(chapter){
var renderer = this, 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) { if(this.currentChapter) {
this.currentChapter.unload();
this.trigger("book:chapterDestroyed"); this.trigger("book:chapterDestroyed");
} }
@ -189,6 +195,8 @@ EPUBJS.Renderer.prototype.setIframeSrc = function(url){
renderer.calcPages(); renderer.calcPages();
promise.resolve(renderer);
renderer.currentLocationCfi = renderer.getPageCfi(); renderer.currentLocationCfi = renderer.getPageCfi();
renderer.trigger("book:chapterDisplayed"); renderer.trigger("book:chapterDisplayed");
@ -197,7 +205,7 @@ EPUBJS.Renderer.prototype.setIframeSrc = function(url){
}); });
promise.resolve(renderer);
// that.afterLoaded(that); // that.afterLoaded(that);
@ -246,6 +254,7 @@ EPUBJS.Renderer.prototype.formatSpread = function(){
this.spreadWidth = (this.colWidth + this.gap) * divisor; this.spreadWidth = (this.colWidth + this.gap) * divisor;
if(this.bodyEl) this.bodyEl.style.margin = 0;
// this.bodyEl.style.fontSize = localStorage.getItem("fontSize") || "medium"; // this.bodyEl.style.fontSize = localStorage.getItem("fontSize") || "medium";
//-- Clear Margins //-- Clear Margins
@ -372,6 +381,8 @@ EPUBJS.Renderer.prototype.prevPage = function(){
EPUBJS.Renderer.prototype.chapterEnd = function(){ EPUBJS.Renderer.prototype.chapterEnd = function(){
this.page(this.displayedPages); this.page(this.displayedPages);
this.currentLocationCfi = this.getPageCfi();
} }
EPUBJS.Renderer.prototype.setLeft = function(leftPos){ EPUBJS.Renderer.prototype.setLeft = function(leftPos){
@ -379,9 +390,186 @@ EPUBJS.Renderer.prototype.setLeft = function(leftPos){
this.doc.defaultView.scrollTo(leftPos, 0) 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 //-- Replaces the relative links within the book to use our internal page changer
EPUBJS.Renderer.prototype.replaceLinks = function(callback){ EPUBJS.Renderer.prototype.replaceLinks = function(callback){
var hrefs = this.doc.querySelectorAll('[href]'), var hrefs = this.doc.querySelectorAll('a'),
links = Array.prototype.slice.call(hrefs), links = Array.prototype.slice.call(hrefs),
that = this; 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 //-- Replaces assets src's to point to stored version if browser is offline
EPUBJS.Renderer.prototype.replaceResources = function(callback){ EPUBJS.Renderer.prototype.replaceResources = function(callback){
var srcs, resources, count; var srcs, resources, count;
var store = this.determineStore();
//-- No need to replace if there is network connectivity if(!store) {
//-- also Filesystem api links are relative, so no need to replace them
if((this.book.online && !this.book.contained) || EPUBJS.storage.getStorageType() == "filesystem") {
if(callback) callback(); if(callback) callback();
return false; return false;
} }
@ -425,16 +612,22 @@ EPUBJS.Renderer.prototype.replaceResources = function(callback){
resources.forEach(function(link){ resources.forEach(function(link){
var src = link.getAttribute("src"), var src = link.getAttribute("src"),
full = this.book.basePath + src; full = this.book.settings.contentsPath + src;
EPUBJS.storage.get(full, function(url){ store.getUrl(full).then(function(url){
link.setAttribute("src", url); // link.setAttribute("src", url);
link.src = url;
link.onload = function(){
count--; count--;
if(count <= 0 && callback) callback(); if(count <= 0 && callback) callback();
}
}); });
}.bind(this)); }.bind(this));
if(count === 0) callback();
} }
EPUBJS.Renderer.prototype.page = function(pg){ EPUBJS.Renderer.prototype.page = function(pg){
@ -446,7 +639,7 @@ EPUBJS.Renderer.prototype.page = function(pg){
// localStorage.setItem("chapterPos", pg); // localStorage.setItem("chapterPos", pg);
return true; return true;
} }
console.log("false", pg, this.displayedPages)
//-- Return false if page is greater than the total //-- Return false if page is greater than the total
return false; return false;
} }
@ -534,7 +727,7 @@ EPUBJS.Renderer.prototype.getPageCfi = function(){
this.visibileEl = this.findFirstVisible(prevEl); this.visibileEl = this.findFirstVisible(prevEl);
if(!this.visibileEl.id) { 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; 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){ EPUBJS.Unarchiver = function(url){
this.libPath = EPUBJS.filePath + "libs/";
this.libPath = EPUBJS.filePath + "zip/";
this.zipUrl = url; this.zipUrl = url;
this.callback = callback; this.loadLib()
this.loadLib(function(){ this.urlCache = {};
this.getZip(this.zipUrl);
}.bind(this)); this.zipFs = new zip.fs.FS();
return this.promise;
} }
EPUBJS.Unarchiver.prototype.loadLib = function(callback){ EPUBJS.Unarchiver.prototype.loadLib = function(callback){
if(typeof(zip) != "undefined") callback(); if(typeof(zip) == "undefined") console.error("Zip lib not loaded");
/*
//-- load script //-- load script
EPUBJS.core.loadScript(this.libPath+"zip.js", function(){ EPUBJS.core.loadScript(this.libPath+"zip.js", function(){
//-- Tell zip where it is located //-- Tell zip where it is located
zip.workerScriptsPath = this.libPath; zip.workerScriptsPath = this.libPath;
callback(); callback();
}.bind(this)); }.bind(this));
*/
// console.log(this.libPath)
zip.workerScriptsPath = this.libPath;
} }
EPUBJS.Unarchiver.prototype.getZip = function(zipUrl){ EPUBJS.Unarchiver.prototype.openZip = function(zipUrl, callback){
var xhr = new EPUBJS.core.loadFile(zipUrl); var promise = new RSVP.Promise();
var zipFs = this.zipFs;
xhr.succeeded = function(file) { zipFs.importHttpContent(zipUrl, false, function() {
this.getEntries(file, this.toStorage.bind(this)); promise.resolve(zipFs);
}.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);
}, this.failed); }, 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){ EPUBJS.Unarchiver.prototype.failed = function(error){
console.log("Error:", error); console.error(error);
} }
EPUBJS.Unarchiver.prototype.afterSaved = function(error){ EPUBJS.Unarchiver.prototype.afterSaved = function(error){