8
0
Просмотр исходного кода

Moved all DOM related functionality from view document to view controller.

Szymon Kupś 8 лет назад
Родитель
Сommit
f27305a212
2 измененных файлов с 185 добавлено и 181 удалено
  1. 0 180
      packages/ckeditor5-engine/src/view/document.js
  2. 185 1
      packages/ckeditor5-engine/src/view/view.js

+ 0 - 180
packages/ckeditor5-engine/src/view/document.js

@@ -10,16 +10,9 @@
 import Selection from './selection';
 import Selection from './selection';
 import { injectQuirksHandling } from './filler';
 import { injectQuirksHandling } from './filler';
 import { injectUiElementHandling } from './uielement';
 import { injectUiElementHandling } from './uielement';
-import log from '@ckeditor/ckeditor5-utils/src/log';
-import MutationObserver from './observer/mutationobserver';
-import SelectionObserver from './observer/selectionobserver';
-import FocusObserver from './observer/focusobserver';
-import KeyObserver from './observer/keyobserver';
-import FakeSelectionObserver from './observer/fakeselectionobserver';
 import Collection from '@ckeditor/ckeditor5-utils/src/collection';
 import Collection from '@ckeditor/ckeditor5-utils/src/collection';
 import mix from '@ckeditor/ckeditor5-utils/src/mix';
 import mix from '@ckeditor/ckeditor5-utils/src/mix';
 import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
 import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
-import { scrollViewportToShowTarget } from '@ckeditor/ckeditor5-utils/src/dom/scroll';
 
 
 // todo: check the docs
 // todo: check the docs
 /**
 /**
@@ -46,14 +39,6 @@ export default class Document {
 	 * Creates a Document instance.
 	 * Creates a Document instance.
 	 */
 	 */
 	constructor() {
 	constructor() {
-		/**
-		 * Roots of the DOM tree. Map on the `HTMLElement`s with roots names as keys.
-		 *
-		 * @readonly
-		 * @member {Map} module:engine/view/document~Document#domRoots
-		 */
-		this.domRoots = new Map();
-
 		/**
 		/**
 		 * Selection done on this document.
 		 * Selection done on this document.
 		 *
 		 *
@@ -97,99 +82,10 @@ export default class Document {
 		 */
 		 */
 		this.set( 'isFocused', false );
 		this.set( 'isFocused', false );
 
 
-		/**
-		 * Map of registered {@link module:engine/view/observer/observer~Observer observers}.
-		 *
-		 * @private
-		 * @member {Map.<Function, module:engine/view/observer/observer~Observer>} module:engine/view/document~Document#_observers
-		 */
-		this._observers = new Map();
-
-		// Add default observers.
-		this.addObserver( MutationObserver );
-		this.addObserver( SelectionObserver );
-		this.addObserver( FocusObserver );
-		this.addObserver( KeyObserver );
-		this.addObserver( FakeSelectionObserver );
-
 		injectQuirksHandling( this );
 		injectQuirksHandling( this );
 		injectUiElementHandling( this );
 		injectUiElementHandling( this );
 	}
 	}
 
 
