Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge pull request #458 from ckeditor/t/ckeditor5/1449
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The `EditableUIView#externalElement` property has been removed.
BREAKING CHANGE: The `EditableUIView#editableElement` property has been made a private property and should not be accessed directly from outside of this class or its subclasses. Use `EditorUI#getEditableElement()` method instead to access editor editable element.
  • Loading branch information
Piotr Jasiun committed Jan 22, 2019
2 parents fd18fb9 + 4f409e8 commit b8cc937
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 98 deletions.
74 changes: 36 additions & 38 deletions docs/_snippets/examples/bootstrap-ui-inner.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@

// Basic classes to create an editor.
import Editor from '@ckeditor/ckeditor5-core/src/editor/editor';
import EditorUI from '@ckeditor/ckeditor5-core/src/editor/editorui';
import EditorUIView from '@ckeditor/ckeditor5-ui/src/editorui/editoruiview';
import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
import ComponentFactory from '@ckeditor/ckeditor5-ui/src/componentfactory';
import InlineEditableUIView from '@ckeditor/ckeditor5-ui/src/editableui/inline/inlineeditableuiview';
import HtmlDataProcessor from '@ckeditor/ckeditor5-engine/src/dataprocessor/htmldataprocessor';
import ElementReplacer from '@ckeditor/ckeditor5-utils/src/elementreplacer';
Expand Down Expand Up @@ -64,22 +63,12 @@ export default class BootstrapEditor extends Editor {
// When editor#element is a textarea inside a form element
// then content of this textarea will be updated on form submit.
attachToForm( this );

// A helper to easily replace the editor#element with editor.editable#element.
this._elementReplacer = new ElementReplacer();
}

get element() {
return this.ui.view.element;
}

