您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在网页上添加注释,文字高亮。本脚本基于‘Annotation’--一个可以轻松在网页上添加注释的公开库。我仅仅将代码整合一下,使其成为一个类似add-one的用户脚本。//To easily annotate and highlight the contents on webpage.This userscript relays on 'Annotator'--an open-source JavaScript library to easily add annotation functionality to any webpage. I just integrated some code and make it a add-one like userscript.
// ==UserScript== // @name annotation // @namespace // @version 0.1 beta // @require http://code.jquery.com/jquery-2.1.1.js // @description 在网页上添加注释,文字高亮。本脚本基于‘Annotation’--一个可以轻松在网页上添加注释的公开库。我仅仅将代码整合一下,使其成为一个类似add-one的用户脚本。//To easily annotate and highlight the contents on webpage.This userscript relays on 'Annotator'--an open-source JavaScript library to easily add annotation functionality to any webpage. I just integrated some code and make it a add-one like userscript. // @description For more imformation or copyright problems,please email me at [email protected]. // @include /^https?://*/ // @exclude http://pan.baidu.com/* // @exclude http://play.baidu.com/* // @exclude http://www.baidu.com/* // @exclude /^https?://www\.google\./ // @exclude /^https?://\.bing\./ // @exclude http://annotatorjs.org/ // @encoding utf-8 // @license MIT license // @run-at document-end // @copyright 2014,7,4 __By Wang Hsin-che // ==/UserScript== /* ** Annotator v1.2.7 ** https://github.com/okfn/annotator/ ** ** Copyright 2012 Aron Carroll, Rufus Pollock, and Nick Stenning. ** Dual licensed under the MIT and GPLv3 licenses. ** https://github.com/okfn/annotator/blob/master/LICENSE ** ** Built at: 2013-06-27 21:49:35Z */ ((function () { var a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F = [ ].slice, G = { }.hasOwnProperty, H = function (a, b) { function d() { this.constructor = a } for (var c in b) G.call(b, c) && (a[c] = b[c]); return d.prototype = b.prototype, a.prototype = new d, a.__super__ = b.prototype, a }, I = function (a, b) { return function () { return a.apply(b, arguments) } }, J = [ ].indexOf || function (a) { for (var b = 0, c = this.length; b < c; b++) if (b in this && this[b] === a) return b; return - 1 }; r = function (b) { var c; return c = this.map(function () { var c, d, e, f; e = '', c = this; while ((c != null ? c.nodeType : void 0) === Node.ELEMENT_NODE && c !== b) f = c.tagName.replace(':', '\:'), d = a(c.parentNode) .children(f) .index(c) + 1, d = '[' + d + ']', e = '/' + c.tagName.toLowerCase() + d + e, c = c.parentNode; return e }), c.get() }, s = function (a) { var b, c, d, e; return b = function (a) { var b, c; return b = n(a), c = o(a), '' + b + '[' + c + ']' }, e = a, c = function (a) { var c; c = ''; while (a !== e) { if (a == null) throw new Error('Called getPathTo on a node which was not a descendant of @rootNode. ' + e); c = b(a) + '/' + c, a = a.parentNode } return c = '/' + c, c = c.replace(/\/$/, ''), c }, d = this.map(function () { var a; return a = c(this), a }), d.get() }, j = function (a, b, c) { var d, e, f, g, h, i; if (!a.hasChildNodes()) throw new Error('XPath error: node has no children!'); e = a.childNodes, f = 0; for (h = 0, i = e.length; h < i; h++) { d = e[h], g = n(d); if (g === b) { f += 1; if (f === c) return d } } throw new Error('XPath error: wanted child not found.') }, n = function (a) { var b; b = a.nodeName.toLowerCase(); switch (b) { case '#text': return 'text()'; case '#comment': return 'comment()'; case '#cdata-section': return 'cdata-section()'; default: return b } }, o = function (a) { var b, c; b = 0, c = a; while (c) c.nodeName === a.nodeName && b++, c = c.previousSibling; return b }, p = null, typeof Gettext != 'undefined' && Gettext !== null ? (u = new Gettext({ domain: 'annotator' }), p = function (a) { return u.gettext(a) }) : p = function (a) { return a }, E = function (a) { return p(a) }, (typeof jQuery != 'undefined' && jQuery !== null ? (z = jQuery.fn) != null ? z.jquery : void 0 : void 0) || console.error(E('Annotator requires jQuery: have you included lib/vendor/jquery.js?')), JSON && JSON.parse && JSON.stringify || console.error(E('Annotator requires a JSON implementation: have you included lib/vendor/json2.js?')), a = jQuery, f = { }, f.flatten = function (b) { var c; return c = function (b) { var d, e, f, g; e = [ ]; for (f = 0, g = b.length; f < g; f++) d = b[f], e = e.concat(d && a.isArray(d) ? c(d) : d); return e }, c(b) }, f.getTextNodes = function (a) { var b; return b = function (a) { var c; if (a && a.nodeType !== Node.TEXT_NODE) { c = [ ]; if (a.nodeType !== Node.COMMENT_NODE) { a = a.lastChild; while (a) c.push(b(a)), a = a.previousSibling } return c.reverse() } return a }, a.map(function () { return f.flatten(b(this)) }) }, f.xpathFromNode = function (a, b) { var c, d; try { d = r.call(a, b) } catch (e) { c = e, console.log('jQuery-based XPath construction failed! Falling back to manual.'), d = s.call(a, b) } return d }, f.nodeFromXPath = function (a, b) { var c, d, e, f, g, h, i, k; g = a.substring(1) .split('/'), e = b; for (h = 0, i = g.length; h < i; h++) f = g[h], k = f.split('['), d = k[0], c = k[1], c = c != null ? parseInt((c != null ? c.split(']') : void 0) [0]) : 1, e = j(e, d.toLowerCase(), c); return e }, f.escape = function (a) { return a.replace(/&(?!\w+;)/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') }, f.uuid = function () { var a; return a = 0, function () { return a++ } }(), f.getGlobal = function () { return function () { return this }() }, f.maxZIndex = function (b) { var c, d; return c = function () { var c, e, f; f = [ ]; for (c = 0, e = b.length; c < e; c++) d = b[c], a(d) .css('position') === 'static' ? f.push( - 1) : f.push(parseInt(a(d) .css('z-index'), 10) || - 1); return f }(), Math.max.apply(Math, c) }, f.mousePosition = function (b, c) { var d; return d = a(c) .position(), { top: b.pageY - d.top, left: b.pageX - d.left } }, f.preventEventDefault = function (a) { return a != null ? typeof a.preventDefault == 'function' ? a.preventDefault() : void 0 : void 0 }, l = [ 'log', 'debug', 'info', 'warn', 'exception', 'assert', 'dir', 'dirxml', 'trace', 'group', 'groupEnd', 'groupCollapsed', 'time', 'timeEnd', 'profile', 'profileEnd', 'count', 'clear', 'table', 'error', 'notifyFirebug', 'firebug', 'userObjects' ]; if (typeof console != 'undefined' && console !== null) { console.group == null && (console.group = function (a) { return console.log('GROUP: ', a) }), console.groupCollapsed == null && (console.groupCollapsed = console.group); for (v = 0, x = l.length; v < x; v++) k = l[v], console[k] == null && (console[k] = function () { return console.log(E('Not implemented:') + (' console.' + name)) }) } else { this.console = { }; for (w = 0, y = l.length; w < y; w++) k = l[w], this.console[k] = function () { }; this.console.error = function () { var a; return a = 1 <= arguments.length ? F.call(arguments, 0) : [ ], alert('ERROR: ' + a.join(', ')) }, this.console.warn = function () { var a; return a = 1 <= arguments.length ? F.call(arguments, 0) : [ ], alert('WARNING: ' + a.join(', ')) } } c = function () { function b(b, c) { this.options = a.extend(!0, { }, this.options, c), this.element = a(b), this.on = this.subscribe, this.addEvents() } return b.prototype.events = { }, b.prototype.options = { }, b.prototype.element = null, b.prototype.addEvents = function () { var a, b, c, d, e, f, g, h; f = this.events, h = [ ]; for (c in f) b = f[c], g = c.split(' '), d = 2 <= g.length ? F.call(g, 0, e = g.length - 1) : (e = 0, [ ]), a = g[e++], h.push(this.addEvent(d.join(' '), a, b)); return h }, b.prototype.addEvent = function (b, c, d) { var e, f, g = this; return e = function () { return g[d].apply(g, arguments) }, f = typeof b == 'string' && b.replace(/\s+/g, '') === '', f && (b = this.element), typeof b == 'string' ? this.element.delegate(b, c, e) : this.isCustomEvent(c) ? this.subscribe(c, e) : a(b) .bind(c, e), this }, b.prototype.isCustomEvent = function (c) { return c = c.split('.') [0], a.inArray(c, b.natives) === - 1 }, b.prototype.publish = function () { return this.element.triggerHandler.apply(this.element, arguments), this }, b.prototype.subscribe = function (b, c) { var d; return d = function () { return c.apply(this, [ ].slice.call(arguments, 1)) }, d.guid = c.guid = a.guid += 1, this.element.bind(b, d), this }, b.prototype.unsubscribe = function () { return this.element.unbind.apply(this.element, arguments), this }, b }(), c.natives = function () { var a, b, c; return b = function () { var b, d; b = jQuery.event.special, d = [ ]; for (a in b) { if (!G.call(b, a)) continue; c = b[a], d.push(a) } return d }(), '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]+/) .concat(b) }(), e = { }, e.sniff = function (a) { return a.commonAncestorContainer != null ? new e.BrowserRange(a) : typeof a.start == 'string' ? new e.SerializedRange(a) : a.start && typeof a.start == 'object' ? new e.NormalizedRange(a) : (console.error(E('Could not sniff range type')), !1) }, e.nodeFromXPath = function (b, c) { var d, e, g, h, i; return c == null && (c = document), e = function (a, b) { var d; b == null && (b = null); try { return document.evaluate('.' + a, c, b, XPathResult.FIRST_ORDERED_NODE_TYPE, null) .singleNodeValue } catch (e) { return d = e, console.log('XPath evaluation failed.'), console.log('Trying fallback...'), f.nodeFromXPath(a, c) } }, a.isXMLDoc(document.documentElement) ? (d = document.createNSResolver(document.ownerDocument === null ? document.documentElement : document.ownerDocument.documentElement), h = e(b, d), h || (b = function () { var a, c, d, e; d = b.split('/'), e = [ ]; for (a = 0, c = d.length; a < c; a++) i = d[a], i && i.indexOf(':') === - 1 ? e.push(i.replace(/^([a-z]+)/, 'xhtml:$1')) : e.push(i); return e }() .join('/'), g = document.lookupNamespaceURI(null), d = function (a) { return a === 'xhtml' ? g : document.documentElement.getAttribute('xmlns:' + a) }, h = e(b, d)), h) : e(b) }, e.RangeError = function (a) { function b(a, c, d) { this.type = a, this.message = c, this.parent = d != null ? d : null, b.__super__.constructor.call(this, this.message) } return H(b, a), b }(Error), e.BrowserRange = function () { function a(a) { this.commonAncestorContainer = a.commonAncestorContainer, this.startContainer = a.startContainer, this.startOffset = a.startOffset, this.endContainer = a.endContainer, this.endOffset = a.endOffset } return a.prototype.normalize = function (a) { var b, c, d, f, g, h, i, j, k; if (this.tainted) return console.error(E('You may only call normalize() once on a BrowserRange!')), !1; this.tainted = !0, h = { }, d = { }, k = [ 'start', 'end' ]; for (i = 0, j = k.length; i < j; i++) { g = k[i], c = this[g + 'Container'], f = this[g + 'Offset']; if (c.nodeType === Node.ELEMENT_NODE) { b = c.childNodes[f], c = b || c.childNodes[f - 1], c.nodeType === Node.ELEMENT_NODE && !c.firstChild && (b = null, c = c.previousSibling); while (c.nodeType !== Node.TEXT_NODE) c = c.firstChild; f = b ? 0 : c.nodeValue.length } h[g] = c, h[g + 'Offset'] = f } d.start = h.startOffset > 0 ? h.start.splitText(h.startOffset) : h.start, h.start === h.end ? (h.endOffset - h.startOffset < d.start.nodeValue.length && d.start.splitText(h.endOffset - h.startOffset), d.end = d.start) : (h.endOffset < h.end.nodeValue.length && h.end.splitText(h.endOffset), d.end = h.end), d.commonAncestor = this.commonAncestorContainer; while (d.commonAncestor.nodeType !== Node.ELEMENT_NODE) d.commonAncestor = d.commonAncestor.parentNode; return new e.NormalizedRange(d) }, a.prototype.serialize = function (a, b) { return this.normalize(a) .serialize(a, b) }, a }(), e.NormalizedRange = function () { function b(a) { this.commonAncestor = a.commonAncestor, this.start = a.start, this.end = a.end } return b.prototype.normalize = function (a) { return this }, b.prototype.limit = function (b) { var c, d, e, f, g, h; c = a.grep(this.textNodes(), function (c) { return c.parentNode === b || a.contains(b, c.parentNode) }); if (!c.length) return null; this.start = c[0], this.end = c[c.length - 1], e = a(this.start) .parents(), h = a(this.end) .parents(); for (f = 0, g = h.length; f < g; f++) { d = h[f]; if (e.index(d) !== - 1) { this.commonAncestor = d; break } } return this }, b.prototype.serialize = function (b, c) { var d, g, h; return g = function (d, e) { var g, h, i, j, k, l, m, n; c ? j = a(d) .parents(':not(' + c + ')') .eq(0) : j = a(d) .parent(), l = f.xpathFromNode(j, b) [0], k = f.getTextNodes(j), h = k.slice(0, k.index(d)), i = 0; for (m = 0, n = h.length; m < n; m++) g = h[m], i += g.nodeValue.length; return e ? [ l, i + d.nodeValue.length ] : [ l, i ] }, h = g(this.start), d = g(this.end, !0), new e.SerializedRange({ start: h[0], end: d[0], startOffset: h[1], endOffset: d[1] }) }, b.prototype.text = function () { var a; return function () { var b, c, d, e; d = this.textNodes(), e = [ ]; for (b = 0, c = d.length; b < c; b++) a = d[b], e.push(a.nodeValue); return e }.call(this) .join('') }, b.prototype.textNodes = function () { var b, c, d, e; return d = f.getTextNodes(a(this.commonAncestor)), e = [ d.index(this.start), d.index(this.end) ], c = e[0], b = e[1], a.makeArray(d.slice(c, + b + 1 || 9000000000)) }, b.prototype.toRange = function () { var a; return a = document.createRange(), a.setStartBefore(this.start), a.setEndAfter(this.end), a }, b }(), e.SerializedRange = function () { function b(a) { this.start = a.start, this.startOffset = a.startOffset, this.end = a.end, this.endOffset = a.endOffset } return b.prototype.normalize = function (b) { var c, d, g, h, i, j, k, l, m, n, o, p, q; j = { }, p = [ 'start', 'end' ]; for (l = 0, n = p.length; l < n; l++) { i = p[l]; try { h = e.nodeFromXPath(this[i], b) } catch (r) { throw d = r, new e.RangeError(i, 'Error while finding ' + i + ' node: ' + this[i] + ': ' + d, d) } if (!h) throw new e.RangeError(i, 'Couldn\'t find ' + i + ' node: ' + this[i]); g = 0, q = f.getTextNodes(a(h)); for (m = 0, o = q.length; m < o; m++) { k = q[m]; if (g + k.nodeValue.length >= this[i + 'Offset']) { j[i + 'Container'] = k, j[i + 'Offset'] = this[i + 'Offset'] - g; break } g += k.nodeValue.length } if (j[i + 'Offset'] == null) throw new e.RangeError('' + i + 'offset', 'Couldn\'t find offset ' + this[i + 'Offset'] + ' in element ' + this[i]) } return c = document.compareDocumentPosition == null ? function (a, b) { return a.contains(b) } : function (a, b) { return a.compareDocumentPosition(b) & 16 }, a(j.startContainer) .parents() .each(function () { if (c(this, j.endContainer)) return j.commonAncestorContainer = this, !1 }), (new e.BrowserRange(j)) .normalize(b) }, b.prototype.serialize = function (a, b) { return this.normalize(a) .serialize(a, b) }, b.prototype.toObject = function () { return { start: this.start, startOffset: this.startOffset, end: this.end, endOffset: this.endOffset } }, b }(), t = this.Annotator, b = function (b) { function c(b, d) { this.onDeleteAnnotation = I(this.onDeleteAnnotation, this), this.onEditAnnotation = I(this.onEditAnnotation, this), this.onAdderClick = I(this.onAdderClick, this), this.onAdderMousedown = I(this.onAdderMousedown, this), this.onHighlightMouseover = I(this.onHighlightMouseover, this), this.checkForEndSelection = I(this.checkForEndSelection, this), this.checkForStartSelection = I(this.checkForStartSelection, this), this.clearViewerHideTimer = I(this.clearViewerHideTimer, this), this.startViewerHideTimer = I(this.startViewerHideTimer, this), this.showViewer = I(this.showViewer, this), this.onEditorSubmit = I(this.onEditorSubmit, this), this.onEditorHide = I(this.onEditorHide, this), this.showEditor = I(this.showEditor, this), c.__super__.constructor.apply(this, arguments), this.plugins = { }; if (!c.supported()) return this; this.options.readOnly || this._setupDocumentEvents(), this._setupWrapper() ._setupViewer() ._setupEditor(), this._setupDynamicStyle(), this.adder = a(this.html.adder) .appendTo(this.wrapper) .hide() } return H(c, b), c.prototype.events = { '.annotator-adder button click': 'onAdderClick', '.annotator-adder button mousedown': 'onAdderMousedown', '.annotator-hl mouseover': 'onHighlightMouseover', '.annotator-hl mouseout': 'startViewerHideTimer' }, c.prototype.html = { adder: '<div class="annotator-adder"><button>' + E('Annotate') + '</button></div>', wrapper: '<div class="annotator-wrapper"></div>' }, c.prototype.options = { readOnly: !1 }, c.prototype.plugins = { }, c.prototype.editor = null, c.prototype.viewer = null, c.prototype.selectedRanges = null, c.prototype.mouseIsDown = !1, c.prototype.ignoreMouseup = !1, c.prototype.viewerHideTimer = null, c.prototype._setupWrapper = function () { return this.wrapper = a(this.html.wrapper), this.element.find('script') .remove(), this.element.wrapInner(this.wrapper), this.wrapper = this.element.find('.annotator-wrapper'), this }, c.prototype._setupViewer = function () { var b = this; return this.viewer = new c.Viewer({ readOnly: this.options.readOnly }), this.viewer.hide() .on('edit', this.onEditAnnotation) .on('delete', this.onDeleteAnnotation) .addField({ load: function (c, d) { return d.text ? a(c) .html(f.escape(d.text)) : a(c) .html('<i>' + E('No Comment') + '</i>'), b.publish('annotationViewerTextField', [ c, d ]) } }) .element.appendTo(this.wrapper) .bind({ mouseover: this.clearViewerHideTimer, mouseout: this.startViewerHideTimer }), this }, c.prototype._setupEditor = function () { return this.editor = new c.Editor, this.editor.hide() .on('hide', this.onEditorHide) .on('save', this.onEditorSubmit) .addField({ type: 'textarea', label: E('Comments') + '鈥�', load: function (b, c) { return a(b) .find('textarea') .val(c.text || '') }, submit: function (b, c) { return c.text = a(b) .find('textarea') .val() } }), this.editor.element.appendTo(this.wrapper), this }, c.prototype._setupDocumentEvents = function () { return a(document) .bind({ mouseup: this.checkForEndSelection, mousedown: this.checkForStartSelection }), this }, c.prototype._setupDynamicStyle = function () { var b, c, d, e; return d = a('#annotator-dynamic-style'), d.length || (d = a('<style id="annotator-dynamic-style"></style>') .appendTo(document.head)), c = '*' + function () { var a, b, c, d; c = [ 'adder', 'outer', 'notice', 'filter' ], d = [ ]; for (a = 0, b = c.length; a < b; a++) e = c[a], d.push(':not(.annotator-' + e + ')'); return d }() .join(''), b = f.maxZIndex(a(document.body) .find(c)), b = Math.max(b, 1000), d.text(['.annotator-adder, .annotator-outer, .annotator-notice {', ' z-index: ' + (b + 20) + ';', '}', '.annotator-filter {', ' z-index: ' + (b + 10) + ';', '}'].join('\n')), this }, c.prototype.getSelectedRanges = function () { var b, c, d, g, h, i, j, k, l; j = f.getGlobal() .getSelection(), h = [ ], i = [ ], j.isCollapsed || (h = function () { var a, f, h; h = [ ]; for (c = a = 0, f = j.rangeCount; 0 <= f ? a < f : a > f; c = 0 <= f ? ++a : --a) g = j.getRangeAt(c), b = new e.BrowserRange(g), d = b.normalize() .limit(this.wrapper[0]), d === null && i.push(g), h.push(d); return h }.call(this), j.removeAllRanges()); for (k = 0, l = i.length; k < l; k++) g = i[k], j.addRange(g); return a.grep(h, function (a) { return a && j.addRange(a.toRange()), a }) }, c.prototype.createAnnotation = function () { var a; return a = { }, this.publish('beforeAnnotationCreated', [ a ]), a }, c.prototype.setupAnnotation = function (b) { var c, d, f, g, h, i, j, k, l, m; h = this.wrapper[0], b.ranges || (b.ranges = this.selectedRanges), f = [ ], m = b.ranges; for (i = 0, k = m.length; i < k; i++) { g = m[i]; try { f.push(e.sniff(g) .normalize(h)) } catch (n) { c = n; if (!(c instanceof e.RangeError)) throw c; this.publish('rangeNormalizeFail', [ b, g, c ]) } } b.quote = [ ], b.ranges = [ ], b.highlights = [ ]; for (j = 0, l = f.length; j < l; j++) d = f[j], b.quote.push(a.trim(d.text())), b.ranges.push(d.serialize(this.wrapper[0], '.annotator-hl')), a.merge(b.highlights, this.highlightRange(d)); return b.quote = b.quote.join(' / '), a(b.highlights) .data('annotation', b), b }, c.prototype.updateAnnotation = function (a) { return this.publish('beforeAnnotationUpdated', [ a ]), this.publish('annotationUpdated', [ a ]), a }, c.prototype.deleteAnnotation = function (b) { var c, d, e, f, g; if (b.highlights != null) { g = b.highlights; for (e = 0, f = g.length; e < f; e++) { d = g[e]; if (d.parentNode == null) continue; c = d.childNodes[0], a(d) .replaceWith(d.childNodes) } } return this.publish('annotationDeleted', [ b ]), b }, c.prototype.loadAnnotations = function (a) { var b, c, d = this; return a == null && (a = [ ]), c = function (a) { var e, f, g, h; a == null && (a = [ ]), f = a.splice(0, 10); for (g = 0, h = f.length; g < h; g++) e = f[g], d.setupAnnotation(e); return a.length > 0 ? setTimeout(function () { return c(a) }, 10) : d.publish('annotationsLoaded', [ b ]) }, b = a.slice(), a.length && c(a), this }, c.prototype.dumpAnnotations = function () { return this.plugins.Store ? this.plugins.Store.dumpAnnotations() : (console.warn(E('Can\'t dump annotations without Store plugin.')), !1) }, c.prototype.highlightRange = function (b, c) { var d, e, f, g, h, i, j; c == null && (c = 'annotator-hl'), f = /^\s*$/, d = a('<span class=\'' + c + '\'></span>'), i = b.textNodes(), j = [ ]; for (g = 0, h = i.length; g < h; g++) e = i[g], f.test(e.nodeValue) || j.push(a(e) .wrapAll(d) .parent() .show() [0]); return j }, c.prototype.highlightRanges = function (b, c) { var d, e, f, g; c == null && (c = 'annotator-hl'), d = [ ]; for (f = 0, g = b.length; f < g; f++) e = b[f], a.merge(d, this.highlightRange(e, c)); return d }, c.prototype.addPlugin = function (a, b) { var d, e; return this.plugins[a] ? console.error(E('You cannot have more than one instance of any plugin.')) : (d = c.Plugin[a], typeof d == 'function' ? (this.plugins[a] = new d(this.element[0], b), this.plugins[a].annotator = this, typeof (e = this.plugins[a]) .pluginInit == 'function' && e.pluginInit()) : console.error(E('Could not load ') + a + E(' plugin. Have you included the appropriate <script> tag?'))), this }, c.prototype.showEditor = function (a, b) { return this.editor.element.css(b), this.editor.load(a), this.publish('annotationEditorShown', [ this.editor, a ]), this }, c.prototype.onEditorHide = function () { return this.publish('annotationEditorHidden', [ this.editor ]), this.ignoreMouseup = !1 }, c.prototype.onEditorSubmit = function (a) { return this.publish('annotationEditorSubmit', [ this.editor, a ]) }, c.prototype.showViewer = function (a, b) { return this.viewer.element.css(b), this.viewer.load(a), this.publish('annotationViewerShown', [ this.viewer, a ]) }, c.prototype.startViewerHideTimer = function () { if (!this.viewerHideTimer) return this.viewerHideTimer = setTimeout(this.viewer.hide, 250) }, c.prototype.clearViewerHideTimer = function () { return clearTimeout(this.viewerHideTimer), this.viewerHideTimer = !1 }, c.prototype.checkForStartSelection = function (a) { return (!a || !this.isAnnotator(a.target)) && this.startViewerHideTimer(), this.mouseIsDown = !0 }, c.prototype.checkForEndSelection = function (b) { var c, d, e, g, h; this.mouseIsDown = !1; if (this.ignoreMouseup) return ; this.selectedRanges = this.getSelectedRanges(), h = this.selectedRanges; for (e = 0, g = h.length; e < g; e++) { d = h[e], c = d.commonAncestor, a(c) .hasClass('annotator-hl') && (c = a(c) .parents('[class!=annotator-hl]') [0]); if (this.isAnnotator(c)) return } return b && this.selectedRanges.length ? this.adder.css(f.mousePosition(b, this.wrapper[0])) .show() : this.adder.hide() }, c.prototype.isAnnotator = function (b) { return !!a(b) .parents() .andSelf() .filter('[class^=annotator-]') .not(this.wrapper) .length }, c.prototype.onHighlightMouseover = function (b) { var c; return this.clearViewerHideTimer(), this.mouseIsDown || this.viewer.isShown() ? !1 : (c = a(b.target) .parents('.annotator-hl') .andSelf() .map(function () { return a(this) .data('annotation') }), this.showViewer(a.makeArray(c), f.mousePosition(b, this.wrapper[0]))) }, c.prototype.onAdderMousedown = function (a) { return a != null && a.preventDefault(), this.ignoreMouseup = !0 }, c.prototype.onAdderClick = function (b) { var c, d, e, f, g, h = this; return b != null && b.preventDefault(), f = this.adder.position(), this.adder.hide(), c = this.setupAnnotation(this.createAnnotation()), a(c.highlights) .addClass('annotator-hl-temporary'), g = function () { return e(), a(c.highlights) .removeClass('annotator-hl-temporary'), h.publish('annotationCreated', [ c ]) }, d = function () { return e(), h.deleteAnnotation(c) }, e = function () { return h.unsubscribe('annotationEditorHidden', d), h.unsubscribe('annotationEditorSubmit', g) }, this.subscribe('annotationEditorHidden', d), this.subscribe('annotationEditorSubmit', g), this.showEditor(c, f) }, c.prototype.onEditAnnotation = function (a) { var b, c, d, e = this; return c = this.viewer.element.position(), d = function () { return b(), e.updateAnnotation(a) }, b = function () { return e.unsubscribe('annotationEditorHidden', b), e.unsubscribe('annotationEditorSubmit', d) }, this.subscribe('annotationEditorHidden', b), this.subscribe('annotationEditorSubmit', d), this.viewer.hide(), this.showEditor(a, c) }, c.prototype.onDeleteAnnotation = function (a) { return this.viewer.hide(), this.deleteAnnotation(a) }, c }(c), b.Plugin = function (a) { function b(a, c) { b.__super__.constructor.apply(this, arguments) } return H(b, a), b.prototype.pluginInit = function () { }, b }(c), m = f.getGlobal(), ((A = m.document) != null ? A.evaluate : void 0) == null && a.getScript('http://assets.annotateit.org/vendor/xpath.min.js'), m.getSelection == null && a.getScript('http://assets.annotateit.org/vendor/ierange.min.js'), m.JSON == null && a.getScript('http://assets.annotateit.org/vendor/json2.min.js'), m.Node == null && (m.Node = { ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, TEXT_NODE: 3, CDATA_SECTION_NODE: 4, ENTITY_REFERENCE_NODE: 5, ENTITY_NODE: 6, PROCESSING_INSTRUCTION_NODE: 7, COMMENT_NODE: 8, DOCUMENT_NODE: 9, DOCUMENT_TYPE_NODE: 10, DOCUMENT_FRAGMENT_NODE: 11, NOTATION_NODE: 12 }), b.$ = a, b.Delegator = c, b.Range = e, b.Util = f, b._t = E, b.supported = function () { return function () { return !!this.getSelection }() }, b.noConflict = function () { return f.getGlobal() .Annotator = t, this }, a.fn.annotator = function (c) { var d; return d = Array.prototype.slice.call(arguments, 1), this.each(function () { var e; return e = a.data(this, 'annotator'), e ? c && e[c].apply(e, d) : (e = new b(this, c), a.data(this, 'annotator', e)) }) }, this.Annotator = b, b.Widget = function (c) { function d(c, e) { d.__super__.constructor.apply(this, arguments), this.classes = a.extend({ }, b.Widget.prototype.classes, this.classes) } return H(d, c), d.prototype.classes = { hide: 'annotator-hide', invert: { x: 'annotator-invert-x', y: 'annotator-invert-y' } }, d.prototype.checkOrientation = function () { var c, d, e, f, g; return this.resetOrientation(), g = a(b.Util.getGlobal()), f = this.element.children(':first'), d = f.offset(), e = { top: g.scrollTop(), right: g.width() + g.scrollLeft() }, c = { top: d.top, right: d.left + f.width() }, c.top - e.top < 0 && this.invertY(), c.right - e.right > 0 && this.invertX(), this }, d.prototype.resetOrientation = function () { return this.element.removeClass(this.classes.invert.x) .removeClass(this.classes.invert.y), this }, d.prototype.invertX = function () { return this.element.addClass(this.classes.invert.x), this }, d.prototype.invertY = function () { return this.element.addClass(this.classes.invert.y), this }, d.prototype.isInvertedY = function () { return this.element.hasClass(this.classes.invert.y) }, d.prototype.isInvertedX = function () { return this.element.hasClass(this.classes.invert.x) }, d }(c), b.Editor = function (c) { function d(b) { this.onCancelButtonMouseover = I(this.onCancelButtonMouseover, this), this.processKeypress = I(this.processKeypress, this), this.submit = I(this.submit, this), this.load = I(this.load, this), this.hide = I(this.hide, this), this.show = I(this.show, this), d.__super__.constructor.call(this, a(this.html) [0], b), this.fields = [ ], this.annotation = { } } return H(d, c), d.prototype.events = { 'form submit': 'submit', '.annotator-save click': 'submit', '.annotator-cancel click': 'hide', '.annotator-cancel mouseover': 'onCancelButtonMouseover', 'textarea keydown': 'processKeypress' }, d.prototype.classes = { hide: 'annotator-hide', focus: 'annotator-focus' }, d.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">' + E('Cancel') + '</a>\n<a href="#save" class="annotator-save annotator-focus">' + E('Save') + '</a>\n </div>\n </form>\n</div>', d.prototype.options = { }, d.prototype.show = function (a) { return b.Util.preventEventDefault(a), this.element.removeClass(this.classes.hide), this.element.find('.annotator-save') .addClass(this.classes.focus), this.checkOrientation(), this.element.find(':input:first') .focus(), this.setupDraggables(), this.publish('show') }, d.prototype.hide = function (a) { return b.Util.preventEventDefault(a), this.element.addClass(this.classes.hide), this.publish('hide') }, d.prototype.load = function (a) { var b, c, d, e; this.annotation = a, this.publish('load', [ this.annotation ]), e = this.fields; for (c = 0, d = e.length; c < d; c++) b = e[c], b.load(b.element, this.annotation); return this.show() }, d.prototype.submit = function (a) { var c, d, e, f; b.Util.preventEventDefault(a), f = this.fields; for (d = 0, e = f.length; d < e; d++) c = f[d], c.submit(c.element, this.annotation); return this.publish('save', [ this.annotation ]), this.hide() }, d.prototype.addField = function (c) { var d, e, f; e = a.extend({ id: 'annotator-field-' + b.Util.uuid(), type: 'input', label: '', load: function () { }, submit: function () { } }, c), f = null, d = a('<li class="annotator-item" />'), e.element = d[0]; switch (e.type) { case 'textarea': f = a('<textarea />'); break; case 'input': case 'checkbox': f = a('<input />'); break; case 'select': f = a('<select />') } return d.append(f), f.attr({ id: e.id, placeholder: e.label }), e.type === 'checkbox' && (f[0].type = 'checkbox', d.addClass('annotator-checkbox'), d.append(a('<label />', { 'for': e.id, html: e.label }))), this.element.find('ul:first') .append(d), this.fields.push(e), e.element }, d.prototype.checkOrientation = function () { var a, b; return d.__super__.checkOrientation.apply(this, arguments), b = this.element.find('ul'), a = this.element.find('.annotator-controls'), this.element.hasClass(this.classes.invert.y) ? a.insertBefore(b) : a.is(':first-child') && a.insertAfter(b), this }, d.prototype.processKeypress = function (a) { if (a.keyCode === 27) return this.hide(); if (a.keyCode === 13 && !a.shiftKey) return this.submit() }, d.prototype.onCancelButtonMouseover = function () { return this.element.find('.' + this.classes.focus) .removeClass(this.classes.focus) }, d.prototype.setupDraggables = function () { var b, c, d, e, f, g, h, i, j, k, l, m = this; return this.element.find('.annotator-resize') .remove(), this.element.hasClass(this.classes.invert.y) ? d = this.element.find('.annotator-item:last') : d = this.element.find('.annotator-item:first'), d && a('<span class="annotator-resize"></span>') .appendTo(d), f = null, b = this.classes, e = this.element, k = null, j = e.find('.annotator-resize'), c = e.find('.annotator-controls'), l = !1, g = function (b) { if (b.target === this) return f = { element: this, top: b.pageY, left: b.pageX }, k = e.find('textarea:first'), a(window) .bind({ 'mouseup.annotator-editor-resize': i, 'mousemove.annotator-editor-resize': h }), b.preventDefault() }, i = function () { return f = null, a(window) .unbind('.annotator-editor-resize') }, h = function (a) { var d, g, h, i, m; if (f && l === !1) return d = { top: a.pageY - f.top, left: a.pageX - f.left }, f.element === j[0] ? (i = k.outerHeight(), m = k.outerWidth(), g = e.hasClass(b.invert.x) ? - 1 : 1, h = e.hasClass(b.invert.y) ? 1 : - 1, k.height(i + d.top * h), k.width(m + d.left * g), k.outerHeight() !== i && (f.top = a.pageY), k.outerWidth() !== m && (f.left = a.pageX)) : f.element === c[0] && (e.css({ top: parseInt(e.css('top'), 10) + d.top, left: parseInt(e.css('left'), 10) + d.left }), f.top = a.pageY, f.left = a.pageX), l = !0, setTimeout(function () { return l = !1 }, 1000 / 60) }, j.bind('mousedown', g), c.bind('mousedown', g) }, d }(b.Widget), b.Viewer = function (c) { function e(b) { this.onDeleteClick = I(this.onDeleteClick, this), this.onEditClick = I(this.onEditClick, this), this.load = I(this.load, this), this.hide = I(this.hide, this), this.show = I(this.show, this), e.__super__.constructor.call(this, a(this.html.element) [0], b), this.item = a(this.html.item) [0], this.fields = [ ], this.annotations = [ ] } return H(e, c), e.prototype.events = { '.annotator-edit click': 'onEditClick', '.annotator-delete click': 'onDeleteClick' }, e.prototype.classes = { hide: 'annotator-hide', showControls: 'annotator-visible' }, e.prototype.html = { element: '<div class="annotator-outer annotator-viewer">\n <ul class="annotator-widget annotator-listing"></ul>\n</div>', item: '<li class="annotator-annotation annotator-item">\n <span class="annotator-controls">\n <a href="#" title="View as webpage" class="annotator-link">View as webpage</a>\n <button title="Edit" class="annotator-edit">Edit</button>\n <button title="Delete" class="annotator-delete">Delete</button>\n </span>\n</li>' }, e.prototype.options = { readOnly: !1 }, e.prototype.show = function (a) { var c, d = this; return b.Util.preventEventDefault(a), c = this.element.find('.annotator-controls') .addClass(this.classes.showControls), setTimeout(function () { return c.removeClass(d.classes.showControls) }, 500), this.element.removeClass(this.classes.hide), this.checkOrientation() .publish('show') }, e.prototype.isShown = function () { return !this.element.hasClass(this.classes.hide) }, e.prototype.hide = function (a) { return b.Util.preventEventDefault(a), this.element.addClass(this.classes.hide), this.publish('hide') }, e.prototype.load = function (b) { var c, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t; this.annotations = b || [], n = this.element.find('ul:first') .empty(), s = this.annotations; for (o = 0, q = s.length; o < q; o++) { c = s[o], k = a(this.item) .clone() .appendTo(n) .data('annotation', c), f = k.find('.annotator-controls'), l = f.find('.annotator-link'), h = f.find('.annotator-edit'), g = f.find('.annotator-delete'), m = (new d(c.links || [])) .get('alternate', { type: 'text/html' }), m.length === 0 || m[0].href == null ? l.remove() : l.attr('href', m[0].href), this.options.readOnly ? (h.remove(), g.remove()) : e = { showEdit: function () { return h.removeAttr('disabled') }, hideEdit: function () { return h.attr('disabled', 'disabled') }, showDelete: function () { return g.removeAttr('disabled') }, hideDelete: function () { return g.attr('disabled', 'disabled') } }, t = this.fields; for (p = 0, r = t.length; p < r; p++) j = t[p], i = a(j.element) .clone() .appendTo(k) [0], j.load(i, c, e) } return this.publish('load', [ this.annotations ]), this.show() }, e.prototype.addField = function (b) { var c; return c = a.extend({ load: function () { } }, b), c.element = a('<div />') [0], this.fields.push(c), c.element, this }, e.prototype.onEditClick = function (a) { return this.onButtonClick(a, 'edit') }, e.prototype.onDeleteClick = function (a) { return this.onButtonClick(a, 'delete') }, e.prototype.onButtonClick = function (b, c) { var d; return d = a(b.target) .parents('.annotator-annotation'), this.publish(c, [ d.data('annotation') ]) }, e }(b.Widget), d = function () { function b(a) { this.data = a } return b.prototype.get = function (b, c) { var d, e, f, g, h, i, j, k, l; c == null && (c = { }), c = a.extend({ }, c, { rel: b }), f = function () { var a; a = [ ]; for (e in c) { if (!G.call(c, e)) continue; h = c[e], a.push(e) } return a }(), k = this.data, l = [ ]; for (i = 0, j = k.length; i < j; i++) { d = k[i], g = f.reduce(function (a, b) { return a && d[b] === c[b] }, !0); if (!g) continue; l.push(d) } return l }, b }(), b = b || { }, b.Notification = function (c) { function d(b) { this.hide = I(this.hide, this), this.show = I(this.show, this), d.__super__.constructor.call(this, a(this.options.html) .appendTo(document.body) [0], b) } return H(d, c), d.prototype.events = { click: 'hide' }, d.prototype.options = { html: '<div class=\'annotator-notice\'></div>', classes: { show: 'annotator-notice-show', info: 'annotator-notice-info', success: 'annotator-notice-success', error: 'annotator-notice-error' } }, d.prototype.show = function (c, d) { return d == null && (d = b.Notification.INFO), a(this.element) .addClass(this.options.classes.show) .addClass(this.options.classes[d]) .html(f.escape(c || '')), setTimeout(this.hide, 5000), this }, d.prototype.hide = function () { return a(this.element) .removeClass(this.options.classes.show), this }, d }(c), b.Notification.INFO = 'show', b.Notification.SUCCESS = 'success', b.Notification.ERROR = 'error', a(function () { var a; return a = new b.Notification, b.showNotification = a.show, b.hideNotification = a.hide }), b.Plugin.Unsupported = function (c) { function d() { return B = d.__super__.constructor.apply(this, arguments), B } return H(d, c), d.prototype.options = { message: b._t('Sorry your current browser does not support the Annotator') }, d.prototype.pluginInit = function () { var c = this; if (!b.supported()) return a(function () { b.showNotification(c.options.message); if (window.XMLHttpRequest === void 0 && ActiveXObject !== void 0) return a('html') .addClass('ie6') }) }, d }(b.Plugin), i = function (a) { var b, c, d, e, f, g; return e = '([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})))?)?)?)?', b = a.match(new RegExp(e)), d = 0, c = new Date(b[1], 0, 1), b[3] && c.setMonth(b[3] - 1), b[5] && c.setDate(b[5]), b[7] && c.setHours(b[7]), b[8] && c.setMinutes(b[8]), b[10] && c.setSeconds(b[10]), b[12] && c.setMilliseconds(Number('0.' + b[12]) * 1000), b[14] && (d = Number(b[16]) * 60 + Number(b[17]), d *= (g = b[15] === '-') != null ? g : { 1: - 1 }), d -= c.getTimezoneOffset(), f = Number(c) + d * 60 * 1000, c.setTime(Number(f)), c }, g = function (a) { var b, c, d, e, f, g, h, i, j, k, l, m, n; if (typeof atob != 'undefined' && atob !== null) return atob(a); c = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', j = 0, b = 0, e = '', n = [ ]; if (!a) return a; a += ''; while (j < a.length) f = c.indexOf(a.charAt(j++)), g = c.indexOf(a.charAt(j++)), h = c.indexOf(a.charAt(j++)), i = c.indexOf(a.charAt(j++)), d = f << 18 | g << 12 | h << 6 | i, k = d >> 16 & 255, l = d >> 8 & 255, m = d & 255, h === 64 ? n[b++] = String.fromCharCode(k) : i === 64 ? n[b++] = String.fromCharCode(k, l) : n[b++] = String.fromCharCode(k, l, m); return n.join('') }, h = function (a) { var b, c, d, e; c = a.length % 4; if (c !== 0) for (b = d = 0, e = 4 - c; 0 <= e ? d < e : d > e; b = 0 <= e ? ++d : --d) a += '='; return a = a.replace(/-/g, '+'), a = a.replace(/_/g, '/'), g(a) }, q = function (a) { var b, c, d, e; return e = a.split('.'), b = e[0], c = e[1], d = e[2], JSON.parse(h(c)) }, b.Plugin.Auth = function (c) { function d(a, b) { d.__super__.constructor.apply(this, arguments), this.waitingForToken = [ ], this.options.token ? this.setToken(this.options.token) : this.requestToken() } return H(d, c), d.prototype.options = { token: null, tokenUrl: '/auth/token', autoFetch: !0 }, d.prototype.requestToken = function () { var c = this; return this.requestInProgress = !0, a.ajax({ url: this.options.tokenUrl, dataType: 'text', xhrFields: { withCredentials: !0 } }) .done(function (a, b, d) { return c.setToken(a) }) .fail(function (a, c, d) { var e; return e = b._t('Couldn\'t get auth token:'), console.error('' + e + ' ' + d, a), b.showNotification('' + e + ' ' + a.responseText, b.Notification.ERROR) }) .always(function () { return c.requestInProgress = !1 }) }, d.prototype.setToken = function (a) { var c, d = this; this.token = a, this._unsafeToken = q(a); if (this.haveValidToken()) { this.options.autoFetch && (this.refreshTimeout = setTimeout(function () { return d.requestToken() }, (this.timeToExpiry() - 2) * 1000)), this.updateHeaders(), c = [ ]; while (this.waitingForToken.length > 0) c.push(this.waitingForToken.pop() (this._unsafeToken)); return c } console.warn(b._t('Didn\'t get a valid token.')); if (this.options.autoFetch) return console.warn(b._t('Getting a new token in 10s.')), setTimeout(function () { return d.requestToken() }, 10000) }, d.prototype.haveValidToken = function () { var a; return a = this._unsafeToken && this._unsafeToken.issuedAt && this._unsafeToken.ttl && this._unsafeToken.consumerKey, a && this.timeToExpiry() > 0 ? !0 : !1 }, d.prototype.timeToExpiry = function () { var a, b, c, d; return c = (new Date) .getTime() / 1000, b = i(this._unsafeToken.issuedAt) .getTime() / 1000, a = b + this._unsafeToken.ttl, d = a - c, d > 0 ? d : 0 }, d.prototype.updateHeaders = function () { var b; return b = this.element.data('annotator:headers'), this.element.data('annotator:headers', a.extend(b, { 'x-annotator-auth-token': this.token })) }, d.prototype.withToken = function (a) { if (a == null) return ; if (this.haveValidToken()) return a(this._unsafeToken); this.waitingForToken.push(a); if (!this.requestInProgress) return this.requestToken() }, d }(b.Plugin), b.Plugin.Store = function (c) { function d(a, b) { this._onError = I(this._onError, this), this._onLoadAnnotationsFromSearch = I(this._onLoadAnnotationsFromSearch, this), this._onLoadAnnotations = I(this._onLoadAnnotations, this), this._getAnnotations = I(this._getAnnotations, this), d.__super__.constructor.apply(this, arguments), this.annotations = [ ] } return H(d, c), d.prototype.events = { annotationCreated: 'annotationCreated', annotationDeleted: 'annotationDeleted', annotationUpdated: 'annotationUpdated' }, d.prototype.options = { annotationData: { }, emulateHTTP: !1, loadFromSearch: !1, prefix: '/store', urls: { create: '/annotations', read: '/annotations/:id', update: '/annotations/:id', destroy: '/annotations/:id', search: '/search' } }, d.prototype.pluginInit = function () { if (!b.supported()) return ; return this.annotator.plugins.Auth ? this.annotator.plugins.Auth.withToken(this._getAnnotations) : this._getAnnotations() }, d.prototype._getAnnotations = function () { return this.options.loadFromSearch ? this.loadAnnotationsFromSearch(this.options.loadFromSearch) : this.loadAnnotations() }, d.prototype.annotationCreated = function (a) { var c = this; return J.call(this.annotations, a) < 0 ? (this.registerAnnotation(a), this._apiRequest('create', a, function (d) { return d.id == null && console.warn(b._t('Warning: No ID returned from server for annotation '), a), c.updateAnnotation(a, d) })) : this.updateAnnotation(a, { }) }, d.prototype.annotationUpdated = function (a) { var b = this; if (J.call(this.annotations, a) >= 0) return this._apiRequest('update', a, function (c) { return b.updateAnnotation(a, c) }) }, d.prototype.annotationDeleted = function (a) { var b = this; if (J.call(this.annotations, a) >= 0) return this._apiRequest('destroy', a, function () { return b.unregisterAnnotation(a) }) }, d.prototype.registerAnnotation = function (a) { return this.annotations.push(a) }, d.prototype.unregisterAnnotation = function (a) { return this.annotations.splice(this.annotations.indexOf(a), 1) }, d.prototype.updateAnnotation = function (c, d) { return J.call(this.annotations, c) < 0 ? console.error(b._t('Trying to update unregistered annotation!')) : a.extend(c, d), a(c.highlights) .data('annotation', c) }, d.prototype.loadAnnotations = function () { return this._apiRequest('read', null, this._onLoadAnnotations) }, d.prototype._onLoadAnnotations = function (a) { var b, c, d, e, f, g, h, i, j; a == null && (a = [ ]), d = { }, j = this.annotations; for (f = 0, h = j.length; f < h; f++) b = j[f], d[b.id] = b; e = [ ]; for (g = 0, i = a.length; g < i; g++) b = a[g], d[b.id] ? (c = d[b.id], this.updateAnnotation(c, b)) : e.push(b); return this.annotations = this.annotations.concat(e), this.annotator.loadAnnotations(e.slice()) }, d.prototype.loadAnnotationsFromSearch = function (a) { return this._apiRequest('search', a, this._onLoadAnnotationsFromSearch) }, d.prototype._onLoadAnnotationsFromSearch = function (a) { return a == null && (a = { }), this._onLoadAnnotations(a.rows || []) }, d.prototype.dumpAnnotations = function () { var a, b, c, d, e; d = this.annotations, e = [ ]; for (b = 0, c = d.length; b < c; b++) a = d[b], e.push(JSON.parse(this._dataFor(a))); return e }, d.prototype._apiRequest = function (b, c, d) { var e, f, g, h; return e = c && c.id, h = this._urlFor(b, e), f = this._apiRequestOptions(b, c, d), g = a.ajax(h, f), g._id = e, g._action = b, g }, d.prototype._apiRequestOptions = function (b, c, d) { var e, f, g; return f = this._methodFor(b), g = { type: f, headers: this.element.data('annotator:headers'), dataType: 'json', success: d || function () { }, error: this._onError }, this.options.emulateHTTP && (f === 'PUT' || f === 'DELETE') && (g.headers = a.extend(g.headers, { 'X-HTTP-Method-Override': f }), g.type = 'POST'), b === 'search' ? (g = a.extend(g, { data: c }), g) : (e = c && this._dataFor(c), this.options.emulateJSON ? (g.data = { json: e }, this.options.emulateHTTP && (g.data._method = f), g) : (g = a.extend(g, { data: e, contentType: 'application/json; charset=utf-8' }), g)) }, d.prototype._urlFor = function (a, b) { var c; return c = this.options.prefix != null ? this.options.prefix : '', c += this.options.urls[a], c = c.replace(/\/:id/, b != null ? '/' + b : ''), c = c.replace(/:id/, b != null ? b : ''), c }, d.prototype._methodFor = function (a) { var b; return b = { create: 'POST', read: 'GET', update: 'PUT', destroy: 'DELETE', search: 'GET' }, b[a] }, d.prototype._dataFor = function (b) { var c, d; return d = b.highlights, delete b.highlights, a.extend(b, this.options.annotationData), c = JSON.stringify(b), d && (b.highlights = d), c }, d.prototype._onError = function (a) { var c, d; c = a._action, d = b._t('Sorry we could not ') + c + b._t(' this annotation'), a._action === 'search' ? d = b._t('Sorry we could not search the store for annotations') : a._action === 'read' && !a._id && (d = b._t('Sorry we could not ') + c + b._t(' the annotations from the store')); switch (a.status) { case 401: d = b._t('Sorry you are not allowed to ') + c + b._t(' this annotation'); break; case 404: d = b._t('Sorry we could not connect to the annotations store'); break; case 500: d = b._t('Sorry something went wrong with the annotation store') } return b.showNotification(d, b.Notification.ERROR), console.error(b._t('API request failed:') + (' \'' + a.status + '\'')) }, d }(b.Plugin), b.Plugin.Permissions = function (c) { function d(a, b) { this._setAuthFromToken = I(this._setAuthFromToken, this), this.updateViewer = I(this.updateViewer, this), this.updateAnnotationPermissions = I(this.updateAnnotationPermissions, this), this.updatePermissionsField = I(this.updatePermissionsField, this), this.addFieldsToAnnotation = I(this.addFieldsToAnnotation, this), d.__super__.constructor.apply(this, arguments), this.options.user && (this.setUser(this.options.user), delete this.options.user) } return H(d, c), d.prototype.events = { beforeAnnotationCreated: 'addFieldsToAnnotation' }, d.prototype.options = { showViewPermissionsCheckbox: !0, showEditPermissionsCheckbox: !0, userId: function (a) { return a }, userString: function (a) { return a }, userAuthorize: function (a, b, c) { var d, e, f, g; if (b.permissions) { e = b.permissions[a] || []; if (e.length === 0) return !0; for (f = 0, g = e.length; f < g; f++) { d = e[f]; if (this.userId(c) === d) return !0 } return !1 } return b.user ? c ? this.userId(c) === this.userId(b.user) : !1 : !0 }, user: '', permissions: { read: [ ], update: [ ], 'delete': [ ], admin: [ ] } }, d.prototype.pluginInit = function () { var a, c, d = this; if (!b.supported()) return ; c = this, a = function (a, b) { return function (d, e) { return c[a].call(c, b, d, e) } }, !this.user && this.annotator.plugins.Auth && this.annotator.plugins.Auth.withToken(this._setAuthFromToken), this.options.showViewPermissionsCheckbox === !0 && this.annotator.editor.addField({ type: 'checkbox', label: b._t('Allow anyone to <strong>view</strong> this annotation'), load: a('updatePermissionsField', 'read'), submit: a('updateAnnotationPermissions', 'read') }), this.options.showEditPermissionsCheckbox === !0 && this.annotator.editor.addField({ type: 'checkbox', label: b._t('Allow anyone to <strong>edit</strong> this annotation'), load: a('updatePermissionsField', 'update'), submit: a('updateAnnotationPermissions', 'update') }), this.annotator.viewer.addField({ load: this.updateViewer }); if (this.annotator.plugins.Filter) return this.annotator.plugins.Filter.addFilter({ label: b._t('User'), property: 'user', isFiltered: function (a, b) { var c, e, f, g; b = d.options.userString(b); if (!a || !b) return !1; g = a.split(/\s*/); for (e = 0, f = g.length; e < f; e++) { c = g[e]; if (b.indexOf(c) === - 1) return !1 } return !0 } }) }, d.prototype.setUser = function (a) { return this.user = a }, d.prototype.addFieldsToAnnotation = function (a) { if (a) { a.permissions = this.options.permissions; if (this.user) return a.user = this.user } }, d.prototype.authorize = function (a, b, c) { return c === void 0 && (c = this.user), this.options.userAuthorize ? this.options.userAuthorize.call(this.options, a, b, c) : !0 }, d.prototype.updatePermissionsField = function (b, c, d) { var e; return c = a(c) .show(), e = c.find('input') .removeAttr('disabled'), this.authorize('admin', d) || c.hide(), this.authorize(b, d || { }, null) ? e.attr('checked', 'checked') : e.removeAttr('checked') }, d.prototype.updateAnnotationPermissions = function (b, c, d) { var e; return d.permissions || (d.permissions = this.options.permissions), e = b + '-permissions', a(c) .find('input') .is(':checked') ? d.permissions[b] = [ ] : d.permissions[b] = [ this.user ] }, d.prototype.updateViewer = function (c, d, e) { var f, g; c = a(c), g = this.options.userString(d.user), d.user && g && typeof g == 'string' ? (f = b.Util.escape(this.options.userString(d.user)), c.html(f) .addClass('annotator-user')) : c.remove(); if (e) { this.authorize('update', d) || e.hideEdit(); if (!this.authorize('delete', d)) return e.hideDelete() } }, d.prototype._setAuthFromToken = function (a) { return this.setUser(a.userId) }, d }(b.Plugin), b.Plugin.AnnotateItPermissions = function (b) { function c() { return this._setAuthFromToken = I(this._setAuthFromToken, this), this.updateAnnotationPermissions = I(this.updateAnnotationPermissions, this), this.updatePermissionsField = I(this.updatePermissionsField, this), this.addFieldsToAnnotation = I(this.addFieldsToAnnotation, this), C = c.__super__.constructor.apply(this, arguments), C } return H(c, b), c.prototype.options = { showViewPermissionsCheckbox: !0, showEditPermissionsCheckbox: !0, groups: { world: 'group:__world__', authenticated: 'group:__authenticated__', consumer: 'group:__consumer__' }, userId: function (a) { return a.userId }, userString: function (a) { return a.userId }, userAuthorize: function (a, b, c) { var d, e, f, g, h, i; return e = b.permissions || { }, d = e[a] || [], (f = this.groups.world, J.call(d, f) >= 0) ? !0 : c != null && c.userId != null && c.consumerKey != null ? c.userId === b.user && c.consumerKey === b.consumer ? !0 : (g = this.groups.authenticated, J.call(d, g) >= 0) ? !0 : c.consumerKey === b.consumer && (h = this.groups.consumer, J.call(d, h) >= 0) ? !0 : c.consumerKey === b.consumer && (i = c.userId, J.call(d, i) >= 0) ? !0 : c.consumerKey === b.consumer && c.admin ? !0 : !1 : !1 }, permissions: { read: [ 'group:__world__' ], update: [ ], 'delete': [ ], admin: [ ] } }, c.prototype.addFieldsToAnnotation = function (a) { if (a) { a.permissions = this.options.permissions; if (this.user) return a.user = this.user.userId, a.consumer = this.user.consumerKey } }, c.prototype.updatePermissionsField = function (b, c, d) { var e; return c = a(c) .show(), e = c.find('input') .removeAttr('disabled'), this.authorize('admin', d) || c.hide(), this.user && this.authorize(b, d || { }, { userId: '__nonexistentuser__', consumerKey: this.user.consumerKey }) ? e.attr('checked', 'checked') : e.removeAttr('checked') }, c.prototype.updateAnnotationPermissions = function (b, c, d) { var e; return d.permissions || (d.permissions = this.options.permissions), e = b + '-permissions', a(c) .find('input') .is(':checked') ? d.permissions[b] = [ b === 'read' ? this.options.groups.world : this.options.groups.consumer ] : d.permissions[b] = [ ] }, c.prototype._setAuthFromToken = function (a) { return this.setUser(a) }, c }(b.Plugin.Permissions), b.Plugin.Filter = function (c) { function d(b, c) { this._onPreviousClick = I(this._onPreviousClick, this), this._onNextClick = I(this._onNextClick, this), this._onFilterKeyup = I(this._onFilterKeyup, this), this._onFilterBlur = I(this._onFilterBlur, this), this._onFilterFocus = I(this._onFilterFocus, this), this.updateHighlights = I(this.updateHighlights, this); var e; b = a(this.html.element) .appendTo((c != null ? c.appendTo : void 0) || this.options.appendTo), d.__super__.constructor.call(this, b, c), (e = this.options) .filters || (e.filters = [ ]), this.filter = a(this.html.filter), this.filters = [ ], this.current = 0 } return H(d, c), d.prototype.events = { '.annotator-filter-property input focus': '_onFilterFocus', '.annotator-filter-property input blur': '_onFilterBlur', '.annotator-filter-property input keyup': '_onFilterKeyup', '.annotator-filter-previous click': '_onPreviousClick', '.annotator-filter-next click': '_onNextClick', '.annotator-filter-clear click': '_onClearClick' }, d.prototype.classes = { active: 'annotator-filter-active', hl: { hide: 'annotator-hl-filtered', active: 'annotator-hl-active' } }, d.prototype.html = { element: '<div class="annotator-filter">\n <strong>' + b._t('Navigate:') + '</strong>\n<span class="annotator-filter-navigation">\n <button class="annotator-filter-previous">' + b._t('Previous') + '</button>\n<button class="annotator-filter-next">' + b._t('Next') + '</button>\n</span>\n<strong>' + b._t('Filter by:') + '</strong>\n</div>', filter: '<span class="annotator-filter-property">\n <label></label>\n <input/>\n <button class="annotator-filter-clear">' + b._t('Clear') + '</button>\n</span>' }, d.prototype.options = { appendTo: 'body', filters: [ ], addAnnotationFilter: !0, isFiltered: function (a, b) { var c, d, e, f; if (!a || !b) return !1; f = a.split(/\s*/); for (d = 0, e = f.length; d < e; d++) { c = f[d]; if (b.indexOf(c) === - 1) return !1 } return !0 } }, d.prototype.pluginInit = function () { var a, c, d, e; e = this.options.filters; for (c = 0, d = e.length; c < d; c++) a = e[c], this.addFilter(a); this.updateHighlights(), this._setupListeners() ._insertSpacer(); if (this.options.addAnnotationFilter === !0) return this.addFilter({ label: b._t('Annotation'), property: 'text' }) }, d.prototype._insertSpacer = function () { var b, c; return c = a('html'), b = parseInt(c.css('padding-top'), 10) || 0, c.css('padding-top', b + this.element.outerHeight()), this }, d.prototype._setupListeners = function () { var a, b, c, d; b = [ 'annotationsLoaded', 'annotationCreated', 'annotationUpdated', 'annotationDeleted' ]; for (c = 0, d = b.length; c < d; c++) a = b[c], this.annotator.subscribe(a, this.updateHighlights); return this }, d.prototype.addFilter = function (c) { var d, e; e = a.extend({ label: '', property: '', isFiltered: this.options.isFiltered }, c); if (!function () { var a, b, c, f; c = this.filters, f = [ ]; for (a = 0, b = c.length; a < b; a++) d = c[a], d.property === e.property && f.push(d); return f }.call(this) .length) e.id = 'annotator-filter-' + e.property, e.annotations = [ ], e.element = this.filter.clone() .appendTo(this.element), e.element.find('label') .html(e.label) .attr('for', e.id), e.element.find('input') .attr({ id: e.id, placeholder: b._t('Filter by ') + e.label + '鈥�' }), e.element.find('button') .hide(), e.element.data('filter', e), this.filters.push(e); return this }, d.prototype.updateFilter = function (b) { var c, d, e, f, g, h, i; b.annotations = [ ], this.updateHighlights(), this.resetHighlights(), e = a.trim(b.element.find('input') .val()); if (e) { d = this.highlights.map(function () { return a(this) .data('annotation') }), i = a.makeArray(d); for (g = 0, h = i.length; g < h; g++) c = i[g], f = c[b.property], b.isFiltered(e, f) && b.annotations.push(c); return this.filterHighlights() } }, d.prototype.updateHighlights = function () { return this.highlights = this.annotator.element.find('.annotator-hl:visible'), this.filtered = this.highlights.not(this.classes.hl.hide) }, d.prototype.filterHighlights = function () { var b, c, d, e, f, g, h, i, j, k; b = a.grep(this.filters, function (a) { return !!a.annotations.length }), e = ((k = b[0]) != null ? k.annotations : void 0) || [], b.length > 1 && (d = [ ], a.each(b, function () { return a.merge(d, this.annotations) }), h = [ ], e = [ ], a.each(d, function () { return a.inArray(this, h) === - 1 ? h.push(this) : e.push(this) })), f = this.highlights; for (g = i = 0, j = e.length; i < j; g = ++i) c = e[g], f = f.not(c.highlights); return f.addClass(this.classes.hl.hide), this.filtered = this.highlights.not(this.classes.hl.hide), this }, d.prototype.resetHighlights = function () { return this.highlights.removeClass(this.classes.hl.hide), this.filtered = this.highlights, this }, d.prototype._onFilterFocus = function (b) { var c; return c = a(b.target), c.parent() .addClass(this.classes.active), c.next('button') .show() }, d.prototype._onFilterBlur = function (b) { var c; if (!b.target.value) return c = a(b.target), c.parent() .removeClass(this.classes.active), c.next('button') .hide() }, d.prototype._onFilterKeyup = function (b) { var c; c = a(b.target) .parent() .data('filter'); if (c) return this.updateFilter(c) }, d.prototype._findNextHighlight = function (a) { var b, c, d, e, f, g, h, i; return this.highlights.length ? (g = a ? 0 : - 1, i = a ? - 1 : 0, h = a ? 'lt' : 'gt', b = this.highlights.not('.' + this.classes.hl.hide), d = b.filter('.' + this.classes.hl.active), d.length || (d = b.eq(g)), c = d.data('annotation'), e = b.index(d[0]), f = b.filter(':' + h + '(' + e + ')') .not(c.highlights) .eq(i), f.length || (f = b.eq(i)), this._scrollToHighlight(f.data('annotation') .highlights)) : this }, d.prototype._onNextClick = function (a) { return this._findNextHighlight() }, d.prototype._onPreviousClick = function (a) { return this._findNextHighlight(!0) }, d.prototype._scrollToHighlight = function (b) { return b = a(b), this.highlights.removeClass(this.classes.hl.active), b.addClass(this.classes.hl.active), a('html, body') .animate({ scrollTop: b.offset() .top - (this.element.height() + 20) }, 150) }, d.prototype._onClearClick = function (b) { return a(b.target) .prev('input') .val('') .keyup() .blur() }, d }(b.Plugin), b.Plugin.Markdown = function (c) { function d(a, c) { this.updateTextField = I(this.updateTextField, this), (typeof Showdown !== 'undefined' && Showdown !== null ? Showdown.converter : void 0) != null ? (d.__super__.constructor.apply(this, arguments), this.converter = new Showdown.converter) : console.error(b._t('To use the Markdown plugin, you must include Showdown into the page first.')) } return H(d, c), d.prototype.events = { annotationViewerTextField: 'updateTextField' }, d.prototype.updateTextField = function (c, d) { var e; return e = b.Util.escape(d.text || ''), a(c) .html(this.convert(e)) }, d.prototype.convert = function (a) { return this.converter.makeHtml(a) }, d }(b.Plugin), b.Plugin.Tags = function (c) { function d() { return this.setAnnotationTags = I(this.setAnnotationTags, this), this.updateField = I(this.updateField, this), D = d.__super__.constructor.apply(this, arguments), D } return H(d, c), d.prototype.options = { parseTags: function (b) { var c; return b = a.trim(b), c = [ ], b && (c = b.split(/\s+/)), c }, stringifyTags: function (a) { return a.join(' ') } }, d.prototype.field = null, d.prototype.input = null, d.prototype.pluginInit = function () { if (!b.supported()) return ; return this.field = this.annotator.editor.addField({ label: b._t('Add some tags here') + '鈥�', load: this.updateField, submit: this.setAnnotationTags }), this.annotator.viewer.addField({ load: this.updateViewer }), this.annotator.plugins.Filter && this.annotator.plugins.Filter.addFilter({ label: b._t('Tag'), property: 'tags', isFiltered: b.Plugin.Tags.filterCallback }), this.input = a(this.field) .find(':input') }, d.prototype.parseTags = function (a) { return this.options.parseTags(a) }, d.prototype.stringifyTags = function (a) { return this.options.stringifyTags(a) }, d.prototype.updateField = function (a, b) { var c; return c = '', b.tags && (c = this.stringifyTags(b.tags)), this.input.val(c) }, d.prototype.setAnnotationTags = function (a, b) { return b.tags = this.parseTags(this.input.val()) }, d.prototype.updateViewer = function (c, d) { return c = a(c), d.tags && a.isArray(d.tags) && d.tags.length ? c.addClass('annotator-tags') .html(function () { var c; return c = a.map(d.tags, function (a) { return '<span class="annotator-tag">' + b.Util.escape(a) + '</span>' }) .join(' ') }) : c.remove() }, d }(b.Plugin), b.Plugin.Tags.filterCallback = function (a, b) { var c, d, e, f, g, h, i, j; b == null && (b = [ ]), e = 0, d = [ ]; if (a) { d = a.split(/\s+/g); for (g = 0, i = d.length; g < i; g++) { c = d[g]; if (b.length) for (h = 0, j = b.length; h < j; h++) f = b[h], f.indexOf(c) !== - 1 && (e += 1) } } return e === d.length }, b.prototype.setupPlugins = function (c, d) { var e, f, g, h, i, j, k, l, m; c == null && (c = { }), d == null && (d = { }), j = b.Util.getGlobal(), h = [ 'Unsupported', 'Auth', 'Tags', 'Filter', 'Store', 'AnnotateItPermissions' ], j.Showdown && h.push('Markdown'), i = j.location.href.split(/#|\?/) .shift() || '', g = { Tags: { }, Filter: { filters: [ { label: b._t('User'), property: 'user' }, { label: b._t('Tags'), property: 'tags' } ] }, Auth: { tokenUrl: c.tokenUrl || 'http://annotateit.org/api/token' }, Store: { prefix: c.storeUrl || 'http://annotateit.org/api', annotationData: { uri: i }, loadFromSearch: { uri: i } } }; for (e in d) { if (!G.call(d, e)) continue; f = d[e], J.call(h, e) < 0 && h.push(e) } a.extend(!0, g, d), m = [ ]; for (k = 0, l = h.length; k < l; k++) e = h[k], e in g && !g[e] ? m.push(void 0) : m.push(this.addPlugin(e, g[e])); return m } })) .call(this); /* Offline Annotator Plugin - v1.0.0 * Copyright 2012, Compendio <www.compendio.ch> * Released under the MIT license * More Information: http://github.com/aron/annotator.offline.js */ ((function () { var a, b, c = function (a, b) { return function () { return a.apply(b, arguments) } }, d = Object.prototype.hasOwnProperty, e = function (a, b) { function e() { this.constructor = a } for (var c in b) d.call(b, c) && (a[c] = b[c]); return e.prototype = b.prototype, a.prototype = new e, a.__super__ = b.prototype, a }; Annotator.Plugin.Offline = a = function (a) { function g() { this._onOffline = c(this._onOffline, this), this._onOnline = c(this._onOnline, this); var a, e, f; g.__super__.constructor.apply(this, arguments), this.store = new g.Store, this.cache = { }, f = { online: 'online', offline: 'offline', beforeAnnotationLoaded: 'setAnnotationData', beforeAnnotationCreated: 'setAnnotationData' }; for (a in f) { if (!d.call(f, a)) continue; e = f[a], typeof this.options[e] == 'function' && this.on(a, b.proxy(this.options, e)) } } var b, f; return e(g, a), f = Annotator._t, b = Annotator.$, g.ANNOTATION_PREFIX = 'annotation.', g.uuid = function () { return ('' + Math.random() + (new Date) .getTime()) .slice(2) }, g.prototype.events = { annotationCreated: '_onAnnotationCreated', annotationUpdated: '_onAnnotationUpdated', annotationDeleted: '_onAnnotationDeleted' }, g.prototype.options = { getUniqueKey: function (a) { return a.id || (a.id = g.uuid()), a.id }, shouldLoadAnnotation: function (a) { return !0 } }, g.prototype.pluginInit = function () { if (!Annotator.supported()) return ; return this.loadAnnotationsFromStore(), this.isOnline() ? this.online() : this.offline(), b(window) .bind({ online: this._onOnline, offline: this._onOffline }) }, g.prototype.annotations = function () { return this.cache }, g.prototype.online = function () { return this.publish('online', [ this ]), this }, g.prototype.offline = function () { return this.publish('offline', [ this ]), this }, g.prototype.isOnline = function () { return window.navigator.onLine }, g.prototype.loadAnnotationsFromStore = function () { var a, b, c, d, e; c = [ ], b = this.store.all(g.ANNOTATION_PREFIX); for (d = 0, e = b.length; d < e; d++) { a = b[d]; if (!this.options.shouldLoadAnnotation(a)) continue; this.publish('beforeAnnotationLoaded', [ a, this ]), this.publish('annotationLoaded', [ a, this ]), this.cache[this.keyForAnnotation(a)] = a, c.push(a) } return c.length && this.annotator.loadAnnotations(c), this }, g.prototype.addAnnotation = function (a, b) { var c; return b == null && (b = { }), c = this.cache[this.options.getUniqueKey(a)], !c && this.options.shouldLoadAnnotation(a) ? this.annotator.setupAnnotation(a, b.silent) : this.updateStoredAnnotation(a), this }, g.prototype.removeAnnotation = function (a) { return this.options.shouldLoadAnnotation(a) ? this.annotator.deleteAnnotation(a) : this.removeStoredAnnotation(a), this }, g.prototype.updateStoredAnnotation = function (a) { var c, d, e, f; return c = this.keyForAnnotation(a), d = this.keyForStore(a), e = this.cache[c], e ? b.extend(e, a) : e = this.cache[c] = a, f = b.extend({ }, e), delete f.highlights, this.store.set(d, f), this }, g.prototype.removeStoredAnnotation = function (a) { var b, c; return b = this.keyForAnnotation(a), c = this.keyForStore(a), this.store.remove(c), delete this.cache[b], this }, g.prototype.keyForAnnotation = function (a) { return this.options.getUniqueKey.call(this, a, this) }, g.prototype.keyForStore = function (a) { return g.ANNOTATION_PREFIX + this.keyForAnnotation(a) }, g.prototype._onOnline = function (a) { return this.online() }, g.prototype._onOffline = function (a) { return this.offline() }, g.prototype._onAnnotationCreated = function (a) { return this.updateStoredAnnotation(a) }, g.prototype._onAnnotationUpdated = function (a) { return this.updateStoredAnnotation(a) }, g.prototype._onAnnotationDeleted = function (a) { return this.removeStoredAnnotation(a) }, g }(Annotator.Plugin), Annotator.Plugin.Offline.Store = b = function (a) { function b() { b.__super__.constructor.apply(this, arguments) } return e(b, a), b.KEY_PREFIX = 'annotator.offline/', b.CACHE_DELIMITER = '--cache--', b.localStorage = window.localStorage, b.isSupported = function () { try { return 'localStorage' in window && window.localStorage !== null } catch (a) { return !1 } }, b.now = function () { return (new Date) .getTime() }, b.prototype.all = function (a) { var c, d, e, f; a == null && (a = ''), f = [ ], d = this.prefixed(a); for (c in localStorage) { if (c.indexOf(d) !== 0) continue; e = this.get(c.slice(b.KEY_PREFIX.length)), f.push(e) } return f }, b.prototype.get = function (a) { var c; return c = b.localStorage.getItem(this.prefixed(a)), c && (c = this.checkCache(c), c || this.remove(a)), JSON.parse(c) }, b.prototype.set = function (a, c, d) { c = JSON.stringify(c), d && (c = b.now() + d + b.CACHE_DELIMITER + c); try { b.localStorage.setItem(this.prefixed(a), c) } catch (e) { this.publish('error', [ e, this ]) } return this }, b.prototype.remove = function (a) { return b.localStorage.removeItem(this.prefixed(a)), this }, b.prototype.clear = function () { var a, c; c = b.localStorage; for (a in c) a.indexOf(b.KEY_PREFIX) === 0 && c.removeItem(a); return this }, b.prototype.prefixed = function (a) { return b.KEY_PREFIX + a }, b.prototype.checkCache = function (a) { var c; return a.indexOf(b.CACHE_DELIMITER) > - 1 && (c = a.split(b.CACHE_DELIMITER), a = b.now() > c.shift() ? null : c.join(b.CACHE_DELIMITER)), a }, b }(Annotator.Delegator) })) .call(this); //in case of compatibility problems,replace jQuery with $wxz var $wxz = jQuery.noConflict(); // insert css var cssText = '<link rel="stylesheet" href="https://wxzproxy.duapp.com/css/annotator.min.css" />'; $wxz('head:first') .append(cssText); //initialize the annotation method,and attach offline plugin var content = $wxz('body:first') .annotator(); content.annotator('addPlugin', 'Offline'); var annotator = content.data('annotator'); //clear local storage method .just for further development $wxz('#clear-storage') .click(function () { if (annotator) { annotator.plugins.Offline.store.clear() } });