-	/**
-	 * Creates observer of the given type if not yet created, {@link module:engine/view/observer/observer~Observer#enable enables} it
-	 * and {@link module:engine/view/observer/observer~Observer#observe attaches} to all existing and future
-	 * {@link module:engine/view/document~Document#domRoots DOM roots}.
-	 *
-	 * Note: Observers are recognized by their constructor (classes). A single observer will be instantiated and used only
-	 * when registered for the first time. This means that features and other components can register a single observer
-	 * multiple times without caring whether it has been already added or not.
-	 *
-	 * @param {Function} Observer The constructor of an observer to add.
-	 * Should create an instance inheriting from {@link module:engine/view/observer/observer~Observer}.
-	 * @returns {module:engine/view/observer/observer~Observer} Added observer instance.
-	 */
-	addObserver( Observer ) {
-		let observer = this._observers.get( Observer );
-
-		if ( observer ) {
-			return observer;
-		}
-
-		observer = new Observer( this );
-
-		this._observers.set( Observer, observer );
-
-		for ( const [ name, domElement ] of this.domRoots ) {
-			observer.observe( domElement, name );
-		}
-
-		observer.enable();
-
-		return observer;
-	}
-
-	/**
-	 * Returns observer of the given type or `undefined` if such observer has not been added yet.
-	 *
-	 * @param {Function} Observer The constructor of an observer to get.
-	 * @returns {module:engine/view/observer/observer~Observer|undefined} Observer instance or undefined.
-	 */
-	getObserver( Observer ) {
-		return this._observers.get( Observer );
-	}
-
-	/**
-	 * Attaches DOM root element to the view element and enable all observers on that element.
-	 * Also {@link module:engine/view/renderer~Renderer#markToSync mark element} to be synchronized with the view
-	 * what means that all child nodes will be removed and replaced with content of the view root.
-	 *
-	 * This method also will change view element name as the same as tag name of given dom root.
-	 * Name is always transformed to lower case.
-	 *
-	 * @param {Element} domRoot DOM root element.
-	 * @param {String} [name='main'] Name of the root.
-	 */
-	attachDomRoot( domRoot, name = 'main' ) {
-		const viewRoot = this.getRoot( name );
-
-		// Set view root name the same as DOM root tag name.
-		viewRoot._name = domRoot.tagName.toLowerCase();
-
-		this.domRoots.set( name, domRoot );
-		this.domConverter.bindElements( domRoot, viewRoot );
-		this.renderer.markToSync( 'children', viewRoot );
-		this.renderer.domDocuments.add( domRoot.ownerDocument );
-
-		viewRoot.on( 'change:children', ( evt, node ) => this.renderer.markToSync( 'children', node ) );
-		viewRoot.on( 'change:attributes', ( evt, node ) => this.renderer.markToSync( 'attributes', node ) );
-		viewRoot.on( 'change:text', ( evt, node ) => this.renderer.markToSync( 'text', node ) );
-
-		for ( const observer of this._observers.values() ) {
-			observer.observe( domRoot, name );
-		}
-	}
-
 	/**
 	/**
 	 * Gets a {@link module:engine/view/document~Document#roots view root element} with the specified name. If the name is not
 	 * Gets a {@link module:engine/view/document~Document#roots view root element} with the specified name. If the name is not
 	 * specific "main" root is returned.
 	 * specific "main" root is returned.
@@ -201,82 +97,6 @@ export default class Document {
 	getRoot( name = 'main' ) {
 	getRoot( name = 'main' ) {
 		return this.roots.get( name );
 		return this.roots.get( name );
 	}
 	}
-
-	/**
-	 * Gets DOM root element.
-	 *
-	 * @param {String} [name='main']  Name of the root.
-	 * @returns {Element} DOM root element instance.
-	 */
-	getDomRoot( name = 'main' ) {
-		return this.domRoots.get( name );
-	}
-
-	/**
-	 * Focuses document. It will focus {@link module:engine/view/editableelement~EditableElement EditableElement} that is currently having
-	 * selection inside.
-	 */
-	focus() {
-		if ( !this.isFocused ) {
-			const editable = this.selection.editableElement;
-
-			if ( editable ) {
-				this.domConverter.focus( editable );
-				this.render();
-			} else {
-				/**
-				 * Before focusing view document, selection should be placed inside one of the view's editables.
-				 * Normally its selection will be converted from model document (which have default selection), but
-				 * when using view document on its own, we need to manually place selection before focusing it.
-				 *
-				 * @error view-focus-no-selection
-				 */
-				log.warn( 'view-focus-no-selection: There is no selection in any editable to focus.' );
-			}
-		}
-	}
-
-	/**
-	 * Scrolls the page viewport and {@link #domRoots} with their ancestors to reveal the
-	 * caret, if not already visible to the user.
-	 */
-	scrollToTheSelection() {
-		const range = this.selection.getFirstRange();
-
-		if ( range ) {
-			scrollViewportToShowTarget( {
-				target: this.domConverter.viewRangeToDom( range ),
-				viewportOffset: 20
-			} );
-		}
-	}
-
-	/**
-	 * Disables all added observers.
-	 */
-	disableObservers() {
-		for ( const observer of this._observers.values() ) {
-			observer.disable();
-		}
-	}
-
-	/**
-	 * Enables all added observers.
-	 */
-	enableObservers() {
-		for ( const observer of this._observers.values() ) {
-			observer.enable();
-		}
-	}
-
-	/**
-	 * Destroys all observers created by view `Document`.
-	 */
-	destroy() {
-		for ( const observer of this._observers.values() ) {
-			observer.destroy();
-		}
-	}
 }
 }
 
 
 mix( Document, ObservableMixin );
 mix( Document, ObservableMixin );

