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