UNPKG

ckeditor5-image-upload-base64

Version:

The development environment of CKEditor 5 – the best browser-based rich text editor.

242 lines (219 loc) 6.85 kB
/** * @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 ui/labeledfield/labeledfieldview */ import View from '../view'; import uid from '@ckeditor/ckeditor5-utils/src/uid'; import LabelView from '../label/labelview'; import '../../theme/components/labeledfield/labeledfieldview.css'; /** * The labeled field view class. It can be used to enhance any view with the following features: * * * a label, * * (optional) an error message, * * (optional) an info (status) text, * * all bound logically by proper DOM attributes for UX and accessibility. It also provides an interface * (e.g. observable properties) that allows controlling those additional features. * * The constructor of this class requires a callback that returns a view to be labeled. The callback * is called with unique ids that allow binding of DOM properties: * * const labeledInputView = new LabeledFieldView( locale, ( labeledFieldView, viewUid, statusUid ) => { * const inputView = new InputTextView( labeledFieldView.locale ); * * inputView.set( { * id: viewUid, * ariaDescribedById: statusUid * } ); * * inputView.bind( 'isReadOnly' ).to( labeledFieldView, 'isEnabled', value => !value ); * inputView.bind( 'hasError' ).to( labeledFieldView, 'errorText', value => !!value ); * * return inputView; * } ); * * labeledInputView.label = 'User name'; * labeledInputView.infoText = 'Full name like for instance, John Doe.'; * labeledInputView.render(); * * document.body.append( labeledInputView.element ); * * See {@link module:ui/labeledfield/utils} to discover ready–to–use labeled input helpers for common * UI components. * * @extends module:ui/view~View */ export default class LabeledFieldView extends View { /** * Creates an instance of the labeled field view class using a provided creator function * that provides the view to be labeled. * * @param {module:utils/locale~Locale} locale The locale instance. * @param {Function} viewCreator A function that returns a {@link module:ui/view~View} * that will be labeled. The following arguments are passed to the creator function: * * * an instance of the `LabeledFieldView` to allow binding observable properties, * * an UID string that connects the {@link #labelView label} and the labeled field view in DOM, * * an UID string that connects the {@link #statusView status} and the labeled field view in DOM. */ constructor( locale, viewCreator ) { super( locale ); const viewUid = `ck-labeled-field-view-${ uid() }`; const statusUid = `ck-labeled-field-view-status-${ uid() }`; /** * The field view that gets labeled. * * @member {module:ui/view~View} #fieldView */ this.fieldView = viewCreator( this, viewUid, statusUid ); /** * The text of the label. * * @observable * @member {String} #label */ this.set( 'label' ); /** * Controls whether the component is in read-only mode. * * @observable * @member {Boolean} #isEnabled */ this.set( 'isEnabled', true ); /** * The validation error text. When set, it will be displayed * next to the {@link #fieldView} as a typical validation error message. * Set it to `null` to hide the message. * * **Note:** Setting this property to anything but `null` will automatically * make the `hasError` of the {@link #fieldView} `true`. * * @observable * @member {String|null} #errorText */ this.set( 'errorText', null ); /** * The additional information text displayed next to the {@link #fieldView} which can * be used to inform the user about its purpose, provide help or hints. * * Set it to `null` to hide the message. * * **Note:** This text will be displayed in the same place as {@link #errorText} but the * latter always takes precedence: if the {@link #errorText} is set, it replaces * {@link #infoText}. * * @observable * @member {String|null} #infoText */ this.set( 'infoText', null ); /** * (Optional) The additional CSS class set on the dropdown {@link #element}. * * @observable * @member {String} #class */ this.set( 'class' ); /** * The label view instance that describes the entire view. * * @member {module:ui/label/labelview~LabelView} #labelView */ this.labelView = this._createLabelView( viewUid ); /** * The status view for the {@link #fieldView}. It displays {@link #errorText} and * {@link #infoText}. * * @member {module:ui/view~View} #statusView */ this.statusView = this._createStatusView( statusUid ); /** * The combined status text made of {@link #errorText} and {@link #infoText}. * Note that when present, {@link #errorText} always takes precedence in the * status. * * @see #errorText * @see #infoText * @see #statusView * @private * @observable * @member {String|null} #_statusText */ this.bind( '_statusText' ).to( this, 'errorText', this, 'infoText', ( errorText, infoText ) => errorText || infoText ); const bind = this.bindTemplate; this.setTemplate( { tag: 'div', attributes: { class: [ 'ck', 'ck-labeled-field-view', bind.to( 'class' ), bind.if( 'isEnabled', 'ck-disabled', value => !value ) ] }, children: [ this.labelView, this.fieldView, this.statusView ] } ); } /** * Creates label view class instance and bind with view. * * @private * @param {String} id Unique id to set as labelView#for attribute. * @returns {module:ui/label/labelview~LabelView} */ _createLabelView( id ) { const labelView = new LabelView( this.locale ); labelView.for = id; labelView.bind( 'text' ).to( this, 'label' ); return labelView; } /** * Creates the status view instance. It displays {@link #errorText} and {@link #infoText} * next to the {@link #fieldView}. See {@link #_statusText}. * * @private * @param {String} statusUid Unique id of the status, shared with the {@link #fieldView view's} * `aria-describedby` attribute. * @returns {module:ui/view~View} */ _createStatusView( statusUid ) { const statusView = new View( this.locale ); const bind = this.bindTemplate; statusView.setTemplate( { tag: 'div', attributes: { class: [ 'ck', 'ck-labeled-field-view__status', bind.if( 'errorText', 'ck-labeled-field-view__status_error' ), bind.if( '_statusText', 'ck-hidden', value => !value ) ], id: statusUid, role: bind.if( 'errorText', 'alert' ) }, children: [ { text: bind.to( '_statusText' ) } ] } ); return statusView; } /** * Focuses the {@link #fieldView}. */ focus() { this.fieldView.focus(); } }