/**
* @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/
/**
* @module typing/deletecommand
*/
import Command from '../core/command/command.js';
import Selection from '../engine/model/selection.js';
import ChangeBuffer from './changebuffer.js';
import count from '../utils/count.js';
/**
* The delete command. Used by the {@link module:typing/delete~Delete delete feature} to handle the Delete and
* Backspace keys.
*
* @extends core.command.Command
*/
export default class DeleteCommand extends Command {
/**
* Creates an instance of the command.
*
* @param {module:core/editor/editor~Editor} editor
* @param {'forward'|'backward'} direction The directionality of the delete describing in what direction it
* should consume the content when the selection is collapsed.
*/
constructor( editor, direction ) {
super( editor );
/**
* The directionality of the delete describing in what direction it should
* consume the content when the selection is collapsed.
*
* @readonly
* @member {'forward'|'backward'} #direction
*/
this.direction = direction;
/**
* Delete's change buffer used to group subsequent changes into batches.
*
* @readonly
* @private
* @member {typing.ChangeBuffer} #buffer
*/
this._buffer = new ChangeBuffer( editor.document, editor.config.get( 'undo.step' ) );
}
/**
* Executes the delete command. Depending on whether the selection is collapsed or not, deletes its content
* or a piece of content in the {@link #direction defined direction}.
*
* @param {Object} [options] The command options.
* @param {'character'} [options.unit='character'] See {@link module:engine/controller/modifyselection~modifySelection}'s
* options.
*/
_doExecute( options = {} ) {
const doc = this.editor.document;
const dataController = this.editor.data;
doc.enqueueChanges( () => {
const selection = Selection.createFromSelection( doc.selection );
// Try to extend the selection in the specified direction.
if ( selection.isCollapsed ) {
dataController.modifySelection( selection, { direction: this.direction, unit: options.unit } );
}
// If selection is still collapsed, then there's nothing to delete.
if ( selection.isCollapsed ) {
return;
}
let changeCount = 0;
selection.getFirstRange().getMinimalFlatRanges().forEach( ( range ) => {
changeCount += count(
range.getWalker( { singleCharacters: true, ignoreElementEnd: true, shallow: true } )
);
} );
dataController.deleteContent( selection, this._buffer.batch, { merge: true } );
this._buffer.input( changeCount );
doc.selection.setRanges( selection.getRanges(), selection.isBackward );
} );
}
}