Sfoglia il codice sorgente

Added fake selection container binding to view selection instance.

Szymon Kupś 9 anni fa
parent
commit
7dffb03934

+ 41 - 1
packages/ckeditor5-engine/src/view/domconverter.js

@@ -87,6 +87,36 @@ export default class DomConverter {
 		 * @member {WeakMap} engine.view.DomConverter#_viewToDomMapping
 		 */
 		this._viewToDomMapping = new WeakMap();
+
+		/**
+		 * Holds mapping between fake selection containers and corresponding view selections.
+		 *
+		 * @private
+		 * @type {WeakMap} engine.view.DomConverter#_fakeSelectionMapping
+		 */
+		this._fakeSelectionMapping = new WeakMap();
+	}
+
+	/**
+	 * Binds given DOM element that represents fake selection to {engine.view.Selection view selection}.
+	 * View selection copy is stored and can be retrieved by {engine.view.DomConverter#fakeSelectionToView} method.
+	 *
+	 * @param {HTMLElement} domElement
+	 * @param {engine.view.Selection} viewSelection
+	 */
+	bindFakeSelection( domElement, viewSelection ) {
+		this._fakeSelectionMapping.set( domElement, ViewSelection.createFromSelection( viewSelection ) );
+	}
+
+	/**
+	 * Returns {engine.view.Selection view selection} instance corresponding to given DOM element that represents fake
+	 * selection. Returns `undefined` if binding to given DOM element does not exists.
+	 *
+	 * @param {HTMLElement} domElement
+	 * @returns {engine.view.Selection|undefined}
+	 */
+	fakeSelectionToView( domElement ) {
+		return this._fakeSelectionMapping.get( domElement );
 	}
 
 	/**
@@ -358,8 +388,18 @@ export default class DomConverter {
 	 * @returns {engine.view.Selection} View selection.
 	 */
 	domSelectionToView( domSelection ) {
-		const viewSelection = new ViewSelection();
+		// DOM selection might be placed in fake selection container.
+		// If container contains fake selection - return corresponding view selection.
+		if ( domSelection.rangeCount === 1 ) {
+			const container = domSelection.getRangeAt( 0 ).startContainer;
+			const viewSelection = this.fakeSelectionToView( container );
+
+			if ( viewSelection ) {
+				return viewSelection;
+			}
+		}
 
+		const viewSelection = new ViewSelection();
 		const isBackward = this.isDomSelectionBackward( domSelection );
 
 		for ( let i = 0; i < domSelection.rangeCount; i++ ) {

+ 32 - 0
packages/ckeditor5-engine/tests/view/domconverter/binding.js

@@ -7,6 +7,8 @@
 /* bender-tags: view, domconverter, browser-only */
 
 import ViewElement from '/ckeditor5/engine/view/element.js';
+import ViewSelection from '/ckeditor5/engine/view/selection.js';
+import ViewRange from '/ckeditor5/engine/view/range.js';
 import DomConverter from '/ckeditor5/engine/view/domconverter.js';
 import ViewDocumentFragment from '/ckeditor5/engine/view/documentfragment.js';
 import { INLINE_FILLER } from '/ckeditor5/engine/view/filler.js';
@@ -334,4 +336,34 @@ describe( 'DomConverter', () => {
 			expect( converter.getCorrespondingDomText( viewText ) ).to.be.null;
 		} );
 	} );
+
+	describe( 'bindFakeSelection', () => {
+		let domEl, selection, viewElement;
+
+		beforeEach( () => {
+			viewElement = new ViewElement();
+			domEl = document.createElement( 'div' );
+			selection = new ViewSelection();
+			selection.addRange( ViewRange.createIn( viewElement ) );
+			converter.bindFakeSelection( domEl, selection );
+		} );
+
+		it( 'should bind DOM element to selection', () => {
+			const bindSelection = converter.fakeSelectionToView( domEl );
+			expect( bindSelection ).to.be.defined;
+			expect( bindSelection.isEqual( selection ) ).to.be.true;
+		} );
+
+		it( 'should keep a copy of selection', () => {
+			const selectionCopy = ViewSelection.createFromSelection( selection );
+
+			selection.addRange( ViewRange.createIn( new ViewElement() ), true );
+			const bindSelection = converter.fakeSelectionToView( domEl );
+
+			expect( bindSelection ).to.be.defined;
+			expect( bindSelection ).to.not.equal( selection );
+			expect( bindSelection.isEqual( selection ) ).to.be.false;
+			expect( bindSelection.isEqual( selectionCopy ) ).to.be.true;
+		} );
+	} );
 } );

+ 22 - 0
packages/ckeditor5-engine/tests/view/domconverter/dom-to-view.js

@@ -7,6 +7,8 @@
 /* bender-tags: view, domconverter, browser-only */
 
 import ViewElement from '/ckeditor5/engine/view/element.js';
+import ViewRange from '/ckeditor5/engine/view/range.js';
+import ViewSelection from '/ckeditor5/engine/view/selection.js';
 import DomConverter from '/ckeditor5/engine/view/domconverter.js';
 import ViewDocumentFragment from '/ckeditor5/engine/view/documentfragment.js';
 import { INLINE_FILLER, INLINE_FILLER_LENGTH, NBSP_FILLER } from '/ckeditor5/engine/view/filler.js';
@@ -653,5 +655,25 @@ describe( 'DomConverter', () => {
 
 			expect( viewSelection.rangeCount ).to.equal( 0 );
 		} );
+
+		it( 'should return fake selection', () => {
+			const domContainer = document.createElement( 'div' );
+			const domSelection = document.getSelection();
+			domContainer.innerHTML = 'fake selection container';
+			document.body.appendChild( domContainer );
+
+			const viewSelection = new ViewSelection();
+			viewSelection.addRange( ViewRange.createIn( new ViewElement() ) );
+			converter.bindFakeSelection( domContainer, viewSelection );
+
+			const domRange = new Range();
+			domRange.selectNodeContents( domContainer );
+			domSelection.removeAllRanges();
+			domSelection.addRange( domRange );
+
+			const bindViewSelection = converter.domSelectionToView( domSelection );
+
+			expect( bindViewSelection.isEqual( viewSelection ) ).to.be.true;
+		} );
 	} );
 } );