mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-03 14:59:18 +02:00
basic scrolling renderer
This commit is contained in:
parent
849625fc83
commit
b1b98f9d57
15 changed files with 1020 additions and 22 deletions
|
@ -8,11 +8,14 @@
|
|||
|
||||
<script src="../lib/epub.js"></script>
|
||||
<script src="../lib/epubjs/core.js"></script>
|
||||
<script src="../lib/epubjs/hooks.js"></script>
|
||||
<script src="../lib/epubjs/book.js"></script>
|
||||
<script src="../lib/epubjs/parser.js"></script>
|
||||
<script src="../lib/epubjs/spine.js"></script>
|
||||
<script src="../lib/epubjs/navigation.js"></script>
|
||||
<script src="../lib/epubjs/epubcfi.js"></script>
|
||||
<script src="../lib/epubjs/renderer.js"></script>
|
||||
<script src="../lib/epubjs/view.js"></script>
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
|
@ -77,7 +80,7 @@
|
|||
var $next = document.getElementById("next");
|
||||
var $prev = document.getElementById("prev");
|
||||
var currentSection;
|
||||
var currentSectionIndex = 7;
|
||||
var currentSectionIndex = 6;
|
||||
|
||||
var book = ePub("../books/moby-dick/OPS/package.opf");
|
||||
book.loaded.navigation.then(function(toc){
|
||||
|
|
127
examples/basic-render.html
Normal file
127
examples/basic-render.html
Normal file
|
@ -0,0 +1,127 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>EPUB.js Basic Example</title>
|
||||
|
||||
<script src="../bower_components/rsvp/rsvp.js"></script>
|
||||
|
||||
<script src="../lib/epub.js"></script>
|
||||
<script src="../lib/epubjs/core.js"></script>
|
||||
<script src="../lib/epubjs/hooks.js"></script>
|
||||
<script src="../lib/epubjs/book.js"></script>
|
||||
<script src="../lib/epubjs/parser.js"></script>
|
||||
<script src="../lib/epubjs/spine.js"></script>
|
||||
<script src="../lib/epubjs/navigation.js"></script>
|
||||
<script src="../lib/epubjs/epubcfi.js"></script>
|
||||
<script src="../lib/epubjs/renderer.js"></script>
|
||||
<script src="../lib/epubjs/view.js"></script>
|
||||
<script src="../lib/epubjs/infinite.js"></script>
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#viewer {
|
||||
display: block;
|
||||
margin: 5% auto;
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#prev {
|
||||
left: 40px;
|
||||
}
|
||||
|
||||
#next {
|
||||
right: 40px;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
margin-top: -32px;
|
||||
font-size: 64px;
|
||||
color: #E2E2E2;
|
||||
font-family: arial, sans-serif;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.arrow:hover {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.arrow:active {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#toc {
|
||||
display: block;
|
||||
margin: 10px auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- <select id="toc"></select> -->
|
||||
<!-- <iframe id="viewer"></iframe> -->
|
||||
<div id="viewer"></div>
|
||||
<div id="prev" class="arrow">‹</div>
|
||||
<div id="next" class="arrow">›</div>
|
||||
|
||||
<script>
|
||||
var $viewer = document.getElementById("viewer");
|
||||
var $next = document.getElementById("next");
|
||||
var $prev = document.getElementById("prev");
|
||||
var currentSection;
|
||||
var currentSectionIndex = 0;
|
||||
|
||||
var book = ePub("../books/moby-dick/OPS/package.opf");
|
||||
var rendition = book.renderTo("viewer");
|
||||
rendition.display(currentSectionIndex);
|
||||
|
||||
// Navigations Drop Down
|
||||
book.loaded.navigation.then(function(toc){
|
||||
var $select = document.getElementById("toc"),
|
||||
docfrag = document.createDocumentFragment();
|
||||
|
||||
toc.forEach(function(chapter) {
|
||||
var option = document.createElement("option");
|
||||
option.textContent = chapter.label;
|
||||
option.ref = chapter.href;
|
||||
|
||||
docfrag.appendChild(option);
|
||||
});
|
||||
|
||||
// $select.appendChild(docfrag);
|
||||
|
||||
// $select.onchange = function(){
|
||||
// var index = $select.selectedIndex;
|
||||
// var url = $select.options[index].ref;
|
||||
// rendition.display(url);
|
||||
// return false;
|
||||
// };
|
||||
|
||||
$next.addEventListener("click", function(){
|
||||
rendition.display(currentSectionIndex+1);
|
||||
currentSectionIndex++;
|
||||
}, false);
|
||||
|
||||
$prev.addEventListener("click", function(){
|
||||
rendition.display(currentSectionIndex-1);
|
||||
currentSectionIndex--;
|
||||
}, false);
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -3,7 +3,7 @@ if (typeof EPUBJS === 'undefined') {
|
|||
}
|
||||
|
||||
EPUBJS.VERSION = "0.3.0";
|
||||
|
||||
EPUBJS.Render = {};
|
||||
|
||||
(function(root) {
|
||||
"use strict";
|
||||
|
|
|
@ -2,6 +2,7 @@ EPUBJS.Book = function(_url){
|
|||
// Promises
|
||||
this.opening = new RSVP.defer();
|
||||
this.opened = this.opening.promise;
|
||||
this.isOpen = false;
|
||||
|
||||
this.url = undefined;
|
||||
|
||||
|
@ -25,17 +26,11 @@ EPUBJS.Book = function(_url){
|
|||
pageList: this.loading.pageList.promise
|
||||
};
|
||||
|
||||
this.loaders = [];
|
||||
for(var promise in this.loaded){
|
||||
this.loaders.push(this.loaded[promise]);
|
||||
}
|
||||
this.ready = RSVP.hash(this.loaded);
|
||||
|
||||
this.ready = RSVP.all(this.loaders);
|
||||
|
||||
// this.pageList = [];
|
||||
|
||||
|
||||
// this.ready.all.then(this._ready.bind(this));
|
||||
// Queue for methods used before opening
|
||||
this.isRendered = false;
|
||||
this._q = EPUBJS.core.queue(this);
|
||||
|
||||
if(_url) {
|
||||
this.open(_url);
|
||||
|
@ -48,6 +43,7 @@ EPUBJS.Book.prototype.open = function(_url){
|
|||
var epubPackage;
|
||||
var book = this;
|
||||
var containerPath = "META-INF/container.xml";
|
||||
var location;
|
||||
|
||||
// Reuse parsed url or create a new uri object
|
||||
if(typeof(_url) === "object") {
|
||||
|
@ -64,6 +60,9 @@ EPUBJS.Book.prototype.open = function(_url){
|
|||
|
||||
if(uri.origin) {
|
||||
this.url = uri.origin + "/" + uri.directory;
|
||||
} else if(window){
|
||||
location = EPUBJS.core.uri(window.location.href);
|
||||
this.url = EPUBJS.core.resolveUrl(location.base, uri.directory);
|
||||
} else {
|
||||
this.url = uri.directory;
|
||||
}
|
||||
|
@ -111,11 +110,13 @@ EPUBJS.Book.prototype.open = function(_url){
|
|||
book.loading.spine.resolve(book.spine);
|
||||
book.loading.cover.resolve(book.cover);
|
||||
|
||||
// Resolve book opened promise
|
||||
book.opening.resolve(book);
|
||||
this.isOpen = true;
|
||||
|
||||
// Clear queue of any waiting book request
|
||||
|
||||
// Resolve book opened promise
|
||||
book.opening.resolve(book);
|
||||
|
||||
}).catch(function(error) {
|
||||
// handle errors in parsing the book
|
||||
console.error(error.message, error.stack);
|
||||
|
@ -152,6 +153,13 @@ EPUBJS.Book.prototype.section = function(target) {
|
|||
return this.spine.get(target);
|
||||
};
|
||||
|
||||
// Sugar to render a book
|
||||
EPUBJS.Book.prototype.renderTo = function(element, options) {
|
||||
var rendition = new EPUBJS.Renderer(this, options);
|
||||
rendition.attachTo(element);
|
||||
return rendition;
|
||||
};
|
||||
|
||||
EPUBJS.Book.prototype.request = function(_url) {
|
||||
// Switch request methods
|
||||
if(this.archived) {
|
||||
|
|
|
@ -153,4 +153,108 @@ EPUBJS.core.folder = function(url){
|
|||
|
||||
return folder;
|
||||
|
||||
};
|
||||
|
||||
|
||||
EPUBJS.core.queue = function(_scope){
|
||||
var _q = [];
|
||||
var scope = _scope;
|
||||
// Add an item to the queue
|
||||
var enqueue = function(funcName, args, context) {
|
||||
_q.push({
|
||||
"funcName" : funcName,
|
||||
"args" : args,
|
||||
"context" : context
|
||||
});
|
||||
return _q;
|
||||
};
|
||||
// Run one item
|
||||
var dequeue = function(){
|
||||
var inwait;
|
||||
if(_q.length) {
|
||||
inwait = _q.shift();
|
||||
// Defer to any current tasks
|
||||
// setTimeout(function(){
|
||||
scope[inwait.funcName].apply(inwait.context || scope, inwait.args);
|
||||
// }, 0);
|
||||
}
|
||||
};
|
||||
|
||||
// Run All
|
||||
var flush = function(){
|
||||
while(_q.length) {
|
||||
dequeue();
|
||||
}
|
||||
};
|
||||
// Clear all items in wait
|
||||
var clear = function(){
|
||||
_q = [];
|
||||
};
|
||||
|
||||
var length = function(){
|
||||
return _q.length;
|
||||
};
|
||||
|
||||
return {
|
||||
"enqueue" : enqueue,
|
||||
"dequeue" : dequeue,
|
||||
"flush" : flush,
|
||||
"clear" : clear,
|
||||
"length" : length
|
||||
};
|
||||
};
|
||||
|
||||
EPUBJS.core.isElement = function(obj) {
|
||||
return !!(obj && obj.nodeType == 1);
|
||||
};
|
||||
|
||||
// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
|
||||
EPUBJS.core.uuid = function() {
|
||||
var d = new Date().getTime();
|
||||
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
var r = (d + Math.random()*16)%16 | 0;
|
||||
d = Math.floor(d/16);
|
||||
return (c=='x' ? r : (r&0x7|0x8)).toString(16);
|
||||
});
|
||||
return uuid;
|
||||
};
|
||||
|
||||
// From Lodash
|
||||
EPUBJS.core.values = function(object) {
|
||||
var index = -1,
|
||||
props = Object.keys(object),
|
||||
length = props.length,
|
||||
result = Array(length);
|
||||
|
||||
while (++index < length) {
|
||||
result[index] = object[props[index]];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
EPUBJS.core.resolveUrl = function(base, path) {
|
||||
var url,
|
||||
segments = [],
|
||||
// uri = EPUBJS.core.uri(path),
|
||||
folders = base.split("/"),
|
||||
paths;
|
||||
|
||||
// if(uri.host) {
|
||||
// return path;
|
||||
// }
|
||||
|
||||
folders.pop();
|
||||
|
||||
paths = path.split("/");
|
||||
paths.forEach(function(p){
|
||||
if(p === ".."){
|
||||
folders.pop();
|
||||
}else{
|
||||
segments.push(p);
|
||||
}
|
||||
});
|
||||
|
||||
url = folders.concat(segments);
|
||||
|
||||
return url.join("/");
|
||||
};
|
87
lib/epubjs/hooks.js
Normal file
87
lib/epubjs/hooks.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
EPUBJS.hooks = {};
|
||||
EPUBJS.Hooks = (function(){
|
||||
function hooks(){}
|
||||
|
||||
//-- Get pre-registered hooks
|
||||
hooks.prototype.getHooks = function(){
|
||||
var plugs, hooks;
|
||||
this.hooks = {};
|
||||
Array.prototype.slice.call(arguments).forEach(function(arg){
|
||||
this.hooks[arg] = [];
|
||||
}, this);
|
||||
|
||||
for (var plugType in this.hooks) {
|
||||
hooks = EPUBJS.hooks[plugType];
|
||||
if(hooks){
|
||||
plugs = EPUBJS.core.values();
|
||||
|
||||
plugs.forEach(function(hook){
|
||||
this.registerHook(plugType, hook);
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//-- Hooks allow for injecting async functions that must all complete before continuing
|
||||
// Functions must have a callback as their first argument.
|
||||
hooks.prototype.registerHook = function(type, toAdd, toFront){
|
||||
|
||||
if(typeof(this.hooks[type]) != "undefined"){
|
||||
|
||||
if(typeof(toAdd) === "function"){
|
||||
if(toFront) {
|
||||
this.hooks[type].unshift(toAdd);
|
||||
}else{
|
||||
this.hooks[type].push(toAdd);
|
||||
}
|
||||
}else if(Array.isArray(toAdd)){
|
||||
toAdd.forEach(function(hook){
|
||||
if(toFront) {
|
||||
this.hooks[type].unshift(hook);
|
||||
}else{
|
||||
this.hooks[type].push(hook);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}else{
|
||||
//-- Allows for undefined hooks, but maybe this should error?
|
||||
this.hooks[type] = [func];
|
||||
}
|
||||
};
|
||||
|
||||
hooks.prototype.triggerHooks = function(type, callback, passed){
|
||||
var hooks, count;
|
||||
|
||||
if(typeof(this.hooks[type]) == "undefined") return false;
|
||||
|
||||
hooks = this.hooks[type];
|
||||
|
||||
count = hooks.length;
|
||||
if(count === 0 && callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
function countdown(){
|
||||
count--;
|
||||
if(count <= 0 && callback) callback();
|
||||
}
|
||||
|
||||
hooks.forEach(function(hook){
|
||||
hook(countdown, passed);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
register: function(name) {
|
||||
if(EPUBJS.hooks[name] === undefined) { EPUBJS.hooks[name] = {}; }
|
||||
if(typeof EPUBJS.hooks[name] !== 'object') { throw "Already registered: "+name; }
|
||||
return EPUBJS.hooks[name];
|
||||
},
|
||||
mixin: function(object) {
|
||||
for (var prop in hooks.prototype) {
|
||||
object[prop] = hooks.prototype[prop];
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
97
lib/epubjs/infinite.js
Normal file
97
lib/epubjs/infinite.js
Normal file
|
@ -0,0 +1,97 @@
|
|||
EPUBJS.Infinite = function(container, renderer){
|
||||
this.container = container;
|
||||
this.windowHeight = window.innerHeight;
|
||||
this.tick = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
|
||||
this.scrolled = false;
|
||||
this.displaying = false;
|
||||
this.offset = 250;
|
||||
this.views = [];
|
||||
this.renderer = renderer;
|
||||
};
|
||||
|
||||
EPUBJS.Infinite.prototype.start = function(first_argument) {
|
||||
|
||||
window.addEventListener("scroll", function(){
|
||||
this.scrolled = true;
|
||||
}.bind(this));
|
||||
|
||||
this.tick.call(window, this.check.bind(this));
|
||||
|
||||
// Fill Screen
|
||||
this.scrolled = false;
|
||||
|
||||
};
|
||||
|
||||
EPUBJS.Infinite.prototype.forwards = function() {
|
||||
this.trigger("forwards");
|
||||
|
||||
};
|
||||
|
||||
EPUBJS.Infinite.prototype.backwards = function() {
|
||||
this.trigger("backwards");
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
// Manage Views
|
||||
EPUBJS.Infinite.prototype.jump = function(view){
|
||||
this.views.push(view);
|
||||
};
|
||||
|
||||
EPUBJS.Infinite.prototype.append = function(view){
|
||||
this.views.push(view);
|
||||
view.appendTo(this.container);
|
||||
};
|
||||
|
||||
EPUBJS.Infinite.prototype.prepend = function(view){
|
||||
this.views.unshift(view);
|
||||
view.prependTo(this.container);
|
||||
};
|
||||
|
||||
// Simple Insert
|
||||
EPUBJS.Infinite.prototype.insert = function(view, index){
|
||||
|
||||
var position;
|
||||
var distanceFront = index - this.positions[0];
|
||||
var distanceRear = index - this.positions[this.positions.length-1];
|
||||
|
||||
if(distanceFront >= 0 || !this.positions.length) {
|
||||
position = this.append(view);
|
||||
this.positions.push(index);
|
||||
} else if(distanceRear <= 0) {
|
||||
position = this.prepend(view);
|
||||
this.positions.unshift(index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return position;
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
EPUBJS.Infinite.prototype.check = function(){
|
||||
|
||||
if(this.scrolled && !this.displaying) {
|
||||
|
||||
var scrollTop = document.body.scrollTop;//TODO: make document.body a variable
|
||||
var scrollHeight = document.body.scrollHeight;
|
||||
// console.log(scrollTop, this.windowHeight - (scrollHeight - scrollTop) )
|
||||
if(this.windowHeight - (scrollHeight - scrollTop) > -this.offset) {
|
||||
this.forwards();
|
||||
}
|
||||
else if(scrollTop < this.offset) {
|
||||
this.backwards();
|
||||
}
|
||||
|
||||
// console.log(document.body.scrollTop)
|
||||
|
||||
|
||||
this.scrolled = false;
|
||||
}
|
||||
|
||||
this.tick.call(window, this.check.bind(this));
|
||||
}
|
||||
|
||||
RSVP.EventTarget.mixin(EPUBJS.Infinite.prototype);
|
95
lib/epubjs/layout.js
Normal file
95
lib/epubjs/layout.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
* Reconciles the current chapters layout properies with
|
||||
* the global layout properities.
|
||||
* Takes: global layout settings object, chapter properties string
|
||||
* Returns: Object with layout properties
|
||||
*/
|
||||
EPUBJS.Renderer.prototype.reconcileLayoutSettings = function(global, chapter){
|
||||
var settings = {};
|
||||
|
||||
//-- Get the global defaults
|
||||
for (var attr in global) {
|
||||
if (global.hasOwnProperty(attr)){
|
||||
settings[attr] = global[attr];
|
||||
}
|
||||
}
|
||||
//-- Get the chapter's display type
|
||||
chapter.forEach(function(prop){
|
||||
var rendition = prop.replace("rendition:", '');
|
||||
var split = rendition.indexOf("-");
|
||||
var property, value;
|
||||
|
||||
if(split != -1){
|
||||
property = rendition.slice(0, split);
|
||||
value = rendition.slice(split+1);
|
||||
|
||||
settings[property] = value;
|
||||
}
|
||||
});
|
||||
return settings;
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the settings to determine which Layout Method is needed
|
||||
* Triggers events based on the method choosen
|
||||
* Takes: Layout settings object
|
||||
* Returns: String of appropriate for EPUBJS.Layout function
|
||||
*/
|
||||
EPUBJS.Renderer.prototype.determineLayout = function(settings){
|
||||
// Default is layout: reflowable & spread: auto
|
||||
var spreads = this.determineSpreads(this.minSpreadWidth);
|
||||
var layoutMethod = spreads ? "ReflowableSpreads" : "Reflowable";
|
||||
var scroll = false;
|
||||
|
||||
if(settings.layout === "pre-paginated") {
|
||||
layoutMethod = "Fixed";
|
||||
scroll = true;
|
||||
spreads = false;
|
||||
}
|
||||
|
||||
if(settings.layout === "reflowable" && settings.spread === "none") {
|
||||
layoutMethod = "Reflowable";
|
||||
scroll = false;
|
||||
spreads = false;
|
||||
}
|
||||
|
||||
if(settings.layout === "reflowable" && settings.spread === "both") {
|
||||
layoutMethod = "ReflowableSpreads";
|
||||
scroll = false;
|
||||
spreads = true;
|
||||
}
|
||||
|
||||
this.spreads = spreads;
|
||||
this.render.scroll(scroll);
|
||||
this.trigger("renderer:spreads", spreads);
|
||||
return layoutMethod;
|
||||
};
|
||||
|
||||
//-- STYLES
|
||||
|
||||
EPUBJS.Renderer.prototype.applyStyles = function(styles) {
|
||||
for (var style in styles) {
|
||||
for (var view in this.views) {
|
||||
view.setStyle(style, styles[style]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
EPUBJS.Renderer.prototype.setStyle = function(style, val, prefixed){
|
||||
for (var view in this.views) {
|
||||
view.setStyle(style, val, prefixed);
|
||||
}
|
||||
};
|
||||
|
||||
EPUBJS.Renderer.prototype.removeStyle = function(style){
|
||||
for (var view in this.views) {
|
||||
view.removeStyle(style);
|
||||
}
|
||||
};
|
||||
|
||||
//-- HEAD TAGS
|
||||
EPUBJS.Renderer.prototype.applyHeadTags = function(headTags) {
|
||||
for ( var headTag in headTags ) {
|
||||
this.render.addHeadTag(headTag, headTags[headTag]);
|
||||
}
|
||||
};
|
70
lib/epubjs/listeners.js
Normal file
70
lib/epubjs/listeners.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
EPUBJS.Renderer.prototype.listeners = function(){
|
||||
// Dom events to listen for
|
||||
this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click"];
|
||||
this.upEvent = "mouseup";
|
||||
this.downEvent = "mousedown";
|
||||
if('ontouchstart' in document.documentElement) {
|
||||
this.listenedEvents.push("touchstart", "touchend");
|
||||
this.upEvent = "touchend";
|
||||
this.downEvent = "touchstart";
|
||||
}
|
||||
|
||||
// Resize events
|
||||
// this.resized = _.debounce(this.onResized.bind(this), 100);
|
||||
|
||||
};
|
||||
|
||||
//-- Listeners for events in the frame
|
||||
|
||||
EPUBJS.Renderer.prototype.onResized = function(e) {
|
||||
var width = this.container.clientWidth;
|
||||
var height = this.container.clientHeight;
|
||||
|
||||
this.resize(width, height, false);
|
||||
};
|
||||
|
||||
EPUBJS.Renderer.prototype.addEventListeners = function(){
|
||||
if(!this.render.document) {
|
||||
return;
|
||||
}
|
||||
this.listenedEvents.forEach(function(eventName){
|
||||
this.render.document.addEventListener(eventName, this.triggerEvent.bind(this), false);
|
||||
}, this);
|
||||
|
||||
};
|
||||
|
||||
EPUBJS.Renderer.prototype.removeEventListeners = function(){
|
||||
if(!this.render.document) {
|
||||
return;
|
||||
}
|
||||
this.listenedEvents.forEach(function(eventName){
|
||||
this.render.document.removeEventListener(eventName, this.triggerEvent, false);
|
||||
}, this);
|
||||
|
||||
};
|
||||
|
||||
// Pass browser events
|
||||
EPUBJS.Renderer.prototype.triggerEvent = function(e){
|
||||
this.trigger("renderer:"+e.type, e);
|
||||
};
|
||||
|
||||
EPUBJS.Renderer.prototype.addSelectionListeners = function(){
|
||||
this.render.document.addEventListener("selectionchange", this.onSelectionChange.bind(this), false);
|
||||
};
|
||||
|
||||
EPUBJS.Renderer.prototype.removeSelectionListeners = function(){
|
||||
if(!this.render.document) {
|
||||
return;
|
||||
}
|
||||
this.doc.removeEventListener("selectionchange", this.onSelectionChange, false);
|
||||
};
|
||||
|
||||
EPUBJS.Renderer.prototype.onSelectionChange = function(e){
|
||||
if (this.selectionEndTimeout) {
|
||||
clearTimeout(this.selectionEndTimeout);
|
||||
}
|
||||
this.selectionEndTimeout = setTimeout(function() {
|
||||
this.selectedRange = this.render.window.getSelection();
|
||||
this.trigger("renderer:selected", this.selectedRange);
|
||||
}.bind(this), 500);
|
||||
};
|
63
lib/epubjs/render/paginated.js
Normal file
63
lib/epubjs/render/paginated.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
EPUBJS.Render.Paginated = function(book, options){
|
||||
|
||||
// Dom events to listen for
|
||||
this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click"];
|
||||
this.upEvent = "mouseup";
|
||||
this.downEvent = "mousedown";
|
||||
if('ontouchstart' in document.documentElement) {
|
||||
this.listenedEvents.push("touchstart", "touchend");
|
||||
this.upEvent = "touchend";
|
||||
this.downEvent = "touchstart";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//-- Takes a string or a element
|
||||
EPUBJS.Render.Paginated.prototype.initialize = function(elem){
|
||||
var book = this;
|
||||
var rendered;
|
||||
|
||||
if(EPUBJS.core.isElement(elem)) {
|
||||
this.element = elem;
|
||||
} else if (typeof elem == "string") {
|
||||
this.element = document.getElementById(elem);
|
||||
} else {
|
||||
console.error("Pass an Element or Element Id");
|
||||
return;
|
||||
}
|
||||
|
||||
rendered = this.opened.
|
||||
then(function(){
|
||||
// book.render = new EPUBJS.Renderer[this.settings.renderer](book);
|
||||
book.renderer.initialize(book.element, book.settings.width, book.settings.height);
|
||||
book._rendered();
|
||||
return book.startDisplay();
|
||||
});
|
||||
|
||||
// rendered.then(null, function(error) { console.error(error); });
|
||||
|
||||
return rendered;
|
||||
};
|
||||
|
||||
|
||||
// epub.renderTo("elementID", _type);
|
||||
// rendition = epub.renderer(book, _type);
|
||||
// rendition.attachTo("elementID");
|
||||
// epub.display();
|
||||
// return rendition;
|
||||
|
||||
// epub.display();
|
||||
// epub.display(1);
|
||||
// epub.display("chapt1.html#something");
|
||||
// epub.display("epubcfi(/6/30[id-id2640702]!2/4/1:0)");
|
||||
// section = book.section(_arg);
|
||||
// rendition.display(section);
|
||||
// section.render();
|
||||
// section.load();
|
||||
// return rendition;
|
||||
|
||||
// epub.rendition.backwards();
|
||||
// epub.rendition.forwards();
|
||||
|
||||
// epub.rendition.addStyle();
|
||||
// epub.rendition.addStyles();
|
220
lib/epubjs/renderer.js
Normal file
220
lib/epubjs/renderer.js
Normal file
|
@ -0,0 +1,220 @@
|
|||
EPUBJS.Renderer = function(book, _options) {
|
||||
var options = _options || {};
|
||||
var settings = {
|
||||
hidden: options.hidden || false,
|
||||
viewLimit: 3,
|
||||
width: options.width || false,
|
||||
height: options.height || false,
|
||||
};
|
||||
|
||||
this.book = book;
|
||||
|
||||
// Listen for load events
|
||||
// this.on("render:loaded", this.loaded.bind(this));
|
||||
|
||||
// Blank Cfi for Parsing
|
||||
this.epubcfi = new EPUBJS.EpubCFI();
|
||||
// this.resized = _.debounce(this.onResized.bind(this), 100);
|
||||
|
||||
this.layoutSettings = {};
|
||||
|
||||
//-- Adds Hook methods to the Book prototype
|
||||
// Hooks will all return before triggering the callback.
|
||||
EPUBJS.Hooks.mixin(this);
|
||||
|
||||
//-- Get pre-registered hooks for events
|
||||
this.getHooks("beforeChapterDisplay");
|
||||
|
||||
//-- Queue up page changes if page map isn't ready
|
||||
this._q = EPUBJS.core.queue(this);
|
||||
|
||||
this.position = 1;
|
||||
|
||||
this.initialize({
|
||||
"width" : settings.width,
|
||||
"height" : settings.height,
|
||||
"hidden" : true
|
||||
});
|
||||
|
||||
this.displaying = false;
|
||||
this.views = [];
|
||||
this.positions = [];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an element to render to.
|
||||
* Resizes to passed width and height or to the elements size
|
||||
*/
|
||||
EPUBJS.Renderer.prototype.initialize = function(_options){
|
||||
var options = _options || {};
|
||||
var height = options.height || "100%";
|
||||
var width = options.width || "100%";
|
||||
var hidden = options.hidden || false;
|
||||
|
||||
|
||||
this.container = document.createElement("div");
|
||||
this.infinite = new EPUBJS.Infinite(this.container, this);
|
||||
|
||||
this.container.style.width = height;
|
||||
this.container.style.height = width;
|
||||
this.container.style.overflow = "scroll";
|
||||
|
||||
if(options.hidden) {
|
||||
this.wrapper = document.createElement("div");
|
||||
this.wrapper.style.visibility = "hidden";
|
||||
this.wrapper.style.overflow = "hidden";
|
||||
this.wrapper.style.width = "0";
|
||||
this.wrapper.style.height = "0";
|
||||
|
||||
this.wrapper.appendChild(this.container);
|
||||
return this.wrapper;
|
||||
}
|
||||
|
||||
return this.container;
|
||||
};
|
||||
|
||||
|
||||
EPUBJS.Renderer.prototype.attachTo = function(_element){
|
||||
var element;
|
||||
|
||||
if(EPUBJS.core.isElement(_element)) {
|
||||
element = _element;
|
||||
} else if (typeof _element === "string") {
|
||||
element = document.getElementById(_element);
|
||||
}
|
||||
|
||||
if(!element){
|
||||
console.error("Not an Element");
|
||||
return;
|
||||
}
|
||||
|
||||
element.appendChild(this.container);
|
||||
|
||||
this.infinite.start();
|
||||
|
||||
this.infinite.on("forwards", this.forwards.bind(this));
|
||||
this.infinite.on("backwards", this.backwards.bind(this));
|
||||
|
||||
};
|
||||
|
||||
|
||||
EPUBJS.Renderer.prototype.display = function(what){
|
||||
var displaying = new RSVP.defer();
|
||||
var displayed = displaying.promise;
|
||||
var view = new EPUBJS.View();
|
||||
|
||||
this.book.opened.then(function(){
|
||||
var section = this.book.spine.get(what);
|
||||
var rendered;
|
||||
|
||||
if(!section) {
|
||||
displaying.reject();
|
||||
return;
|
||||
};
|
||||
|
||||
rendered = section.render();
|
||||
|
||||
view.index = section.index;
|
||||
|
||||
rendered.then(function(contents){
|
||||
return view.load(contents);
|
||||
}).then(function(){
|
||||
displaying.resolve(this);
|
||||
}.bind(this));
|
||||
|
||||
// Place view in correct position
|
||||
this.insert(view, section.index);
|
||||
|
||||
}.bind(this));
|
||||
|
||||
return displayed;
|
||||
};
|
||||
|
||||
|
||||
EPUBJS.Renderer.prototype.forwards = function(){
|
||||
var next;
|
||||
var displayed;
|
||||
|
||||
if(this.displaying) return;
|
||||
|
||||
next = this.last().index + 1;
|
||||
|
||||
if(next === this.book.spine.length){
|
||||
return;
|
||||
}
|
||||
|
||||
displayed = this.display(next);
|
||||
this.displaying = true;
|
||||
|
||||
displayed.then(function(){
|
||||
this.displaying = false;
|
||||
}.bind(this));
|
||||
|
||||
return displayed;
|
||||
};
|
||||
|
||||
EPUBJS.Renderer.prototype.backwards = function(view){
|
||||
var prev;
|
||||
var displayed;
|
||||
|
||||
if(this.displaying) return;
|
||||
|
||||
prev = this.first().index - 1;
|
||||
if(prev < 0){
|
||||
return;
|
||||
}
|
||||
|
||||
displayed = this.display(prev);
|
||||
this.displaying = true;
|
||||
|
||||
displayed.then(function(){
|
||||
this.displaying = false;
|
||||
window.scrollBy(0, this.first().height + 20);
|
||||
}.bind(this));
|
||||
|
||||
return displayed;
|
||||
};
|
||||
|
||||
|
||||
// Manage Views
|
||||
EPUBJS.Renderer.prototype.jump = function(view){
|
||||
this.views.push(view);
|
||||
};
|
||||
|
||||
EPUBJS.Renderer.prototype.append = function(view){
|
||||
this.views.push(view);
|
||||
view.appendTo(this.container);
|
||||
};
|
||||
|
||||
EPUBJS.Renderer.prototype.prepend = function(view){
|
||||
this.views.unshift(view);
|
||||
view.prependTo(this.container);
|
||||
};
|
||||
|
||||
// Simple Insert
|
||||
EPUBJS.Renderer.prototype.insert = function(view, index){
|
||||
|
||||
if(!this.first()) {
|
||||
this.append(view);
|
||||
} else if(index - this.first().index >= 0) {
|
||||
this.append(view);
|
||||
} else if(index - this.last().index <= 0) {
|
||||
this.prepend(view);
|
||||
}
|
||||
|
||||
// return position;
|
||||
};
|
||||
|
||||
// Remove the render element and clean up listeners
|
||||
EPUBJS.Renderer.prototype.destroy = function() {
|
||||
|
||||
};
|
||||
|
||||
EPUBJS.Renderer.prototype.first = function() {
|
||||
return this.views[0];
|
||||
};
|
||||
|
||||
EPUBJS.Renderer.prototype.last = function() {
|
||||
return this.views[this.views.length-1];
|
||||
};
|
|
@ -37,13 +37,13 @@ EPUBJS.Spine = function(_package, _request){
|
|||
// book.spine.get("chap1.html");
|
||||
// book.spine.get("#id1234");
|
||||
EPUBJS.Spine.prototype.get = function(target) {
|
||||
var index = 1;
|
||||
var index = 0;
|
||||
|
||||
if(typeof target === "number" || isNaN(target) === false){
|
||||
index = target-1;
|
||||
} else if(target.indexOf("#") === 0) {
|
||||
if(target && (typeof target === "number" || isNaN(target) === false)){
|
||||
index = target;
|
||||
} else if(target && target.indexOf("#") === 0) {
|
||||
index = this.spineById[target.substring(1)];
|
||||
} else {
|
||||
} else if(target) {
|
||||
index = this.spineByHref[target];
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,13 @@ EPUBJS.SpineItem.prototype.load = function(_request){
|
|||
loading.resolve(this.contents);
|
||||
} else {
|
||||
request(this.url, 'xml').then(function(xml){
|
||||
var base;
|
||||
var directory = EPUBJS.core.folder(this.url);
|
||||
this.document = xml;
|
||||
this.contents = xml.documentElement;
|
||||
|
||||
this.replacements(this.document);
|
||||
|
||||
loading.resolve(this.contents);
|
||||
}.bind(this));
|
||||
}
|
||||
|
@ -79,11 +85,23 @@ EPUBJS.SpineItem.prototype.load = function(_request){
|
|||
return loaded;
|
||||
};
|
||||
|
||||
EPUBJS.SpineItem.prototype.replacements = function(_document){
|
||||
var base = _document.createElement("base");
|
||||
base.setAttribute("href", this.url);
|
||||
_document.head.insertBefore(base, _document.head.firstChild);
|
||||
};
|
||||
|
||||
EPUBJS.SpineItem.prototype.render = function(){
|
||||
return this.load().then(function(contents){
|
||||
var rendering = new RSVP.defer();
|
||||
var rendered = rendering.promise;
|
||||
|
||||
this.load().then(function(contents){
|
||||
var serializer = new XMLSerializer();
|
||||
return serializer.serializeToString(contents);
|
||||
var output = serializer.serializeToString(contents);
|
||||
rendering.resolve(output);
|
||||
});
|
||||
|
||||
return rendered;
|
||||
};
|
||||
|
||||
EPUBJS.SpineItem.prototype.find = function(_query){
|
||||
|
|
87
lib/epubjs/view.js
Normal file
87
lib/epubjs/view.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
EPUBJS.View = function(options) {
|
||||
this.id = "epubjs-view:" + EPUBJS.core.uuid();
|
||||
this.loading = new RSVP.defer();
|
||||
this.loaded = this.loading.promise;
|
||||
this.iframe = this.create();
|
||||
this.height;
|
||||
this.width;
|
||||
};
|
||||
|
||||
// EPUBJS.View.prototype.load = function(section) {
|
||||
// var contents = section.render();
|
||||
// var loading = new RSVP.defer();
|
||||
// var loaded = loading.promise;
|
||||
|
||||
// this.section = section;
|
||||
|
||||
// contents.then(function(contents) {
|
||||
// //TODO: Add a more generic set contents
|
||||
// this.iframe.srcdoc = contents;
|
||||
// this.layout();
|
||||
|
||||
// loading.resolve(this);
|
||||
// }.bind(this));
|
||||
|
||||
// return loaded;
|
||||
// };
|
||||
|
||||
EPUBJS.View.prototype.load = function(contents) {
|
||||
var loading = new RSVP.defer();
|
||||
var loaded = loading.promise;
|
||||
|
||||
this.document = this.iframe.contentDocument;
|
||||
|
||||
// this.iframe.srcdoc = contents;
|
||||
this.document.open();
|
||||
this.document.write(contents);
|
||||
this.document.close();
|
||||
|
||||
this.iframe.onload = function(e) {
|
||||
this.iframe.style.display = "block";
|
||||
this.layout();
|
||||
this.iframe.style.visibility = "visible";
|
||||
loading.resolve(this);
|
||||
this.loading.resolve(this);
|
||||
}.bind(this);
|
||||
|
||||
return loaded;
|
||||
};
|
||||
|
||||
|
||||
EPUBJS.View.prototype.unload = function() {
|
||||
|
||||
};
|
||||
|
||||
EPUBJS.View.prototype.create = function() {
|
||||
this.iframe = document.createElement('iframe');
|
||||
this.iframe.id = this.id;
|
||||
this.iframe.scrolling = "no";
|
||||
this.iframe.seamless = "seamless";
|
||||
// Back up if seamless isn't supported
|
||||
this.iframe.style.border = "none";
|
||||
this.iframe.width = "100%";
|
||||
this.iframe.height = "100%";
|
||||
// this.iframe.addEventListener("load", this.loaded.bind(this), false);
|
||||
this.iframe.style.display = "none";
|
||||
this.iframe.style.visibility = "hidden";
|
||||
|
||||
return this.iframe;
|
||||
};
|
||||
|
||||
EPUBJS.View.prototype.layout = function() {
|
||||
this.height = this.document.documentElement.getBoundingClientRect().height;
|
||||
this.width = this.document.documentElement.getBoundingClientRect().width;
|
||||
this.iframe.style.height = this.height + "px";
|
||||
};
|
||||
|
||||
EPUBJS.View.prototype.appendTo = function(element) {
|
||||
element.appendChild(this.iframe);
|
||||
};
|
||||
|
||||
EPUBJS.View.prototype.prependTo = function(element) {
|
||||
element.insertBefore(this.iframe, element.firstChild);
|
||||
};
|
||||
|
||||
EPUBJS.View.prototype.destroy = function() {
|
||||
|
||||
};
|
|
@ -12,18 +12,22 @@
|
|||
|
||||
<script src="../lib/epub.js"></script>
|
||||
<script src="../lib/epubjs/core.js"></script>
|
||||
<script src="../lib/epubjs/hooks.js"></script>
|
||||
<script src="../lib/epubjs/book.js"></script>
|
||||
<script src="../lib/epubjs/parser.js"></script>
|
||||
<script src="../lib/epubjs/spine.js"></script>
|
||||
<script src="../lib/epubjs/navigation.js"></script>
|
||||
<script src="../lib/epubjs/epubcfi.js"></script>
|
||||
<script src="../lib/epubjs/renderer.js"></script>
|
||||
<script src="../lib/epubjs/view.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
|
||||
|
||||
<script src="tests/epub.js"></script>
|
||||
<script src="tests/rendering.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
15
test/tests/rendering.js
Normal file
15
test/tests/rendering.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
module('Rendering');
|
||||
|
||||
asyncTest("Render To", 1, function() {
|
||||
|
||||
var book = ePub("../books/moby-dick/OPS/package.opf");
|
||||
var rendition = book.renderTo("qunit-fixture");
|
||||
var displayed = rendition.display();
|
||||
|
||||
displayed.then(function(){
|
||||
equal( $( "iframe", "#qunit-fixture" ).length, 1, "iframe added successfully" );
|
||||
start();
|
||||
});
|
||||
|
||||
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue