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