浏览代码

Changed: ViewSelection instance is passed with viewMutations in mutations events, if possible.

Szymon Cofalik 9 年之前
父节点
当前提交
a1b1c3b595

+ 24 - 1
packages/ckeditor5-engine/src/view/observer/mutationobserver.js

@@ -6,6 +6,7 @@
 /* globals window */
 
 import Observer from './observer.js';
+import ViewSelection from '../selection.js';
 import { startsWithFiller, getDataWithoutFiller } from '../filler.js';
 
 /**
@@ -191,8 +192,30 @@ export default class MutationObserver extends Observer {
 			} );
 		}
 
-		this.document.fire( 'mutations', viewMutations );
+		// Retrieve `domSelection` using `ownerDocument` of one of mutated nodes.
+		// There should not be simultaneous mutation in multiple documents, so it's fine.
+		const domSelection = domMutations[ 0 ].target.ownerDocument.getSelection();
 
+		let viewSelection = null;
+
+		if ( domSelection && domSelection.anchorNode ) {
+			// If `domSelection` is inside a dom node that is already bound to a view node from view tree, get
+			// corresponding selection in the view and pass it together with `viewMutations`. The `viewSelection` may
+			// be used by features handling mutations.
+			// Only one range is supported.
+
+			const viewSelectionAnchor = domConverter.domPositionToView( domSelection.anchorNode, domSelection.anchorOffset );
+			const viewSelectionFocus = domConverter.domPositionToView( domSelection.focusNode, domSelection.focusOffset );
+
+			// Anchor and focus has to be properly mapped to view.
+			if ( viewSelectionAnchor && viewSelectionFocus ) {
+				viewSelection = new ViewSelection();
+				viewSelection.collapse( viewSelectionAnchor );
+				viewSelection.setFocus( viewSelectionFocus );
+			}
+		}
+
+		this.document.fire( 'mutations', viewMutations, viewSelection );
 		this.document.render();
 	}
 }

+ 19 - 0
packages/ckeditor5-engine/tests/view/observer/mutationobserver.js

@@ -113,6 +113,25 @@ describe( 'MutationObserver', () => {
 		expect( lastMutations[ 0 ].node ).to.equal( viewRoot );
 	} );
 
+	it( 'should fire mutations event with view selection instance, if dom selection can be mapped to view', ( done ) => {
+		const textNode = domEditor.childNodes[ 0 ].childNodes[ 0 ];
+		textNode.data = 'foom';
+
+		const domSelection = document.getSelection();
+		domSelection.collapse( textNode, 4 );
+
+		viewDocument.on( 'mutations', ( evt, viewMutations, viewSelection ) => {
+			expect( viewSelection.anchor.parent ).to.equal( viewRoot.getChild( 0 ).getChild( 0 ) );
+			expect( viewSelection.anchor.offset ).to.equal( 4 );
+
+			done();
+		} );
+
+		mutationObserver.flush();
+
+		expectDomEditorNotToChange();
+	} );
+
 	it( 'should be able to observe multiple roots', () => {
 		const domAdditionalEditor = document.getElementById( 'additional' );