Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge pull request #23 from ckeditor/t/1
Browse files Browse the repository at this point in the history
Feature: Implemented the basic user interface of the feature (see #1).
  • Loading branch information
oleq authored Jun 5, 2018
2 parents 8fbf8b2 + cf7f363 commit b8b9799
Show file tree
Hide file tree
Showing 30 changed files with 1,936 additions and 231 deletions.
6 changes: 5 additions & 1 deletion src/commands/insertcolumncommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ export default class InsertColumnCommand extends Command {
}

/**
* @inheritDoc
* Executes the command.
*
* Depending on command's {@link #order} value it inserts a column `'before'` or `'after'` the column in which selection is set.
*
* @fires execute
*/
execute() {
const editor = this.editor;
Expand Down
6 changes: 5 additions & 1 deletion src/commands/insertrowcommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ export default class InsertRowCommand extends Command {
}

/**
* @inheritDoc
* Executes the command.
*
* Depending on command's {@link #order} value it inserts a row `'below'` or `'above'` the row in which selection is set.
*
* @fires execute
*/
execute() {
const editor = this.editor;
Expand Down
9 changes: 8 additions & 1 deletion src/commands/inserttablecommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,14 @@ export default class InsertTableCommand extends Command {
}

/**
* @inheritDoc
* Executes the command.
*
* Inserts table of given rows and columns into the editor.
*
* @param {Object} options
* @param {Number} [options.rows=2] Number of rows to create in inserted table.
* @param {Number} [options.columns=2] Number of columns to create in inserted table.
* @fires execute
*/
execute( options = {} ) {
const model = this.editor.model;
Expand Down
6 changes: 5 additions & 1 deletion src/commands/mergecellcommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ export default class MergeCellCommand extends Command {
}

/**
* @inheritDoc
* Executes the command.
*
* Depending on command's {@link #direction} value it will merge a cell that is to the `'left'`, `'right'`, `'up'` or `'down'`.
*
* @fires execute
*/
execute() {
const model = this.editor.model;
Expand Down
2 changes: 1 addition & 1 deletion src/commands/removecolumncommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import TableUtils from '../tableutils';
import { updateNumericAttribute } from './utils';

/**
* The split cell command.
* The remove column command.
*
* @extends module:core/command~Command
*/
Expand Down
96 changes: 96 additions & 0 deletions src/commands/setheadercolumncommand.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
* @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/

/**
* @module table/commands/setheadercolumncommand
*/

import Command from '@ckeditor/ckeditor5-core/src/command';

import { getParentTable, updateNumericAttribute } from './utils';

/**
* The header coloumn command.
*
* @extends module:core/command~Command
*/
export default class SetHeaderColumnCommand extends Command {
/**
* @inheritDoc
*/
refresh() {
const model = this.editor.model;
const doc = model.document;
const selection = doc.selection;

const position = selection.getFirstPosition();
const tableParent = getParentTable( position );

const isInTable = !!tableParent;

this.isEnabled = isInTable;

/**
* Flag indicating whether the command is active. The command is active when the
* {@link module:engine/model/selection~Selection} is in a header column.
*
* @observable
* @readonly
* @member {Boolean} #value
*/
this.value = isInTable && this._isInHeading( position.parent, tableParent );
}

/**
* Executes the command.
*
* When the selection is non-header column, the command will set `headingColumns` table's attribute to cover that column.
*
* When selection is already in a header column then it will set `headingColumns` so the heading section will end before that column.
*
* @fires execute
*/
execute() {
const model = this.editor.model;
const doc = model.document;
const selection = doc.selection;
const tableUtils = this.editor.plugins.get( 'TableUtils' );

const position = selection.getFirstPosition();
const tableCell = position.parent;
const tableRow = tableCell.parent;
const table = tableRow.parent;

const currentHeadingColumns = parseInt( table.getAttribute( 'headingColumns' ) || 0 );

let { column } = tableUtils.getCellLocation( tableCell );

if ( column + 1 !== currentHeadingColumns ) {
column++;
}

model.change( writer => {
updateNumericAttribute( 'headingColumns', column, table, writer, 0 );
} );
}

/**
* Checks if a table cell is in the heading section.
*
* @param {module:engine/model/element~Element} tableCell
* @param {module:engine/model/element~Element} table
* @returns {Boolean}
* @private
*/
_isInHeading( tableCell, table ) {
const headingColumns = parseInt( table.getAttribute( 'headingColumns' ) || 0 );

const tableUtils = this.editor.plugins.get( 'TableUtils' );

const { column } = tableUtils.getCellLocation( tableCell );

return !!headingColumns && column < headingColumns;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

/**
* @module table/commands/settableheaderscommand
* @module table/commands/setheaderrowcommand
*/

import Command from '@ckeditor/ckeditor5-core/src/command';
Expand All @@ -14,11 +14,11 @@ import { getParentTable, updateNumericAttribute } from './utils';
import TableWalker from '../tablewalker';

/**
* The set table headers command.
* The header row command.
*
* @extends module:core/command~Command
*/
export default class SetTableHeadersCommand extends Command {
export default class SetHeaderRowCommand extends Command {
/**
* @inheritDoc
*/
Expand All @@ -27,41 +27,78 @@ export default class SetTableHeadersCommand extends Command {
const doc = model.document;
const selection = doc.selection;

const tableParent = getParentTable( selection.getFirstPosition() );
const position = selection.getFirstPosition();
const tableParent = getParentTable( position );

this.isEnabled = !!tableParent;
const isInTable = !!tableParent;

this.isEnabled = isInTable;

/**
* Flag indicating whether the command is active. The command is active when the
* {@link module:engine/model/selection~Selection} is in a header row.
*
* @observable
* @readonly
* @member {Boolean} #value
*/
this.value = isInTable && this._isInHeading( position.parent, tableParent );
}

/**
* @inheritDoc
* Executes the command.
*
* When the selection is non-header row, the command will set `headingRows` table's attribute to cover that row.
*
* When selection is already in a header row then it will set `headingRows` so the heading section will end before that row.
*
* @fires execute
*/
execute( options = {} ) {
execute() {
const model = this.editor.model;
const doc = model.document;
const selection = doc.selection;

const rowsToSet = parseInt( options.rows ) || 0;
const position = selection.getFirstPosition();
const tableCell = position.parent;
const tableRow = tableCell.parent;
const table = tableRow.parent;

const table = getParentTable( selection.getFirstPosition() );
const currentHeadingRows = table.getAttribute( 'headingRows' ) || 0;
let rowIndex = tableRow.index;

model.change( writer => {
const currentHeadingRows = table.getAttribute( 'headingRows' ) || 0;
if ( rowIndex + 1 !== currentHeadingRows ) {
rowIndex++;
}

if ( currentHeadingRows !== rowsToSet && rowsToSet > 0 ) {
// Changing heading rows requires to check if any of a heading cell is overlaping vertically the table head.
model.change( writer => {
if ( rowIndex ) {
// Changing heading rows requires to check if any of a heading cell is overlapping vertically the table head.
// Any table cell that has a rowspan attribute > 1 will not exceed the table head so we need to fix it in rows below.
const cellsToSplit = getOverlappingCells( table, rowsToSet, currentHeadingRows );
const cellsToSplit = getOverlappingCells( table, rowIndex, currentHeadingRows );

for ( const cell of cellsToSplit ) {
splitHorizontally( cell, rowsToSet, writer );
splitHorizontally( cell, rowIndex, writer );
}
}

const columnsToSet = parseInt( options.columns ) || 0;
updateTableAttribute( table, 'headingColumns', columnsToSet, writer );
updateTableAttribute( table, 'headingRows', rowsToSet, writer );
updateNumericAttribute( 'headingRows', rowIndex, table, writer, 0 );
} );
}

/**
* Checks if table cell is in heading section.
*
* @param {module:engine/model/element~Element} tableCell
* @param {module:engine/model/element~Element} table
* @returns {Boolean}
* @private
*/
_isInHeading( tableCell, table ) {
const headingRows = parseInt( table.getAttribute( 'headingRows' ) || 0 );

return !!headingRows && tableCell.parent.index < headingRows;
}
}

// Returns cells that span beyond new heading section.
Expand All @@ -86,15 +123,6 @@ function getOverlappingCells( table, headingRowsToSet, currentHeadingRows ) {
return cellsToSplit;
}

// @private
function updateTableAttribute( table, attributeName, newValue, writer ) {
const currentValue = table.getAttribute( attributeName ) || 0;

if ( newValue !== currentValue ) {
updateNumericAttribute( attributeName, newValue, table, writer, 0 );
}
}

// Splits table cell horizontally.
//
// @param {module:engine/model/element~Element} tableCell
Expand Down
5 changes: 3 additions & 2 deletions src/converters/downcast.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
import ViewPosition from '@ckeditor/ckeditor5-engine/src/view/position';
import ViewRange from '@ckeditor/ckeditor5-engine/src/view/range';
import TableWalker from './../tablewalker';
import { toWidget, toWidgetEditable } from '@ckeditor/ckeditor5-widget/src/utils';
import { toWidgetEditable } from '@ckeditor/ckeditor5-widget/src/utils';
import { toTableWidget } from '../utils';

/**
* Model table element to view table element conversion helper.
Expand Down Expand Up @@ -40,7 +41,7 @@ export function downcastInsertTable( options = {} ) {
let tableWidget;

if ( asWidget ) {
tableWidget = toWidget( tableElement, conversionApi.writer );
tableWidget = toTableWidget( tableElement, conversionApi.writer );
}

const tableWalker = new TableWalker( table );
Expand Down
15 changes: 15 additions & 0 deletions src/table.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,18 @@ export default class Table extends Plugin {
return 'Table';
}
}

/**
* The configuration of the table features. Used by the table features in the `@ckeditor/ckeditor5-table` package.
*
* ClassicEditor
* .create( editorElement, {
* table: ... // Table feature options.
* } )
* .then( ... )
* .catch( ... );
*
* See {@link module:core/editor/editorconfig~EditorConfig all editor options}.
*
* @interface TableConfig
*/
8 changes: 5 additions & 3 deletions src/tableediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ import SplitCellCommand from './commands/splitcellcommand';
import MergeCellCommand from './commands/mergecellcommand';
import RemoveRowCommand from './commands/removerowcommand';
import RemoveColumnCommand from './commands/removecolumncommand';
import SetTableHeadersCommand from './commands/settableheaderscommand';
import SetHeaderRowCommand from './commands/setheaderrowcommand';
import SetHeaderColumnCommand from './commands/setheadercolumncommand';
import { getParentTable } from './commands/utils';
import TableUtils from './tableutils';

import './../theme/table.css';
import TableUtils from './tableutils';

/**
* The table editing feature.
Expand Down Expand Up @@ -111,7 +112,8 @@ export default class TableEditing extends Plugin {
editor.commands.add( 'mergeCellDown', new MergeCellCommand( editor, { direction: 'down' } ) );
editor.commands.add( 'mergeCellUp', new MergeCellCommand( editor, { direction: 'up' } ) );

editor.commands.add( 'setTableHeaders', new SetTableHeadersCommand( editor ) );
editor.commands.add( 'setColumnHeader', new SetHeaderColumnCommand( editor ) );
editor.commands.add( 'setRowHeader', new SetHeaderRowCommand( editor ) );

// Handle tab key navigation.
this.listenTo( editor.editing.view.document, 'keydown', ( ...args ) => this._handleTabOnSelectedTable( ...args ) );
Expand Down
Loading

0 comments on commit b8b9799

Please sign in to comment.