destroy() {
// When destroyed, editor sets the output of editor#getData() into editor#element...
this.updateSourceElement();

// ...and restores the original editor#element...
this._elementReplacer.restore();

// ...and destroys the UI.
this.ui.destroy();

Expand All @@ -89,22 +78,13 @@ export default class BootstrapEditor extends Editor {
static create( element, config ) {
return new Promise( resolve => {
const editor = new this( element, config );
const editable = editor.ui.view.editable;

resolve(
editor.initPlugins()
.then( () => {
// Initialize the UI first. See the BootstrapEditorUI class to learn more.
editor.ui.init();

// Replace the editor#element with editor.editable#element.
editor._elementReplacer.replace( element, editable.element );

// Tell the world that the UI of the editor is ready to use.
editor.fire( 'uiReady' );
} )
// Initialize the UI first. See the BootstrapEditorUI class to learn more.
.then( () => editor.ui.init( element ) )
// Bind the editor editing layer to the editable in DOM.
.then( () => editor.editing.view.attachDomRoot( editable.element ) )
.then( () => editor.editing.view.attachDomRoot( editor.ui.getEditableElement() ) )
// Fill the editable with the initial data.
.then( () => editor.data.init( getDataFromElement( element ) ) )
// Fire the events that announce that the editor is complete and ready to use.
Expand All @@ -123,17 +103,20 @@ mix( BootstrapEditor, DataApiMixin );
mix( BootstrapEditor, ElementApiMixin );

// The class organizing the UI of the editor, binding it with existing Bootstrap elements in DOM.
class BootstrapEditorUI {
class BootstrapEditorUI extends EditorUI {
constructor( editor ) {
this.editor = editor;
super( editor );

// A helper to easily replace the editor#element with editor.editable#element.
this._elementReplacer = new ElementReplacer();

// The global UI view of the editor. It aggregates various Bootstrap DOM elements.
const view = this.view = new EditorUIView( editor.locale );
const view = this._view = new EditorUIView( editor.locale );

// This is the main editor element in DOM.
// This is the main editor element in the DOM.
view.element = $( '.ck-editor' );

// This is the editable view in DOM. It will replace the data container in DOM.
// This is the editable view in the DOM. It will replace the data container in the DOM.
view.editable = new InlineEditableUIView( editor.locale );

// References to the dropdown elements for further usage. See #_setupBootstrapHeadingDropdown.
Expand All @@ -144,39 +127,54 @@ class BootstrapEditorUI {
view.toolbarButtons = {};

[ 'bold', 'italic', 'underline', 'undo', 'redo' ].forEach( name => {
// Retrieve the jQuery object corresponding with the button in DOM.
// Retrieve the jQuery object corresponding with the button in the DOM.
view.toolbarButtons[ name ] = view.element.find( `#${ name }` );
} );
}

// Mandatory EditorUI interface components.
this.componentFactory = new ComponentFactory( editor );
this.focusTracker = new FocusTracker();
get view() {
return this._view;
}

init() {
init( replacementElement ) {
const editor = this.editor;
const view = this.view;

// Render the editable component in DOM first.
// Render the editable component in the DOM first.
view.editable.render();

// Create an editing root in the editing layer. It will correspond with the
// document root created in the constructor().
const editingRoot = editor.editing.view.document.getRoot();

// Bind the basic attributes of the editable in DOM with the editing layer.
// Bind the basic attributes of the editable in the DOM with the editing layer.
view.editable.bind( 'isReadOnly' ).to( editingRoot );
view.editable.bind( 'isFocused' ).to( editor.editing.view.document );
view.editable.name = editingRoot.rootName;

// Register editable element so it is available via getEditableElement() method.
this._editableElements.set( view.editable.name, view.editable.element );

// Setup the existing, external Bootstrap UI so it works with the rest of the editor.
this._setupBootstrapToolbarButtons();
this._setupBootstrapHeadingDropdown();

// Replace the editor#element with editor.editable#element.
this._elementReplacer.replace( replacementElement, view.editable.element );

// Tell the world that the UI of the editor is ready to use.
this.fire( 'ready' );
}

destroy() {
this.view.editable.destroy();
this.view.destroy();
// Restore the original editor#element.
this._elementReplacer.restore();

// Destroy the view.
this._view.editable.destroy();
this._view.destroy();

super.destroy();
}

// This method activates Bold, Italic, Underline, Undo and Redo buttons in the toolbar.
Expand Down
65 changes: 33 additions & 32 deletions docs/framework/guides/external-ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The ready–to–use builds of CKEditor like {@link examples/builds/classic-edit
```js
// Basic classes to create an editor.
import Editor from '@ckeditor/ckeditor5-core/src/editor/editor';
import EditorUI from '@ckeditor/ckeditor5-core/src/editor/editorui';
import EditorUIView from '@ckeditor/ckeditor5-ui/src/editorui/editoruiview';
import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
import ComponentFactory from '@ckeditor/ckeditor5-ui/src/componentfactory';
Expand Down Expand Up @@ -81,22 +82,12 @@ export default class BootstrapEditor extends Editor {
// When editor#element is a textarea inside a form element,
// the content of this textarea will be updated on form submit.
attachToForm( this );

// A helper to easily replace the editor#element with editor.editable#element.
this._elementReplacer = new ElementReplacer();
}

get element() {
return this.ui.view.element;
}

destroy() {
// When destroyed, the editor sets the output of editor#getData() into editor#element...
this.updateSourceElement();

// ...and restores the original editor#element...
this._elementReplacer.restore();

// ...and destroys the UI.
this.ui.destroy();

Expand All @@ -106,23 +97,14 @@ export default class BootstrapEditor extends Editor {
static create( element, config ) {
return new Promise( resolve => {
const editor = new this( element, config );
const editable = editor.ui.view.editable;

resolve(
editor.initPlugins()
.then( () => {
// Initialize the UI first. See the BootstrapEditorUI class to learn more.
editor.ui.init();

// Replace the editor#element with editor.editable#element.
editor._elementReplacer.replace( element, editable.element );

// Tell the world that the UI of the editor is ready to use.
editor.fire( 'uiReady' );
} )
// Bind the editor editing layer to the editable in the DOM.
.then( () => editor.editing.view.attachDomRoot( editable.element ) )
// Fill the editable with the intial data.
// Initialize the UI first. See the BootstrapEditorUI class to learn more.
.then( () => editor.ui.init( element ) )
// Bind the editor editing layer to the editable in DOM.
.then( () => editor.editing.view.attachDomRoot( editor.ui.getEditableElement() ) )
// Fill the editable with the initial data.
.then( () => editor.data.init( getDataFromElement( element ) ) )
// Fire the events that announce that the editor is complete and ready to use.
.then( () => {
Expand Down Expand Up @@ -256,12 +238,15 @@ Define the `BootstrapEditorUI` and then have a closer look at the content of the

```js
// The class organizing the UI of the editor, binding it with existing Bootstrap elements in the DOM.
class BootstrapEditorUI {
class BootstrapEditorUI extends EditorUI {
constructor( editor ) {
this.editor = editor;
super( editor );

// A helper to easily replace the editor#element with editor.editable#element.
this._elementReplacer = new ElementReplacer();

// The global UI view of the editor. It aggregates various Bootstrap DOM elements.
const view = this.view = new EditorUIView( editor.locale );
const view = this._view = new EditorUIView( editor.locale );

// This is the main editor element in the DOM.
view.element = $( '.ck-editor' );
Expand All @@ -280,13 +265,13 @@ class BootstrapEditorUI {
// Retrieve the jQuery object corresponding with the button in the DOM.
view.toolbarButtons[ name ] = view.element.find( `#${ name }` );
} );
}

// Mandatory EditorUI interface components.
this.componentFactory = new ComponentFactory( editor );
this.focusTracker = new FocusTracker();
get view() {
return this._view;
}

init() {
init( replacementElement ) {
const editor = this.editor;
const view = this.view;

Expand All @@ -302,13 +287,29 @@ class BootstrapEditorUI {
view.editable.bind( 'isFocused' ).to( editor.editing.view.document );
view.editable.name = editingRoot.rootName;

// Register editable element so it is available via getEditableElement() method.
this._editableElements.set( view.editable.name, view.editable.element );

// Setup the existing, external Bootstrap UI so it works with the rest of the editor.
this._setupBootstrapToolbarButtons();
this._setupBootstrapHeadingDropdown();

// Replace the editor#element with editor.editable#element.
this._elementReplacer.replace( replacementElement, view.editable.element );

// Tell the world that the UI of the editor is ready to use.
this.fire( 'ready' );
}

destroy() {
this.view.editable.destroy();
// Restore the original editor#element.
this._elementReplacer.restore();

// Destroy the view.
this._view.editable.destroy();
this._view.destroy();

super.destroy();
}

// This method activates Bold, Italic, Underline, Undo and Redo buttons in the toolbar.
Expand Down
32 changes: 15 additions & 17 deletions src/editableui/editableuiview.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ export default class EditableUIView extends View {

const bind = this.bindTemplate;

if ( editableElement ) {
this.element = this.editableElement = editableElement;
}

this.setTemplate( {
tag: 'div',
attributes: {
Expand Down Expand Up @@ -64,41 +60,43 @@ export default class EditableUIView extends View {
this.set( 'isFocused', false );

/**
* An external {@link #editableElement} passed into the constructor, which also means
* the view will not render its {@link #template}.
* The element which is the main editable element (usually the one with `contentEditable="true"`).
*
* @member {HTMLElement} #externalElement
* @private
* @member {HTMLElement} #_editableElement
*/
this.externalElement = editableElement;
this._editableElement = editableElement;

/**
* The element which is the main editable element (usually the one with `contentEditable="true"`).
* Whether an external {@link #_editableElement} was passed into the constructor, which also means
* the view will not render its {@link #template}.
*
* @readonly
* @member {HTMLElement} #editableElement
* @private
* @member {Boolean} #_hasExternalElement
*/
this._hasExternalElement = !!this._editableElement;
}

/**
* Renders the view by either applying the {@link #template} to the existing
* {@link #editableElement} or assigning {@link #element} as {@link #editableElement}.
* {@link #_editableElement} or assigning {@link #element} as {@link #_editableElement}.
*/
render() {
super.render();

if ( this.externalElement ) {
this.template.apply( this.element = this.externalElement );
if ( this._hasExternalElement ) {
this.template.apply( this.element = this._editableElement );
} else {
this.editableElement = this.element;
this._editableElement = this.element;
}
}

/**
* @inheritDoc
*/
destroy() {
if ( this.externalElement ) {
this.template.revert( this.externalElement );
if ( this._hasExternalElement ) {
this.template.revert( this._editableElement );
}

super.destroy();
Expand Down
6 changes: 3 additions & 3 deletions src/toolbar/balloon/balloontoolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export default class BalloonToolbar extends Plugin {
this.toolbarView = this._createToolbarView();

/**
* Tracks the focus of the {@link module:ui/editableui/editableuiview~EditableUIView#editableElement}
* Tracks the focus of the {@link module:core/editor/editorui~EditorUI#getEditableElement editable element}
* and the {@link #toolbarView}. When both are blurred then the toolbar should hide.
*
* @readonly
Expand All @@ -61,8 +61,8 @@ export default class BalloonToolbar extends Plugin {
this.focusTracker = new FocusTracker();

// Wait for the EditorUI#init. EditableElement is not available before.
editor.once( 'uiReady', () => {
this.focusTracker.add( editor.ui.view.editableElement );
editor.ui.once( 'ready', () => {
this.focusTracker.add( editor.ui.getEditableElement() );
this.focusTracker.add( this.toolbarView.element );
} );

Expand Down
4 changes: 2 additions & 2 deletions src/toolbar/block/blocktoolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ export default class BlockToolbar extends Plugin {

this.panelView.pin( {
target: this.buttonView.element,
limiter: this.editor.ui.view.editableElement
limiter: this.editor.ui.getEditableElement()
} );

if ( !wasVisible ) {
Expand Down Expand Up @@ -349,7 +349,7 @@ export default class BlockToolbar extends Plugin {
_attachButtonToElement( targetElement ) {
const contentStyles = window.getComputedStyle( targetElement );

const editableRect = new Rect( this.editor.ui.view.editableElement );
const editableRect = new Rect( this.editor.ui.getEditableElement() );
const contentPaddingTop = parseInt( contentStyles.paddingTop, 10 );
// When line height is not an integer then thread it as "normal".
// MDN says that 'normal' == ~1.2 on desktop browsers.
Expand Down
Loading

0 comments on commit b8cc937

Please sign in to comment.