UNPKG

@syncfusion/ej2-richtexteditor

Version:
660 lines (656 loc) 32 kB
import { closest } from '@syncfusion/ej2-base'; import { getCorrespondingColumns, getCorrespondingIndex, insertColGroupWithSizes } from './../../common/util'; /** * Handles table pasting operations within the editor * * This class provides functionality for pasting table content from one location to another, * handling complex scenarios such as: * - Merging and splitting cells * - Preserving row and column spans * - Managing cell content and styles * - Preventing overflow when pasting into selected regions * - Adjusting table structure to accommodate pasted content * * @hidden */ var TablePasting = /** @class */ (function () { function TablePasting() { this.allCells = []; this.hasCellsUpdated = false; this.preventOverflowCells = false; } /** * Handles pasting a table into the target table at the specified cell * * This method processes the inserted table and integrates it into the target location, * handling cell merging, content preservation, and structural adjustments. * When multiple cells are selected, it ensures proper distribution of content. * * @param {HTMLTableElement} insertedTable - The table being pasted * @param {NodeListOf<Element>} targetCells - Collection of cells where the paste operation targets * @returns {void} * @hidden */ TablePasting.prototype.handleTablePaste = function (insertedTable, targetCells) { if (!insertedTable || !targetCells || targetCells.length < 1) { return; } this.hasCellsUpdated = false; var targetCell = targetCells[0]; this.preventOverflowCells = targetCells.length > 1; var targetTable = this.getClosestTable(targetCell); if (!targetTable) { return; } var pastedRows = this.getTableRows(insertedTable); var startRowIndex = this.getRowIndex(targetCell); // Fix missing cells in existing rows this.allCells = getCorrespondingColumns(targetTable); var startCellIndex = this.getCellIndex(targetCell, startRowIndex); var pastedTableAllCells = getCorrespondingColumns(insertedTable); this.pasteMultipleRows(targetTable, pastedRows, startRowIndex, startCellIndex, pastedTableAllCells); if (this.hasCellsUpdated) { insertColGroupWithSizes(targetTable, true); } }; /* Gets the closest parent table of the given cell */ TablePasting.prototype.getClosestTable = function (cell) { return closest(cell, 'table'); }; /* Gets all table rows from the given table */ TablePasting.prototype.getTableRows = function (table) { var rows = []; var totalRows = table.rows.length; for (var i = 0; i < totalRows; i++) { var row = table.rows.item(i); if (row !== null) { rows.push(row); } } return rows; }; /* Gets the row index of a cell */ TablePasting.prototype.getRowIndex = function (cell) { var row = cell.parentElement; return row !== null ? row.rowIndex : 0; }; /* Gets the cell index of a cell */ TablePasting.prototype.getCellIndex = function (selectedCell, startRowIndex) { if (startRowIndex === void 0) { startRowIndex = 0; } for (var rowIndex = startRowIndex; rowIndex < this.allCells.length; rowIndex++) { var row = this.allCells[rowIndex]; for (var colIndex = 0; colIndex < row.length; colIndex++) { if (this.allCells[rowIndex][colIndex] === selectedCell) { return colIndex; } } } return selectedCell.cellIndex >= 0 ? selectedCell.cellIndex : 0; }; /* Pastes multiple rows into the target table, creating rows/columns if needed */ TablePasting.prototype.pasteMultipleRows = function (targetTable, pastedRows, startRowIndex, startCellIndex, pastedTableAllCells) { for (var i = 0; i < pastedRows.length; i++) { var pastedRow = pastedRows[i]; this.pasteRowContent(targetTable, pastedRow, startCellIndex, startRowIndex, pastedTableAllCells); } }; /* Ensures the row has at least the required number of cells */ TablePasting.prototype.ensureCellCount = function (row, requiredCellCount, presentCellCount) { if (presentCellCount < requiredCellCount) { this.hasCellsUpdated = true; while (presentCellCount < requiredCellCount) { var newCell = row.insertCell(); newCell.innerHTML = '<br>'; presentCellCount++; } } }; /* Gets or creates a row at the given index */ TablePasting.prototype.getOrCreateRow = function (table, rowIndex) { if (rowIndex < table.rows.length) { return table.rows.item(rowIndex); } if (!this.preventOverflowCells) { var newRow = table.insertRow(); this.fillRowWithEmptyCells(newRow, this.getMaxColumnCount(table.rows[0].cells)); this.allCells = getCorrespondingColumns(table); return newRow; } return null; }; /* Fills a row with empty cells to match a given column count */ TablePasting.prototype.fillRowWithEmptyCells = function (row, columnCount) { for (var i = 0; i < columnCount; i++) { var newCell = row.insertCell(); newCell.innerHTML = '<br>'; } }; /* Returns the maximum number of columns in the table */ TablePasting.prototype.getMaxColumnCount = function (cellColl) { var cellCount = 0; for (var cell = 0; cell < cellColl.length; cell++) { cellCount += cellColl[cell].colSpan; } return cellCount; }; /* Pastes the content from the pasted row into the target row starting from a specific cell */ TablePasting.prototype.pasteRowContent = function (targetTable, pastedRow, startCellIndex, startRowIndex, pastedTableAllCells) { var pastedCells = this.getRowCells(pastedRow); this.allCells = getCorrespondingColumns(targetTable); if (!this.preventOverflowCells) { this.ensureTargetTableCapacity(targetTable, startCellIndex, pastedTableAllCells); } for (var i = 0; i < pastedCells.length; i++) { var pastedCell = pastedCells[i]; this.allCells = getCorrespondingColumns(targetTable); var cellIndex = getCorrespondingIndex(pastedCell, pastedTableAllCells); var currentTargetRowIndex = startRowIndex + cellIndex[0]; var colIndex = startCellIndex + cellIndex[1]; if (this.preventOverflowCells) { this.adjustCellSpans(pastedCell, currentTargetRowIndex, colIndex, targetTable); } var targetRow = this.getOrCreateRow(targetTable, currentTargetRowIndex); if (!targetRow) { continue; } var targetCell = this.allCells[currentTargetRowIndex][colIndex]; if (!targetCell || this.shouldSkipCell(targetCell)) { continue; } this.copyCellAttributes(targetCell, pastedCell, currentTargetRowIndex, colIndex, targetTable, targetRow); } }; /* * Adjusts rowspan and colspan attributes of a cell to prevent overflow */ TablePasting.prototype.adjustCellSpans = function (cell, rowIndex, colIndex, targetTable) { var rowSpan = parseInt(cell.getAttribute('rowspan') || '1', 10); var colSpan = parseInt(cell.getAttribute('colspan') || '1', 10); // Adjust rowspan if needed if (rowSpan > 1) { var adjustedRowSpan = this.calculateAdjustedRowSpan(cell, rowIndex, colIndex, rowSpan, targetTable); cell.setAttribute('rowspan', adjustedRowSpan.toString()); } // Adjust colspan if needed if (colSpan > 1) { var adjustedColSpan = this.calculateAdjustedColSpan(rowIndex, colIndex, colSpan); cell.setAttribute('colspan', adjustedColSpan.toString()); } }; /* * Calculates the adjusted rowspan value based on available target cells */ TablePasting.prototype.calculateAdjustedRowSpan = function (cell, rowIndex, colIndex, originalRowSpan, targetTable) { var adjustedRowSpan = originalRowSpan; for (var offset = 1; offset < originalRowSpan; offset++) { var targetRowIndex = rowIndex + offset; var targetRow = this.getOrCreateRow(targetTable, targetRowIndex); if (!targetRow) { --adjustedRowSpan; } else { var nextTargetCell = this.allCells[targetRowIndex][colIndex]; if (!nextTargetCell || this.shouldSkipCell(nextTargetCell)) { --adjustedRowSpan; } } } var rowSpanDifference = originalRowSpan - adjustedRowSpan; if (rowSpanDifference > 0) { this.adjustCellHeights(cell, null, adjustedRowSpan, rowSpanDifference); } return adjustedRowSpan; }; /* * Calculates the adjusted colspan value based on available target cells */ TablePasting.prototype.calculateAdjustedColSpan = function (rowIndex, colIndex, originalColSpan) { var adjustedColSpan = originalColSpan; for (var colOffset = 0; colOffset < originalColSpan; colOffset++) { var columnIndex = colIndex + colOffset; var nextTargetCell = this.allCells[rowIndex][columnIndex]; if (!nextTargetCell || this.shouldSkipCell(nextTargetCell)) { --adjustedColSpan; } } return adjustedColSpan; }; /* * Ensures the target table has enough cells to accommodate the pasted content */ TablePasting.prototype.ensureTargetTableCapacity = function (table, startCellIndex, pastedCells) { if (!pastedCells[0]) { return; } for (var i = 0; i < table.rows.length; i++) { var row = table.rows[i]; var presentCellCount = this.allCells[i].length; var requiredCellCount = startCellIndex + pastedCells[0].length; this.ensureCellCount(row, requiredCellCount, presentCellCount); } }; /* * Determines if a cell should be skipped during paste operation */ TablePasting.prototype.shouldSkipCell = function (cell) { return this.preventOverflowCells && !(cell.classList.contains('e-cell-select') && cell.classList.contains('e-multi-cells-select')); }; /* Gets all cells from a row */ TablePasting.prototype.getRowCells = function (row) { var cells = []; var totalCells = row.cells.length; for (var i = 0; i < totalCells; i++) { var cell = row.cells.item(i); if (cell !== null) { cells.push(cell); } } return cells; }; /* * Copies the attributes and styles from a source table cell to a target cell, * handling both rowspan and colspan, and updating the table structure accordingly. */ TablePasting.prototype.copyCellAttributes = function (targetCell, sourceCell, rowIndex, targetCellIndex, targetTable, targetRow) { if (!sourceCell) { return; } // Handle cell insertion location targetCell = this.handleCellInsertLocation(targetCell, targetRow, rowIndex, targetCellIndex); // Handle parent element mismatch targetCell = this.handleInsertRowMismatch(targetCell, targetRow, rowIndex, targetCellIndex, targetTable); // Get span attributes var spanAttributes = this.getCellSpanAttributes(targetCell, sourceCell); // Handle colspan changes targetCell = this.handleColspanChanges(targetCell, spanAttributes.oldColSpan, spanAttributes.newColSpan, rowIndex, targetCellIndex, targetRow, targetTable); // Handle rowspan changes targetCell = this.handleRowspanChanges(targetCell, spanAttributes.oldRowSpan, spanAttributes.newRowSpan, rowIndex, targetCellIndex, targetTable, spanAttributes.newColSpan); // Apply content and styles targetCell.innerHTML = sourceCell.innerHTML; targetCell.style.cssText = sourceCell.style.cssText; }; /* * Gets span attributes from cells */ TablePasting.prototype.getCellSpanAttributes = function (targetCell, sourceCell) { return { oldRowSpan: parseInt(targetCell.getAttribute('rowspan') || '1', 10), oldColSpan: parseInt(targetCell.getAttribute('colspan') || '1', 10), newRowSpan: parseInt(sourceCell.getAttribute('rowspan') || '1', 10), newColSpan: parseInt(sourceCell.getAttribute('colspan') || '1', 10) }; }; /* * Handles cell insertion location adjustments */ TablePasting.prototype.handleCellInsertLocation = function (targetCell, targetRow, rowIndex, targetCellIndex) { var cellInsertLocation = this.getInsertionColIndex(targetCellIndex, targetRow, rowIndex); if (cellInsertLocation < targetCellIndex) { var currentColSpan = parseInt(targetCell.getAttribute('colspan') || '1', 10); var newColSpan = currentColSpan - (targetCellIndex - cellInsertLocation); if (newColSpan > 0) { var insertAt = cellInsertLocation + 1; var newCell = targetRow.insertCell(insertAt); newCell.innerHTML = '<br>'; // fill with empty newCell.style.cssText = targetCell.style.cssText; newCell.className = targetCell.className; targetCell.setAttribute('colspan', (currentColSpan - newColSpan).toString()); this.allCells[rowIndex][targetCellIndex] = newCell; newCell.setAttribute('colspan', newColSpan.toString()); if (targetCell.hasAttribute('rowspan')) { newCell.setAttribute('rowspan', targetCell.getAttribute('rowspan')); } return newCell; } } return targetCell; }; /* * Handles parent element mismatch between cell and row */ TablePasting.prototype.handleInsertRowMismatch = function (targetCell, targetRow, rowIndex, targetCellIndex, targetTable) { if (targetCell.parentElement !== targetRow) { var rowSpan = parseInt(targetCell.getAttribute('rowspan') || '1', 10); var targetRowIndex = this.getRowIndex(targetCell); var remainingRowSpan = rowSpan - (rowIndex - targetRowIndex); var newRowSpan = rowSpan - remainingRowSpan; if (rowSpan > 1) { this.removeRowspanAttributes(targetTable, rowIndex, targetCellIndex); var newCell = this.allCells[rowIndex][targetCellIndex]; newCell.innerHTML = targetCell.innerHTML; newCell.style.cssText = targetCell.style.cssText; newCell.className = targetCell.className; if (targetCell.hasAttribute('colspan')) { newCell.setAttribute('colspan', targetCell.getAttribute('colspan')); } if (remainingRowSpan === 1) { newCell.removeAttribute('rowspan'); } else { newCell.setAttribute('rowspan', remainingRowSpan.toString()); } if (newRowSpan > 1) { targetCell.setAttribute('rowspan', newRowSpan.toString()); } else { targetCell.removeAttribute('rowspan'); } this.adjustCellHeights(targetCell, newCell, newRowSpan, remainingRowSpan); return newCell; } } return targetCell; }; /* * Adjusts cell heights based on rowspan distribution */ TablePasting.prototype.adjustCellHeights = function (targetCell, newCell, newRowSpan, remainingRowSpan) { if (targetCell.style.height) { var heightStr = targetCell.style.height; var heightValue = parseFloat(heightStr); // Check if we got a valid number if (!isNaN(heightValue) && heightValue > 0) { var totalRowSpan = newRowSpan + remainingRowSpan; var height = heightValue / totalRowSpan; targetCell.style.height = (newRowSpan * height) + 'px'; if (newCell) { newCell.style.height = (remainingRowSpan * height) + 'px'; } } } }; /* * Handles rowspan changes between old and new values */ TablePasting.prototype.handleRowspanChanges = function (targetCell, oldRowSpan, newRowSpan, rowIndex, targetCellIndex, targetTable, newColSpan) { // Decrease rowspan to 1 if (oldRowSpan > 1 && newRowSpan <= 1) { var remainingRowSpan = oldRowSpan - newRowSpan; var nextRowIndex = rowIndex + 1; this.removeRowspanAttributes(targetTable, nextRowIndex, targetCellIndex); var newCell = this.allCells[nextRowIndex][targetCellIndex]; newCell.innerHTML = targetCell.innerHTML; newCell.style.cssText = targetCell.style.cssText; newCell.className = targetCell.className; if (targetCell.hasAttribute('colspan')) { newCell.setAttribute('colspan', targetCell.getAttribute('colspan')); } if (remainingRowSpan === 1) { newCell.removeAttribute('rowspan'); } else { newCell.setAttribute('rowspan', remainingRowSpan.toString()); } targetCell.removeAttribute('rowspan'); this.adjustCellHeights(targetCell, newCell, newRowSpan, remainingRowSpan); } // Both have rowspan > 1 else if (oldRowSpan > 1 && newRowSpan > 1) { var delta = newRowSpan - oldRowSpan; if (delta > 0) { // Increase rowspan this.applyRowspanAttributes(targetTable, rowIndex, targetCellIndex, newRowSpan, newColSpan); targetCell.setAttribute('rowspan', newRowSpan.toString()); } else if (delta < 0) { // Decrease rowspan var nextRowIndex = rowIndex + newRowSpan; this.removeRowspanAttributes(targetTable, nextRowIndex, targetCellIndex); var newCell = this.allCells[nextRowIndex][targetCellIndex]; newCell.innerHTML = targetCell.innerHTML; newCell.style.cssText = targetCell.style.cssText; newCell.className = targetCell.className; if (targetCell.hasAttribute('colspan')) { newCell.setAttribute('colspan', targetCell.getAttribute('colspan')); } if (-delta === 1) { newCell.removeAttribute('rowspan'); } else { newCell.setAttribute('rowspan', (-delta).toString()); } targetCell.setAttribute('rowspan', newRowSpan.toString()); this.adjustCellHeights(targetCell, newCell, newRowSpan, -delta); } } // Increase rowspan from 1 else if (newRowSpan > 1 && oldRowSpan <= 1) { this.applyRowspanAttributes(targetTable, rowIndex, targetCellIndex, newRowSpan, newColSpan); targetCell.setAttribute('rowspan', newRowSpan.toString()); } return targetCell; }; /* * Handles colspan changes between old and new values */ TablePasting.prototype.handleColspanChanges = function (targetCell, oldColSpan, newColSpan, rowIndex, targetCellIndex, targetRow, targetTable) { // Decrease colspan to 1 if (oldColSpan > 1 && newColSpan <= 1) { var targetNewCellSpan = oldColSpan - newColSpan; this.insertFollowingSiblings(targetRow, targetCellIndex, rowIndex, newColSpan); if (targetNewCellSpan === 1) { targetCell.removeAttribute('colspan'); } else { targetCell.setAttribute('colspan', targetNewCellSpan.toString()); } targetCell.innerHTML = ''; var newCell = this.allCells[rowIndex][targetCellIndex]; newCell.className = targetCell.className; targetCell = newCell; } // Increase colspan from 1 else if (newColSpan > 1 && oldColSpan <= 1) { var deleteCellCount = newColSpan - oldColSpan; if (deleteCellCount > 0) { this.removeFollowingSiblings(this.allCells[rowIndex], targetCellIndex + oldColSpan, deleteCellCount, targetTable, targetRow, rowIndex); targetCell.setAttribute('colspan', newColSpan.toString()); } } // Both have colspan > 1 else if (newColSpan > 1 && oldColSpan > 1) { var colSpanDiff = newColSpan - oldColSpan; if (colSpanDiff > 0) { // Increase colspan this.removeFollowingSiblings(this.allCells[rowIndex], targetCellIndex + oldColSpan, colSpanDiff, targetTable, targetRow, rowIndex); targetCell.setAttribute('colspan', newColSpan.toString()); } else if (colSpanDiff < 0) { // Decrease colspan this.insertFollowingSiblings(targetRow, targetCellIndex, rowIndex, 1); targetCell.setAttribute('colspan', (-colSpanDiff).toString()); targetCell.innerHTML = ''; var newCell = this.allCells[rowIndex][targetCellIndex]; newCell.className = targetCell.className; targetCell = newCell; targetCell.setAttribute('colspan', newColSpan.toString()); } } return targetCell; }; /* Applies rowspan logic by removing redundant cells and tracking rowspan spans */ TablePasting.prototype.applyRowspanAttributes = function (targetTable, baseRowIndex, startCellIndex, rowSpan, colSpan) { for (var offset = 1; offset < rowSpan; offset++) { var targetRowIndex = baseRowIndex + offset; for (var colOffset = 0; colOffset < colSpan; colOffset++) { var columnIndex = startCellIndex + colOffset; this.processRowspanCell(targetTable, targetRowIndex, columnIndex); } } }; /* Processes a single cell for rowspan application */ TablePasting.prototype.processRowspanCell = function (targetTable, targetRowIndex, columnIndex) { var targetRow = this.getOrCreateRow(targetTable, targetRowIndex); var cellToRemove = this.allCells[targetRowIndex][columnIndex]; var index = Array.prototype.indexOf.call(targetRow.cells, cellToRemove); if (!cellToRemove || !cellToRemove.parentElement || index === -1) { return; } var currentColSpan = parseInt(cellToRemove.getAttribute('colspan') || '1', 10); var currentRowSpan = parseInt(cellToRemove.getAttribute('rowspan') || '1', 10); var shouldRemoveCompletely = currentColSpan <= 1 && currentRowSpan <= 1; if (!shouldRemoveCompletely) { this.handleComplexCellRemoval(targetTable, targetRow, cellToRemove, targetRowIndex, columnIndex, currentColSpan, currentRowSpan); } targetRow.removeChild(cellToRemove); this.allCells[targetRowIndex][columnIndex] = null; }; /* Handles removal of cells with colspan or rowspan */ TablePasting.prototype.handleComplexCellRemoval = function (targetTable, targetRow, cellToRemove, targetRowIndex, columnIndex, currentColSpan, currentRowSpan) { if (currentColSpan > 1) { this.handleColspanCellRemoval(targetRow, cellToRemove, targetRowIndex, columnIndex, currentColSpan); } if (currentRowSpan > 1) { this.handleRowspanCellRemoval(targetTable, cellToRemove, targetRowIndex, columnIndex, currentRowSpan); } }; /* Handles removal of a cell with colspan */ TablePasting.prototype.handleColspanCellRemoval = function (targetRow, cellToRemove, targetRowIndex, columnIndex, currentColSpan) { this.insertFollowingSiblings(targetRow, columnIndex, targetRowIndex, 1); var newColSpan = currentColSpan - 1; var newCell = this.allCells[targetRowIndex][columnIndex]; newCell.innerHTML = '<br>'; newCell.style.cssText = cellToRemove.style.cssText; newCell.className = cellToRemove.className; if (newColSpan === 1) { newCell.removeAttribute('colspan'); } else { newCell.setAttribute('colspan', newColSpan.toString()); } }; /* Handles removal of a cell with rowspan */ TablePasting.prototype.handleRowspanCellRemoval = function (targetTable, cellToRemove, targetRowIndex, columnIndex, currentRowSpan) { this.removeRowspanAttributes(targetTable, targetRowIndex + 1, columnIndex); var newCell = this.allCells[targetRowIndex + 1][columnIndex]; var newRowSpan = currentRowSpan - 1; newCell.innerHTML = cellToRemove.innerHTML; newCell.style.cssText = cellToRemove.style.cssText; newCell.className = cellToRemove.className; if (newRowSpan === 1) { newCell.removeAttribute('rowspan'); } else { newCell.setAttribute('rowspan', newRowSpan.toString()); } this.adjustCellHeights(cellToRemove, newCell, currentRowSpan, newRowSpan); }; /* Removes rowspan logic by adding cells to rows that were previously spanned */ TablePasting.prototype.removeRowspanAttributes = function (targetTable, nextRowIndex, targetCellIndex) { var nextRow = this.getOrCreateRow(targetTable, nextRowIndex); var insertionColIndex = this.getInsertionColIndex(targetCellIndex, nextRow, nextRowIndex); var newCell = nextRow.insertCell(insertionColIndex); this.allCells[nextRowIndex][targetCellIndex] = newCell; }; /* Retrieves or creates a row at the specified index in the table */ TablePasting.prototype.getInsertionColIndex = function (targetCellIndex, nextRow, rowIndex) { // Handle empty rows if (!nextRow || nextRow.cells.length === 0) { return 0; } var insertionColIndex = targetCellIndex; var rowCells = this.allCells[rowIndex] || []; // Try to find a matching cell by incrementing the index insertionColIndex = this.findMatchingCellIndex(rowCells, nextRow, insertionColIndex, true); var visualStartIndex = rowCells.indexOf(nextRow.cells[0]); // If no match found or index out of bounds, try decrementing approach if (rowCells.length <= insertionColIndex || (nextRow.cells.length <= targetCellIndex && visualStartIndex !== -1 && visualStartIndex < insertionColIndex)) { insertionColIndex = targetCellIndex; insertionColIndex = this.findMatchingCellIndex(rowCells, nextRow, insertionColIndex, false); } // Get the actual cell index if a cell was found if (rowCells[insertionColIndex]) { var cell = rowCells[insertionColIndex]; insertionColIndex = cell.cellIndex; // Adjust index for cases where target exceeds available cells if (nextRow.cells.length <= targetCellIndex && visualStartIndex !== -1 && targetCellIndex > visualStartIndex) { insertionColIndex++; } } else { // Fallback to the original target index insertionColIndex = targetCellIndex; } return insertionColIndex; }; /* * Finds a matching cell index by incrementing or decrementing from the starting index */ TablePasting.prototype.findMatchingCellIndex = function (rowCells, nextRow, startIndex, increment) { var index = startIndex; while (rowCells && index >= 0 && rowCells[index] && nextRow && Array.prototype.indexOf.call(nextRow.cells, rowCells[index]) === -1) { index = increment ? index + 1 : index - 1; } return index; }; /* Removes (colSpan - 1) cells following the given cell index in a row */ TablePasting.prototype.removeFollowingSiblings = function (row, deleteCellIndex, colSpan, targetTable, targetRow, targetRowIndex) { for (var offset = 0; offset < colSpan; offset++) { var cellToRemove = row[deleteCellIndex]; if (cellToRemove && cellToRemove.parentElement) { var currentColSpan = parseInt(cellToRemove.getAttribute('colspan') || '1', 10); var currentRowSpan = parseInt(cellToRemove.getAttribute('rowspan') || '1', 10); var shouldRemoveCompletely = currentColSpan <= 1 && currentRowSpan <= 1; if (!shouldRemoveCompletely) { this.handleComplexCellRemoval(targetTable, targetRow, cellToRemove, targetRowIndex, deleteCellIndex, currentColSpan, currentRowSpan); } cellToRemove.parentElement.removeChild(cellToRemove); row[deleteCellIndex] = null; } } }; TablePasting.prototype.insertFollowingSiblings = function (row, startCellIndex, rowIndex, oldColSpan) { var cellInsertLocation = this.getInsertionColIndex(startCellIndex, row, rowIndex); for (var offset = 0; offset < oldColSpan; offset++) { var newCell = row.insertCell(cellInsertLocation); newCell.innerHTML = '<br>'; // fill with empty this.allCells[rowIndex][startCellIndex] = newCell; } }; /** * Retrieves a valid table element from the pasted content if it exists and is valid * * This method examines the pasted content to find a table element. It handles three scenarios: * 1. The inserted node is already a table * 2. The inserted node contains a table that needs to be extracted * 3. The inserted node contains a table with wrapper elements that should be preserved * * If the content is not a valid table or a valid wrapper around a table, returns null. * * @param {HTMLElement} insertedNode - The node that was pasted into the editor * @returns {HTMLElement | null} - The valid table element or wrapper, or null if no valid table found * @hidden */ TablePasting.prototype.getValidTableFromPaste = function (insertedNode) { if (insertedNode.nodeName.toLowerCase() === 'table') { return insertedNode; } var tableElement = insertedNode.querySelector('table'); if (!tableElement) { return null; } return this.getWrapperNodeForTable(insertedNode, tableElement); }; /* * Retrieves the wrapper node around the table if it is valid (only the table inside a single wrapper element). * If the wrapper is invalid or contains extra elements, returns null. */ TablePasting.prototype.getWrapperNodeForTable = function (container, tableElement) { var currentNode = container; while (currentNode !== tableElement) { var nonCommentChildren = Array.from(currentNode.childNodes) .filter(function (node) { return node.nodeType !== Node.COMMENT_NODE && !(node.nodeType === Node.TEXT_NODE && node.textContent.trim() === ''); }); if (nonCommentChildren.length !== 1) { return null; } currentNode = nonCommentChildren[0]; } return currentNode; }; return TablePasting; }()); export { TablePasting };