Przeglądaj źródła

Implemented skeleton of the creator.

Aleksander Nowodzinski 9 lat temu
rodzic
commit
1eb855cca6

+ 87 - 0
packages/ckeditor5-editor-inline/src/inline.js

@@ -0,0 +1,87 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * @module editor-inline/inline
+ */
+
+import StandardEditor from '@ckeditor/ckeditor5-core/src/editor/standardeditor';
+import HtmlDataProcessor from '@ckeditor/ckeditor5-engine/src/dataprocessor/htmldataprocessor';
+import InlineEditorUI from './inlineeditorui';
+import InlineEditorUIView from './inlineeditoruiview';
+
+import '../theme/theme.scss';
+
+/**
+ * Inline editor. Uses an inline editable and a floating toolbar.
+ *
+ * @extends module:core/editor/standardeditor~StandardEditor
+ */
+export default class InlineEditor extends StandardEditor {
+	/**
+	 * Creates an instance of the inline editor.
+	 *
+	 * @param {HTMLElement} element The DOM element that will be the source for the created editor.
+	 * @param {Object} config The editor configuration.
+	 */
+	constructor( element, config ) {
+		super( element, config );
+
+		this.document.createRoot();
+		this.data.processor = new HtmlDataProcessor();
+		this.ui = new InlineEditorUI( this, new InlineEditorUIView( this.locale, element ) );
+	}
+
+	/**
+	 * Destroys the editor instance, releasing all resources used by it.
+	 *
+	 * Updates the original editor element with the data.
+	 *
+	 * @returns {Promise}
+	 */
+	destroy() {
+		this.updateEditorElement();
+
+		return this.ui.destroy()
+			.then( () => super.destroy() );
+	}
+
+	/**
+	 * Creates an inline editor instance.
+	 *
+	 *		InlineEditor.create( document.querySelector( '#editor' ), {
+	 *			plugins: [ Delete, Enter, Typing, Paragraph, Undo, Bold, Italic ],
+	 *			toolbar: [ 'bold', 'italic', 'undo', 'redo' ]
+	 *		} )
+	 *		.then( editor => {
+	 *			console.log( 'Editor was initialized', editor );
+	 *		} )
+	 *		.catch( err => {
+	 *			console.error( err.stack );
+	 *		} );
+	 *
+	 * @param {HTMLElement} element See {@link module:editor-inline/inline~InlineEditor#constructor}'s parameters.
+	 * @param {Object} config See {@link module:editor-inline/inline~InlineEditor#constructor}'s parameters.
+	 * @returns {Promise} A promise resolved once the editor is ready.
+	 * @returns {module:core/editor/standardeditor~StandardEditor} return.editor The editor instance.
+	 */
+	static create( element, config ) {
+		return new Promise( ( resolve ) => {
+			const editor = new InlineEditor( element, config );
+
+			resolve(
+				editor.initPlugins()
+					.then( () => editor.ui.init() )
+					.then( () => editor.fire( 'uiReady' ) )
+					.then( () => editor.loadDataFromEditorElement() )
+					.then( () => {
+						editor.fire( 'dataReady' );
+						editor.fire( 'ready' );
+					} )
+					.then( () => editor )
+			);
+		} );
+	}
+}

+ 124 - 0
packages/ckeditor5-editor-inline/src/inlineeditorui.js

