diff --git a/examples/hypothesis.html b/examples/hypothesis.html
index 3af9ad6..0cf17ae 100755
--- a/examples/hypothesis.html
+++ b/examples/hypothesis.html
@@ -58,7 +58,6 @@
-
diff --git a/reader_src/controllers/notes_controller.js b/reader_src/controllers/notes_controller.js
index b0c6e5a..fe88dd9 100644
--- a/reader_src/controllers/notes_controller.js
+++ b/reader_src/controllers/notes_controller.js
@@ -105,16 +105,16 @@ EPUBJS.reader.NotesController = function() {
marker.style.verticalAlign = "super";
marker.style.fontSize = ".75em";
- marker.style.position = "relative";
+ // marker.style.position = "relative";
marker.style.lineHeight = "1em";
- mark.style.display = "inline-block";
+ // mark.style.display = "inline-block";
mark.style.padding = "2px";
mark.style.backgroundColor = "#fffa96";
mark.style.borderRadius = "5px";
mark.style.cursor = "pointer";
- marker.id = annotation.anchor;
+ marker.id = "note-"+EPUBJS.core.uuid();
mark.innerHTML = annotations.indexOf(annotation) + 1 + "[Reader]";
marker.appendChild(mark);
diff --git a/reader_src/controllers/reader_controller.js b/reader_src/controllers/reader_controller.js
index c44c3d9..ece295b 100644
--- a/reader_src/controllers/reader_controller.js
+++ b/reader_src/controllers/reader_controller.js
@@ -101,6 +101,14 @@ EPUBJS.reader.ReaderController = function(book) {
}
});
+ // book.on("book:atStart", function(){
+ // $prev.addClass("disabled");
+ // });
+ //
+ // book.on("book:atEnd", function(){
+ // $next.addClass("disabled");
+ // });
+
return {
"slideOut" : slideOut,
"slideIn" : slideIn,
diff --git a/reader_src/reader.js b/reader_src/reader.js
index 5c1061c..3ec82e5 100644
--- a/reader_src/reader.js
+++ b/reader_src/reader.js
@@ -33,17 +33,6 @@ EPUBJS.Reader = function(bookPath, _options) {
var $viewer = $("#viewer");
var search = window.location.search;
var parameters;
-
- // Overide options with search parameters
- if(search) {
- parameters = search.slice(1).split("&");
- parameters.forEach(function(p){
- var split = p.split("=");
- var name = split[0];
- var value = split[1] || '';
- _options[name] = value;
- });
- }
this.settings = _.defaults(_options || {}, {
bookPath : bookPath,
@@ -58,8 +47,19 @@ EPUBJS.Reader = function(bookPath, _options) {
generatePagination: false,
history: true
});
-
- this.setBookKey(bookPath); //-- This could be username + path or any unique string
+
+ // Overide options with search parameters
+ if(search) {
+ parameters = search.slice(1).split("&");
+ parameters.forEach(function(p){
+ var split = p.split("=");
+ var name = split[0];
+ var value = split[1] || '';
+ reader.settings[name] = value;
+ });
+ }
+
+ this.setBookKey(this.settings.bookPath); //-- This could be username + path or any unique string
if(this.settings.restore && this.isSaved()) {
this.applySavedSettings();
diff --git a/src/epubcfi.js b/src/epubcfi.js
index f566209..55e3c6a 100644
--- a/src/epubcfi.js
+++ b/src/epubcfi.js
@@ -121,7 +121,7 @@ EPUBJS.EpubCFI.prototype.parse = function(cfiStr) {
cfi.str = cfiStr;
- if(cfiStr.indexOf("epubcfi(") === 0) {
+ if(cfiStr.indexOf("epubcfi(") === 0 && cfiStr[cfiStr.length-1] === ")") {
// Remove intial epubcfi( and ending )
cfiStr = cfiStr.slice(8, cfiStr.length-1);
}
@@ -172,7 +172,7 @@ EPUBJS.EpubCFI.prototype.parse = function(cfiStr) {
} else {
cfi.steps.push({
"type" : "text",
- 'index' : parseInt(end) - 1,
+ 'index' : (endInt - 1 ) / 2
});
}
@@ -384,7 +384,7 @@ EPUBJS.EpubCFI.prototype.generateCfiFromTextNode = function(anchor, offset, base
var parent = anchor.parentElement;
var steps = this.pathTo(parent);
var path = this.generatePathComponent(steps);
- var index = [].slice.apply(parent.childNodes).indexOf(anchor) + 1;
+ var index = 1 + (2 * Array.prototype.indexOf.call(parent.childNodes, anchor));
return "epubcfi(" + base + "!" + path + "/"+index+":"+(offset || 0)+")";
};
@@ -394,3 +394,64 @@ EPUBJS.EpubCFI.prototype.generateCfiFromRangeAnchor = function(range, base) {
return this.generateCfiFromTextNode(anchor, offset, base);
};
+EPUBJS.EpubCFI.prototype.generateXpathFromSteps = function(steps) {
+ var xpath = [".", "*"];
+
+ steps.forEach(function(step){
+ var position = step.index + 1;
+
+ if(step.id){
+ xpath.push("*[position()=" + position + " and @id='" + step.id + "']");
+ } else if(step.type === "text") {
+ xpath.push("text()[" + position + "]");
+ } else {
+ xpath.push("*[" + position + "]");
+ }
+ });
+
+ return xpath.join("/");
+};
+
+
+EPUBJS.EpubCFI.prototype.generateRangeFromCfi = function(cfi, _doc) {
+ var doc = _doc || document;
+ var range = doc.createRange();
+ var lastStep;
+ var xpath;
+ var startContainer;
+ var textLength;
+
+ if(typeof cfi === 'string') {
+ cfi = this.parse(cfi);
+ }
+
+ // check spinePos
+ if(cfi.spinePos === -1) {
+ // Not a valid CFI
+ return false;
+ }
+
+ xpath = this.generateXpathFromSteps(cfi.steps);
+
+ // Get the terminal step
+ lastStep = cfi.steps[cfi.steps.length-1];
+ startContainer = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
+ if(!startContainer) {
+ return null;
+ }
+
+ if(startContainer && cfi.characterOffset >= 0) {
+ textLength = startContainer.length;
+ if(cfi.characterOffset < textLength) {
+ range.setStart(startContainer, cfi.characterOffset);
+ range.setEnd(startContainer, textLength );
+ } else {
+ range.setStart(startContainer, cfi.characterOffset - 1 );
+ range.setEnd(startContainer, cfi.characterOffset );
+ }
+ } else if(startContainer) {
+ range.selectNode(startContainer);
+ }
+ // doc.defaultView.getSelection().addRange(range);
+ return range;
+};
diff --git a/src/layout.js b/src/layout.js
index d28e875..5118457 100644
--- a/src/layout.js
+++ b/src/layout.js
@@ -12,11 +12,10 @@ EPUBJS.Layout.Reflowable.prototype.format = function(documentElement, _width, _h
var columnWidth = EPUBJS.core.prefixed('columnWidth');
//-- Check the width and create even width columns
- var fullWidth = Math.floor(_width);
- var width = (fullWidth % 2 === 0) ? fullWidth : fullWidth - 1;
+ var width = Math.floor(_width);
+ // var width = (fullWidth % 2 === 0) ? fullWidth : fullWidth - 0; // Not needed for single
var section = Math.floor(width / 8);
var gap = (section % 2 === 0) ? section : section - 1;
-
this.documentElement = documentElement;
//-- Single Page
this.spreadWidth = (width + gap);
@@ -32,8 +31,8 @@ EPUBJS.Layout.Reflowable.prototype.format = function(documentElement, _width, _h
//-- Add columns
documentElement.style[columnAxis] = "horizontal";
- documentElement.style[columnGap] = gap+"px";
documentElement.style[columnWidth] = width+"px";
+ documentElement.style[columnGap] = gap+"px";
return {
pageWidth : this.spreadWidth,
@@ -69,6 +68,7 @@ EPUBJS.Layout.ReflowableSpreads.prototype.format = function(documentElement, _wi
//-- Check the width and create even width columns
var fullWidth = Math.floor(_width);
var width = (fullWidth % 2 === 0) ? fullWidth : fullWidth - 1;
+
var section = Math.floor(width / 8);
var gap = (section % 2 === 0) ? section : section - 1;
//-- Double Page
diff --git a/src/render_iframe.js b/src/render_iframe.js
index 8af29e0..f4bf40b 100644
--- a/src/render_iframe.js
+++ b/src/render_iframe.js
@@ -163,6 +163,16 @@ EPUBJS.Render.Iframe.prototype.getPageNumberByElement = function(el){
return pg;
};
+//-- Show the page containing an Element
+EPUBJS.Render.Iframe.prototype.getPageNumberByRect = function(boundingClientRect){
+ var left, pg;
+
+ left = this.leftPos + boundingClientRect.left; //-- Calculate left offset compaired to scrolled position
+ pg = Math.floor(left / this.pageWidth) + 1; //-- pages start at 1
+
+ return pg;
+};
+
// Return the root element of the content
EPUBJS.Render.Iframe.prototype.getBaseElement = function(){
return this.bodyEl;
diff --git a/src/renderer.js b/src/renderer.js
index ee4c615..3b33fb8 100644
--- a/src/renderer.js
+++ b/src/renderer.js
@@ -452,19 +452,28 @@ EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){
// Goto a cfi position in the current chapter
EPUBJS.Renderer.prototype.gotoCfi = function(cfi){
- var element;
var pg;
+ var marker;
+ var range;
if(_.isString(cfi)){
cfi = this.epubcfi.parse(cfi);
}
-
- marker = this.epubcfi.addMarker(cfi, this.doc);
- if(marker) {
- pg = this.render.getPageNumberByElement(marker);
- // Must Clean up Marker before going to page
- this.epubcfi.removeMarker(marker, this.doc);
- this.page(pg);
+
+ if(typeof document.evaluate === 'undefined') {
+ marker = this.epubcfi.addMarker(cfi, this.doc);
+ if(marker) {
+ pg = this.render.getPageNumberByElement(marker);
+ // Must Clean up Marker before going to page
+ this.epubcfi.removeMarker(marker, this.doc);
+ this.page(pg);
+ }
+ } else {
+ var range = this.epubcfi.generateRangeFromCfi(cfi, this.doc);
+ if(range) {
+ pg = this.render.getPageNumberByRect(range.getBoundingClientRect());
+ this.page(pg);
+ }
}
};
diff --git a/tests/epubcfi.js b/tests/epubcfi.js
index 8fdfe19..d234a07 100644
--- a/tests/epubcfi.js
+++ b/tests/epubcfi.js
@@ -78,4 +78,32 @@ test("Compare CFI's", null, function() {
equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/8/5:1)", "epubcfi(/6/2[cover]!/4/6/15:2)"), 1, "First Element is greater");
equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/8/1:0)", "epubcfi(/6/2[cover]!/4/8/1:0)"), 0, "All Equal");
-})
\ No newline at end of file
+});
+
+test("Generate XPath from Steps", null, function() {
+ var epubcfi = new EPUBJS.EpubCFI();
+ var cfi = epubcfi.parse("epubcfi(/6/12[xepigraph_001]!4/2/8[extracts]/1:0)");
+ var xpath = epubcfi.generateXpathFromSteps(cfi.steps);
+
+ equal(xpath, "./*/*[2]/*[1]/*[position()=4 and @id='extracts']/text()[1]", "Correct Xpath Generated");
+
+});
+
+
+asyncTest("Generate Range from CFI", 1, function() {
+ var book = ePub('/reader/moby-dick/', { width: 400, height: 600 });
+
+ var render = book.renderTo("qunit-fixture");
+
+ var result = function(){
+ var displayed = book.gotoHref("epigraph_001.xhtml");
+ displayed.then(function(){
+ var epubcfi = new EPUBJS.EpubCFI();
+ var range = epubcfi.generateRangeFromCfi("epubcfi(/6/12[xepigraph_001]!4/2/8[extracts]/1:0)", book.renderer.doc);
+ equal( range.startContainer.data, "Extracts.", "Anchor is correct" );
+ start();
+ });
+ };
+
+ render.then(result);
+});
\ No newline at end of file
diff --git a/tools/server b/tools/server
new file mode 100755
index 0000000..ca55cda
--- /dev/null
+++ b/tools/server
@@ -0,0 +1,45 @@
+#!/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,
+ 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(!logger) server.use(connect.logger(logger))
+
+ server.listen(port);
+
+ log('Starting up Server, serving '.yellow
+ + __dirname.replace("tools", '').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();
+});