@ckeditor/ckeditor5-table 32.0.0 → 33.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/table.js +2 -2
- package/build/table.js.map +1 -0
- package/build/translations/el.js +1 -0
- package/build/translations/es.js +1 -1
- package/lang/translations/el.po +261 -0
- package/lang/translations/es.po +32 -32
- package/package.json +23 -21
- package/src/commands/insertcolumncommand.js +4 -4
- package/src/commands/insertrowcommand.js +4 -4
- package/src/commands/mergecellcommand.js +4 -5
- package/src/commands/mergecellscommand.js +5 -4
- package/src/commands/removecolumncommand.js +8 -7
- package/src/commands/removerowcommand.js +5 -6
- package/src/commands/selectcolumncommand.js +4 -4
- package/src/commands/selectrowcommand.js +5 -5
- package/src/commands/setheadercolumncommand.js +5 -4
- package/src/commands/setheaderrowcommand.js +7 -4
- package/src/commands/splitcellcommand.js +4 -4
- package/src/converters/downcast.js +76 -407
- package/src/converters/{table-cell-refresh-post-fixer.js → table-cell-refresh-handler.js} +8 -19
- package/src/converters/table-headings-refresh-handler.js +68 -0
- package/src/plaintableoutput.js +151 -0
- package/src/tablecellproperties/commands/tablecellpropertycommand.js +4 -3
- package/src/tableclipboard.js +18 -15
- package/src/tableediting.js +48 -27
- package/src/tablekeyboard.js +6 -5
- package/src/tablemouse.js +6 -4
- package/src/tableselection.js +9 -8
- package/src/tableutils.js +310 -0
- package/theme/table.css +1 -1
- package/src/converters/table-heading-rows-refresh-post-fixer.js +0 -72
- package/src/utils/selection.js +0 -276
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @module table/plaintableoutput
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { Plugin } from 'ckeditor5/src/core';
|
|
11
|
+
import Table from './table';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The plain table output feature.
|
|
15
|
+
*
|
|
16
|
+
* @extends module:core/plugin~Plugin
|
|
17
|
+
*/
|
|
18
|
+
export default class PlainTableOutput extends Plugin {
|
|
19
|
+
/**
|
|
20
|
+
* @inheritDoc
|
|
21
|
+
*/
|
|
22
|
+
static get pluginName() {
|
|
23
|
+
return 'PlainTableOutput';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @inheritDoc
|
|
28
|
+
*/
|
|
29
|
+
static get requires() {
|
|
30
|
+
return [ Table ];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @inheritDoc
|
|
35
|
+
*/
|
|
36
|
+
init() {
|
|
37
|
+
const editor = this.editor;
|
|
38
|
+
|
|
39
|
+
// Override default table data downcast converter.
|
|
40
|
+
editor.conversion.for( 'dataDowncast' ).elementToStructure( {
|
|
41
|
+
model: 'table',
|
|
42
|
+
view: downcastTableElement,
|
|
43
|
+
converterPriority: 'high'
|
|
44
|
+
} );
|
|
45
|
+
|
|
46
|
+
// Make sure table <caption> is downcasted into <caption> in the data pipeline when necessary.
|
|
47
|
+
if ( editor.plugins.has( 'TableCaption' ) ) {
|
|
48
|
+
editor.conversion.for( 'dataDowncast' ).elementToElement( {
|
|
49
|
+
model: 'caption',
|
|
50
|
+
view: ( modelElement, { writer } ) => {
|
|
51
|
+
if ( modelElement.parent.name === 'table' ) {
|
|
52
|
+
return writer.createContainerElement( 'caption' );
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
converterPriority: 'high'
|
|
56
|
+
} );
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Handle border-style, border-color, border-width and background-color table attributes.
|
|
60
|
+
if ( editor.plugins.has( 'TableProperties' ) ) {
|
|
61
|
+
downcastTableBorderAndBackgroundAttributes( editor );
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// The plain table downcast converter callback.
|
|
67
|
+
//
|
|
68
|
+
// @private
|
|
69
|
+
// @param {module:engine/model/element~Element} Table model element.
|
|
70
|
+
// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi The conversion API object.
|
|
71
|
+
// @returns {module:engine/view/containerelement~ContainerElement} Created element.
|
|
72
|
+
function downcastTableElement( table, { writer } ) {
|
|
73
|
+
const headingRows = table.getAttribute( 'headingRows' ) || 0;
|
|
74
|
+
|
|
75
|
+
// Table head rows slot.
|
|
76
|
+
const headRowsSlot = writer.createSlot( element =>
|
|
77
|
+
element.is( 'element', 'tableRow' ) && element.index < headingRows
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
// Table body rows slot.
|
|
81
|
+
const bodyRowsSlot = writer.createSlot( element =>
|
|
82
|
+
element.is( 'element', 'tableRow' ) && element.index >= headingRows
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
// Table children slot.
|
|
86
|
+
const childrenSlot = writer.createSlot( element => !element.is( 'element', 'tableRow' ) );
|
|
87
|
+
|
|
88
|
+
// Table <thead> element with all the heading rows.
|
|
89
|
+
const theadElement = writer.createContainerElement( 'thead', null, headRowsSlot );
|
|
90
|
+
|
|
91
|
+
// Table <tbody> element with all the body rows.
|
|
92
|
+
const tbodyElement = writer.createContainerElement( 'tbody', null, bodyRowsSlot );
|
|
93
|
+
|
|
94
|
+
// Table contents element containing <thead> and <tbody> when necessary.
|
|
95
|
+
const tableContentElements = [];
|
|
96
|
+
|
|
97
|
+
if ( headingRows ) {
|
|
98
|
+
tableContentElements.push( theadElement );
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if ( headingRows < table.childCount ) {
|
|
102
|
+
tableContentElements.push( tbodyElement );
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Create table structure.
|
|
106
|
+
//
|
|
107
|
+
// <table>
|
|
108
|
+
// {children-slot-like-caption}
|
|
109
|
+
// <thead>
|
|
110
|
+
// {table-head-rows-slot}
|
|
111
|
+
// </thead>
|
|
112
|
+
// <tbody>
|
|
113
|
+
// {table-body-rows-slot}
|
|
114
|
+
// </tbody>
|
|
115
|
+
// </table>
|
|
116
|
+
return writer.createContainerElement( 'table', null, [ childrenSlot, ...tableContentElements ] );
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Register table border and background attributes converters.
|
|
120
|
+
//
|
|
121
|
+
// @private
|
|
122
|
+
// @param {module:core/editor/editor~Editor} editor
|
|
123
|
+
function downcastTableBorderAndBackgroundAttributes( editor ) {
|
|
124
|
+
const modelAttributes = {
|
|
125
|
+
'border-width': 'tableBorderWidth',
|
|
126
|
+
'border-color': 'tableBorderColor',
|
|
127
|
+
'border-style': 'tableBorderStyle',
|
|
128
|
+
'background-color': 'tableBackgroundColor'
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
for ( const [ styleName, modelAttribute ] of Object.entries( modelAttributes ) ) {
|
|
132
|
+
editor.conversion.for( 'dataDowncast' ).add( dispatcher => {
|
|
133
|
+
return dispatcher.on( `attribute:${ modelAttribute }:table`, ( evt, data, conversionApi ) => {
|
|
134
|
+
const { item, attributeNewValue } = data;
|
|
135
|
+
const { mapper, writer } = conversionApi;
|
|
136
|
+
|
|
137
|
+
if ( !conversionApi.consumable.consume( item, evt.name ) ) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const table = mapper.toViewElement( item );
|
|
142
|
+
|
|
143
|
+
if ( attributeNewValue ) {
|
|
144
|
+
writer.setStyle( styleName, attributeNewValue, table );
|
|
145
|
+
} else {
|
|
146
|
+
writer.removeStyle( styleName, table );
|
|
147
|
+
}
|
|
148
|
+
}, { priority: 'high' } );
|
|
149
|
+
} );
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { Command } from 'ckeditor5/src/core';
|
|
11
|
-
import { getSelectionAffectedTableCells } from '../../utils/selection';
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
13
|
* The table cell attribute command.
|
|
@@ -51,7 +50,8 @@ export default class TableCellPropertyCommand extends Command {
|
|
|
51
50
|
*/
|
|
52
51
|
refresh() {
|
|
53
52
|
const editor = this.editor;
|
|
54
|
-
const
|
|
53
|
+
const tableUtils = this.editor.plugins.get( 'TableUtils' );
|
|
54
|
+
const selectedTableCells = tableUtils.getSelectionAffectedTableCells( editor.model.document.selection );
|
|
55
55
|
|
|
56
56
|
this.isEnabled = !!selectedTableCells.length;
|
|
57
57
|
this.value = this._getSingleValue( selectedTableCells );
|
|
@@ -70,7 +70,8 @@ export default class TableCellPropertyCommand extends Command {
|
|
|
70
70
|
execute( options = {} ) {
|
|
71
71
|
const { value, batch } = options;
|
|
72
72
|
const model = this.editor.model;
|
|
73
|
-
const
|
|
73
|
+
const tableUtils = this.editor.plugins.get( 'TableUtils' );
|
|
74
|
+
const tableCells = tableUtils.getSelectionAffectedTableCells( model.document.selection );
|
|
74
75
|
const valueToSet = this._getValueToSet( value );
|
|
75
76
|
|
|
76
77
|
model.enqueueChange( batch, writer => {
|
package/src/tableclipboard.js
CHANGED
|
@@ -12,7 +12,6 @@ import { Plugin } from 'ckeditor5/src/core';
|
|
|
12
12
|
import TableSelection from './tableselection';
|
|
13
13
|
import TableWalker from './tablewalker';
|
|
14
14
|
import TableUtils from './tableutils';
|
|
15
|
-
import { getColumnIndexes, getRowIndexes, getSelectionAffectedTableCells, isSelectionRectangular, sortRanges } from './utils/selection';
|
|
16
15
|
import {
|
|
17
16
|
cropTableToDimensions,
|
|
18
17
|
getHorizontallyOverlappingCells,
|
|
@@ -122,7 +121,7 @@ export default class TableClipboard extends Plugin {
|
|
|
122
121
|
return;
|
|
123
122
|
}
|
|
124
123
|
|
|
125
|
-
const selectedTableCells = getSelectionAffectedTableCells( model.document.selection );
|
|
124
|
+
const selectedTableCells = tableUtils.getSelectionAffectedTableCells( model.document.selection );
|
|
126
125
|
|
|
127
126
|
if ( !selectedTableCells.length ) {
|
|
128
127
|
removeEmptyRowsColumns( pastedTable, tableUtils );
|
|
@@ -171,7 +170,7 @@ export default class TableClipboard extends Plugin {
|
|
|
171
170
|
if ( this.editor.plugins.get( 'TableSelection' ).isEnabled ) {
|
|
172
171
|
// Selection ranges must be sorted because the first and last selection ranges are considered
|
|
173
172
|
// as anchor/focus cell ranges for multi-cell selection.
|
|
174
|
-
const selectionRanges = sortRanges( cellsToSelect.map( cell => writer.createRangeOn( cell ) ) );
|
|
173
|
+
const selectionRanges = tableUtils.sortRanges( cellsToSelect.map( cell => writer.createRangeOn( cell ) ) );
|
|
175
174
|
|
|
176
175
|
writer.setSelection( selectionRanges );
|
|
177
176
|
} else {
|
|
@@ -311,17 +310,21 @@ export default class TableClipboard extends Plugin {
|
|
|
311
310
|
|
|
312
311
|
return cellToInsert;
|
|
313
312
|
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Extracts the table for pasting into a table.
|
|
316
|
+
*
|
|
317
|
+
* @protected
|
|
318
|
+
* @param {module:engine/model/documentfragment~DocumentFragment|module:engine/model/item~Item} content The content to insert.
|
|
319
|
+
* @param {module:engine/model/model~Model} model The editor model.
|
|
320
|
+
* @returns {module:engine/model/element~Element|null}
|
|
321
|
+
*/
|
|
322
|
+
getTableIfOnlyTableInContent( content, model ) {
|
|
323
|
+
return getTableIfOnlyTableInContent( content, model );
|
|
324
|
+
}
|
|
314
325
|
}
|
|
315
326
|
|
|
316
|
-
|
|
317
|
-
* Extract table for pasting into table.
|
|
318
|
-
*
|
|
319
|
-
* @private
|
|
320
|
-
* @param {module:engine/model/documentfragment~DocumentFragment|module:engine/model/item~Item} content The content to insert.
|
|
321
|
-
* @param {module:engine/model/model~Model} model The editor model.
|
|
322
|
-
* @returns {module:engine/model/element~Element|null}
|
|
323
|
-
*/
|
|
324
|
-
export function getTableIfOnlyTableInContent( content, model ) {
|
|
327
|
+
function getTableIfOnlyTableInContent( content, model ) {
|
|
325
328
|
if ( !content.is( 'documentFragment' ) && !content.is( 'element' ) ) {
|
|
326
329
|
return null;
|
|
327
330
|
}
|
|
@@ -381,8 +384,8 @@ export function getTableIfOnlyTableInContent( content, model ) {
|
|
|
381
384
|
function prepareTableForPasting( selectedTableCells, pastedDimensions, writer, tableUtils ) {
|
|
382
385
|
const selectedTable = selectedTableCells[ 0 ].findAncestor( 'table' );
|
|
383
386
|
|
|
384
|
-
const columnIndexes = getColumnIndexes( selectedTableCells );
|
|
385
|
-
const rowIndexes = getRowIndexes( selectedTableCells );
|
|
387
|
+
const columnIndexes = tableUtils.getColumnIndexes( selectedTableCells );
|
|
388
|
+
const rowIndexes = tableUtils.getRowIndexes( selectedTableCells );
|
|
386
389
|
|
|
387
390
|
const selection = {
|
|
388
391
|
firstColumn: columnIndexes.first,
|
|
@@ -403,7 +406,7 @@ function prepareTableForPasting( selectedTableCells, pastedDimensions, writer, t
|
|
|
403
406
|
|
|
404
407
|
// In case of expanding selection we do not reset the selection so in this case we will always try to fix selection
|
|
405
408
|
// like in the case of a non-rectangular area. This might be fixed by re-setting selected cells array but this shortcut is safe.
|
|
406
|
-
if ( shouldExpandSelection || !isSelectionRectangular( selectedTableCells
|
|
409
|
+
if ( shouldExpandSelection || !tableUtils.isSelectionRectangular( selectedTableCells ) ) {
|
|
407
410
|
// For a non-rectangular selection (ie in which some cells sticks out from a virtual selection rectangle) we need to create
|
|
408
411
|
// a table layout that has a rectangular selection. This will split cells so the selection become rectangular.
|
|
409
412
|
// Beyond this point we will operate on fixed content table.
|
package/src/tableediting.js
CHANGED
|
@@ -10,14 +10,7 @@
|
|
|
10
10
|
import { Plugin } from 'ckeditor5/src/core';
|
|
11
11
|
|
|
12
12
|
import upcastTable, { ensureParagraphInTableCell, skipEmptyTableRow, upcastTableFigure } from './converters/upcasttable';
|
|
13
|
-
import {
|
|
14
|
-
convertParagraphInTableCell,
|
|
15
|
-
downcastInsertCell,
|
|
16
|
-
downcastInsertRow,
|
|
17
|
-
downcastInsertTable,
|
|
18
|
-
downcastRemoveRow,
|
|
19
|
-
downcastTableHeadingColumnsChange
|
|
20
|
-
} from './converters/downcast';
|
|
13
|
+
import { convertParagraphInTableCell, downcastCell, downcastRow, downcastTable } from './converters/downcast';
|
|
21
14
|
|
|
22
15
|
import InsertTableCommand from './commands/inserttablecommand';
|
|
23
16
|
import InsertRowCommand from './commands/insertrowcommand';
|
|
@@ -35,8 +28,9 @@ import TableUtils from '../src/tableutils';
|
|
|
35
28
|
|
|
36
29
|
import injectTableLayoutPostFixer from './converters/table-layout-post-fixer';
|
|
37
30
|
import injectTableCellParagraphPostFixer from './converters/table-cell-paragraph-post-fixer';
|
|
38
|
-
|
|
39
|
-
import
|
|
31
|
+
|
|
32
|
+
import tableHeadingsRefreshHandler from './converters/table-headings-refresh-handler';
|
|
33
|
+
import tableCellRefreshHandler from './converters/table-cell-refresh-handler';
|
|
40
34
|
|
|
41
35
|
import '../theme/tableediting.css';
|
|
42
36
|
|
|
@@ -53,6 +47,13 @@ export default class TableEditing extends Plugin {
|
|
|
53
47
|
return 'TableEditing';
|
|
54
48
|
}
|
|
55
49
|
|
|
50
|
+
/**
|
|
51
|
+
* @inheritDoc
|
|
52
|
+
*/
|
|
53
|
+
static get requires() {
|
|
54
|
+
return [ TableUtils ];
|
|
55
|
+
}
|
|
56
|
+
|
|
56
57
|
/**
|
|
57
58
|
* @inheritDoc
|
|
58
59
|
*/
|
|
@@ -61,6 +62,7 @@ export default class TableEditing extends Plugin {
|
|
|
61
62
|
const model = editor.model;
|
|
62
63
|
const schema = model.schema;
|
|
63
64
|
const conversion = editor.conversion;
|
|
65
|
+
const tableUtils = editor.plugins.get( TableUtils );
|
|
64
66
|
|
|
65
67
|
schema.register( 'table', {
|
|
66
68
|
allowWhere: '$block',
|
|
@@ -88,15 +90,29 @@ export default class TableEditing extends Plugin {
|
|
|
88
90
|
// Table conversion.
|
|
89
91
|
conversion.for( 'upcast' ).add( upcastTable() );
|
|
90
92
|
|
|
91
|
-
conversion.for( 'editingDowncast' ).
|
|
92
|
-
|
|
93
|
+
conversion.for( 'editingDowncast' ).elementToStructure( {
|
|
94
|
+
model: {
|
|
95
|
+
name: 'table',
|
|
96
|
+
attributes: [ 'headingRows' ]
|
|
97
|
+
},
|
|
98
|
+
view: downcastTable( tableUtils, { asWidget: true } )
|
|
99
|
+
} );
|
|
100
|
+
conversion.for( 'dataDowncast' ).elementToStructure( {
|
|
101
|
+
model: {
|
|
102
|
+
name: 'table',
|
|
103
|
+
attributes: [ 'headingRows' ]
|
|
104
|
+
},
|
|
105
|
+
view: downcastTable( tableUtils )
|
|
106
|
+
} );
|
|
93
107
|
|
|
94
108
|
// Table row conversion.
|
|
95
109
|
conversion.for( 'upcast' ).elementToElement( { model: 'tableRow', view: 'tr' } );
|
|
96
110
|
conversion.for( 'upcast' ).add( skipEmptyTableRow() );
|
|
97
111
|
|
|
98
|
-
conversion.for( '
|
|
99
|
-
|
|
112
|
+
conversion.for( 'downcast' ).elementToElement( {
|
|
113
|
+
model: 'tableRow',
|
|
114
|
+
view: downcastRow()
|
|
115
|
+
} );
|
|
100
116
|
|
|
101
117
|
// Table cell conversion.
|
|
102
118
|
conversion.for( 'upcast' ).elementToElement( { model: 'tableCell', view: 'td' } );
|
|
@@ -104,12 +120,24 @@ export default class TableEditing extends Plugin {
|
|
|
104
120
|
conversion.for( 'upcast' ).add( ensureParagraphInTableCell( 'td' ) );
|
|
105
121
|
conversion.for( 'upcast' ).add( ensureParagraphInTableCell( 'th' ) );
|
|
106
122
|
|
|
107
|
-
conversion.for( 'editingDowncast' ).
|
|
123
|
+
conversion.for( 'editingDowncast' ).elementToElement( {
|
|
124
|
+
model: 'tableCell',
|
|
125
|
+
view: downcastCell( { asWidget: true } )
|
|
126
|
+
} );
|
|
127
|
+
conversion.for( 'dataDowncast' ).elementToElement( {
|
|
128
|
+
model: 'tableCell',
|
|
129
|
+
view: downcastCell()
|
|
130
|
+
} );
|
|
108
131
|
|
|
109
132
|
// Duplicates code - needed to properly refresh paragraph inside a table cell.
|
|
110
133
|
conversion.for( 'editingDowncast' ).elementToElement( {
|
|
111
134
|
model: 'paragraph',
|
|
112
|
-
view: convertParagraphInTableCell,
|
|
135
|
+
view: convertParagraphInTableCell( { asWidget: true } ),
|
|
136
|
+
converterPriority: 'high'
|
|
137
|
+
} );
|
|
138
|
+
conversion.for( 'dataDowncast' ).elementToElement( {
|
|
139
|
+
model: 'paragraph',
|
|
140
|
+
view: convertParagraphInTableCell(),
|
|
113
141
|
converterPriority: 'high'
|
|
114
142
|
} );
|
|
115
143
|
|
|
@@ -126,9 +154,6 @@ export default class TableEditing extends Plugin {
|
|
|
126
154
|
view: 'rowspan'
|
|
127
155
|
} );
|
|
128
156
|
|
|
129
|
-
// Table heading columns conversion (a change of heading rows requires a reconversion of the whole table).
|
|
130
|
-
conversion.for( 'editingDowncast' ).add( downcastTableHeadingColumnsChange() );
|
|
131
|
-
|
|
132
157
|
// Manually adjust model position mappings in a special case, when a table cell contains a paragraph, which is bound
|
|
133
158
|
// to its parent (to the table cell). This custom model-to-view position mapping is necessary in data pipeline only,
|
|
134
159
|
// because only during this conversion a paragraph can be bound to its parent.
|
|
@@ -164,17 +189,13 @@ export default class TableEditing extends Plugin {
|
|
|
164
189
|
editor.commands.add( 'selectTableRow', new SelectRowCommand( editor ) );
|
|
165
190
|
editor.commands.add( 'selectTableColumn', new SelectColumnCommand( editor ) );
|
|
166
191
|
|
|
167
|
-
injectTableHeadingRowsRefreshPostFixer( model );
|
|
168
192
|
injectTableLayoutPostFixer( model );
|
|
169
|
-
injectTableCellRefreshPostFixer( model, editor.editing.mapper );
|
|
170
193
|
injectTableCellParagraphPostFixer( model );
|
|
171
|
-
}
|
|
172
194
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return [ TableUtils ];
|
|
195
|
+
this.listenTo( model.document, 'change:data', () => {
|
|
196
|
+
tableHeadingsRefreshHandler( model, editor.editing );
|
|
197
|
+
tableCellRefreshHandler( model, editor.editing );
|
|
198
|
+
} );
|
|
178
199
|
}
|
|
179
200
|
}
|
|
180
201
|
|
package/src/tablekeyboard.js
CHANGED
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
|
|
10
10
|
import TableSelection from './tableselection';
|
|
11
11
|
import TableWalker from './tablewalker';
|
|
12
|
+
import TableUtils from './tableutils';
|
|
12
13
|
|
|
13
14
|
import { Plugin } from 'ckeditor5/src/core';
|
|
14
15
|
import { getLocalizedArrowKeyCodeDirection } from 'ckeditor5/src/utils';
|
|
15
|
-
import { getSelectedTableCells, getTableCellsContainingSelection } from './utils/selection';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* This plugin enables keyboard navigation for tables.
|
|
@@ -32,7 +32,7 @@ export default class TableKeyboard extends Plugin {
|
|
|
32
32
|
* @inheritDoc
|
|
33
33
|
*/
|
|
34
34
|
static get requires() {
|
|
35
|
-
return [ TableSelection ];
|
|
35
|
+
return [ TableSelection, TableUtils ];
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/**
|
|
@@ -83,10 +83,11 @@ export default class TableKeyboard extends Plugin {
|
|
|
83
83
|
*/
|
|
84
84
|
_getTabHandler( isForward ) {
|
|
85
85
|
const editor = this.editor;
|
|
86
|
+
const tableUtils = this.editor.plugins.get( TableUtils );
|
|
86
87
|
|
|
87
88
|
return ( domEventData, cancel ) => {
|
|
88
89
|
const selection = editor.model.document.selection;
|
|
89
|
-
let tableCell = getTableCellsContainingSelection( selection )[ 0 ];
|
|
90
|
+
let tableCell = tableUtils.getTableCellsContainingSelection( selection )[ 0 ];
|
|
90
91
|
|
|
91
92
|
if ( !tableCell ) {
|
|
92
93
|
tableCell = this.editor.plugins.get( 'TableSelection' ).getFocusCell();
|
|
@@ -115,7 +116,6 @@ export default class TableKeyboard extends Plugin {
|
|
|
115
116
|
return;
|
|
116
117
|
}
|
|
117
118
|
|
|
118
|
-
const tableUtils = this.editor.plugins.get( 'TableUtils' );
|
|
119
119
|
const isLastCellInRow = currentCellIndex === tableRow.childCount - 1;
|
|
120
120
|
const isLastRow = currentRowIndex === tableUtils.getRows( table ) - 1;
|
|
121
121
|
|
|
@@ -188,13 +188,14 @@ export default class TableKeyboard extends Plugin {
|
|
|
188
188
|
* @returns {Boolean} Returns `true` if key was handled.
|
|
189
189
|
*/
|
|
190
190
|
_handleArrowKeys( direction, expandSelection ) {
|
|
191
|
+
const tableUtils = this.editor.plugins.get( TableUtils );
|
|
191
192
|
const model = this.editor.model;
|
|
192
193
|
const selection = model.document.selection;
|
|
193
194
|
const isForward = [ 'right', 'down' ].includes( direction );
|
|
194
195
|
|
|
195
196
|
// In case one or more table cells are selected (from outside),
|
|
196
197
|
// move the selection to a cell adjacent to the selected table fragment.
|
|
197
|
-
const selectedCells = getSelectedTableCells( selection );
|
|
198
|
+
const selectedCells = tableUtils.getSelectedTableCells( selection );
|
|
198
199
|
|
|
199
200
|
if ( selectedCells.length ) {
|
|
200
201
|
let focusCell;
|
package/src/tablemouse.js
CHANGED
|
@@ -11,8 +11,7 @@ import { Plugin } from 'ckeditor5/src/core';
|
|
|
11
11
|
|
|
12
12
|
import TableSelection from './tableselection';
|
|
13
13
|
import MouseEventsObserver from './tablemouse/mouseeventsobserver';
|
|
14
|
-
|
|
15
|
-
import { getTableCellsContainingSelection } from './utils/selection';
|
|
14
|
+
import TableUtils from './tableutils';
|
|
16
15
|
|
|
17
16
|
/**
|
|
18
17
|
* This plugin enables a table cells' selection with the mouse.
|
|
@@ -32,7 +31,7 @@ export default class TableMouse extends Plugin {
|
|
|
32
31
|
* @inheritDoc
|
|
33
32
|
*/
|
|
34
33
|
static get requires() {
|
|
35
|
-
return [ TableSelection ];
|
|
34
|
+
return [ TableSelection, TableUtils ];
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
/**
|
|
@@ -57,11 +56,14 @@ export default class TableMouse extends Plugin {
|
|
|
57
56
|
*/
|
|
58
57
|
_enableShiftClickSelection() {
|
|
59
58
|
const editor = this.editor;
|
|
59
|
+
const tableUtils = editor.plugins.get( TableUtils );
|
|
60
60
|
let blockSelectionChange = false;
|
|
61
61
|
|
|
62
62
|
const tableSelection = editor.plugins.get( TableSelection );
|
|
63
63
|
|
|
64
64
|
this.listenTo( editor.editing.view.document, 'mousedown', ( evt, domEventData ) => {
|
|
65
|
+
const selection = editor.model.document.selection;
|
|
66
|
+
|
|
65
67
|
if ( !this.isEnabled || !tableSelection.isEnabled ) {
|
|
66
68
|
return;
|
|
67
69
|
}
|
|
@@ -70,7 +72,7 @@ export default class TableMouse extends Plugin {
|
|
|
70
72
|
return;
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
const anchorCell = tableSelection.getAnchorCell() || getTableCellsContainingSelection(
|
|
75
|
+
const anchorCell = tableSelection.getAnchorCell() || tableUtils.getTableCellsContainingSelection( selection )[ 0 ];
|
|
74
76
|
|
|
75
77
|
if ( !anchorCell ) {
|
|
76
78
|
return;
|
package/src/tableselection.js
CHANGED
|
@@ -14,7 +14,6 @@ import TableWalker from './tablewalker';
|
|
|
14
14
|
import TableUtils from './tableutils';
|
|
15
15
|
|
|
16
16
|
import { cropTableToDimensions, adjustLastRowIndex, adjustLastColumnIndex } from './utils/structure';
|
|
17
|
-
import { getColumnIndexes, getRowIndexes, getSelectedTableCells, isSelectionRectangular } from './utils/selection';
|
|
18
17
|
|
|
19
18
|
import '../theme/tableselection.css';
|
|
20
19
|
|
|
@@ -36,7 +35,7 @@ export default class TableSelection extends Plugin {
|
|
|
36
35
|
* @inheritDoc
|
|
37
36
|
*/
|
|
38
37
|
static get requires() {
|
|
39
|
-
return [ TableUtils ];
|
|
38
|
+
return [ TableUtils, TableUtils ];
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
/**
|
|
@@ -58,9 +57,10 @@ export default class TableSelection extends Plugin {
|
|
|
58
57
|
* @returns {Array.<module:engine/model/element~Element>|null}
|
|
59
58
|
*/
|
|
60
59
|
getSelectedTableCells() {
|
|
60
|
+
const tableUtils = this.editor.plugins.get( TableUtils );
|
|
61
61
|
const selection = this.editor.model.document.selection;
|
|
62
62
|
|
|
63
|
-
const selectedCells = getSelectedTableCells( selection );
|
|
63
|
+
const selectedCells = tableUtils.getSelectedTableCells( selection );
|
|
64
64
|
|
|
65
65
|
if ( selectedCells.length == 0 ) {
|
|
66
66
|
return null;
|
|
@@ -81,6 +81,7 @@ export default class TableSelection extends Plugin {
|
|
|
81
81
|
* @returns {module:engine/model/documentfragment~DocumentFragment|null}
|
|
82
82
|
*/
|
|
83
83
|
getSelectionAsFragment() {
|
|
84
|
+
const tableUtils = this.editor.plugins.get( TableUtils );
|
|
84
85
|
const selectedCells = this.getSelectedTableCells();
|
|
85
86
|
|
|
86
87
|
if ( !selectedCells ) {
|
|
@@ -89,10 +90,9 @@ export default class TableSelection extends Plugin {
|
|
|
89
90
|
|
|
90
91
|
return this.editor.model.change( writer => {
|
|
91
92
|
const documentFragment = writer.createDocumentFragment();
|
|
92
|
-
const tableUtils = this.editor.plugins.get( 'TableUtils' );
|
|
93
93
|
|
|
94
|
-
const { first: firstColumn, last: lastColumn } = getColumnIndexes( selectedCells );
|
|
95
|
-
const { first: firstRow, last: lastRow } = getRowIndexes( selectedCells );
|
|
94
|
+
const { first: firstColumn, last: lastColumn } = tableUtils.getColumnIndexes( selectedCells );
|
|
95
|
+
const { first: firstRow, last: lastRow } = tableUtils.getRowIndexes( selectedCells );
|
|
96
96
|
|
|
97
97
|
const sourceTable = selectedCells[ 0 ].findAncestor( 'table' );
|
|
98
98
|
|
|
@@ -101,7 +101,7 @@ export default class TableSelection extends Plugin {
|
|
|
101
101
|
|
|
102
102
|
// If the selection is rectangular there could be a case of all cells in the last row/column spanned over
|
|
103
103
|
// next row/column so the real lastRow/lastColumn should be updated.
|
|
104
|
-
if ( isSelectionRectangular( selectedCells
|
|
104
|
+
if ( tableUtils.isSelectionRectangular( selectedCells ) ) {
|
|
105
105
|
const dimensions = {
|
|
106
106
|
firstColumn,
|
|
107
107
|
lastColumn,
|
|
@@ -269,10 +269,11 @@ export default class TableSelection extends Plugin {
|
|
|
269
269
|
* @param {Array.<*>} args Delete content method arguments.
|
|
270
270
|
*/
|
|
271
271
|
_handleDeleteContent( event, args ) {
|
|
272
|
+
const tableUtils = this.editor.plugins.get( TableUtils );
|
|
272
273
|
const [ selection, options ] = args;
|
|
273
274
|
const model = this.editor.model;
|
|
274
275
|
const isBackward = !options || options.direction == 'backward';
|
|
275
|
-
const selectedTableCells = getSelectedTableCells( selection );
|
|
276
|
+
const selectedTableCells = tableUtils.getSelectedTableCells( selection );
|
|
276
277
|
|
|
277
278
|
if ( !selectedTableCells.length ) {
|
|
278
279
|
return;
|