epubjs
Version:
Render ePub documents in the browser, across many devices
245 lines (194 loc) • 6.03 kB
HTML
<html>
<head>
<meta charset="utf-8">
<title>EPUB.js Basic Example</title>
<script src="../dist/epub.js"></script>
<style type="text/css">
body {
margin: 0;
background: #fafafa;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #333;
}
#viewer {
display: block;
margin: 0;
width: 100%;
height: 100%;
}
#viewer iframe {
background: white;
box-shadow: 0 0 4px #ccc;
width: 590px;
margin: 10px auto;
}
#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>
<div id="viewer"></div>
<script type="text/javascript">
var OReader = OReader || {};
OReader.Stitcher = {};
OReader.Stitcher.resolver = function(prefix) {
var ns = {
'xhtml' : 'http://www.w3.org/1999/xhtml',
'mathml': 'http://www.w3.org/1998/Math/MathML'
};
return ns[prefix] || null;
};
OReader.Stitcher.parsePart = function(partString) {
var tokens = partString.split("["); // Split string into element and other
var attributes = {};
var part = {
"string" : "xhtml:" + partString,
"attributes" : attributes,
"node" : tokens[0],
"offset" : 1
};
var attrString;
var re = /\@([^=]+)=[\'\"]([^\'^\"]+)[\'\"]/g;
var match;
// Part muight have additional information such as id or offset
if(tokens[1]){
// remove the last part
attrString = tokens[1].replace(']', '');
// If there is an offset it will be numerical
if(!isNaN(parseFloat(attrString)) && isFinite(attrString)){ // is a number
part.offset = parseInt(attrString);
} else {
// Run through string looking for @key=value paris
do {
match = re.exec(attrString);
if (match) {
// Add pairs to attributes object
attributes[match[1]] = match[2];
}
} while (match);
}
}
return part;
};
OReader.Stitcher.parseXpath = function(_xpath){
// Split path into parts
var parts = _xpath.substring(1).split("/");
var xpath = [];
// Parse each part and add to xpath array
parts.forEach(function(part){
var parsed = OReader.Stitcher.parsePart(part);
xpath.push(parsed);
});
return xpath;
};
OReader.Stitcher.createElement = function(part, _doc){
var doc = _doc || document;
var element = doc.createElement(part.node);
for (var attribute in part.attributes){
if (part.attributes.hasOwnProperty(attribute)) {
element.setAttribute(attribute, part.attributes[attribute]);
}
}
return element;
};
OReader.Stitcher.rebuild = function(_xpath, doc, payload){
var xpath = OReader.Stitcher.parseXpath(_xpath);
var walked = [];
var fragment = document.createDocumentFragment();
var prevElement;
var existingElement;
// Process xpath parts
xpath.forEach(function(part){
var present;
var element;
walked.push(part.string);
// Check if part is present in DOM
present = doc.evaluate("./"+walked.join('/'), doc, OReader.Stitcher.resolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if(!present) {
// Create the element, add attributes
element = OReader.Stitcher.createElement(part, doc);
if(prevElement) {
// Add to previously created element
prevElement.appendChild(element);
} else {
fragment.appendChild(element);
}
// Continue
prevElement = element;
} else {
// Continue, adding to
existingElement = present;
}
});
// // Add the wrapper last
if(prevElement) {
// wrap the current payload in element
while (payload.childNodes.length > 0) {
if(payload.childNodes[0] != prevElement){
prevElement.appendChild(payload.childNodes[0]);
}
}
}
if(existingElement) {
existingElement.appendChild(fragment);
}
return fragment;
};
</script>
<script>;
// Load the opf
var book = ePub("../books/9781565922259/content.opf");
// Where to render to
var element = document.getElementById("viewer");
// Give the renderer an id or element to render to - takes an options such as size {width: 400, height: 600}
var rendition = book.renderTo(element);
// Display a section -> takes spineIndex, #id or chapter.html
var displayed = rendition.display("7.xhtml");
// Register the hook for rebuilding the dom
rendition.hooks.display.register(function(view){
var task = new RSVP.defer(); // Create a defer to return
// Get the orginal xpath of the chunk
var chunk = view.document.body;
var pathElement = view.document.head.querySelector("meta[name='data-origPath']");
var path = pathElement.getAttribute('value');
if(path){
// Rebuild the DOM, insert current chunk to orginal position
OReader.Stitcher.rebuild(path, view.document, chunk);
}
// Resolve defer since all tasks are finished
task.resolve();
// Hook must return a promise
return task.promise;
});
</script>
</body>
</html>