| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- /**
- * @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 link/ui/linkformview
- */
- import View from '@ckeditor/ckeditor5-ui/src/view';
- import ViewCollection from '@ckeditor/ckeditor5-ui/src/viewcollection';
- import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
- import SwitchButtonView from '@ckeditor/ckeditor5-ui/src/button/switchbuttonview';
- import LabeledFieldView from '@ckeditor/ckeditor5-ui/src/labeledfield/labeledfieldview';
- import { createLabeledInputText } from '@ckeditor/ckeditor5-ui/src/labeledfield/utils';
- import submitHandler from '@ckeditor/ckeditor5-ui/src/bindings/submithandler';
- import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
- import FocusCycler from '@ckeditor/ckeditor5-ui/src/focuscycler';
- import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';
- import checkIcon from '@ckeditor/ckeditor5-core/theme/icons/check.svg';
- import cancelIcon from '@ckeditor/ckeditor5-core/theme/icons/cancel.svg';
- import '../../theme/linkform.css';
- import '@ckeditor/ckeditor5-ui/theme/components/responsive-form/responsiveform.css';
- /**
- * The link form view controller class.
- *
- * See {@link module:link/ui/linkformview~LinkFormView}.
- *
- * @extends module:ui/view~View
- */
- export default class LinkFormView extends View {
- /**
- * Creates an instance of the {@link module:link/ui/linkformview~LinkFormView} class.
- *
- * Also see {@link #render}.
- *
- * @param {module:utils/locale~Locale} [locale] The localization services instance.
- * @param {module:link/linkcommand~LinkCommand} linkCommand Reference to {@link module:link/linkcommand~LinkCommand}.
- * @param {String} [protocol] A value of a protocol to be displayed in the input's placeholder.
- */
- constructor( locale, linkCommand, protocol ) {
- super( locale );
- const t = locale.t;
- /**
- * Tracks information about DOM focus in the form.
- *
- * @readonly
- * @member {module:utils/focustracker~FocusTracker}
- */
- this.focusTracker = new FocusTracker();
- /**
- * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
- *
- * @readonly
- * @member {module:utils/keystrokehandler~KeystrokeHandler}
- */
- this.keystrokes = new KeystrokeHandler();
- /**
- * The URL input view.
- *
- * @member {module:ui/labeledfield/labeledfieldview~LabeledFieldView}
- */
- this.urlInputView = this._createUrlInput( protocol );
- /**
- * The Save button view.
- *
- * @member {module:ui/button/buttonview~ButtonView}
- */
- this.saveButtonView = this._createButton( t( 'Save' ), checkIcon, 'ck-button-save' );
- this.saveButtonView.type = 'submit';
- /**
- * The Cancel button view.
- *
- * @member {module:ui/button/buttonview~ButtonView}
- */
- this.cancelButtonView = this._createButton( t( 'Cancel' ), cancelIcon, 'ck-button-cancel', 'cancel' );
- /**
- * A collection of {@link module:ui/button/switchbuttonview~SwitchButtonView},
- * which corresponds to {@link module:link/linkcommand~LinkCommand#manualDecorators manual decorators}
- * configured in the editor.
- *
- * @private
- * @readonly
- * @type {module:ui/viewcollection~ViewCollection}
- */
- this._manualDecoratorSwitches = this._createManualDecoratorSwitches( linkCommand );
- /**
- * A collection of child views in the form.
- *
- * @readonly
- * @type {module:ui/viewcollection~ViewCollection}
- */
- this.children = this._createFormChildren( linkCommand.manualDecorators );
- /**
- * A collection of views that can be focused in the form.
- *
- * @readonly
- * @protected
- * @member {module:ui/viewcollection~ViewCollection}
- */
- this._focusables = new ViewCollection();
- /**
- * Helps cycling over {@link #_focusables} in the form.
- *
- * @readonly
- * @protected
- * @member {module:ui/focuscycler~FocusCycler}
- */
- this._focusCycler = new FocusCycler( {
- focusables: this._focusables,
- focusTracker: this.focusTracker,
- keystrokeHandler: this.keystrokes,
- actions: {
- // Navigate form fields backwards using the Shift + Tab keystroke.
- focusPrevious: 'shift + tab',
- // Navigate form fields forwards using the Tab key.
- focusNext: 'tab'
- }
- } );
- const classList = [ 'ck', 'ck-link-form', 'ck-responsive-form' ];
- if ( linkCommand.manualDecorators.length ) {
- classList.push( 'ck-link-form_layout-vertical', 'ck-vertical-form' );
- }
- this.setTemplate( {
- tag: 'form',
- attributes: {
- class: classList,
- // https://github.com/ckeditor/ckeditor5-link/issues/90
- tabindex: '-1'
- },
- children: this.children
- } );
- }
- /**
- * Obtains the state of the {@link module:ui/button/switchbuttonview~SwitchButtonView switch buttons} representing
- * {@link module:link/linkcommand~LinkCommand#manualDecorators manual link decorators}
- * in the {@link module:link/ui/linkformview~LinkFormView}.
- *
- * @returns {Object.<String,Boolean>} Key-value pairs, where the key is the name of the decorator and the value is
- * its state.
- */
- getDecoratorSwitchesState() {
- return Array.from( this._manualDecoratorSwitches ).reduce( ( accumulator, switchButton ) => {
- accumulator[ switchButton.name ] = switchButton.isOn;
- return accumulator;
- }, {} );
- }
- /**
- * @inheritDoc
- */
- render() {
- super.render();
- submitHandler( {
- view: this
- } );
- const childViews = [
- this.urlInputView,
- ...this._manualDecoratorSwitches,
- this.saveButtonView,
- this.cancelButtonView
- ];
- childViews.forEach( v => {
- // Register the view as focusable.
- this._focusables.add( v );
- // Register the view in the focus tracker.
- this.focusTracker.add( v.element );
- } );
- // Start listening for the keystrokes coming from #element.
- this.keystrokes.listenTo( this.element );
- }
- /**
- * Focuses the fist {@link #_focusables} in the form.
- */
- focus() {
- this._focusCycler.focusFirst();
- }
- /**
- * Creates a labeled input view.
- *
- * @private
- * @param {String} [protocol=http://] A value of a protocol to be displayed in the input's placeholder.
- * @returns {module:ui/labeledfield/labeledfieldview~LabeledFieldView} Labeled field view instance.
- */
- _createUrlInput( protocol = 'https://' ) {
- const t = this.locale.t;
- const labeledInput = new LabeledFieldView( this.locale, createLabeledInputText );
- labeledInput.label = t( 'Link URL' );
- labeledInput.fieldView.placeholder = protocol + 'example.com';
- return labeledInput;
- }
- /**
- * Creates a button view.
- *
- * @private
- * @param {String} label The button label.
- * @param {String} icon The button icon.
- * @param {String} className The additional button CSS class name.
- * @param {String} [eventName] An event name that the `ButtonView#execute` event will be delegated to.
- * @returns {module:ui/button/buttonview~ButtonView} The button view instance.
- */
- _createButton( label, icon, className, eventName ) {
- const button = new ButtonView( this.locale );
- button.set( {
- label,
- icon,
- tooltip: true
- } );
- button.extendTemplate( {
- attributes: {
- class: className
- }
- } );
- if ( eventName ) {
- button.delegate( 'execute' ).to( this, eventName );
- }
- return button;
- }
- /**
- * Populates {@link module:ui/viewcollection~ViewCollection} of {@link module:ui/button/switchbuttonview~SwitchButtonView}
- * made based on {@link module:link/linkcommand~LinkCommand#manualDecorators}.
- *
- * @private
- * @param {module:link/linkcommand~LinkCommand} linkCommand A reference to the link command.
- * @returns {module:ui/viewcollection~ViewCollection} of switch buttons.
- */
- _createManualDecoratorSwitches( linkCommand ) {
- const switches = this.createCollection();
- for ( const manualDecorator of linkCommand.manualDecorators ) {
- const switchButton = new SwitchButtonView( this.locale );
- switchButton.set( {
- name: manualDecorator.id,
- label: manualDecorator.label,
- withText: true
- } );
- switchButton.bind( 'isOn' ).toMany( [ manualDecorator, linkCommand ], 'value', ( decoratorValue, commandValue ) => {
- return commandValue === undefined && decoratorValue === undefined ? manualDecorator.defaultValue : decoratorValue;
- } );
- switchButton.on( 'execute', () => {
- manualDecorator.set( 'value', !switchButton.isOn );
- } );
- switches.add( switchButton );
- }
- return switches;
- }
- /**
- * Populates the {@link #children} collection of the form.
- *
- * If {@link module:link/linkcommand~LinkCommand#manualDecorators manual decorators} are configured in the editor, it creates an
- * additional `View` wrapping all {@link #_manualDecoratorSwitches} switch buttons corresponding
- * to these decorators.
- *
- * @private
- * @param {module:utils/collection~Collection} manualDecorators A reference to
- * the collection of manual decorators stored in the link command.
- * @returns {module:ui/viewcollection~ViewCollection} The children of link form view.
- */
- _createFormChildren( manualDecorators ) {
- const children = this.createCollection();
- children.add( this.urlInputView );
- if ( manualDecorators.length ) {
- const additionalButtonsView = new View();
- additionalButtonsView.setTemplate( {
- tag: 'ul',
- children: this._manualDecoratorSwitches.map( switchButton => ( {
- tag: 'li',
- children: [ switchButton ],
- attributes: {
- class: [
- 'ck',
- 'ck-list__item'
- ]
- }
- } ) ),
- attributes: {
- class: [
- 'ck',
- 'ck-reset',
- 'ck-list'
- ]
- }
- } );
- children.add( additionalButtonsView );
- }
- children.add( this.saveButtonView );
- children.add( this.cancelButtonView );
- return children;
- }
- }
- /**
- * Fired when the form view is submitted (when one of the children triggered the submit event),
- * for example with a click on {@link #saveButtonView}.
- *
- * @event submit
- */
- /**
- * Fired when the form view is canceled, for example with a click on {@link #cancelButtonView}.
- *
- * @event cancel
- */
|