1 /** 2 * Copyright (C) 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, odf, runtime*/ 26 27 /** 28 * @constructor 29 * @implements ops.Operation 30 */ 31 ops.OpInsertTable = function OpInsertTable() { 32 "use strict"; 33 34 var memberid, timestamp, initialRows, initialColumns, position, tableName, tableStyleName, 35 tableColumnStyleName, 36 /**@type{!Array.<!Array.<string>>}*/ 37 tableCellStyleMatrix, 38 /**@const*/ 39 tablens = "urn:oasis:names:tc:opendocument:xmlns:table:1.0", 40 /**@const*/ 41 textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0", 42 odfUtils = odf.OdfUtils; 43 44 /** 45 * @param {!ops.OpInsertTable.InitSpec} data 46 */ 47 this.init = function (data) { 48 memberid = data.memberid; 49 timestamp = data.timestamp; 50 position = data.position; 51 initialRows = data.initialRows; 52 initialColumns = data.initialColumns; 53 tableName = data.tableName; 54 tableStyleName = data.tableStyleName; 55 tableColumnStyleName = data.tableColumnStyleName; 56 tableCellStyleMatrix = data.tableCellStyleMatrix; 57 }; 58 59 this.isEdit = true; 60 this.group = undefined; 61 62 /** 63 * @param {!number} row 64 * @param {!number} column 65 * @return {!string|undefined} 66 */ 67 function getCellStyleName(row, column) { 68 var rowStyles; 69 if (tableCellStyleMatrix.length === 1) { 70 rowStyles = tableCellStyleMatrix[0]; 71 } else if (tableCellStyleMatrix.length === 3) { 72 switch (row) { 73 case 0: 74 rowStyles = tableCellStyleMatrix[0]; 75 break; 76 case initialRows - 1: 77 rowStyles = tableCellStyleMatrix[2]; 78 break; 79 default: 80 rowStyles = tableCellStyleMatrix[1]; 81 break; 82 } 83 } else { 84 rowStyles = tableCellStyleMatrix[row]; 85 } 86 87 if (rowStyles.length === 1) { 88 return rowStyles[0]; 89 } 90 if (rowStyles.length === 3) { 91 switch (column) { 92 case 0: 93 return rowStyles[0]; 94 case initialColumns - 1: 95 return rowStyles[2]; 96 default: 97 return rowStyles[1]; 98 } 99 } 100 return rowStyles[column]; 101 } 102 103 /** 104 * @param {!Document} document 105 * @return {!Element} 106 */ 107 function createTableNode(document) { 108 var tableNode = document.createElementNS(tablens, "table:table"), 109 columns = document.createElementNS(tablens, "table:table-column"), 110 row, cell, paragraph, 111 rowCounter, columnCounter, cellStyleName; 112 113 if (tableStyleName) { 114 tableNode.setAttributeNS(tablens, "table:style-name", tableStyleName); 115 } 116 if (tableName) { 117 tableNode.setAttributeNS(tablens, "table:name", tableName); 118 } 119 120 columns.setAttributeNS(tablens, "table:number-columns-repeated", initialColumns); 121 if (tableColumnStyleName) { 122 columns.setAttributeNS(tablens, "table:style-name", tableColumnStyleName); 123 } 124 125 tableNode.appendChild(columns); 126 for (rowCounter = 0; rowCounter < initialRows; rowCounter += 1) { 127 row = document.createElementNS(tablens, "table:table-row"); 128 for (columnCounter = 0; columnCounter < initialColumns; columnCounter += 1) { 129 cell = document.createElementNS(tablens, "table:table-cell"); 130 cellStyleName = getCellStyleName(rowCounter, columnCounter); 131 if (cellStyleName) { 132 cell.setAttributeNS(tablens, "table:style-name", cellStyleName); 133 } 134 paragraph = document.createElementNS(textns, "text:p"); 135 cell.appendChild(paragraph); 136 row.appendChild(cell); 137 } 138 tableNode.appendChild(row); 139 } 140 return tableNode; 141 } 142 143 /** 144 * @param {!ops.Document} document 145 */ 146 this.execute = function (document) { 147 var odtDocument = /**@type{ops.OdtDocument}*/(document), 148 domPosition = odtDocument.getTextNodeAtStep(position), 149 rootNode = odtDocument.getRootNode(), 150 previousSibling, 151 tableNode; 152 153 if (domPosition) { 154 tableNode = createTableNode(odtDocument.getDOMDocument()); 155 // For now assume the table should be inserted after the current paragraph 156 // or failing that, as the first element in the root node 157 previousSibling = odfUtils.getParagraphElement(domPosition.textNode); 158 rootNode.insertBefore(tableNode, previousSibling.nextSibling); 159 // The parent table counts for 1 position, and 1 paragraph is added per cell 160 odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position: position}); 161 162 odtDocument.getOdfCanvas().refreshSize(); 163 odtDocument.emit(ops.OdtDocument.signalTableAdded, { 164 tableElement: tableNode, 165 memberId: memberid, 166 timeStamp: timestamp 167 }); 168 169 odtDocument.getOdfCanvas().rerenderAnnotations(); 170 return true; 171 } 172 return false; 173 }; 174 175 /** 176 * @return {!ops.OpInsertTable.Spec} 177 */ 178 this.spec = function () { 179 return { 180 optype: "InsertTable", 181 memberid: memberid, 182 timestamp: timestamp, 183 position: position, 184 initialRows: initialRows, 185 initialColumns: initialColumns, 186 tableName: tableName, 187 tableStyleName: tableStyleName, 188 tableColumnStyleName: tableColumnStyleName, 189 tableCellStyleMatrix: tableCellStyleMatrix 190 }; 191 }; 192 }; 193 /**@typedef{{ 194 optype:string, 195 memberid:string, 196 timestamp:number, 197 position:number, 198 initialRows:number, 199 initialColumns:number, 200 tableName:string, 201 tableStyleName:string, 202 tableColumnStyleName:string, 203 tableCellStyleMatrix:!Array.<!Array.<string>> 204 }}*/ 205 ops.OpInsertTable.Spec; 206 /**@typedef{{ 207 memberid:string, 208 timestamp:(number|undefined), 209 position:number, 210 initialRows:number, 211 initialColumns:number, 212 tableName:string, 213 tableStyleName:string, 214 tableColumnStyleName:string, 215 tableCellStyleMatrix:!Array.<!Array.<string>> 216 }}*/ 217 ops.OpInsertTable.InitSpec; 218