| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- /**
- * @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 image/imageupload/ui/imageuploadpanelview
- */
- import View from '@ckeditor/ckeditor5-ui/src/view';
- import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
- import SplitButtonView from '@ckeditor/ckeditor5-ui/src/dropdown/button/splitbuttonview';
- import ImageUploadFormRowView from './imageuploadformrowview';
- import { createDropdown } from '@ckeditor/ckeditor5-ui/src/dropdown/utils';
- import Collection from '@ckeditor/ckeditor5-utils/src/collection';
- import ViewCollection from '@ckeditor/ckeditor5-ui/src/viewcollection';
- 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 imageIcon from '@ckeditor/ckeditor5-core/theme/icons/image.svg';
- import checkIcon from '@ckeditor/ckeditor5-core/theme/icons/check.svg';
- import cancelIcon from '@ckeditor/ckeditor5-core/theme/icons/cancel.svg';
- import '../../../theme/imageupload.css';
- /**
- * The insert an image via URL view controller class.
- *
- * See {@link module:image/imageupload/ui/imageuploadpanelview~ImageUploadPanelView}.
- *
- * @extends module:ui/view~View
- */
- export default class ImageUploadPanelView extends View {
- /**
- * Creates a view for the dropdown panel of {@link module:image/imageupload/imageuploadui~ImageUploadUI}.
- *
- * @param {module:utils/locale~Locale} [locale] The localization services instance.
- * @param {Object} [integrations] An integrations object that contains
- * components (or tokens for components) to be shown in the panel view.
- */
- constructor( locale, integrations ) {
- super( locale );
- const { insertButtonView, cancelButtonView } = this._createActionButtons( locale );
- /**
- * The "insert/update" button view.
- *
- * @member {module:ui/button/buttonview~ButtonView}
- */
- this.insertButtonView = insertButtonView;
- /**
- * The "cancel" button view.
- *
- * @member {module:ui/button/buttonview~ButtonView}
- */
- this.cancelButtonView = cancelButtonView;
- /**
- * The dropdown view.
- *
- * @member {module:ui/dropdown/dropdownview~DropdownView}
- */
- this.dropdownView = this._createDropdownView( locale );
- /**
- * The value of the URL input.
- *
- * @member {String} #imageURLInputValue
- * @observable
- */
- this.set( 'imageURLInputValue', '' );
- /**
- * 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();
- /**
- * 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'
- }
- } );
- /**
- * A collection of the defined integrations for inserting the images.
- *
- * @private
- * @member {module:utils/collection~Collection}
- */
- this.set( '_integrations', new Collection() );
- if ( integrations ) {
- for ( const [ integration, integrationView ] of Object.entries( integrations ) ) {
- if ( integration === 'insertImageViaUrl' ) {
- integrationView.fieldView.bind( 'value' ).to( this, 'imageURLInputValue', value => value || '' );
- integrationView.fieldView.on( 'input', () => {
- this.imageURLInputValue = integrationView.fieldView.element.value;
- } );
- }
- integrationView.name = integration;
- this._integrations.add( integrationView );
- }
- }
- this.setTemplate( {
- tag: 'form',
- attributes: {
- class: [
- 'ck',
- 'ck-image-upload-form'
- ],
- tabindex: '-1'
- },
- children: [
- ...this._integrations,
- new ImageUploadFormRowView( locale, {
- children: [
- this.insertButtonView,
- this.cancelButtonView
- ],
- class: 'ck-image-upload-form__action-row'
- } )
- ]
- } );
- }
- /**
- * @inheritDoc
- */
- render() {
- super.render();
- submitHandler( {
- view: this
- } );
- const childViews = [
- ...this._integrations,
- this.insertButtonView,
- 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 );
- const stopPropagation = data => data.stopPropagation();
- // Since the form is in the dropdown panel which is a child of the toolbar, the toolbar's
- // keystroke handler would take over the key management in the URL input. We need to prevent
- // this ASAP. Otherwise, the basic caret movement using the arrow keys will be impossible.
- this.keystrokes.set( 'arrowright', stopPropagation );
- this.keystrokes.set( 'arrowleft', stopPropagation );
- this.keystrokes.set( 'arrowup', stopPropagation );
- this.keystrokes.set( 'arrowdown', stopPropagation );
- // Intercept the "selectstart" event, which is blocked by default because of the default behavior
- // of the DropdownView#panelView.
- // TODO: blocking "selectstart" in the #panelView should be configurable per–drop–down instance.
- this.listenTo( childViews[ 0 ].element, 'selectstart', ( evt, domEvt ) => {
- domEvt.stopPropagation();
- }, { priority: 'high' } );
- }
- /**
- * Returns a view of the integration.
- *
- * @param {String} name The name of the integration.
- * @returns {module:ui/view~View}
- */
- getIntegration( name ) {
- return this._integrations.find( integration => integration.name === name );
- }
- /**
- * Creates the dropdown view.
- *
- * @param {module:utils/locale~Locale} locale The localization services instance.
- *
- * @private
- * @returns {module:ui/dropdown/dropdownview~DropdownView}
- */
- _createDropdownView( locale ) {
- const t = locale.t;
- const dropdownView = createDropdown( locale, SplitButtonView );
- const splitButtonView = dropdownView.buttonView;
- const panelView = dropdownView.panelView;
- splitButtonView.set( {
- label: t( 'Insert image' ),
- icon: imageIcon,
- tooltip: true
- } );
- panelView.extendTemplate( {
- attributes: {
- class: 'ck-image-upload__panel'
- }
- } );
- return dropdownView;
- }
- /**
- * Creates the following form controls:
- *
- * * {@link #insertButtonView},
- * * {@link #cancelButtonView}.
- *
- * @param {module:utils/locale~Locale} locale The localization services instance.
- *
- * @private
- * @returns {Object.<String,module:ui/view~View>}
- */
- _createActionButtons( locale ) {
- const t = locale.t;
- const insertButtonView = new ButtonView( locale );
- const cancelButtonView = new ButtonView( locale );
- insertButtonView.set( {
- label: t( 'Insert' ),
- icon: checkIcon,
- class: 'ck-button-save',
- type: 'submit',
- withText: true,
- isEnabled: this.imageURLInputValue
- } );
- cancelButtonView.set( {
- label: t( 'Cancel' ),
- icon: cancelIcon,
- class: 'ck-button-cancel',
- withText: true
- } );
- insertButtonView.bind( 'isEnabled' ).to( this, 'imageURLInputValue' );
- insertButtonView.delegate( 'execute' ).to( this, 'submit' );
- cancelButtonView.delegate( 'execute' ).to( this, 'cancel' );
- return { insertButtonView, cancelButtonView };
- }
- /**
- * Focuses the first {@link #_focusables focusable} in the form.
- */
- focus() {
- this._focusCycler.focusFirst();
- }
- }
- /**
- * Fired when the form view is submitted (when one of the children triggered the submit event),
- * e.g. by a click on {@link #insertButtonView}.
- *
- * @event submit
- */
- /**
- * Fired when the form view is canceled, e.g. by a click on {@link #cancelButtonView}.
- *
- * @event cancel
- */
|