# HG changeset patch
# User robcast
# Date 1421939657 -3600
# Node ID 85906c9cd08b25ffe1f5604a5f07f5b18f302d95
# Parent be5a63e5b8ee0a19ba7771cd2c0dd1de30743166# Parent 425ce8f971aa19ee7471a1d7841280c6990f5287
Merge with 425ce8f971aa19ee7471a1d7841280c6990f5287
diff -r be5a63e5b8ee -r 85906c9cd08b webapp/src/main/webapp/jquery/annotator-dl.js
--- a/webapp/src/main/webapp/jquery/annotator-dl.js Thu Jan 22 15:52:56 2015 +0100
+++ b/webapp/src/main/webapp/jquery/annotator-dl.js Thu Jan 22 16:14:17 2015 +0100
@@ -1,13 +1,13 @@
/*
-** Annotator v1.2.9-dev-b091a74
+** Annotator v1.2.9-dev-5096249
** https://github.com/okfn/annotator/
**
** Copyright 2015, the Annotator project contributors.
** Dual licensed under the MIT and GPLv3 licenses.
** https://github.com/okfn/annotator/blob/master/LICENSE
**
-** Built at: 2015-01-16 17:56:43Z
+** Built at: 2015-01-17 13:38:31Z
*/
@@ -3106,9 +3106,6 @@
annotation.highlights = [];
annotation.ranges = [];
this.digilib.setupAnnotation(annotation);
- if (fireEvents) {
- this.publish('annotationCreated', [annotation]);
- }
return annotation;
} else {
return this.setupRangeAnnotation.apply(this, arguments);
diff -r be5a63e5b8ee -r 85906c9cd08b webapp/src/main/webapp/jquery/annotator-dl.min.js
--- a/webapp/src/main/webapp/jquery/annotator-dl.min.js Thu Jan 22 15:52:56 2015 +0100
+++ b/webapp/src/main/webapp/jquery/annotator-dl.min.js Thu Jan 22 16:14:17 2015 +0100
@@ -1,13 +1,13 @@
/*
-** Annotator v1.2.9-dev-b091a74
+** Annotator v1.2.9-dev-5096249
** https://github.com/okfn/annotator/
**
** Copyright 2015, the Annotator project contributors.
** Dual licensed under the MIT and GPLv3 licenses.
** https://github.com/okfn/annotator/blob/master/LICENSE
**
-** Built at: 2015-01-16 17:56:43Z
+** Built at: 2015-01-17 13:38:31Z
*/
@@ -15,6 +15,6 @@
!function(){var $,Annotator,Delegator,LinkParser,Range,Util,base64Decode,base64UrlDecode,createDateFromISO8601,findChild,fn,functions,g,getNodeName,getNodePosition,gettext,parseToken,simpleXPathJQuery,simpleXPathPure,_Annotator,_gettext,_i,_j,_len,_len1,_ref,_ref1,_ref2,_ref3,_ref4,_t,__slice=[].slice,__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},__bind=function(fn,me){return function(){return fn.apply(me,arguments)}},__indexOf=[].indexOf||function(item){for(var i=0,l=this.length;i/g,">").replace(/"/g,""")};Util.uuid=function(){var counter;counter=0;return function(){return counter++}}();Util.getGlobal=function(){return function(){return this}()};Util.maxZIndex=function($elements){var all,el;all=function(){var _i,_len,_results;_results=[];for(_i=0,_len=$elements.length;_i<_len;_i++){el=$elements[_i];if($(el).css("position")==="static"){_results.push(-1)}else{_results.push(parseFloat($(el).css("z-index"))||-1)}}return _results}();return Math.max.apply(Math,all)};Util.mousePosition=function(e,offsetEl){var offset,_ref1;if((_ref1=$(offsetEl).css("position"))!=="absolute"&&_ref1!=="fixed"&&_ref1!=="relative"){offsetEl=$(offsetEl).offsetParent()[0]}offset=$(offsetEl).offset();return{top:e.pageY-offset.top,left:e.pageX-offset.left}};Util.preventEventDefault=function(event){return event!=null?typeof event.preventDefault==="function"?event.preventDefault():void 0:void 0};functions=["log","debug","info","warn","exception","assert","dir","dirxml","trace","group","groupEnd","groupCollapsed","time","timeEnd","profile","profileEnd","count","clear","table","error","notifyFirebug","firebug","userObjects"];if(typeof console!=="undefined"&&console!==null){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={};Delegator.prototype.options={};Delegator.prototype.element=null;function Delegator(element,options){this.options=$.extend(true,{},this.options,options);this.element=$(element);this._closures={};this.on=this.subscribe;this.addEvents()}Delegator.prototype.destroy=function(){return this.removeEvents()};Delegator.prototype.addEvents=function(){var event,_k,_len2,_ref1,_results;_ref1=Delegator._parseEvents(this.events);_results=[];for(_k=0,_len2=_ref1.length;_k<_len2;_k++){event=_ref1[_k];_results.push(this._addEvent(event.selector,event.event,event.functionName))}return _results};Delegator.prototype.removeEvents=function(){var event,_k,_len2,_ref1,_results;_ref1=Delegator._parseEvents(this.events);_results=[];for(_k=0,_len2=_ref1.length;_k<_len2;_k++){event=_ref1[_k];_results.push(this._removeEvent(event.selector,event.event,event.functionName))}return _results};Delegator.prototype._addEvent=function(selector,event,functionName){var closure,_this=this;closure=function(){return _this[functionName].apply(_this,arguments)};if(selector===""&&Delegator._isCustomEvent(event)){this.subscribe(event,closure)}else{this.element.delegate(selector,event,closure)}this._closures[""+selector+"/"+event+"/"+functionName]=closure;return this};Delegator.prototype._removeEvent=function(selector,event,functionName){var closure;closure=this._closures[""+selector+"/"+event+"/"+functionName];if(selector===""&&Delegator._isCustomEvent(event)){this.unsubscribe(event,closure)}else{this.element.undelegate(selector,event,closure)}delete this._closures[""+selector+"/"+event+"/"+functionName];return this};Delegator.prototype.publish=function(){this.element.triggerHandler.apply(this.element,arguments);return this};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}();Delegator._parseEvents=function(eventsObj){var event,events,functionName,sel,selector,_k,_ref1;events=[];for(sel in eventsObj){functionName=eventsObj[sel];_ref1=sel.split(" "),selector=2<=_ref1.length?__slice.call(_ref1,0,_k=_ref1.length-1):(_k=0,[]),event=_ref1[_k++];events.push({selector:selector.join(" "),event:event,functionName:functionName})}return events};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 _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)}();Delegator._isCustomEvent=function(event){event=event.split(".")[0];return $.inArray(event,Delegator.natives)===-1};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}};Range.nodeFromXPath=function(xpath,root){var customResolver,evaluateXPath,namespace,node,segment;if(root==null){root=document}evaluateXPath=function(xp,nsResolver){var exception;if(nsResolver==null){nsResolver=null}try{return document.evaluate("."+xp,root,nsResolver,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue}catch(_error){exception=_error;console.log("XPath evaluation failed.");console.log("Trying fallback...");return Util.nodeFromXPath(xp,root)}};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}};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}BrowserRange.prototype.normalize=function(root){var n,node,nr,r;if(this.tainted){console.error(_t("You may only call normalize() once on a BrowserRange!"));return false}else{this.tainted=true}r={};if(this.startContainer.nodeType===Node.ELEMENT_NODE){r.start=Util.getFirstTextNodeNotBefore(this.startContainer.childNodes[this.startOffset]);r.startOffset=0}else{r.start=this.startContainer;r.startOffset=this.startOffset}if(this.endContainer.nodeType===Node.ELEMENT_NODE){node=this.endContainer.childNodes[this.endOffset];if(node!=null){n=node;while(n!=null&&n.nodeType!==Node.TEXT_NODE){n=n.firstChild}if(n!=null){r.end=n;r.endOffset=0}}if(r.end==null){node=this.endContainer.childNodes[this.endOffset-1];r.end=Util.getLastTextNodeUpTo(node);r.endOffset=r.end.nodeValue.length}}else{r.end=this.endContainer;r.endOffset=this.endOffset}nr={};if(r.startOffset>0){if(r.start.nodeValue.length>r.startOffset){nr.start=r.start.splitText(r.startOffset)}else{nr.start=r.start.nextSibling}}else{nr.start=r.start}if(r.start===r.end){if(nr.start.nodeValue.length>r.endOffset-r.startOffset){nr.start.splitText(r.endOffset-r.startOffset)}nr.end=nr.start}else{if(r.end.nodeValue.length>r.endOffset){r.end.splitText(r.endOffset)}nr.end=r.end}nr.commonAncestor=this.commonAncestorContainer;while(nr.commonAncestor.nodeType!==Node.ELEMENT_NODE){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};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=Util.xpathFromNode(origParent,root)[0];textNodes=Util.getTextNodes(origParent);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]})};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("")};NormalizedRange.prototype.textNodes=function(){var end,start,textNodes,_ref1;textNodes=Util.getTextNodes($(this.commonAncestor));_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}SerializedRange.prototype.normalize=function(root){var contains,e,length,node,p,range,targetOffset,tn,_k,_l,_len2,_len3,_ref1,_ref2;range={};_ref1=["start","end"];for(_k=0,_len2=_ref1.length;_k<_len2;_k++){p=_ref1[_k];try{node=Range.nodeFromXPath(this[p],root)}catch(_error){e=_error;throw new Range.RangeError(p,"Error while finding "+p+" node: "+this[p]+": "+e,e)}if(!node){throw new Range.RangeError(p,"Couldn't find "+p+" node: "+this[p])}length=0;targetOffset=this[p+"Offset"];if(p==="end"){targetOffset--}_ref2=Util.getTextNodes($(node));for(_l=0,_len3=_ref2.length;_l<_len3;_l++){tn=_ref2[_l];if(length+tn.nodeValue.length>targetOffset){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])}}contains=document.compareDocumentPosition==null?function(a,b){return a.contains(b)}:function(a,b){return a.compareDocumentPosition(b)&16};$(range.startContainer).parents().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}();_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;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);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();Annotator._instances.push(this)}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(){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))}else{$(field).html(""+_t("No Comment")+"")}return _this.publish("annotationViewerTextField",[field,annotation])}}).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")+"…",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 _k,_len2,_ref1,_results;_ref1=["adder","outer","notice","filter"];_results=[];for(_k=0,_len2=_ref1.length;_k<_len2;_k++){x=_ref1[_k];_results.push(":not(.annotator-"+x+")")}return _results}().join("");max=Util.maxZIndex($(document.body).find(sel));max=Math.max(max,1e3);style.text([".annotator-adder, .annotator-outer, .annotator-notice {"," z-index: "+(max+20)+";","}",".annotator-filter {"," z-index: "+(max+10)+";","}"].join("\n"));return this};Annotator.prototype.destroy=function(){var idx,name,plugin,_base,_ref1;Annotator.__super__.destroy.apply(this,arguments);$(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);_ref1=this.plugins;for(name in _ref1){plugin=_ref1[name];if(typeof(_base=this.plugins[name]).destroy==="function"){_base.destroy()}}idx=Annotator._instances.indexOf(this);if(idx!==-1){return Annotator._instances.splice(idx,1)}};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){var e,normed,normedRanges,r,root,_k,_l,_len2,_len3,_ref1;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(_error){e=_error;if(e instanceof Range.RangeError){this.publish("rangeNormalizeFail",[annotation,r,e])}else{throw e}}}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);$(annotation.highlights).attr("data-annotation-id",annotation.id);return annotation};Annotator.prototype.updateAnnotation=function(annotation){this.publish("beforeAnnotationUpdated",[annotation]);$(annotation.highlights).attr("data-annotation-id",annotation.id);this.publish("annotationUpdated",[annotation]);return annotation};Annotator.prototype.deleteAnnotation=function(annotation){var child,h,_k,_len2,_ref1;if(annotation.highlights!=null){_ref1=annotation.highlights;for(_k=0,_len2=_ref1.length;_k<_len2;_k++){h=_ref1[_k];if(!(h.parentNode!=null)){continue}child=h.childNodes[0];$(h).replaceWith(h.childNodes)}}this.publish("annotationDeleted",[annotation]);return annotation};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(_k=0,_len2=now.length;_k<_len2;_k++){n=now[_k];_this.setupAnnotation(n)}if(annList.length>0){return setTimeout(function(){return loader(annList)},10)}else{return _this.publish("annotationsLoaded",[clone])}};clone=annotations.slice();loader(annotations);return this};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.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.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
-
@@ -27,6 +25,7 @@
+
@@ -42,10 +41,11 @@
// are annotations read-only?
'annotationsReadOnly' : false,
// URL of authentication token server
- //'annotationTokenUrl' : 'http://localhost:8080/test/annotator/token/getLoginToken',
+ 'annotationTokenUrl' : 'http://localhost:8080/test/annotator/token/getLoginToken',
// list of Annotator plugins
- //'annotatorPlugins' : ['Auth', 'Permissions', 'Store', 'Markdown', 'DigilibIntegrator']
- 'annotatorPlugins' : ['Store', 'Markdown', 'DigilibIntegrator']
+ 'annotatorPlugins' : ['Auth', 'Permissions', 'Markdown', 'DigilibIntegrator', 'Store']
+ //'annotatorPlugins' : ['Auth', 'Permissions', 'Markdown', 'DigilibIntegrator', 'Store']
+ //'annotatorPlugins' : ['Store', 'Markdown', 'DigilibIntegrator']
};
var $div = $('div#digilib');
$div.digilib(opts);
diff -r be5a63e5b8ee -r 85906c9cd08b webapp/src/main/webapp/jquery/digilib-vector.html
--- a/webapp/src/main/webapp/jquery/digilib-vector.html Thu Jan 22 15:52:56 2015 +0100
+++ b/webapp/src/main/webapp/jquery/digilib-vector.html Thu Jan 22 16:14:17 2015 +0100
@@ -63,23 +63,23 @@
'editable' : true
}
}]);
- $('#test-squares')[0].addEventListener('load', function (evt) {
+ /* $('#test-squares')[0].addEventListener('load', function (evt) {
var layer = {'projection': 'relative',
'$elem': $(this),
'svgElem': this.contentDocument.documentElement};
$div.digilib("addVectorLayer", layer);
return false;
- });
+ }); */
});
-
-
+
+
digilib doesn't work! Please switch on Javascript or notify the server administrator!
-

