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