| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- /**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
- /**
- * @module table/tableediting
- */
- import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
- import Position from '@ckeditor/ckeditor5-engine/src/model/position';
- import TableWalker from './tablewalker';
- import TableUtils from './tableutils';
- import { findAncestor } from './commands/utils';
- import Range from '@ckeditor/ckeditor5-engine/src/model/range';
- export default class TableSelection extends Plugin {
- /**
- * @inheritDoc
- */
- static get pluginName() {
- return 'TableSelection';
- }
- /**
- * @inheritDoc
- */
- static get requires() {
- return [ TableUtils ];
- }
- constructor( editor ) {
- super( editor );
- this._isSelecting = false;
- this._highlighted = new Set();
- this.editor = editor;
- this.tableUtils = editor.plugins.get( TableUtils );
- }
- init() {
- const editor = this.editor;
- const viewDocument = editor.editing.view.document;
- this.listenTo( viewDocument, 'mousedown', ( eventInfo, domEventData ) => {
- const tableCell = getTableCell( domEventData, this.editor );
- if ( !tableCell ) {
- return;
- }
- this.startSelection( tableCell );
- } );
- this.listenTo( viewDocument, 'mousemove', ( eventInfo, domEventData ) => {
- if ( !this.isSelecting ) {
- return;
- }
- const tableCell = getTableCell( domEventData, this.editor );
- if ( !tableCell ) {
- return;
- }
- const wasOne = this.size === 1;
- this.updateSelection( tableCell );
- if ( this.size > 1 ) {
- domEventData.preventDefault();
- if ( wasOne ) {
- // TODO:
- // editor.editing.view.change( writer => {
- // // TODO const viewElement = editor.editing.mapper.toViewElement( this._startElement );
- //
- // // Set selection to the first selected table cell.
- // // writer.setSelection( ViewRange.createIn( viewElement ), {
- // // fake: true,
- // // label: 'fake selection over table cell'
- // // } );
- // } );
- }
- this.redrawSelection();
- }
- } );
- this.listenTo( viewDocument, 'mouseup', ( eventInfo, domEventData ) => {
- if ( !this.isSelecting ) {
- return;
- }
- const tableCell = getTableCell( domEventData, this.editor );
- this.stopSelection( tableCell );
- } );
- }
- get isSelecting() {
- return this._isSelecting;
- }
- get size() {
- return [ ...this.getSelection() ].length;
- }
- startSelection( tableCell ) {
- this.clearSelection();
- this._isSelecting = true;
- this._startElement = tableCell;
- this._endElement = tableCell;
- // todo: stop rendering
- this.editor.editing.view._renderer.renderSelection = false;
- }
- updateSelection( tableCell ) {
- // Do not update if not in selection mode or no table cell passed.
- if ( !this.isSelecting || !tableCell ) {
- return;
- }
- const table = this._startElement.parent.parent;
- // Do not add tableCell to selection if it is from other table or is already set as end element.
- if ( table !== tableCell.parent.parent || this._endElement === tableCell ) {
- return;
- }
- const headingRows = parseInt( table.getAttribute( 'headingRows' ) || 0 );
- const startInHeading = this._startElement.parent.index < headingRows;
- const updateCellInHeading = tableCell.parent.index < headingRows;
- // Only add cell to selection if they are in the same table section.
- if ( startInHeading === updateCellInHeading ) {
- this._endElement = tableCell;
- this.redrawSelection();
- }
- }
- stopSelection( tableCell ) {
- if ( this.isSelecting && tableCell && tableCell.parent.parent === this._startElement.parent.parent ) {
- this._endElement = tableCell;
- }
- this._isSelecting = false;
- this.editor.editing.view._renderer.renderSelection = true;
- }
- clearSelection() {
- this._startElement = undefined;
- this._endElement = undefined;
- this._isSelecting = false;
- this.clearPreviousSelection();
- this._highlighted.clear();
- this.editor.editing.view._renderer.renderSelection = true;
- }
- * getSelection() {
- if ( !this._startElement || !this._endElement ) {
- return;
- }
- yield* this._getBlockSelection();
- }
- * _getBlockSelection() {
- const startLocation = this.tableUtils.getCellLocation( this._startElement );
- const endLocation = this.tableUtils.getCellLocation( this._endElement );
- const startRow = startLocation.row > endLocation.row ? endLocation.row : startLocation.row;
- const endRow = startLocation.row > endLocation.row ? startLocation.row : endLocation.row;
- const startColumn = startLocation.column > endLocation.column ? endLocation.column : startLocation.column;
- const endColumn = startLocation.column > endLocation.column ? startLocation.column : endLocation.column;
- for ( const cellInfo of new TableWalker( this._startElement.parent.parent, { startRow, endRow } ) ) {
- if ( cellInfo.column >= startColumn && cellInfo.column <= endColumn ) {
- yield cellInfo.cell;
- }
- }
- }
- redrawSelection() {
- const editor = this.editor;
- const mapper = editor.editing.mapper;
- const view = editor.editing.view;
- const model = editor.model;
- const modelRanges = [];
- const selected = [ ...this.getSelection() ];
- const previous = [ ...this._highlighted.values() ];
- this._highlighted.clear();
- for ( const tableCell of selected ) {
- const viewElement = mapper.toViewElement( tableCell );
- modelRanges.push( Range.createOn( tableCell ) );
- this._highlighted.add( viewElement );
- }
- // Update model's selection
- model.change( writer => {
- writer.setSelection( modelRanges );
- } );
- view.change( writer => {
- for ( const previouslyHighlighted of previous ) {
- if ( !selected.includes( previouslyHighlighted ) ) {
- writer.removeClass( 'selected', previouslyHighlighted );
- }
- }
- for ( const currently of this._highlighted ) {
- writer.addClass( 'selected', currently );
- }
- } );
- }
- clearPreviousSelection() {
- const previous = [ ...this._highlighted.values() ];
- this.editor.editing.view.change( writer => {
- for ( const previouslyHighlighted of previous ) {
- writer.removeClass( 'selected', previouslyHighlighted );
- }
- } );
- }
- }
- function getTableCell( domEventData, editor ) {
- const element = domEventData.target;
- const modelElement = editor.editing.mapper.toModelElement( element );
- if ( !modelElement ) {
- return;
- }
- return findAncestor( 'tableCell', Position.createAt( modelElement ) );
- }
|