| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- /**
- * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
- */
- /**
- * @module typing/deleteobserver
- */
- import Observer from '@ckeditor/ckeditor5-engine/src/view/observer/observer';
- import DomEventData from '@ckeditor/ckeditor5-engine/src/view/observer/domeventdata';
- import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
- import env from '@ckeditor/ckeditor5-utils/src/env';
- /**
- * Delete observer introduces the {@link module:engine/view/document~Document#event:delete} event.
- *
- * @extends module:engine/view/observer/observer~Observer
- */
- export default class DeleteObserver extends Observer {
- constructor( view ) {
- super( view );
- const document = view.document;
- let sequence = 0;
- document.on( 'keyup', ( evt, data ) => {
- if ( data.keyCode == keyCodes.delete || data.keyCode == keyCodes.backspace ) {
- sequence = 0;
- }
- } );
- document.on( 'keydown', ( evt, data ) => {
- const deleteData = {};
- if ( data.keyCode == keyCodes.delete ) {
- deleteData.direction = 'forward';
- deleteData.unit = 'character';
- } else if ( data.keyCode == keyCodes.backspace ) {
- deleteData.direction = 'backward';
- deleteData.unit = 'codePoint';
- } else {
- return;
- }
- const hasWordModifier = env.isMac ? data.altKey : data.ctrlKey;
- deleteData.unit = hasWordModifier ? 'word' : deleteData.unit;
- deleteData.sequence = ++sequence;
- fireViewDeleteEvent( evt, data.domEvent, deleteData );
- } );
- // `beforeinput` is handled only for Android devices. Desktop Chrome and iOS are skipped because they are working fine now.
- if ( env.isAndroid ) {
- document.on( 'beforeinput', ( evt, data ) => {
- // If event type is other than `deleteContentBackward` then this is not deleting.
- if ( data.domEvent.inputType != 'deleteContentBackward' ) {
- return;
- }
- const deleteData = {
- unit: 'codepoint',
- direction: 'backward',
- sequence: 1
- };
- // Android IMEs may change the DOM selection on `beforeinput` event so that the selection contains all the text
- // that the IME wants to remove. We will pass this information to `delete` event so proper part of the content is removed.
- //
- // Sometimes it is only expanding by a one character (in case of collapsed selection). In this case we don't need to
- // set a different selection to remove, it will work just fine.
- const domSelection = data.domTarget.ownerDocument.defaultView.getSelection();
- if ( domSelection.anchorNode == domSelection.focusNode && domSelection.anchorOffset + 1 != domSelection.focusOffset ) {
- deleteData.selectionToRemove = view.domConverter.domSelectionToView( domSelection );
- }
- fireViewDeleteEvent( evt, data.domEvent, deleteData );
- } );
- }
- function fireViewDeleteEvent( originalEvent, domEvent, deleteData ) {
- // Save the event object to check later if it was stopped or not.
- let event;
- document.once( 'delete', evt => ( event = evt ), { priority: Number.POSITIVE_INFINITY } );
- document.fire( 'delete', new DomEventData( document, domEvent, deleteData ) );
- // Stop the original event if `delete` event was stopped.
- // https://github.com/ckeditor/ckeditor5/issues/753
- if ( event && event.stop.called ) {
- originalEvent.stop();
- }
- }
- }
- /**
- * @inheritDoc
- */
- observe() {}
- }
- /**
- * Event fired when the user tries to delete content (e.g. presses <kbd>Delete</kbd> or <kbd>Backspace</kbd>).
- *
- * Note: This event is fired by the {@link module:typing/deleteobserver~DeleteObserver observer}
- * (usually registered by the {@link module:typing/delete~Delete delete feature}).
- *
- * @event module:engine/view/document~Document#event:delete
- * @param {module:engine/view/observer/domeventdata~DomEventData} data
- * @param {'forward'|'delete'} data.direction The direction in which the deletion should happen.
- * @param {'character'|'word'} data.unit The "amount" of content that should be deleted.
- * @param {Number} data.sequence A number describing which subsequent delete event it is without the key being released.
- * If it's 2 or more it means that the key was pressed and hold.
- * @param {module:engine/view/selection~Selection} [data.selectionToRemove] View selection which content should be removed. If not set,
- * current selection should be used.
- */
|