8
0
Pārlūkot izejas kodu

Merge branch 'master' into t/12

Piotrek Koszuliński 7 gadi atpakaļ
vecāks
revīzija
4581bbd9c0

+ 9 - 0
packages/ckeditor5-table/.github/PULL_REQUEST_TEMPLATE.md

@@ -0,0 +1,9 @@
+### Suggested merge commit message ([convention](https://github.com/ckeditor/ckeditor5-design/wiki/Git-commit-message-convention))
+
+Type: Message. Closes #000.
+
+---
+
+### Additional information
+
+*For example – encountered issues, assumptions you had to make, other affected tickets, etc.*

+ 0 - 0
packages/ckeditor5-table/docs/_snippets/features/build-table-source.html


+ 16 - 0
packages/ckeditor5-table/docs/_snippets/features/build-table-source.js

@@ -0,0 +1,16 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals window */
+
+import ClassicEditor from '@ckeditor/ckeditor5-build-classic/src/ckeditor';
+
+import Table from '@ckeditor/ckeditor5-table/src/table';
+import TableToolbar from '@ckeditor/ckeditor5-table/src/tabletoolbar';
+
+ClassicEditor.build.plugins.push( Table );
+ClassicEditor.build.plugins.push( TableToolbar );
+
+window.ClassicEditor = ClassicEditor;

+ 54 - 0
packages/ckeditor5-table/docs/_snippets/features/table.html

@@ -0,0 +1,54 @@
+<div id="snippet-table">
+	<p>The ultimate table of <a href="https://en.wikipedia.org/wiki/List_of_coffee_drinks">coffee drinks</a>:</p>
+	<table>
+		<thead>
+			<tr>
+				<th rowspan="2"></th>
+				<th scope="col" rowspan="2">Espresso</th>
+				<th scope="colgroup" colspan="2">Milk</th>
+				<th scope="col" rowspan="2">Water</th>
+			</tr>
+			<tr>
+				<th scope="col">Steamed</th>
+				<th scope="col">Foam</th>
+			</tr>
+		</thead>
+		<tbody>
+			<tr>
+				<th scope="row">Cappuccino</th>
+				<td>yes</td>
+				<td>yes</td>
+				<td>yes</td>
+				<td>no</td>
+			</tr>
+			<tr>
+				<th scope="row">Macchiato</th>
+				<td>yes</td>
+				<td>no</td>
+				<td>yes</td>
+				<td>no</td>
+			</tr>
+			<tr>
+				<th scope="row">Latte</th>
+				<td>yes</td>
+				<td>yes</td>
+				<td>no</td>
+				<td>no</td>
+			</tr>
+			<tr>
+				<th scope="row">Americano</th>
+				<td>yes</td>
+				<td>no</td>
+				<td>no</td>
+				<td>yes</td>
+			</tr>
+		</tbody>
+	</table>
+</div>
+
+<style>
+	.ck.ck-content table td,
+	.ck.ck-content table th {
+		vertical-align: middle;
+	}
+</style>

+ 28 - 0
packages/ckeditor5-table/docs/_snippets/features/table.js

@@ -0,0 +1,28 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals ClassicEditor, console, window, document */
+
+import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud-services-config';
+
+ClassicEditor
+	.create( document.querySelector( '#snippet-table' ), {
+		cloudServices: CS_CONFIG,
+		toolbar: {
+			items: [
+				'insertTable', '|', 'heading', '|', 'bold', 'italic', 'underline', '|', 'undo', 'redo'
+			],
+			viewportTopOffset: 60
+		},
+		table: {
+			toolbar: [ 'tableColumn', 'tableRow', 'mergeCell' ]
+		}
+	} )
+	.then( editor => {
+		window.editor = editor;
+	} )
+	.catch( err => {
+		console.error( err.stack );
+	} );

+ 35 - 0
packages/ckeditor5-table/docs/api/table.md

