|
|
@@ -104,116 +104,113 @@ export default class TableClipboard extends Plugin {
|
|
|
|
|
|
const table = getTable( content );
|
|
|
|
|
|
- if ( table ) {
|
|
|
- evt.stop();
|
|
|
-
|
|
|
- if ( selectedTableCells.length === 1 ) {
|
|
|
- // @if CK_DEBUG // console.log( 'Single table cell is selected. Not handled.' );
|
|
|
-
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const tableUtils = this.editor.plugins.get( 'TableUtils' );
|
|
|
+ if ( !table ) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- const rowIndexes = getRowIndexes( selectedTableCells );
|
|
|
- const columnIndexes = getColumnIndexes( selectedTableCells );
|
|
|
- const selectionHeight = rowIndexes.last - rowIndexes.first + 1;
|
|
|
- const selectionWidth = columnIndexes.last - columnIndexes.first + 1;
|
|
|
- const insertHeight = tableUtils.getRows( table );
|
|
|
- const insertWidth = tableUtils.getColumns( table );
|
|
|
+ evt.stop();
|
|
|
|
|
|
- const contentTable = findAncestor( 'table', selectedTableCells[ 0 ] );
|
|
|
+ if ( selectedTableCells.length === 1 ) {
|
|
|
+ // @if CK_DEBUG // console.log( 'Single table cell is selected. Not handled.' );
|
|
|
|
|
|
- // TODO: Temporally block non-rectangular selection.
|
|
|
- if ( !isSelectionRectangular( this.editor.model.document.selection, tableUtils ) ) {
|
|
|
- // @if CK_DEBUG // console.log( 'Selection is not rectangular (non-mergeable) - pasting disabled.' );
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- return;
|
|
|
- }
|
|
|
+ const tableUtils = this.editor.plugins.get( 'TableUtils' );
|
|
|
+ const rowIndexes = getRowIndexes( selectedTableCells );
|
|
|
+ const columnIndexes = getColumnIndexes( selectedTableCells );
|
|
|
+ const selectionHeight = rowIndexes.last - rowIndexes.first + 1;
|
|
|
+ const selectionWidth = columnIndexes.last - columnIndexes.first + 1;
|
|
|
+ const insertHeight = tableUtils.getRows( table );
|
|
|
+ const insertWidth = tableUtils.getColumns( table );
|
|
|
+ const contentTable = findAncestor( 'table', selectedTableCells[ 0 ] );
|
|
|
+ if ( !isSelectionRectangular( this.editor.model.document.selection, tableUtils ) ) {
|
|
|
+ // @if CK_DEBUG // console.log( 'Selection is not rectangular (non-mergeable) - pasting disabled.' );
|
|
|
|
|
|
- // TODO: Temporally block block tables that are smaller than selection area.
|
|
|
- if ( selectionHeight > insertHeight || selectionWidth > insertWidth ) {
|
|
|
- // @if CK_DEBUG // console.log( 'Pasted table is smaller than selection area.' );
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- return;
|
|
|
- }
|
|
|
+ if ( selectionHeight > insertHeight || selectionWidth > insertWidth ) {
|
|
|
+ // @if CK_DEBUG // console.log( 'Pasted table is smaller than selection area.' );
|
|
|
|
|
|
- if ( selectionHeight < insertHeight || selectionWidth < insertWidth ) {
|
|
|
- // @if CK_DEBUG // console.log( 'Pasted table extends selection area.' );
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- return;
|
|
|
- }
|
|
|
+ if ( selectionHeight < insertHeight || selectionWidth < insertWidth ) {
|
|
|
+ // @if CK_DEBUG // console.log( 'Pasted table extends selection area.' );
|
|
|
|
|
|
- const model = this.editor.model;
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- model.change( writer => {
|
|
|
- const insertionMap = new Map();
|
|
|
+ const model = this.editor.model;
|
|
|
|
|
|
- for ( const { column, row, cell } of new TableWalker( table ) ) {
|
|
|
- insertionMap.set( `${ row }x${ column }`, cell );
|
|
|
- }
|
|
|
+ model.change( writer => {
|
|
|
+ const insertionMap = new Map();
|
|
|
|
|
|
- const tableMap = [ ...new TableWalker( contentTable, {
|
|
|
- startRow: rowIndexes.first,
|
|
|
- endRow: rowIndexes.last,
|
|
|
- includeSpanned: true
|
|
|
- } ) ];
|
|
|
+ for ( const { column, row, cell } of new TableWalker( table ) ) {
|
|
|
+ insertionMap.set( `${ row }x${ column }`, cell );
|
|
|
+ }
|
|
|
|
|
|
- let previousCell;
|
|
|
+ const tableMap = [ ...new TableWalker( contentTable, {
|
|
|
+ startRow: rowIndexes.first,
|
|
|
+ endRow: rowIndexes.last,
|
|
|
+ includeSpanned: true
|
|
|
+ } ) ];
|
|
|
|
|
|
- const cellsToSelect = [];
|
|
|
+ let previousCell;
|
|
|
|
|
|
- for ( const { column, row, cell, isSpanned } of tableMap ) {
|
|
|
- // TODO: crete issue for table walker startColumn, endColumn.
|
|
|
- if ( column < columnIndexes.first || column > columnIndexes.last ) {
|
|
|
- previousCell = cell;
|
|
|
+ const cellsToSelect = [];
|
|
|
|
|
|
- continue;
|
|
|
- }
|
|
|
+ for ( const { column, row, cell, isSpanned } of tableMap ) {
|
|
|
+ // TODO: crete issue for table walker startColumn, endColumn.
|
|
|
+ if ( column < columnIndexes.first || column > columnIndexes.last ) {
|
|
|
+ previousCell = cell;
|
|
|
|
|
|
- const toGet = `${ row - rowIndexes.first }x${ column - columnIndexes.first }`;
|
|
|
- const cellToInsert = insertionMap.get( toGet );
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- if ( !cellToInsert ) {
|
|
|
- if ( !isSpanned ) {
|
|
|
- writer.remove( writer.createRangeOn( cell ) );
|
|
|
- }
|
|
|
+ const toGet = `${ row - rowIndexes.first }x${ column - columnIndexes.first }`;
|
|
|
+ const cellToInsert = insertionMap.get( toGet );
|
|
|
|
|
|
- continue;
|
|
|
+ if ( !cellToInsert ) {
|
|
|
+ if ( !isSpanned ) {
|
|
|
+ writer.remove( writer.createRangeOn( cell ) );
|
|
|
}
|
|
|
|
|
|
- let targetCell = cell;
|
|
|
-
|
|
|
- if ( isSpanned ) {
|
|
|
- let insertPosition;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- if ( column === 0 || !previousCell || previousCell.parent.index !== row ) {
|
|
|
- insertPosition = writer.createPositionAt( contentTable.getChild( row ), 0 );
|
|
|
- } else {
|
|
|
- insertPosition = writer.createPositionAfter( previousCell );
|
|
|
- }
|
|
|
+ let targetCell = cell;
|
|
|
|
|
|
- targetCell = writer.createElement( 'tableCell' );
|
|
|
+ if ( isSpanned ) {
|
|
|
+ let insertPosition;
|
|
|
|
|
|
- writer.insert( targetCell, insertPosition );
|
|
|
+ if ( column === 0 || !previousCell || previousCell.parent.index !== row ) {
|
|
|
+ insertPosition = writer.createPositionAt( contentTable.getChild( row ), 0 );
|
|
|
} else {
|
|
|
- writer.remove( writer.createRangeIn( cell ) );
|
|
|
+ insertPosition = writer.createPositionAfter( previousCell );
|
|
|
}
|
|
|
|
|
|
- updateNumericAttribute( 'colspan', cellToInsert.getAttribute( 'colspan' ), targetCell, writer, 1 );
|
|
|
- updateNumericAttribute( 'rowspan', cellToInsert.getAttribute( 'rowspan' ), targetCell, writer, 1 );
|
|
|
+ targetCell = writer.createElement( 'tableCell' );
|
|
|
|
|
|
- for ( const child of cellToInsert.getChildren() ) {
|
|
|
- writer.insert( child, targetCell, 'end' );
|
|
|
- }
|
|
|
+ writer.insert( targetCell, insertPosition );
|
|
|
+ } else {
|
|
|
+ writer.remove( writer.createRangeIn( cell ) );
|
|
|
+ }
|
|
|
|
|
|
- cellsToSelect.push( targetCell );
|
|
|
- previousCell = targetCell;
|
|
|
+ updateNumericAttribute( 'colspan', cellToInsert.getAttribute( 'colspan' ), targetCell, writer, 1 );
|
|
|
+ updateNumericAttribute( 'rowspan', cellToInsert.getAttribute( 'rowspan' ), targetCell, writer, 1 );
|
|
|
+
|
|
|
+ for ( const child of cellToInsert.getChildren() ) {
|
|
|
+ writer.insert( child, targetCell, 'end' );
|
|
|
}
|
|
|
|
|
|
- writer.setSelection( cellsToSelect.map( cell => writer.createRangeOn( cell ) ) );
|
|
|
- } );
|
|
|
- }
|
|
|
+ cellsToSelect.push( targetCell );
|
|
|
+ previousCell = targetCell;
|
|
|
+ }
|
|
|
+
|
|
|
+ writer.setSelection( cellsToSelect.map( cell => writer.createRangeOn( cell ) ) );
|
|
|
+ } );
|
|
|
}
|
|
|
}
|
|
|
|