source: main/trunk/model-cols-dev/peijones/js/annotator/pkg/annotator-full.min.js@ 24948

Last change on this file since 24948 was 24948, checked in by sjm84, 12 years ago

Some initial updates to allow deletion of text annotations

File size: 82.2 KB
Line 
1(function () {
2 var h, o, b, p, n, i, l, a, e, d, c, r, s, j;
3 var m = Array.prototype.slice,
4 g = function (t, u) {
5 return function () {
6 return t.apply(u, arguments)
7 }
8 },
9 k = Object.prototype.hasOwnProperty,
10 q = function (w, u) {
11 for (var t in u) {
12 if (k.call(u, t)) {
13 w[t] = u[t]
14 }
15 }
16 function v() {
17 this.constructor = w
18 }
19 v.prototype = u.prototype;
20 w.prototype = new v;
21 w.__super__ = u.prototype;
22 return w
23 },
24 f = Array.prototype.indexOf ||
25 function (v) {
26 for (var u = 0, t = this.length; u < t; u++) {
27 if (this[u] === v) {
28 return u
29 }
30 }
31 return -1
32 };
33 if (!(typeof jQuery !== "undefined" && jQuery !== null ? (j = jQuery.fn) != null ? j.jquery : void 0 : void 0)) {
34 console.error("Annotator requires jQuery: have you included lib/vendor/jquery.js?")
35 }
36 if (!(JSON && JSON.parse && JSON.stringify)) {
37 console.error("Annotator requires a JSON implementation: have you included lib/vendor/json2.js?")
38 }
39 h = jQuery.sub();
40 h.flatten = function (u) {
41 var t;
42 t = function (w) {
43 var x, z, y, v;
44 z = [];
45 for (y = 0, v = w.length; y < v; y++) {
46 x = w[y];
47 z = z.concat(x && h.isArray(x) ? t(x) : x)
48 }
49 return z
50 };
51 return t(u)
52 };
53 h.plugin = function (u, t) {
54 return jQuery.fn[u] = function (w) {
55 var v;
56 v = Array.prototype.slice.call(arguments, 1);
57 return this.each(function () {
58 var x;
59 x = h.data(this, u);
60 if (x) {
61 return w && x[w].apply(x, v)
62 } else {
63 x = new t(this, w);
64 return h.data(this, u, x)
65 }
66 })
67 }
68 };
69 h.fn.textNodes = function () {
70 var t;
71 t = function (v) {
72 var u;
73 if (v && v.nodeType !== 3) {
74 u = [];
75 if (v.nodeType !== 8) {
76 v = v.lastChild;
77 while (v) {
78 u.push(t(v));
79 v = v.previousSibling
80 }
81 }
82 return u.reverse()
83 } else {
84 return v
85 }
86 };
87 return this.map(function () {
88 return h.flatten(t(this))
89 })
90 };
91 h.fn.xpath = function (t) {
92 var u;
93 u = this.map(function () {
94 var w, v, x;
95 x = "";
96 w = this;
97 while (w && w.nodeType === 1 && w !== t) {
98 v = h(w.parentNode).children(w.tagName).index(w) + 1;
99 v = v > 1 ? "[" + v + "]" : "";
100 x = "/" + w.tagName.toLowerCase() + v + x;
101 w = w.parentNode
102 }
103 return x
104 });
105 return u.get()
106 };
107 h.escape = function (t) {
108 return t.replace(/&(?!\w+;)/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;")
109 };
110 h.fn.escape = function (t) {
111 if (arguments.length) {
112 return this.html(h.escape(t))
113 }
114 return this.html()
115 };
116 l = ["log", "debug", "info", "warn", "exception", "assert", "dir", "dirxml", "trace", "group", "groupEnd", "groupCollapsed", "time", "timeEnd", "profile", "profileEnd", "count", "clear", "table", "error", "notifyFirebug", "firebug", "userObjects"];
117 if (typeof console !== "undefined" && console !== null) {
118 if (!(console.group != null)) {
119 console.group = function (t) {
120 return console.log("GROUP: ", t)
121 }
122 }
123 if (!(console.groupCollapsed != null)) {
124 console.groupCollapsed = console.group
125 }
126 for (d = 0, r = l.length; d < r; d++) {
127 i = l[d];
128 if (!(console[i] != null)) {
129 console[i] = function () {
130 return console.log("Not implemented: console." + name)
131 }
132 }
133 }
134 } else {
135 this.console = {};
136 for (c = 0, s = l.length; c < s; c++) {
137 i = l[c];
138 this.console[i] = function () {}
139 }
140 this.console.error = function () {
141 var t;
142 t = 1 <= arguments.length ? m.call(arguments, 0) : [];
143 return alert("ERROR: " + (t.join(", ")))
144 };
145 this.console.warn = function () {
146 var t;
147 t = 1 <= arguments.length ? m.call(arguments, 0) : [];
148 return alert("WARNING: " + (t.join(", ")))
149 }
150 }
151 b = (function () {
152 t.prototype.events = {};
153 t.prototype.options = {};
154 t.prototype.element = null;
155
156 function t(v, u) {
157 this.options = h.extend(true, {}, this.options, u);
158 this.element = h(v);
159 this.on = this.subscribe;
160 this.addEvents()
161 }
162 t.prototype.addEvents = function () {
163 var x, z, y, u, w, B, A, v;
164 B = this.events;
165 v = [];
166 for (y in B) {
167 z = B[y];
168 A = y.split(" "), u = 2 <= A.length ? m.call(A, 0, w = A.length - 1) : (w = 0, []), x = A[w++];
169 v.push(this.addEvent(u.join(" "), x, z))
170 }
171 return v
172 };
173 t.prototype.addEvent = function (u, w, x) {
174 var y, v;
175 y = g(function () {
176 return this[x].apply(this, arguments)
177 }, this);
178 v = typeof u === "string" && u.replace(/\s+/g, "") === "";
179 if (v) {
180 u = this.element
181 }
182 if (typeof u === "string") {
183 this.element.delegate(u, w, y)
184 } else {
185 if (this.isCustomEvent(w)) {
186 this.subscribe(w, y)
187 } else {
188 h(u).bind(w, y)
189 }
190 }
191 return this
192 };
193 t.prototype.isCustomEvent = function (v) {
194 var u;
195 u = "blur focus focusin focusout load resize scroll unload click dblclick\nmousedown mouseup mousemove mouseover mouseout mouseenter mouseleave\nchange select submit keydown keypress keyup error".split(/[^a-z]+/);
196 v = v.split(".")[0];
197 return h.inArray(v, u) === -1
198 };
199 t.prototype.publish = function () {
200 this.element.triggerHandler.apply(this.element, arguments);
201 return this
202 };
203 t.prototype.subscribe = function (u, w) {
204 var v;
205 v = function () {
206 return w.apply(this, [].slice.call(arguments, 1))
207 };
208 v.guid = w.guid = (h.guid += 1);
209 this.element.bind(u, v);
210 return this
211 };
212 t.prototype.unsubscribe = function () {
213 this.element.unbind.apply(this.element, arguments);
214 return this
215 };
216 return t
217 })();
218 p = {};
219 p.sniff = function (t) {
220 if (t.commonAncestorContainer != null) {
221 return new p.BrowserRange(t)
222 } else {
223 if (typeof t.start === "string") {
224 return new p.SerializedRange(t)
225 } else {
226 if (t.start && typeof t.start === "object") {
227 return new p.NormalizedRange(t)
228 } else {
229 console.error("Couldn't not sniff range type");
230 return false
231 }
232 }
233 }
234 };
235 p.BrowserRange = (function () {
236 function t(u) {
237 this.commonAncestorContainer = u.commonAncestorContainer;
238 this.startContainer = u.startContainer;
239 this.startOffset = u.startOffset;
240 this.endContainer = u.endContainer;
241 this.endOffset = u.endOffset
242 }
243 t.prototype.normalize = function (C) {
244 var B, x, D, A, w, v, z, u, y;
245 if (this.tainted) {
246 console.error("You may only call normalize() once on a BrowserRange!");
247 return false
248 } else {
249 this.tainted = true
250 }
251 v = {};
252 D = {};
253 y = ["start", "end"];
254 for (z = 0, u = y.length; z < u; z++) {
255 w = y[z];
256 x = this[w + "Container"];
257 A = this[w + "Offset"];
258 if (x.nodeType === 1) {
259 B = x.childNodes[A];
260 x = B || x.childNodes[A - 1];
261 while (x.nodeType !== 3) {
262 x = x.firstChild
263 }
264 A = B ? 0 : x.nodeValue.length
265 }
266 v[w] = x;
267 v[w + "Offset"] = A
268 }
269 D.start = v.startOffset > 0 ? v.start.splitText(v.startOffset) : v.start;
270 if (v.start === v.end) {
271 if ((v.endOffset - v.startOffset) < D.start.nodeValue.length) {
272 D.start.splitText(v.endOffset - v.startOffset)
273 }
274 D.end = D.start
275 } else {
276 if (v.endOffset < v.end.nodeValue.length) {
277 v.end.splitText(v.endOffset)
278 }
279 D.end = v.end
280 }
281 D.commonAncestor = this.commonAncestorContainer;
282 while (D.commonAncestor.nodeType !== 1) {
283 D.commonAncestor = D.commonAncestor.parentNode
284 }
285 return new p.NormalizedRange(D)
286 };
287 t.prototype.serialize = function (u, v) {
288 return this.normalize(u).serialize(u, v)
289 };
290 return t
291 })();
292 p.NormalizedRange = (function () {
293 function t(u) {
294 this.commonAncestor = u.commonAncestor;
295 this.start = u.start;
296 this.end = u.end
297 }
298 t.prototype.normalize = function (u) {
299 return this
300 };
301 t.prototype.limit = function (y) {
302 var u, x, v, w, A, z;
303 u = h.grep(this.textNodes(), function (B) {
304 return B.parentNode === y || h.contains(y, B.parentNode)
305 });
306 if (!u.length) {
307 return null
308 }
309 this.start = u[0];
310 this.end = u[u.length - 1];
311 v = h(this.start).parents();
312 z = h(this.end).parents();
313 for (w = 0, A = z.length; w < A; w++) {
314 x = z[w];
315 if (v.index(x) !== -1) {
316 this.commonAncestor = x;
317 break
318 }
319 }
320 return this
321 };
322 t.prototype.serialize = function (w, x) {
323 var v, u, y;
324 u = function (D, C) {
325 var B, A, F, I, H, G, E, z;
326 if (x) {
327 I = h(D).parents(":not(" + x + ")").eq(0)
328 } else {
329 I = h(D).parent()
330 }
331 G = I.xpath(w)[0];
332 H = I.textNodes();
333 A = H.slice(0, H.index(D));
334 F = 0;
335 for (E = 0, z = A.length; E < z; E++) {
336 B = A[E];
337 F += B.nodeValue.length
338 }
339 if (C) {
340 return [G, F + D.nodeValue.length]
341 } else {
342 return [G, F]
343 }
344 };
345 y = u(this.start);
346 v = u(this.end, true);
347 return new p.SerializedRange({
348 start: y[0],
349 end: v[0],
350 startOffset: y[1],
351 endOffset: v[1]
352 })
353 };
354 t.prototype.text = function () {
355 var u;
356 return ((function () {
357 var w, y, x, v;
358 x = this.textNodes();
359 v = [];
360 for (w = 0, y = x.length; w < y; w++) {
361 u = x[w];
362 v.push(u.nodeValue)
363 }
364 return v
365 }).call(this)).join("")
366 };
367 t.prototype.textNodes = function () {
368 var u, x, v, w;
369 v = h(this.commonAncestor).textNodes();
370 w = [v.index(this.start), v.index(this.end)], x = w[0], u = w[1];
371 return h.makeArray(v.slice(x, (u + 1) || 9000000000))
372 };
373 return t
374 })();
375 p.SerializedRange = (function () {
376 function t(u) {
377 this.start = u.start;
378 this.startOffset = u.startOffset;
379 this.end = u.end;
380 this.endOffset = u.endOffset
381 }
382 t.prototype._nodeFromXPath = function (u) {
383 var z, y, v, x, w;
384 y = function (B, A) {
385 if (A == null) {
386 A = null
387 }
388 return document.evaluate(B, document, A, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue
389 };
390 if (!h.isXMLDoc(document.documentElement)) {
391 return y(u)
392 } else {
393 z = document.createNSResolver(document.ownerDocument === null ? document.documentElement : document.ownerDocument.documentElement);
394 x = y(u, z);
395 if (!x) {
396 u = ((function () {
397 var B, D, C, A;
398 C = u.split("/");
399 A = [];
400 for (B = 0, D = C.length; B < D; B++) {
401 w = C[B];
402 A.push(w && w.indexOf(":") === -1 ? w.replace(/^([a-z]+)/, "xhtml:$1") : w)
403 }
404 return A
405 })()).join("/");
406 v = document.lookupNamespaceURI(null);
407 z = function (A) {
408 if (A === "xhtml") {
409 return v
410 } else {
411 return document.documentElement.getAttribute("xmlns:" + A)
412 }
413 };
414 x = y(u, z)
415 }
416 return x
417 }
418 };
419 t.prototype.normalize = function (G) {
420 var K, D, C, I, A, F, H, E, B, z, v, u, L, J, y, x, w;
421 H = h(G).xpath()[0];
422 B = this.start.split("/");
423 C = this.end.split("/");
424 D = [];
425 E = {};
426 for (I = 0, y = B.length; 0 <= y ? I < y : I > y; 0 <= y ? I++ : I--) {
427 if (B[I] === C[I]) {
428 D.push(B[I])
429 } else {
430 break
431 }
432 }
433 K = H + D.join("/");
434 E.commonAncestorContainer = this._nodeFromXPath(K);
435 if (!E.commonAncestorContainer) {
436 console.error("Error deserializing range: can't find XPath '" + K + "'. Is this the right document?");
437 return null
438 }
439 x = ["start", "end"];
440 for (v = 0, L = x.length; v < L; v++) {
441 F = x[v];
442 A = 0;
443 w = h(this._nodeFromXPath(H + this[F])).textNodes();
444 for (u = 0, J = w.length; u < J; u++) {
445 z = w[u];
446 if (A + z.nodeValue.length >= this[F + "Offset"]) {
447 E[F + "Container"] = z;
448 E[F + "Offset"] = this[F + "Offset"] - A;
449 break
450 } else {
451 A += z.nodeValue.length
452 }
453 }
454 }
455 return new p.BrowserRange(E).normalize(G)
456 };
457 t.prototype.serialize = function (u, v) {
458 return this.normalize(u).serialize(u, v)
459 };
460 t.prototype.toObject = function () {
461 return {
462 start: this.start,
463 startOffset: this.startOffset,
464 end: this.end,
465 endOffset: this.endOffset
466 }
467 };
468 return t
469 })();
470 a = {
471 getGlobal: function () {
472 return (function () {
473 return this
474 })()
475 },
476 mousePosition: function (t, v) {
477 var u;
478 u = h(v).offset();
479 return {
480 top: t.pageY - u.top,
481 left: t.pageX - u.left
482 }
483 }
484 };
485 e = this.Annotator;
486 o = (function () {
487 q(t, b);
488 t.prototype.events = {
489 ".annotator-adder button click": "onAdderClick",
490 ".annotator-adder button mousedown": "onAdderMousedown",
491 ".annotator-hl mouseover": "onHighlightMouseover",
492 ".annotator-hl mouseout": "startViewerHideTimer"
493 };
494 t.prototype.html = {
495 hl: '<span class="annotator-hl"></span>',
496 adder: '<div class="annotator-adder"><button>Annotate</button></div>',
497 wrapper: '<div class="annotator-wrapper"></div>'
498 };
499 t.prototype.options = {};
500 t.prototype.plugins = {};
501 t.prototype.editor = null;
502 t.prototype.viewer = null;
503 t.prototype.selectedRanges = null;
504 t.prototype.mouseIsDown = false;
505 t.prototype.ignoreMouseup = false;
506 t.prototype.viewerHideTimer = null;
507
508 function t(w, v) {
509 this.onDeleteAnnotation = g(this.onDeleteAnnotation, this);
510 this.onEditAnnotation = g(this.onEditAnnotation, this);
511 this.onAdderClick = g(this.onAdderClick, this);
512 this.onAdderMousedown = g(this.onAdderMousedown, this);
513 this.onHighlightMouseover = g(this.onHighlightMouseover, this);
514 this.checkForEndSelection = g(this.checkForEndSelection, this);
515 this.checkForStartSelection = g(this.checkForStartSelection, this);
516 this.clearViewerHideTimer = g(this.clearViewerHideTimer, this);
517 this.startViewerHideTimer = g(this.startViewerHideTimer, this);
518 this.showViewer = g(this.showViewer, this);
519 this.onEditorSubmit = g(this.onEditorSubmit, this);
520 this.onEditorHide = g(this.onEditorHide, this);
521 this.showEditor = g(this.showEditor, this);
522 var u, x, y;
523 t.__super__.constructor.apply(this, arguments);
524 this.plugins = {};
525 if (!t.supported()) {
526 return this
527 }
528 this._setupDocumentEvents()._setupWrapper()._setupViewer()._setupEditor();
529 y = this.html;
530 for (u in y) {
531 x = y[u];
532 if (u !== "wrapper") {
533 this[u] = h(x).appendTo(this.wrapper).hide()
534 }
535 }
536 }
537 t.prototype._setupWrapper = function () {
538 this.wrapper = h(this.html.wrapper);
539 this.element.find("script").remove();
540 this.element.wrapInner(this.wrapper);
541 this.wrapper = this.element.find(".annotator-wrapper");
542 return this
543 };
544 t.prototype._setupViewer = function () {
545 this.viewer = new t.Viewer();
546 this.viewer.hide().on("edit", this.onEditAnnotation).on("delete", this.onDeleteAnnotation).addField({
547 load: g(function (v, u) {
548 h(v).escape(u.text || "");
549 return this.publish("annotationViewerTextField", [v, u])
550 }, this)
551 }).element.appendTo(this.wrapper).bind({
552 mouseover: this.clearViewerHideTimer,
553 mouseout: this.startViewerHideTimer
554 });
555 return this
556 };
557 t.prototype._setupEditor = function () {
558 this.editor = new t.Editor();
559 this.editor.hide().on("hide", this.onEditorHide).on("save", this.onEditorSubmit).addField({
560 type: "textarea",
561 label: "Comments\u2026",
562 load: function (v, u) {
563 return h(v).find("textarea").val(u.text || "")
564 },
565 submit: function (v, u) {
566 return u.text = h(v).find("textarea").val()
567 }
568 });
569 this.editor.element.appendTo(this.wrapper);
570 return this
571 };
572 t.prototype._setupDocumentEvents = function () {
573 h(document).bind({
574 mouseup: this.checkForEndSelection,
575 mousedown: this.checkForStartSelection
576 });
577 return this
578 };
579 t.prototype.getSelectedRanges = function () {
580 var x, v, u, w;
581 w = a.getGlobal().getSelection();
582 u = [];
583 if (!w.isCollapsed) {
584 u = (function () {
585 var z, y;
586 y = [];
587 for (v = 0, z = w.rangeCount; 0 <= z ? v < z : v > z; 0 <= z ? v++ : v--) {
588 x = new p.BrowserRange(w.getRangeAt(v));
589 y.push(x.normalize().limit(this.wrapper[0]))
590 }
591 return y
592 }).call(this)
593 }
594 return h.grep(u, function (y) {
595 return y
596 })
597 };
598 t.prototype.createAnnotation = function () {
599 var u;
600 u = {};
601 this.publish("beforeAnnotationCreated", [u]);
602 return u
603 };
604 t.prototype.setupAnnotation = function (u, w) {
605 var v, A, z, x, y, B;
606 if (w == null) {
607 w = true
608 }
609 u.ranges || (u.ranges = this.selectedRanges);
610 A = (function () {
611 var D, F, E, C;
612 E = u.ranges;
613 C = [];
614 for (D = 0, F = E.length; D < F; D++) {
615 z = E[D];
616 x = p.sniff(z);
617 C.push(x.normalize(this.wrapper[0]))
618 }
619
620 return C
621 }).call(this);
622 A = h.grep(A, function (C) {
623 return C !== null
624 });
625 u.quote = [];
626 u.ranges = [];
627 u.highlights = [];
628 for (y = 0, B = A.length; y < B; y++) {
629 v = A[y];
630 u.quote.push(h.trim(v.text()));
631 u.ranges.push(v.serialize(this.wrapper[0], ".annotator-hl"));
632 h.merge(u.highlights, this.highlightRange(v))
633 }
634 u.quote = u.quote.join(" / ");
635 h(u.highlights).data("annotation", u);
636 if (w) {
637 this.publish("annotationCreated", [u])
638 }
639
640 var rangeString = u.ranges[0].startOffset + "_" + u.ranges[0].endOffset;
641
642 var found = false;
643 for(var i = 0; i < gs.annotationArray.keys.length; i++){if(gs.annotationArray.keys[i] == rangeString){found = true; break;}}
644
645 if(!found)
646 {
647 gs.annotationArray.keys.push(rangeString);
648 }
649 gs.annotationArray[rangeString] = u;
650 console.log("(setup) Adding " + u.quote + ", " + u.text + ", " + u.tags + " to " + rangeString);
651 return u
652 };
653 t.prototype.updateAnnotation = function (u) {
654 this.publish("beforeAnnotationUpdated", [u]);
655 this.publish("annotationUpdated", [u]);
656 return u
657 };
658 t.prototype.deleteAnnotation = function (u) {
659 var w, v, y, x;
660 x = u.highlights;
661
662 for (v = 0, y = x.length; v < y; v++) {
663 w = x[v];
664 h(w).replaceWith(w.childNodes)
665 }
666
667 var rangeString = u.ranges[0].startOffset + "_" + u.ranges[0].endOffset;
668 gs.toDeleteArray[rangeString] = gs.annotationArray[rangeString];
669 gs.toDeleteArray.keys.push(rangeString);
670 gs.annotationArray[rangeString] = null;
671
672 this.publish("annotationDeleted", [u]);
673 return u
674 };
675 t.prototype.loadAnnotations = function (v) {
676 var w, u;
677 if (v == null) {
678 v = []
679 }
680 u = g(function (z) {
681 var B, x, y, A;
682 if (z == null) {
683 z = []
684 }
685 x = z.splice(0, 10);
686 for (y = 0, A = x.length; y < A; y++) {
687 B = x[y];
688 this.setupAnnotation(B, false)
689 }
690 if (z.length > 0) {
691 return setTimeout((function () {
692 return u(z)
693 }), 100)
694 } else {
695 return this.publish("annotationsLoaded", [w])
696 }
697 }, this);
698 w = v.slice();
699 if (v.length) {
700 u(v)
701 }
702 return this
703 };
704 t.prototype.dumpAnnotations = function () {
705 if (this.plugins.Store) {
706 return this.plugins.Store.dumpAnnotations()
707 } else {
708 return console.warn("Can't dump annotations without Store plugin.")
709 }
710 };
711 t.prototype.highlightRange = function (v) {
712 var u, w, x;
713 return u = (function () {
714 var z, B, A, y;
715 A = v.textNodes();
716 y = [];
717 for (z = 0, B = A.length; z < B; z++) {
718 w = A[z];
719 x = this.hl.clone().show();
720 y.push(h(w).wrap(x).parent().get(0))
721 }
722 return y
723 }).call(this)
724 };
725 t.prototype.addPlugin = function (w, v) {
726 var u, x;
727 if (this.plugins[w]) {
728 console.error("You cannot have more than one instance of any plugin.")
729 } else {
730 u = t.Plugin[w];
731 if (typeof u === "function") {
732 this.plugins[w] = new u(this.element[0], v);
733 this.plugins[w].annotator = this;
734 if (typeof (x = this.plugins[w]).pluginInit === "function") {
735 x.pluginInit()
736 }
737 } else {
738 console.error("Could not load " + w + " plugin. Have you included the appropriate <script> tag?")
739 }
740 }
741 return this
742 };
743 t.prototype.showEditor = function (u, v) {
744 this.editor.element.css(v);
745 this.editor.load(u);
746 return this
747 };
748 t.prototype.onEditorHide = function () {
749 this.publish("annotationEditorHidden", [this.editor]);
750 return this.ignoreMouseup = false
751 };
752 t.prototype.onEditorSubmit = function (u) {
753 this.publish("annotationEditorSubmit", [this.editor, u]);
754 if (u.ranges === void 0) {
755 return this.setupAnnotation(u)
756 } else {
757 return this.updateAnnotation(u)
758 }
759 };
760 t.prototype.showViewer = function (v, u) {
761 this.viewer.element.css(u);
762 this.viewer.load(v);
763 return this.publish("annotationViewerShown", [this.viewer, v])
764 };
765 t.prototype.startViewerHideTimer = function () {
766 if (!this.viewerHideTimer) {
767 return this.viewerHideTimer = setTimeout(h.proxy(this.viewer.hide, this.viewer), 250)
768 }
769 };
770 t.prototype.clearViewerHideTimer = function () {
771 clearTimeout(this.viewerHideTimer);
772 return this.viewerHideTimer = false
773 };
774 t.prototype.checkForStartSelection = function (u) {
775 if (!(u && this.isAnnotator(u.target))) {
776 this.startViewerHideTimer();
777 return this.mouseIsDown = true
778 }
779 };
780 t.prototype.checkForEndSelection = function (x) {
781 var u, v, w, z, y;
782 this.mouseIsDown = false;
783 if (this.ignoreMouseup) {
784 return
785 }
786 this.selectedRanges = this.getSelectedRanges();
787 y = this.selectedRanges;
788 for (w = 0, z = y.length; w < z; w++) {
789 v = y[w];
790 u = v.commonAncestor;
791 if (this.isAnnotator(u)) {
792 return
793 }
794 }
795 if (x && this.selectedRanges.length) {
796 return this.adder.css(a.mousePosition(x, this.wrapper[0])).show()
797 } else {
798 return this.adder.hide()
799 }
800 };
801 t.prototype.isAnnotator = function (u) {
802 return !!h(u).parents().andSelf().filter("[class^=annotator-]").not(this.wrapper).length
803 };
804 t.prototype.onHighlightMouseover = function (u) {
805 var v;
806 this.clearViewerHideTimer();
807 if (this.mouseIsDown || this.viewer.isShown()) {
808 return false
809 }
810 v = h(u.target).parents(".annotator-hl").andSelf().map(function () {
811 return h(this).data("annotation")
812 });
813 return this.showViewer(h.makeArray(v), a.mousePosition(u, this.wrapper[0]))
814 };
815 t.prototype.onAdderMousedown = function (u) {
816 if (u != null) {
817 u.preventDefault()
818 }
819 return this.ignoreMouseup = true
820 };
821 t.prototype.onAdderClick = function (v) {
822 var u;
823 if (v != null) {
824 v.preventDefault()
825 }
826 u = this.adder.position();
827 this.adder.hide();
828 return this.showEditor(this.createAnnotation(), u)
829 };
830 t.prototype.onEditAnnotation = function (u) {
831 var v;
832 v = this.viewer.element.position();
833 this.viewer.hide();
834 return this.showEditor(u, v)
835 };
836 t.prototype.onDeleteAnnotation = function (u) {
837 this.viewer.hide();
838 return this.deleteAnnotation(u)
839 };
840 return t
841 })();
842 o.Plugin = (function () {
843 q(t, b);
844
845 function t(v, u) {
846 t.__super__.constructor.apply(this, arguments)
847 }
848 t.prototype.pluginInit = function () {};
849 return t
850 })();
851 o.$ = h;
852 o.supported = function () {
853 return (function () {
854 return !!this.getSelection
855 })()
856 };
857 o.noConflict = function () {
858 a.getGlobal().Annotator = e;
859 return this
860 };
861 h.plugin("annotator", o);
862 this.Annotator = o;
863 o.Widget = (function () {
864 q(t, b);
865 t.prototype.classes = {
866 hide: "annotator-hide",
867 invert: {
868 x: "annotator-invert-x",
869 y: "annotator-invert-y"
870 }
871 };
872
873 function t(v, u) {
874 t.__super__.constructor.apply(this, arguments);
875 this.classes = h.extend({}, o.Widget.prototype.classes, this.classes)
876 }
877 t.prototype.checkOrientation = function () {
878 var x, y, u, w, v;
879 this.resetOrientation();
880 v = h(a.getGlobal());
881 w = this.element.children(":first");
882 y = w.offset();
883 u = {
884 top: v.scrollTop(),
885 right: v.width() + v.scrollLeft()
886 };
887 x = {
888 top: y.top,
889 right: y.left + w.width()
890 };
891 if ((x.top - u.top) < 0) {
892 this.invertY()
893 }
894 if ((x.right - u.right) > 0) {
895 this.invertX()
896 }
897 return this
898 };
899 t.prototype.resetOrientation = function () {
900 this.element.removeClass(this.classes.invert.x).removeClass(this.classes.invert.y);
901 return this
902 };
903 t.prototype.invertX = function () {
904 this.element.addClass(this.classes.invert.x);
905 return this
906 };
907 t.prototype.invertY = function () {
908 this.element.addClass(this.classes.invert.y);
909 return this
910 };
911 return t
912 })();
913 o.Editor = (function () {
914 q(t, o.Widget);
915 t.prototype.events = {
916 "form submit": "submit",
917 ".annotator-save click": "submit",
918 ".annotator-cancel click": "hide",
919 ".annotator-cancel mouseover": "onCancelButtonMouseover",
920 "textarea keydown": "processKeypress"
921 };
922 t.prototype.classes = {
923 hide: "annotator-hide",
924 focus: "annotator-focus"
925 };
926 t.prototype.html = '<div class="annotator-outer annotator-editor">\n <form class="annotator-widget">\n <ul class="annotator-listing"></ul>\n <div class="annotator-controls">\n <a href="#cancel" class="annotator-cancel">Cancel</a>\n <a href="#save" class="annotator-save annotator-focus">Save</a>\n </div>\n <span class="annotator-resize"></span>\n </form>\n</div>';
927 t.prototype.options = {};
928
929 function t(u) {
930 this.onCancelButtonMouseover = g(this.onCancelButtonMouseover, this);
931 this.processKeypress = g(this.processKeypress, this);
932 this.submit = g(this.submit, this);
933 this.load = g(this.load, this);
934 this.hide = g(this.hide, this);
935 this.show = g(this.show, this);
936 t.__super__.constructor.call(this, h(this.html)[0], u);
937 this.fields = [];
938 this.annotation = {};
939 this.setupDragabbles()
940 }
941 t.prototype.show = function (u) {
942 if (u != null) {
943 u.preventDefault()
944 }
945 this.element.removeClass(this.classes.hide);
946 this.element.find(".annotator-save").addClass(this.classes.focus);
947 this.element.find(":input:first").focus();
948 return this.checkOrientation().publish("show")
949 };
950 t.prototype.hide = function (u) {
951 if (u != null) {
952 u.preventDefault()
953 }
954 this.element.addClass(this.classes.hide);
955 return this.publish("hide")
956 };
957 t.prototype.load = function (u) {
958 var w, v, y, x;
959 this.annotation = u;
960 this.publish("load", [this.annotation]);
961 x = this.fields;
962 for (v = 0, y = x.length; v < y; v++) {
963 w = x[v];
964 w.load(w.element, this.annotation)
965 }
966 return this.show()
967 };
968 t.prototype.submit = function (v) {
969 var w, u, y, x;
970 if (v != null) {
971 v.preventDefault()
972 }
973 x = this.fields;
974 for (u = 0, y = x.length; u < y; u++) {
975 w = x[u];
976 w.submit(w.element, this.annotation)
977 }
978 this.publish("save", [this.annotation]);
979 return this.hide()
980 };
981 t.prototype.addField = function (v) {
982 var w, x, u;
983 x = h.extend({
984 id: "annotator-field-" + (new Date()).getTime(),
985 type: "input",
986 label: "",
987 load: function () {},
988 submit: function () {}
989 }, v);
990 u = null;
991 w = h('<li class="annotator-item" />');
992 x.element = w[0];
993 switch (x.type) {
994 case "textarea":
995 u = h("<textarea />");
996 break;
997 case "input":
998 case "checkbox":
999 u = h("<input />")
1000 }
1001 w.append(u);
1002 u.attr({
1003 id: x.id,
1004 placeholder: x.label
1005 });
1006 if (x.type === "checkbox") {
1007 u[0].type = "checkbox";
1008 w.addClass("annotator-checkbox");
1009 w.append(h("<label />", {
1010 "for": x.id,
1011 html: x.label
1012 }))
1013 }
1014 this.element.find("ul:first").append(w);
1015 this.fields.push(x);
1016 return x.element
1017 };
1018 t.prototype.checkOrientation = function () {
1019 var u, w, v;
1020 t.__super__.checkOrientation.apply(this, arguments);
1021 v = this.element.find("ul");
1022 u = this.element.find(".annotator-controls");
1023 w = function () {
1024 return v.children().each(function () {
1025 return h(this).parent().prepend(this)
1026 })
1027 };
1028 if (this.element.hasClass(this.classes.invert.y) && v.is(":first-child")) {
1029 u.insertBefore(v);
1030 w()
1031 } else {
1032 if (u.is(":first-child")) {
1033 u.insertAfter(v);
1034 w()
1035 }
1036 }
1037 return this
1038 };
1039 t.prototype.processKeypress = function (u) {
1040 if (u.keyCode === 27) {
1041 return this.hide()
1042 } else {
1043 if (u.keyCode === 13 && !u.shiftKey) {
1044 return this.submit()
1045 }
1046 }
1047 };
1048 t.prototype.onCancelButtonMouseover = function () {
1049 return this.element.find("." + this.classes.focus).removeClass(this.classes.focus)
1050 };
1051 t.prototype.setupDragabbles = function () {
1052 var w, D, z, u, y, B, x, v, A, C;
1053 u = null;
1054 w = this.classes;
1055 z = this.element;
1056 A = null;
1057 v = z.find(".annotator-resize");
1058 D = z.find(".annotator-controls");
1059 C = false;
1060 y = function (E) {
1061 if (E.target === this) {
1062 u = {
1063 element: this,
1064 top: E.pageY,
1065 left: E.pageX
1066 };
1067 A = z.find("textarea:first");
1068 h(window).bind({
1069 "mouseup.annotator-editor-resize": x,
1070 "mousemove.annotator-editor-resize": B
1071 });
1072 return E.preventDefault()
1073 }
1074 };
1075 x = function () {
1076 u = null;
1077 return h(window).unbind(".annotator-editor-resize")
1078 };
1079 B = g(function (I) {
1080 var J, G, F, E, H;
1081 if (u && C === false) {
1082 J = {
1083 top: I.pageY - u.top,
1084 left: I.pageX - u.left
1085 };
1086 if (u.element === v[0]) {
1087 E = A.outerHeight();
1088 H = A.outerWidth();
1089 G = z.hasClass(w.invert.x) ? -1 : 1;
1090 F = z.hasClass(w.invert.y) ? 1 : -1;
1091 A.height(E + (J.top * F));
1092 A.width(H + (J.left * G));
1093 if (A.outerHeight() !== E) {
1094 u.top = I.pageY
1095 }
1096 if (A.outerWidth() !== H) {
1097 u.left = I.pageX
1098 }
1099 } else {
1100 if (u.element === D[0]) {
1101 z.css({
1102 top: parseInt(z.css("top"), 10) + J.top,
1103 left: parseInt(z.css("left"), 10) + J.left
1104 });
1105 u.top = I.pageY;
1106 u.left = I.pageX
1107 }
1108 }
1109 C = true;
1110 return setTimeout(function () {
1111 return C = false
1112 }, 1000 / 60)
1113 }
1114 }, this);
1115 v.bind("mousedown", y);
1116 return D.bind("mousedown", y)
1117 };
1118 return t
1119 })();
1120 o.Viewer = (function () {
1121 q(t, o.Widget);
1122 t.prototype.events = {
1123 ".annotator-edit click": "onEditClick",
1124 ".annotator-delete click": "onDeleteClick"
1125 };
1126 t.prototype.classes = {
1127 hide: "annotator-hide",
1128 showControls: "annotator-visible"
1129 };
1130 t.prototype.html = {
1131 element: '<div class="annotator-outer annotator-viewer">\n <ul class="annotator-widget annotator-listing"></ul>\n</div>',
1132 item: '<li class="annotator-annotation annotator-item">\n <span class="annotator-controls">\n <button class="annotator-edit">Edit</button>\n <button class="annotator-delete">Delete</button>\n </span>\n</li>'
1133 };
1134
1135 function t(u) {
1136 this.onDeleteClick = g(this.onDeleteClick, this);
1137 this.onEditClick = g(this.onEditClick, this);
1138 this.load = g(this.load, this);
1139 this.hide = g(this.hide, this);
1140 this.show = g(this.show, this);
1141 t.__super__.constructor.call(this, h(this.html.element)[0], u);
1142 this.item = h(this.html.item)[0];
1143 this.fields = [];
1144 this.annotations = []
1145 }
1146 t.prototype.show = function (v) {
1147 var u;
1148 if (v != null) {
1149 v.preventDefault()
1150 }
1151 u = this.element.find(".annotator-controls").addClass(this.classes.showControls);
1152 setTimeout((g(function () {
1153 return u.removeClass(this.classes.showControls)
1154 }, this)), 500);
1155 this.element.removeClass(this.classes.hide);
1156 return this.checkOrientation().publish("show")
1157 };
1158 t.prototype.isShown = function () {
1159 return !this.element.hasClass(this.classes.hide)
1160 };
1161 t.prototype.hide = function (u) {
1162 if (u != null) {
1163 //u.preventDefault()
1164 }
1165 this.element.addClass(this.classes.hide);
1166 return this.publish("hide")
1167 };
1168 t.prototype.load = function (C) {
1169 var z, B, G, H, F, A, E, I, D, y, w, u, J, x, v;
1170 this.annotations = C || [];
1171 D = this.element.find("ul:first").empty();
1172 x = this.annotations;
1173 for (y = 0, u = x.length; y < u; y++) {
1174 z = x[y];
1175 I = h(this.item).clone().appendTo(D).data("annotation", z);
1176 G = I.find(".annotator-controls");
1177 F = G.find(".annotator-edit");
1178 H = G.find(".annotator-delete");
1179 B = {
1180 showEdit: function () {
1181 return F.removeAttr("disabled")
1182 },
1183 hideEdit: function () {
1184 return F.attr("disabled", "disabled")
1185 },
1186 showDelete: function () {
1187 return H.removeAttr("disabled")
1188 },
1189 hideDelete: function () {
1190 return H.attr("disabled", "disabled")
1191 }
1192 };
1193 v = this.fields;
1194 for (w = 0, J = v.length; w < J; w++) {
1195 E = v[w];
1196 A = h(E.element).clone().appendTo(I)[0];
1197 E.load(A, z, B)
1198 }
1199 }
1200 this.publish("load", [this.annotations]);
1201 return this.show()
1202 };
1203 t.prototype.addField = function (u) {
1204 var v;
1205 v = h.extend({
1206 load: function () {}
1207 }, u);
1208 v.element = h("<div />")[0];
1209 this.fields.push(v);
1210 v.element;
1211 return this
1212 };
1213 t.prototype.onEditClick = function (u) {
1214 return this.onButtonClick(u, "edit")
1215 };
1216 t.prototype.onDeleteClick = function (u) {
1217 return this.onButtonClick(u, "delete")
1218 };
1219 t.prototype.onButtonClick = function (w, u) {
1220 var v;
1221 v = h(w.target).parents(".annotator-annotation");
1222 return this.publish(u, [v.data("annotation")])
1223 };
1224 return t
1225 })();
1226 o = o || {};
1227 o.Notification = (function () {
1228 q(t, b);
1229 t.prototype.events = {
1230 click: "hide"
1231 };
1232 t.prototype.options = {
1233 html: "<div class='annotator-notice'></div>",
1234 classes: {
1235 show: "annotator-notice-show",
1236 info: "annotator-notice-info",
1237 success: "annotator-notice-success",
1238 error: "annotator-notice-error"
1239 }
1240 };
1241
1242 function t(u) {
1243 this.hide = g(this.hide, this);
1244 this.show = g(this.show, this);
1245 t.__super__.constructor.call(this, h(this.options.html).appendTo(document.body)[0], u)
1246 }
1247 t.prototype.show = function (v, u) {
1248 if (u == null) {
1249 u = o.Notification.INFO
1250 }
1251 h(this.element).addClass(this.options.classes.show).addClass(this.options.classes[u]).escape(v || "");
1252 setTimeout(this.hide, 5000);
1253 return this
1254 };
1255 t.prototype.hide = function () {
1256 h(this.element).removeClass(this.options.classes.show);
1257 return this
1258 };
1259 return t
1260 })();
1261 o.Notification.INFO = "show";
1262 o.Notification.SUCCESS = "success";
1263 o.Notification.ERROR = "error";
1264 h(function () {
1265 var t;
1266 t = new o.Notification;
1267 o.showNotification = t.show;
1268 return o.hideNotification = t.hide
1269 });
1270 o.Plugin.Tags = (function () {
1271 q(t, o.Plugin);
1272
1273 function t() {
1274 this.setAnnotationTags = g(this.setAnnotationTags, this);
1275 this.updateField = g(this.updateField, this);
1276 t.__super__.constructor.apply(this, arguments)
1277 }
1278 t.prototype.field = null;
1279 t.prototype.input = null;
1280 t.prototype.pluginInit = function () {
1281 if (!o.supported()) {
1282 return
1283 }
1284 this.field = this.annotator.editor.addField({
1285 label: "Add some tags here\u2026",
1286 load: this.updateField,
1287 submit: this.setAnnotationTags
1288 });
1289 this.annotator.viewer.addField({
1290 load: this.updateViewer
1291 });
1292 if (this.annotator.plugins.Filter) {
1293 this.annotator.plugins.Filter.addFilter({
1294 label: "Tag",
1295 property: "tags",
1296 isFiltered: o.Plugin.Tags.filterCallback
1297 })
1298 }
1299 return this.input = h(this.field).find(":input")
1300 };
1301 t.prototype.parseTags = function (v) {
1302 var u;
1303 v = h.trim(v);
1304 u = [];
1305 if (v) {
1306 u = v.split(/\s+/)
1307 }
1308 return u
1309 };
1310 t.prototype.stringifyTags = function (u) {
1311 return u.join(" ")
1312 };
1313 t.prototype.updateField = function (w, u) {
1314 var v;
1315 v = "";
1316 if (u.tags) {
1317 v = this.stringifyTags(u.tags)
1318 }
1319 return this.input.val(v)
1320 };
1321 t.prototype.setAnnotationTags = function (v, u) {
1322 return u.tags = this.parseTags(this.input.val())
1323 };
1324 t.prototype.updateViewer = function (v, u) {
1325 v = h(v);
1326 if (u.tags && h.isArray(u.tags) && u.tags.length) {
1327 return v.addClass("annotator-tags").html(function () {
1328 var w;
1329 return w = h.map(u.tags, function (x) {
1330 return '<span class="annotator-tag">' + o.$.escape(x) + "</span>"
1331 }).join(" ")
1332 })
1333 } else {
1334 return v.remove()
1335 }
1336 };
1337 return t
1338 })();
1339 o.Plugin.Tags.filterCallback = function (z, B) {
1340 var y, x, w, C, v, u, t, A;
1341 if (B == null) {
1342 B = []
1343 }
1344 w = 0;
1345 x = [];
1346 if (z) {
1347 x = z.split(/\s+/g);
1348 for (v = 0, t = x.length; v < t; v++) {
1349 y = x[v];
1350 if (B.length) {
1351 for (u = 0, A = B.length; u < A; u++) {
1352 C = B[u];
1353 if (C.indexOf(y) !== -1) {
1354 w += 1
1355 }
1356 }
1357 }
1358 }
1359 }
1360 return w === x.length
1361 };
1362 n = function (u) {
1363 var y, t, x, v, w, z;
1364 v = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
1365 y = u.match(new RegExp(v));
1366 x = 0;
1367 t = new Date(y[1], 0, 1);
1368 if (y[3]) {
1369 t.setMonth(y[3] - 1)
1370 }
1371 if (y[5]) {
1372 t.setDate(y[5])
1373 }
1374 if (y[7]) {
1375 t.setHours(y[7])
1376 }
1377 if (y[8]) {
1378 t.setMinutes(y[8])
1379 }
1380 if (y[10]) {
1381 t.setSeconds(y[10])
1382 }
1383 if (y[12]) {
1384 t.setMilliseconds(Number("0." + y[12]) * 1000)
1385 }
1386 if (y[14]) {
1387 x = (Number(y[16]) * 60) + Number(y[17]);
1388 x *= (z = y[15] === "-") != null ? z : {
1389 1: -1
1390 }
1391 }
1392 x -= t.getTimezoneOffset();
1393 w = Number(t) + (x * 60 * 1000);
1394 t.setTime(Number(w));
1395 return t
1396 };
1397 o.Plugin.Auth = (function () {
1398 q(t, o.Plugin);
1399 t.prototype.options = {
1400 token: null,
1401 tokenUrl: "/auth/token",
1402 autoFetch: true
1403 };
1404
1405 function t(v, u) {
1406 this.haveValidToken = g(this.haveValidToken, this);
1407 t.__super__.constructor.apply(this, arguments);
1408 this.element.data("annotator:auth", this);
1409 this.waitingForToken = [];
1410 if (this.options.token) {
1411 this.setToken(this.options.token)
1412 } else {
1413 this.requestToken()
1414 }
1415 }
1416 t.prototype.requestToken = function () {
1417 this.requestInProgress = true;
1418 return h.getJSON(this.options.tokenUrl, g(function (v, u, w) {
1419 if (u !== "success") {
1420 return console.error("Couldn't get auth token: " + u, w)
1421 } else {
1422 this.setToken(v);
1423 return this.requestInProgress = false
1424 }
1425 }, this))
1426 };
1427 t.prototype.setToken = function (v) {
1428 var u;
1429 this.token = v;
1430 if (this.haveValidToken()) {
1431 if (this.options.autoFetch) {
1432 this.refreshTimeout = setTimeout((g(function () {
1433 return this.requestToken()
1434 }, this)), (this.timeToExpiry() - 2) * 1000)
1435 }
1436 this.updateHeaders();
1437 u = [];
1438 while (this.waitingForToken.length > 0) {
1439 u.push(this.waitingForToken.pop().apply())
1440 }
1441 return u
1442 } else {
1443 console.warn("Didn't get a valid token.");
1444 if (this.options.autoFetch) {
1445 console.warn("Getting a new token in 10s.");
1446 return setTimeout((g(function () {
1447 return this.requestToken()
1448 }, this)), 10 * 1000)
1449 }
1450 }
1451 };
1452 t.prototype.haveValidToken = function () {
1453 var u;
1454 u = this.token && this.token.authToken && this.token.authTokenIssueTime && this.token.authTokenTTL && this.token.accountId && this.token.userId;
1455 return u && this.timeToExpiry() > 0
1456 };
1457 t.prototype.timeToExpiry = function () {
1458 var w, u, v, x;
1459 v = new Date().getTime() / 1000;
1460 u = n(this.token.authTokenIssueTime).getTime() / 1000;
1461 w = u + this.token.authTokenTTL;
1462 x = w - v;
1463 if (x > 0) {
1464 return x
1465 } else {
1466 return 0
1467 }
1468 };
1469 t.prototype.updateHeaders = function () {
1470 var u;
1471 u = this.element.data("annotator:headers");
1472 return this.element.data("annotator:headers", h.extend(u, {
1473 "x-annotator-auth-token": this.token.authToken,
1474 "x-annotator-auth-token-issue-time": this.token.authTokenIssueTime,
1475 "x-annotator-auth-token-ttl": this.token.authTokenTTL,
1476 "x-annotator-account-id": this.token.accountId,
1477 "x-annotator-user-id": this.token.userId
1478 }))
1479 };
1480 t.prototype.withToken = function (u) {
1481 if (!(u != null)) {
1482 return
1483 }
1484 if (this.haveValidToken()) {
1485 return u()
1486 } else {
1487 this.waitingForToken.push(u);
1488 if (!this.requestInProgress) {
1489 return this.requestToken()
1490 }
1491 }
1492 };
1493 return t
1494 })();
1495 o.Plugin.Store = (function () {
1496 q(t, o.Plugin);
1497 t.prototype.events = {
1498 annotationCreated: "annotationCreated",
1499 annotationDeleted: "annotationDeleted",
1500 annotationUpdated: "annotationUpdated"
1501 };
1502 t.prototype.options = {
1503 prefix: "/store",
1504 autoFetch: true,
1505 annotationData: {},
1506 loadFromSearch: false,
1507 urls: {
1508 create: "/annotations",
1509 read: "/annotations/:id",
1510 update: "/annotations/:id",
1511 destroy: "/annotations/:id",
1512 search: "/search"
1513 }
1514 };
1515
1516 function t(v, u) {
1517 this._onError = g(this._onError, this);
1518 this._onBeforeSend = g(this._onBeforeSend, this);
1519 this._onLoadAnnotationsFromSearch = g(this._onLoadAnnotationsFromSearch, this);
1520 this._onLoadAnnotations = g(this._onLoadAnnotations, this);
1521 this._getAnnotations = g(this._getAnnotations, this);
1522 t.__super__.constructor.apply(this, arguments);
1523 this.annotations = []
1524 }
1525 t.prototype.pluginInit = function () {
1526 var u;
1527 if (!o.supported()) {
1528 return
1529 }
1530 u = this.element.data("annotator:auth");
1531 if (u) {
1532 return u.withToken(this._getAnnotations)
1533 } else {
1534 return this._getAnnotations()
1535 }
1536 };
1537 t.prototype._getAnnotations = function () {
1538 if (this.options.loadFromSearch) {
1539 return this.loadAnnotationsFromSearch(this.options.loadFromSearch)
1540 } else {
1541 return this.loadAnnotations()
1542 }
1543 };
1544 t.prototype.annotationCreated = function (u) {
1545 if (f.call(this.annotations, u) < 0) {
1546 this.registerAnnotation(u);
1547 return this._apiRequest("create", u, g(function (v) {
1548 if (!(v.id != null)) {
1549 console.warn("Warning: No ID returned from server for annotation ", u)
1550 }
1551 return this.updateAnnotation(u, v)
1552 }, this))
1553 } else {
1554 return this.updateAnnotation(u, {})
1555 }
1556 };
1557 t.prototype.annotationUpdated = function (u) {
1558 if (f.call(this.annotations, u) >= 0) {
1559 return this._apiRequest("update", u, (g(function (v) {
1560 return this.updateAnnotation(u, v)
1561 }, this)))
1562 }
1563 };
1564 t.prototype.annotationDeleted = function (u) {
1565 if (f.call(this.annotations, u) >= 0) {
1566 return this._apiRequest("destroy", u, (g(function () {
1567 return this.unregisterAnnotation(u)
1568 }, this)))
1569 }
1570 };
1571 t.prototype.registerAnnotation = function (u) {
1572 return this.annotations.push(u)
1573 };
1574 t.prototype.unregisterAnnotation = function (u) {
1575 return this.annotations.splice(this.annotations.indexOf(u), 1)
1576 };
1577 t.prototype.updateAnnotation = function (u, v) {
1578 if (f.call(this.annotations, u) < 0) {
1579 console.error("Trying to update unregistered annotation!")
1580 } else {
1581 h.extend(u, v)
1582 }
1583
1584 var rangeString = u.ranges[0].startOffset + "_" + u.ranges[0].endOffset;
1585
1586 var found = false;
1587 for(var i = 0; i < gs.annotationArray.keys.length; i++){if(gs.annotationArray.keys[i] == rangeString){found = true; break;}}
1588
1589 if(!found)
1590 {
1591 gs.annotationArray.keys.push(rangeString);
1592 }
1593 gs.annotationArray[rangeString] = u;
1594 console.log("(setup) Adding " + u.quote + ", " + u.text + ", " + u.tags + " to " + rangeString);
1595 return h(u.highlights).data("annotation", u)
1596 };
1597 t.prototype.loadAnnotations = function () {
1598 return this._apiRequest("read", null, this._onLoadAnnotations)
1599 };
1600 t.prototype._onLoadAnnotations = function (u) {
1601 if (u == null) {
1602 u = []
1603 }
1604 this.annotations = u;
1605 return this.annotator.loadAnnotations(u.slice())
1606 };
1607 t.prototype.loadAnnotationsFromSearch = function (u) {
1608 return this._apiRequest("search", u, this._onLoadAnnotationsFromSearch)
1609 };
1610 t.prototype._onLoadAnnotationsFromSearch = function (u) {
1611 if (u == null) {
1612 u = {}
1613 }
1614 return this._onLoadAnnotations(u.rows || [])
1615 };
1616 t.prototype.dumpAnnotations = function () {
1617 var w, v, y, x, u;
1618 x = this.annotations;
1619 u = [];
1620 for (v = 0, y = x.length; v < y; v++) {
1621 w = x[v];
1622 u.push(JSON.parse(this._dataFor(w)))
1623 }
1624 return u
1625 };
1626 t.prototype._apiRequest = function (x, y, z) {
1627 var A, v, w, u;
1628 A = y && y.id;
1629 u = this._urlFor(x, A);
1630 v = this._apiRequestOptions(x, y, z);
1631 w = h.ajax(u, v);
1632 w._id = A;
1633 w._action = x;
1634 return w
1635 };
1636 t.prototype._apiRequestOptions = function (v, w, x) {
1637 var u;
1638 u = {
1639 type: this._methodFor(v),
1640 beforeSend: this._onBeforeSend,
1641 dataType: "json",
1642 success: x ||
1643 function () {},
1644 error: this._onError
1645 };
1646 if (v === "search") {
1647 u = h.extend(u, {
1648 data: w
1649 })
1650 } else {
1651 u = h.extend(u, {
1652 data: w && this._dataFor(w),
1653 contentType: "application/json; charset=utf-8"
1654 })
1655 }
1656 return u
1657 };
1658 t.prototype._urlFor = function (w, x) {
1659 var u, v;
1660 u = x != null ? "/" + x : "";
1661 v = this.options.prefix || "/";
1662 v += this.options.urls[w];
1663 v = v.replace(/\/:id/, u);
1664 return v
1665 };
1666 t.prototype._methodFor = function (v) {
1667 var u;
1668 u = {
1669 create: "POST",
1670 read: "GET",
1671 update: "PUT",
1672 destroy: "DELETE",
1673 search: "GET"
1674 };
1675 return u[v]
1676 };
1677 t.prototype._dataFor = function (u) {
1678 var v, w;
1679 w = u.highlights;
1680 delete u.highlights;
1681 h.extend(u, this.options.annotationData);
1682 v = JSON.stringify(u);
1683 if (w) {
1684 u.highlights = w
1685 }
1686 return v
1687 };
1688 t.prototype._onBeforeSend = function (y) {
1689 var x, v, w, u;
1690 x = this.element.data("annotator:headers");
1691 if (x) {
1692 u = [];
1693 for (v in x) {
1694 w = x[v];
1695 u.push(y.setRequestHeader(v, w))
1696 }
1697 return u
1698 }
1699 };
1700 t.prototype._onError = function (w) {
1701 var v, u;
1702 v = w._action;
1703 u = "Sorry we could not " + v + " this annotation";
1704 if (w._action === "search") {
1705 u = "Sorry we could not search the store for annotations"
1706 } else {
1707 if (w._action === "read" && !w._id) {
1708 u = "Sorry we could not " + v + " the annotations from the store"
1709 }
1710 }
1711 switch (w.status) {
1712 case 401:
1713 u = "Sorry you are not allowed to " + v + " this annotation";
1714 break;
1715 case 404:
1716 u = "Sorry we could not connect to the annotations store";
1717 break;
1718 case 500:
1719 u = "Sorry something went wrong with the annotation store"
1720 }
1721 o.showNotification(u, o.Notification.ERROR);
1722 return console.error("API request failed: '" + w.status + "'")
1723 };
1724 return t
1725 })();
1726 o.Plugin.Filter = (function () {
1727 q(t, o.Plugin);
1728 t.prototype.events = {
1729 ".annotator-filter-property input focus": "_onFilterFocus",
1730 ".annotator-filter-property input blur": "_onFilterBlur",
1731 ".annotator-filter-property input keyup": "_onFilterKeyup",
1732 ".annotator-filter-previous click": "_onPreviousClick",
1733 ".annotator-filter-next click": "_onNextClick",
1734 ".annotator-filter-clear click": "_onClearClick"
1735 };
1736 t.prototype.classes = {
1737 active: "annotator-filter-active",
1738 hl: {
1739 hide: "annotator-hl-filtered",
1740 active: "annotator-hl-active"
1741 }
1742 };
1743 t.prototype.html = {
1744 // element: '<div class="annotator-filter">\n <strong>Navigate:</strong>\n <span class="annotator-filter-navigation">\n <button class="annotator-filter-previous">Previous</button>\n <button class="annotator-filter-next">Next</button>\n </span>\n <strong>Filter by:</strong>\n</div>',
1745 filter: '<span class="annotator-filter-property">\n <label></label>\n <input/>\n <button class="annotator-filter-clear">Clear</button>\n</span>'
1746 };
1747 t.prototype.options = {
1748 appendTo: "body",
1749 filters: [],
1750 addAnnotationFilter: true,
1751 isFiltered: function (v, x) {
1752 var u, w, z, y;
1753 if (!(v && x)) {
1754 return false
1755 }
1756 y = v.split(/\s*/);
1757 for (w = 0, z = y.length; w < z; w++) {
1758 u = y[w];
1759 if (x.indexOf(u) === -1) {
1760 return false
1761 }
1762 }
1763 return true
1764 }
1765 };
1766
1767 function t(v, u) {
1768 this._onPreviousClick = g(this._onPreviousClick, this);
1769 this._onNextClick = g(this._onNextClick, this);
1770 this._onFilterKeyup = g(this._onFilterKeyup, this);
1771 this._onFilterBlur = g(this._onFilterBlur, this);
1772 this._onFilterFocus = g(this._onFilterFocus, this);
1773 this.updateHighlights = g(this.updateHighlights, this);
1774 v = h(this.html.element).appendTo(this.options.appendTo);
1775 t.__super__.constructor.call(this, v, u);
1776 this.filter = h(this.html.filter);
1777 this.filters = [];
1778 this.current = 0
1779 }
1780 t.prototype.pluginInit = function () {
1781 var v, u, x, w;
1782 w = this.options.filters;
1783 for (u = 0, x = w.length; u < x; u++) {
1784 v = w[u];
1785 this.addFilter(v)
1786 }
1787 this.updateHighlights();
1788 this._setupListeners()._insertSpacer();
1789 if (this.options.addAnnotationFilter === true) {
1790 return this.addFilter({
1791 label: "Annotation",
1792 property: "text"
1793 })
1794 }
1795 };
1796 t.prototype._insertSpacer = function () {
1797 var v, u;
1798 u = h("html");
1799 v = parseInt(u.css("padding-top"), 10) || 0;
1800 u.css("padding-top", v + this.element.outerHeight());
1801 return this
1802 };
1803 t.prototype._setupListeners = function () {
1804 var w, u, v, x;
1805 u = ["annotationsLoaded", "annotationCreated", "annotationUpdated", "annotationDeleted"];
1806 for (v = 0, x = u.length; v < x; v++) {
1807 w = u[v];
1808 this.annotator.subscribe(w, this.updateHighlights)
1809 }
1810 return this
1811 };
1812 t.prototype.addFilter = function (u) {
1813 var w, v;
1814 v = h.extend({
1815 label: "",
1816 property: "",
1817 isFiltered: this.options.isFiltered
1818 }, u);
1819 if (!((function () {
1820 var y, A, z, x;
1821 z = this.filters;
1822 x = [];
1823 for (y = 0, A = z.length; y < A; y++) {
1824 w = z[y];
1825 if (w.property === v.property) {
1826 x.push(w)
1827 }
1828 }
1829 return x
1830 }).call(this)).length) {
1831 v.id = "annotator-filter-" + v.property;
1832 v.annotations = [];
1833 v.element = this.filter.clone().appendTo(this.element);
1834 v.element.find("label").html(v.label).attr("for", v.id);
1835 v.element.find("input").attr({
1836 id: v.id,
1837 placeholder: "Filter by " + v.label + "\u2026"
1838 });
1839 v.element.find("button").hide();
1840 v.element.data("filter", v);
1841 this.filters.push(v)
1842 }
1843 return this
1844 };
1845 t.prototype.updateFilter = function (x) {
1846 var u, z, v, y, w, B, A;
1847 x.annotations = [];
1848 this.updateHighlights();
1849 this.resetHighlights();
1850 v = h.trim(x.element.find("input").val());
1851 if (v) {
1852 z = this.highlights.map(function () {
1853 return h(this).data("annotation")
1854 });
1855 A = h.makeArray(z);
1856 for (w = 0, B = A.length; w < B; w++) {
1857 u = A[w];
1858 y = u[x.property];
1859 if (x.isFiltered(v, y)) {
1860 x.annotations.push(u)
1861 }
1862 }
1863 return this.filterHighlights()
1864 }
1865 };
1866 t.prototype.updateHighlights = function () {
1867 this.highlights = this.annotator.element.find(".annotator-hl:visible");
1868 return this.filtered = this.highlights.not(this.classes.hl.hide)
1869 };
1870 t.prototype.filterHighlights = function () {
1871 var v, x, y, B, z, A, C, u, w;
1872 v = h.grep(this.filters, function (D) {
1873 return !!D.annotations.length
1874 });
1875 B = ((w = v[0]) != null ? w.annotations : void 0) || [];
1876 if (v.length > 1) {
1877 y = [];
1878 h.each(v, function () {
1879 return h.merge(y, this.annotations)
1880 });
1881 C = [];
1882 B = [];
1883 h.each(y, function () {
1884 if (h.inArray(this, C) === -1) {
1885 return C.push(this)
1886 } else {
1887 return B.push(this)
1888 }
1889 })
1890 }
1891 z = this.highlights;
1892 for (A = 0, u = B.length; A < u; A++) {
1893 x = B[A];
1894 z = z.not(x.highlights)
1895 }
1896 z.addClass(this.classes.hl.hide);
1897 this.filtered = this.highlights.not(this.classes.hl.hide);
1898 return this
1899 };
1900 t.prototype.resetHighlights = function () {
1901 this.highlights.removeClass(this.classes.hl.hide);
1902 this.filtered = this.highlights;
1903 return this
1904 };
1905 t.prototype._onFilterFocus = function (v) {
1906 var u;
1907 u = h(v.target);
1908 u.parent().addClass(this.classes.active);
1909 return u.next("button").show()
1910 };
1911 t.prototype._onFilterBlur = function (v) {
1912 var u;
1913 if (!v.target.value) {
1914 u = h(v.target);
1915 u.parent().removeClass(this.classes.active);
1916 return u.next("button").hide()
1917 }
1918 };
1919 t.prototype._onFilterKeyup = function (v) {
1920 var u;
1921 u = h(v.target).parent().data("filter");
1922 if (u) {
1923 return this.updateFilter(u)
1924 }
1925 };
1926 t.prototype._findNextHighlight = function (z) {
1927 var v, w, B, A, y, x, u, C;
1928 if (!this.highlights.length) {
1929 return this
1930 }
1931 x = z ? 0 : -1;
1932 C = z ? -1 : 0;
1933 u = z ? "lt" : "gt";
1934 v = this.highlights.not("." + this.classes.hl.hide);
1935 B = v.filter("." + this.classes.hl.active);
1936 if (!B.length) {
1937 B = v.eq(x)
1938 }
1939 w = B.data("annotation");
1940 A = v.index(B[0]);
1941 y = v.filter(":" + u + "(" + A + ")").not(w.highlights).eq(C);
1942 if (!y.length) {
1943 y = v.eq(C)
1944 }
1945 return this._scrollToHighlight(y.data("annotation").highlights)
1946 };
1947 t.prototype._onNextClick = function (u) {
1948 return this._findNextHighlight()
1949 };
1950 t.prototype._onPreviousClick = function (u) {
1951 return this._findNextHighlight(true)
1952 };
1953 t.prototype._scrollToHighlight = function (u) {
1954 u = h(u);
1955 this.highlights.removeClass(this.classes.hl.active);
1956 u.addClass(this.classes.hl.active);
1957 return h("html, body").animate({
1958 scrollTop: u.offset().top - (this.element.height() + 20)
1959 }, 150)
1960 };
1961 t.prototype._onClearClick = function (u) {
1962 return h(u.target).prev("input").val("").keyup().blur()
1963 };
1964 return t
1965 })();
1966 o.Plugin.Markdown = (function () {
1967 q(t, o.Plugin);
1968 t.prototype.events = {
1969 annotationViewerTextField: "updateTextField"
1970 };
1971
1972 function t(v, u) {
1973 this.updateTextField = g(this.updateTextField, this);
1974 if ((typeof Showdown !== "undefined" && Showdown !== null ? Showdown.converter : void 0) != null) {
1975 t.__super__.constructor.apply(this, arguments);
1976 this.converter = new Showdown.converter()
1977 } else {
1978 console.error("To use the Markdown plugin, you must include Showdown into the page first.")
1979 }
1980 }
1981 t.prototype.updateTextField = function (v, u) {
1982 var w;
1983 w = o.$.escape(u.text || "");
1984 return h(v).html(this.convert(w))
1985 };
1986 t.prototype.convert = function (u) {
1987 return this.converter.makeHtml(u)
1988 };
1989 return t
1990 })();
1991 o.Plugin.Unsupported = (function () {
1992 q(t, o.Plugin);
1993
1994 function t() {
1995 t.__super__.constructor.apply(this, arguments)
1996 }
1997 t.prototype.options = {
1998 message: "Sorry your current browser does not support the Annotator"
1999 };
2000 t.prototype.pluginInit = function () {
2001 if (!o.supported()) {
2002 return h(g(function () {
2003 o.showNotification(this.options.message);
2004 if ((window.XMLHttpRequest === void 0) && (ActiveXObject !== void 0)) {
2005 return h("html").addClass("ie6")
2006 }
2007 }, this))
2008 }
2009 };
2010 return t
2011 })();
2012 o.Plugin.Permissions = (function () {
2013 q(t, o.Plugin);
2014 t.prototype.events = {
2015 beforeAnnotationCreated: "addFieldsToAnnotation"
2016 };
2017 t.prototype.options = {
2018 showViewPermissionsCheckbox: true,
2019 showEditPermissionsCheckbox: true,
2020 userId: function (u) {
2021 return u
2022 },
2023 userString: function (u) {
2024 return u
2025 },
2026 userAuthorize: function (u, v) {
2027 return this.userId(u) === v
2028 },
2029 user: "",
2030 permissions: {
2031 read: [],
2032 update: [],
2033 "delete": [],
2034 admin: []
2035 }
2036 };
2037
2038 function t(v, u) {
2039 this.updateViewer = g(this.updateViewer, this);
2040 this.updateAnnotationPermissions = g(this.updateAnnotationPermissions, this);
2041 this.updatePermissionsField = g(this.updatePermissionsField, this);
2042 this.addFieldsToAnnotation = g(this.addFieldsToAnnotation, this);
2043 t.__super__.constructor.apply(this, arguments);
2044 if (this.options.user) {
2045 this.setUser(this.options.user);
2046 delete this.options.user
2047 }
2048 }
2049 t.prototype.pluginInit = function () {
2050 var u, v;
2051 if (!o.supported()) {
2052 return
2053 }
2054 v = this;
2055 u = function (x, w) {
2056 return function (z, y) {
2057 return v[x].call(v, w, z, y)
2058 }
2059 };
2060 if (this.options.showViewPermissionsCheckbox === true) {
2061 this.annotator.editor.addField({
2062 type: "checkbox",
2063 label: "Allow anyone to <strong>view</strong> this annotation",
2064 load: u("updatePermissionsField", "read"),
2065 submit: u("updateAnnotationPermissions", "read")
2066 })
2067 }
2068 if (this.options.showEditPermissionsCheckbox === true) {
2069 this.annotator.editor.addField({
2070 type: "checkbox",
2071 label: "Allow anyone to <strong>edit</strong> this annotation",
2072 load: u("updatePermissionsField", "update"),
2073 submit: u("updateAnnotationPermissions", "update")
2074 })
2075 }
2076 this.annotator.viewer.addField({
2077 load: this.updateViewer
2078 });
2079 if (this.annotator.plugins.Filter) {
2080 return this.annotator.plugins.Filter.addFilter({
2081 label: "User",
2082 property: "user",
2083 isFiltered: g(function (y, x) {
2084 var w, z, B, A;
2085 x = this.options.userString(x);
2086 if (!(y && x)) {
2087 return false
2088 }
2089 A = y.split(/\s*/);
2090 for (z = 0, B = A.length; z < B; z++) {
2091 w = A[z];
2092 if (x.indexOf(w) === -1) {
2093 return false
2094 }
2095 }
2096 return true
2097 }, this)
2098 })
2099 }
2100 };
2101 t.prototype.setUser = function (u) {
2102 return this.user = u
2103 };
2104 t.prototype.addFieldsToAnnotation = function (u) {
2105 if (u) {
2106 u.permissions = this.options.permissions;
2107 if (this.user) {
2108 return u.user = this.user
2109 }
2110 }
2111 };
2112 t.prototype.authorize = function (y, u, v) {
2113 var w, z, x, A;
2114 if (v === void 0) {
2115 v = this.user
2116 }
2117 if (u.permissions) {
2118 z = u.permissions[y] || [];
2119 if (z.length === 0) {
2120 return true
2121 }
2122 for (x = 0, A = z.length; x < A; x++) {
2123 w = z[x];
2124 if (this.options.userAuthorize.call(this.options, v, w)) {
2125 return true
2126 }
2127 }
2128 return false
2129 } else {
2130 if (u.user) {
2131 return v && this.options.userId(v) === u.user
2132 }
2133 }
2134 return true
2135 };
2136 t.prototype.updatePermissionsField = function (w, y, u) {
2137 var x, v;
2138 y = h(y).show();
2139 v = y.find("input").removeAttr("disabled");
2140 if (!this.authorize("admin", u)) {
2141 y.hide()
2142 }
2143 if (this.authorize(w, u || {}, null)) {
2144 v.attr("checked", "checked");
2145 x = {
2146 permissions: this.options.permissions
2147 };
2148 if (this.authorize(w, x, null)) {
2149 return v.attr("disabled", "disabled")
2150 }
2151 } else {
2152 return v.removeAttr("checked")
2153 }
2154 };
2155 t.prototype.updateAnnotationPermissions = function (w, x, u) {
2156 var y, v;
2157 if (!u.permissions) {
2158 u.permissions = this.options.permissions
2159 }
2160 y = w + "-permissions";
2161 if (h(x).find("input").is(":checked")) {
2162 h.data(u, y, u.permissions[w]);
2163 return u.permissions[w] = []
2164 } else {
2165 v = h.data(u, y);
2166 if (v) {
2167 return u.permissions[w] = v
2168 }
2169 }
2170 };
2171 t.prototype.updateViewer = function (x, u, w) {
2172 var v, y;
2173 x = h(x);
2174 y = this.options.userString(u.user);
2175 if (u.user && y && typeof y === "string") {
2176 v = o.$.escape(this.options.userString(u.user));
2177 x.html(v).addClass("annotator-user")
2178 } else {
2179 x.remove()
2180 }
2181 if (u.permissions) {
2182 if (!this.authorize("update", u)) {
2183 w.hideEdit()
2184 }
2185 if (!this.authorize("delete", u)) {
2186 return w.hideDelete()
2187 }
2188 } else {
2189 if (u.user && !this.authorize(null, u)) {
2190 w.hideEdit();
2191 return w.hideDelete()
2192 }
2193 }
2194 };
2195 return t
2196 })();
2197 o.prototype.setupPlugins = function (w, E) {
2198 var B, D, u, t, y, v, A, C, z, x;
2199 if (w == null) {
2200 w = {}
2201 }
2202 if (E == null) {
2203 E = {}
2204 }
2205 z = a.getGlobal();
2206 y = {
2207 Tags: {},
2208 Filter: {
2209 filters: [{
2210 label: "User",
2211 property: "user"
2212 }, {
2213 label: "Tags",
2214 property: "tags"
2215 }]
2216 },
2217 Unsupported: {}
2218 };
2219 if (z.Showdown) {
2220 y.Markdown = {}
2221 }
2222 A = w.userId, C = w.userName, B = w.accountId, D = w.authToken;
2223 if (A && C && B && D) {
2224 v = z.location.href.split(/#|\?/).shift() || "";
2225 h.extend(y, {
2226 Store: {
2227 prefix: w.storeUri || "http://annotateit.org/api",
2228 annotationData: {
2229 uri: v
2230 },
2231 loadFromSearch: {
2232 uri: v,
2233 all_fields: 1
2234 }
2235 },
2236 Permissions: {
2237 user: {
2238 id: w.userId,
2239 name: w.userName
2240 },
2241 permissions: {
2242 read: [w.userId],
2243 update: [w.userId],
2244 "delete": [w.userId],
2245 admin: [w.userId]
2246 },
2247 userId: function (F) {
2248 if (F != null ? F.id : void 0) {
2249 return F.id
2250 } else {
2251 return ""
2252 }
2253 },
2254 userString: function (F) {
2255 if (F != null ? F.name : void 0) {
2256 return F.name
2257 } else {
2258 return ""
2259 }
2260 }
2261 }
2262 });
2263 this.element.data({
2264 "annotator:headers": {
2265 "X-Annotator-User-Id": w.userId,
2266 "X-Annotator-Account-Id": w.accountId,
2267 "X-Annotator-Auth-Token": w.authToken
2268 }
2269 })
2270 }
2271 h.extend(y, E);
2272 x = [];
2273 for (u in y) {
2274 if (!k.call(y, u)) {
2275 continue
2276 }
2277 t = y[u];
2278 if (t !== null && t !== false) {
2279 x.push(this.addPlugin(u, t))
2280 }
2281 }
2282 return x
2283 }
2284}).call(this);
Note: See TracBrowser for help on using the repository browser.