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 runtime, odf, ops*/ 26 27 /** 28 * @constructor 29 * @implements ops.Operation 30 */ 31 ops.OpUpdateParagraphStyle = function OpUpdateParagraphStyle() { 32 "use strict"; 33 34 var memberid, timestamp, styleName, 35 setProperties, 36 /**@type{{attributes:string}}*/ 37 removedProperties, 38 /**@const*/ 39 paragraphPropertiesName = 'style:paragraph-properties', 40 /**@const*/ 41 textPropertiesName = 'style:text-properties', 42 /**@const*/ 43 stylens = odf.Namespaces.stylens; 44 45 /** 46 * Removes attributes of a node by the names listed in removedAttributeNames. 47 * @param {!Element} node 48 * @param {!string} removedAttributeNames 49 */ 50 function removedAttributesFromStyleNode(node, removedAttributeNames) { 51 var i, attributeNameParts, 52 /**@type{!Array.<string>}*/ 53 attributeNameList = removedAttributeNames ? removedAttributeNames.split(',') : []; 54 55 for (i = 0; i < attributeNameList.length; i += 1) { 56 attributeNameParts = attributeNameList[i].split(":"); 57 // TODO: ensure all used prefixes have a namespaces listed 58 node.removeAttributeNS(/**@type{string}*/(odf.Namespaces.lookupNamespaceURI(attributeNameParts[0])), attributeNameParts[1]); 59 } 60 } 61 62 /** 63 * @param {!ops.OpUpdateParagraphStyle.InitSpec} data 64 */ 65 this.init = function (data) { 66 memberid = data.memberid; 67 timestamp = data.timestamp; 68 styleName = data.styleName; 69 setProperties = data.setProperties; 70 removedProperties = data.removedProperties; 71 }; 72 73 this.isEdit = true; 74 this.group = undefined; 75 76 /** 77 * @param {!ops.Document} document 78 */ 79 this.execute = function (document) { 80 var odtDocument = /**@type{ops.OdtDocument}*/(document), 81 formatting = odtDocument.getFormatting(), 82 styleNode, object, 83 paragraphPropertiesNode, textPropertiesNode; 84 85 if (styleName !== "") { 86 // Common Style 87 styleNode = formatting.getStyleElement(styleName, 'paragraph'); 88 } else { 89 // Default Style 90 styleNode = formatting.getDefaultStyleElement('paragraph'); 91 } 92 93 if (styleNode) { 94 paragraphPropertiesNode = /**@type{Element}*/(styleNode.getElementsByTagNameNS(stylens, 'paragraph-properties').item(0)); 95 textPropertiesNode = /**@type{Element}*/(styleNode.getElementsByTagNameNS(stylens, 'text-properties').item(0)); 96 97 if (setProperties) { 98 formatting.updateStyle(styleNode, setProperties); 99 } 100 101 // remove attributes in the style nodes 102 if (removedProperties) { 103 object = /**@type{{attributes:string}}*/(removedProperties[paragraphPropertiesName]); 104 if (paragraphPropertiesNode && object) { 105 removedAttributesFromStyleNode(paragraphPropertiesNode, object.attributes); 106 if (paragraphPropertiesNode.attributes.length === 0) { 107 styleNode.removeChild(paragraphPropertiesNode); 108 } 109 } 110 111 object = /**@type{{attributes:string}}*/(removedProperties[textPropertiesName]); 112 if (textPropertiesNode && object) { 113 // TODO: check if fontname can be removed from font-face-declaration 114 removedAttributesFromStyleNode(textPropertiesNode, object.attributes); 115 if (textPropertiesNode.attributes.length === 0) { 116 styleNode.removeChild(textPropertiesNode); 117 } 118 } 119 120 removedAttributesFromStyleNode(styleNode, removedProperties.attributes); 121 } 122 123 odtDocument.getOdfCanvas().refreshCSS(); 124 odtDocument.emit(ops.OdtDocument.signalParagraphStyleModified, styleName); 125 odtDocument.getOdfCanvas().rerenderAnnotations(); 126 return true; 127 } 128 return false; 129 }; 130 131 /** 132 * @return {!ops.OpUpdateParagraphStyle.Spec} 133 */ 134 this.spec = function () { 135 return { 136 optype: "UpdateParagraphStyle", 137 memberid: memberid, 138 timestamp: timestamp, 139 styleName: styleName, 140 setProperties: setProperties, 141 removedProperties: removedProperties 142 }; 143 }; 144 }; 145 /**@typedef{{ 146 optype:string, 147 memberid:string, 148 timestamp:number, 149 styleName:string, 150 setProperties:Object, 151 removedProperties:{attributes:string} 152 }}*/ 153 ops.OpUpdateParagraphStyle.Spec; 154 /**@typedef{{ 155 memberid:string, 156 timestamp:(number|undefined), 157 styleName:string, 158 setProperties:Object, 159 removedProperties:{attributes:string} 160 }}*/ 161 ops.OpUpdateParagraphStyle.InitSpec; 162