@@ -0,0 +1,124 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * @module editor-inline/inlineeditorui
+ */
+
+import ComponentFactory from '@ckeditor/ckeditor5-ui/src/componentfactory';
+import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
+
+/**
+ * The inline editor UI class.
+ */
+export default class InlineEditorUI {
+	/**
+	 * Creates an instance of the editor UI class.
+	 *
+	 * @param {module:core/editor/editor~Editor} editor The editor instance.
+	 * @param {module:ui/editorui/editoruiview~EditorUIView} view View of the ui.
+	 */
+	constructor( editor, view ) {
+		/**
+		 * Editor that the UI belongs to.
+		 *
+		 * @readonly
+		 * @member {module:core/editor/editor~Editor}
+		 */
+		this.editor = editor;
+
+		/**
+		 * View of the ui.
+		 *
+		 * @readonly
+		 * @member {module:ui/editorui/editoruiview~EditorUIView}
+		 */
+		this.view = view;
+
+		/**
+		 * Instance of the {@link module:ui/componentfactory~ComponentFactory}.
+		 *
+		 * @readonly
+		 * @member {module:ui/componentfactory~ComponentFactory}
+		 */
+		this.componentFactory = new ComponentFactory( editor );
+
+		/**
+		 * Keeps information about editor focus.
+		 *
+		 * @readonly
+		 * @member {module:utils/focustracker~FocusTracker}
+		 */
+		this.focusTracker = new FocusTracker();
+
+		// Set–up the toolbar.
+		view.toolbar.bind( 'isActive' ).to( this.focusTracker, 'isFocused' );
+		view.toolbar.targetElement = view.editableElement;
+
+		// Setup the editable.
+		const editingRoot = editor.editing.createRoot( view.editableElement );
+		view.editable.bind( 'isReadOnly' ).to( editingRoot );
+		view.editable.bind( 'isFocused' ).to( editor.editing.view );
+		view.editable.name = editingRoot.rootName;
+
+		this.focusTracker.add( view.editableElement );
+	}
+
+	/**
+	 * Initializes the UI.
+	 *
+	 * @returns {Promise} A Promise resolved when the initialization process is finished.
+	 */
+	init() {
+		// TODO: All of this should be common with editor-classic.
+		const editor = this.editor;
+
+		return this.view.init()
+			.then( () => {
+				const toolbarConfig = editor.config.get( 'toolbar' );
+				const promises = [];
+
+				if ( toolbarConfig ) {
+					for ( let name of toolbarConfig ) {
+						promises.push( this.view.toolbar.items.add( this.componentFactory.create( name ) ) );
+					}
+				}
+
+				return Promise.all( promises );
+			} )
+			.then( () => {
+				const toolbarFocusTracker = this.view.toolbar.focusTracker;
+
+				// Because toolbar items can get focus, the overall state of
+				// the toolbar must also be tracked.
+				this.focusTracker.add( this.view.toolbar.element );
+
+				// Focus the toolbar on the keystroke, if not already focused.
+				editor.keystrokes.set( 'Alt+F10', ( data, cancel ) => {
+					if ( this.focusTracker.isFocused && !toolbarFocusTracker.isFocused ) {
+						this.view.toolbar.focus();
+						cancel();
+					}
+				} );
+
+				// Blur the toolbar and bring the focus back to editable on the keystroke.
+				this.view.toolbar.keystrokes.set( 'Esc', ( data, cancel ) => {
+					if ( toolbarFocusTracker.isFocused ) {
+						editor.editing.view.focus();
+						cancel();
+					}
+				} );
+			} );
+	}
+
+	/**
+	 * Destroys the UI.
+	 *
+	 * @returns {Promise} A Promise resolved when the destruction process is finished.
+	 */
+	destroy() {
+		return this.view.destroy();
+	}
+}

+ 55 - 0
packages/ckeditor5-editor-inline/src/inlineeditoruiview.js

