source: OKFNAnnotator (for Zope)/annotator_files/lib/range.js @ 4:6979313586cf

Last change on this file since 4:6979313586cf was 4:6979313586cf, checked in by casties, 12 years ago

new version of annotator.

File size: 9.5 KB
Line 
1// Generated by CoffeeScript 1.3.3
2var 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; };
5
6Range = {};
7
8Range.sniff = function(r) {
9  if (r.commonAncestorContainer != null) {
10    return new Range.BrowserRange(r);
11  } else if (typeof r.start === "string") {
12    return new Range.SerializedRange(r);
13  } else if (r.start && typeof r.start === "object") {
14    return new Range.NormalizedRange(r);
15  } else {
16    console.error(_t("Could not sniff range type"));
17    return false;
18  }
19};
20
21Range.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
66Range.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
81Range.BrowserRange = (function() {
82
83  function BrowserRange(obj) {
84    this.commonAncestorContainer = obj.commonAncestorContainer;
85    this.startContainer = obj.startContainer;
86    this.startOffset = obj.startOffset;
87    this.endContainer = obj.endContainer;
88    this.endOffset = obj.endOffset;
89  }
90
91  BrowserRange.prototype.normalize = function(root) {
92    var it, node, nr, offset, p, r, _i, _len, _ref;
93    if (this.tainted) {
94      console.error(_t("You may only call normalize() once on a BrowserRange!"));
95      return false;
96    } else {
97      this.tainted = true;
98    }
99    r = {};
100    nr = {};
101    _ref = ['start', 'end'];
102    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
103      p = _ref[_i];
104      node = this[p + 'Container'];
105      offset = this[p + 'Offset'];
106      if (!((node != null) && (offset != null))) {
107        return false;
108      }
109      if (node.nodeType === 1) {
110        it = node.childNodes[offset];
111        node = it || node.childNodes[offset - 1];
112        if (node.nodeType === 1 && !node.firstChild) {
113          it = null;
114          node = node.previousSibling;
115        }
116        while (node.nodeType !== 3) {
117          node = node.firstChild;
118        }
119        offset = it ? 0 : node.nodeValue.length;
120      }
121      r[p] = node;
122      r[p + 'Offset'] = offset;
123    }
124    nr.start = r.startOffset > 0 ? r.start.splitText(r.startOffset) : r.start;
125    if (r.start === r.end) {
126      if ((r.endOffset - r.startOffset) < nr.start.nodeValue.length) {
127        nr.start.splitText(r.endOffset - r.startOffset);
128      }
129      nr.end = nr.start;
130    } else {
131      if (r.endOffset < r.end.nodeValue.length) {
132        r.end.splitText(r.endOffset);
133      }
134      nr.end = r.end;
135    }
136    nr.commonAncestor = this.commonAncestorContainer;
137    while (nr.commonAncestor.nodeType !== 1) {
138      nr.commonAncestor = nr.commonAncestor.parentNode;
139    }
140    return new Range.NormalizedRange(nr);
141  };
142
143  BrowserRange.prototype.serialize = function(root, ignoreSelector) {
144    return this.normalize(root).serialize(root, ignoreSelector);
145  };
146
147  return BrowserRange;
148
149})();
150
151Range.NormalizedRange = (function() {
152
153  function NormalizedRange(obj) {
154    this.commonAncestor = obj.commonAncestor;
155    this.start = obj.start;
156    this.end = obj.end;
157  }
158
159  NormalizedRange.prototype.normalize = function(root) {
160    return this;
161  };
162
163  NormalizedRange.prototype.limit = function(bounds) {
164    var nodes, parent, startParents, _i, _len, _ref;
165    nodes = $.grep(this.textNodes(), function(node) {
166      return node.parentNode === bounds || $.contains(bounds, node.parentNode);
167    });
168    if (!nodes.length) {
169      return null;
170    }
171    this.start = nodes[0];
172    this.end = nodes[nodes.length - 1];
173    startParents = $(this.start).parents();
174    _ref = $(this.end).parents();
175    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
176      parent = _ref[_i];
177      if (startParents.index(parent) !== -1) {
178        this.commonAncestor = parent;
179        break;
180      }
181    }
182    return this;
183  };
184
185  NormalizedRange.prototype.serialize = function(root, ignoreSelector) {
186    var end, serialization, start;
187    serialization = function(node, isEnd) {
188      var n, nodes, offset, origParent, textNodes, xpath, _i, _len;
189      if (ignoreSelector) {
190        origParent = $(node).parents(":not(" + ignoreSelector + ")").eq(0);
191      } else {
192        origParent = $(node).parent();
193      }
194      xpath = origParent.xpath(root)[0];
195      textNodes = origParent.textNodes();
196      nodes = textNodes.slice(0, textNodes.index(node));
197      offset = 0;
198      for (_i = 0, _len = nodes.length; _i < _len; _i++) {
199        n = nodes[_i];
200        offset += n.nodeValue.length;
201      }
202      if (isEnd) {
203        return [xpath, offset + node.nodeValue.length];
204      } else {
205        return [xpath, offset];
206      }
207    };
208    start = serialization(this.start);
209    end = serialization(this.end, true);
210    return new Range.SerializedRange({
211      start: start[0],
212      end: end[0],
213      startOffset: start[1],
214      endOffset: end[1]
215    });
216  };
217
218  NormalizedRange.prototype.text = function() {
219    var node;
220    return ((function() {
221      var _i, _len, _ref, _results;
222      _ref = this.textNodes();
223      _results = [];
224      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
225        node = _ref[_i];
226        _results.push(node.nodeValue);
227      }
228      return _results;
229    }).call(this)).join('');
230  };
231
232  NormalizedRange.prototype.textNodes = function() {
233    var end, start, textNodes, _ref;
234    textNodes = $(this.commonAncestor).textNodes();
235    _ref = [textNodes.index(this.start), textNodes.index(this.end)], start = _ref[0], end = _ref[1];
236    return $.makeArray(textNodes.slice(start, end + 1 || 9e9));
237  };
238
239  NormalizedRange.prototype.toRange = function() {
240    var range;
241    range = document.createRange();
242    range.setStartBefore(this.start);
243    range.setEndAfter(this.end);
244    return range;
245  };
246
247  return NormalizedRange;
248
249})();
250
251Range.SerializedRange = (function() {
252
253  function SerializedRange(obj) {
254    this.start = obj.start;
255    this.startOffset = obj.startOffset;
256    this.end = obj.end;
257    this.endOffset = obj.endOffset;
258  }
259
260  SerializedRange.prototype.normalize = function(root) {
261    var contains, length, node, p, range, tn, _i, _j, _len, _len1, _ref, _ref1;
262    range = {};
263    _ref = ['start', 'end'];
264    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
265      p = _ref[_i];
266      try {
267        node = Range.nodeFromXPath(this[p], root);
268      } catch (e) {
269        throw new Range.RangeError(p, ("Error while finding " + p + " node: " + this[p] + ": ") + e, e);
270      }
271      if (!node) {
272        throw new Range.RangeError(p, "Couldn't find " + p + " node: " + this[p]);
273      }
274      length = 0;
275      _ref1 = $(node).textNodes();
276      for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
277        tn = _ref1[_j];
278        if (length + tn.nodeValue.length >= this[p + 'Offset']) {
279          range[p + 'Container'] = tn;
280          range[p + 'Offset'] = this[p + 'Offset'] - length;
281          break;
282        } else {
283          length += tn.nodeValue.length;
284        }
285      }
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    });
301    return new Range.BrowserRange(range).normalize(root);
302  };
303
304  SerializedRange.prototype.serialize = function(root, ignoreSelector) {
305    return this.normalize(root).serialize(root, ignoreSelector);
306  };
307
308  SerializedRange.prototype.toObject = function() {
309    return {
310      start: this.start,
311      startOffset: this.startOffset,
312      end: this.end,
313      endOffset: this.endOffset
314    };
315  };
316
317  return SerializedRange;
318
319})();
Note: See TracBrowser for help on using the repository browser.