Mercurial > hg > OKFNAnnotator
comparison annotator_files/lib/range.js @ 4:6979313586cf
new version of annotator.
author | casties |
---|---|
date | Mon, 27 Aug 2012 19:05:38 +0200 |
parents | 6356e78ccf5c |
children |
comparison
equal
deleted
inserted
replaced
3:6356e78ccf5c | 4:6979313586cf |
---|---|
1 var Range; | 1 // Generated by CoffeeScript 1.3.3 |
2 var Range, | |
3 __hasProp = {}.hasOwnProperty, | |
4 __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; }; | |
2 | 5 |
3 Range = {}; | 6 Range = {}; |
4 | 7 |
5 Range.sniff = function(r) { | 8 Range.sniff = function(r) { |
6 if (r.commonAncestorContainer != null) { | 9 if (r.commonAncestorContainer != null) { |
13 console.error(_t("Could not sniff range type")); | 16 console.error(_t("Could not sniff range type")); |
14 return false; | 17 return false; |
15 } | 18 } |
16 }; | 19 }; |
17 | 20 |
21 Range.nodeFromXPath = function(xpath, root) { | |
22 var customResolver, evaluateXPath, namespace, node, segment; | |
23 if (root == null) { | |
24 root = document; | |
25 } | |
26 evaluateXPath = function(xp, nsResolver) { | |
27 if (nsResolver == null) { | |
28 nsResolver = null; | |
29 } | |
30 return document.evaluate('.' + xp, root, nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; | |
31 }; | |
32 if (!$.isXMLDoc(document.documentElement)) { | |
33 return evaluateXPath(xpath); | |
34 } else { | |
35 customResolver = document.createNSResolver(document.ownerDocument === null ? document.documentElement : document.ownerDocument.documentElement); | |
36 node = evaluateXPath(xpath, customResolver); | |
37 if (!node) { | |
38 xpath = ((function() { | |
39 var _i, _len, _ref, _results; | |
40 _ref = xpath.split('/'); | |
41 _results = []; | |
42 for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
43 segment = _ref[_i]; | |
44 if (segment && segment.indexOf(':') === -1) { | |
45 _results.push(segment.replace(/^([a-z]+)/, 'xhtml:$1')); | |
46 } else { | |
47 _results.push(segment); | |
48 } | |
49 } | |
50 return _results; | |
51 })()).join('/'); | |
52 namespace = document.lookupNamespaceURI(null); | |
53 customResolver = function(ns) { | |
54 if (ns === 'xhtml') { | |
55 return namespace; | |
56 } else { | |
57 return document.documentElement.getAttribute('xmlns:' + ns); | |
58 } | |
59 }; | |
60 node = evaluateXPath(xpath, customResolver); | |
61 } | |
62 return node; | |
63 } | |
64 }; | |
65 | |
66 Range.RangeError = (function(_super) { | |
67 | |
68 __extends(RangeError, _super); | |
69 | |
70 function RangeError(type, message, parent) { | |
71 this.type = type; | |
72 this.message = message; | |
73 this.parent = parent != null ? parent : null; | |
74 RangeError.__super__.constructor.call(this, this.message); | |
75 } | |
76 | |
77 return RangeError; | |
78 | |
79 })(Error); | |
80 | |
18 Range.BrowserRange = (function() { | 81 Range.BrowserRange = (function() { |
19 | 82 |
20 function BrowserRange(obj) { | 83 function BrowserRange(obj) { |
21 this.commonAncestorContainer = obj.commonAncestorContainer; | 84 this.commonAncestorContainer = obj.commonAncestorContainer; |
22 this.startContainer = obj.startContainer; | 85 this.startContainer = obj.startContainer; |
38 _ref = ['start', 'end']; | 101 _ref = ['start', 'end']; |
39 for (_i = 0, _len = _ref.length; _i < _len; _i++) { | 102 for (_i = 0, _len = _ref.length; _i < _len; _i++) { |
40 p = _ref[_i]; | 103 p = _ref[_i]; |
41 node = this[p + 'Container']; | 104 node = this[p + 'Container']; |
42 offset = this[p + 'Offset']; | 105 offset = this[p + 'Offset']; |
43 if (!((node != null) && (offset != null))) return false; | 106 if (!((node != null) && (offset != null))) { |
107 return false; | |
108 } | |
44 if (node.nodeType === 1) { | 109 if (node.nodeType === 1) { |
45 it = node.childNodes[offset]; | 110 it = node.childNodes[offset]; |
46 node = it || node.childNodes[offset - 1]; | 111 node = it || node.childNodes[offset - 1]; |
47 if (node.nodeType === 1 && !node.firstChild) { | 112 if (node.nodeType === 1 && !node.firstChild) { |
48 it = null; | 113 it = null; |
61 if ((r.endOffset - r.startOffset) < nr.start.nodeValue.length) { | 126 if ((r.endOffset - r.startOffset) < nr.start.nodeValue.length) { |
62 nr.start.splitText(r.endOffset - r.startOffset); | 127 nr.start.splitText(r.endOffset - r.startOffset); |
63 } | 128 } |
64 nr.end = nr.start; | 129 nr.end = nr.start; |
65 } else { | 130 } else { |
66 if (r.endOffset < r.end.nodeValue.length) r.end.splitText(r.endOffset); | 131 if (r.endOffset < r.end.nodeValue.length) { |
132 r.end.splitText(r.endOffset); | |
133 } | |
67 nr.end = r.end; | 134 nr.end = r.end; |
68 } | 135 } |
69 nr.commonAncestor = this.commonAncestorContainer; | 136 nr.commonAncestor = this.commonAncestorContainer; |
70 while (nr.commonAncestor.nodeType !== 1) { | 137 while (nr.commonAncestor.nodeType !== 1) { |
71 nr.commonAncestor = nr.commonAncestor.parentNode; | 138 nr.commonAncestor = nr.commonAncestor.parentNode; |
96 NormalizedRange.prototype.limit = function(bounds) { | 163 NormalizedRange.prototype.limit = function(bounds) { |
97 var nodes, parent, startParents, _i, _len, _ref; | 164 var nodes, parent, startParents, _i, _len, _ref; |
98 nodes = $.grep(this.textNodes(), function(node) { | 165 nodes = $.grep(this.textNodes(), function(node) { |
99 return node.parentNode === bounds || $.contains(bounds, node.parentNode); | 166 return node.parentNode === bounds || $.contains(bounds, node.parentNode); |
100 }); | 167 }); |
101 if (!nodes.length) return null; | 168 if (!nodes.length) { |
169 return null; | |
170 } | |
102 this.start = nodes[0]; | 171 this.start = nodes[0]; |
103 this.end = nodes[nodes.length - 1]; | 172 this.end = nodes[nodes.length - 1]; |
104 startParents = $(this.start).parents(); | 173 startParents = $(this.start).parents(); |
105 _ref = $(this.end).parents(); | 174 _ref = $(this.end).parents(); |
106 for (_i = 0, _len = _ref.length; _i < _len; _i++) { | 175 for (_i = 0, _len = _ref.length; _i < _len; _i++) { |
186 this.startOffset = obj.startOffset; | 255 this.startOffset = obj.startOffset; |
187 this.end = obj.end; | 256 this.end = obj.end; |
188 this.endOffset = obj.endOffset; | 257 this.endOffset = obj.endOffset; |
189 } | 258 } |
190 | 259 |
191 SerializedRange.prototype._nodeFromXPath = function(xpath) { | 260 SerializedRange.prototype.normalize = function(root) { |
192 var customResolver, evaluateXPath, namespace, node, segment; | 261 var contains, length, node, p, range, tn, _i, _j, _len, _len1, _ref, _ref1; |
193 evaluateXPath = function(xp, nsResolver) { | 262 range = {}; |
194 if (nsResolver == null) nsResolver = null; | 263 _ref = ['start', 'end']; |
195 return document.evaluate(xp, document, nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; | 264 for (_i = 0, _len = _ref.length; _i < _len; _i++) { |
196 }; | 265 p = _ref[_i]; |
197 if (!$.isXMLDoc(document.documentElement)) { | 266 try { |
198 return evaluateXPath(xpath); | 267 node = Range.nodeFromXPath(this[p], root); |
199 } else { | 268 } catch (e) { |
200 customResolver = document.createNSResolver(document.ownerDocument === null ? document.documentElement : document.ownerDocument.documentElement); | 269 throw new Range.RangeError(p, ("Error while finding " + p + " node: " + this[p] + ": ") + e, e); |
201 node = evaluateXPath(xpath, customResolver); | 270 } |
202 if (!node) { | 271 if (!node) { |
203 xpath = ((function() { | 272 throw new Range.RangeError(p, "Couldn't find " + p + " node: " + this[p]); |
204 var _i, _len, _ref, _results; | 273 } |
205 _ref = xpath.split('/'); | |
206 _results = []; | |
207 for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
208 segment = _ref[_i]; | |
209 if (segment && segment.indexOf(':') === -1) { | |
210 _results.push(segment.replace(/^([a-z]+)/, 'xhtml:$1')); | |
211 } else { | |
212 _results.push(segment); | |
213 } | |
214 } | |
215 return _results; | |
216 })()).join('/'); | |
217 namespace = document.lookupNamespaceURI(null); | |
218 customResolver = function(ns) { | |
219 if (ns === 'xhtml') { | |
220 return namespace; | |
221 } else { | |
222 return document.documentElement.getAttribute('xmlns:' + ns); | |
223 } | |
224 }; | |
225 node = evaluateXPath(xpath, customResolver); | |
226 } | |
227 return node; | |
228 } | |
229 }; | |
230 | |
231 SerializedRange.prototype.normalize = function(root) { | |
232 var cacXPath, common, endAncestry, i, length, p, parentXPath, range, startAncestry, tn, _i, _j, _len, _len2, _ref, _ref2, _ref3; | |
233 parentXPath = $(root).xpath()[0]; | |
234 startAncestry = this.start.split("/"); | |
235 endAncestry = this.end.split("/"); | |
236 common = []; | |
237 range = {}; | |
238 for (i = 0, _ref = startAncestry.length; 0 <= _ref ? i < _ref : i > _ref; 0 <= _ref ? i++ : i--) { | |
239 if (startAncestry[i] === endAncestry[i]) { | |
240 common.push(startAncestry[i]); | |
241 } else { | |
242 break; | |
243 } | |
244 } | |
245 cacXPath = parentXPath + common.join("/"); | |
246 range.commonAncestorContainer = this._nodeFromXPath(cacXPath); | |
247 if (!range.commonAncestorContainer) { | |
248 console.error(_t("Error deserializing range: can't find XPath '") + cacXPath + _t("'. Is this the right document?")); | |
249 return null; | |
250 } | |
251 _ref2 = ['start', 'end']; | |
252 for (_i = 0, _len = _ref2.length; _i < _len; _i++) { | |
253 p = _ref2[_i]; | |
254 length = 0; | 274 length = 0; |
255 _ref3 = $(this._nodeFromXPath(parentXPath + this[p])).textNodes(); | 275 _ref1 = $(node).textNodes(); |
256 for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) { | 276 for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { |
257 tn = _ref3[_j]; | 277 tn = _ref1[_j]; |
258 if (length + tn.nodeValue.length >= this[p + 'Offset']) { | 278 if (length + tn.nodeValue.length >= this[p + 'Offset']) { |
259 range[p + 'Container'] = tn; | 279 range[p + 'Container'] = tn; |
260 range[p + 'Offset'] = this[p + 'Offset'] - length; | 280 range[p + 'Offset'] = this[p + 'Offset'] - length; |
261 break; | 281 break; |
262 } else { | 282 } else { |
263 length += tn.nodeValue.length; | 283 length += tn.nodeValue.length; |
264 } | 284 } |
265 } | 285 } |
266 } | 286 if (!(range[p + 'Offset'] != null)) { |
287 throw new Range.RangeError("" + p + "offset", "Couldn't find offset " + this[p + 'Offset'] + " in element " + this[p]); | |
288 } | |
289 } | |
290 contains = !(document.compareDocumentPosition != null) ? function(a, b) { | |
291 return a.contains(b); | |
292 } : function(a, b) { | |
293 return a.compareDocumentPosition(b) & 16; | |
294 }; | |
295 $(range.startContainer).parents().reverse().each(function() { | |
296 if (contains(this, range.endContainer)) { | |
297 range.commonAncestorContainer = this; | |
298 return false; | |
299 } | |
300 }); | |
267 return new Range.BrowserRange(range).normalize(root); | 301 return new Range.BrowserRange(range).normalize(root); |
268 }; | 302 }; |
269 | 303 |
270 SerializedRange.prototype.serialize = function(root, ignoreSelector) { | 304 SerializedRange.prototype.serialize = function(root, ignoreSelector) { |
271 return this.normalize(root).serialize(root, ignoreSelector); | 305 return this.normalize(root).serialize(root, ignoreSelector); |