feat(epub): complete wxread parity scope
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
(function() {
|
||||
if (!window.rangy) {
|
||||
window.rangy = {};
|
||||
}
|
||||
if (window.rangy.serializeRange && window.rangy.deserializeRange) {
|
||||
return;
|
||||
}
|
||||
|
||||
function normalizeHref(rawHref) {
|
||||
if (!rawHref) { return ''; }
|
||||
var value = String(rawHref);
|
||||
value = value.replace(/^.*?:\/\/[^/]+\//, '');
|
||||
value = value.split('#')[0];
|
||||
value = value.replace(/^\/+/, '');
|
||||
try {
|
||||
value = decodeURIComponent(value);
|
||||
} catch (error) {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function nodePath(node) {
|
||||
var path = [];
|
||||
var current = node;
|
||||
while (current && current !== current.ownerDocument) {
|
||||
var parent = current.parentNode;
|
||||
if (!parent) { break; }
|
||||
var index = Array.prototype.indexOf.call(parent.childNodes, current);
|
||||
path.unshift(index);
|
||||
current = parent;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
function nodeFromPath(doc, path) {
|
||||
var current = doc;
|
||||
for (var index = 0; index < path.length; index += 1) {
|
||||
if (!current || !current.childNodes || current.childNodes.length <= path[index]) {
|
||||
return null;
|
||||
}
|
||||
current = current.childNodes[path[index]];
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
function documentContexts(rootDoc) {
|
||||
var items = [];
|
||||
if (!rootDoc) { return items; }
|
||||
items.push(rootDoc);
|
||||
var frames = rootDoc.querySelectorAll ? rootDoc.querySelectorAll('iframe') : [];
|
||||
Array.prototype.forEach.call(frames, function(frame) {
|
||||
try {
|
||||
if (!frame.contentDocument) { return; }
|
||||
documentContexts(frame.contentDocument).forEach(function(item) {
|
||||
items.push(item);
|
||||
});
|
||||
} catch (error) {
|
||||
}
|
||||
});
|
||||
return items;
|
||||
}
|
||||
|
||||
window.rangy.serializeRange = function(range, doc) {
|
||||
var ownerDocument = doc || (range && range.startContainer && range.startContainer.ownerDocument) || document;
|
||||
return JSON.stringify({
|
||||
kind: 'dom-range',
|
||||
documentHref: normalizeHref(ownerDocument.location && ownerDocument.location.href),
|
||||
startPath: nodePath(range.startContainer),
|
||||
startOffset: range.startOffset,
|
||||
endPath: nodePath(range.endContainer),
|
||||
endOffset: range.endOffset
|
||||
});
|
||||
};
|
||||
|
||||
window.rangy.deserializeRange = function(rangeInfo, rootDoc) {
|
||||
try {
|
||||
var payload = typeof rangeInfo === 'string' ? JSON.parse(rangeInfo) : rangeInfo;
|
||||
var documentHref = normalizeHref(payload.documentHref);
|
||||
var resolvedDocument = (documentContexts(rootDoc || document).find(function(candidate) {
|
||||
return normalizeHref(candidate.location && candidate.location.href) === documentHref;
|
||||
})) || (rootDoc || document);
|
||||
var startNode = nodeFromPath(resolvedDocument, payload.startPath || []);
|
||||
var endNode = nodeFromPath(resolvedDocument, payload.endPath || []);
|
||||
if (!startNode || !endNode) { return null; }
|
||||
var range = resolvedDocument.createRange();
|
||||
range.setStart(startNode, payload.startOffset || 0);
|
||||
range.setEnd(endNode, payload.endOffset || 0);
|
||||
return range;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user