webui/src/components/common/ckeditor/plugins/abbreviation/abbreviationui.js
2026-01-20 21:48:51 +00:00

133 lines
3.8 KiB
JavaScript

/**
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md.
*/
import { ButtonView, ContextualBalloon, Plugin, clickOutsideHandler } from 'ckeditor5';
import FormView from './abbreviationview';
import getRangeText from './utils.js';
import './styles.css';
export default class AbbreviationUI extends Plugin {
static get requires() {
return [ ContextualBalloon ];
}
init() {
const editor = this.editor;
// Create the balloon and the form view.
this._balloon = this.editor.plugins.get( ContextualBalloon );
this.formView = this._createFormView();
editor.ui.componentFactory.add( 'abbreviation', () => {
const button = new ButtonView();
button.label = 'Abbreviation';
button.tooltip = true;
button.withText = true;
// Show the UI on button click.
this.listenTo( button, 'execute', () => {
this._showUI();
} );
return button;
} );
}
_createFormView() {
const editor = this.editor;
const formView = new FormView( editor.locale );
// Execute the command after clicking the "Save" button.
this.listenTo( formView, 'submit', () => {
// Grab values from the abbreviation and title input fields.
const value = {
abbr: formView.abbrInputView.fieldView.element.value,
title: formView.titleInputView.fieldView.element.value
};
editor.execute( 'addAbbreviation', value );
// Hide the form view after submit.
this._hideUI();
} );
// Hide the form view after clicking the "Cancel" button.
this.listenTo( formView, 'cancel', () => {
this._hideUI();
} );
// Hide the form view when clicking outside the balloon.
clickOutsideHandler( {
emitter: formView,
activator: () => this._balloon.visibleView === formView,
contextElements: [ this._balloon.view.element ],
callback: () => this._hideUI()
} );
formView.keystrokes.set( 'Esc', ( data, cancel ) => {
this._hideUI();
cancel();
} );
return formView;
}
_showUI() {
const selection = this.editor.model.document.selection;
// Check the value of the command.
const commandValue = this.editor.commands.get( 'addAbbreviation' ).value;
this._balloon.add( {
view: this.formView,
position: this._getBalloonPositionData()
} );
// Disable the input when the selection is not collapsed.
this.formView.abbrInputView.isEnabled = selection.getFirstRange().isCollapsed;
// Fill the form using the state (value) of the command.
if ( commandValue ) {
this.formView.abbrInputView.fieldView.value = commandValue.abbr;
this.formView.titleInputView.fieldView.value = commandValue.title;
}
// If the command has no value, put the currently selected text (not collapsed)
// in the first field and empty the second in that case.
else {
const selectedText = getRangeText( selection.getFirstRange() );
this.formView.abbrInputView.fieldView.value = selectedText;
this.formView.titleInputView.fieldView.value = '';
}
this.formView.focus();
}
_hideUI() {
// Clear the input field values and reset the form.
this.formView.abbrInputView.fieldView.value = '';
this.formView.titleInputView.fieldView.value = '';
this.formView.element.reset();
this._balloon.remove( this.formView );
// Focus the editing view after inserting the abbreviation so the user can start typing the content
// right away and keep the editor focused.
this.editor.editing.view.focus();
}
_getBalloonPositionData() {
const view = this.editor.editing.view;
const viewDocument = view.document;
let target = null;
// Set a target position by converting view selection range to DOM
target = () => view.domConverter.viewRangeToDom( viewDocument.selection.getFirstRange() );
return {
target
};
}
}