mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-03 14:59:18 +02:00
326 lines
9.8 KiB
JavaScript
326 lines
9.8 KiB
JavaScript
// Generated by CoffeeScript 1.6.3
|
|
var Range,
|
|
__hasProp = {}.hasOwnProperty,
|
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
|
|
Range = {};
|
|
|
|
Range.sniff = function(r) {
|
|
if (r.commonAncestorContainer != null) {
|
|
return new Range.BrowserRange(r);
|
|
} else if (typeof r.start === "string") {
|
|
return new Range.SerializedRange(r);
|
|
} else if (r.start && typeof r.start === "object") {
|
|
return new Range.NormalizedRange(r);
|
|
} else {
|
|
console.error(_t("Could not sniff range type"));
|
|
return false;
|
|
}
|
|
};
|
|
|
|
Range.nodeFromXPath = function(xpath, root) {
|
|
var customResolver, evaluateXPath, namespace, node, segment;
|
|
if (root == null) {
|
|
root = document;
|
|
}
|
|
this.document = root.ownerDocument || document;
|
|
evaluateXPath = function(xp, nsResolver) {
|
|
var exception;
|
|
if (nsResolver == null) {
|
|
nsResolver = null;
|
|
}
|
|
try {
|
|
return this.document.evaluate('.' + xp, root, nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
|
} catch (_error) {
|
|
exception = _error;
|
|
console.log("XPath evaluation failed.");
|
|
console.log("Trying fallback...");
|
|
return Util.nodeFromXPath(xp, root);
|
|
}
|
|
};
|
|
if (!$.isXMLDoc(document.documentElement)) {
|
|
return evaluateXPath(xpath);
|
|
} else {
|
|
customResolver = document.createNSResolver(document.ownerDocument === null ? document.documentElement : document.ownerDocument.documentElement);
|
|
node = evaluateXPath(xpath, customResolver);
|
|
if (!node) {
|
|
xpath = ((function() {
|
|
var _i, _len, _ref, _results;
|
|
_ref = xpath.split('/');
|
|
_results = [];
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
segment = _ref[_i];
|
|
if (segment && segment.indexOf(':') === -1) {
|
|
_results.push(segment.replace(/^([a-z]+)/, 'xhtml:$1'));
|
|
} else {
|
|
_results.push(segment);
|
|
}
|
|
}
|
|
return _results;
|
|
})()).join('/');
|
|
namespace = document.lookupNamespaceURI(null);
|
|
customResolver = function(ns) {
|
|
if (ns === 'xhtml') {
|
|
return namespace;
|
|
} else {
|
|
return document.documentElement.getAttribute('xmlns:' + ns);
|
|
}
|
|
};
|
|
node = evaluateXPath(xpath, customResolver);
|
|
}
|
|
return node;
|
|
}
|
|
};
|
|
|
|
Range.RangeError = (function(_super) {
|
|
__extends(RangeError, _super);
|
|
|
|
function RangeError(type, message, parent) {
|
|
this.type = type;
|
|
this.message = message;
|
|
this.parent = parent != null ? parent : null;
|
|
RangeError.__super__.constructor.call(this, this.message);
|
|
}
|
|
|
|
return RangeError;
|
|
|
|
})(Error);
|
|
|
|
Range.BrowserRange = (function() {
|
|
function BrowserRange(obj) {
|
|
this.commonAncestorContainer = obj.commonAncestorContainer;
|
|
this.startContainer = obj.startContainer;
|
|
this.startOffset = obj.startOffset;
|
|
this.endContainer = obj.endContainer;
|
|
this.endOffset = obj.endOffset;
|
|
}
|
|
|
|
BrowserRange.prototype.normalize = function(root) {
|
|
var it, node, nr, offset, p, r, _i, _len, _ref;
|
|
if (this.tainted) {
|
|
console.error(_t("You may only call normalize() once on a BrowserRange!"));
|
|
return false;
|
|
} else {
|
|
this.tainted = true;
|
|
}
|
|
r = {};
|
|
nr = {};
|
|
_ref = ['start', 'end'];
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
p = _ref[_i];
|
|
node = this[p + 'Container'];
|
|
offset = this[p + 'Offset'];
|
|
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
it = node.childNodes[offset];
|
|
node = it || node.childNodes[offset - 1];
|
|
if (node.nodeType === Node.ELEMENT_NODE && !node.firstChild) {
|
|
it = null;
|
|
node = node.previousSibling;
|
|
}
|
|
while (node.nodeType !== Node.TEXT_NODE) {
|
|
node = node.firstChild;
|
|
}
|
|
offset = it ? 0 : node.nodeValue.length;
|
|
}
|
|
r[p] = node;
|
|
r[p + 'Offset'] = offset;
|
|
}
|
|
nr.start = r.startOffset > 0 ? r.start.splitText(r.startOffset) : r.start;
|
|
if (r.start === r.end) {
|
|
if ((r.endOffset - r.startOffset) < nr.start.nodeValue.length) {
|
|
nr.start.splitText(r.endOffset - r.startOffset);
|
|
}
|
|
nr.end = nr.start;
|
|
} else {
|
|
if (r.endOffset < r.end.nodeValue.length) {
|
|
r.end.splitText(r.endOffset);
|
|
}
|
|
nr.end = r.end;
|
|
}
|
|
nr.commonAncestor = this.commonAncestorContainer;
|
|
while (nr.commonAncestor.nodeType !== Node.ELEMENT_NODE) {
|
|
nr.commonAncestor = nr.commonAncestor.parentNode;
|
|
}
|
|
return new Range.NormalizedRange(nr);
|
|
};
|
|
|
|
BrowserRange.prototype.serialize = function(root, ignoreSelector) {
|
|
return this.normalize(root).serialize(root, ignoreSelector);
|
|
};
|
|
|
|
return BrowserRange;
|
|
|
|
})();
|
|
|
|
Range.NormalizedRange = (function() {
|
|
function NormalizedRange(obj) {
|
|
this.commonAncestor = obj.commonAncestor;
|
|
this.start = obj.start;
|
|
this.end = obj.end;
|
|
}
|
|
|
|
NormalizedRange.prototype.normalize = function(root) {
|
|
return this;
|
|
};
|
|
|
|
NormalizedRange.prototype.limit = function(bounds) {
|
|
var nodes, parent, startParents, _i, _len, _ref;
|
|
nodes = $.grep(this.textNodes(), function(node) {
|
|
return node.parentNode === bounds || $.contains(bounds, node.parentNode);
|
|
});
|
|
if (!nodes.length) {
|
|
return null;
|
|
}
|
|
this.start = nodes[0];
|
|
this.end = nodes[nodes.length - 1];
|
|
startParents = $(this.start).parents();
|
|
_ref = $(this.end).parents();
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
parent = _ref[_i];
|
|
if (startParents.index(parent) !== -1) {
|
|
this.commonAncestor = parent;
|
|
break;
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
|
|
NormalizedRange.prototype.serialize = function(root, ignoreSelector) {
|
|
var end, serialization, start;
|
|
serialization = function(node, isEnd) {
|
|
var n, nodes, offset, origParent, textNodes, xpath, _i, _len;
|
|
if (ignoreSelector) {
|
|
origParent = $(node).parents(":not(" + ignoreSelector + ")").eq(0);
|
|
} else {
|
|
origParent = $(node).parent();
|
|
}
|
|
xpath = Util.xpathFromNode(origParent, root)[0];
|
|
textNodes = Util.getTextNodes(origParent);
|
|
nodes = textNodes.slice(0, textNodes.index(node));
|
|
offset = 0;
|
|
for (_i = 0, _len = nodes.length; _i < _len; _i++) {
|
|
n = nodes[_i];
|
|
offset += n.nodeValue.length;
|
|
}
|
|
if (isEnd) {
|
|
return [xpath, offset + node.nodeValue.length];
|
|
} else {
|
|
return [xpath, offset];
|
|
}
|
|
};
|
|
start = serialization(this.start);
|
|
end = serialization(this.end, true);
|
|
return new Range.SerializedRange({
|
|
start: start[0],
|
|
end: end[0],
|
|
startOffset: start[1],
|
|
endOffset: end[1]
|
|
});
|
|
};
|
|
|
|
NormalizedRange.prototype.text = function() {
|
|
var node;
|
|
return ((function() {
|
|
var _i, _len, _ref, _results;
|
|
_ref = this.textNodes();
|
|
_results = [];
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
node = _ref[_i];
|
|
_results.push(node.nodeValue);
|
|
}
|
|
return _results;
|
|
}).call(this)).join('');
|
|
};
|
|
|
|
NormalizedRange.prototype.textNodes = function() {
|
|
var end, start, textNodes, _ref;
|
|
textNodes = Util.getTextNodes($(this.commonAncestor));
|
|
_ref = [textNodes.index(this.start), textNodes.index(this.end)], start = _ref[0], end = _ref[1];
|
|
return $.makeArray(textNodes.slice(start, +end + 1 || 9e9));
|
|
};
|
|
|
|
NormalizedRange.prototype.toRange = function() {
|
|
var range;
|
|
range = document.createRange();
|
|
range.setStartBefore(this.start);
|
|
range.setEndAfter(this.end);
|
|
return range;
|
|
};
|
|
|
|
return NormalizedRange;
|
|
|
|
})();
|
|
|
|
Range.SerializedRange = (function() {
|
|
function SerializedRange(obj) {
|
|
this.start = obj.start;
|
|
this.startOffset = obj.startOffset;
|
|
this.end = obj.end;
|
|
this.endOffset = obj.endOffset;
|
|
}
|
|
|
|
SerializedRange.prototype.normalize = function(root) {
|
|
var contains, e, length, node, p, range, tn, _i, _j, _len, _len1, _ref, _ref1;
|
|
range = {};
|
|
_ref = ['start', 'end'];
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
p = _ref[_i];
|
|
try {
|
|
node = Range.nodeFromXPath(this[p], root);
|
|
} catch (_error) {
|
|
e = _error;
|
|
throw new Range.RangeError(p, ("Error while finding " + p + " node: " + this[p] + ": ") + e, e);
|
|
}
|
|
if (!node) {
|
|
throw new Range.RangeError(p, "Couldn't find " + p + " node: " + this[p]);
|
|
}
|
|
length = 0;
|
|
_ref1 = Util.getTextNodes($(node));
|
|
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
|
tn = _ref1[_j];
|
|
if (length + tn.nodeValue.length >= this[p + 'Offset']) {
|
|
range[p + 'Container'] = tn;
|
|
range[p + 'Offset'] = this[p + 'Offset'] - length;
|
|
break;
|
|
} else {
|
|
length += tn.nodeValue.length;
|
|
}
|
|
}
|
|
if (range[p + 'Offset'] == null) {
|
|
throw new Range.RangeError("" + p + "offset", "Couldn't find offset " + this[p + 'Offset'] + " in element " + this[p]);
|
|
}
|
|
}
|
|
contains = document.compareDocumentPosition == null ? function(a, b) {
|
|
return a.contains(b);
|
|
} : function(a, b) {
|
|
return a.compareDocumentPosition(b) & 16;
|
|
};
|
|
$(range.startContainer).parents().each(function() {
|
|
if (contains(this, range.endContainer)) {
|
|
range.commonAncestorContainer = this;
|
|
return false;
|
|
}
|
|
});
|
|
return new Range.BrowserRange(range).normalize(root);
|
|
};
|
|
|
|
SerializedRange.prototype.serialize = function(root, ignoreSelector) {
|
|
return this.normalize(root).serialize(root, ignoreSelector);
|
|
};
|
|
|
|
SerializedRange.prototype.toObject = function() {
|
|
return {
|
|
start: this.start,
|
|
startOffset: this.startOffset,
|
|
end: this.end,
|
|
endOffset: this.endOffset
|
|
};
|
|
};
|
|
|
|
return SerializedRange;
|
|
|
|
})();
|
|
|
|
/*
|
|
//@ sourceMappingURL=range.map
|
|
*/
|