@@ -0,0 +1,35 @@
+---
+category: api-reference
+---
+
+# CKEditor 5 table feature
+
+[![npm version](https://badge.fury.io/js/%40ckeditor%2Fckeditor5-table.svg)](https://www.npmjs.com/package/@ckeditor/ckeditor5-table)
+
+This package implements the table feature for CKEditor 5.
+
+## Documentation
+
+See the {@link features/table Table feature} guide and the documentation for the following plugins:
+
+  * {@link module:table/table~Table}
+  * {@link module:table/tabletoolbar~TableToolbar}
+  * {@link module:table/tableutils~TableUtils}
+
+
+## Installation
+
+```bash
+npm install --save @ckeditor/ckeditor5-table
+```
+
+## Contribute
+
+The source code of this package is available on GitHub in https://github.com/ckeditor/ckeditor5-table.
+
+## External links
+
+* [`@ckeditor/ckeditor5-table` on npm](https://www.npmjs.com/package/@ckeditor/ckeditor5-table)
+* [`ckeditor/ckeditor5-table` on GitHub](https://github.com/ckeditor/ckeditor5-table)
+* [Issue tracker](https://github.com/ckeditor/ckeditor5-table/issues)
+* [Changelog](https://github.com/ckeditor/ckeditor5-table/blob/master/CHANGELOG.md)

+ 149 - 0
packages/ckeditor5-table/docs/features/table.md

@@ -0,0 +1,149 @@
+---
+title: Tables
+category: features
+---
+
+{@snippet features/build-table-source}
+
+The {@link module:table/table~Table} feature offers table creation an editing tools that help content authors bring tabular data into their documents.
+
+## Demo
+
+{@snippet features/table}
+
+## Installation
+
+To add this feature to your editor install the [`@ckeditor/ckeditor5-table`](https://www.npmjs.com/package/@ckeditor/ckeditor5-table) package
+
+```bash
+npm install --save @ckeditor/ckeditor5-table
+```
+
+then add `'Table'` and `'TableToolbar'` to your plugin list and the table toolbar configuration:
+
+```js
+import Table from '@ckeditor/ckeditor5-table/src/table';
+import TableToolbar from '@ckeditor/ckeditor5-table/src/tabletoolbar';
+
+ClassicEditor
+	.create( document.querySelector( '#editor' ), {
+		plugins: [ Table, TableToolbar, ... ],
+		toolbar: [ 'insertTable', ... ]
+		table: {
+			toolbar: [ 'tableColumn', 'tableRow', 'mergeCell' ]
+		}
+	} )
+	.then( ... )
+	.catch( ... );
+```
+
+<info-box info>
+	Read more about {@link builds/guides/development/installing-plugins installing plugins}.
+</info-box>
+
+## Common API
+
+The {@link module:table/table~Table} plugin registers the following UI components:
+
+* The `'insertTable'` dropdown,
+* The `'tableColumn'` dropdown,
+* The `'tableRow'` dropdown,
+* The `'mergeCell'` dropdown,
+
+and the following commands:
+
+* The {@link module:table/commands/inserttablecommand~InsertTableCommand `'inserttable'`} command.
+
+	To insert a table at the current selection, execute the command and specify the dimensions:
+
+	```js
+	editor.execute( 'insertTable', { rows: 20, columns: 5 } );
+	```
+
+* The {@link module:table/commands/insertcolumncommand~InsertColumnCommand} as `'insertColumnBefore'` and `'insertColumnAfter'` commands.
+
+	To insert a column before or after the selected cell, execute one of the commands:
+
+	```js
+	editor.execute( 'insertColumnBefore' );
+	```
+
+	or
+
+	```js
+	editor.execute( 'insertColumnAfter' );
+	```
+
+* The {@link module:table/commands/insertrowcommand~InsertRowCommand} as `'insertRowAbove'`and `'insertRowBelow'` commands.
+
+	To insert a row below or above the selected cell, execute one of the commands:
+
+	```js
+	editor.execute( 'insertRowBelow' );
+	```
+
+	or
+
+	```js
+	editor.execute( 'insertRowAbove' );
+	```
+
+* The {@link module:table/commands/removecolumncommand~RemoveColumnCommand `'removeColumn'`} command.
+
+	To remove the column containing the selected cell, execute the command:
+
+	```js
+	editor.execute( 'removeColumn' );
+	```
+
+* The {@link module:table/commands/removerowcommand~RemoveRowCommand `'removeRow'`} command.
+
+	To remove the row containing the selected cell, execute the command:
+
+	```js
+	editor.execute( 'removeRow' );
+	```
+
+* The {@link module:table/commands/setheadercolumncommand~SetHeaderColumnCommand `'setColumnHeader'`} command.
+
+	You can make the column containing the selected cell a [header](https://www.w3.org/TR/html50/tabular-data.html#the-th-element) by executing:
+
+	```js
+	editor.execute( 'setColumnHeader' );
+	```
+
+	**Note:** All preceding columns will also become headers. If the current column is already a header, executing this command will make it a regular column back again (including following columns).
+
+* The {@link module:table/commands/setheaderrowcommand~SetHeaderRowCommand `'setRowHeader'`} command.
+
+	You can make the row containing the selected cell a [header](https://www.w3.org/TR/html50/tabular-data.html#the-th-element) by executing:
+
+	```js
+	editor.execute( 'setRowHeader' );
+	```
+
+	**Note:** All preceding rows will also become headers. If the current row is already a header, executing this command will make it a regular row back again (including following rows).
+
+* The {@link module:table/commands/mergecellcommand~MergeCellCommand} as `'mergeCellRight'`, `'mergeCellLeft'`, `'mergeCellUp'` and `'mergeCellDown'` commands.
+
+	To merge a table cell at the current selection with another cell, execute the command corresponding with the preferred direction. E.g. to merge with a cell to the right:
+
+	```js
+	editor.execute( 'mergeCellRight' );
+	```
+
+	**Note**: If a table cell has a different [`rowspan`](https://www.w3.org/TR/html50/tabular-data.html#attr-tdth-rowspan) (for `'mergeCellRight'` and `'mergeCellLeft'`) or [`colspan`](https://www.w3.org/TR/html50/tabular-data.html#attr-tdth-colspan) (for `'mergeCellUp'` and `'mergeCellDown'`), the command will be disabled.
+
+* The {@link module:table/commands/splitcellcommand~SplitCellCommand} as `'splitCellVertically'` and `'splitCellHorizontally'` commands.
+
+	You can split any cell vertically or horizontally by executing this command. E.g. to split the selected table cell vertically:
+
+	```js
+	editor.execute( 'splitCellVertically' );
+	```
+
+The {@link module:table/tabletoolbar~TableToolbar} plugin introduces the balloon toolbar for the tables. The toolbar shows up when a table cell is selected, anchored to the table. It is possible to {@link module:table/table~TableConfig#toolbar configure} its content. Normally, it contains the table-related tools such as `'tableColumn'`, `'tableRow'`, and `'mergeCell'` dropdowns.
+
+## Contribute
+
+The source code of the feature is available on GitHub in https://github.com/ckeditor/ckeditor5-table.

+ 15 - 5
packages/ckeditor5-table/src/commands/mergecellcommand.js

@@ -158,16 +158,26 @@ function getVerticalCell( tableCell, direction ) {
 		return;
 	}
 
-	const rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 );
-	const mergeRow = direction == 'down' ? rowIndex + rowspan : rowIndex;
+	const currentCellRowSpan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 );
+	const rowOfCellToMerge = direction == 'down' ? rowIndex + currentCellRowSpan : rowIndex;
 
-	const tableMap = [ ...new TableWalker( table, { endRow: mergeRow } ) ];
+	const tableMap = [ ...new TableWalker( table, { endRow: rowOfCellToMerge } ) ];
 
 	const currentCellData = tableMap.find( value => value.cell === tableCell );
 	const mergeColumn = currentCellData.column;
 
-	const cellToMergeData = tableMap.find( ( { row, column } ) => {
-		return column === mergeColumn && ( direction == 'down' ? mergeRow === row : mergeRow === rowspan + row );
+	const cellToMergeData = tableMap.find( ( { row, rowspan, column } ) => {
+		if ( column !== mergeColumn ) {
+			return false;
+		}
+
+		if ( direction == 'down' ) {
+			// If merging a cell below the mergeRow is already calculated.
+			return row === rowOfCellToMerge;
+		} else {
+			// If merging a cell above calculate if it spans to mergeRow.
+			return rowOfCellToMerge === row + rowspan;
+		}
 	} );
 
 	return cellToMergeData && cellToMergeData.cell;

+ 3 - 1
packages/ckeditor5-table/src/commands/setheaderrowcommand.js

@@ -111,8 +111,10 @@ function getOverlappingCells( table, headingRowsToSet, currentHeadingRows ) {
 	const cellsToSplit = [];
 
 	const startAnalysisRow = headingRowsToSet > currentHeadingRows ? currentHeadingRows : 0;
+	// We're analyzing only when headingRowsToSet > 0.
+	const endAnalysisRow = headingRowsToSet - 1;
 
-	const tableWalker = new TableWalker( table, { startRow: startAnalysisRow, endRow: headingRowsToSet } );
+	const tableWalker = new TableWalker( table, { startRow: startAnalysisRow, endRow: endAnalysisRow } );
 
 	for ( const { row, rowspan, cell } of tableWalker ) {
 		if ( rowspan > 1 && row + rowspan > headingRowsToSet ) {

+ 2 - 0
packages/ckeditor5-table/src/table.js

@@ -13,6 +13,8 @@ import TableEditing from './tableediting';
 import TableUI from './tableui';
 import Widget from '@ckeditor/ckeditor5-widget/src/widget';
 
+import '../theme/table.css';
+
 /**
  * The table plugin.
  *

+ 1 - 1
packages/ckeditor5-table/src/tableediting.js

@@ -33,7 +33,7 @@ import SetHeaderColumnCommand from './commands/setheadercolumncommand';
 import { getParentTable } from './commands/utils';
 import TableUtils from './tableutils';
 
-import './../theme/table.css';
+import '../theme/tableediting.css';
 
 /**
  * The table editing feature.

+ 3 - 3
packages/ckeditor5-table/src/tabletoolbar.js

@@ -112,9 +112,9 @@ export default class TableToolbar extends Plugin {
 		if ( !editor.ui.focusTracker.isFocused ) {
 			this._hideToolbar();
 		} else {
-			const viewSeleciton = editor.editing.view.document.selection;
+			const viewSelection = editor.editing.view.document.selection;
 
-			if ( isTableWidgetSelected( viewSeleciton ) || isTableContentSelected( viewSeleciton ) ) {
+			if ( isTableContentSelected( viewSelection ) ) {
 				this._showToolbar();
 			} else {
 				this._hideToolbar();
@@ -190,5 +190,5 @@ export default class TableToolbar extends Plugin {
  *
  * Read more about configuring toolbar in {@link module:core/editor/editorconfig~EditorConfig#toolbar}.
  *
- * @member {Array.<String>} module:table~TableConfig#toolbar
+ * @member {Array.<String>} module:table/table~TableConfig#toolbar
  */

+ 21 - 10
packages/ckeditor5-table/src/tableui.js

@@ -75,6 +75,7 @@ export default class TableUI extends Plugin {
 		editor.ui.componentFactory.add( 'tableColumn', locale => {
 			const options = [
 				{ commandName: 'setColumnHeader', label: t( 'Header column' ), bindIsActive: true },
+				'|',
 				{ commandName: 'insertColumnBefore', label: t( 'Insert column before' ) },
 				{ commandName: 'insertColumnAfter', label: t( 'Insert column after' ) },
 				{ commandName: 'removeColumn', label: t( 'Delete column' ) }
@@ -86,6 +87,7 @@ export default class TableUI extends Plugin {
 		editor.ui.componentFactory.add( 'tableRow', locale => {
 			const options = [
 				{ commandName: 'setRowHeader', label: t( 'Header row' ), bindIsActive: true },
+				'|',
 				{ commandName: 'insertRowBelow', label: t( 'Insert row below' ) },
 				{ commandName: 'insertRowAbove', label: t( 'Insert row above' ) },
 				{ commandName: 'removeRow', label: t( 'Delete row' ) }
@@ -100,6 +102,7 @@ export default class TableUI extends Plugin {
 				{ commandName: 'mergeCellRight', label: t( 'Merge cell right' ) },
 				{ commandName: 'mergeCellDown', label: t( 'Merge cell down' ) },
 				{ commandName: 'mergeCellLeft', label: t( 'Merge cell left' ) },
+				'|',
 				{ commandName: 'splitCellVertically', label: t( 'Split cell vertically' ) },
 				{ commandName: 'splitCellHorizontally', label: t( 'Split cell horizontally' ) }
 			];
@@ -161,20 +164,28 @@ export default class TableUI extends Plugin {
 // @param {Array.<module:core/command~Command>} commands List of commands to update.
 // @param {module:utils/collection~Collection} dropdownItems Collection of dropdown items to update with given option.
 function addListOption( option, editor, commands, dropdownItems ) {
-	const { commandName, label, bindIsActive } = option;
-	const command = editor.commands.get( commandName );
+	const itemModel = new Model();
 
-	commands.push( command );
+	if ( option === '|' ) {
+		itemModel.set( {
+			isSeparator: true
+		} );
+	} else {
+		const { commandName, label, bindIsActive } = option;
+		const command = editor.commands.get( commandName );
+
+		commands.push( command );
 
-	const itemModel = new Model( {
-		commandName,
-		label
-	} );
+		itemModel.set( {
+			commandName,
+			label
+		} );
 
-	itemModel.bind( 'isEnabled' ).to( command );
+		itemModel.bind( 'isEnabled' ).to( command );
 
-	if ( bindIsActive ) {
-		itemModel.bind( 'isActive' ).to( command, 'value' );
+		if ( bindIsActive ) {
+			itemModel.bind( 'isActive' ).to( command, 'value' );
+		}
 	}
 
 	dropdownItems.add( itemModel );

+ 21 - 0
packages/ckeditor5-table/src/ui/inserttableview.js

@@ -17,6 +17,7 @@ import './../../theme/inserttable.css';
  * It renders a 10x10 grid to choose inserted table size.
  *
  * @extends module:ui/view~View
+ * @implements module:ui/dropdown/dropdownpanelfocusable~DropdownPanelFocusable
  */
 export default class InsertTableView extends View {
 	/**
@@ -88,6 +89,10 @@ export default class InsertTableView extends View {
 			],
 
 			on: {
+				mousedown: bind.to( evt => {
+					evt.preventDefault();
+				} ),
+
 				click: bind.to( () => {
 					this.fire( 'execute' );
 				} )
@@ -121,6 +126,22 @@ export default class InsertTableView extends View {
 		} );
 	}
 
+	/**
+	 * @inheritDoc
+	 */
+	focus() {
+		// The dropdown panel expects DropdownPanelFocusable interface on views passed to dropdown panel. See #30.
+		// The method should be implemented while working on keyboard support for this view. See #22.
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	focusLast() {
+		// The dropdown panel expects DropdownPanelFocusable interface on views passed to dropdown panel. See #30.
+		// The method should be implemented while working on keyboard support for this view. See #22.
+	}
+
 	/**
 	 * Highlights grid boxes depending on rows & columns selected.
 	 *

+ 1 - 7
packages/ckeditor5-table/src/ui/utils.js

@@ -9,7 +9,6 @@
 
 import BalloonPanelView from '@ckeditor/ckeditor5-ui/src/panel/balloon/balloonpanelview';
 import { getParentTable } from '../commands/utils';
-import { isTableWidgetSelected } from '../utils';
 
 /**
  * A helper utility that positions the
@@ -36,13 +35,8 @@ export function getBalloonPositionData( editor ) {
 	const editingView = editor.editing.view;
 	const defaultPositions = BalloonPanelView.defaultPositions;
 	const viewSelection = editingView.document.selection;
-	let parentTable;
 
-	if ( isTableWidgetSelected( viewSelection ) ) {
-		parentTable = viewSelection.getSelectedElement();
-	} else {
-		parentTable = getParentTable( viewSelection.getFirstPosition() );
-	}
+	const parentTable = getParentTable( viewSelection.getFirstPosition() );
 
 	return {
 		target: editingView.domConverter.viewToDom( parentTable ),

+ 32 - 3
packages/ckeditor5-table/tests/commands/mergecellcommand.js

@@ -4,7 +4,7 @@
  */
 
 import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor';
-import { setData, getData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
+import { getData, setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 import { upcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters';
 
 import MergeCellCommand from '../../src/commands/mergecellcommand';
@@ -483,6 +483,17 @@ describe( 'MergeCellCommand', () => {
 				expect( command.value ).to.equal( root.getNodeByPath( [ 0, 0, 0 ] ) );
 			} );
 
+			it( 'should be set to mergeable cell in rows with spanned cells', () => {
+				setData( model, modelTable( [
+					[ { rowspan: 3, contents: '00' }, '11', '12', '13' ],
+					[ { rowspan: 2, contents: '21' }, '22', '23' ],
+					[ '32', { rowspan: 2, contents: '33[]' } ],
+					[ { colspan: 2, contents: '40' }, '42' ]
+				] ) );
+
+				expect( command.value ).to.equal( root.getNodeByPath( [ 0, 1, 2 ] ) );
+			} );
+
 			it( 'should be undefined if in a cell that potential mergeable cell has different rowspan', () => {
 				setData( model, modelTable( [
 					[ { colspan: 2, contents: '00' }, '02' ],
@@ -500,10 +511,10 @@ describe( 'MergeCellCommand', () => {
 		} );
 
 		describe( 'execute()', () => {
-			it( 'should merge table cells ', () => {
+			it( 'should merge table cells', () => {
 				setData( model, modelTable( [
 					[ '00', '01' ],
-					[ '10', '11[]' ]
+					[ '10', '[]11' ]
 				] ) );
 
 				command.execute();
@@ -513,6 +524,24 @@ describe( 'MergeCellCommand', () => {
 					[ '10' ]
 				] ) );
 			} );
+
+			it( 'should properly merge cells in rows with spaned cells', () => {
+				setData( model, modelTable( [
+					[ { rowspan: 3, contents: '00' }, '11', '12', '13' ],
+					[ { rowspan: 2, contents: '21' }, '22', '23' ],
+					[ '32', { rowspan: 2, contents: '33[]' } ],
+					[ { colspan: 2, contents: '40' }, '42' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { rowspan: 3, contents: '00' }, '11', '12', '13' ],
+					[ { rowspan: 2, contents: '21' }, '22', { rowspan: 3, contents: '[2333]' } ],
+					[ '32' ],
+					[ { colspan: 2, contents: '40' }, '42' ]
+				] ) );
+			} );
 		} );
 	} );
 } );

+ 16 - 0
packages/ckeditor5-table/tests/commands/setheaderrowcommand.js

@@ -252,5 +252,21 @@ describe( 'HeaderRowCommand', () => {
 				[ '10', '' ]
 			], { headingRows: 1 } ) );
 		} );
+
+		it( 'should work properly in the first row of a table', () => {
+			setData( model, modelTable( [
+				[ '00', '[]01', '02' ],
+				[ { colspan: 2, rowspan: 2, contents: '10' }, '12' ],
+				[ '22' ]
+			] ) );
+
+			command.execute();
+
+			expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+				[ '00', '[]01', '02' ],
+				[ { colspan: 2, rowspan: 2, contents: '10' }, '12' ],
+				[ '22' ]
+			], { headingRows: 1 } ) );
+		} );
 	} );
 } );

+ 4 - 25
packages/ckeditor5-table/tests/manual/table.html

@@ -1,28 +1,7 @@
 <style>
-
-	table {
-		border-collapse: collapse;
-		border-spacing: 0;
-		border-color: hsl(0,0%,87%);
-	}
-
-	table, th, td {
-		padding: 5px;
-		border: 1px inset hsl(0,0%,87%);
-	}
-
-	table th,
-	table td {
-		min-width: 1em;
-	}
-
-	table th {
-		background: hsl(0,0%,96%);
-		font-weight: bold;
-	}
-
-	table thead th {
-		background: hsl(0,0%,90%);
+	body {
+		font-family: Helvetica, Arial, sans-serif;
+		font-size: 14px;
 	}
 </style>
 
@@ -47,7 +26,7 @@
 		</thead>
 		<tbody>
 		<tr>
-			<th colspan="2" rowspan="4" scope="rowgroup">Terrestial planets</th>
+			<th colspan="2" rowspan="4" scope="rowgroup">Terrestrial planets</th>
 			<th scope="row">Mercury</th>
 			<td>0.330</td>
 			<td>4,879</td>

+ 2 - 2
packages/ckeditor5-table/tests/tabletoolbar.js

@@ -117,10 +117,10 @@ describe( 'TableToolbar', () => {
 			editor.ui.focusTracker.isFocused = true;
 		} );
 
-		it( 'should show the toolbar on render when the table is selected', () => {
+		it( 'should not show the toolbar on render when the table is selected', () => {
 			setData( model, '<paragraph>foo</paragraph>[<table><tableRow><tableCell></tableCell></tableRow></table>]' );
 
-			expect( balloon.visibleView ).to.equal( toolbar );
+			expect( balloon.visibleView ).to.be.null;
 		} );
 
 		it( 'should show the toolbar on render when the table content is selected', () => {

+ 18 - 16
packages/ckeditor5-table/tests/tableui.js

@@ -12,6 +12,7 @@ import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
 import TableEditing from '../src/tableediting';
 import TableUI from '../src/tableui';
 import DropdownView from '@ckeditor/ckeditor5-ui/src/dropdown/dropdownview';
+import ListSeparatorView from '@ckeditor/ckeditor5-ui/src/list/listseparatorview';
 
 testUtils.createSinonSandbox();
 
@@ -121,9 +122,9 @@ describe( 'TableUI', () => {
 		it( 'should have proper items in panel', () => {
 			const listView = dropdown.listView;
 
-			const labels = listView.items.map( ( { label } ) => label );
+			const labels = listView.items.map( item => item instanceof ListSeparatorView ? '|' : item.label );
 
-			expect( labels ).to.deep.equal( [ 'Header row', 'Insert row below', 'Insert row above', 'Delete row' ] );
+			expect( labels ).to.deep.equal( [ 'Header row', '|', 'Insert row below', 'Insert row above', 'Delete row' ] );
 		} );
 
 		it( 'should bind items in panel to proper commands', () => {
@@ -140,9 +141,9 @@ describe( 'TableUI', () => {
 			removeRowCommand.isEnabled = true;
 
 			expect( items.get( 0 ).isEnabled ).to.be.true;
-			expect( items.get( 1 ).isEnabled ).to.be.true;
 			expect( items.get( 2 ).isEnabled ).to.be.true;
 			expect( items.get( 3 ).isEnabled ).to.be.true;
+			expect( items.get( 4 ).isEnabled ).to.be.true;
 			expect( dropdown.buttonView.isEnabled ).to.be.true;
 
 			setRowHeaderCommand.isEnabled = false;
@@ -152,16 +153,16 @@ describe( 'TableUI', () => {
 
 			insertRowBelowCommand.isEnabled = false;
 
-			expect( items.get( 1 ).isEnabled ).to.be.false;
+			expect( items.get( 2 ).isEnabled ).to.be.false;
 			expect( dropdown.buttonView.isEnabled ).to.be.true;
 
 			insertRowAboveCommand.isEnabled = false;
-			expect( items.get( 2 ).isEnabled ).to.be.false;
+			expect( items.get( 3 ).isEnabled ).to.be.false;
 			expect( dropdown.buttonView.isEnabled ).to.be.true;
 
 			removeRowCommand.isEnabled = false;
 
-			expect( items.get( 3 ).isEnabled ).to.be.false;
+			expect( items.get( 4 ).isEnabled ).to.be.false;
 			expect( dropdown.buttonView.isEnabled ).to.be.false;
 		} );
 
@@ -216,9 +217,9 @@ describe( 'TableUI', () => {
 		it( 'should have proper items in panel', () => {
 			const listView = dropdown.listView;
 
-			const labels = listView.items.map( ( { label } ) => label );
+			const labels = listView.items.map( item => item instanceof ListSeparatorView ? '|' : item.label );
 
-			expect( labels ).to.deep.equal( [ 'Header column', 'Insert column before', 'Insert column after', 'Delete column' ] );
+			expect( labels ).to.deep.equal( [ 'Header column', '|', 'Insert column before', 'Insert column after', 'Delete column' ] );
 		} );
 
 		it( 'should bind items in panel to proper commands', () => {
@@ -235,9 +236,9 @@ describe( 'TableUI', () => {
 			removeColumnCommand.isEnabled = true;
 
 			expect( items.get( 0 ).isEnabled ).to.be.true;
-			expect( items.get( 1 ).isEnabled ).to.be.true;
 			expect( items.get( 2 ).isEnabled ).to.be.true;
 			expect( items.get( 3 ).isEnabled ).to.be.true;
+			expect( items.get( 4 ).isEnabled ).to.be.true;
 			expect( dropdown.buttonView.isEnabled ).to.be.true;
 
 			setColumnHeaderCommand.isEnabled = false;
@@ -247,14 +248,14 @@ describe( 'TableUI', () => {
 
 			insertColumnBeforeCommand.isEnabled = false;
 
-			expect( items.get( 1 ).isEnabled ).to.be.false;
+			expect( items.get( 2 ).isEnabled ).to.be.false;
 			expect( dropdown.buttonView.isEnabled ).to.be.true;
 
 			insertColumnAfterCommand.isEnabled = false;
-			expect( items.get( 2 ).isEnabled ).to.be.false;
+			expect( items.get( 3 ).isEnabled ).to.be.false;
 
 			removeColumnCommand.isEnabled = false;
-			expect( items.get( 3 ).isEnabled ).to.be.false;
+			expect( items.get( 4 ).isEnabled ).to.be.false;
 			expect( dropdown.buttonView.isEnabled ).to.be.false;
 		} );
 
@@ -309,13 +310,14 @@ describe( 'TableUI', () => {
 		it( 'should have proper items in panel', () => {
 			const listView = dropdown.listView;
 
-			const labels = listView.items.map( ( { label } ) => label );
+			const labels = listView.items.map( item => item instanceof ListSeparatorView ? '|' : item.label );
 
 			expect( labels ).to.deep.equal( [
 				'Merge cell up',
 				'Merge cell right',
 				'Merge cell down',
 				'Merge cell left',
+				'|',
 				'Split cell vertically',
 				'Split cell horizontally'
 			] );
@@ -342,8 +344,8 @@ describe( 'TableUI', () => {
 			expect( items.get( 1 ).isEnabled ).to.be.true;
 			expect( items.get( 2 ).isEnabled ).to.be.true;
 			expect( items.get( 3 ).isEnabled ).to.be.true;
-			expect( items.get( 4 ).isEnabled ).to.be.true;
 			expect( items.get( 5 ).isEnabled ).to.be.true;
+			expect( items.get( 6 ).isEnabled ).to.be.true;
 			expect( dropdown.buttonView.isEnabled ).to.be.true;
 
 			mergeCellUpCommand.isEnabled = false;
@@ -363,10 +365,10 @@ describe( 'TableUI', () => {
 			expect( items.get( 3 ).isEnabled ).to.be.false;
 
 			splitCellVerticallyCommand.isEnabled = false;
-			expect( items.get( 4 ).isEnabled ).to.be.false;
+			expect( items.get( 5 ).isEnabled ).to.be.false;
 
 			splitCellHorizontallyCommand.isEnabled = false;
-			expect( items.get( 5 ).isEnabled ).to.be.false;
+			expect( items.get( 6 ).isEnabled ).to.be.false;
 
 			expect( dropdown.buttonView.isEnabled ).to.be.false;
 		} );

+ 11 - 0
packages/ckeditor5-table/tests/ui/inserttableview.js

@@ -54,6 +54,11 @@ describe( 'InsertTableView', () => {
 			expect( view.items ).to.have.length( 100 );
 		} );
 
+		it( 'should not throw error for DropdownPanelFocusable interface methods', () => {
+			expect( () => view.focus() ).to.not.throw();
+			expect( () => view.focusLast() ).to.not.throw();
+		} );
+
 		describe( 'view#items bindings', () => {
 			it( 'updates view#height & view#width on "over" event', () => {
 				const boxView = view.items.get( 0 );
@@ -87,6 +92,12 @@ describe( 'InsertTableView', () => {
 				expect( view.label ).to.equal( '3 x 7' );
 			} );
 
+			it( 'mousedown event should be prevented', () => {
+				const ret = view.element.dispatchEvent( new Event( 'mousedown', { cancelable: true } ) );
+
+				expect( ret ).to.false;
+			} );
+
 			describe( 'DOM', () => {
 				it( 'fires execute on "click" event', () => {
 					const spy = sinon.spy();

+ 21 - 17
packages/ckeditor5-table/theme/table.css

@@ -3,24 +3,28 @@
  * For licensing, see LICENSE.md.
  */
 
-.ck table.ck-widget th.ck-editor__nested-editable {
-	border-color: inherit;
-	border-style: inset;
-}
+.ck.ck-content table {
+	/* Give the table some air and center it horizontally */
+	margin: 1em auto;
 
-.ck table.ck-widget td.ck-editor__nested-editable {
-	border-color: inherit;
-	border-style: inset;
-}
+	/* The table cells should have slight borders */
+	border-collapse: collapse;
+	border-spacing: 0;
 
-.ck table.ck-widget td.ck-editor__nested-editable.ck-editor__nested-editable_focused,
-.ck table.ck-widget td.ck-editor__nested-editable:focus {
-	background-color: inherit;
-	color: inherit;
-}
+	/* The outer border of the table should be slightly darker than the inner lines.
+	Also see https://github.com/ckeditor/ckeditor5-table/issues/50. */
+	border: 1px double hsl(0, 0%, 70%);
+
+	& td,
+	& th {
+		min-width: 2em;
+		padding: .4em;
+		text-align: center;
+		border-color: hsl(0, 0%, 85%);
+	}
 
-.ck table.ck-widget th.ck-editor__nested-editable.ck-editor__nested-editable_focused,
-.ck table.ck-widget th.ck-editor__nested-editable:focus {
-	background-color: inherit;
-	color: inherit;
+	& th {
+		font-weight: bold;
+		background: hsl(0, 0%, 98%);
+	}
 }

+ 10 - 0
packages/ckeditor5-table/theme/tableediting.css

@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/*
+ * Note: This file should contain the wireframe styles only. But since there are no such styles,
+ * it acts as a message to the builder telling that it should look for the corresponding styles
+ * **in the theme** when compiling the editor.
+ */