# HG changeset patch # User robcast # Date 1421428815 -3600 # Node ID 49d643f0d6587cad5b9d027b5ffed994c7894f4c # Parent 7d9132a513ab4c2e8a1cf4505197c6bd88ad8236 reverted back to stable branch Annotator.js-1.2.5. diff -r 7d9132a513ab -r 49d643f0d658 webapp/src/main/webapp/jquery/annotator-dl.js --- a/webapp/src/main/webapp/jquery/annotator-dl.js Mon Dec 15 18:49:42 2014 +0100 +++ b/webapp/src/main/webapp/jquery/annotator-dl.js Fri Jan 16 18:20:15 2015 +0100 @@ -1,747 +1,886 @@ /* -** Annotator v2.0.0-dev-e25ce72 +** Annotator 1.2.5-dev-a4cd304 ** https://github.com/okfn/annotator/ ** -** Copyright 2014, the Annotator project contributors. +** 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: 2014-03-14 15:39:01Z +** Built at: 2012-11-23 09:46:08Z */ -!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Annotator=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o/g, '>').replace(/"/g, '"'); + }; - // Bind an event to only be triggered a single time. After the first time - // the callback is invoked, it will be removed. - once: function(name, callback, context) { - if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this; - var self = this; - var once = _.once(function() { - self.off(name, once); - callback.apply(this, arguments); - }); - once._callback = callback; - return this.on(name, once, context); - }, + $.fn.escape = function(html) { + if (arguments.length) { + return this.html($.escape(html)); + } + return this.html(); + }; + + $.fn.reverse = []._reverse || [].reverse; + + functions = ["log", "debug", "info", "warn", "exception", "assert", "dir", "dirxml", "trace", "group", "groupEnd", "groupCollapsed", "time", "timeEnd", "profile", "profileEnd", "count", "clear", "table", "error", "notifyFirebug", "firebug", "userObjects"]; - // Remove one or many callbacks. If `context` is null, removes all - // callbacks with that function. If `callback` is null, removes all - // callbacks for the event. If `name` is null, removes all bound - // callbacks for all events. - off: function(name, callback, context) { - var retain, ev, events, names, i, l, j, k; - if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this; - if (!name && !callback && !context) { - this._events = {}; - return this; + if (typeof console !== "undefined" && console !== null) { + if (!(console.group != null)) { + console.group = function(name) { + return console.log("GROUP: ", name); + }; + } + if (!(console.groupCollapsed != null)) { + console.groupCollapsed = console.group; + } + for (_i = 0, _len = functions.length; _i < _len; _i++) { + fn = functions[_i]; + if (!(console[fn] != null)) { + console[fn] = function() { + return console.log(_t("Not implemented:") + (" console." + name)); + }; } + } + } else { + this.console = {}; + for (_j = 0, _len1 = functions.length; _j < _len1; _j++) { + fn = functions[_j]; + this.console[fn] = function() {}; + } + this.console['error'] = function() { + var args; + args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + return alert("ERROR: " + (args.join(', '))); + }; + this.console['warn'] = function() { + var args; + args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + return alert("WARNING: " + (args.join(', '))); + }; + } + + Delegator = (function() { + + Delegator.prototype.events = {}; - names = name ? [name] : _.keys(this._events); - for (i = 0, l = names.length; i < l; i++) { - name = names[i]; - if (events = this._events[name]) { - this._events[name] = retain = []; - if (callback || context) { - for (j = 0, k = events.length; j < k; j++) { - ev = events[j]; - if ((callback && callback !== ev.callback && callback !== ev.callback._callback) || - (context && context !== ev.context)) { - retain.push(ev); - } - } - } - if (!retain.length) delete this._events[name]; + Delegator.prototype.options = {}; + + Delegator.prototype.element = null; + + function Delegator(element, options) { + this.options = $.extend(true, {}, this.options, options); + this.element = $(element); + this.on = this.subscribe; + this.addEvents(); + } + + Delegator.prototype.addEvents = function() { + var event, functionName, sel, selector, _k, _ref1, _ref2, _results; + _ref1 = this.events; + _results = []; + for (sel in _ref1) { + functionName = _ref1[sel]; + _ref2 = sel.split(' '), selector = 2 <= _ref2.length ? __slice.call(_ref2, 0, _k = _ref2.length - 1) : (_k = 0, []), event = _ref2[_k++]; + _results.push(this.addEvent(selector.join(' '), event, functionName)); + } + return _results; + }; + + Delegator.prototype.addEvent = function(bindTo, event, functionName) { + var closure, isBlankSelector, + _this = this; + closure = function() { + return _this[functionName].apply(_this, arguments); + }; + isBlankSelector = typeof bindTo === 'string' && bindTo.replace(/\s+/g, '') === ''; + if (isBlankSelector) { + bindTo = this.element; + } + if (typeof bindTo === 'string') { + this.element.delegate(bindTo, event, closure); + } else { + if (this.isCustomEvent(event)) { + this.subscribe(event, closure); + } else { + $(bindTo).bind(event, closure); } } - return this; - }, + }; + + Delegator.prototype.isCustomEvent = function(event) { + event = event.split('.')[0]; + return $.inArray(event, Delegator.natives) === -1; + }; + + Delegator.prototype.publish = function() { + this.element.triggerHandler.apply(this.element, arguments); + return this; + }; - // Trigger one or many events, firing all bound callbacks. Callbacks are - // passed the same arguments as `trigger` is, apart from the event name - // (unless you're listening on `"all"`, which will cause your callback to - // receive the true name of the event as the first argument). - trigger: function(name) { - if (!this._events) return this; - var args = slice.call(arguments, 1); - if (!eventsApi(this, 'trigger', name, args)) return this; - var events = this._events[name]; - var allEvents = this._events.all; - if (events) triggerEvents(events, args); - if (allEvents) triggerEvents(allEvents, arguments); + Delegator.prototype.subscribe = function(event, callback) { + var closure; + closure = function() { + return callback.apply(this, [].slice.call(arguments, 1)); + }; + closure.guid = callback.guid = ($.guid += 1); + this.element.bind(event, closure); + return this; + }; + + Delegator.prototype.unsubscribe = function() { + this.element.unbind.apply(this.element, arguments); return this; - }, + }; + + return Delegator; + + })(); - // Tell this object to stop listening to either specific events ... or - // to every object it's currently listening to. - stopListening: function(obj, name, callback) { - var listeners = this._listeners; - if (!listeners) return this; - var deleteListener = !name && !callback; - if (typeof name === 'object') callback = this; - if (obj) (listeners = {})[obj._listenerId] = obj; - for (var id in listeners) { - listeners[id].off(name, callback, this); - if (deleteListener) delete this._listeners[id]; + Delegator.natives = (function() { + var key, specials, val; + specials = (function() { + var _ref1, _results; + _ref1 = jQuery.event.special; + _results = []; + for (key in _ref1) { + if (!__hasProp.call(_ref1, key)) continue; + val = _ref1[key]; + _results.push(key); } - return this; + return _results; + })(); + return "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(specials); + })(); + + Range = {}; + + Range.sniff = function(r) { + if (r.commonAncestorContainer != null) { + return new Range.BrowserRange(r); + } else if (typeof r.start === "string") { + return new Range.SerializedRange(r); + } else if (r.start && typeof r.start === "object") { + return new Range.NormalizedRange(r); + } else { + console.error(_t("Could not sniff range type")); + return false; } - }; - // Regular expression used to split event strings. - var eventSplitter = /\s+/; - - // Implement fancy features of the Events API such as multiple event - // names `"change blur"` and jQuery-style event maps `{change: action}` - // in terms of the existing API. - var eventsApi = function(obj, action, name, rest) { - if (!name) return true; - - // Handle event maps. - if (typeof name === 'object') { - for (var key in name) { - obj[action].apply(obj, [key, name[key]].concat(rest)); - } - return false; + Range.nodeFromXPath = function(xpath, root) { + var customResolver, evaluateXPath, namespace, node, segment; + if (root == null) { + root = document; } - - // Handle space separated event names. - if (eventSplitter.test(name)) { - var names = name.split(eventSplitter); - for (var i = 0, l = names.length; i < l; i++) { - obj[action].apply(obj, [names[i]].concat(rest)); + evaluateXPath = function(xp, nsResolver) { + if (nsResolver == null) { + nsResolver = null; } - return false; - } - - return true; - }; - - // A difficult-to-believe, but optimized internal dispatch function for - // triggering events. Tries to keep the usual cases speedy (most internal - // Backbone events have 3 arguments). - var triggerEvents = function(events, args) { - var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2]; - switch (args.length) { - case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return; - case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return; - case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return; - case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return; - default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); + return document.evaluate('.' + xp, root, nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; + }; + if (!$.isXMLDoc(document.documentElement)) { + return evaluateXPath(xpath); + } else { + customResolver = document.createNSResolver(document.ownerDocument === null ? document.documentElement : document.ownerDocument.documentElement); + node = evaluateXPath(xpath, customResolver); + if (!node) { + xpath = ((function() { + var _k, _len2, _ref1, _results; + _ref1 = xpath.split('/'); + _results = []; + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + segment = _ref1[_k]; + if (segment && segment.indexOf(':') === -1) { + _results.push(segment.replace(/^([a-z]+)/, 'xhtml:$1')); + } else { + _results.push(segment); + } + } + return _results; + })()).join('/'); + namespace = document.lookupNamespaceURI(null); + customResolver = function(ns) { + if (ns === 'xhtml') { + return namespace; + } else { + return document.documentElement.getAttribute('xmlns:' + ns); + } + }; + node = evaluateXPath(xpath, customResolver); + } + return node; } }; - var listenMethods = {listenTo: 'on', listenToOnce: 'once'}; + Range.RangeError = (function(_super) { + + __extends(RangeError, _super); + + function RangeError(type, message, parent) { + this.type = type; + this.message = message; + this.parent = parent != null ? parent : null; + RangeError.__super__.constructor.call(this, this.message); + } + + return RangeError; + + })(Error); + + Range.BrowserRange = (function() { + + function BrowserRange(obj) { + this.commonAncestorContainer = obj.commonAncestorContainer; + this.startContainer = obj.startContainer; + this.startOffset = obj.startOffset; + this.endContainer = obj.endContainer; + this.endOffset = obj.endOffset; + } - // Inversion-of-control versions of `on` and `once`. Tell *this* object to - // listen to an event in another object ... keeping track of what it's - // listening to. - _.each(listenMethods, function(implementation, method) { - Events[method] = function(obj, name, callback) { - var listeners = this._listeners || (this._listeners = {}); - var id = obj._listenerId || (obj._listenerId = _.uniqueId('l')); - listeners[id] = obj; - if (typeof name === 'object') callback = this; - obj[implementation](name, callback, this); + BrowserRange.prototype.normalize = function(root) { + var it, node, nr, offset, p, r, _k, _len2, _ref1; + if (this.tainted) { + console.error(_t("You may only call normalize() once on a BrowserRange!")); + return false; + } else { + this.tainted = true; + } + r = {}; + nr = {}; + _ref1 = ['start', 'end']; + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + p = _ref1[_k]; + node = this[p + 'Container']; + offset = this[p + 'Offset']; + if (!((node != null) && (offset != null))) { + return false; + } + if (node.nodeType === 1) { + it = node.childNodes[offset]; + node = it || node.childNodes[offset - 1]; + if (node.nodeType === 1 && !node.firstChild) { + it = null; + node = node.previousSibling; + } + while (node.nodeType !== 3) { + node = node.firstChild; + } + offset = it ? 0 : node.nodeValue.length; + } + r[p] = node; + r[p + 'Offset'] = offset; + } + nr.start = r.startOffset > 0 ? r.start.splitText(r.startOffset) : r.start; + if (r.start === r.end) { + if ((r.endOffset - r.startOffset) < nr.start.nodeValue.length) { + nr.start.splitText(r.endOffset - r.startOffset); + } + nr.end = nr.start; + } else { + if (r.endOffset < r.end.nodeValue.length) { + r.end.splitText(r.endOffset); + } + nr.end = r.end; + } + nr.commonAncestor = this.commonAncestorContainer; + while (nr.commonAncestor.nodeType !== 1) { + nr.commonAncestor = nr.commonAncestor.parentNode; + } + return new Range.NormalizedRange(nr); + }; + + BrowserRange.prototype.serialize = function(root, ignoreSelector) { + return this.normalize(root).serialize(root, ignoreSelector); + }; + + return BrowserRange; + + })(); + + Range.NormalizedRange = (function() { + + function NormalizedRange(obj) { + this.commonAncestor = obj.commonAncestor; + this.start = obj.start; + this.end = obj.end; + } + + NormalizedRange.prototype.normalize = function(root) { + return this; + }; + + NormalizedRange.prototype.limit = function(bounds) { + var nodes, parent, startParents, _k, _len2, _ref1; + nodes = $.grep(this.textNodes(), function(node) { + return node.parentNode === bounds || $.contains(bounds, node.parentNode); + }); + if (!nodes.length) { + return null; + } + this.start = nodes[0]; + this.end = nodes[nodes.length - 1]; + startParents = $(this.start).parents(); + _ref1 = $(this.end).parents(); + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + parent = _ref1[_k]; + if (startParents.index(parent) !== -1) { + this.commonAncestor = parent; + break; + } + } return this; }; - }); - // Aliases for backwards compatibility. - Events.bind = Events.on; - Events.unbind = Events.off; + NormalizedRange.prototype.serialize = function(root, ignoreSelector) { + var end, serialization, start; + serialization = function(node, isEnd) { + var n, nodes, offset, origParent, textNodes, xpath, _k, _len2; + if (ignoreSelector) { + origParent = $(node).parents(":not(" + ignoreSelector + ")").eq(0); + } else { + origParent = $(node).parent(); + } + xpath = origParent.xpath(root)[0]; + textNodes = origParent.textNodes(); + nodes = textNodes.slice(0, textNodes.index(node)); + offset = 0; + for (_k = 0, _len2 = nodes.length; _k < _len2; _k++) { + n = nodes[_k]; + offset += n.nodeValue.length; + } + if (isEnd) { + return [xpath, offset + node.nodeValue.length]; + } else { + return [xpath, offset]; + } + }; + start = serialization(this.start); + end = serialization(this.end, true); + return new Range.SerializedRange({ + start: start[0], + end: end[0], + startOffset: start[1], + endOffset: end[1] + }); + }; - // Mixin utility - Events.mixin = function(proto) { - var exports = ['on', 'once', 'off', 'trigger', 'stopListening', 'listenTo', - 'listenToOnce', 'bind', 'unbind']; - _.each(exports, function(name) { - proto[name] = this[name]; - }, this); - return proto; - }; + NormalizedRange.prototype.text = function() { + var node; + return ((function() { + var _k, _len2, _ref1, _results; + _ref1 = this.textNodes(); + _results = []; + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + node = _ref1[_k]; + _results.push(node.nodeValue); + } + return _results; + }).call(this)).join(''); + }; - // Export Events as BackboneEvents depending on current context - if (typeof define === "function") { - define(function() { - return Events; - }); - } else if (typeof exports !== 'undefined') { - if (typeof module !== 'undefined' && module.exports) { - exports = module.exports = Events; + NormalizedRange.prototype.textNodes = function() { + var end, start, textNodes, _ref1; + textNodes = $(this.commonAncestor).textNodes(); + _ref1 = [textNodes.index(this.start), textNodes.index(this.end)], start = _ref1[0], end = _ref1[1]; + return $.makeArray(textNodes.slice(start, end + 1 || 9e9)); + }; + + NormalizedRange.prototype.toRange = function() { + var range; + range = document.createRange(); + range.setStartBefore(this.start); + range.setEndAfter(this.end); + return range; + }; + + return NormalizedRange; + + })(); + + Range.SerializedRange = (function() { + + function SerializedRange(obj) { + this.start = obj.start; + this.startOffset = obj.startOffset; + this.end = obj.end; + this.endOffset = obj.endOffset; } - exports.BackboneEvents = Events; - } else { - root.BackboneEvents = Events; - } -})(this); -},{}],2:[function(_dereq_,module,exports){ -module.exports = _dereq_('./backbone-events-standalone'); - -},{"./backbone-events-standalone":1}],3:[function(_dereq_,module,exports){ -(function (definition) { - if (typeof exports === "object") { - module.exports = definition(); - } - else if (typeof define === 'function' && define.amd) { - define(definition); - } - else { - window.BackboneExtend = definition(); - } -})(function () { - "use strict"; - - // mini-underscore - var _ = { - has: function (obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); - }, - - extend: function(obj) { - for (var i=1; i= this[p + 'Offset']) { + range[p + 'Container'] = tn; + range[p + 'Offset'] = this[p + 'Offset'] - length; + break; + } else { + length += tn.nodeValue.length; } } + if (!(range[p + 'Offset'] != null)) { + throw new Range.RangeError("" + p + "offset", "Couldn't find offset " + this[p + 'Offset'] + " in element " + this[p]); + } } - return obj; + contains = !(document.compareDocumentPosition != null) ? function(a, b) { + return a.contains(b); + } : function(a, b) { + return a.compareDocumentPosition(b) & 16; + }; + $(range.startContainer).parents().reverse().each(function() { + if (contains(this, range.endContainer)) { + range.commonAncestorContainer = this; + return false; + } + }); + return new Range.BrowserRange(range).normalize(root); + }; + + SerializedRange.prototype.serialize = function(root, ignoreSelector) { + return this.normalize(root).serialize(root, ignoreSelector); + }; + + SerializedRange.prototype.toObject = function() { + return { + start: this.start, + startOffset: this.startOffset, + end: this.end, + endOffset: this.endOffset + }; + }; + + return SerializedRange; + + })(); + + util = { + uuid: (function() { + var counter; + counter = 0; + return function() { + return counter++; + }; + })(), + getGlobal: function() { + return (function() { + return this; + })(); + }, + maxZIndex: function($elements) { + var all, el; + all = (function() { + var _k, _len2, _results; + _results = []; + for (_k = 0, _len2 = $elements.length; _k < _len2; _k++) { + el = $elements[_k]; + if ($(el).css('position') === 'static') { + _results.push(-1); + } else { + _results.push(parseInt($(el).css('z-index'), 10) || -1); + } + } + return _results; + })(); + return Math.max.apply(Math, all); + }, + mousePosition: function(e, offsetEl) { + var offset; + offset = $(offsetEl).offset(); + return { + top: e.pageY - offset.top, + left: e.pageX - offset.left + }; + }, + preventEventDefault: function(event) { + return event != null ? typeof event.preventDefault === "function" ? event.preventDefault() : void 0 : void 0; } }; - /// Following code is pasted from Backbone.js /// + _Annotator = this.Annotator; + + Annotator = (function(_super) { + + __extends(Annotator, _super); + + Annotator.prototype.events = { + ".annotator-adder button click": "onAdderClick", + ".annotator-adder button mousedown": "onAdderMousedown", + ".annotator-hl mouseover": "onHighlightMouseover", + ".annotator-hl mouseout": "startViewerHideTimer" + }; + + Annotator.prototype.html = { + adder: '
', + wrapper: '
' + }; + + Annotator.prototype.options = { + readOnly: false + }; + + Annotator.prototype.plugins = {}; + + Annotator.prototype.editor = null; + + Annotator.prototype.viewer = null; + + Annotator.prototype.selectedRanges = null; + + Annotator.prototype.mouseIsDown = false; + + Annotator.prototype.ignoreMouseup = false; + + Annotator.prototype.viewerHideTimer = null; - // Helper function to correctly set up the prototype chain, for subclasses. - // Similar to `goog.inherits`, but uses a hash of prototype properties and - // class properties to be extended. - var extend = function(protoProps, staticProps) { - var parent = this; - var child; + function Annotator(element, options) { + this.onDeleteAnnotation = __bind(this.onDeleteAnnotation, this); + + this.onEditAnnotation = __bind(this.onEditAnnotation, this); + + this.onAdderClick = __bind(this.onAdderClick, this); + + this.onAdderMousedown = __bind(this.onAdderMousedown, this); + + this.onHighlightMouseover = __bind(this.onHighlightMouseover, this); + + this.checkForEndSelection = __bind(this.checkForEndSelection, this); + + this.checkForStartSelection = __bind(this.checkForStartSelection, this); + + this.clearViewerHideTimer = __bind(this.clearViewerHideTimer, this); + + this.startViewerHideTimer = __bind(this.startViewerHideTimer, this); - // The constructor function for the new subclass is either defined by you - // (the "constructor" property in your `extend` definition), or defaulted - // by us to simply call the parent's constructor. - if (protoProps && _.has(protoProps, 'constructor')) { - child = protoProps.constructor; - } else { - child = function(){ return parent.apply(this, arguments); }; + this.showViewer = __bind(this.showViewer, this); + + this.onEditorSubmit = __bind(this.onEditorSubmit, this); + + this.onEditorHide = __bind(this.onEditorHide, this); + + this.showEditor = __bind(this.showEditor, this); + Annotator.__super__.constructor.apply(this, arguments); + this.plugins = {}; + if (!Annotator.supported()) { + return this; + } + if (!this.options.readOnly) { + this._setupDocumentEvents(); + } + this._setupWrapper()._setupViewer()._setupEditor(); + this._setupDynamicStyle(); + this.adder = $(this.html.adder).appendTo(this.wrapper).hide(); } - // Add static properties to the constructor function, if supplied. - _.extend(child, parent, staticProps); - - // Set the prototype chain to inherit from `parent`, without calling - // `parent`'s constructor function. - var Surrogate = function(){ this.constructor = child; }; - Surrogate.prototype = parent.prototype; - child.prototype = new Surrogate(); - - // Add prototype properties (instance properties) to the subclass, - // if supplied. - if (protoProps) _.extend(child.prototype, protoProps); - - // Set a convenience property in case the parent's prototype is needed - // later. - child.__super__ = parent.prototype; - - return child; - }; - - // Expose the extend function - return extend; -}); - -},{}],4:[function(_dereq_,module,exports){ -var AnnotationProvider, StorageProvider, - __hasProp = {}.hasOwnProperty; - -StorageProvider = _dereq_('./storage'); - -AnnotationProvider = (function() { - AnnotationProvider.configure = function(registry) { - if (registry['annotations'] == null) { - registry['annotations'] = new this(registry); - } - return registry.include(StorageProvider); - }; - - function AnnotationProvider(registry) { - this.registry = registry; - } - - AnnotationProvider.prototype.create = function(obj) { - if (obj == null) { - obj = {}; - } - return this._cycle(obj, 'create'); - }; - - AnnotationProvider.prototype.update = function(obj) { - if (obj.id == null) { - throw new TypeError("annotation must have an id for update()"); - } - return this._cycle(obj, 'update'); - }; - - AnnotationProvider.prototype["delete"] = function(obj) { - if (obj.id == null) { - throw new TypeError("annotation must have an id for delete()"); - } - return this._cycle(obj, 'delete'); - }; - - AnnotationProvider.prototype.query = function(query) { - return this.registry['store'].query(query); - }; - - AnnotationProvider.prototype.load = function(query) { - return this.query(query); - }; - - AnnotationProvider.prototype._cycle = function(obj, storeFunc) { - var safeCopy; - safeCopy = $.extend(true, {}, obj); - delete safeCopy._local; - return this.registry['store'][storeFunc](safeCopy).then((function(_this) { - return function(ret) { - var k, v; - for (k in obj) { - if (!__hasProp.call(obj, k)) continue; - v = obj[k]; - if (k !== '_local') { - delete obj[k]; - } - } - $.extend(obj, ret); - return obj; - }; - })(this)); - }; - - return AnnotationProvider; - -})(); - -module.exports = AnnotationProvider; - - -},{"./storage":26}],"annotator":[function(_dereq_,module,exports){ -module.exports=_dereq_('haW+cw'); -},{}],"haW+cw":[function(_dereq_,module,exports){ -var AnnotationProvider, Annotator, Delegator, Editor, Notification, Range, Registry, Util, Viewer, Widget, extend, g, handleError, notification, _Annotator, _ref, _t, - __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, - __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; - -extend = _dereq_('backbone-extend-standalone'); - -Delegator = _dereq_('./class'); + Annotator.prototype._setupWrapper = function() { + this.wrapper = $(this.html.wrapper); + this.element.find('script').remove(); + this.element.wrapInner(this.wrapper); + this.wrapper = this.element.find('.annotator-wrapper'); + return this; + }; -Range = _dereq_('./range'); - -Util = _dereq_('./util'); - -Widget = _dereq_('./widget'); - -Viewer = _dereq_('./viewer'); - -Editor = _dereq_('./editor'); - -Notification = _dereq_('./notification'); - -Registry = _dereq_('./registry'); - -AnnotationProvider = _dereq_('./annotations'); - -_t = Util.TranslationString; - -_Annotator = this.Annotator; - -handleError = function() { - return console.error.apply(console, arguments); -}; - -Annotator = (function(_super) { - __extends(Annotator, _super); - - Annotator.prototype.events = { - ".annotator-adder button click": "onAdderClick", - ".annotator-adder button mousedown": "onAdderMousedown", - ".annotator-hl mouseover": "onHighlightMouseover", - ".annotator-hl mouseout": "startViewerHideTimer" - }; - - Annotator.prototype.html = { - adder: '
', - wrapper: '
' - }; - - Annotator.prototype.options = { - store: null, - readOnly: false, - loadQuery: {} - }; - - Annotator.prototype.plugins = {}; - - Annotator.prototype.editor = null; - - Annotator.prototype.viewer = null; - - Annotator.prototype.selectedRanges = null; - - Annotator.prototype.mouseIsDown = false; - - Annotator.prototype.ignoreMouseup = false; - - Annotator.prototype.viewerHideTimer = null; - - function Annotator(element, options) { - this.onEditAnnotation = __bind(this.onEditAnnotation, this); - this.onAdderClick = __bind(this.onAdderClick, this); - this.onAdderMousedown = __bind(this.onAdderMousedown, this); - this.onHighlightMouseover = __bind(this.onHighlightMouseover, this); - this.checkForEndSelection = __bind(this.checkForEndSelection, this); - this.checkForStartSelection = __bind(this.checkForStartSelection, this); - this.clearViewerHideTimer = __bind(this.clearViewerHideTimer, this); - this.startViewerHideTimer = __bind(this.startViewerHideTimer, this); - this.showViewer = __bind(this.showViewer, this); - this.onEditorSubmit = __bind(this.onEditorSubmit, this); - this.onEditorHide = __bind(this.onEditorHide, this); - this.showEditor = __bind(this.showEditor, this); - Annotator.__super__.constructor.apply(this, arguments); - this.plugins = {}; - Annotator._instances.push(this); - if (!Annotator.supported()) { - return this; - } - Registry.createApp(this, options); - } - - Annotator.extend = extend; - - Annotator.prototype._setupWrapper = function() { - this.wrapper = $(this.html.wrapper); - this.element.find('script').remove(); - this.element.wrapInner(this.wrapper); - this.wrapper = this.element.find('.annotator-wrapper'); - return this; - }; - - Annotator.prototype._setupViewer = function() { - this.viewer = new Annotator.Viewer({ - readOnly: this.options.readOnly - }); - this.viewer.hide().on("edit", this.onEditAnnotation).on("delete", (function(_this) { - return function(annotation) { - _this.viewer.hide(); - _this.publish('beforeAnnotationDeleted', [annotation]); - _this.cleanupAnnotation(annotation); - return _this.annotations["delete"](annotation).done(function() { - return _this.publish('annotationDeleted', [annotation]); - }); - }; - })(this)).addField({ - load: (function(_this) { - return function(field, annotation) { + Annotator.prototype._setupViewer = function() { + var _this = this; + this.viewer = new Annotator.Viewer({ + readOnly: this.options.readOnly + }); + this.viewer.hide().on("edit", this.onEditAnnotation).on("delete", this.onDeleteAnnotation).addField({ + load: function(field, annotation) { if (annotation.text) { - $(field).html(Util.escape(annotation.text)); + $(field).escape(annotation.text); } else { $(field).html("" + (_t('No Comment')) + ""); } return _this.publish('annotationViewerTextField', [field, annotation]); - }; - })(this) - }).element.appendTo(this.wrapper).bind({ - "mouseover": this.clearViewerHideTimer, - "mouseout": this.startViewerHideTimer - }); - return this; - }; - - Annotator.prototype._setupEditor = function() { - this.editor = new Annotator.Editor(); - this.editor.hide().on('hide', this.onEditorHide).on('save', this.onEditorSubmit).addField({ - type: 'textarea', - label: _t('Comments') + '\u2026', - load: function(field, annotation) { - return $(field).find('textarea').val(annotation.text || ''); - }, - submit: function(field, annotation) { - return annotation.text = $(field).find('textarea').val(); - } - }); - this.editor.element.appendTo(this.wrapper); - return this; - }; - - Annotator.prototype._setupDocumentEvents = function() { - $(document).bind({ - "mouseup": this.checkForEndSelection, - "mousedown": this.checkForStartSelection - }); - return this; - }; - - Annotator.prototype._setupDynamicStyle = function() { - var max, sel, style, x; - style = $('#annotator-dynamic-style'); - if (!style.length) { - style = $('').appendTo(document.head); - } - sel = '*' + ((function() { - var _i, _len, _ref, _results; - _ref = ['adder', 'outer', 'notice', 'filter']; - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - x = _ref[_i]; - _results.push(":not(.annotator-" + x + ")"); - } - return _results; - })()).join(''); - max = Util.maxZIndex($(document.body).find(sel)); - max = Math.max(max, 1000); - style.text([".annotator-adder, .annotator-outer, .annotator-notice {", " z-index: " + (max + 20) + ";", "}", ".annotator-filter {", " z-index: " + (max + 10) + ";", "}"].join("\n")); - return this; - }; + } + }).element.appendTo(this.wrapper).bind({ + "mouseover": this.clearViewerHideTimer, + "mouseout": this.startViewerHideTimer + }); + return this; + }; - Annotator.prototype.load = function(query) { - return this.annotations.load(query).then((function(_this) { - return function(annotations, meta) { - return _this.loadAnnotations(annotations); - }; - })(this)); - }; + Annotator.prototype._setupEditor = function() { + this.editor = new Annotator.Editor(); + this.editor.hide().on('hide', this.onEditorHide).on('save', this.onEditorSubmit).addField({ + type: 'textarea', + label: _t('Comments') + '\u2026', + load: function(field, annotation) { + return $(field).find('textarea').val(annotation.text || ''); + }, + submit: function(field, annotation) { + return annotation.text = $(field).find('textarea').val(); + } + }); + this.editor.element.appendTo(this.wrapper); + return this; + }; - Annotator.prototype.destroy = function() { - var idx, name, plugin, _ref; - $(document).unbind({ - "mouseup": this.checkForEndSelection, - "mousedown": this.checkForStartSelection - }); - $('#annotator-dynamic-style').remove(); - this.adder.remove(); - this.viewer.destroy(); - this.editor.destroy(); - this.wrapper.find('.annotator-hl').each(function() { - $(this).contents().insertBefore(this); - return $(this).remove(); - }); - this.wrapper.contents().insertBefore(this.wrapper); - this.wrapper.remove(); - this.element.data('annotator', null); - _ref = this.plugins; - for (name in _ref) { - plugin = _ref[name]; - this.plugins[name].destroy(); - } - this.removeEvents(); - idx = Annotator._instances.indexOf(this); - if (idx !== -1) { - return Annotator._instances.splice(idx, 1); - } - }; + Annotator.prototype._setupDocumentEvents = function() { + $(document).bind({ + "mouseup": this.checkForEndSelection, + "mousedown": this.checkForStartSelection + }); + return this; + }; - Annotator.prototype.getSelectedRanges = function() { - var browserRange, i, normedRange, r, ranges, rangesToIgnore, selection, _i, _len; - selection = Util.getGlobal().getSelection(); - ranges = []; - rangesToIgnore = []; - if (!selection.isCollapsed) { - ranges = (function() { - var _i, _ref, _results; + Annotator.prototype._setupDynamicStyle = function() { + var max, sel, style, x; + style = $('#annotator-dynamic-style'); + if (!style.length) { + style = $('').appendTo(document.head); + } + sel = '*' + ((function() { + var _k, _len2, _ref1, _results; + _ref1 = ['adder', 'outer', 'notice', 'filter']; _results = []; - for (i = _i = 0, _ref = selection.rangeCount; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { - r = selection.getRangeAt(i); - browserRange = new Range.BrowserRange(r); - normedRange = browserRange.normalize().limit(this.wrapper[0]); - if (normedRange === null) { - rangesToIgnore.push(r); - } - _results.push(normedRange); + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + x = _ref1[_k]; + _results.push(":not(.annotator-" + x + ")"); } return _results; - }).call(this); - selection.removeAllRanges(); - } - for (_i = 0, _len = rangesToIgnore.length; _i < _len; _i++) { - r = rangesToIgnore[_i]; - selection.addRange(r); - } - return $.grep(ranges, function(range) { - if (range) { - selection.addRange(range.toRange()); - } - return range; - }); - }; + })()).join(''); + max = util.maxZIndex($(document.body).find(sel)); + max = Math.max(max, 1000); + style.text([".annotator-adder, .annotator-outer, .annotator-notice {", " z-index: " + (max + 20) + ";", "}", ".annotator-filter {", " z-index: " + (max + 10) + ";", "}"].join("\n")); + return this; + }; - Annotator.prototype.setupAnnotation = function(annotation) { - var e, normed, normedRanges, r, root, _i, _j, _len, _len1, _ref; - root = this.wrapper[0]; - normedRanges = []; - _ref = annotation.ranges; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - r = _ref[_i]; - try { - normedRanges.push(Range.sniff(r).normalize(root)); - } catch (_error) { - e = _error; - if (e instanceof Range.RangeError) { - this.publish('rangeNormalizeFail', [annotation, r, e]); - } else { - throw e; + Annotator.prototype.getSelectedRanges = function() { + var browserRange, i, normedRange, r, ranges, rangesToIgnore, selection, _k, _len2; + selection = util.getGlobal().getSelection(); + ranges = []; + rangesToIgnore = []; + if (!selection.isCollapsed) { + ranges = (function() { + var _k, _ref1, _results; + _results = []; + for (i = _k = 0, _ref1 = selection.rangeCount; 0 <= _ref1 ? _k < _ref1 : _k > _ref1; i = 0 <= _ref1 ? ++_k : --_k) { + r = selection.getRangeAt(i); + browserRange = new Range.BrowserRange(r); + normedRange = browserRange.normalize().limit(this.wrapper[0]); + if (normedRange === null) { + rangesToIgnore.push(r); + } + _results.push(normedRange); + } + return _results; + }).call(this); + selection.removeAllRanges(); + } + for (_k = 0, _len2 = rangesToIgnore.length; _k < _len2; _k++) { + r = rangesToIgnore[_k]; + selection.addRange(r); + } + return $.grep(ranges, function(range) { + if (range) { + selection.addRange(range.toRange()); + } + return range; + }); + }; + + Annotator.prototype.createAnnotation = function() { + var annotation; + annotation = {}; + this.publish('beforeAnnotationCreated', [annotation]); + return annotation; + }; + + Annotator.prototype.setupAnnotation = function(annotation, fireEvents) { + var normed, normedRanges, r, root, _k, _l, _len2, _len3, _ref1; + if (fireEvents == null) { + fireEvents = true; + } + root = this.wrapper[0]; + annotation.ranges || (annotation.ranges = this.selectedRanges); + normedRanges = []; + _ref1 = annotation.ranges; + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + r = _ref1[_k]; + try { + normedRanges.push(Range.sniff(r).normalize(root)); + } catch (e) { + if (e instanceof Range.RangeError) { + this.publish('rangeNormalizeFail', [annotation, r, e]); + } else { + throw e; + } } } - } - annotation.quote = []; - annotation.ranges = []; - annotation._local = {}; - annotation._local.highlights = []; - for (_j = 0, _len1 = normedRanges.length; _j < _len1; _j++) { - normed = normedRanges[_j]; - annotation.quote.push($.trim(normed.text())); - annotation.ranges.push(normed.serialize(this.wrapper[0], '.annotator-hl')); - $.merge(annotation._local.highlights, this.highlightRange(normed)); - } - annotation.quote = annotation.quote.join(' / '); - $(annotation._local.highlights).data('annotation', annotation); - return annotation; - }; + annotation.quote = []; + annotation.ranges = []; + annotation.highlights = []; + for (_l = 0, _len3 = normedRanges.length; _l < _len3; _l++) { + normed = normedRanges[_l]; + annotation.quote.push($.trim(normed.text())); + annotation.ranges.push(normed.serialize(this.wrapper[0], '.annotator-hl')); + $.merge(annotation.highlights, this.highlightRange(normed)); + } + annotation.quote = annotation.quote.join(' / '); + $(annotation.highlights).data('annotation', annotation); + if (fireEvents) { + this.publish('annotationCreated', [annotation]); + } + return annotation; + }; - Annotator.prototype.cleanupAnnotation = function(annotation) { - var h, _i, _len, _ref, _ref1; - if (((_ref = annotation._local) != null ? _ref.highlights : void 0) != null) { - _ref1 = annotation._local.highlights; - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - h = _ref1[_i]; - if (h.parentNode != null) { - $(h).replaceWith(h.childNodes); - } + Annotator.prototype.updateAnnotation = function(annotation) { + this.publish('beforeAnnotationUpdated', [annotation]); + this.publish('annotationUpdated', [annotation]); + return annotation; + }; + + Annotator.prototype.deleteAnnotation = function(annotation) { + var h, _k, _len2, _ref1; + _ref1 = annotation.highlights; + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + h = _ref1[_k]; + $(h).replaceWith(h.childNodes); } - delete annotation._local.highlights; - } - return annotation; - }; + this.publish('annotationDeleted', [annotation]); + return annotation; + }; - Annotator.prototype.loadAnnotations = function(annotations) { - var clone, loader; - if (annotations == null) { - annotations = []; - } - loader = (function(_this) { - return function(annList) { - var n, now, _i, _len; + Annotator.prototype.loadAnnotations = function(annotations) { + var clone, loader, + _this = this; + if (annotations == null) { + annotations = []; + } + loader = function(annList) { + var n, now, _k, _len2; if (annList == null) { annList = []; } now = annList.splice(0, 10); - for (_i = 0, _len = now.length; _i < _len; _i++) { - n = now[_i]; - _this.setupAnnotation(n); + for (_k = 0, _len2 = now.length; _k < _len2; _k++) { + n = now[_k]; + _this.setupAnnotation(n, false); } if (annList.length > 0) { return setTimeout((function() { @@ -751,700 +890,510 @@ return _this.publish('annotationsLoaded', [clone]); } }; - })(this); - clone = annotations.slice(); - loader(annotations); - return this; - }; + clone = annotations.slice(); + if (annotations.length) { + loader(annotations); + } + return this; + }; + + Annotator.prototype.dumpAnnotations = function() { + if (this.plugins['Store']) { + return this.plugins['Store'].dumpAnnotations(); + } else { + return console.warn(_t("Can't dump annotations without Store plugin.")); + } + }; + + Annotator.prototype.highlightRange = function(normedRange, cssClass) { + var hl, node, white, _k, _len2, _ref1, _results; + if (cssClass == null) { + cssClass = 'annotator-hl'; + } + white = /^\s*$/; + hl = $(""); + _ref1 = normedRange.textNodes(); + _results = []; + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + node = _ref1[_k]; + if (!white.test(node.nodeValue)) { + _results.push($(node).wrapAll(hl).parent().show()[0]); + } + } + return _results; + }; + + Annotator.prototype.highlightRanges = function(normedRanges, cssClass) { + var highlights, r, _k, _len2; + if (cssClass == null) { + cssClass = 'annotator-hl'; + } + highlights = []; + for (_k = 0, _len2 = normedRanges.length; _k < _len2; _k++) { + r = normedRanges[_k]; + $.merge(highlights, this.highlightRange(r, cssClass)); + } + return highlights; + }; - Annotator.prototype.dumpAnnotations = function() { - if (this.plugins['Store']) { - return this.plugins['Store'].dumpAnnotations(); - } else { - console.warn(_t("Can't dump annotations without Store plugin.")); - return false; - } - }; + Annotator.prototype.addPlugin = function(name, options) { + var klass, _base; + if (this.plugins[name]) { + console.error(_t("You cannot have more than one instance of any plugin.")); + } else { + klass = Annotator.Plugin[name]; + if (typeof klass === 'function') { + this.plugins[name] = new klass(this.element[0], options); + this.plugins[name].annotator = this; + if (typeof (_base = this.plugins[name]).pluginInit === "function") { + _base.pluginInit(); + } + } else { + console.error(_t("Could not load ") + name + _t(" plugin. Have you included the appropriate + @@ -43,7 +44,8 @@ // URL of authentication token server //'annotationTokenUrl' : 'http://localhost:8080/test/annotator/token/getLoginToken', // list of Annotator plugins - 'annotatorPlugins' : ['Auth', 'Permissions', 'Markdown'] + //'annotatorPlugins' : ['Auth', 'Permissions', 'Store', 'Markdown', 'DigilibIntegrator'] + 'annotatorPlugins' : ['Store', 'Markdown', 'DigilibIntegrator'] }; var $div = $('div#digilib'); $div.digilib(opts); diff -r 7d9132a513ab -r 49d643f0d658 webapp/src/main/webapp/jquery/jquery.digilib.annotator-new.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webapp/src/main/webapp/jquery/jquery.digilib.annotator-new.js Fri Jan 16 18:20:15 2015 +0100 @@ -0,0 +1,785 @@ +/* + * #%L + * digilib plugin for annotations. + * %% + * Copyright (C) 2012 - 2013 MPIWG Berlin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + * Authors: Robert Casties, Martin Raspe + */ + +/** + * digilib plugin for annotations. + * + * Currently supported are point-like annotations (like marks) and rectangular region annotations. + * + * Annotations are displayed using code from the Annotator (http://annotatorjs.org) project + * and stored on a Annotator-API compatible server. + */ +(function($) { + + // affine geometry + var geom = null; + // plugin object with digilib data + var digilib = null; + // the functions made available by digilib + var fn = {}; + // the normal zoom area + var FULL_AREA = null; + + var buttons = { + annotations : { + onclick : "toggleAnnotations", + tooltip : "show or hide annotations", + icon : "annotations.png" + }, + annotationuser : { + onclick : "setAnnotationUser", + tooltip : "set user account for annotations", + icon : "annotation-user.png" + }, + annotationmark : { + onclick : "setAnnotationMark", + tooltip : "create an annotation for a point", + icon : "annotation-mark.png" + }, + annotationregion : { + onclick : "setAnnotationRegion", + tooltip : "create an annotation for a region", + icon : "annotation-region.png" + } + }; + + // for defaults see below (we need to define the functions used in annotatorPluginSettings first) + + var actions = { + /** + * show/hide annotations + */ + toggleAnnotations : function (data) { + var show = !data.settings.isAnnotationsVisible; + data.settings.isAnnotationsVisible = show; + fn.highlightButtons(data, 'annotations', show); + renderAnnotations(data); + }, + + /** + * set user account for annotations + */ + setAnnotationUser : function (data, user, password) { + var annotator = data.annotator; + var auth = annotator.plugins.Auth; + if (auth == null) { + console.error("setAnnotationUser: No Auth plugin!!"); + return; + } + // set new user in digilib and Annotator Auth plugin + setAnnotationUser(data, auth, user, password); + // get new token + auth.token = null; + auth._unsafeToken = null; + auth.requestToken(); + // save new token in cookie + auth.withToken(function (tkn) { + data.dlOpts.annotationToken = auth.token; + fn.storeOptions(data); + // reload annotations + reloadAnnotations(data); + }); + }, + + /** + * set a mark-annotation by clicking (or giving a position and a text) + * + * @param data + * @param mpos + * @param text + */ + setAnnotationMark : function (data, mpos, text) { + if (mpos == null) { + // interactive + setAnnotationMark(data); + } else { + // use position and text (and user-id) + console.error("Sorry, currently only interactive annotations!"); + } + }, + + /** + * set a region-annotation by clicking (or giving a position and a text) + * + * @param data + * @param rect + * @param text + */ + setAnnotationRegion : function (data, rect, text) { + if (rect == null) { + // interactive + setAnnotationRegion(data); + } else { + // use position and text (and user-id) + console.error("Sorry, currently only interactive annotations!"); + } + } + }; + + /** + * install additional buttons + */ + var installButtons = function(data, buttonSet) { + var settings = data.settings; + var mode = settings.interactionMode; + var buttonSettings = settings.buttonSettings[mode]; + // set annotationSet to [] or '' for no buttons (when showing annotations only) + if (buttonSet.length && buttonSet.length > 0) { + buttonSettings.annotationSet = buttonSet; + buttonSettings.buttonSets.push('annotationSet'); + } + }; + + + /** + * returns an annotatable uri to this digilib image + */ + var getAnnotationPageUri = function(data) { + var settings = data.settings; + var uri = settings.annotationPageUri; + if (uri == null) { + // default uri with digilibBaseUrl + uri = settings.digilibBaseUrl + settings.digilibFrontendPath; + uri += '?' + fn.getParamString(data.settings, ['fn', 'pn'], digilib.defaults); + } else if (typeof uri === 'function') { + // call function + uri = uri(data); + } + return uri; + }; + + /** + * Set annotation user and password in digilib and Annotator.Auth plugin. + * + * @param auth Auth plugin instance. + * @param user user name (optional) + * @param password password (optional) + */ + var setAnnotationUser = function (data, auth, user, password) { + if (user == null) { + // user name entered in JS-prompt + user = window.prompt("Please authenticate (Cancel to log out): User name", data.settings.annotationUser); + if (user != null && user != 'anonymous') { + // password entered in JS-prompt + password = window.prompt("Please authenticate: Password", ''); + // set params for Auth plugin + auth.options.requestData.password = password; + // try to use the safe url for the password + if (data.settings.annotationSafeTokenUrl != null) { + auth.options.tokenUrl = data.settings.annotationSafeTokenUrl; + } else { + console.warn("Sending token password over standard-URL!"); + } + } else { + // use anonymous user + user = 'anonymous'; + delete auth.options.requestData.password; + if (data.settings.annotationSafeTokenUrl != null) { + // reset url to unsafe + auth.options.tokenUrl = data.settings.annotationTokenUrl; + } + } + } + // set user in digilib + data.settings.annotationUser = user; + data.dlOpts.annotationUser = user; + fn.storeOptions(data); + // set params for Auth plugin + auth.options.requestData.user = user; + // set params for Permissions plugin + var perms = data.annotator.plugins.Permissions; + if (perms != null) { + perms.setUser(user); + } + }; + + + /** + * add a mark-annotation where clicked. + */ + var setAnnotationMark = function(data) { + var $scaler = data.$scaler; + // start event capturing + $scaler.one('mousedown.dlSetAnnotationMark', function (evt) { + // event handler adding a new mark + console.log("setAnnotationMark at=", evt); + var mpos = geom.position(evt); + var pos = data.imgTrafo.invtransform(mpos); + // mark selection shape + var shape = {'type' : 'point', 'units' : 'fraction', 'geometry' : geom.position(pos)}; + // create and edit new annotation + createAnnotation(data, shape, mpos.getAsCss()); + return false; + }); + }; + + /** + * Add a region-annotation where clicked. + */ + var setAnnotationRegion = function (data) { + fn.defineArea(data, function (data, rect) { + if (rect == null) return; + // event handler adding a new mark + console.log("setAnnotationRegion at=", rect); + // mark selection shape + var shape = {'type' : 'rectangle', 'units' : 'fraction', 'geometry' : rect}; + var pos = rect.getPt1(); + var mpos = data.imgTrafo.transform(pos); + // create and edit new annotation + createAnnotation(data, shape, mpos.getAsCss()); + }); + }; + + /** + * create an empty annotation with the given shape, show the editor at the given position, + * and store the annotation using Annotator. + * + * @param shape shape object + * @param editorPos css position object + * @returns promise + */ + var createAnnotation = function (data, shape, editorPos) { + var annotator = data.annotator; + var annotation = {'shapes' : [shape]}; + annotator.publish('beforeAnnotationCreated', [annotation]); + annotator.setupAnnotation(annotation); + // edit the annotation (returns a promise) + var dfd = annotator.editAnnotation(annotation, editorPos); + dfd.then(function (annotation) { + // store annotation (returns deferred) + return annotator.annotations.create(annotation) + // handle storage errors + .fail(function () { + console.error("Error storing annotation!"); + // TODO: more error handling? + }); + }); + dfd.done(function (annotation) { + annotator.publish('annotationCreated', [annotation]); + }); + // clean up (if, for example, editing was cancelled, or storage failed) + dfd.fail(function (annotation) { + console.warn("Editing annotation cancelled!"); + deleteAnnotation(data, annotation); + }); + return dfd; + }; + + /** + * Render all annotations on the image. + */ + var renderAnnotations = function (data) { + if (data.annotations == null || data.annotator == null || data.$img == null || data.imgTrafo == null) + return; + var annotations = data.annotations; + var cssPrefix = data.settings.cssPrefix; + var $elem = data.$elem; + // show annotation user state + $elem.find('div#'+cssPrefix+'button-annotationuser').attr('title', 'annotation user: '+data.settings.annotationUser); + // clear annotations + $elem.find('div.'+cssPrefix+'annotationmark,div.'+cssPrefix+'annotationregion').remove(); + if (!data.settings.isAnnotationsVisible) return; + // re-render + for (var i = 0; i < annotations.length; i++) { + renderAnnotation(data, annotations[i]); + } + }; + + /** + * Render a single annotation on the image. + * + * @param annot annotation wrapper object + */ + var renderAnnotation = function (data, annot) { + if (annot == null || annot.annotation == null || data.$img == null || data.imgTrafo == null) + return; + if (!data.settings.isAnnotationsVisible) return; + var cssPrefix = data.settings.cssPrefix; + var $elem = data.$elem; + var annotator = data.annotator; + var annotation = annot.annotation; + var idx = ''; + if (data.settings.showAnnotationNumbers) { + // show annotation number + idx = annot.idx ? annot.idx : '?'; + } + var shape = null; + var area = null; + var type = null; + if (annotation.shapes != null) { + // annotation shape + shape = annotation.shapes[0]; + type = shape.type; + if (type === "point") { + area = geom.position(shape.geometry); + } else if (type === "rectangle") { + area = geom.rectangle(shape.geometry); + } else { + console.error("Unsupported shape type="+type); + return; + } + } else if (annotation.areas != null) { + // legacy annotation areas + shape = annotation.areas[0]; + area = geom.rectangle(shape); + if (area.isRectangle()) { + type = 'rectangle'; + } else { + type = 'point'; + } + } else { + console.error("Unable to render this annotation!"); + return; + } + var screenRect = null; + var $annotation = null; + if (type === 'rectangle') { + // render rectangle + var clippedArea = data.zoomArea.intersect(area); + if (clippedArea == null) return; + screenRect = data.imgTrafo.transform(clippedArea); + $annotation = $('
'+idx+'
'); + } else { + // render point + if (!data.zoomArea.containsPosition(area)) return; + screenRect = data.imgTrafo.transform(area); + // create annotation + var html = '
'+idx+'
'; + $annotation = $(html); + } + // save annotation in data for Annotator + $annotation.data('annotation', annotation); + $annotation.data('rect', area); + // add shared css class from annotations collection + if (annotation.cssclass != null) { + $annotation.addClass(annotation.cssclass); + } + // add individual css class from this annotation + if (shape.cssclass != null) { + $annotation.addClass(shape.cssclass); + } + // save reference to div + annot.$div = $annotation; + $elem.append($annotation); + // hook up Annotator events + $annotation.on("mouseover", annotator.onHighlightMouseover); + $annotation.on("mouseout", annotator.startViewerHideTimer); + $annotation.on('click.dlAnnotation', function(event) { + $(data).trigger('annotationClick', [$annotation]); + }); + screenRect.adjustDiv($annotation); + }; + + + /** + * Delete annotation from digilib. + * + * Finds the corresponding digilib annotation wrapper, removes any elements from screen, + * and deletes the wrapper from the list. + * + * @param annotation the annotation object to delete. + */ + var deleteAnnotation = function (data, annotation) { + // remove annotation mark + var annots = data.annotations; + for (var i = 0; i < annots.length; ++i) { + var annot = annots[i]; + if (annot.annotation === annotation) { + // this is the right wrapper + if (annot.$div != null) { + // remove from screen + annot.$div.remove(); + } + // remove from list + annots.splice(i, 1); + break; + } + } + }; + + + /** + * Reload annotations for current page. + */ + var reloadAnnotations = function (data) { + // clear annotations + data.annotations = []; + renderAnnotations(data); + // reload annotations + data.annotator.load(data.annotatorLoadQuery); + }; + + + /** + * Our modified version of Annotator. + */ + var DigilibAnnotator = Annotator.extend({ + /** + * Set digilib data object in Annotator + */ + 'setDigilibData' : function (data) { + // set digilib data in options + this.options.digilibData = data; + }, + /** + * Initialises an annotation from an object representation. + * Overwrites Annotator.setupAnnotation(). + * + * Checks for image annotations, creates a wrapper, adds wrapper to list, + * and renders the annotation. + */ + 'setupAnnotation' : function (annotation) { + // digilibData has to be set in the options + var data = this.options.digilibData; + // is this a digilib image annotation? + if (annotation.shapes != null || annotation.areas != null) { + // create annotation wrapper + var ann = { + 'annotation' : annotation, + 'idx' : data.annotations.length+1 + }; + // add to list + data.annotations.push(ann); + // render this annotation + renderAnnotation(data, ann); + } else { + // Invoke the built-in implementation + Annotator.prototype.setupAnnotation.call(this, annotation); + } + return annotation; + }, + /** + * Handler for annotationDeleted event for digilib annotations. + */ + 'onDigilibAnnotationDeleted' : function (annotation) { + // remove digilib annotation + var data = this.options.digilibData; + deleteAnnotation(data, annotation); + } + }); + + + /** + * returns unauthorizedCallback function for Annotator authlogin plugin. + */ + var getHandleUnauthorized = function (data) { + return function (auth) { + // prompt for user name and set user + setAnnotationUser(data, auth); + // then try again + return true; + }; + }; + + /** + * returns the annotation server URL. + */ + var getAnnotationServerUrl = function (data) { + return data.settings.annotationServerUrl; + }; + + /** + * returns the annotation token URL. + */ + var getAnnotationTokenUrl = function (data) { + return data.settings.annotationTokenUrl; + }; + + /** + * returns the cached annotation token. + */ + var getAnnotationToken = function (data) { + return data.dlOpts.annotationToken; + }; + + /** + * returns the annotation user. + */ + var getAnnotationUser = function (data) { + return data.settings.annotationUser; + }; + + + /** + * zoom in and display the annotation in the middle of the screen. + */ + var zoomToAnnotation = function (data, $div) { + var settings = data.settings; + var rect = $div.data('rect'); + var za = geom.rectangle(rect); + var w = settings.annotationAutoWidth; + if (za.width == null || za.width == 0) za.width = w; + if (za.height == null || za.height == 0) za.height = w; + var factor = settings.annotationAutoZoomFactor; + za.width *= factor; + za.height *= factor; + za.setProportion(1, true); // avoid extreme zoomArea proportions + if (rect.width != null) { + za.setCenter(rect.getCenter()).stayInside(FULL_AREA); + } + fn.setZoomArea(data, za); + fn.redisplay(data); + }; + + + /** + * event handler, gets called when a annotationClick event is triggered + */ + var handleAnnotationClick = function (evt, $div) { + var data = this; + var settings = data.settings; + console.debug("annotations: handleAnnotationClick", $div); + if (typeof settings.annotationOnClick === 'function') { + // execute callback + return settings.annotationOnClick(data, $div); + } + if (typeof settings.annotationOnClick === 'string') { + // execute action + return actions[settings.annotationOnClick](data, $div); + } + }; + + + var defaults = { + // are annotations active? + 'isAnnotationsVisible' : true, + // buttonset of this plugin + 'annotationSet' : ['annotations', 'annotationuser', 'annotationmark', 'annotationregion', 'lessoptions'], + 'annotationReadOnlySet' : ['annotations', 'lessoptions'], + // URL of annotation server .e.g. 'http://tuxserve03.mpiwg-berlin.mpg.de/AnnotationManager/annotator' + 'annotationServerUrl' : null, + // show numbers in rectangle annotations + 'showAnnotationNumbers' : true, + // default width for annotation when only point is given + 'annotationAutoWidth' : 0.005, + // zoomfactor for displaying larger area around region (for autoZoomOnClick) + 'annotationAutoZoomFactor' : 3, + // zoom in and center on click on the annotation area + 'annotationOnClick' : zoomToAnnotation, + // are the annotations read-only + 'annotationsReadOnly' : false, + // URL of authentication token server e.g. 'http://libcoll.mpiwg-berlin.mpg.de/libviewa/template/token' + 'annotationTokenUrl' : null, + // URL of safe authentication token server e.g. 'https://libcoll.mpiwg-berlin.mpg.de/libviewa/template/token' + 'annotationSafeTokenUrl' : null, + // annotation user name + 'annotationUser' : 'anonymous', + // string or function that returns the uri of the page being annotated + 'annotationPageUri' : null, + // list of Annotator plugins + 'annotatorPlugins' : ['Auth', 'Permissions'], + // Annotator plugin settings (values that are functions are replaced by fn(data)) + 'annotatorPluginSettings' : { + 'Auth' : { + 'token' : getAnnotationToken, + 'tokenUrl' : getAnnotationTokenUrl, + 'autoFetch' : true, + 'requestMethod' : 'POST', + 'requestData' : { + 'user': getAnnotationUser + }, + 'unauthorizedCallback' : getHandleUnauthorized + }, + 'Permissions' : { + 'user' : getAnnotationUser, + // userString and userId have to remain functions after evaluation + 'userString' : function (data) { + return function(user) { + if (user && user.name) { + return user.name; + } + return user; + }; + }, + 'userId' : function (data) { + return function(user) { + if (user && user.id) { + return user.id; + } + return user; + }; + } + } + } + }; + + /** + * plugin installation. called by digilib on plugin object. + */ + var install = function(plugin) { + digilib = plugin; + console.debug('installing annotator plugin. digilib:', digilib); + // import digilib functions + $.extend(fn, digilib.fn); + // import geometry classes + geom = fn.geometry; + // add defaults, actions, buttons + $.extend(digilib.defaults, defaults); + $.extend(digilib.actions, actions); + $.extend(digilib.buttons, buttons); + }; + + /** plugin initialization */ + var init = function(data) { + console.debug('initialising annotator plugin. data:', data); + var $data = $(data); + var settings = data.settings; + FULL_AREA = geom.rectangle(0, 0, 1, 1); + // set up list of annotation wrappers + data.annotations = []; + // set up buttons + if (digilib.plugins.buttons != null) { + if (settings.annotationsReadOnly) { + installButtons(data, settings.annotationReadOnlySet); + } else { + installButtons(data, settings.annotationSet); + } + } + if (data.dlOpts.annotationUser != null) { + // get annotation user from cookie + settings.annotationUser = data.dlOpts.annotationUser; + } + // install event handler + $data.bind('setup', handleSetup); + $data.bind('redisplay', handleRedisplay); + $data.bind('update', handleUpdate); + $data.on('annotationClick', handleAnnotationClick); + }; + + /** + * setup creates Annotator object (after HTML setup by digilib). + */ + var handleSetup = function(evt) { + console.debug("annotations: handleSetup"); + var data = this; + var settings = data.settings; + // set up annotator (after html has been set up) + var uri = getAnnotationPageUri(data); + var elem = data.$elem.get(0); + var opts = { + 'store' : { + 'type' : Annotator.Plugin.Store, + 'prefix' : getAnnotationServerUrl(data), + 'annotationData' : {'uri' : uri} + }, + 'loadQuery' : null, + 'readOnly' : data.settings.annotationsReadOnly, + }; + console.debug("creating annotator."); + var annotator = new DigilibAnnotator(elem, opts); + annotator.setDigilibData(data); + // save annotator reference + data.annotator = annotator; + // set plugin parameters + var pluginParams = {}; + // merge settings + // (deep copy of defaults from plugin and options from HTML) + $.extend(true, pluginParams, defaults.annotatorPluginSettings, data.options.annotatorPluginSettings); + // function to evaluate plugin settings + var evalParams = function (params) { + if (params == null) return; + // eval functions in params + $.each(params, function (idx, param) { + if (typeof param === 'function') { + // replace function by value + params[idx] = param(data); + } else if (param == null) { + // delete value null + delete params[idx]; + } else if (typeof param === 'object') { + // evaluate sub-objects + evalParams(param); + } + }); + }; + // add plugins + $.each(settings.annotatorPlugins, function (idx, name) { + // ignore Store plugin (added by Annotator constructor) + if (name === 'Store') return; + var params = pluginParams[name]; + evalParams(params); + console.debug("plugin:", name, params); + annotator.addPlugin(name, params); + }); + // subscribe annotation delete event + annotator.subscribe("annotationDeleted", annotator.onDigilibAnnotationDeleted); + // save annotation token in cookie + var auth = annotator.plugins.Auth; + if (auth != null) { + auth.withToken(function (tkn) { + data.dlOpts.annotationToken = auth.token; + fn.storeOptions(data); + }); + } + // load annotations + var query = {'uri' : uri}; + annotator.load(query); + data.annotatorLoadQuery = query; + }; + + + /** + * redisplay checks if the page has changes and reloads all annotations. + */ + var handleRedisplay = function(evt) { + console.debug("annotations: handleRedisplay"); + var data = this; + var uri = getAnnotationPageUri(data); + if (uri != data.annotatorLoadQuery.uri) { + // uri changed + data.annotatorLoadQuery.uri = uri; + reloadAnnotations(data); + } + }; + + + /** + * update renders all annotations. + */ + var handleUpdate = function(evt) { + console.debug("annotations: handleUpdate"); + var data = this; + renderAnnotations(data); + }; + + // plugin object with name and init + // shared objects filled by digilib on registration + var plugin = { + name : 'annotator', + install : install, + init : init, + buttons : {}, + actions : {}, + fn : {}, + plugins : {} + }; + + if (Annotator == null) { + $.error("Annotator.js Javascript not found!"); + } + if ($.fn.digilib == null) { + $.error("jquery.digilib.annotator must be loaded after jquery.digilib!"); + } else { + $.fn.digilib('plugin', plugin); + } +})(jQuery); diff -r 7d9132a513ab -r 49d643f0d658 webapp/src/main/webapp/jquery/jquery.digilib.annotator.js --- a/webapp/src/main/webapp/jquery/jquery.digilib.annotator.js Mon Dec 15 18:49:42 2014 +0100 +++ b/webapp/src/main/webapp/jquery/jquery.digilib.annotator.js Fri Jan 16 18:20:15 2015 +0100 @@ -30,6 +30,8 @@ * and stored on a Annotator-API compatible server. */ (function($) { + // version of this plugin + var version = 'jquery.digilib.annotator.js 1.2.0'; // affine geometry var geom = null; @@ -96,8 +98,11 @@ auth.withToken(function (tkn) { data.dlOpts.annotationToken = auth.token; fn.storeOptions(data); - // reload annotations - reloadAnnotations(data); + // clear annotations + data.annotations = []; + renderAnnotations(data); + // reload annotations + annotator.plugins.Store.pluginInit(); }); }, @@ -223,12 +228,15 @@ $scaler.one('mousedown.dlSetAnnotationMark', function (evt) { // event handler adding a new mark console.log("setAnnotationMark at=", evt); + var annotator = data.annotator; var mpos = geom.position(evt); var pos = data.imgTrafo.invtransform(mpos); // mark selection shape var shape = {'type' : 'point', 'units' : 'fraction', 'geometry' : geom.position(pos)}; + annotator.selectedShapes = [shape]; // create and edit new annotation - createAnnotation(data, shape, mpos.getAsCss()); + var annotation = annotator.createAnnotation(); + annotator.showEditor(annotation, mpos.getAsCss()); return false; }); }; @@ -236,57 +244,25 @@ /** * Add a region-annotation where clicked. */ - var setAnnotationRegion = function (data) { + var setAnnotationRegion = function(data) { + var annotator = data.annotator; fn.defineArea(data, function (data, rect) { if (rect == null) return; // event handler adding a new mark console.log("setAnnotationRegion at=", rect); // mark selection shape var shape = {'type' : 'rectangle', 'units' : 'fraction', 'geometry' : rect}; + annotator.selectedShapes = [shape]; + // create and edit new annotation var pos = rect.getPt1(); var mpos = data.imgTrafo.transform(pos); - // create and edit new annotation - createAnnotation(data, shape, mpos.getAsCss()); + var annotation = annotator.createAnnotation(); + annotator.showEditor(annotation, mpos.getAsCss()); }); }; /** - * create an empty annotation with the given shape, show the editor at the given position, - * and store the annotation using Annotator. - * - * @param shape shape object - * @param editorPos css position object - * @returns promise - */ - var createAnnotation = function (data, shape, editorPos) { - var annotator = data.annotator; - var annotation = {'shapes' : [shape]}; - annotator.publish('beforeAnnotationCreated', [annotation]); - annotator.setupAnnotation(annotation); - // edit the annotation (returns a promise) - var dfd = annotator.editAnnotation(annotation, editorPos); - dfd.then(function (annotation) { - // store annotation (returns deferred) - return annotator.annotations.create(annotation) - // handle storage errors - .fail(function () { - console.error("Error storing annotation!"); - // TODO: more error handling? - }); - }); - dfd.done(function (annotation) { - annotator.publish('annotationCreated', [annotation]); - }); - // clean up (if, for example, editing was cancelled, or storage failed) - dfd.fail(function (annotation) { - console.warn("Editing annotation cancelled!"); - deleteAnnotation(data, annotation); - }); - return dfd; - }; - - /** - * Render all annotations on the image. + * Render all annotations on the image */ var renderAnnotations = function (data) { if (data.annotations == null || data.annotator == null || data.$img == null || data.imgTrafo == null) @@ -390,95 +366,46 @@ screenRect.adjustDiv($annotation); }; - - /** - * Delete annotation from digilib. - * - * Finds the corresponding digilib annotation wrapper, removes any elements from screen, - * and deletes the wrapper from the list. - * - * @param annotation the annotation object to delete. - */ - var deleteAnnotation = function (data, annotation) { - // remove annotation mark - var annots = data.annotations; - for (var i = 0; i < annots.length; ++i) { - var annot = annots[i]; - if (annot.annotation === annotation) { - // this is the right wrapper - if (annot.$div != null) { - // remove from screen - annot.$div.remove(); - } - // remove from list - annots.splice(i, 1); - break; - } - } - }; - - - /** - * Reload annotations for current page. - */ - var reloadAnnotations = function (data) { - // clear annotations - data.annotations = []; - renderAnnotations(data); - // reload annotations - data.annotator.load(data.annotatorLoadQuery); - }; + /** + * returns setupAnnotation function using the given data. + */ + var getSetupAnnotation = function(data) { + return function (annotation) { + // create annotation wrapper + var ann = { + 'annotation' : annotation, + 'idx' : data.annotations.length+1 + }; + // add to list + data.annotations.push(ann); + // render this annotation + renderAnnotation(data, ann); + }; + }; - - /** - * Our modified version of Annotator. - */ - var DigilibAnnotator = Annotator.extend({ - /** - * Set digilib data object in Annotator - */ - 'setDigilibData' : function (data) { - // set digilib data in options - this.options.digilibData = data; - }, - /** - * Initialises an annotation from an object representation. - * Overwrites Annotator.setupAnnotation(). - * - * Checks for image annotations, creates a wrapper, adds wrapper to list, - * and renders the annotation. - */ - 'setupAnnotation' : function (annotation) { - // digilibData has to be set in the options - var data = this.options.digilibData; - // is this a digilib image annotation? - if (annotation.shapes != null || annotation.areas != null) { - // create annotation wrapper - var ann = { - 'annotation' : annotation, - 'idx' : data.annotations.length+1 - }; - // add to list - data.annotations.push(ann); - // render this annotation - renderAnnotation(data, ann); - } else { - // Invoke the built-in implementation - Annotator.prototype.setupAnnotation.call(this, annotation); - } - return annotation; - }, - /** - * Handler for annotationDeleted event for digilib annotations. - */ - 'onDigilibAnnotationDeleted' : function (annotation) { - // remove digilib annotation - var data = this.options.digilibData; - deleteAnnotation(data, annotation); - } - }); - - + /** + * returns annotationDeleted function using the given data. + */ + var getAnnotationDeleted = function(data) { + return function (annotation) { + // remove annotation mark + var annots = data.annotations; + for (var i = 0; i < annots.length; ++i) { + var annot = annots[i]; + if (annot.annotation === annotation) { + // this is the right wrapper + if (annot.$div != null) { + // remove from screen + annot.$div.remove(); + } + // remove from list + delete annots[i]; + break; + } + } + }; + }; + /** * returns unauthorizedCallback function for Annotator authlogin plugin. */ @@ -587,7 +514,7 @@ // string or function that returns the uri of the page being annotated 'annotationPageUri' : null, // list of Annotator plugins - 'annotatorPlugins' : ['Auth', 'Permissions'], + 'annotatorPlugins' : ['Auth', 'Permissions', 'Store', 'DigilibIntegrator'], // Annotator plugin settings (values that are functions are replaced by fn(data)) 'annotatorPluginSettings' : { 'Auth' : { @@ -619,6 +546,21 @@ return user; }; } + }, + 'Store' : { + 'prefix' : getAnnotationServerUrl, + 'annotationData': { + 'uri': getAnnotationPageUri + }, + 'loadFromSearch': { + 'uri': getAnnotationPageUri + } + }, + 'DigilibIntegrator' : { + 'hooks' : { + 'setupAnnotation' : getSetupAnnotation, + 'annotationDeleted' : getAnnotationDeleted + } } } }; @@ -661,7 +603,6 @@ } // install event handler $data.bind('setup', handleSetup); - $data.bind('redisplay', handleRedisplay); $data.bind('update', handleUpdate); $data.on('annotationClick', handleAnnotationClick); }; @@ -676,21 +617,10 @@ // set up annotator (after html has been set up) var uri = getAnnotationPageUri(data); var elem = data.$elem.get(0); - var opts = { - 'store' : { - 'type' : Annotator.Plugin.Store, - 'prefix' : getAnnotationServerUrl(data), - 'annotationData' : {'uri' : uri} - }, - 'loadQuery' : null, - 'readOnly' : data.settings.annotationsReadOnly, - }; - console.debug("creating annotator."); - var annotator = new DigilibAnnotator(elem, opts); - annotator.setDigilibData(data); - // save annotator reference - data.annotator = annotator; + var opts = {'readOnly' : data.settings.annotationsReadOnly}; + var annotator = new Annotator(elem, opts); // set plugin parameters + var def = defaults.annotatorPluginSettings; var pluginParams = {}; // merge settings // (deep copy of defaults from plugin and options from HTML) @@ -714,15 +644,13 @@ }; // add plugins $.each(settings.annotatorPlugins, function (idx, name) { - // ignore Store plugin (added by Annotator constructor) - if (name === 'Store') return; var params = pluginParams[name]; evalParams(params); console.debug("plugin:", name, params); annotator.addPlugin(name, params); }); - // subscribe annotation delete event - annotator.subscribe("annotationDeleted", annotator.onDigilibAnnotationDeleted); + // save annotator reference + data.annotator = annotator; // save annotation token in cookie var auth = annotator.plugins.Auth; if (auth != null) { @@ -731,28 +659,8 @@ fn.storeOptions(data); }); } - // load annotations - var query = {'uri' : uri}; - annotator.load(query); - data.annotatorLoadQuery = query; }; - - /** - * redisplay checks if the page has changes and reloads all annotations. - */ - var handleRedisplay = function(evt) { - console.debug("annotations: handleRedisplay"); - var data = this; - var uri = getAnnotationPageUri(data); - if (uri != data.annotatorLoadQuery.uri) { - // uri changed - data.annotatorLoadQuery.uri = uri; - reloadAnnotations(data); - } - }; - - /** * update renders all annotations. */