1 /**
  2  * Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
  3  *
  4  * @licstart
  5  * This file is part of WebODF.
  6  *
  7  * WebODF is free software: you can redistribute it and/or modify it
  8  * under the terms of the GNU Affero General Public License (GNU AGPL)
  9  * as published by the Free Software Foundation, either version 3 of
 10  * the License, or (at your option) any later version.
 11  *
 12  * WebODF is distributed in the hope that it will be useful, but
 13  * WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15  * GNU Affero General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU Affero General Public License
 18  * along with WebODF.  If not, see <http://www.gnu.org/licenses/>.
 19  * @licend
 20  *
 21  * @source: http://www.webodf.org/
 22  * @source: https://github.com/kogmbh/WebODF/
 23  */
 24 
 25 /*global ops, runtime, odf, core*/
 26 
 27 /**
 28  * @constructor
 29  * @implements ops.Operation
 30  */
 31 ops.OpRemoveAnnotation = function OpRemoveAnnotation() {
 32     "use strict";
 33     var memberid, timestamp,
 34         /**@type{number}*/
 35         position,
 36         /**@type{number}*/
 37         length,
 38         domUtils = core.DomUtils;
 39 
 40     /**
 41      * @param {!ops.OpRemoveAnnotation.InitSpec} data
 42      */
 43     this.init = function (data) {
 44         memberid = data.memberid;
 45         timestamp = data.timestamp;
 46         position = parseInt(data.position, 10);
 47         length = parseInt(data.length, 10);
 48     };
 49 
 50     this.isEdit = true;
 51     this.group = undefined;
 52 
 53     /**
 54      * @param {!ops.Document} document
 55      */
 56     this.execute = function (document) {
 57         var odtDocument = /**@type{ops.OdtDocument}*/(document),
 58             iterator = odtDocument.getIteratorAtPosition(position),
 59             container = iterator.container(),
 60             annotationNode,
 61             annotationEnd;
 62 
 63         while (!(container.namespaceURI === odf.Namespaces.officens
 64             && container.localName === 'annotation')) {
 65             container = container.parentNode;
 66         }
 67         if (container === null) {
 68             return false;
 69         }
 70 
 71         annotationNode = /**@type{!odf.AnnotationElement}*/(container);
 72         annotationEnd = annotationNode.annotationEndElement;
 73 
 74         // Untrack and unwrap annotation
 75         odtDocument.getOdfCanvas().forgetAnnotation(annotationNode);
 76 
 77         /**
 78          * @param {!Node} node
 79          */
 80         function insert(node) {
 81             /**@type{!Node}*/(annotationNode).parentNode.insertBefore(node, annotationNode);
 82         }
 83         // Move all cursors - outside and before the annotation node
 84         domUtils.getElementsByTagNameNS(annotationNode, 'urn:webodf:names:cursor', 'cursor').forEach(insert);
 85         domUtils.getElementsByTagNameNS(annotationNode, 'urn:webodf:names:cursor', 'anchor').forEach(insert);
 86 
 87         // Delete start and end
 88         annotationNode.parentNode.removeChild(annotationNode);
 89         if (annotationEnd) {
 90             annotationEnd.parentNode.removeChild(annotationEnd);
 91         }
 92         // The specified position is the first walkable step in the annotation. The position is always just before the first point of change
 93         odtDocument.emit(ops.OdtDocument.signalStepsRemoved, {position: position > 0 ? position - 1 : position});
 94 
 95         odtDocument.getOdfCanvas().rerenderAnnotations();
 96         odtDocument.fixCursorPositions();
 97         return true;
 98     };
 99 
100     /**
101      * @return {!ops.OpRemoveAnnotation.Spec}
102      */
103     this.spec = function () {
104         return {
105             optype: "RemoveAnnotation",
106             memberid: memberid,
107             timestamp: timestamp,
108             position: position,
109             length: length
110         };
111     };
112 };
113 /**@typedef{{
114     optype:string,
115     memberid:string,
116     timestamp:number,
117     position:number,
118     length:number
119 }}*/
120 ops.OpRemoveAnnotation.Spec;
121 /**@typedef{{
122     memberid:string,
123     timestamp:(number|undefined),
124     position:number,
125     length:number
126 }}*/
127 ops.OpRemoveAnnotation.InitSpec;
128