@@ -0,0 +1,55 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * @module editor-inline/inlineeditoruiview
+ */
+
+import EditorUIView from '@ckeditor/ckeditor5-ui/src/editorui/editoruiview';
+import InlineEditableUIView from '@ckeditor/ckeditor5-ui/src/editableui/inline/inlineeditableuiview';
+import FloatingToolbarView from '@ckeditor/ckeditor5-ui/src/toolbar/floating/floatingtoolbarview';
+
+/**
+ * Inline editor UI view. Uses inline editable and floating toolbar, all
+ * enclosed in a boxed UI view.
+ *
+ * @extends module:ui/editorui/editoruiview~EditorUIView
+ */
+export default class InlineEditorUIView extends EditorUIView {
+	/**
+	 * Creates an instance of the inline editor UI view.
+	 *
+	 * @param {module:utils/locale~Locale} locale The {@link module:core/editor/editor~Editor#locale} instance.
+	 */
+	constructor( locale, editableElement ) {
+		super( locale );
+
+		/**
+		 * A floating toolbar view instance.
+		 *
+		 * @readonly
+		 * @member {module:ui/toolbar/floating/floatingtoolbarview~FloatingToolbarView}
+		 */
+		this.toolbar = new FloatingToolbarView( locale );
+
+		/**
+		 * Editable UI view.
+		 *
+		 * @readonly
+		 * @member {module:ui/editableui/inline/inlineeditableuiview~InlineEditableUIView}
+		 */
+		this.editable = new InlineEditableUIView( locale, editableElement );
+
+		this.body.add( this.toolbar );
+		this.addChildren( this.editable );
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	get editableElement() {
+		return this.editable.element;
+	}
+}

+ 23 - 0
packages/ckeditor5-editor-inline/tests/manual/inline.html

@@ -0,0 +1,23 @@
+<p>
+	<button id="destroyEditor">Destroy editor</button>
+	<button id="initEditor">Init editor</button>
+</p>
+
+<div id="editor" class="custom-class" custom-attr="foo" contenteditable="true">
+	<h2>Hello world!</h2>
+	<p>This is an editor instance.</p>
+</div>
+
+<style>
+	body {
+		width: 10000px;
+		height: 10000px;
+	}
+
+	#editor {
+		margin-top: 200px;
+		margin-left: 100px;
+		margin-bottom: 200px;
+		width: 300px;
+	}
+</style>

+ 56 - 0
packages/ckeditor5-editor-inline/tests/manual/inline.js

@@ -0,0 +1,56 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals console:false, document, window */
+
+import InlineEditor from '../../src/inline';
+import Enter from '@ckeditor/ckeditor5-enter/src/enter';
+import Typing from '@ckeditor/ckeditor5-typing/src/typing';
+import Heading from '@ckeditor/ckeditor5-heading/src/heading';
+import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
+import Undo from '@ckeditor/ckeditor5-undo/src/undo';
+import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
+import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
+import testUtils from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
+
+let editor, editable, observer;
+
+function initEditor() {
+	InlineEditor.create( document.querySelector( '#editor' ), {
+		plugins: [ Enter, Typing, Paragraph, Undo, Heading, Bold, Italic ],
+		toolbar: [ 'headings', 'bold', 'italic', 'undo', 'redo' ]
+	} )
+	.then( newEditor => {
+		console.log( 'Editor was initialized', newEditor );
+		console.log( 'You can now play with it using global `editor` and `editable` variables.' );
+
+		window.editor = editor = newEditor;
+		window.editable = editable = editor.editing.view.getRoot();
+
+		observer = testUtils.createObserver();
+		observer.observe( 'Editable', editable, [ 'isFocused' ] );
+	} )
+	.catch( err => {
+		console.error( err.stack );
+	} );
+}
+
+function destroyEditor() {
+	editor.destroy()
+		.then( () => {
+			window.editor = editor = null;
+			window.editable = editable = null;
+
+			observer.stopListening();
+			observer = null;
+
+			console.log( 'Editor was destroyed' );
+		} );
+}
+
+document.getElementById( 'initEditor' ).addEventListener( 'click', initEditor );
+document.getElementById( 'destroyEditor' ).addEventListener( 'click', destroyEditor );
+
+initEditor();

+ 9 - 0
packages/ckeditor5-editor-inline/tests/manual/inline.md

@@ -0,0 +1,9 @@
+1. Click "Init editor".
+2. TODO
+
+## Notes:
+
+* You can play with:
+  * `editable.isReadOnly`,
+* Changes to `editable.isFocused` should be logged to the console.
+* Features should work.

+ 21 - 0
packages/ckeditor5-editor-inline/theme/theme.scss

@@ -0,0 +1,21 @@
+// Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+// For licensing, see LICENSE.md or http://ckeditor.com/license
+
+@import '~@ckeditor/ckeditor5-theme-lark/theme/theme.scss';
+
+// TODO move to make a common style with editor-classic.
+.ck-editor__editable {
+	&.ck-focused {
+		@include ck-focus-ring( 'outline' );
+		@include ck-box-shadow( $ck-inner-shadow );
+	}
+
+	&_inline {
+		overflow: auto;
+		padding: 0 ck-spacing();
+	}
+}
+
+.ck-body .ck-toolbar {
+	@include ck-editor-toolbar();
+}