+ 185 - 1
packages/ckeditor5-engine/src/view/view.js

@@ -1,11 +1,27 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * @module engine/view/document
+ */
+
 import Document from './document';
 import Document from './document';
 import Writer from './writer';
 import Writer from './writer';
 import Renderer from './renderer';
 import Renderer from './renderer';
 import DomConverter from './domconverter';
 import DomConverter from './domconverter';
 
 
+import MutationObserver from './observer/mutationobserver';
+import KeyObserver from './observer/keyobserver';
+import FakeSelectionObserver from './observer/fakeselectionobserver';
+import SelectionObserver from './observer/selectionobserver';
+import FocusObserver from './observer/focusobserver';
+
+import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
 import log from '@ckeditor/ckeditor5-utils/src/log';
 import log from '@ckeditor/ckeditor5-utils/src/log';
 import mix from '@ckeditor/ckeditor5-utils/src/mix';
 import mix from '@ckeditor/ckeditor5-utils/src/mix';
-import ObservableMixin from '../../../ckeditor5-utils/src/observablemixin';
+import { scrollViewportToShowTarget } from '@ckeditor/ckeditor5-utils/src/dom/scroll';
 
 
 export default class View {
 export default class View {
 	constructor() {
 	constructor() {
@@ -35,10 +51,174 @@ export default class View {
 		this._renderer.bind( 'isFocused' ).to( this.document );
 		this._renderer.bind( 'isFocused' ).to( this.document );
 		// this.decorate( 'render' );
 		// this.decorate( 'render' );
 
 
+		/**
+		 * Roots of the DOM tree. Map on the `HTMLElement`s with roots names as keys.
+		 *
+		 * @readonly
+		 * @member {Map} module:engine/view/view~View#domRoots
+		 */
+		this.domRoots = new Map();
+
+		/**
+		 * Map of registered {@link module:engine/view/observer/observer~Observer observers}.
+		 *
+		 * @private
+		 * @member {Map.<Function, module:engine/view/observer/observer~Observer>} module:engine/view/view~View#_observers
+		 */
+		this._observers = new Map();
+
+		// Add default observers.
+		this.addObserver( MutationObserver );
+		this.addObserver( SelectionObserver );
+		this.addObserver( FocusObserver );
+		this.addObserver( KeyObserver );
+		this.addObserver( FakeSelectionObserver );
+
 		this._ongoingChange = false;
 		this._ongoingChange = false;
 		this._renderingInProgress = false;
 		this._renderingInProgress = false;
 	}
 	}
 
 
+	/**
+	 * Attaches DOM root element to the view element and enable all observers on that element.
+	 * Also {@link module:engine/view/renderer~Renderer#markToSync mark element} to be synchronized with the view
+	 * what means that all child nodes will be removed and replaced with content of the view root.
+	 *
+	 * This method also will change view element name as the same as tag name of given dom root.
+	 * Name is always transformed to lower case.
+	 *
+	 * @param {Element} domRoot DOM root element.
+	 * @param {String} [name='main'] Name of the root.
+	 */
+	attachDomRoot( domRoot, name = 'main' ) {
+		const viewRoot = this.document.getRoot( name );
+
+		// Set view root name the same as DOM root tag name.
+		viewRoot._name = domRoot.tagName.toLowerCase();
+
+		this.domRoots.set( name, domRoot );
+		this.domConverter.bindElements( domRoot, viewRoot );
+		this._renderer.markToSync( 'children', viewRoot );
+		this._renderer.domDocuments.add( domRoot.ownerDocument );
+
+		viewRoot.on( 'change:children', ( evt, node ) => this._renderer.markToSync( 'children', node ) );
+		viewRoot.on( 'change:attributes', ( evt, node ) => this._renderer.markToSync( 'attributes', node ) );
+		viewRoot.on( 'change:text', ( evt, node ) => this._renderer.markToSync( 'text', node ) );
+
+		for ( const observer of this._observers.values() ) {
+			observer.observe( domRoot, name );
+		}
+	}
+
+	/**
+	 * Gets DOM root element.
+	 *
+	 * @param {String} [name='main']  Name of the root.
+	 * @returns {Element} DOM root element instance.
+	 */
+	getDomRoot( name = 'main' ) {
+		return this.domRoots.get( name );
+	}
+
+	/**
+	 * Creates observer of the given type if not yet created, {@link module:engine/view/observer/observer~Observer#enable enables} it
+	 * and {@link module:engine/view/observer/observer~Observer#observe attaches} to all existing and future
+	 * {@link module:engine/view/document~Document#domRoots DOM roots}.
+	 *
+	 * Note: Observers are recognized by their constructor (classes). A single observer will be instantiated and used only
+	 * when registered for the first time. This means that features and other components can register a single observer
+	 * multiple times without caring whether it has been already added or not.
+	 *
+	 * @param {Function} Observer The constructor of an observer to add.
+	 * Should create an instance inheriting from {@link module:engine/view/observer/observer~Observer}.
+	 * @returns {module:engine/view/observer/observer~Observer} Added observer instance.
+	 */
+	addObserver( Observer ) {
+		let observer = this._observers.get( Observer );
+
+		if ( observer ) {
+			return observer;
+		}
+
+		observer = new Observer( this );
+
+		this._observers.set( Observer, observer );
+
+		for ( const [ name, domElement ] of this.domRoots ) {
+			observer.observe( domElement, name );
+		}
+
+		observer.enable();
+
+		return observer;
+	}
+
+	/**
+	 * Returns observer of the given type or `undefined` if such observer has not been added yet.
+	 *
+	 * @param {Function} Observer The constructor of an observer to get.
+	 * @returns {module:engine/view/observer/observer~Observer|undefined} Observer instance or undefined.
+	 */
+	getObserver( Observer ) {
+		return this._observers.get( Observer );
+	}
+
+	/**
+	 * Disables all added observers.
+	 */
+	disableObservers() {
+		for ( const observer of this._observers.values() ) {
+			observer.disable();
+		}
+	}
+
+	/**
+	 * Enables all added observers.
+	 */
+	enableObservers() {
+		for ( const observer of this._observers.values() ) {
+			observer.enable();
+		}
+	}
+
+	/**
+	 * Scrolls the page viewport and {@link #domRoots} with their ancestors to reveal the
+	 * caret, if not already visible to the user.
+	 */
+	scrollToTheSelection() {
+		const range = this.document.selection.getFirstRange();
+
+		if ( range ) {
+			scrollViewportToShowTarget( {
+				target: this.domConverter.viewRangeToDom( range ),
+				viewportOffset: 20
+			} );
+		}
+	}
+
+	/**
+	 * Focuses document. It will focus {@link module:engine/view/editableelement~EditableElement EditableElement} that is currently having
+	 * selection inside.
+	 */
+	focus() {
+		if ( !this.document.isFocused ) {
+			const editable = this.doocument.selection.editableElement;
+
+			if ( editable ) {
+				this.domConverter.focus( editable );
+				this.render();
+			} else {
+				/**
+				 * Before focusing view document, selection should be placed inside one of the view's editables.
+				 * Normally its selection will be converted from model document (which have default selection), but
+				 * when using view document on its own, we need to manually place selection before focusing it.
+				 *
+				 * @error view-focus-no-selection
+				 */
+				log.warn( 'view-focus-no-selection: There is no selection in any editable to focus.' );
+			}
+		}
+	}
+
 	change( callback ) {
 	change( callback ) {
 		if ( this._renderingInProgress ) {
 		if ( this._renderingInProgress ) {
 			/**
 			/**
@@ -83,6 +263,10 @@ export default class View {
 	}
 	}
 
 
 	destroy() {
 	destroy() {
+		for ( const observer of this._observers.values() ) {
+			observer.destroy();
+		}
+
 		this.document.destroy();
 		this.document.destroy();
 		this.stopListening();
 		this.stopListening();
 	}
 	}