Mercurial > hg > digilib-old
annotate webapp/src/main/webapp/jquery/jquery.digilib.annotator.js @ 1115:526dafa4690d
using annotator in digilib works now. code still ugly.
author | robcast |
---|---|
date | Fri, 02 Nov 2012 20:49:51 +0100 |
parents | 1525c820ee27 |
children | 08206603c7dc |
rev | line source |
---|---|
1113 | 1 /** |
2 digilib plugin for annotations. | |
3 | |
4 currently only point-like annotations (like marks). | |
5 | |
6 Annotations are stored on a Annotator http://annotateit.org compatible server. | |
7 | |
8 */ | |
9 | |
10 (function($) { | |
11 | |
12 // affine geometry | |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
13 var geom = null; |
1113 | 14 // plugin object with digilib data |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
15 var digilib = null; |
1113 | 16 // our Annotator instance |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
17 var annotator = null; |
1113 | 18 |
19 var buttons = { | |
20 annotations : { | |
21 onclick : "toggleAnnotations", | |
22 tooltip : "show or hide annotations", | |
23 icon : "annotations.png" | |
24 }, | |
25 annotationuser : { | |
26 onclick : "setAnnotationUser", | |
27 tooltip : "set user account for annotations", | |
28 icon : "annotation-user.png" | |
29 }, | |
30 annotationmark : { | |
31 onclick : "setAnnotationMark", | |
32 tooltip : "create an annotation for a point", | |
33 icon : "annotation-mark.png" | |
34 } | |
35 }; | |
36 | |
37 var defaults = { | |
38 // are annotations active? | |
39 'isAnnotationsVisible' : true, | |
40 // buttonset of this plugin | |
41 'annotationSet' : ['annotations', 'annotationuser', 'annotationmark', 'lessoptions'], | |
42 // URL of annotation server | |
43 'annotationServerUrl' : 'http://virtuoso.mpiwg-berlin.mpg.de:8080/AnnotationManager/annotator', | |
44 // URL of authentication token server | |
45 'annotationTokenUrl' : 'http://localhost:8080/test/annotator/token', | |
46 // annotation user name | |
47 'annotationUser' : 'anonymous', | |
48 // function to translate user name from annotation server format | |
49 'annotationServerUserString' : function() { | |
50 if (this.user && this.user.name) { | |
51 return this.user.name; | |
52 } | |
53 return this.user; | |
54 }, | |
55 | |
56 }; | |
57 | |
58 var actions = { | |
59 /** | |
60 * show/hide annotations | |
61 */ | |
62 toggleAnnotations : function (data) { | |
63 var show = !data.settings.isAnnotationsVisible; | |
64 data.settings.isAnnotationsVisible = show; | |
65 digilib.fn.highlightButtons(data, 'annotations', show); | |
66 renderAnnotations(data); | |
67 }, | |
68 | |
69 /** | |
70 * set user account for annotations | |
71 */ | |
72 setAnnotationUser : function (data, user, password) { | |
73 var settings = data.settings; | |
74 if (user == null) { | |
75 // user name entered in JS-prompt | |
76 user = window.prompt("User name:", settings.annotationUser); | |
77 if (user != null) { | |
78 // password entered in JS-prompt | |
79 password = window.prompt("Password:", ''); | |
80 settings.annotationUser = user; | |
81 data.dlOpts.annotationUser = user; | |
82 digilib.fn.storeOptions(data); | |
83 loadAnnotationToken(data, password); | |
84 } | |
85 } else { | |
86 settings.annotationUser = user; | |
87 data.dlOpts.annotationUser = user; | |
88 digilib.fn.storeOptions(data); | |
89 loadAnnotationToken(data, password); | |
90 } | |
91 }, | |
92 | |
93 /** | |
94 * set a mark-annotation by clicking (or giving a position and a text) | |
95 * | |
96 * @param data | |
97 * @param mpos | |
98 * @param text | |
99 */ | |
100 setAnnotationMark : function (data, mpos, text) { | |
101 if (mpos == null) { | |
102 // interactive | |
103 setAnnotationMark(data); | |
104 } else { | |
105 // use position and text (and user-id) | |
106 var annotation = newAnnotation(data, mpos, text, null, null, data.settings.annotationUser); | |
107 storeAnnotation(data, annotation); | |
108 // TODO: replace with annotation returned by server | |
109 data.annotations.push(annotation); | |
110 digilib.fn.redisplay(data); | |
111 } | |
112 }, | |
113 }; | |
114 | |
115 /** | |
116 * returns an annotatable url to this digilib image | |
117 */ | |
118 var getAnnotationPageUrl = function(data) { | |
119 var url = data.settings.digilibBaseUrl + '/jquery/digilib.html?'; | |
120 url += digilib.fn.getParamString(data.settings, ['fn', 'pn'], digilib.defaults); | |
121 return url; | |
122 }; | |
123 | |
124 /** | |
125 * add a mark-annotation where clicked. | |
126 */ | |
127 var setAnnotationMark = function(data) { | |
128 var $scaler = data.$scaler; | |
129 // unbind other handler TODO: do we need to do this? | |
130 $scaler.off(".dlZoomDrag"); | |
131 // start event capturing | |
132 $scaler.one('mousedown.dlSetAnnotationMark', function(evt) { | |
133 // event handler adding a new mark | |
134 console.log("setAnnotationMark at=", evt); | |
135 var mpos = geom.position(evt); | |
136 var pos = data.imgTrafo.invtransform(mpos); | |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
137 // mark selected areas |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
138 annotator.selectedAreas = [geom.rectangle(pos)]; |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
139 // create and edit new annotation |
1113 | 140 var annotation = annotator.createAnnotation(); |
141 annotator.showEditor(annotation, mpos.getAsCss()); | |
142 return false; | |
143 }); | |
144 }; | |
145 | |
146 /** | |
147 * place annotations on the image | |
148 */ | |
1114 | 149 var renderAnnotations = function (data) { |
1113 | 150 console.debug("renderAnnotations: annotator=", annotator); |
151 if (annotator == null || data.$img == null || data.imgTrafo == null) | |
152 return; | |
153 var annotations = annotator.plugins['Store'].annotations; | |
154 var cssPrefix = data.settings.cssPrefix; | |
155 var $elem = data.$elem; | |
156 // try to show annotation user state | |
157 $elem.find('div#'+cssPrefix+'button-annotationuser').attr('title', 'annotation user: '+data.settings.annotationUser); | |
158 // clear annotations | |
159 $elem.find('div.' + cssPrefix + 'annotationmark').remove(); | |
160 if (!data.settings.isAnnotationsVisible) return; | |
161 for (var i = 0; i < annotations.length; i++) { | |
162 var annotation = annotations[i]; | |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
163 annotation.idx = i+1; |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
164 renderAnnotation(data, annotation); |
1113 | 165 } |
166 }; | |
167 | |
168 /** | |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
169 * place single annotation on the image |
1113 | 170 */ |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
171 var renderAnnotation = function (data, annotation) { |
1113 | 172 console.debug("renderAnnotation: annotation=", annotation); |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
173 if (annotation == null || annotation.areas == null || data.$img == null || data.imgTrafo == null) |
1113 | 174 return; |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
175 if (!data.settings.isAnnotationsVisible) return; |
1113 | 176 var cssPrefix = data.settings.cssPrefix; |
177 var $elem = data.$elem; | |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
178 var idx = annotation.idx; |
1114 | 179 if (idx == null) idx = '?'; |
1113 | 180 var pos = geom.position(annotation.areas[0]); |
181 if (data.zoomArea.containsPosition(pos)) { | |
182 var mpos = data.imgTrafo.transform(pos); | |
183 console.debug("renderannotations: pos=", mpos); | |
184 // create annotation | |
1114 | 185 var html = '<div class="'+cssPrefix+'annotationmark '+cssPrefix+'overlay annotator-hl">'+idx+'</div>'; |
1113 | 186 var $annotation = $(html); |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
187 // save annotation in data for Annotator |
1114 | 188 $annotation.data('annotation', annotation); |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
189 // save reference to div |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
190 annotation.$div = $annotation; |
1113 | 191 $elem.append($annotation); |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
192 // hook up Annotator events |
1114 | 193 $annotation.on("mouseover", annotator.onHighlightMouseover); |
194 $annotation.on("mouseout", annotator.startViewerHideTimer); | |
1113 | 195 mpos.adjustDiv($annotation); |
196 } | |
197 }; | |
198 | |
199 /** | |
200 * Get an authentication token from the token server. | |
201 * | |
202 * Stores the token and loads annotations on success. | |
203 */ | |
204 var loadAnnotationToken = function(data, password) { | |
205 var settings = data.settings; | |
206 var url = settings.annotationTokenUrl; | |
207 var params = {'user': settings.annotationUser}; | |
208 if (password != null) { | |
209 params.password = password; | |
210 } | |
211 // TODO: better error handling | |
212 $.post(url, params) | |
213 .done(function (authToken, authStatus) { | |
214 console.debug("got auth token data=", authToken); | |
215 data.annotationToken = authToken; | |
216 data.dlOpts.annotationToken = authToken; | |
217 digilib.fn.storeOptions(data); | |
218 //loadAnnotations(data); | |
219 }) | |
220 .fail(function (xhr, status) { | |
221 console.error("got auth token error:", xhr); | |
222 data.annotationToken = null; | |
223 data.settings.annotationUser = "anonymous"; | |
224 //loadAnnotations(data); | |
225 }); | |
226 }; | |
227 | |
228 /** | |
229 * install additional buttons | |
230 */ | |
231 var installButtons = function(data) { | |
232 var settings = data.settings; | |
233 var mode = settings.interactionMode; | |
234 var buttonSettings = settings.buttonSettings[mode]; | |
235 // configure buttons through digilib "annotationSet" option | |
236 var buttonSet = settings.annotationSet || annotationSet; | |
237 // set annotationSet to [] or '' for no buttons (when showing annotations only) | |
238 if (buttonSet.length && buttonSet.length > 0) { | |
239 buttonSettings.annotationSet = buttonSet; | |
240 buttonSettings.buttonSets.push('annotationSet'); | |
241 } | |
242 }; | |
243 | |
244 /** | |
245 * plugin installation. called by digilib on plugin object. | |
246 */ | |
247 var install = function(plugin) { | |
248 digilib = plugin; | |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
249 console.debug('installing annotator plugin. digilib:', digilib); |
1113 | 250 // import geometry classes |
251 geom = digilib.fn.geometry; | |
252 FULL_AREA = geom.rectangle(0, 0, 1, 1); | |
253 // add defaults, actins, buttons | |
254 $.extend(digilib.defaults, defaults); | |
255 $.extend(digilib.actions, actions); | |
256 $.extend(digilib.buttons, buttons); | |
257 }; | |
258 | |
259 /** plugin initialization */ | |
260 var init = function(data) { | |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
261 console.debug('initialising annotator plugin. data:', data); |
1113 | 262 var $data = $(data); |
263 // set up | |
264 data.annotations = []; | |
265 if (digilib.plugins.buttons != null) { | |
266 installButtons(data); | |
267 } | |
268 if (data.dlOpts.annotationUser != null) { | |
269 // get annotation user from cookie | |
270 data.settings.annotationUser = data.dlOpts.annotationUser; | |
271 } | |
272 if (data.dlOpts.annotationToken != null) { | |
273 // get annotation token from cookie | |
274 data.annotationToken = data.dlOpts.annotationToken; | |
275 } | |
276 // install event handler | |
277 $data.bind('setup', handleSetup); | |
278 $data.bind('update', handleUpdate); | |
279 }; | |
280 | |
281 /** | |
282 * setup loads all annotations. | |
283 */ | |
284 var handleSetup = function(evt) { | |
285 console.debug("annotations: handleSetup"); | |
286 var data = this; | |
287 if (data.annotationToken == null) { | |
288 loadAnnotationToken(data); | |
289 } | |
290 // set up annotator (after html has been set up) | |
291 var uri = getAnnotationPageUrl(data); | |
292 annotator = new Annotator(data.$elem.get(0)) | |
293 //.addPlugin('Tags') | |
294 .addPlugin('Auth', { | |
295 token : data.annotationToken, | |
296 //tokenUrl: 'http://annotateit.org/api/token' | |
297 //autoFetch: false | |
298 }) | |
299 .addPlugin('Permissions', { | |
300 user: data.settings.annotationUser, | |
301 userString: function (user) { | |
302 if (user && user.name) { | |
303 return user.name; | |
304 } | |
305 return user; | |
306 }, | |
307 userId: function (user) { | |
308 if (user && user.id) { | |
309 return user.id; | |
310 } | |
311 return user; | |
312 } | |
313 }) | |
314 .addPlugin('Store', { | |
315 prefix : data.settings.annotationServerUrl, | |
316 annotationData: { | |
317 'uri': uri | |
318 }, | |
319 loadFromSearch: { | |
320 'limit': 20, | |
321 'uri': uri | |
322 } | |
323 }) | |
324 ; | |
325 | |
326 // monkey-patch Annotator.setupAnnotation | |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
327 annotator.setupRangeAnnotation = annotator.setupAnnotation; |
1113 | 328 annotator.setupAnnotation = function(annotation, fireEvents) { |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
329 if (annotator.selectedAreas == null && annotation.areas == null) { |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
330 // pass call to original method |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
331 return annotator.setupRangeAnnotation.apply(this, arguments); |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
332 } else { |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
333 // set up digilib-area annotation |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
334 if (fireEvents == null) { |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
335 fireEvents = true; |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
336 } |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
337 if (annotation.areas == null) { |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
338 annotation.areas = annotator.selectedAreas; |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
339 } |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
340 // compatibility crap |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
341 annotation.highlights = []; |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
342 // pre-render this annotation |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
343 renderAnnotation(data, annotation); |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
344 if (fireEvents) { |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
345 this.publish('annotationCreated', [annotation]); |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
346 } |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
347 return annotation; |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
348 } |
1113 | 349 }; |
350 | |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
351 // hook Annotator events |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
352 annotator.subscribe('annotationDeleted', function (ann) { |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
353 console.debug("got annotationDeleted!"); |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
354 if (ann.$div != null) { |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
355 ann.$div.remove(); |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
356 delete ann.$div; |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
357 } |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
358 }); |
1113 | 359 |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
360 // TODO: should we really export annotator? |
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
361 data.annotator = annotator; |
1113 | 362 }; |
363 | |
364 /** | |
365 * update renders all annotations. | |
366 */ | |
367 var handleUpdate = function(evt) { | |
368 console.debug("annotations: handleUpdate"); | |
369 var data = this; | |
370 renderAnnotations(data); | |
371 }; | |
372 | |
373 // plugin object with name and init | |
374 // shared objects filled by digilib on registration | |
375 var plugin = { | |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
376 name : 'annotator', |
1113 | 377 install : install, |
378 init : init, | |
379 buttons : {}, | |
380 actions : {}, | |
381 fn : {}, | |
382 plugins : {} | |
383 }; | |
384 | |
385 if ($.fn.digilib == null) { | |
1115
526dafa4690d
using annotator in digilib works now. code still ugly.
robcast
parents:
1114
diff
changeset
|
386 $.error("jquery.digilib.annotator must be loaded after jquery.digilib!"); |
1113 | 387 } else { |
388 $.fn.digilib('plugin', plugin); | |
389 } | |
390 })(jQuery); |