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

updated cfi to handle text nodes and character offset

This commit is contained in:
fchasen 2014-01-29 11:04:48 -08:00
parent 0a0a13f5f5
commit 73ac66ba65
19 changed files with 529 additions and 228 deletions

2
books

@ -1 +1 @@
Subproject commit ab9755a74714b647290c861f666515de220935d8 Subproject commit 09bd1725f5839996e747cf83500a2526b86ae6af

View file

@ -3047,12 +3047,21 @@ EPUBJS.core.resolveUrl = function(base, path) {
return url.join("/"); return url.join("/");
}; };
// 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;
};
EPUBJS.EpubCFI = function(cfiStr){ EPUBJS.EpubCFI = function(cfiStr){
if(cfiStr) return this.parse(cfiStr); if(cfiStr) return this.parse(cfiStr);
}; };
EPUBJS.EpubCFI.prototype.generateChapter = function(_spineNodeIndex, _pos, id) { EPUBJS.EpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id) {
var pos = parseInt(_pos), var pos = parseInt(_pos),
spineNodeIndex = _spineNodeIndex + 1, spineNodeIndex = _spineNodeIndex + 1,
cfi = '/'+spineNodeIndex+'/'; cfi = '/'+spineNodeIndex+'/';
@ -3061,27 +3070,23 @@ EPUBJS.EpubCFI.prototype.generateChapter = function(_spineNodeIndex, _pos, id) {
if(id) cfi += "[" + id + "]"; if(id) cfi += "[" + id + "]";
cfi += "!"; //cfi += "!";
return cfi; return cfi;
}; };
EPUBJS.EpubCFI.prototype.generatePathComponent = function(steps) {
var parts = [];
EPUBJS.EpubCFI.prototype.generateFragment = function(element, chapter) { steps.forEach(function(part){
var path = this.pathTo(element),
parts = [];
if(chapter) parts.push(chapter);
path.forEach(function(part){
var segment = ''; var segment = '';
segment += (part.index + 1) * 2; segment += (part.index + 1) * 2;
if(part.id && if(part.id && part.id.slice(0, 6) === "EPUBJS") {
part.id.slice(0, 6) != "EPUBJS") { //-- ignore internal @EPUBJS ids //-- ignore internal @EPUBJS ids for
return;
} else if(part.id) {
segment += "[" + part.id + "]"; segment += "[" + part.id + "]";
} }
parts.push(segment); parts.push(segment);
@ -3090,6 +3095,13 @@ EPUBJS.EpubCFI.prototype.generateFragment = function(element, chapter) {
return parts.join('/'); return parts.join('/');
}; };
EPUBJS.EpubCFI.prototype.generateCfiFromElement = function(element, chapter) {
var steps = this.pathTo(element);
var path = this.generatePathComponent(steps);
return "epubcfi(" + chapter + "!" + path + ")";
};
EPUBJS.EpubCFI.prototype.pathTo = function(node) { EPUBJS.EpubCFI.prototype.pathTo = function(node) {
var stack = [], var stack = [],
children; children;
@ -3110,110 +3122,152 @@ EPUBJS.EpubCFI.prototype.pathTo = function(node) {
return stack; return stack;
}; };
EPUBJS.EpubCFI.prototype.getChapter = function(cfiStr) { EPUBJS.EpubCFI.prototype.getChapterComponent = function(cfiStr) {
var splitStr = cfiStr.split("!"); var splitStr = cfiStr.split("!");
return splitStr[0]; return splitStr[0];
}; };
EPUBJS.EpubCFI.prototype.getFragment = function(cfiStr) { EPUBJS.EpubCFI.prototype.getPathComponent = function(cfiStr) {
var splitStr = cfiStr.split("!"); var splitStr = cfiStr.split("!");
var pathComponent = splitStr[1] ? splitStr[1].split(":") : '';
return splitStr[1]; return pathComponent[0];
}; };
EPUBJS.EpubCFI.prototype.getOffset = function(cfiStr) { EPUBJS.EpubCFI.prototype.getCharecterOffsetComponent = function(cfiStr) {
var splitStr = cfiStr.split(":"); var splitStr = cfiStr.split(":");
return splitStr[1] || '';
return [splitStr[0], splitStr[1]];
}; };
EPUBJS.EpubCFI.prototype.parse = function(cfiStr) { EPUBJS.EpubCFI.prototype.parse = function(cfiStr) {
var cfi = {}, var cfi = {},
chapSegment, chapSegment,
chapterComponent,
pathComponent,
charecterOffsetComponent,
assertion,
chapId, chapId,
path, path,
end, end,
text; text;
cfi.chapter = this.getChapter(cfiStr); if(cfiStr.indexOf("epubcfi(") === 0) {
// Remove intial epubcfi( and ending )
cfiStr = cfiStr.slice(8, cfiStr.length-1);
}
chapSegment = parseInt(cfi.chapter.split("/")[2]) || false;
cfi.fragment = this.getFragment(cfiStr);
if(!chapSegment || !cfi.fragment) return {spinePos: -1}; chapterComponent = this.getChapterComponent(cfiStr);
pathComponent = this.getPathComponent(cfiStr);
charecterOffsetComponent = this.getCharecterOffsetComponent(cfiStr);
// Make sure this is a valid cfi or return
if(!chapterComponent.length || !pathComponent.length) {
return {spinePos: -1};
}
// Chapter segment is always the second one
chapSegment = chapterComponent.split("/")[2] || '';
if(!chapSegment) return {spinePos:-1};
cfi.spinePos = (parseInt(chapSegment) / 2 - 1 ) || 0; cfi.spinePos = (parseInt(chapSegment) / 2 - 1 ) || 0;
chapId = cfi.chapter.match(/\[(.*)\]/); chapId = chapSegment.match(/\[(.*)\]/);
cfi.spineId = chapId ? chapId[1] : false; cfi.spineId = chapId ? chapId[1] : false;
path = cfi.fragment.split('/'); if(pathComponent.indexOf(',') != -1) {
end = path[path.length-1]; // Handle ranges -- not supported yet
cfi.sections = []; console.warn("CFI Ranges are not supported");
//-- Check for Character Offset
if(parseInt(end) % 2){
text = this.getOffset();
cfi.text = parseInt(text[0]);
cfi.character = parseInt(text[1]);
path.pop(); //-- remove from path to element
} }
path = pathComponent.split('/');
end = path[path.length-1];
cfi.steps = [];
path.forEach(function(part){ path.forEach(function(part){
var index, has_id, id; var type, index, has_brackets, id;
if(!part) return; if(!part) return;
//-- Check if this is a text node or element
index = parseInt(part) / 2 - 1; if(parseInt(part) % 2){
has_id = part.match(/\[(.*)\]/); type = "text";
index = parseInt(part) - 1;
} else {
if(has_id && has_id[1]){ type = "element";
id = has_id[1]; index = parseInt(part) / 2 - 1;
has_brackets = part.match(/\[(.*)\]/);
if(has_brackets && has_brackets[1]){
id = has_brackets[1];
}
} }
cfi.sections.push({ cfi.steps.push({
"type" : type,
'index' : index, 'index' : index,
'id' : id || false 'id' : id || false
}); });
assertion = charecterOffsetComponent.match(/\[(.*)\]/);
if(assertion && assertion[1]){
cfi.characterOffset = parseInt(charecterOffsetComponent.split('[')[0]);
// We arent handling these assertions yet
cfi.textLocationAssertion = assertion[1];
} else {
cfi.characterOffset = parseInt(charecterOffsetComponent);
}
}); });
return cfi; return cfi;
}; };
EPUBJS.EpubCFI.prototype.getElement = function(cfi, _doc) { EPUBJS.EpubCFI.prototype.getElement = function(cfi, _doc) {
var doc = _doc || document, var doc = _doc || document,
sections = cfi.sections, element = doc.getElementsByTagName('html')[0],
element = doc.getElementsByTagName('html')[0], children = Array.prototype.slice.call(element.children),
children = Array.prototype.slice.call(element.children), num, index, part, sections,
num, index, part, text, textBegin, textEnd;
has_id, id;
// sections.shift(); //-- html if(typeof cfi === 'string') {
cfi = this.parse(cfi);
}
sections = cfi.steps;
while(sections && sections.length > 0) { while(sections && sections.length > 0) {
part = sections.shift(); part = sections.shift();
if(part.id){ // Wrap text elements in a span and return that new element
if(part.type === "text") {
text = element.childNodes[part.index];
element = doc.createElement('span');
element.id = "EPUBJS-CFI-MARKER:"+ EPUBJS.core.uuid();
if(cfi.characterOffset) {
textBegin = doc.createTextNode(text.textContent.slice(0, cfi.characterOffset));
textEnd = doc.createTextNode(text.textContent.slice(cfi.characterOffset));
text.parentNode.insertBefore(textEnd, text);
text.parentNode.insertBefore(element, textEnd);
text.parentNode.insertBefore(textBegin, element);
text.parentNode.removeChild(text);
} else {
text.parentNode.insertBefore(element, text);
}
// sort cut to find element by id
} else if(part.id){
element = doc.getElementById(part.id); element = doc.getElementById(part.id);
// find element in parent
}else{ }else{
element = children[part.index];
if(!children) console.error("No Kids", element); if(!children) console.error("No Kids", element);
element = children[part.index];
} }
@ -3224,7 +3278,44 @@ EPUBJS.EpubCFI.prototype.getElement = function(cfi, _doc) {
return element; return element;
}; };
//-- Todo: function to remove IDs to sort EPUBJS.EpubCFI.prototype.compare = function(cfiOne, cfiTwo) {
if(typeof cfiOne === 'string') {
cfiOne = this.parse(cfiOne);
}
if(typeof cfiTwo === 'string') {
cfiTwo = this.parse(cfiTwo);
}
// Compare Spine Positions
if(cfiOne.spinePos > cfiTwo.spinePos) {
return 1;
}
if(cfiOne.spinePos < cfiTwo.spinePos) {
return -1;
}
// Compare Each Step
for (var i = 0; i < cfiOne.steps.length; i++) {
if(!cfiTwo.steps[i]) {
return 1;
}
if(cfiOne.steps[i].index > cfiTwo.steps[i].index) {
return 1;
}
if(cfiOne.steps[i].index < cfiTwo.steps[i].index) {
return -1;
}
// Otherwise continue checking
}
// Compare the charecter offset of the text node
if(cfiOne.characterOffset > cfiTwo.characterOffset) {
return 1;
}
if(cfiOne.characterOffset < cfiTwo.characterOffset) {
return -1;
}
// CFI's are equal
return 0;
};
EPUBJS.Events = function(obj, el){ EPUBJS.Events = function(obj, el){
this.events = {}; this.events = {};
@ -3538,6 +3629,11 @@ EPUBJS.Layout.Fixed.prototype.calculatePages = function(){
pageCount : 1 pageCount : 1
}; };
}; };
EPUBJS.Navigation = function() {
};
// percentage at cfi, nearest page to Cfi, total pages and goto page.
EPUBJS.Parser = function(baseUrl){ EPUBJS.Parser = function(baseUrl){
this.baseUrl = baseUrl || ''; this.baseUrl = baseUrl || '';
@ -3759,7 +3855,7 @@ EPUBJS.Parser.prototype.spine = function(spineXml, manifest){
//-- Add to array to mantain ordering and cross reference with manifest //-- Add to array to mantain ordering and cross reference with manifest
items.forEach(function(item, index){ items.forEach(function(item, index){
var Id = item.getAttribute('idref'); var Id = item.getAttribute('idref');
var cfiBase = epubcfi.generateChapter(spineNodeIndex, index, Id); var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id);
var props = item.getAttribute('properties') || ''; var props = item.getAttribute('properties') || '';
var propArray = props.length ? props.split(' ') : []; var propArray = props.length ? props.split(' ') : [];
var manifestProps = manifest[Id].properties; var manifestProps = manifest[Id].properties;
@ -4528,7 +4624,7 @@ EPUBJS.Renderer.prototype.walk = function(node) {
EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){ EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){
this.visibileEl = this.findFirstVisible(prevEl); this.visibileEl = this.findFirstVisible(prevEl);
return this.epubcfi.generateFragment(this.visibileEl, this.currentChapter.cfiBase); return this.epubcfi.generateCfiFromElement(this.visibileEl, this.currentChapter.cfiBase);
}; };
// Goto a cfi position in the current chapter // Goto a cfi position in the current chapter

6
build/epub.min.js vendored

File diff suppressed because one or more lines are too long

View file

@ -3046,12 +3046,21 @@ EPUBJS.core.resolveUrl = function(base, path) {
return url.join("/"); return url.join("/");
}; };
// 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;
};
EPUBJS.EpubCFI = function(cfiStr){ EPUBJS.EpubCFI = function(cfiStr){
if(cfiStr) return this.parse(cfiStr); if(cfiStr) return this.parse(cfiStr);
}; };
EPUBJS.EpubCFI.prototype.generateChapter = function(_spineNodeIndex, _pos, id) { EPUBJS.EpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id) {
var pos = parseInt(_pos), var pos = parseInt(_pos),
spineNodeIndex = _spineNodeIndex + 1, spineNodeIndex = _spineNodeIndex + 1,
cfi = '/'+spineNodeIndex+'/'; cfi = '/'+spineNodeIndex+'/';
@ -3060,27 +3069,23 @@ EPUBJS.EpubCFI.prototype.generateChapter = function(_spineNodeIndex, _pos, id) {
if(id) cfi += "[" + id + "]"; if(id) cfi += "[" + id + "]";
cfi += "!"; //cfi += "!";
return cfi; return cfi;
}; };
EPUBJS.EpubCFI.prototype.generatePathComponent = function(steps) {
var parts = [];
EPUBJS.EpubCFI.prototype.generateFragment = function(element, chapter) { steps.forEach(function(part){
var path = this.pathTo(element),
parts = [];
if(chapter) parts.push(chapter);
path.forEach(function(part){
var segment = ''; var segment = '';
segment += (part.index + 1) * 2; segment += (part.index + 1) * 2;
if(part.id && if(part.id && part.id.slice(0, 6) === "EPUBJS") {
part.id.slice(0, 6) != "EPUBJS") { //-- ignore internal @EPUBJS ids //-- ignore internal @EPUBJS ids for
return;
} else if(part.id) {
segment += "[" + part.id + "]"; segment += "[" + part.id + "]";
} }
parts.push(segment); parts.push(segment);
@ -3089,6 +3094,13 @@ EPUBJS.EpubCFI.prototype.generateFragment = function(element, chapter) {
return parts.join('/'); return parts.join('/');
}; };
EPUBJS.EpubCFI.prototype.generateCfiFromElement = function(element, chapter) {
var steps = this.pathTo(element);
var path = this.generatePathComponent(steps);
return "epubcfi(" + chapter + "!" + path + ")";
};
EPUBJS.EpubCFI.prototype.pathTo = function(node) { EPUBJS.EpubCFI.prototype.pathTo = function(node) {
var stack = [], var stack = [],
children; children;
@ -3109,110 +3121,152 @@ EPUBJS.EpubCFI.prototype.pathTo = function(node) {
return stack; return stack;
}; };
EPUBJS.EpubCFI.prototype.getChapter = function(cfiStr) { EPUBJS.EpubCFI.prototype.getChapterComponent = function(cfiStr) {
var splitStr = cfiStr.split("!"); var splitStr = cfiStr.split("!");
return splitStr[0]; return splitStr[0];
}; };
EPUBJS.EpubCFI.prototype.getFragment = function(cfiStr) { EPUBJS.EpubCFI.prototype.getPathComponent = function(cfiStr) {
var splitStr = cfiStr.split("!"); var splitStr = cfiStr.split("!");
var pathComponent = splitStr[1] ? splitStr[1].split(":") : '';
return splitStr[1]; return pathComponent[0];
}; };
EPUBJS.EpubCFI.prototype.getOffset = function(cfiStr) { EPUBJS.EpubCFI.prototype.getCharecterOffsetComponent = function(cfiStr) {
var splitStr = cfiStr.split(":"); var splitStr = cfiStr.split(":");
return splitStr[1] || '';
return [splitStr[0], splitStr[1]];
}; };
EPUBJS.EpubCFI.prototype.parse = function(cfiStr) { EPUBJS.EpubCFI.prototype.parse = function(cfiStr) {
var cfi = {}, var cfi = {},
chapSegment, chapSegment,
chapterComponent,
pathComponent,
charecterOffsetComponent,
assertion,
chapId, chapId,
path, path,
end, end,
text; text;
cfi.chapter = this.getChapter(cfiStr); if(cfiStr.indexOf("epubcfi(") === 0) {
// Remove intial epubcfi( and ending )
cfiStr = cfiStr.slice(8, cfiStr.length-1);
}
chapSegment = parseInt(cfi.chapter.split("/")[2]) || false;
cfi.fragment = this.getFragment(cfiStr);
if(!chapSegment || !cfi.fragment) return {spinePos: -1}; chapterComponent = this.getChapterComponent(cfiStr);
pathComponent = this.getPathComponent(cfiStr);
charecterOffsetComponent = this.getCharecterOffsetComponent(cfiStr);
// Make sure this is a valid cfi or return
if(!chapterComponent.length || !pathComponent.length) {
return {spinePos: -1};
}
// Chapter segment is always the second one
chapSegment = chapterComponent.split("/")[2] || '';
if(!chapSegment) return {spinePos:-1};
cfi.spinePos = (parseInt(chapSegment) / 2 - 1 ) || 0; cfi.spinePos = (parseInt(chapSegment) / 2 - 1 ) || 0;
chapId = cfi.chapter.match(/\[(.*)\]/); chapId = chapSegment.match(/\[(.*)\]/);
cfi.spineId = chapId ? chapId[1] : false; cfi.spineId = chapId ? chapId[1] : false;
path = cfi.fragment.split('/'); if(pathComponent.indexOf(',') != -1) {
end = path[path.length-1]; // Handle ranges -- not supported yet
cfi.sections = []; console.warn("CFI Ranges are not supported");
//-- Check for Character Offset
if(parseInt(end) % 2){
text = this.getOffset();
cfi.text = parseInt(text[0]);
cfi.character = parseInt(text[1]);
path.pop(); //-- remove from path to element
} }
path = pathComponent.split('/');
end = path[path.length-1];
cfi.steps = [];
path.forEach(function(part){ path.forEach(function(part){
var index, has_id, id; var type, index, has_brackets, id;
if(!part) return; if(!part) return;
//-- Check if this is a text node or element
index = parseInt(part) / 2 - 1; if(parseInt(part) % 2){
has_id = part.match(/\[(.*)\]/); type = "text";
index = parseInt(part) - 1;
} else {
if(has_id && has_id[1]){ type = "element";
id = has_id[1]; index = parseInt(part) / 2 - 1;
has_brackets = part.match(/\[(.*)\]/);
if(has_brackets && has_brackets[1]){
id = has_brackets[1];
}
} }
cfi.sections.push({ cfi.steps.push({
"type" : type,
'index' : index, 'index' : index,
'id' : id || false 'id' : id || false
}); });
assertion = charecterOffsetComponent.match(/\[(.*)\]/);
if(assertion && assertion[1]){
cfi.characterOffset = parseInt(charecterOffsetComponent.split('[')[0]);
// We arent handling these assertions yet
cfi.textLocationAssertion = assertion[1];
} else {
cfi.characterOffset = parseInt(charecterOffsetComponent);
}
}); });
return cfi; return cfi;
}; };
EPUBJS.EpubCFI.prototype.getElement = function(cfi, _doc) { EPUBJS.EpubCFI.prototype.getElement = function(cfi, _doc) {
var doc = _doc || document, var doc = _doc || document,
sections = cfi.sections, element = doc.getElementsByTagName('html')[0],
element = doc.getElementsByTagName('html')[0], children = Array.prototype.slice.call(element.children),
children = Array.prototype.slice.call(element.children), num, index, part, sections,
num, index, part, text, textBegin, textEnd;
has_id, id;
// sections.shift(); //-- html if(typeof cfi === 'string') {
cfi = this.parse(cfi);
}
sections = cfi.steps;
while(sections && sections.length > 0) { while(sections && sections.length > 0) {
part = sections.shift(); part = sections.shift();
if(part.id){ // Wrap text elements in a span and return that new element
if(part.type === "text") {
text = element.childNodes[part.index];
element = doc.createElement('span');
element.id = "EPUBJS-CFI-MARKER:"+ EPUBJS.core.uuid();
if(cfi.characterOffset) {
textBegin = doc.createTextNode(text.textContent.slice(0, cfi.characterOffset));
textEnd = doc.createTextNode(text.textContent.slice(cfi.characterOffset));
text.parentNode.insertBefore(textEnd, text);
text.parentNode.insertBefore(element, textEnd);
text.parentNode.insertBefore(textBegin, element);
text.parentNode.removeChild(text);
} else {
text.parentNode.insertBefore(element, text);
}
// sort cut to find element by id
} else if(part.id){
element = doc.getElementById(part.id); element = doc.getElementById(part.id);
// find element in parent
}else{ }else{
element = children[part.index];
if(!children) console.error("No Kids", element); if(!children) console.error("No Kids", element);
element = children[part.index];
} }
@ -3223,7 +3277,44 @@ EPUBJS.EpubCFI.prototype.getElement = function(cfi, _doc) {
return element; return element;
}; };
//-- Todo: function to remove IDs to sort EPUBJS.EpubCFI.prototype.compare = function(cfiOne, cfiTwo) {
if(typeof cfiOne === 'string') {
cfiOne = this.parse(cfiOne);
}
if(typeof cfiTwo === 'string') {
cfiTwo = this.parse(cfiTwo);
}
// Compare Spine Positions
if(cfiOne.spinePos > cfiTwo.spinePos) {
return 1;
}
if(cfiOne.spinePos < cfiTwo.spinePos) {
return -1;
}
// Compare Each Step
for (var i = 0; i < cfiOne.steps.length; i++) {
if(!cfiTwo.steps[i]) {
return 1;
}
if(cfiOne.steps[i].index > cfiTwo.steps[i].index) {
return 1;
}
if(cfiOne.steps[i].index < cfiTwo.steps[i].index) {
return -1;
}
// Otherwise continue checking
}
// Compare the charecter offset of the text node
if(cfiOne.characterOffset > cfiTwo.characterOffset) {
return 1;
}
if(cfiOne.characterOffset < cfiTwo.characterOffset) {
return -1;
}
// CFI's are equal
return 0;
};
EPUBJS.Events = function(obj, el){ EPUBJS.Events = function(obj, el){
this.events = {}; this.events = {};
@ -3537,6 +3628,11 @@ EPUBJS.Layout.Fixed.prototype.calculatePages = function(){
pageCount : 1 pageCount : 1
}; };
}; };
EPUBJS.Navigation = function() {
};
// percentage at cfi, nearest page to Cfi, total pages and goto page.
EPUBJS.Parser = function(baseUrl){ EPUBJS.Parser = function(baseUrl){
this.baseUrl = baseUrl || ''; this.baseUrl = baseUrl || '';
@ -3758,7 +3854,7 @@ EPUBJS.Parser.prototype.spine = function(spineXml, manifest){
//-- Add to array to mantain ordering and cross reference with manifest //-- Add to array to mantain ordering and cross reference with manifest
items.forEach(function(item, index){ items.forEach(function(item, index){
var Id = item.getAttribute('idref'); var Id = item.getAttribute('idref');
var cfiBase = epubcfi.generateChapter(spineNodeIndex, index, Id); var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id);
var props = item.getAttribute('properties') || ''; var props = item.getAttribute('properties') || '';
var propArray = props.length ? props.split(' ') : []; var propArray = props.length ? props.split(' ') : [];
var manifestProps = manifest[Id].properties; var manifestProps = manifest[Id].properties;
@ -4527,7 +4623,7 @@ EPUBJS.Renderer.prototype.walk = function(node) {
EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){ EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){
this.visibileEl = this.findFirstVisible(prevEl); this.visibileEl = this.findFirstVisible(prevEl);
return this.epubcfi.generateFragment(this.visibileEl, this.currentChapter.cfiBase); return this.epubcfi.generateCfiFromElement(this.visibileEl, this.currentChapter.cfiBase);
}; };
// Goto a cfi position in the current chapter // Goto a cfi position in the current chapter

View file

@ -217,10 +217,16 @@ EPUBJS.Hooks.register("beforeChapterDisplay").smartimages = function(callback, r
item.style.maxHeight = newHeight + "px"; item.style.maxHeight = newHeight + "px";
item.style.width= "auto"; item.style.width= "auto";
}else{ }else{
newHeight = (height < iheight ? height : iheight); if(height > iheight) {
item.style.maxHeight = newHeight + "px"; item.style.maxHeight = iheight + "px";
item.style.marginTop = iheight - top + "px"; item.style.width= "auto";
item.style.width= "auto"; itemRect = item.getBoundingClientRect();
height = itemRect.height;
}
item.style.display = "block";
item.style["WebkitColumnBreakBefore"] = "always";
item.style["breakBefore"] = "column";
} }
item.setAttribute('data-height', newHeight); item.setAttribute('data-height', newHeight);

2
build/hooks.min.js vendored
View file

@ -1 +1 @@
EPUBJS.Hooks.register("beforeChapterDisplay").endnotes=function(a,b){var c=b.contents.querySelectorAll("a[href]"),d=Array.prototype.slice.call(c),e="epub:type",f="noteref",g=EPUBJS.core.folder(location.pathname),h=g+EPUBJS.cssPath||g,i={};EPUBJS.core.addCss(h+"popup.css",!1,b.render.document.head),d.forEach(function(a){function c(){var c,e=b.height,f=b.width,j=225;o||(c=l.cloneNode(!0),o=c.querySelector("p")),i[k]||(i[k]=document.createElement("div"),i[k].setAttribute("class","popup"),pop_content=document.createElement("div"),i[k].appendChild(pop_content),pop_content.appendChild(o),pop_content.setAttribute("class","pop_content"),chapter.bodyEl.appendChild(i[k]),i[k].addEventListener("mouseover",d,!1),i[k].addEventListener("mouseout",g,!1),b.on("renderer:pageChanged",h,this),b.on("renderer:pageChanged",g,this)),c=i[k],itemRect=a.getBoundingClientRect(),m=itemRect.left,n=itemRect.top,c.classList.add("show"),popRect=c.getBoundingClientRect(),c.style.left=m-popRect.width/2+"px",c.style.top=n+"px",j>e/2.5&&(j=e/2.5,pop_content.style.maxHeight=j+"px"),popRect.height+n>=e-25?(c.style.top=n-popRect.height+"px",c.classList.add("above")):c.classList.remove("above"),m-popRect.width<=0?(c.style.left=m+"px",c.classList.add("left")):c.classList.remove("left"),m+popRect.width/2>=f?(c.style.left=m-300+"px",popRect=c.getBoundingClientRect(),c.style.left=m-popRect.width+"px",popRect.height+n>=e-25?(c.style.top=n-popRect.height+"px",c.classList.add("above")):c.classList.remove("above"),c.classList.add("right")):c.classList.remove("right")}function d(){i[k].classList.add("on")}function g(){i[k].classList.remove("on")}function h(){setTimeout(function(){i[k].classList.remove("show")},100)}var j,k,l,m,n,o,p=a.getAttribute(e);p==f&&(j=a.getAttribute("href"),k=j.replace("#",""),l=b.render.document.getElementById(k),a.addEventListener("mouseover",c,!1),a.addEventListener("mouseout",h,!1))}),a&&a()},EPUBJS.Hooks.register("beforeChapterDisplay").mathml=function(a,b){if(-1!==b.currentChapter.manifestProperties.indexOf("mathml")){b.iframe.contentWindow.mathmlCallback=a;var c=document.createElement("script");c.type="text/x-mathjax-config",c.innerHTML=' MathJax.Hub.Register.StartupHook("End",function () { window.mathmlCallback(); }); MathJax.Hub.Config({jax: ["input/TeX","input/MathML","output/SVG"],extensions: ["tex2jax.js","mml2jax.js","MathEvents.js"],TeX: {extensions: ["noErrors.js","noUndefined.js","autoload-all.js"]},MathMenu: {showRenderer: false},menuSettings: {zoom: "Click"},messageStyle: "none"}); ',b.doc.body.appendChild(c),EPUBJS.core.addScript("http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML",null,b.doc.head)}else a&&a()},EPUBJS.Hooks.register("beforeChapterDisplay").smartimages=function(a,b){var c=b.contents.querySelectorAll("img"),d=Array.prototype.slice.call(c),e=b.height;return"reflowable"!=b.layoutSettings.layout?(a(),void 0):(d.forEach(function(a){function c(){var c,d=a.getBoundingClientRect(),f=d.height,g=d.top,h=a.getAttribute("data-height"),i=h||f,j=Number(getComputedStyle(a,"").fontSize.match(/(\d*(\.\d*)?)px/)[1]),k=j?j/2:0;e=b.contents.clientHeight,0>g&&(g=0),i+g>=e?(e/2>g?(c=e-g-k,a.style.maxHeight=c+"px",a.style.width="auto"):(c=e>i?i:e,a.style.maxHeight=c+"px",a.style.marginTop=e-g+"px",a.style.width="auto"),a.setAttribute("data-height",c)):(a.style.removeProperty("max-height"),a.style.removeProperty("margin-top"))}a.addEventListener("load",c,!1),b.on("renderer:resized",c),b.on("renderer:chapterUnloaded",function(){a.removeEventListener("load",c),b.off("renderer:resized",c)}),c()}),a&&a(),void 0)},EPUBJS.Hooks.register("beforeChapterDisplay").transculsions=function(a,b){var c=b.contents.querySelectorAll("[transclusion]"),d=Array.prototype.slice.call(c);d.forEach(function(a){function c(){j=g,k=h,j>chapter.colWidth&&(d=chapter.colWidth/j,j=chapter.colWidth,k*=d),f.width=j,f.height=k}var d,e=a.getAttribute("ref"),f=document.createElement("iframe"),g=a.getAttribute("width"),h=a.getAttribute("height"),i=a.parentNode,j=g,k=h;c(),b.listenUntil("renderer:resized","renderer:chapterUnloaded",c),f.src=e,i.replaceChild(f,a)}),a&&a()}; EPUBJS.Hooks.register("beforeChapterDisplay").endnotes=function(a,b){var c=b.contents.querySelectorAll("a[href]"),d=Array.prototype.slice.call(c),e="epub:type",f="noteref",g=EPUBJS.core.folder(location.pathname),h=g+EPUBJS.cssPath||g,i={};EPUBJS.core.addCss(h+"popup.css",!1,b.render.document.head),d.forEach(function(a){function c(){var c,e=b.height,f=b.width,j=225;o||(c=l.cloneNode(!0),o=c.querySelector("p")),i[k]||(i[k]=document.createElement("div"),i[k].setAttribute("class","popup"),pop_content=document.createElement("div"),i[k].appendChild(pop_content),pop_content.appendChild(o),pop_content.setAttribute("class","pop_content"),chapter.bodyEl.appendChild(i[k]),i[k].addEventListener("mouseover",d,!1),i[k].addEventListener("mouseout",g,!1),b.on("renderer:pageChanged",h,this),b.on("renderer:pageChanged",g,this)),c=i[k],itemRect=a.getBoundingClientRect(),m=itemRect.left,n=itemRect.top,c.classList.add("show"),popRect=c.getBoundingClientRect(),c.style.left=m-popRect.width/2+"px",c.style.top=n+"px",j>e/2.5&&(j=e/2.5,pop_content.style.maxHeight=j+"px"),popRect.height+n>=e-25?(c.style.top=n-popRect.height+"px",c.classList.add("above")):c.classList.remove("above"),m-popRect.width<=0?(c.style.left=m+"px",c.classList.add("left")):c.classList.remove("left"),m+popRect.width/2>=f?(c.style.left=m-300+"px",popRect=c.getBoundingClientRect(),c.style.left=m-popRect.width+"px",popRect.height+n>=e-25?(c.style.top=n-popRect.height+"px",c.classList.add("above")):c.classList.remove("above"),c.classList.add("right")):c.classList.remove("right")}function d(){i[k].classList.add("on")}function g(){i[k].classList.remove("on")}function h(){setTimeout(function(){i[k].classList.remove("show")},100)}var j,k,l,m,n,o,p=a.getAttribute(e);p==f&&(j=a.getAttribute("href"),k=j.replace("#",""),l=b.render.document.getElementById(k),a.addEventListener("mouseover",c,!1),a.addEventListener("mouseout",h,!1))}),a&&a()},EPUBJS.Hooks.register("beforeChapterDisplay").mathml=function(a,b){if(-1!==b.currentChapter.manifestProperties.indexOf("mathml")){b.iframe.contentWindow.mathmlCallback=a;var c=document.createElement("script");c.type="text/x-mathjax-config",c.innerHTML=' MathJax.Hub.Register.StartupHook("End",function () { window.mathmlCallback(); }); MathJax.Hub.Config({jax: ["input/TeX","input/MathML","output/SVG"],extensions: ["tex2jax.js","mml2jax.js","MathEvents.js"],TeX: {extensions: ["noErrors.js","noUndefined.js","autoload-all.js"]},MathMenu: {showRenderer: false},menuSettings: {zoom: "Click"},messageStyle: "none"}); ',b.doc.body.appendChild(c),EPUBJS.core.addScript("http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML",null,b.doc.head)}else a&&a()},EPUBJS.Hooks.register("beforeChapterDisplay").smartimages=function(a,b){var c=b.contents.querySelectorAll("img"),d=Array.prototype.slice.call(c),e=b.height;return"reflowable"!=b.layoutSettings.layout?(a(),void 0):(d.forEach(function(a){function c(){var c,d=a.getBoundingClientRect(),f=d.height,g=d.top,h=a.getAttribute("data-height"),i=h||f,j=Number(getComputedStyle(a,"").fontSize.match(/(\d*(\.\d*)?)px/)[1]),k=j?j/2:0;e=b.contents.clientHeight,0>g&&(g=0),i+g>=e?(e/2>g?(c=e-g-k,a.style.maxHeight=c+"px",a.style.width="auto"):(i>e&&(a.style.maxHeight=e+"px",a.style.width="auto",d=a.getBoundingClientRect(),i=d.height),a.style.display="block",a.style.WebkitColumnBreakBefore="always",a.style.breakBefore="column"),a.setAttribute("data-height",c)):(a.style.removeProperty("max-height"),a.style.removeProperty("margin-top"))}a.addEventListener("load",c,!1),b.on("renderer:resized",c),b.on("renderer:chapterUnloaded",function(){a.removeEventListener("load",c),b.off("renderer:resized",c)}),c()}),a&&a(),void 0)},EPUBJS.Hooks.register("beforeChapterDisplay").transculsions=function(a,b){var c=b.contents.querySelectorAll("[transclusion]"),d=Array.prototype.slice.call(c);d.forEach(function(a){function c(){j=g,k=h,j>chapter.colWidth&&(d=chapter.colWidth/j,j=chapter.colWidth,k*=d),f.width=j,f.height=k}var d,e=a.getAttribute("ref"),f=document.createElement("iframe"),g=a.getAttribute("width"),h=a.getAttribute("height"),i=a.parentNode,j=g,k=h;c(),b.listenUntil("renderer:resized","renderer:chapterUnloaded",c),f.src=e,i.replaceChild(f,a)}),a&&a()};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

6
demo/js/epub.min.js vendored

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
EPUBJS.Hooks.register("beforeChapterDisplay").endnotes=function(a,b){var c=b.contents.querySelectorAll("a[href]"),d=Array.prototype.slice.call(c),e="epub:type",f="noteref",g=EPUBJS.core.folder(location.pathname),h=g+EPUBJS.cssPath||g,i={};EPUBJS.core.addCss(h+"popup.css",!1,b.render.document.head),d.forEach(function(a){function c(){var c,e=b.height,f=b.width,j=225;o||(c=l.cloneNode(!0),o=c.querySelector("p")),i[k]||(i[k]=document.createElement("div"),i[k].setAttribute("class","popup"),pop_content=document.createElement("div"),i[k].appendChild(pop_content),pop_content.appendChild(o),pop_content.setAttribute("class","pop_content"),chapter.bodyEl.appendChild(i[k]),i[k].addEventListener("mouseover",d,!1),i[k].addEventListener("mouseout",g,!1),b.on("renderer:pageChanged",h,this),b.on("renderer:pageChanged",g,this)),c=i[k],itemRect=a.getBoundingClientRect(),m=itemRect.left,n=itemRect.top,c.classList.add("show"),popRect=c.getBoundingClientRect(),c.style.left=m-popRect.width/2+"px",c.style.top=n+"px",j>e/2.5&&(j=e/2.5,pop_content.style.maxHeight=j+"px"),popRect.height+n>=e-25?(c.style.top=n-popRect.height+"px",c.classList.add("above")):c.classList.remove("above"),m-popRect.width<=0?(c.style.left=m+"px",c.classList.add("left")):c.classList.remove("left"),m+popRect.width/2>=f?(c.style.left=m-300+"px",popRect=c.getBoundingClientRect(),c.style.left=m-popRect.width+"px",popRect.height+n>=e-25?(c.style.top=n-popRect.height+"px",c.classList.add("above")):c.classList.remove("above"),c.classList.add("right")):c.classList.remove("right")}function d(){i[k].classList.add("on")}function g(){i[k].classList.remove("on")}function h(){setTimeout(function(){i[k].classList.remove("show")},100)}var j,k,l,m,n,o,p=a.getAttribute(e);p==f&&(j=a.getAttribute("href"),k=j.replace("#",""),l=b.render.document.getElementById(k),a.addEventListener("mouseover",c,!1),a.addEventListener("mouseout",h,!1))}),a&&a()},EPUBJS.Hooks.register("beforeChapterDisplay").mathml=function(a,b){if(-1!==b.currentChapter.manifestProperties.indexOf("mathml")){b.iframe.contentWindow.mathmlCallback=a;var c=document.createElement("script");c.type="text/x-mathjax-config",c.innerHTML=' MathJax.Hub.Register.StartupHook("End",function () { window.mathmlCallback(); }); MathJax.Hub.Config({jax: ["input/TeX","input/MathML","output/SVG"],extensions: ["tex2jax.js","mml2jax.js","MathEvents.js"],TeX: {extensions: ["noErrors.js","noUndefined.js","autoload-all.js"]},MathMenu: {showRenderer: false},menuSettings: {zoom: "Click"},messageStyle: "none"}); ',b.doc.body.appendChild(c),EPUBJS.core.addScript("http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML",null,b.doc.head)}else a&&a()},EPUBJS.Hooks.register("beforeChapterDisplay").smartimages=function(a,b){var c=b.contents.querySelectorAll("img"),d=Array.prototype.slice.call(c),e=b.height;return"reflowable"!=b.layoutSettings.layout?(a(),void 0):(d.forEach(function(a){function c(){var c,d=a.getBoundingClientRect(),f=d.height,g=d.top,h=a.getAttribute("data-height"),i=h||f,j=Number(getComputedStyle(a,"").fontSize.match(/(\d*(\.\d*)?)px/)[1]),k=j?j/2:0;e=b.contents.clientHeight,0>g&&(g=0),i+g>=e?(e/2>g?(c=e-g-k,a.style.maxHeight=c+"px",a.style.width="auto"):(c=e>i?i:e,a.style.maxHeight=c+"px",a.style.marginTop=e-g+"px",a.style.width="auto"),a.setAttribute("data-height",c)):(a.style.removeProperty("max-height"),a.style.removeProperty("margin-top"))}a.addEventListener("load",c,!1),b.on("renderer:resized",c),b.on("renderer:chapterUnloaded",function(){a.removeEventListener("load",c),b.off("renderer:resized",c)}),c()}),a&&a(),void 0)},EPUBJS.Hooks.register("beforeChapterDisplay").transculsions=function(a,b){var c=b.contents.querySelectorAll("[transclusion]"),d=Array.prototype.slice.call(c);d.forEach(function(a){function c(){j=g,k=h,j>chapter.colWidth&&(d=chapter.colWidth/j,j=chapter.colWidth,k*=d),f.width=j,f.height=k}var d,e=a.getAttribute("ref"),f=document.createElement("iframe"),g=a.getAttribute("width"),h=a.getAttribute("height"),i=a.parentNode,j=g,k=h;c(),b.listenUntil("renderer:resized","renderer:chapterUnloaded",c),f.src=e,i.replaceChild(f,a)}),a&&a()}; EPUBJS.Hooks.register("beforeChapterDisplay").endnotes=function(a,b){var c=b.contents.querySelectorAll("a[href]"),d=Array.prototype.slice.call(c),e="epub:type",f="noteref",g=EPUBJS.core.folder(location.pathname),h=g+EPUBJS.cssPath||g,i={};EPUBJS.core.addCss(h+"popup.css",!1,b.render.document.head),d.forEach(function(a){function c(){var c,e=b.height,f=b.width,j=225;o||(c=l.cloneNode(!0),o=c.querySelector("p")),i[k]||(i[k]=document.createElement("div"),i[k].setAttribute("class","popup"),pop_content=document.createElement("div"),i[k].appendChild(pop_content),pop_content.appendChild(o),pop_content.setAttribute("class","pop_content"),chapter.bodyEl.appendChild(i[k]),i[k].addEventListener("mouseover",d,!1),i[k].addEventListener("mouseout",g,!1),b.on("renderer:pageChanged",h,this),b.on("renderer:pageChanged",g,this)),c=i[k],itemRect=a.getBoundingClientRect(),m=itemRect.left,n=itemRect.top,c.classList.add("show"),popRect=c.getBoundingClientRect(),c.style.left=m-popRect.width/2+"px",c.style.top=n+"px",j>e/2.5&&(j=e/2.5,pop_content.style.maxHeight=j+"px"),popRect.height+n>=e-25?(c.style.top=n-popRect.height+"px",c.classList.add("above")):c.classList.remove("above"),m-popRect.width<=0?(c.style.left=m+"px",c.classList.add("left")):c.classList.remove("left"),m+popRect.width/2>=f?(c.style.left=m-300+"px",popRect=c.getBoundingClientRect(),c.style.left=m-popRect.width+"px",popRect.height+n>=e-25?(c.style.top=n-popRect.height+"px",c.classList.add("above")):c.classList.remove("above"),c.classList.add("right")):c.classList.remove("right")}function d(){i[k].classList.add("on")}function g(){i[k].classList.remove("on")}function h(){setTimeout(function(){i[k].classList.remove("show")},100)}var j,k,l,m,n,o,p=a.getAttribute(e);p==f&&(j=a.getAttribute("href"),k=j.replace("#",""),l=b.render.document.getElementById(k),a.addEventListener("mouseover",c,!1),a.addEventListener("mouseout",h,!1))}),a&&a()},EPUBJS.Hooks.register("beforeChapterDisplay").mathml=function(a,b){if(-1!==b.currentChapter.manifestProperties.indexOf("mathml")){b.iframe.contentWindow.mathmlCallback=a;var c=document.createElement("script");c.type="text/x-mathjax-config",c.innerHTML=' MathJax.Hub.Register.StartupHook("End",function () { window.mathmlCallback(); }); MathJax.Hub.Config({jax: ["input/TeX","input/MathML","output/SVG"],extensions: ["tex2jax.js","mml2jax.js","MathEvents.js"],TeX: {extensions: ["noErrors.js","noUndefined.js","autoload-all.js"]},MathMenu: {showRenderer: false},menuSettings: {zoom: "Click"},messageStyle: "none"}); ',b.doc.body.appendChild(c),EPUBJS.core.addScript("http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML",null,b.doc.head)}else a&&a()},EPUBJS.Hooks.register("beforeChapterDisplay").smartimages=function(a,b){var c=b.contents.querySelectorAll("img"),d=Array.prototype.slice.call(c),e=b.height;return"reflowable"!=b.layoutSettings.layout?(a(),void 0):(d.forEach(function(a){function c(){var c,d=a.getBoundingClientRect(),f=d.height,g=d.top,h=a.getAttribute("data-height"),i=h||f,j=Number(getComputedStyle(a,"").fontSize.match(/(\d*(\.\d*)?)px/)[1]),k=j?j/2:0;e=b.contents.clientHeight,0>g&&(g=0),i+g>=e?(e/2>g?(c=e-g-k,a.style.maxHeight=c+"px",a.style.width="auto"):(i>e&&(a.style.maxHeight=e+"px",a.style.width="auto",d=a.getBoundingClientRect(),i=d.height),a.style.display="block",a.style.WebkitColumnBreakBefore="always",a.style.breakBefore="column"),a.setAttribute("data-height",c)):(a.style.removeProperty("max-height"),a.style.removeProperty("margin-top"))}a.addEventListener("load",c,!1),b.on("renderer:resized",c),b.on("renderer:chapterUnloaded",function(){a.removeEventListener("load",c),b.off("renderer:resized",c)}),c()}),a&&a(),void 0)},EPUBJS.Hooks.register("beforeChapterDisplay").transculsions=function(a,b){var c=b.contents.querySelectorAll("[transclusion]"),d=Array.prototype.slice.call(c);d.forEach(function(a){function c(){j=g,k=h,j>chapter.colWidth&&(d=chapter.colWidth/j,j=chapter.colWidth,k*=d),f.width=j,f.height=k}var d,e=a.getAttribute("ref"),f=document.createElement("iframe"),g=a.getAttribute("width"),h=a.getAttribute("height"),i=a.parentNode,j=g,k=h;c(),b.listenUntil("renderer:resized","renderer:chapterUnloaded",c),f.src=e,i.replaceChild(f,a)}),a&&a()};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -32,10 +32,16 @@ EPUBJS.Hooks.register("beforeChapterDisplay").smartimages = function(callback, r
item.style.maxHeight = newHeight + "px"; item.style.maxHeight = newHeight + "px";
item.style.width= "auto"; item.style.width= "auto";
}else{ }else{
newHeight = (height < iheight ? height : iheight); if(height > iheight) {
item.style.maxHeight = newHeight + "px"; item.style.maxHeight = iheight + "px";
item.style.marginTop = iheight - top + "px"; item.style.width= "auto";
item.style.width= "auto"; itemRect = item.getBoundingClientRect();
height = itemRect.height;
}
item.style.display = "block";
item.style["WebkitColumnBreakBefore"] = "always";
item.style["breakBefore"] = "column";
} }
item.setAttribute('data-height', newHeight); item.setAttribute('data-height', newHeight);

View file

@ -303,3 +303,14 @@ EPUBJS.core.resolveUrl = function(base, path) {
return url.join("/"); return url.join("/");
}; };
// 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;
};

View file

@ -2,8 +2,7 @@ EPUBJS.EpubCFI = function(cfiStr){
if(cfiStr) return this.parse(cfiStr); if(cfiStr) return this.parse(cfiStr);
}; };
EPUBJS.EpubCFI.prototype.generateChapter = function(_spineNodeIndex, _pos, id) { EPUBJS.EpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id) {
var pos = parseInt(_pos), var pos = parseInt(_pos),
spineNodeIndex = _spineNodeIndex + 1, spineNodeIndex = _spineNodeIndex + 1,
cfi = '/'+spineNodeIndex+'/'; cfi = '/'+spineNodeIndex+'/';
@ -12,27 +11,23 @@ EPUBJS.EpubCFI.prototype.generateChapter = function(_spineNodeIndex, _pos, id) {
if(id) cfi += "[" + id + "]"; if(id) cfi += "[" + id + "]";
cfi += "!"; //cfi += "!";
return cfi; return cfi;
}; };
EPUBJS.EpubCFI.prototype.generatePathComponent = function(steps) {
var parts = [];
EPUBJS.EpubCFI.prototype.generateFragment = function(element, chapter) { steps.forEach(function(part){
var path = this.pathTo(element),
parts = [];
if(chapter) parts.push(chapter);
path.forEach(function(part){
var segment = ''; var segment = '';
segment += (part.index + 1) * 2; segment += (part.index + 1) * 2;
if(part.id && if(part.id && part.id.slice(0, 6) === "EPUBJS") {
part.id.slice(0, 6) != "EPUBJS") { //-- ignore internal @EPUBJS ids //-- ignore internal @EPUBJS ids for
return;
} else if(part.id) {
segment += "[" + part.id + "]"; segment += "[" + part.id + "]";
} }
parts.push(segment); parts.push(segment);
@ -41,6 +36,13 @@ EPUBJS.EpubCFI.prototype.generateFragment = function(element, chapter) {
return parts.join('/'); return parts.join('/');
}; };
EPUBJS.EpubCFI.prototype.generateCfiFromElement = function(element, chapter) {
var steps = this.pathTo(element);
var path = this.generatePathComponent(steps);
return "epubcfi(" + chapter + "!" + path + ")";
};
EPUBJS.EpubCFI.prototype.pathTo = function(node) { EPUBJS.EpubCFI.prototype.pathTo = function(node) {
var stack = [], var stack = [],
children; children;
@ -61,110 +63,152 @@ EPUBJS.EpubCFI.prototype.pathTo = function(node) {
return stack; return stack;
}; };
EPUBJS.EpubCFI.prototype.getChapter = function(cfiStr) { EPUBJS.EpubCFI.prototype.getChapterComponent = function(cfiStr) {
var splitStr = cfiStr.split("!"); var splitStr = cfiStr.split("!");
return splitStr[0]; return splitStr[0];
}; };
EPUBJS.EpubCFI.prototype.getFragment = function(cfiStr) { EPUBJS.EpubCFI.prototype.getPathComponent = function(cfiStr) {
var splitStr = cfiStr.split("!"); var splitStr = cfiStr.split("!");
var pathComponent = splitStr[1] ? splitStr[1].split(":") : '';
return splitStr[1]; return pathComponent[0];
}; };
EPUBJS.EpubCFI.prototype.getOffset = function(cfiStr) { EPUBJS.EpubCFI.prototype.getCharecterOffsetComponent = function(cfiStr) {
var splitStr = cfiStr.split(":"); var splitStr = cfiStr.split(":");
return splitStr[1] || '';
return [splitStr[0], splitStr[1]];
}; };
EPUBJS.EpubCFI.prototype.parse = function(cfiStr) { EPUBJS.EpubCFI.prototype.parse = function(cfiStr) {
var cfi = {}, var cfi = {},
chapSegment, chapSegment,
chapterComponent,
pathComponent,
charecterOffsetComponent,
assertion,
chapId, chapId,
path, path,
end, end,
text; text;
cfi.chapter = this.getChapter(cfiStr); if(cfiStr.indexOf("epubcfi(") === 0) {
// Remove intial epubcfi( and ending )
cfiStr = cfiStr.slice(8, cfiStr.length-1);
}
chapSegment = parseInt(cfi.chapter.split("/")[2]) || false;
cfi.fragment = this.getFragment(cfiStr);
if(!chapSegment || !cfi.fragment) return {spinePos: -1}; chapterComponent = this.getChapterComponent(cfiStr);
pathComponent = this.getPathComponent(cfiStr);
charecterOffsetComponent = this.getCharecterOffsetComponent(cfiStr);
// Make sure this is a valid cfi or return
if(!chapterComponent.length || !pathComponent.length) {
return {spinePos: -1};
}
// Chapter segment is always the second one
chapSegment = chapterComponent.split("/")[2] || '';
if(!chapSegment) return {spinePos:-1};
cfi.spinePos = (parseInt(chapSegment) / 2 - 1 ) || 0; cfi.spinePos = (parseInt(chapSegment) / 2 - 1 ) || 0;
chapId = cfi.chapter.match(/\[(.*)\]/); chapId = chapSegment.match(/\[(.*)\]/);
cfi.spineId = chapId ? chapId[1] : false; cfi.spineId = chapId ? chapId[1] : false;
path = cfi.fragment.split('/'); if(pathComponent.indexOf(',') != -1) {
end = path[path.length-1]; // Handle ranges -- not supported yet
cfi.sections = []; console.warn("CFI Ranges are not supported");
//-- Check for Character Offset
if(parseInt(end) % 2){
text = this.getOffset();
cfi.text = parseInt(text[0]);
cfi.character = parseInt(text[1]);
path.pop(); //-- remove from path to element
} }
path = pathComponent.split('/');
end = path[path.length-1];
cfi.steps = [];
path.forEach(function(part){ path.forEach(function(part){
var index, has_id, id; var type, index, has_brackets, id;
if(!part) return; if(!part) return;
//-- Check if this is a text node or element
index = parseInt(part) / 2 - 1; if(parseInt(part) % 2){
has_id = part.match(/\[(.*)\]/); type = "text";
index = parseInt(part) - 1;
} else {
if(has_id && has_id[1]){ type = "element";
id = has_id[1]; index = parseInt(part) / 2 - 1;
has_brackets = part.match(/\[(.*)\]/);
if(has_brackets && has_brackets[1]){
id = has_brackets[1];
}
} }
cfi.sections.push({ cfi.steps.push({
"type" : type,
'index' : index, 'index' : index,
'id' : id || false 'id' : id || false
}); });
assertion = charecterOffsetComponent.match(/\[(.*)\]/);
if(assertion && assertion[1]){
cfi.characterOffset = parseInt(charecterOffsetComponent.split('[')[0]);
// We arent handling these assertions yet
cfi.textLocationAssertion = assertion[1];
} else {
cfi.characterOffset = parseInt(charecterOffsetComponent);
}
}); });
return cfi; return cfi;
}; };
EPUBJS.EpubCFI.prototype.getElement = function(cfi, _doc) { EPUBJS.EpubCFI.prototype.getElement = function(cfi, _doc) {
var doc = _doc || document, var doc = _doc || document,
sections = cfi.sections, element = doc.getElementsByTagName('html')[0],
element = doc.getElementsByTagName('html')[0], children = Array.prototype.slice.call(element.children),
children = Array.prototype.slice.call(element.children), num, index, part, sections,
num, index, part, text, textBegin, textEnd;
has_id, id;
// sections.shift(); //-- html if(typeof cfi === 'string') {
cfi = this.parse(cfi);
}
sections = cfi.steps;
while(sections && sections.length > 0) { while(sections && sections.length > 0) {
part = sections.shift(); part = sections.shift();
if(part.id){ // Wrap text elements in a span and return that new element
if(part.type === "text") {
text = element.childNodes[part.index];
element = doc.createElement('span');
element.id = "EPUBJS-CFI-MARKER:"+ EPUBJS.core.uuid();
if(cfi.characterOffset) {
textBegin = doc.createTextNode(text.textContent.slice(0, cfi.characterOffset));
textEnd = doc.createTextNode(text.textContent.slice(cfi.characterOffset));
text.parentNode.insertBefore(textEnd, text);
text.parentNode.insertBefore(element, textEnd);
text.parentNode.insertBefore(textBegin, element);
text.parentNode.removeChild(text);
} else {
text.parentNode.insertBefore(element, text);
}
// sort cut to find element by id
} else if(part.id){
element = doc.getElementById(part.id); element = doc.getElementById(part.id);
// find element in parent
}else{ }else{
element = children[part.index];
if(!children) console.error("No Kids", element); if(!children) console.error("No Kids", element);
element = children[part.index];
} }
@ -175,4 +219,41 @@ EPUBJS.EpubCFI.prototype.getElement = function(cfi, _doc) {
return element; return element;
}; };
//-- Todo: function to remove IDs to sort EPUBJS.EpubCFI.prototype.compare = function(cfiOne, cfiTwo) {
if(typeof cfiOne === 'string') {
cfiOne = this.parse(cfiOne);
}
if(typeof cfiTwo === 'string') {
cfiTwo = this.parse(cfiTwo);
}
// Compare Spine Positions
if(cfiOne.spinePos > cfiTwo.spinePos) {
return 1;
}
if(cfiOne.spinePos < cfiTwo.spinePos) {
return -1;
}
// Compare Each Step
for (var i = 0; i < cfiOne.steps.length; i++) {
if(!cfiTwo.steps[i]) {
return 1;
}
if(cfiOne.steps[i].index > cfiTwo.steps[i].index) {
return 1;
}
if(cfiOne.steps[i].index < cfiTwo.steps[i].index) {
return -1;
}
// Otherwise continue checking
}
// Compare the charecter offset of the text node
if(cfiOne.characterOffset > cfiTwo.characterOffset) {
return 1;
}
if(cfiOne.characterOffset < cfiTwo.characterOffset) {
return -1;
}
// CFI's are equal
return 0;
};

View file

@ -0,0 +1,5 @@
EPUBJS.Navigation = function() {
};
// percentage at cfi, nearest page to Cfi, total pages and goto page.

View file

@ -218,7 +218,7 @@ EPUBJS.Parser.prototype.spine = function(spineXml, manifest){
//-- Add to array to mantain ordering and cross reference with manifest //-- Add to array to mantain ordering and cross reference with manifest
items.forEach(function(item, index){ items.forEach(function(item, index){
var Id = item.getAttribute('idref'); var Id = item.getAttribute('idref');
var cfiBase = epubcfi.generateChapter(spineNodeIndex, index, Id); var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id);
var props = item.getAttribute('properties') || ''; var props = item.getAttribute('properties') || '';
var propArray = props.length ? props.split(' ') : []; var propArray = props.length ? props.split(' ') : [];
var manifestProps = manifest[Id].properties; var manifestProps = manifest[Id].properties;

View file

@ -425,7 +425,7 @@ EPUBJS.Renderer.prototype.walk = function(node) {
EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){ EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){
this.visibileEl = this.findFirstVisible(prevEl); this.visibileEl = this.findFirstVisible(prevEl);
return this.epubcfi.generateFragment(this.visibileEl, this.currentChapter.cfiBase); return this.epubcfi.generateCfiFromElement(this.visibileEl, this.currentChapter.cfiBase);
}; };
// Goto a cfi position in the current chapter // Goto a cfi position in the current chapter