mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-04 15:09:16 +02:00
Cleaned up highlighting example, epubcfi ignoreClass option
This commit is contained in:
parent
9d6d16683c
commit
3a21665e80
10 changed files with 167 additions and 476 deletions
278
dist/epub.js
vendored
278
dist/epub.js
vendored
|
@ -4313,14 +4313,13 @@ Book.prototype.coverUrl = function(){
|
||||||
return retrieved;
|
return retrieved;
|
||||||
};
|
};
|
||||||
|
|
||||||
Book.prototype.getTextFromCfiRange = function(cfiRange) {
|
Book.prototype.selectCfiRange = function(cfiRange) {
|
||||||
var cfi = new EpubCFI(cfiRange);
|
var cfi = new EpubCFI(cfiRange);
|
||||||
var item = this.spine.get(cfi.spinePos)
|
var item = this.spine.get(cfi.spinePos)
|
||||||
|
|
||||||
return item.load().then(function (contents) {
|
return item.load().then(function (contents) {
|
||||||
var range = cfi.toRange(item.document);
|
var range = cfi.toRange(item.document);
|
||||||
var text = range.toString();
|
return range;
|
||||||
return text;
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4342,7 +4341,7 @@ RSVP.on('rejected', function(event){
|
||||||
console.error(event.detail.message, event.detail.stack);
|
console.error(event.detail.message, event.detail.stack);
|
||||||
});
|
});
|
||||||
|
|
||||||
},{"./continuous":7,"./core":8,"./epubcfi":9,"./locations":13,"./navigation":15,"./paginate":16,"./parser":17,"./rendition":19,"./request":21,"./spine":23,"./unarchive":24,"rsvp":4,"urijs":5}],7:[function(require,module,exports){
|
},{"./continuous":7,"./core":8,"./epubcfi":9,"./locations":12,"./navigation":14,"./paginate":15,"./parser":16,"./rendition":18,"./request":20,"./spine":22,"./unarchive":23,"rsvp":4,"urijs":5}],7:[function(require,module,exports){
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
var Rendition = require('./rendition');
|
var Rendition = require('./rendition');
|
||||||
|
@ -4762,7 +4761,7 @@ Continuous.prototype.current = function(what){
|
||||||
|
|
||||||
module.exports = Continuous;
|
module.exports = Continuous;
|
||||||
|
|
||||||
},{"./core":8,"./rendition":19,"./view":25,"rsvp":4}],8:[function(require,module,exports){
|
},{"./core":8,"./rendition":18,"./view":24,"rsvp":4}],8:[function(require,module,exports){
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
|
|
||||||
var requestAnimationFrame = (typeof window != 'undefined') ? (window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame) : false;
|
var requestAnimationFrame = (typeof window != 'undefined') ? (window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame) : false;
|
||||||
|
@ -5221,11 +5220,8 @@ var core = require('./core');
|
||||||
- Text Location Assertion ([)
|
- Text Location Assertion ([)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function EpubCFI(cfiFrom, base, options){
|
function EpubCFI(cfiFrom, base, ignoreClass){
|
||||||
var type;
|
var type;
|
||||||
this.options = {
|
|
||||||
ignoreClass: 'annotator-hl'
|
|
||||||
};
|
|
||||||
|
|
||||||
this.str = '';
|
this.str = '';
|
||||||
|
|
||||||
|
@ -5240,25 +5236,9 @@ function EpubCFI(cfiFrom, base, options){
|
||||||
|
|
||||||
// Allow instantiation without the 'new' keyword
|
// Allow instantiation without the 'new' keyword
|
||||||
if (!(this instanceof EpubCFI)) {
|
if (!(this instanceof EpubCFI)) {
|
||||||
return new EpubCFI(cfiFrom, base, options);
|
return new EpubCFI(cfiFrom, base, ignoreClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find options
|
|
||||||
for (var i = 1, length = arguments.length; i < length; i++) {
|
|
||||||
if(typeof arguments[i] === 'object' && (arguments[i].ignoreClass)) {
|
|
||||||
core.extend(this.options, arguments[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* TODO: maybe accept object that includes:
|
|
||||||
{
|
|
||||||
spineNodeIndex: <int>
|
|
||||||
index: <int>
|
|
||||||
idref: <string:optional>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if(typeof base === 'string') {
|
if(typeof base === 'string') {
|
||||||
this.base = this.parseComponent(base);
|
this.base = this.parseComponent(base);
|
||||||
} else if(typeof base === 'object' && base.steps) {
|
} else if(typeof base === 'object' && base.steps) {
|
||||||
|
@ -5272,9 +5252,9 @@ function EpubCFI(cfiFrom, base, options){
|
||||||
this.str = cfiFrom;
|
this.str = cfiFrom;
|
||||||
return core.extend(this, this.parse(cfiFrom));
|
return core.extend(this, this.parse(cfiFrom));
|
||||||
} else if (type === 'range') {
|
} else if (type === 'range') {
|
||||||
return core.extend(this, this.fromRange(cfiFrom, this.base));
|
return core.extend(this, this.fromRange(cfiFrom, this.base, ignoreClass));
|
||||||
} else if (type === 'node') {
|
} else if (type === 'node') {
|
||||||
return core.extend(this, this.fromNode(cfiFrom, this.base));
|
return core.extend(this, this.fromNode(cfiFrom, this.base, ignoreClass));
|
||||||
} else if (type === 'EpubCFI' && cfiFrom.path) {
|
} else if (type === 'EpubCFI' && cfiFrom.path) {
|
||||||
return cfiFrom;
|
return cfiFrom;
|
||||||
} else if (!cfiFrom) {
|
} else if (!cfiFrom) {
|
||||||
|
@ -5664,7 +5644,7 @@ EpubCFI.prototype.equalStep = function(stepA, stepB) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
EpubCFI.prototype.fromRange = function(range, base) {
|
EpubCFI.prototype.fromRange = function(range, base, ignoreClass) {
|
||||||
var cfi = {
|
var cfi = {
|
||||||
range: false,
|
range: false,
|
||||||
base: {},
|
base: {},
|
||||||
|
@ -5679,15 +5659,14 @@ EpubCFI.prototype.fromRange = function(range, base) {
|
||||||
var startOffset = range.startOffset;
|
var startOffset = range.startOffset;
|
||||||
var endOffset = range.endOffset;
|
var endOffset = range.endOffset;
|
||||||
|
|
||||||
var needsIgnoring = (start.ownerDocument.querySelector('.' + this.options.ignoreClass) != null);
|
var needsIgnoring = false;
|
||||||
var ignoreClass;
|
|
||||||
// Tell pathTo if / what to ignore
|
if (ignoreClass) {
|
||||||
if (needsIgnoring) {
|
// Tell pathTo if / what to ignore
|
||||||
ignoreClass = this.options.ignoreClass
|
needsIgnoring = (start.ownerDocument.querySelector('.' + ignoreClass) != null);
|
||||||
} else {
|
|
||||||
ignoreClass = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (typeof base === 'string') {
|
if (typeof base === 'string') {
|
||||||
cfi.base = this.parseComponent(base);
|
cfi.base = this.parseComponent(base);
|
||||||
cfi.spinePos = cfi.base.steps[1].index;
|
cfi.spinePos = cfi.base.steps[1].index;
|
||||||
|
@ -5753,7 +5732,7 @@ EpubCFI.prototype.fromRange = function(range, base) {
|
||||||
return cfi;
|
return cfi;
|
||||||
}
|
}
|
||||||
|
|
||||||
EpubCFI.prototype.fromNode = function(anchor, base) {
|
EpubCFI.prototype.fromNode = function(anchor, base, ignoreClass) {
|
||||||
var cfi = {
|
var cfi = {
|
||||||
range: false,
|
range: false,
|
||||||
base: {},
|
base: {},
|
||||||
|
@ -5762,13 +5741,11 @@ EpubCFI.prototype.fromNode = function(anchor, base) {
|
||||||
end: null
|
end: null
|
||||||
};
|
};
|
||||||
|
|
||||||
var needsIgnoring = (anchor.ownerDocument.querySelector('.' + this.options.ignoreClass) != null);
|
var needsIgnoring = false;
|
||||||
var ignoreClass;
|
|
||||||
// Tell pathTo if / what to ignore
|
if (ignoreClass) {
|
||||||
if (needsIgnoring) {
|
// Tell pathTo if / what to ignore
|
||||||
ignoreClass = this.options.ignoreClass
|
needsIgnoring = (anchor.ownerDocument.querySelector('.' + ignoreClass) != null);
|
||||||
} else {
|
|
||||||
ignoreClass = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof base === 'string') {
|
if (typeof base === 'string') {
|
||||||
|
@ -6021,18 +5998,16 @@ EpubCFI.prototype.walkToNode = function(steps, _doc, ignoreClass) {
|
||||||
return container;
|
return container;
|
||||||
};
|
};
|
||||||
|
|
||||||
EpubCFI.prototype.findNode = function(steps, _doc) {
|
EpubCFI.prototype.findNode = function(steps, _doc, ignoreClass) {
|
||||||
var doc = _doc || document;
|
var doc = _doc || document;
|
||||||
var container;
|
var container;
|
||||||
var xpath;
|
var xpath;
|
||||||
// Check if we might need to need to fix missed results
|
|
||||||
var needsIgnoring = (doc.querySelector('.' + this.options.ignoreClass) != null);
|
|
||||||
|
|
||||||
if(!needsIgnoring && typeof doc.evaluate != 'undefined') {
|
if(!ignoreClass && typeof doc.evaluate != 'undefined') {
|
||||||
xpath = this.stepsToXpath(steps);
|
xpath = this.stepsToXpath(steps);
|
||||||
container = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
container = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||||
} else if(needsIgnoring) {
|
} else if(ignoreClass) {
|
||||||
container = this.walkToNode(steps, doc, this.options.ignoreClass);
|
container = this.walkToNode(steps, doc, ignoreClass);
|
||||||
} else {
|
} else {
|
||||||
container = this.walkToNode(steps, doc);
|
container = this.walkToNode(steps, doc);
|
||||||
}
|
}
|
||||||
|
@ -6041,7 +6016,7 @@ EpubCFI.prototype.findNode = function(steps, _doc) {
|
||||||
};
|
};
|
||||||
|
|
||||||
EpubCFI.prototype.fixMiss = function(steps, offset, _doc, ignoreClass) {
|
EpubCFI.prototype.fixMiss = function(steps, offset, _doc, ignoreClass) {
|
||||||
var container = this.findNode(steps.slice(0,-1), _doc);
|
var container = this.findNode(steps.slice(0,-1), _doc, ignoreClass);
|
||||||
var children = container.childNodes;
|
var children = container.childNodes;
|
||||||
var map = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass);
|
var map = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass);
|
||||||
var i;
|
var i;
|
||||||
|
@ -6076,25 +6051,26 @@ EpubCFI.prototype.fixMiss = function(steps, offset, _doc, ignoreClass) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EpubCFI.prototype.toRange = function(_doc, _cfi) {
|
EpubCFI.prototype.toRange = function(_doc, ignoreClass) {
|
||||||
var doc = _doc || document;
|
var doc = _doc || document;
|
||||||
var range = doc.createRange();
|
var range = doc.createRange();
|
||||||
var start, end, startContainer, endContainer;
|
var start, end, startContainer, endContainer;
|
||||||
var cfi = _cfi || this;
|
var cfi = this;
|
||||||
var startSteps, endSteps;
|
var startSteps, endSteps;
|
||||||
|
var needsIgnoring = ignoreClass ? (doc.querySelector('.' + ignoreClass) != null) : false;
|
||||||
var missed;
|
var missed;
|
||||||
|
|
||||||
if (cfi.range) {
|
if (cfi.range) {
|
||||||
start = cfi.start;
|
start = cfi.start;
|
||||||
startSteps = cfi.path.steps.concat(start.steps);
|
startSteps = cfi.path.steps.concat(start.steps);
|
||||||
startContainer = this.findNode(startSteps, doc);
|
startContainer = this.findNode(startSteps, doc, needsIgnoring ? ignoreClass : null);
|
||||||
end = cfi.end;
|
end = cfi.end;
|
||||||
endSteps = cfi.path.steps.concat(end.steps);
|
endSteps = cfi.path.steps.concat(end.steps);
|
||||||
endContainer = this.findNode(endSteps, doc);
|
endContainer = this.findNode(endSteps, doc, needsIgnoring ? ignoreClass : null);
|
||||||
} else {
|
} else {
|
||||||
start = cfi.path;
|
start = cfi.path;
|
||||||
startSteps = cfi.path.steps;
|
startSteps = cfi.path.steps;
|
||||||
startContainer = this.findNode(cfi.path.steps, doc);
|
startContainer = this.findNode(cfi.path.steps, doc, needsIgnoring ? ignoreClass : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6109,7 +6085,7 @@ EpubCFI.prototype.toRange = function(_doc, _cfi) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
missed = this.fixMiss(startSteps, start.terminal.offset, doc, this.options.ignoreClass);
|
missed = this.fixMiss(startSteps, start.terminal.offset, doc, needsIgnoring ? ignoreClass : null);
|
||||||
range.setStart(missed.container, missed.offset);
|
range.setStart(missed.container, missed.offset);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -6128,7 +6104,7 @@ EpubCFI.prototype.toRange = function(_doc, _cfi) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
missed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, this.options.ignoreClass);
|
missed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, needsIgnoring ? ignoreClass : null);
|
||||||
range.setEnd(missed.container, missed.offset);
|
range.setEnd(missed.container, missed.offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6166,110 +6142,6 @@ EpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id)
|
||||||
module.exports = EpubCFI;
|
module.exports = EpubCFI;
|
||||||
|
|
||||||
},{"./core":8,"urijs":5}],10:[function(require,module,exports){
|
},{"./core":8,"urijs":5}],10:[function(require,module,exports){
|
||||||
// Based on - https://gist.github.com/kidoman/5625116
|
|
||||||
function Highlighter(className) {
|
|
||||||
this.className = className || "annotator-hl";
|
|
||||||
};
|
|
||||||
|
|
||||||
Highlighter.prototype.add = function(range, className) {
|
|
||||||
var wrappers = [];
|
|
||||||
var wrapper;
|
|
||||||
if (!range || !range.startContainer) {
|
|
||||||
console.error("Not a valid Range");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (className) {
|
|
||||||
this.className = className;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.doc = range.startContainer.ownerDocument;
|
|
||||||
|
|
||||||
// Wrap all child text nodes
|
|
||||||
this.getTextNodes(range, this.doc).forEach(function(node) {
|
|
||||||
wrappers.push(this.wrapNode(node));
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
|
|
||||||
if (range.startContainer === range.endContainer) {
|
|
||||||
wrappers.push(this.wrapRange(range));
|
|
||||||
} else {
|
|
||||||
// Wrap start and end elements
|
|
||||||
wrappers.push(this.wrapPartial(range, range.startContainer, 'start'));
|
|
||||||
wrappers.push(this.wrapPartial(range, range.endContainer, 'end'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return wrappers;
|
|
||||||
};
|
|
||||||
|
|
||||||
Highlighter.prototype.remove = function(range) {
|
|
||||||
// STUB
|
|
||||||
};
|
|
||||||
|
|
||||||
Highlighter.prototype.rejectEmpty = function(node) {
|
|
||||||
if (node.data.match(/^\s+$/)) return NodeFilter.FILTER_SKIP;
|
|
||||||
|
|
||||||
return NodeFilter.FILTER_ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
Highlighter.prototype.getTextNodes = function(range, _doc) {
|
|
||||||
var doc = _doc || document;
|
|
||||||
var nodeIterator = doc.createNodeIterator(range.commonAncestorContainer, NodeFilter.SHOW_TEXT, this.rejectEmpty);
|
|
||||||
var mark = false;
|
|
||||||
var nodes = [];
|
|
||||||
var node;
|
|
||||||
|
|
||||||
while(node = nodeIterator.nextNode()) {
|
|
||||||
if (node == range.startContainer) {
|
|
||||||
mark = true;
|
|
||||||
continue
|
|
||||||
} else if (node === range.endContainer) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mark) nodes.push(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nodes
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Highlighter.prototype.wrapRange = function(range) {
|
|
||||||
var wrapper = this.wrapperNode();
|
|
||||||
range.surroundContents(wrapper);
|
|
||||||
return wrapper;
|
|
||||||
};
|
|
||||||
|
|
||||||
Highlighter.prototype.wrapNode = function(node) {
|
|
||||||
var wrapper = this.wrapperNode();
|
|
||||||
var range = this.doc.createRange();
|
|
||||||
range.selectNodeContents(node);
|
|
||||||
range.surroundContents(wrapper);
|
|
||||||
return wrapper;
|
|
||||||
};
|
|
||||||
|
|
||||||
Highlighter.prototype.wrapPartial = function(range, node, position) {
|
|
||||||
var startOffset = position === 'start' ? range.startOffset : 0;
|
|
||||||
var endOffset = position === 'start' ? node.length : range.endOffset;
|
|
||||||
var range = this.doc.createRange();
|
|
||||||
var wrapper = this.wrapperNode();
|
|
||||||
|
|
||||||
range.setStart(node, startOffset);
|
|
||||||
range.setEnd(node, endOffset);
|
|
||||||
|
|
||||||
range.surroundContents(wrapper);
|
|
||||||
return wrapper;
|
|
||||||
};
|
|
||||||
|
|
||||||
Highlighter.prototype.wrapperNode = function(type) {
|
|
||||||
if (type === undefined) type = 'span';
|
|
||||||
var elem = document.createElement(type)
|
|
||||||
elem.classList.add(this.className);
|
|
||||||
return elem;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = Highlighter;
|
|
||||||
|
|
||||||
},{}],11:[function(require,module,exports){
|
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
|
|
||||||
//-- Hooks allow for injecting functions that must all complete in order before finishing
|
//-- Hooks allow for injecting functions that must all complete in order before finishing
|
||||||
|
@ -6326,7 +6198,7 @@ Hook.prototype.list = function(){
|
||||||
|
|
||||||
module.exports = Hook;
|
module.exports = Hook;
|
||||||
|
|
||||||
},{"rsvp":4}],12:[function(require,module,exports){
|
},{"rsvp":4}],11:[function(require,module,exports){
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
|
|
||||||
function Reflowable(){
|
function Reflowable(){
|
||||||
|
@ -6489,7 +6361,7 @@ module.exports = {
|
||||||
'Scroll': Scroll
|
'Scroll': Scroll
|
||||||
};
|
};
|
||||||
|
|
||||||
},{"./core":8}],13:[function(require,module,exports){
|
},{"./core":8}],12:[function(require,module,exports){
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
var Queue = require('./queue');
|
var Queue = require('./queue');
|
||||||
var EpubCFI = require('./epubcfi');
|
var EpubCFI = require('./epubcfi');
|
||||||
|
@ -6714,7 +6586,7 @@ RSVP.EventTarget.mixin(Locations.prototype);
|
||||||
|
|
||||||
module.exports = Locations;
|
module.exports = Locations;
|
||||||
|
|
||||||
},{"./core":8,"./epubcfi":9,"./queue":18,"rsvp":4}],14:[function(require,module,exports){
|
},{"./core":8,"./epubcfi":9,"./queue":17,"rsvp":4}],13:[function(require,module,exports){
|
||||||
function Map(layout){
|
function Map(layout){
|
||||||
this.layout = layout;
|
this.layout = layout;
|
||||||
};
|
};
|
||||||
|
@ -7003,7 +6875,7 @@ Map.prototype.rangeListToCfiList = function(view, columns){
|
||||||
|
|
||||||
module.exports = Map;
|
module.exports = Map;
|
||||||
|
|
||||||
},{}],15:[function(require,module,exports){
|
},{}],14:[function(require,module,exports){
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
var Parser = require('./parser');
|
var Parser = require('./parser');
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
|
@ -7107,7 +6979,7 @@ Navigation.prototype.get = function(target) {
|
||||||
|
|
||||||
module.exports = Navigation;
|
module.exports = Navigation;
|
||||||
|
|
||||||
},{"./core":8,"./parser":17,"./request":21,"rsvp":4,"urijs":5}],16:[function(require,module,exports){
|
},{"./core":8,"./parser":16,"./request":20,"rsvp":4,"urijs":5}],15:[function(require,module,exports){
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
var Continuous = require('./continuous');
|
var Continuous = require('./continuous');
|
||||||
|
@ -7395,7 +7267,7 @@ Paginate.prototype.adjustImages = function(view) {
|
||||||
|
|
||||||
module.exports = Paginate;
|
module.exports = Paginate;
|
||||||
|
|
||||||
},{"./continuous":7,"./core":8,"./layout":12,"./map":14,"rsvp":4}],17:[function(require,module,exports){
|
},{"./continuous":7,"./core":8,"./layout":11,"./map":13,"rsvp":4}],16:[function(require,module,exports){
|
||||||
var URI = require('urijs');
|
var URI = require('urijs');
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
var EpubCFI = require('./epubcfi');
|
var EpubCFI = require('./epubcfi');
|
||||||
|
@ -7859,7 +7731,7 @@ Parser.prototype.pageListItem = function(item, spineIndexByURL, bookSpine){
|
||||||
|
|
||||||
module.exports = Parser;
|
module.exports = Parser;
|
||||||
|
|
||||||
},{"./core":8,"./epubcfi":9,"urijs":5}],18:[function(require,module,exports){
|
},{"./core":8,"./epubcfi":9,"urijs":5}],17:[function(require,module,exports){
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
|
|
||||||
|
@ -8054,7 +7926,7 @@ function Task(task, args, context){
|
||||||
|
|
||||||
module.exports = Queue;
|
module.exports = Queue;
|
||||||
|
|
||||||
},{"./core":8,"rsvp":4}],19:[function(require,module,exports){
|
},{"./core":8,"rsvp":4}],18:[function(require,module,exports){
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var URI = require('urijs');
|
var URI = require('urijs');
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
|
@ -8075,12 +7947,15 @@ function Rendition(book, options) {
|
||||||
width: false,
|
width: false,
|
||||||
height: null,
|
height: null,
|
||||||
layoutOveride : null, // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'},
|
layoutOveride : null, // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'},
|
||||||
axis: "vertical"
|
axis: "vertical",
|
||||||
|
ignoreClass: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
core.extend(this.settings, options);
|
core.extend(this.settings, options);
|
||||||
|
|
||||||
this.viewSettings = {};
|
this.viewSettings = {
|
||||||
|
ignoreClass: this.settings.ignoreClass
|
||||||
|
};
|
||||||
|
|
||||||
this.book = book;
|
this.book = book;
|
||||||
|
|
||||||
|
@ -8807,16 +8682,15 @@ Rendition.prototype.replaceAssets = function(section, urls, replacementUrls){
|
||||||
section.output = replace.substitute(section.output, relUrls, replacementUrls);
|
section.output = replace.substitute(section.output, relUrls, replacementUrls);
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.highlight = function(_cfi, className){
|
Rendition.prototype.selectCfiRange = function(_cfi, ignoreClass){
|
||||||
var cfi = new EpubCFI(_cfi);
|
var cfi = new EpubCFI(_cfi);
|
||||||
var views = this.visible();
|
var found = this.visible().filter(function (view) {
|
||||||
var found = views.filter(function (view) {
|
|
||||||
if(cfi.spinePos === view.index) return true;
|
if(cfi.spinePos === view.index) return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Should only every return 1 item
|
// Should only every return 1 item
|
||||||
if (found.length) {
|
if (found.length) {
|
||||||
return found[0].highlight(cfi, className);
|
return found[0].selectCfiRange(cfi, ignoreClass);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8825,7 +8699,7 @@ RSVP.EventTarget.mixin(Rendition.prototype);
|
||||||
|
|
||||||
module.exports = Rendition;
|
module.exports = Rendition;
|
||||||
|
|
||||||
},{"./core":8,"./epubcfi":9,"./hook":11,"./layout":12,"./map":14,"./queue":18,"./replacements":20,"./view":25,"./views":26,"rsvp":4,"urijs":5}],20:[function(require,module,exports){
|
},{"./core":8,"./epubcfi":9,"./hook":10,"./layout":11,"./map":13,"./queue":17,"./replacements":19,"./view":24,"./views":25,"rsvp":4,"urijs":5}],19:[function(require,module,exports){
|
||||||
var URI = require('urijs');
|
var URI = require('urijs');
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
|
|
||||||
|
@ -8912,7 +8786,7 @@ module.exports = {
|
||||||
'substitute': substitute
|
'substitute': substitute
|
||||||
};
|
};
|
||||||
|
|
||||||
},{"./core":8,"urijs":5}],21:[function(require,module,exports){
|
},{"./core":8,"urijs":5}],20:[function(require,module,exports){
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var URI = require('urijs');
|
var URI = require('urijs');
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
|
@ -9045,7 +8919,7 @@ function request(url, type, withCredentials, headers) {
|
||||||
|
|
||||||
module.exports = request;
|
module.exports = request;
|
||||||
|
|
||||||
},{"./core":8,"rsvp":4,"urijs":5}],22:[function(require,module,exports){
|
},{"./core":8,"rsvp":4,"urijs":5}],21:[function(require,module,exports){
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var URI = require('urijs');
|
var URI = require('urijs');
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
|
@ -9196,7 +9070,7 @@ Section.prototype.cfiFromElement = function(el) {
|
||||||
|
|
||||||
module.exports = Section;
|
module.exports = Section;
|
||||||
|
|
||||||
},{"./core":8,"./epubcfi":9,"./hook":11,"./replacements":20,"./request":21,"rsvp":4,"urijs":5}],23:[function(require,module,exports){
|
},{"./core":8,"./epubcfi":9,"./hook":10,"./replacements":19,"./request":20,"rsvp":4,"urijs":5}],22:[function(require,module,exports){
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
var EpubCFI = require('./epubcfi');
|
var EpubCFI = require('./epubcfi');
|
||||||
|
@ -9320,7 +9194,7 @@ Spine.prototype.each = function() {
|
||||||
|
|
||||||
module.exports = Spine;
|
module.exports = Spine;
|
||||||
|
|
||||||
},{"./core":8,"./epubcfi":9,"./section":22,"rsvp":4}],24:[function(require,module,exports){
|
},{"./core":8,"./epubcfi":9,"./section":21,"rsvp":4}],23:[function(require,module,exports){
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var URI = require('urijs');
|
var URI = require('urijs');
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
|
@ -9470,14 +9344,15 @@ Unarchive.prototype.revokeUrl = function(url){
|
||||||
|
|
||||||
module.exports = Unarchive;
|
module.exports = Unarchive;
|
||||||
|
|
||||||
},{"../libs/mime/mime":1,"./core":8,"./request":21,"jszip":"jszip","rsvp":4,"urijs":5}],25:[function(require,module,exports){
|
},{"../libs/mime/mime":1,"./core":8,"./request":20,"jszip":"jszip","rsvp":4,"urijs":5}],24:[function(require,module,exports){
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
var EpubCFI = require('./epubcfi');
|
var EpubCFI = require('./epubcfi');
|
||||||
var Highlighter = require('./highlighter');
|
|
||||||
|
|
||||||
function View(section, options) {
|
function View(section, options) {
|
||||||
this.settings = options || {};
|
this.settings = core.extend({
|
||||||
|
ignoreClass : ''
|
||||||
|
}, options || {});
|
||||||
|
|
||||||
this.id = "epubjs-view:" + core.uuid();
|
this.id = "epubjs-view:" + core.uuid();
|
||||||
this.section = section;
|
this.section = section;
|
||||||
|
@ -9502,9 +9377,6 @@ function View(section, options) {
|
||||||
// Blank Cfi for Parsing
|
// Blank Cfi for Parsing
|
||||||
this.epubcfi = new EpubCFI();
|
this.epubcfi = new EpubCFI();
|
||||||
|
|
||||||
// Highlighter
|
|
||||||
this.highlighter = new Highlighter(this.settings.highlightClass);
|
|
||||||
|
|
||||||
if(this.settings.axis && this.settings.axis == "horizontal"){
|
if(this.settings.axis && this.settings.axis == "horizontal"){
|
||||||
this.element.style.display = "inline-block";
|
this.element.style.display = "inline-block";
|
||||||
} else {
|
} else {
|
||||||
|
@ -10053,24 +9925,7 @@ View.prototype.locationOf = function(target) {
|
||||||
if(!this.document) return;
|
if(!this.document) return;
|
||||||
|
|
||||||
if(this.epubcfi.isCfiString(target)) {
|
if(this.epubcfi.isCfiString(target)) {
|
||||||
// cfi = this.epubcfi.parse(target);
|
range = new EpubCFI(cfi).toRange(this.document, this.settings.ignoreClass);
|
||||||
//
|
|
||||||
// if(typeof document.evaluate === 'undefined') {
|
|
||||||
// marker = this.epubcfi.addMarker(cfi, this.document);
|
|
||||||
// if(marker) {
|
|
||||||
// // Must Clean up Marker before going to page
|
|
||||||
// this.epubcfi.removeMarker(marker, this.document);
|
|
||||||
//
|
|
||||||
// targetPos = marker.getBoundingClientRect();
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// range = this.epubcfi.generateRangeFromCfi(cfi, this.document);
|
|
||||||
// if(range) {
|
|
||||||
// targetPos = range.getBoundingClientRect();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
range = new EpubCFI(cfi).toRange(this.document);
|
|
||||||
if(range) {
|
if(range) {
|
||||||
targetPos = range.getBoundingClientRect();
|
targetPos = range.getBoundingClientRect();
|
||||||
}
|
}
|
||||||
|
@ -10245,23 +10100,16 @@ View.prototype.triggerSelectedEvent = function(selection){
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
View.prototype.highlight = function(_cfi, className){
|
View.prototype.selectCfiRange = function(_cfi, ignoreClass){
|
||||||
var cfi = new EpubCFI(_cfi);
|
var cfi = new EpubCFI(_cfi);
|
||||||
return cfi.toRange(this.document);
|
return cfi.toRange(this.document, ignoreClass || this.settings.ignoreClass);
|
||||||
var span = this.document.createElement("span");
|
|
||||||
var range;
|
|
||||||
|
|
||||||
if (cfi.spinePos === this.index) {
|
|
||||||
range = cfi.toRange(this.document);
|
|
||||||
return this.highlighter.add(range, className || "annotator-hl");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RSVP.EventTarget.mixin(View.prototype);
|
RSVP.EventTarget.mixin(View.prototype);
|
||||||
|
|
||||||
module.exports = View;
|
module.exports = View;
|
||||||
|
|
||||||
},{"./core":8,"./epubcfi":9,"./highlighter":10,"rsvp":4}],26:[function(require,module,exports){
|
},{"./core":8,"./epubcfi":9,"rsvp":4}],25:[function(require,module,exports){
|
||||||
function Views(container) {
|
function Views(container) {
|
||||||
this.container = container;
|
this.container = container;
|
||||||
this._views = [];
|
this._views = [];
|
||||||
|
|
2
dist/epub.js.map
vendored
2
dist/epub.js.map
vendored
File diff suppressed because one or more lines are too long
|
@ -131,16 +131,12 @@
|
||||||
var rendition = book.renderTo("viewer", {
|
var rendition = book.renderTo("viewer", {
|
||||||
method: "paginate",
|
method: "paginate",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: 600
|
height: 600,
|
||||||
|
ignoreClass: 'annotator-hl'
|
||||||
});
|
});
|
||||||
|
|
||||||
var displayed = rendition.display(3);
|
var displayed = rendition.display(3);
|
||||||
|
|
||||||
|
|
||||||
displayed.then(function(renderer){
|
|
||||||
// -- do stuff
|
|
||||||
});
|
|
||||||
|
|
||||||
// Navigation loaded
|
// Navigation loaded
|
||||||
book.loaded.navigation.then(function(toc){
|
book.loaded.navigation.then(function(toc){
|
||||||
// console.log(toc);
|
// console.log(toc);
|
||||||
|
@ -173,52 +169,34 @@
|
||||||
rendition.on("keyup", keyListener);
|
rendition.on("keyup", keyListener);
|
||||||
document.addEventListener("keyup", keyListener, false);
|
document.addEventListener("keyup", keyListener, false);
|
||||||
|
|
||||||
var highlights = [];
|
|
||||||
|
|
||||||
var r, applier;
|
|
||||||
|
|
||||||
rendition.hooks.render.register(function (view) {
|
|
||||||
r = rangy.createHighlighter(view.document);
|
|
||||||
applier = rangy.createClassApplier("annotator-hl");
|
|
||||||
r.addClassApplier(applier);
|
|
||||||
})
|
|
||||||
|
|
||||||
rendition.on("selected", function(cfiRange) {
|
|
||||||
console.log(cfiRange);
|
|
||||||
var range = rendition.highlight(cfiRange);
|
|
||||||
console.log(range);
|
|
||||||
var rr = rangy.createRange();
|
|
||||||
|
|
||||||
rr.setStart(range.startContainer, range.startOffset);
|
|
||||||
rr.setEnd(range.endContainer, range.endOffset);
|
|
||||||
applier.applyToRange(rr);
|
|
||||||
|
|
||||||
window.getSelection().removeAllRanges();
|
|
||||||
|
|
||||||
// highlights = rendition.highlight(cfiRange);
|
|
||||||
|
|
||||||
// Illustation of how to add events to highlights
|
|
||||||
// and how get text from a range.
|
|
||||||
|
|
||||||
highlights.forEach(function (h) {
|
|
||||||
// Set the cfi range
|
|
||||||
h.setAttribute("data-epubcfi", cfiRange);
|
|
||||||
// Add a click event
|
|
||||||
h.addEventListener('click', function (e) {
|
|
||||||
var cfiRange = e.target.getAttribute("data-epubcfi");
|
|
||||||
book.getTextFromCfiRange(cfiRange).then(function (text) {
|
|
||||||
console.log(text);
|
|
||||||
})
|
|
||||||
return e.stopPropagation();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
rendition.on("locationChanged", function(location){
|
rendition.on("locationChanged", function(location){
|
||||||
// console.log(location);
|
// console.log(location);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var applier;
|
||||||
|
|
||||||
|
displayed.then(function(renderer){
|
||||||
|
// wait till something has been rendered to add applier
|
||||||
|
applier = rangy.createClassApplier("annotator-hl");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Apply a class to selected text
|
||||||
|
rendition.on("selected", function(cfiRange) {
|
||||||
|
// Get the dom range of the selected text
|
||||||
|
var range = rendition.selectCfiRange(cfiRange);
|
||||||
|
// Create an empty Rangy range
|
||||||
|
var rr = rangy.createRange();
|
||||||
|
// Set that range to equal the dom range
|
||||||
|
rr.setStart(range.startContainer, range.startOffset);
|
||||||
|
rr.setEnd(range.endContainer, range.endOffset);
|
||||||
|
// Add the class to that range
|
||||||
|
applier.applyToRange(rr);
|
||||||
|
// Clear the selection
|
||||||
|
window.getSelection().removeAllRanges();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add a yellow background to text with our highlight class
|
||||||
rendition.hooks.render.register(function (view) {
|
rendition.hooks.render.register(function (view) {
|
||||||
var highlightColor = [
|
var highlightColor = [
|
||||||
['.annotator-hl', ['background-color', 'yellow']]
|
['.annotator-hl', ['background-color', 'yellow']]
|
||||||
|
@ -226,15 +204,15 @@
|
||||||
view.addStylesheetRules(highlightColor);
|
view.addStylesheetRules(highlightColor);
|
||||||
})
|
})
|
||||||
|
|
||||||
rendition.on("selected", function(range) {
|
// Illustration of how to get text from a saved cfiRange
|
||||||
console.log("selected", range);
|
rendition.on("selected", function(cfiRange) {
|
||||||
book.getTextFromCfiRange(range).then(function (text) {
|
|
||||||
|
book.selectCfiRange(cfiRange).then(function (range) {
|
||||||
|
var text = range.toString();
|
||||||
console.log(text);
|
console.log(text);
|
||||||
})
|
})
|
||||||
|
|
||||||
});
|
});
|
||||||
// epubcfi(/6/8[chapter_001]!/4/2/8,/1:244,/1:256)
|
|
||||||
// epubcfi(/6/8[chapter_001]!/4/2/12,/3:351,/3:410)
|
|
||||||
// watch to take out of it, and, burning with curiosity, she
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
17
gulpfile.js
17
gulpfile.js
|
@ -52,7 +52,7 @@ gulp.task('minify', ['bundle'], function(){
|
||||||
|
|
||||||
// Watch Our Files
|
// Watch Our Files
|
||||||
gulp.task('watch', function(cb) {
|
gulp.task('watch', function(cb) {
|
||||||
// gulp.watch('src/*.js', ['watchify']);
|
server();
|
||||||
bundle('epub.js', cb);
|
bundle('epub.js', cb);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -74,6 +74,21 @@ gulp.task('test', function(cb) {
|
||||||
.bundle();
|
.bundle();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
gulp.task('test:once', function(cb) {
|
||||||
|
mochify('./test/*.js', {
|
||||||
|
reporter: 'spec',
|
||||||
|
transform: 'brfs',
|
||||||
|
"web-security": false,
|
||||||
|
"webSecurityEnabled": false,
|
||||||
|
// "localUrlAccess": true,
|
||||||
|
watch: false,
|
||||||
|
wd: false,
|
||||||
|
debug: false
|
||||||
|
})
|
||||||
|
.bundle();
|
||||||
|
});
|
||||||
|
|
||||||
// Default
|
// Default
|
||||||
gulp.task('default', ['lint', 'bundle']);
|
gulp.task('default', ['lint', 'bundle']);
|
||||||
|
|
||||||
|
|
|
@ -279,14 +279,13 @@ Book.prototype.coverUrl = function(){
|
||||||
return retrieved;
|
return retrieved;
|
||||||
};
|
};
|
||||||
|
|
||||||
Book.prototype.getTextFromCfiRange = function(cfiRange) {
|
Book.prototype.selectCfiRange = function(cfiRange) {
|
||||||
var cfi = new EpubCFI(cfiRange);
|
var cfi = new EpubCFI(cfiRange);
|
||||||
var item = this.spine.get(cfi.spinePos)
|
var item = this.spine.get(cfi.spinePos)
|
||||||
|
|
||||||
return item.load().then(function (contents) {
|
return item.load().then(function (contents) {
|
||||||
var range = cfi.toRange(item.document);
|
var range = cfi.toRange(item.document);
|
||||||
var text = range.toString();
|
return range;
|
||||||
return text;
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,8 @@ var core = require('./core');
|
||||||
- Text Location Assertion ([)
|
- Text Location Assertion ([)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function EpubCFI(cfiFrom, base, options){
|
function EpubCFI(cfiFrom, base, ignoreClass){
|
||||||
var type;
|
var type;
|
||||||
this.options = {
|
|
||||||
ignoreClass: 'annotator-hl'
|
|
||||||
};
|
|
||||||
|
|
||||||
this.str = '';
|
this.str = '';
|
||||||
|
|
||||||
|
@ -34,25 +31,9 @@ function EpubCFI(cfiFrom, base, options){
|
||||||
|
|
||||||
// Allow instantiation without the 'new' keyword
|
// Allow instantiation without the 'new' keyword
|
||||||
if (!(this instanceof EpubCFI)) {
|
if (!(this instanceof EpubCFI)) {
|
||||||
return new EpubCFI(cfiFrom, base, options);
|
return new EpubCFI(cfiFrom, base, ignoreClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find options
|
|
||||||
for (var i = 1, length = arguments.length; i < length; i++) {
|
|
||||||
if(typeof arguments[i] === 'object' && (arguments[i].ignoreClass)) {
|
|
||||||
core.extend(this.options, arguments[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* TODO: maybe accept object that includes:
|
|
||||||
{
|
|
||||||
spineNodeIndex: <int>
|
|
||||||
index: <int>
|
|
||||||
idref: <string:optional>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if(typeof base === 'string') {
|
if(typeof base === 'string') {
|
||||||
this.base = this.parseComponent(base);
|
this.base = this.parseComponent(base);
|
||||||
} else if(typeof base === 'object' && base.steps) {
|
} else if(typeof base === 'object' && base.steps) {
|
||||||
|
@ -66,9 +47,9 @@ function EpubCFI(cfiFrom, base, options){
|
||||||
this.str = cfiFrom;
|
this.str = cfiFrom;
|
||||||
return core.extend(this, this.parse(cfiFrom));
|
return core.extend(this, this.parse(cfiFrom));
|
||||||
} else if (type === 'range') {
|
} else if (type === 'range') {
|
||||||
return core.extend(this, this.fromRange(cfiFrom, this.base));
|
return core.extend(this, this.fromRange(cfiFrom, this.base, ignoreClass));
|
||||||
} else if (type === 'node') {
|
} else if (type === 'node') {
|
||||||
return core.extend(this, this.fromNode(cfiFrom, this.base));
|
return core.extend(this, this.fromNode(cfiFrom, this.base, ignoreClass));
|
||||||
} else if (type === 'EpubCFI' && cfiFrom.path) {
|
} else if (type === 'EpubCFI' && cfiFrom.path) {
|
||||||
return cfiFrom;
|
return cfiFrom;
|
||||||
} else if (!cfiFrom) {
|
} else if (!cfiFrom) {
|
||||||
|
@ -458,7 +439,7 @@ EpubCFI.prototype.equalStep = function(stepA, stepB) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
EpubCFI.prototype.fromRange = function(range, base) {
|
EpubCFI.prototype.fromRange = function(range, base, ignoreClass) {
|
||||||
var cfi = {
|
var cfi = {
|
||||||
range: false,
|
range: false,
|
||||||
base: {},
|
base: {},
|
||||||
|
@ -473,15 +454,14 @@ EpubCFI.prototype.fromRange = function(range, base) {
|
||||||
var startOffset = range.startOffset;
|
var startOffset = range.startOffset;
|
||||||
var endOffset = range.endOffset;
|
var endOffset = range.endOffset;
|
||||||
|
|
||||||
var needsIgnoring = (start.ownerDocument.querySelector('.' + this.options.ignoreClass) != null);
|
var needsIgnoring = false;
|
||||||
var ignoreClass;
|
|
||||||
// Tell pathTo if / what to ignore
|
if (ignoreClass) {
|
||||||
if (needsIgnoring) {
|
// Tell pathTo if / what to ignore
|
||||||
ignoreClass = this.options.ignoreClass
|
needsIgnoring = (start.ownerDocument.querySelector('.' + ignoreClass) != null);
|
||||||
} else {
|
|
||||||
ignoreClass = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (typeof base === 'string') {
|
if (typeof base === 'string') {
|
||||||
cfi.base = this.parseComponent(base);
|
cfi.base = this.parseComponent(base);
|
||||||
cfi.spinePos = cfi.base.steps[1].index;
|
cfi.spinePos = cfi.base.steps[1].index;
|
||||||
|
@ -547,7 +527,7 @@ EpubCFI.prototype.fromRange = function(range, base) {
|
||||||
return cfi;
|
return cfi;
|
||||||
}
|
}
|
||||||
|
|
||||||
EpubCFI.prototype.fromNode = function(anchor, base) {
|
EpubCFI.prototype.fromNode = function(anchor, base, ignoreClass) {
|
||||||
var cfi = {
|
var cfi = {
|
||||||
range: false,
|
range: false,
|
||||||
base: {},
|
base: {},
|
||||||
|
@ -556,13 +536,11 @@ EpubCFI.prototype.fromNode = function(anchor, base) {
|
||||||
end: null
|
end: null
|
||||||
};
|
};
|
||||||
|
|
||||||
var needsIgnoring = (anchor.ownerDocument.querySelector('.' + this.options.ignoreClass) != null);
|
var needsIgnoring = false;
|
||||||
var ignoreClass;
|
|
||||||
// Tell pathTo if / what to ignore
|
if (ignoreClass) {
|
||||||
if (needsIgnoring) {
|
// Tell pathTo if / what to ignore
|
||||||
ignoreClass = this.options.ignoreClass
|
needsIgnoring = (anchor.ownerDocument.querySelector('.' + ignoreClass) != null);
|
||||||
} else {
|
|
||||||
ignoreClass = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof base === 'string') {
|
if (typeof base === 'string') {
|
||||||
|
@ -815,18 +793,16 @@ EpubCFI.prototype.walkToNode = function(steps, _doc, ignoreClass) {
|
||||||
return container;
|
return container;
|
||||||
};
|
};
|
||||||
|
|
||||||
EpubCFI.prototype.findNode = function(steps, _doc) {
|
EpubCFI.prototype.findNode = function(steps, _doc, ignoreClass) {
|
||||||
var doc = _doc || document;
|
var doc = _doc || document;
|
||||||
var container;
|
var container;
|
||||||
var xpath;
|
var xpath;
|
||||||
// Check if we might need to need to fix missed results
|
|
||||||
var needsIgnoring = (doc.querySelector('.' + this.options.ignoreClass) != null);
|
|
||||||
|
|
||||||
if(!needsIgnoring && typeof doc.evaluate != 'undefined') {
|
if(!ignoreClass && typeof doc.evaluate != 'undefined') {
|
||||||
xpath = this.stepsToXpath(steps);
|
xpath = this.stepsToXpath(steps);
|
||||||
container = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
container = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||||
} else if(needsIgnoring) {
|
} else if(ignoreClass) {
|
||||||
container = this.walkToNode(steps, doc, this.options.ignoreClass);
|
container = this.walkToNode(steps, doc, ignoreClass);
|
||||||
} else {
|
} else {
|
||||||
container = this.walkToNode(steps, doc);
|
container = this.walkToNode(steps, doc);
|
||||||
}
|
}
|
||||||
|
@ -835,7 +811,7 @@ EpubCFI.prototype.findNode = function(steps, _doc) {
|
||||||
};
|
};
|
||||||
|
|
||||||
EpubCFI.prototype.fixMiss = function(steps, offset, _doc, ignoreClass) {
|
EpubCFI.prototype.fixMiss = function(steps, offset, _doc, ignoreClass) {
|
||||||
var container = this.findNode(steps.slice(0,-1), _doc);
|
var container = this.findNode(steps.slice(0,-1), _doc, ignoreClass);
|
||||||
var children = container.childNodes;
|
var children = container.childNodes;
|
||||||
var map = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass);
|
var map = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass);
|
||||||
var i;
|
var i;
|
||||||
|
@ -870,25 +846,26 @@ EpubCFI.prototype.fixMiss = function(steps, offset, _doc, ignoreClass) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EpubCFI.prototype.toRange = function(_doc, _cfi) {
|
EpubCFI.prototype.toRange = function(_doc, ignoreClass) {
|
||||||
var doc = _doc || document;
|
var doc = _doc || document;
|
||||||
var range = doc.createRange();
|
var range = doc.createRange();
|
||||||
var start, end, startContainer, endContainer;
|
var start, end, startContainer, endContainer;
|
||||||
var cfi = _cfi || this;
|
var cfi = this;
|
||||||
var startSteps, endSteps;
|
var startSteps, endSteps;
|
||||||
|
var needsIgnoring = ignoreClass ? (doc.querySelector('.' + ignoreClass) != null) : false;
|
||||||
var missed;
|
var missed;
|
||||||
|
|
||||||
if (cfi.range) {
|
if (cfi.range) {
|
||||||
start = cfi.start;
|
start = cfi.start;
|
||||||
startSteps = cfi.path.steps.concat(start.steps);
|
startSteps = cfi.path.steps.concat(start.steps);
|
||||||
startContainer = this.findNode(startSteps, doc);
|
startContainer = this.findNode(startSteps, doc, needsIgnoring ? ignoreClass : null);
|
||||||
end = cfi.end;
|
end = cfi.end;
|
||||||
endSteps = cfi.path.steps.concat(end.steps);
|
endSteps = cfi.path.steps.concat(end.steps);
|
||||||
endContainer = this.findNode(endSteps, doc);
|
endContainer = this.findNode(endSteps, doc, needsIgnoring ? ignoreClass : null);
|
||||||
} else {
|
} else {
|
||||||
start = cfi.path;
|
start = cfi.path;
|
||||||
startSteps = cfi.path.steps;
|
startSteps = cfi.path.steps;
|
||||||
startContainer = this.findNode(cfi.path.steps, doc);
|
startContainer = this.findNode(cfi.path.steps, doc, needsIgnoring ? ignoreClass : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -903,7 +880,7 @@ EpubCFI.prototype.toRange = function(_doc, _cfi) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
missed = this.fixMiss(startSteps, start.terminal.offset, doc, this.options.ignoreClass);
|
missed = this.fixMiss(startSteps, start.terminal.offset, doc, needsIgnoring ? ignoreClass : null);
|
||||||
range.setStart(missed.container, missed.offset);
|
range.setStart(missed.container, missed.offset);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -922,7 +899,7 @@ EpubCFI.prototype.toRange = function(_doc, _cfi) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
missed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, this.options.ignoreClass);
|
missed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, needsIgnoring ? ignoreClass : null);
|
||||||
range.setEnd(missed.container, missed.offset);
|
range.setEnd(missed.container, missed.offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
// Based on - https://gist.github.com/kidoman/5625116
|
|
||||||
function Highlighter(className) {
|
|
||||||
this.className = className || "annotator-hl";
|
|
||||||
};
|
|
||||||
|
|
||||||
Highlighter.prototype.add = function(range, className) {
|
|
||||||
var wrappers = [];
|
|
||||||
var wrapper;
|
|
||||||
if (!range || !range.startContainer) {
|
|
||||||
console.error("Not a valid Range");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (className) {
|
|
||||||
this.className = className;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.doc = range.startContainer.ownerDocument;
|
|
||||||
|
|
||||||
// Wrap all child text nodes
|
|
||||||
this.getTextNodes(range, this.doc).forEach(function(node) {
|
|
||||||
wrappers.push(this.wrapNode(node));
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
|
|
||||||
if (range.startContainer === range.endContainer) {
|
|
||||||
wrappers.push(this.wrapRange(range));
|
|
||||||
} else {
|
|
||||||
// Wrap start and end elements
|
|
||||||
wrappers.push(this.wrapPartial(range, range.startContainer, 'start'));
|
|
||||||
wrappers.push(this.wrapPartial(range, range.endContainer, 'end'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return wrappers;
|
|
||||||
};
|
|
||||||
|
|
||||||
Highlighter.prototype.remove = function(range) {
|
|
||||||
// STUB
|
|
||||||
};
|
|
||||||
|
|
||||||
Highlighter.prototype.rejectEmpty = function(node) {
|
|
||||||
if (node.data.match(/^\s+$/)) return NodeFilter.FILTER_SKIP;
|
|
||||||
|
|
||||||
return NodeFilter.FILTER_ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
Highlighter.prototype.getTextNodes = function(range, _doc) {
|
|
||||||
var doc = _doc || document;
|
|
||||||
var nodeIterator = doc.createNodeIterator(range.commonAncestorContainer, NodeFilter.SHOW_TEXT, this.rejectEmpty);
|
|
||||||
var mark = false;
|
|
||||||
var nodes = [];
|
|
||||||
var node;
|
|
||||||
|
|
||||||
while(node = nodeIterator.nextNode()) {
|
|
||||||
if (node == range.startContainer) {
|
|
||||||
mark = true;
|
|
||||||
continue
|
|
||||||
} else if (node === range.endContainer) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mark) nodes.push(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nodes
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Highlighter.prototype.wrapRange = function(range) {
|
|
||||||
var wrapper = this.wrapperNode();
|
|
||||||
range.surroundContents(wrapper);
|
|
||||||
return wrapper;
|
|
||||||
};
|
|
||||||
|
|
||||||
Highlighter.prototype.wrapNode = function(node) {
|
|
||||||
var wrapper = this.wrapperNode();
|
|
||||||
var range = this.doc.createRange();
|
|
||||||
range.selectNodeContents(node);
|
|
||||||
range.surroundContents(wrapper);
|
|
||||||
return wrapper;
|
|
||||||
};
|
|
||||||
|
|
||||||
Highlighter.prototype.wrapPartial = function(range, node, position) {
|
|
||||||
var startOffset = position === 'start' ? range.startOffset : 0;
|
|
||||||
var endOffset = position === 'start' ? node.length : range.endOffset;
|
|
||||||
var range = this.doc.createRange();
|
|
||||||
var wrapper = this.wrapperNode();
|
|
||||||
|
|
||||||
range.setStart(node, startOffset);
|
|
||||||
range.setEnd(node, endOffset);
|
|
||||||
|
|
||||||
range.surroundContents(wrapper);
|
|
||||||
return wrapper;
|
|
||||||
};
|
|
||||||
|
|
||||||
Highlighter.prototype.wrapperNode = function(type) {
|
|
||||||
if (type === undefined) type = 'span';
|
|
||||||
var elem = document.createElement(type)
|
|
||||||
elem.classList.add(this.className);
|
|
||||||
return elem;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = Highlighter;
|
|
|
@ -18,12 +18,15 @@ function Rendition(book, options) {
|
||||||
width: false,
|
width: false,
|
||||||
height: null,
|
height: null,
|
||||||
layoutOveride : null, // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'},
|
layoutOveride : null, // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'},
|
||||||
axis: "vertical"
|
axis: "vertical",
|
||||||
|
ignoreClass: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
core.extend(this.settings, options);
|
core.extend(this.settings, options);
|
||||||
|
|
||||||
this.viewSettings = {};
|
this.viewSettings = {
|
||||||
|
ignoreClass: this.settings.ignoreClass
|
||||||
|
};
|
||||||
|
|
||||||
this.book = book;
|
this.book = book;
|
||||||
|
|
||||||
|
@ -750,16 +753,15 @@ Rendition.prototype.replaceAssets = function(section, urls, replacementUrls){
|
||||||
section.output = replace.substitute(section.output, relUrls, replacementUrls);
|
section.output = replace.substitute(section.output, relUrls, replacementUrls);
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.highlight = function(_cfi, className){
|
Rendition.prototype.selectCfiRange = function(_cfi, ignoreClass){
|
||||||
var cfi = new EpubCFI(_cfi);
|
var cfi = new EpubCFI(_cfi);
|
||||||
var views = this.visible();
|
var found = this.visible().filter(function (view) {
|
||||||
var found = views.filter(function (view) {
|
|
||||||
if(cfi.spinePos === view.index) return true;
|
if(cfi.spinePos === view.index) return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Should only every return 1 item
|
// Should only every return 1 item
|
||||||
if (found.length) {
|
if (found.length) {
|
||||||
return found[0].highlight(cfi, className);
|
return found[0].selectCfiRange(cfi, ignoreClass);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
38
src/view.js
38
src/view.js
|
@ -1,10 +1,11 @@
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
var EpubCFI = require('./epubcfi');
|
var EpubCFI = require('./epubcfi');
|
||||||
var Highlighter = require('./highlighter');
|
|
||||||
|
|
||||||
function View(section, options) {
|
function View(section, options) {
|
||||||
this.settings = options || {};
|
this.settings = core.extend({
|
||||||
|
ignoreClass : ''
|
||||||
|
}, options || {});
|
||||||
|
|
||||||
this.id = "epubjs-view:" + core.uuid();
|
this.id = "epubjs-view:" + core.uuid();
|
||||||
this.section = section;
|
this.section = section;
|
||||||
|
@ -29,9 +30,6 @@ function View(section, options) {
|
||||||
// Blank Cfi for Parsing
|
// Blank Cfi for Parsing
|
||||||
this.epubcfi = new EpubCFI();
|
this.epubcfi = new EpubCFI();
|
||||||
|
|
||||||
// Highlighter
|
|
||||||
this.highlighter = new Highlighter(this.settings.highlightClass);
|
|
||||||
|
|
||||||
if(this.settings.axis && this.settings.axis == "horizontal"){
|
if(this.settings.axis && this.settings.axis == "horizontal"){
|
||||||
this.element.style.display = "inline-block";
|
this.element.style.display = "inline-block";
|
||||||
} else {
|
} else {
|
||||||
|
@ -580,24 +578,7 @@ View.prototype.locationOf = function(target) {
|
||||||
if(!this.document) return;
|
if(!this.document) return;
|
||||||
|
|
||||||
if(this.epubcfi.isCfiString(target)) {
|
if(this.epubcfi.isCfiString(target)) {
|
||||||
// cfi = this.epubcfi.parse(target);
|
range = new EpubCFI(cfi).toRange(this.document, this.settings.ignoreClass);
|
||||||
//
|
|
||||||
// if(typeof document.evaluate === 'undefined') {
|
|
||||||
// marker = this.epubcfi.addMarker(cfi, this.document);
|
|
||||||
// if(marker) {
|
|
||||||
// // Must Clean up Marker before going to page
|
|
||||||
// this.epubcfi.removeMarker(marker, this.document);
|
|
||||||
//
|
|
||||||
// targetPos = marker.getBoundingClientRect();
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// range = this.epubcfi.generateRangeFromCfi(cfi, this.document);
|
|
||||||
// if(range) {
|
|
||||||
// targetPos = range.getBoundingClientRect();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
range = new EpubCFI(cfi).toRange(this.document);
|
|
||||||
if(range) {
|
if(range) {
|
||||||
targetPos = range.getBoundingClientRect();
|
targetPos = range.getBoundingClientRect();
|
||||||
}
|
}
|
||||||
|
@ -772,16 +753,9 @@ View.prototype.triggerSelectedEvent = function(selection){
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
View.prototype.highlight = function(_cfi, className){
|
View.prototype.selectCfiRange = function(_cfi, ignoreClass){
|
||||||
var cfi = new EpubCFI(_cfi);
|
var cfi = new EpubCFI(_cfi);
|
||||||
return cfi.toRange(this.document);
|
return cfi.toRange(this.document, ignoreClass || this.settings.ignoreClass);
|
||||||
var span = this.document.createElement("span");
|
|
||||||
var range;
|
|
||||||
|
|
||||||
if (cfi.spinePos === this.index) {
|
|
||||||
range = cfi.toRange(this.document);
|
|
||||||
return this.highlighter.add(range, className || "annotator-hl");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RSVP.EventTarget.mixin(View.prototype);
|
RSVP.EventTarget.mixin(View.prototype);
|
||||||
|
|
|
@ -159,7 +159,7 @@ describe('EpubCFI', function() {
|
||||||
|
|
||||||
it('get a cfi from a text node inside a highlight', function() {
|
it('get a cfi from a text node inside a highlight', function() {
|
||||||
var t = doc.getElementById('highlight-1').childNodes[0];
|
var t = doc.getElementById('highlight-1').childNodes[0];
|
||||||
var cfi = new EpubCFI(t, base);
|
var cfi = new EpubCFI(t, base, 'annotator-hl');
|
||||||
|
|
||||||
assert.equal(t.nodeType, Node.TEXT_NODE, "provided a text node");
|
assert.equal(t.nodeType, Node.TEXT_NODE, "provided a text node");
|
||||||
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017]/1)" );
|
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017]/1)" );
|
||||||
|
@ -168,7 +168,7 @@ describe('EpubCFI', function() {
|
||||||
|
|
||||||
it('get a cfi from a highlight node', function() {
|
it('get a cfi from a highlight node', function() {
|
||||||
var t = doc.getElementById('highlight-1');
|
var t = doc.getElementById('highlight-1');
|
||||||
var cfi = new EpubCFI(t, base);
|
var cfi = new EpubCFI(t, base, 'annotator-hl');
|
||||||
|
|
||||||
assert.equal(t.nodeType, Node.ELEMENT_NODE, "provided a highlight node");
|
assert.equal(t.nodeType, Node.ELEMENT_NODE, "provided a highlight node");
|
||||||
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017])" );
|
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017])" );
|
||||||
|
@ -242,7 +242,7 @@ describe('EpubCFI', function() {
|
||||||
|
|
||||||
range.setStart(t1, 6);
|
range.setStart(t1, 6);
|
||||||
|
|
||||||
cfi = new EpubCFI(range, base);
|
cfi = new EpubCFI(range, base, 'annotator-hl');
|
||||||
|
|
||||||
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017]/1:43)" );
|
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017]/1:43)" );
|
||||||
|
|
||||||
|
@ -255,7 +255,7 @@ describe('EpubCFI', function() {
|
||||||
|
|
||||||
range.setStart(t1, 25);
|
range.setStart(t1, 25);
|
||||||
|
|
||||||
cfi = new EpubCFI(range, base);
|
cfi = new EpubCFI(range, base, 'annotator-hl');
|
||||||
|
|
||||||
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/4/2[c001s0001]/1:41)" );
|
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/4/2[c001s0001]/1:41)" );
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ describe('EpubCFI', function() {
|
||||||
|
|
||||||
range.setStart(t1, 4);
|
range.setStart(t1, 4);
|
||||||
|
|
||||||
cfi = new EpubCFI(range, base);
|
cfi = new EpubCFI(range, base, 'annotator-hl');
|
||||||
|
|
||||||
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/4[p2]/1:123)" );
|
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/4[p2]/1:123)" );
|
||||||
|
|
||||||
|
@ -357,12 +357,12 @@ describe('EpubCFI', function() {
|
||||||
|
|
||||||
ogRange.setStart(t1, 6);
|
ogRange.setStart(t1, 6);
|
||||||
|
|
||||||
cfi = new EpubCFI(ogRange, base);
|
cfi = new EpubCFI(ogRange, base, 'annotator-hl');
|
||||||
|
|
||||||
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017]/1:43)" );
|
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017]/1:43)" );
|
||||||
|
|
||||||
// Check the range
|
// Check the range
|
||||||
newRange = cfi.toRange(doc);
|
newRange = cfi.toRange(doc, 'annotator-hl');
|
||||||
|
|
||||||
assert.ok(newRange.startContainer);
|
assert.ok(newRange.startContainer);
|
||||||
|
|
||||||
|
@ -381,12 +381,12 @@ describe('EpubCFI', function() {
|
||||||
ogRange.setStart(t1, 5);
|
ogRange.setStart(t1, 5);
|
||||||
ogRange.setEnd(t2, 25);
|
ogRange.setEnd(t2, 25);
|
||||||
|
|
||||||
cfi = new EpubCFI(ogRange, base);
|
cfi = new EpubCFI(ogRange, base, 'annotator-hl');
|
||||||
|
|
||||||
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/4/2[c001s0001],/1:5,/1:41)" );
|
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/4/2[c001s0001],/1:5,/1:41)" );
|
||||||
|
|
||||||
// Check the range
|
// Check the range
|
||||||
newRange = cfi.toRange(doc);
|
newRange = cfi.toRange(doc, 'annotator-hl');
|
||||||
|
|
||||||
assert.strictEqual( newRange.startContainer.textContent, t1.textContent);
|
assert.strictEqual( newRange.startContainer.textContent, t1.textContent);
|
||||||
// assert.strictEqual( newRange.startContainer, t1);
|
// assert.strictEqual( newRange.startContainer, t1);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue