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