1
0
Fork 0
mirror of https://github.com/futurepress/epub.js.git synced 2025-10-04 15:09:16 +02:00

basic scrolling renderer

This commit is contained in:
Fred Chasen 2014-07-31 17:25:56 -04:00
parent 849625fc83
commit b1b98f9d57
15 changed files with 1020 additions and 22 deletions

View file

@ -8,11 +8,14 @@
<script src="../lib/epub.js"></script> <script src="../lib/epub.js"></script>
<script src="../lib/epubjs/core.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/book.js"></script>
<script src="../lib/epubjs/parser.js"></script> <script src="../lib/epubjs/parser.js"></script>
<script src="../lib/epubjs/spine.js"></script> <script src="../lib/epubjs/spine.js"></script>
<script src="../lib/epubjs/navigation.js"></script> <script src="../lib/epubjs/navigation.js"></script>
<script src="../lib/epubjs/epubcfi.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"> <style type="text/css">
body { body {
@ -77,7 +80,7 @@
var $next = document.getElementById("next"); var $next = document.getElementById("next");
var $prev = document.getElementById("prev"); var $prev = document.getElementById("prev");
var currentSection; var currentSection;
var currentSectionIndex = 7; var currentSectionIndex = 6;
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.loaded.navigation.then(function(toc){ book.loaded.navigation.then(function(toc){

127
examples/basic-render.html Normal file
View 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>

View file

@ -3,7 +3,7 @@ if (typeof EPUBJS === 'undefined') {
} }
EPUBJS.VERSION = "0.3.0"; EPUBJS.VERSION = "0.3.0";
EPUBJS.Render = {};
(function(root) { (function(root) {
"use strict"; "use strict";

View file

@ -2,6 +2,7 @@ EPUBJS.Book = function(_url){
// Promises // Promises
this.opening = new RSVP.defer(); this.opening = new RSVP.defer();
this.opened = this.opening.promise; this.opened = this.opening.promise;
this.isOpen = false;
this.url = undefined; this.url = undefined;
@ -25,17 +26,11 @@ EPUBJS.Book = function(_url){
pageList: this.loading.pageList.promise pageList: this.loading.pageList.promise
}; };
this.loaders = []; this.ready = RSVP.hash(this.loaded);
for(var promise in this.loaded){
this.loaders.push(this.loaded[promise]);
}
this.ready = RSVP.all(this.loaders); // Queue for methods used before opening
this.isRendered = false;
// this.pageList = []; this._q = EPUBJS.core.queue(this);
// this.ready.all.then(this._ready.bind(this));
if(_url) { if(_url) {
this.open(_url); this.open(_url);
@ -48,6 +43,7 @@ EPUBJS.Book.prototype.open = function(_url){
var epubPackage; var epubPackage;
var book = this; var book = this;
var containerPath = "META-INF/container.xml"; var containerPath = "META-INF/container.xml";
var location;
// Reuse parsed url or create a new uri object // Reuse parsed url or create a new uri object
if(typeof(_url) === "object") { if(typeof(_url) === "object") {
@ -64,6 +60,9 @@ EPUBJS.Book.prototype.open = function(_url){
if(uri.origin) { if(uri.origin) {
this.url = uri.origin + "/" + uri.directory; 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 { } else {
this.url = uri.directory; this.url = uri.directory;
} }
@ -111,11 +110,13 @@ EPUBJS.Book.prototype.open = function(_url){
book.loading.spine.resolve(book.spine); book.loading.spine.resolve(book.spine);
book.loading.cover.resolve(book.cover); book.loading.cover.resolve(book.cover);
// Resolve book opened promise this.isOpen = true;
book.opening.resolve(book);
// Clear queue of any waiting book request // Clear queue of any waiting book request
// Resolve book opened promise
book.opening.resolve(book);
}).catch(function(error) { }).catch(function(error) {
// handle errors in parsing the book // handle errors in parsing the book
console.error(error.message, error.stack); console.error(error.message, error.stack);
@ -152,6 +153,13 @@ EPUBJS.Book.prototype.section = function(target) {
return this.spine.get(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) { EPUBJS.Book.prototype.request = function(_url) {
// Switch request methods // Switch request methods
if(this.archived) { if(this.archived) {

View file

@ -154,3 +154,107 @@ EPUBJS.core.folder = function(url){
return folder; 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
View 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
View 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
View 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
View 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);
};

View 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
View 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];
};

View file

@ -37,13 +37,13 @@ EPUBJS.Spine = function(_package, _request){
// book.spine.get("chap1.html"); // book.spine.get("chap1.html");
// book.spine.get("#id1234"); // book.spine.get("#id1234");
EPUBJS.Spine.prototype.get = function(target) { EPUBJS.Spine.prototype.get = function(target) {
var index = 1; var index = 0;
if(typeof target === "number" || isNaN(target) === false){ if(target && (typeof target === "number" || isNaN(target) === false)){
index = target-1; index = target;
} else if(target.indexOf("#") === 0) { } else if(target && target.indexOf("#") === 0) {
index = this.spineById[target.substring(1)]; index = this.spineById[target.substring(1)];
} else { } else if(target) {
index = this.spineByHref[target]; index = this.spineByHref[target];
} }
@ -71,7 +71,13 @@ EPUBJS.SpineItem.prototype.load = function(_request){
loading.resolve(this.contents); loading.resolve(this.contents);
} else { } else {
request(this.url, 'xml').then(function(xml){ request(this.url, 'xml').then(function(xml){
var base;
var directory = EPUBJS.core.folder(this.url);
this.document = xml;
this.contents = xml.documentElement; this.contents = xml.documentElement;
this.replacements(this.document);
loading.resolve(this.contents); loading.resolve(this.contents);
}.bind(this)); }.bind(this));
} }
@ -79,11 +85,23 @@ EPUBJS.SpineItem.prototype.load = function(_request){
return loaded; 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(){ 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(); var serializer = new XMLSerializer();
return serializer.serializeToString(contents); var output = serializer.serializeToString(contents);
rendering.resolve(output);
}); });
return rendered;
}; };
EPUBJS.SpineItem.prototype.find = function(_query){ EPUBJS.SpineItem.prototype.find = function(_query){

87
lib/epubjs/view.js Normal file
View 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() {
};

View file

@ -12,11 +12,14 @@
<script src="../lib/epub.js"></script> <script src="../lib/epub.js"></script>
<script src="../lib/epubjs/core.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/book.js"></script>
<script src="../lib/epubjs/parser.js"></script> <script src="../lib/epubjs/parser.js"></script>
<script src="../lib/epubjs/spine.js"></script> <script src="../lib/epubjs/spine.js"></script>
<script src="../lib/epubjs/navigation.js"></script> <script src="../lib/epubjs/navigation.js"></script>
<script src="../lib/epubjs/epubcfi.js"></script> <script src="../lib/epubjs/epubcfi.js"></script>
<script src="../lib/epubjs/renderer.js"></script>
<script src="../lib/epubjs/view.js"></script>
</head> </head>
<body> <body>
@ -24,6 +27,7 @@
<div id="qunit-fixture"></div> <div id="qunit-fixture"></div>
<script src="tests/epub.js"></script> <script src="tests/epub.js"></script>
<script src="tests/rendering.js"></script>
</body> </body>
</html> </html>

15
test/tests/rendering.js Normal file
View 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();
});
});