-
+

+
diff -r be5a63e5b8ee -r 85906c9cd08b webapp/src/main/webapp/jquery/jquery.digilib.annotator.js
--- a/webapp/src/main/webapp/jquery/jquery.digilib.annotator.js Thu Jan 22 15:52:56 2015 +0100
+++ b/webapp/src/main/webapp/jquery/jquery.digilib.annotator.js Thu Jan 22 16:14:17 2015 +0100
@@ -31,7 +31,7 @@
*/
(function($) {
// version of this plugin
- var version = 'jquery.digilib.annotator.js 1.2.0';
+ var version = 'jquery.digilib.annotator.js 1.3.0';
// affine geometry
var geom = null;
@@ -39,8 +39,8 @@
var digilib = null;
// the functions made available by digilib
var fn = {};
- // the normal zoom area
- var FULL_AREA = null;
+ // annotation shape layer
+ var annotationLayer = null;
var buttons = {
annotations : {
@@ -233,27 +233,7 @@
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
- var annotation = annotator.createAnnotation();
- var cleanup = function () {
- annotator.unsubscribe('annotationEditorSubmit', save);
- annotator.unsubscribe('annotationEditorHidden', cancel);
- };
- var save = function () {
- console.log("annotation save.")
- cleanup();
- annotator.setupAnnotation(annotation);
- // Fire annotationCreated events so that plugins can react to them
- annotator.publish('annotationCreated', [annotation]);
- };
- var cancel = function () {
- console.log("annotation cancel.")
- cleanup();
- };
- annotator.subscribe('annotationEditorSubmit', save);
- annotator.subscribe('annotationEditorHidden', cancel);
- annotator.showEditor(annotation, mpos.getAsCss());
+ createAnnotation(data, shape, mpos);
return false;
});
};
@@ -269,117 +249,179 @@
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);
- var annotation = annotator.createAnnotation();
- var cleanup = function () {
- annotator.unsubscribe('annotationEditorSubmit', save);
- annotator.unsubscribe('annotationEditorHidden', cancel);
- };
- var save = function () {
- console.log("annotation save.")
- cleanup();
- annotator.setupAnnotation(annotation);
- // Fire annotationCreated events so that plugins can react to them
- annotator.publish('annotationCreated', [annotation]);
- };
- var cancel = function () {
- console.log("annotation cancel.")
- cleanup();
- };
- annotator.subscribe('annotationEditorSubmit', save);
- annotator.subscribe('annotationEditorHidden', cancel);
- annotator.showEditor(annotation, mpos.getAsCss());
+ createAnnotation(data, shape, mpos);
});
};
/**
+ * Show editor and save annotation.
+ */
+ var createAnnotation = function (data, shape, screenPos) {
+ var annotator = data.annotator;
+ annotator.selectedShapes = [shape];
+ // create and edit new annotation
+ var annotation = annotator.createAnnotation();
+ var cleanup = function () {
+ annotator.unsubscribe('annotationEditorSubmit', save);
+ annotator.unsubscribe('annotationEditorHidden', cancel);
+ };
+ var save = function () {
+ console.log("annotation save.");
+ cleanup();
+ annotator.setupAnnotation(annotation);
+ // Fire annotationCreated events so that plugins can react to them
+ annotator.publish('annotationCreated', [annotation]);
+ renderAnnotations(data);
+ };
+ var cancel = function () {
+ console.log("annotation cancel.")
+ cleanup();
+ };
+ annotator.subscribe('annotationEditorSubmit', save);
+ annotator.subscribe('annotationEditorHidden', cancel);
+ annotator.showEditor(annotation, screenPos.getAsCss());
+ }
+
+ /**
* Render all annotations on the image
*/
var renderAnnotations = function (data) {
- if (data.annotations == null || data.annotator == null || data.$img == null || data.imgTrafo == null)
+ if (data.annotations == null || data.annotator == 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]);
+ // create vector shapes
+ var shapes = [];
+ for (var i = 0; i < annotations.length; ++i) {
+ shapes.push(createVectorShape(data, annotations[i]));
+ }
+ annotationLayer.shapes = shapes;
+ // render vector layer
+ if (data.$img != null && data.imgTrafo != null) {
+ annotationLayer.renderFn(data, annotationLayer);
}
};
/**
- * Render a single annotation on the image.
+ * Layer render function for vector plugin.
+ */
+ var layerRenderFn = function (data, layer) {
+ // default shape render fn creates SVG elements
+ fn.vectorDefaultRenderFn(data, layer);
+ // attach annotations to shapes
+ var annotations = data.annotations;
+ for (var i = 0; i < annotations.length; ++i) {
+ attachAnnotation(data, annotations[i], layer);
+ }
+ layer.dirty = false;
+ };
+
+ /**
+ * Create a vector shape for an annotation.
*
* @param annot annotation wrapper object
+ * @returns vector shape object
*/
- var renderAnnotation = function (data, annot) {
- if (annot == null || annot.annotation == null || data.$img == null || data.imgTrafo == null)
+ var createVectorShape = function (data, annot) {
+ if (annot == null || annot.annotation == 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 id = fn.createId(annotation.id, cssPrefix+'annot-');
+ if (annotation.id == null) {
+ console.warn("substituting annotation id!");
+ annotation.id = id;
+ }
var shape = null;
var area = null;
var type = null;
+ var vectorShape = null;
if (annotation.shapes != null) {
// annotation shape
shape = annotation.shapes[0];
type = shape.type;
if (type === "point") {
area = geom.position(shape.geometry);
+ vectorShape = {
+ 'id': id,
+ 'geometry': {
+ 'type' : 'Point',
+ 'coordinates' : [[area.x, area.y]]
+ },
+ 'properties' : {
+ 'stroke' : 'yellow',
+ 'cssclass' : cssPrefix+'svg-annotationregion annotator-hl',
+ 'style' : 'pointer-events:all'
+ }
+ };
} else if (type === "rectangle") {
area = geom.rectangle(shape.geometry);
+ // render rectangle
+ var pt1 = area.getPt1();
+ var pt2 = area.getPt2();
+ vectorShape = {
+ 'id': id,
+ 'geometry': {
+ 'type' : 'Rectangle',
+ 'coordinates' : [[pt1.x, pt1.y], [pt2.x, pt2.y]]
+ },
+ 'properties' : {
+ 'stroke' : 'yellow',
+ 'cssclass' : cssPrefix+'svg-annotationregion annotator-hl',
+ 'style' : 'pointer-events:all'
+ }
+ };
} else {
- console.error("Unsupported shape type="+type);
+ 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!");
+ console.error("Unable to create a shape for 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);
- }
+ return vectorShape;
+ };
+
+ /**
+ * Attach annotation handlers to the SVG shape.
+ *
+ * @param annot annotation wrapper object
+ * @param layer vector shape layer
+ */
+ var attachAnnotation = function (data, annot, layer) {
+ if (annot == null || annot.annotation == null || layer == null || layer.shapes == 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 id = annotation.id;
+ // get vector shape
+ var vecShape = digilib.actions.getShapeById(data, id, layer);
+ if (vecShape == null) {
+ console.error("Unable to find shape for annotation! id=", id);
+ return;
+ };
+ // annotation shape
+ var shape = annotation.shapes[0];
+ var $annotation = vecShape.$elem;
// save annotation in data for Annotator
$annotation.data('annotation', annotation);
- $annotation.data('rect', area);
+ $annotation.attr('data-annotation-id', id)
+ //$annotation.data('rect', area);
// add shared css class from annotations collection
if (annotation.cssclass != null) {
$annotation.addClass(annotation.cssclass);
@@ -390,16 +432,14 @@
}
// 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) {
+ /* $annotation.on('click.dlAnnotation', function(event) {
$(data).trigger('annotationClick', [$annotation]);
- });
- screenRect.adjustDiv($annotation);
+ }); */
};
-
+
/**
* returns setupAnnotation function using the given data.
*/
@@ -412,8 +452,7 @@
};
// add to list
data.annotations.push(ann);
- // render this annotation
- renderAnnotation(data, ann);
+ annotationLayer.dirty = true;
};
};
@@ -423,17 +462,14 @@
var getAnnotationDeleted = function(data) {
return function (annotation) {
// remove annotation mark
+ console.debug("delete annotation.");
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];
+ // this is the right wrapper -- delete
+ annots.splice(i, 1);
+ renderAnnotations(data);
break;
}
}
@@ -605,6 +641,10 @@
var install = function(plugin) {
digilib = plugin;
console.debug('installing annotator plugin. digilib:', digilib);
+ if (digilib.plugins.vector == null) {
+ console.error('annotator plugin: vector plugin is missing, aborting installation.');
+ return;
+ }
// import digilib functions
$.extend(fn, digilib.fn);
// import geometry classes
@@ -620,7 +660,6 @@
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
@@ -635,10 +674,17 @@
// get annotation user from cookie
settings.annotationUser = data.dlOpts.annotationUser;
}
+ // create annotation shapes layer
+ annotationLayer = {
+ 'projection': 'screen',
+ 'renderFn': layerRenderFn,
+ 'shapes': []
+ };
+ digilib.actions.addVectorLayer(data, annotationLayer);
// install event handler
- $data.bind('setup', handleSetup);
- $data.bind('update', handleUpdate);
- $data.on('annotationClick', handleAnnotationClick);
+ $data.on('setup', handleSetup);
+ $data.on('update', handleUpdate);
+ //$data.on('annotationClick', handleAnnotationClick);
};
/**
@@ -653,6 +699,7 @@
var elem = data.$elem.get(0);
var opts = {'readOnly' : data.settings.annotationsReadOnly};
var annotator = new Annotator(elem, opts);
+ console.debug("annotator created");
// set plugin parameters
var def = defaults.annotatorPluginSettings;
var pluginParams = {};
@@ -685,6 +732,10 @@
});
// save annotator reference
data.annotator = annotator;
+ annotator.subscribe("annotationsLoaded", function () {
+ console.debug("annotations loaded!");
+ renderAnnotations(data);
+ });
// save annotation token in cookie
var auth = annotator.plugins.Auth;
if (auth != null) {
@@ -701,7 +752,10 @@
var handleUpdate = function(evt) {
console.debug("annotations: handleUpdate");
var data = this;
- renderAnnotations(data);
+ // TODO: do not render too often
+ if (annotationLayer.dirty) {
+ renderAnnotations(data);
+ }
};
// plugin object with name and init
@@ -716,7 +770,7 @@
plugins : {}
};
- if (Annotator == null) {
+ if (typeof(Annotator) === 'undefined') {
$.error("Annotator.js Javascript not found!");
}
if ($.fn.digilib == null) {
diff -r be5a63e5b8ee -r 85906c9cd08b webapp/src/main/webapp/jquery/jquery.digilib.css
--- a/webapp/src/main/webapp/jquery/jquery.digilib.css Thu Jan 22 15:52:56 2015 +0100
+++ b/webapp/src/main/webapp/jquery/jquery.digilib.css Thu Jan 22 16:14:17 2015 +0100
@@ -400,6 +400,16 @@
div.dl-digilib .dl-svg-handle:hover {
fill: red;
}
+div.dl-digilib .dl-svg-annotationregion {
+ fill: rgba(255, 255, 10, 0.3);
+ stroke: none;
+}
+div.dl-digilib .dl-svg-annotationregion:hover {
+ fill: transparent;
+ stroke: yellow;
+ stroke-width: 2px;
+}
+
/* special definitions for embedded */
div.dl-digilib.dl-embedded {
diff -r be5a63e5b8ee -r 85906c9cd08b webapp/src/main/webapp/jquery/jquery.digilib.vector.js
--- a/webapp/src/main/webapp/jquery/jquery.digilib.vector.js Thu Jan 22 15:52:56 2015 +0100
+++ b/webapp/src/main/webapp/jquery/jquery.digilib.vector.js Thu Jan 22 16:14:17 2015 +0100
@@ -73,13 +73,18 @@
/**
* set list of vector objects (shapes).
*
- * replaces all existing shapes.
+ * replaces all existing shapes on layer.
*
* @param data
* @param shapes
+ * @param layer
*/
- setShapes : function(data, shapes) {
- data.shapes = shapes;
+ setShapes : function(data, shapes, layer) {
+ if (layer == null) {
+ // assume shape layer is 0
+ layer = data.vectorLayers[0];
+ }
+ layer.shapes = shapes;
renderShapes(data);
},
@@ -96,18 +101,18 @@
* @param layer
*/
addShape : function(data, shape, onComplete, layer) {
- if (data.shapes == null) {
- data.shapes = [];
- };
if (layer == null) {
// assume shape layer is 0
layer = data.vectorLayers[0];
}
+ if (layer.shapes == null) {
+ layer.shapes = [];
+ }
if (shape.geometry.coordinates == null) {
// define shape interactively
defineShape(data, shape, layer, onComplete);
} else {
- data.shapes.push(shape);
+ layer.shapes.push(shape);
renderShapes(data, layer);
}
},
@@ -119,8 +124,12 @@
* @param id
* @returns shape
*/
- getShapeById : function(data, id) {
- var shapes = data.shapes;
+ getShapeById : function(data, id, layer) {
+ if (layer == null) {
+ // assume shape layer is 0
+ layer = data.vectorLayers[0];
+ }
+ var shapes = layer.shapes;
if (shapes == null) return null;
for (var i in shapes) {
if (shapes[i].id === id) {
@@ -136,15 +145,19 @@
* @param data
* @param id
*/
- removeShapeById : function(data, id) {
- var shapes = data.shapes;
- if (shapes == null) return;
+ removeShapeById : function(data, id, layer) {
+ if (layer == null) {
+ // assume shape layer is 0
+ layer = data.vectorLayers[0];
+ }
+ var shapes = layer.shapes;
+ if (shapes == null) return;
for (var i in shapes) {
if (shapes[i].id === id) {
shapes.splice(i, 1);
}
}
- renderShapes(data);
+ renderShapes(data, layer);
},
/**
@@ -174,10 +187,10 @@
// set defaults for HTML element
$elem.css({'position':'absolute', 'z-index': 9, 'pointer-events':'none'});
$elem.addClass(data.settings.cssPrefix+'overlay');
- // add layer
- data.vectorLayers.push(layer);
- renderLayers(data);
}
+ // add layer
+ data.vectorLayers.push(layer);
+ renderLayers(data);
}
};
@@ -192,6 +205,8 @@
// add defaults, actions, buttons to the main digilib object
$.extend(digilib.defaults, defaults);
$.extend(digilib.actions, actions);
+ // export functions
+ digilib.fn.vectorDefaultRenderFn = renderShapes;
};
/**
@@ -203,7 +218,8 @@
// create default shapes layer
var shapeLayer = {
'projection': 'screen',
- 'renderFn': renderShapes
+ 'renderFn': renderShapes,
+ 'shapes': []
};
// shapes layer is first
data.vectorLayers = [shapeLayer];
@@ -232,7 +248,7 @@
var renderLayers = function(data) {
if (data.imgRect == null)
return;
- for ( var i in data.vectorLayers) {
+ for (var i in data.vectorLayers) {
var layer = data.vectorLayers[i];
if (layer.projection === 'screen') {
// screen layers have render function
@@ -262,8 +278,9 @@
* @param layer
*/
var renderShapes = function (data, layer) {
- console.debug("renderShapes shapes:", data.shapes);
- if (data.shapes == null || data.imgTrafo == null || !data.settings.isVectorActive)
+ var shapes = layer.shapes || data.shapes;
+ console.debug("renderShapes shapes:", shapes);
+ if (shapes == null || data.imgTrafo == null || !data.settings.isVectorActive)
return;
if (layer == null) {
// assume shape layer is 0
@@ -280,8 +297,8 @@
$svg = $(svgElem);
layer.svgElem = svgElem;
layer.$elem = $svg;
- for (var i in data.shapes) {
- var shape = data.shapes[i];
+ for (var i = 0; i < shapes.length; ++i) {
+ var shape = shapes[i];
renderShape(data, shape, layer);
}
data.$elem.append($svg);
@@ -317,19 +334,37 @@
var stroke = props['stroke'] || settings.defaultStroke;
var strokeWidth = props['stroke-width'] || settings.defaultStrokeWidth;
var fill = props['fill'] || settings.defaultFill;
+ var cssclass = props['cssclass'];
+ var style = props['style'];
var coords = shape.geometry.coordinates;
var gt = shape.geometry.type;
- if (gt === 'Line') {
+ if (gt === 'Point') {
+ /*
+ * Point
+ */
+ var p1 = trafo.transform(geom.position(coords[0]));
+ var $elem = $(svgElement('circle', {
+ 'id': id, 'class': cssclass,
+ 'cx': p1.x, 'cy': p1.y,
+ 'r': hs,
+ 'stroke': stroke, 'stroke-width': strokeWidth,
+ 'fill': fill, 'style': style}));
+ shape.$elem = $elem;
+ $svg.append($elem);
+ if (props.editable) {
+ $elem.one("mousedown.dlVertexDrag", getVertexDragHandler(data, shape, 0));
+ }
+ } else if (gt === 'Line') {
/*
* Line
*/
var p1 = trafo.transform(geom.position(coords[0]));
var p2 = trafo.transform(geom.position(coords[1]));
var $elem = $(svgElement('line', {
- 'id': id,
+ 'id': id, 'class': cssclass,
'x1': p1.x, 'y1': p1.y,
'x2': p2.x, 'y2': p2.y,
- 'stroke': stroke, 'stroke-width': strokeWidth}));
+ 'stroke': stroke, 'stroke-width': strokeWidth, 'style': style}));
shape.$elem = $elem;
$svg.append($elem);
if (props.editable) {
@@ -355,11 +390,11 @@
var p2 = trafo.transform(geom.position(coords[1]));
var rect = geom.rectangle(p1, p2);
var $elem = $(svgElement('rect', {
- 'id': id,
+ 'id': id, 'class': cssclass,
'x': rect.x, 'y': rect.y,
'width': rect.width, 'height': rect.height,
'stroke': stroke, 'stroke-width': strokeWidth,
- 'fill': fill}));
+ 'fill': fill, 'style': style}));
shape.$elem = $elem;
$svg.append($elem);
if (props.editable) {
@@ -386,10 +421,10 @@
ps[i] = trafo.transform(geom.position(coords[i]));
}
var $elem = $(svgElement('polygon', {
- 'id': id,
+ 'id': id, 'class': cssclass,
'points': ps.join(" "),
'stroke': stroke, 'stroke-width': strokeWidth,
- 'fill': fill}));
+ 'fill': fill, 'style': style}));
shape.$elem = $elem;
$svg.append($elem);
if (props.editable) {
@@ -416,10 +451,10 @@
ps[i] = trafo.transform(geom.position(coords[i]));
}
var $elem = $(svgElement('polyline', {
- 'id': id,
+ 'id': id, 'class': cssclass,
'points': ps.join(" "),
'stroke': stroke, 'stroke-width': strokeWidth,
- 'fill': 'none'}));
+ 'fill': 'none', 'style': style}));
shape.$elem = $elem;
$svg.append($elem);
if (props.editable) {
@@ -433,7 +468,7 @@
'class': css+'svg-handle', 'style': 'pointer-events:all'}));
$vertexElems[i] = $vertexElem;
// getVertexDragHandler needs shape.$vertexElems
- $vertexElem.one("mousedown.dlVertexDrag", getVertexDragHandler(data, shape, i));
+ $vertexElem.one('mousedown.dlVertexDrag', getVertexDragHandler(data, shape, i));
}
$svg.append($vertexElems);
}
@@ -441,6 +476,29 @@
};
/**
+ * remove rendered shape from screen.
+ *
+ * Removes the SVG elements from the layer.
+ *
+ * @param data
+ * @param shape
+ */
+ var unrenderShape = function (data, shape) {
+ // remove vertex handles
+ if (shape.$vertexElems != null) {
+ for (var i = 0; i < shape.$vertexElems.length; ++i) {
+ shape.$vertexElems[i].remove();
+ }
+ delete shape.$vertexElems;
+ }
+ // remove SVG element
+ if (shape.$elem != null) {
+ shape.$elem.remove();
+ delete shape.$elem;
+ }
+ };
+
+ /**
* return a vertexDragHandler function.
*
* @param data
@@ -468,6 +526,7 @@
}
$document.on("mousemove.dlVertexDrag", dragMove);
$document.on("mouseup.dlVertexDrag", dragEnd);
+ $document.on("dblclick.dlVertexDrag", dragEnd);
return false;
};
@@ -476,7 +535,7 @@
pt.clipTo(imgRect);
// move handle
$handle.attr({'x': pt.x-hs/2, 'y': pt.y-hs/2});
- // update shape element
+ // update shape SVG element
if (shapeType === 'Line') {
if (vtx == 0) {
$shape.attr({'x1': pt.x, 'y1': pt.y});
@@ -491,7 +550,7 @@
}
$shape.attr({'x': rect.x, 'y': rect.y,
'width': rect.width, 'height': rect.height});
- } else if (shapeType === 'Polygon' || shapeType === 'LineString' ) {
+ } else if (shapeType === 'Polygon' || shapeType === 'LineString') {
var points = $shape.attr('points');
var ps = points.split(' ');
ps[vtx] = pt.x + ',' + pt.y;
@@ -503,24 +562,25 @@
var dragEnd = function (evt) {
pt = geom.position(evt);
- if (pt.distance(pt0) < 5) {
+ if ((pt.distance(pt0) < 5) && evt.type === 'mouseup') {
+ // not drag but click to start
return false;
}
pt.clipTo(imgRect);
var p1 = data.imgTrafo.invtransform(pt);
- // update shape element
- if (shapeType === 'Line') {
- shape.geometry.coordinates[vtx] = [p1.x, p1.y];
- } else if (shapeType === 'Rectangle') {
+ // update shape object
+ if (shapeType === 'Line' || shapeType === 'Rectangle' ||
+ shapeType === 'Polygon' || shapeType === 'LineString') {
shape.geometry.coordinates[vtx] = [p1.x, p1.y];
}
// remove move/end handler
$document.off("mousemove.dlVertexDrag", dragMove);
$document.off("mouseup.dlVertexDrag", dragEnd);
+ $document.off("dblclick.dlVertexDrag", dragEnd);
// rearm start handler
$handle.one("mousedown.dlVertexDrag", dragStart);
if (onComplete != null) {
- onComplete(data, shape);
+ onComplete(data, shape, evt);
} else {
$(data).trigger('changeShape', shape);
}
@@ -559,25 +619,68 @@
var pt = geom.position(evt);
// setup shape
var p = data.imgTrafo.invtransform(pt);
- if (shapeType === 'Line' || shapeType === 'Rectangle') {
+ var vtxidx = 1;
+ if (shapeType === 'Line' || shapeType === 'Rectangle' ||
+ shapeType === 'LineString' || shapeType === 'Polygon') {
shape.geometry.coordinates = [[p.x, p.y], [p.x, p.y]];
} else {
console.error("unsupported shape type: "+shapeType);
$overlayDiv.remove();
return false;
}
+ // save editable state and set to non-editable
+ var isShapeEditable = false;
+ if (shape.properties != null) {
+ isShapeEditable = shape.properties.editable;
+ shape.properties.editable = false;
+ } else {
+ shape.properties = {'editable' : false};
+ }
// draw shape
renderShape(data, shape, layer);
- // execute vertex drag handler on second vertex
- getVertexDragHandler(data, shape, 1, function (data, newshape) {
+ // vertex drag end handler
+ var vertexDragDone = function (data, newshape, newevt) {
+ var coords = newshape.geometry.coordinates;
+ if (shapeType === 'LineString' || shapeType === 'Polygon') {
+ if (newevt.type === 'mouseup') {
+ // single click adds line to LineString/Polygon
+ unrenderShape(data, newshape);
+ // copy last vertex as starting point
+ coords.push(coords[vtxidx].slice());
+ vtxidx += 1;
+ // draw shape
+ renderShape(data, newshape, layer);
+ // execute vertex drag handler on next vertex
+ getVertexDragHandler(data, newshape, vtxidx, vertexDragDone)(newevt);
+ return false;
+ } else if (newevt.type === 'dblclick') {
+ // double click ends Linestring/Polygon
+ if (coords[vtxidx][0] === coords[vtxidx-1][0] &&
+ coords[vtxidx][1] === coords[vtxidx-1][1]) {
+ unrenderShape(data, newshape);
+ // remove duplicate last vertex (from mouseup)
+ coords.pop();
+ renderShape(data, newshape, layer);
+ }
+ } else {
+ console.error("unknown event type!");
+ return false;
+ }
+ }
// dragging vertex done
- console.debug("new shape:", newshape);
- data.shapes.push(newshape);
+ // re-set editable
+ unrenderShape(data, newshape);
+ shape.properties.editable = isShapeEditable;
+ renderShape(data, newshape, layer);
+ // save shape
+ layer.shapes.push(newshape);
$overlayDiv.remove();
if (onComplete != null) {
onComplete(data, newshape);
}
- })(evt);
+ };
+ // execute vertex drag handler on second vertex
+ getVertexDragHandler(data, shape, vtxidx, vertexDragDone)(evt);
return false;
};
@@ -595,7 +698,9 @@
var elem = document.createElementNS(svgNS, name);
if (attrs != null) {
for (var att in attrs) {
- elem.setAttributeNS(null, att, attrs[att]);
+ if (attrs[att] != null) {
+ elem.setAttributeNS(null, att, attrs[att]);
+ }
};
}
return elem;