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         /**@type{!core.DomUtils}*/
 39         domUtils;
 40 
 41     /**
 42      * @param {!ops.OpRemoveAnnotation.InitSpec} data
 43      */
 44     this.init = function (data) {
 45         memberid = data.memberid;
 46         timestamp = data.timestamp;
 47         position = parseInt(data.position, 10);
 48         length = parseInt(data.length, 10);
 49         domUtils = new core.DomUtils();
 50     };
 51 
 52     this.isEdit = true;
 53     this.group = undefined;
 54 
 55     /**
 56      * @param {!ops.Document} document
 57      */
 58     this.execute = function (document) {
 59         var odtDocument = /**@type{ops.OdtDocument}*/(document),
 60             iterator = odtDocument.getIteratorAtPosition(position),
 61             container = iterator.container(),
 62             annotationNode,
 63             annotationEnd;
 64 
 65         while (!(container.namespaceURI === odf.Namespaces.officens
 66             && container.localName === 'annotation')) {
 67             container = container.parentNode;
 68         }
 69         if (container === null) {
 70             return false;
 71         }
 72 
 73         annotationNode = /**@type{!odf.AnnotationElement}*/(container);
 74         annotationEnd = annotationNode.annotationEndElement;
 75 
 76         // Untrack and unwrap annotation
 77         odtDocument.getOdfCanvas().forgetAnnotations();
 78 
 79         /**
 80          * @param {!Node} node
 81          */
 82         function insert(node) {
 83             /**@type{!Node}*/(annotationNode).parentNode.insertBefore(node, annotationNode);
 84         }
 85         // Move all cursors - outside and before the annotation node
 86         domUtils.getElementsByTagNameNS(annotationNode, 'urn:webodf:names:cursor', 'cursor').forEach(insert);
 87         domUtils.getElementsByTagNameNS(annotationNode, 'urn:webodf:names:cursor', 'anchor').forEach(insert);
 88 
 89         // Delete start and end
 90         annotationNode.parentNode.removeChild(annotationNode);
 91         if (annotationEnd) {
 92             annotationEnd.parentNode.removeChild(annotationEnd);
 93         }
 94         // The specified position is the first walkable step in the annotation. The position is always just before the first point of change
 95         odtDocument.emit(ops.OdtDocument.signalStepsRemoved, {position: position > 0 ? position - 1 : position});
 96 
 97         odtDocument.fixCursorPositions();
 98         odtDocument.getOdfCanvas().refreshAnnotations();
 99         return true;
100     };
101 
102     /**
103      * @return {!ops.OpRemoveAnnotation.Spec}
104      */
105     this.spec = function () {
106         return {
107             optype: "RemoveAnnotation",
108             memberid: memberid,
109             timestamp: timestamp,
110             position: position,
111             length: length
112         };
113     };
114 };
115 /**@typedef{{
116     optype:string,
117     memberid:string,
118     timestamp:number,
119     position:number,
120     length:number
121 }}*/
122 ops.OpRemoveAnnotation.Spec;
123 /**@typedef{{
124     memberid:string,
125     timestamp:(number|undefined),
126     position:number,
127     length:number
128 }}*/
129 ops.OpRemoveAnnotation.InitSpec;
130