Parcourir la source

Various stability and cross browser fixes.

Piotrek Koszuliński il y a 9 ans
Parent
commit
853a374cde

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

@@ -391,7 +391,13 @@ export default class DomConverter {
 		// DOM selection might be placed in fake selection container.
 		// DOM selection might be placed in fake selection container.
 		// If container contains fake selection - return corresponding view selection.
 		// If container contains fake selection - return corresponding view selection.
 		if ( domSelection.rangeCount === 1 ) {
 		if ( domSelection.rangeCount === 1 ) {
-			const container = domSelection.getRangeAt( 0 ).startContainer;
+			let container = domSelection.getRangeAt( 0 ).startContainer;
+
+			// The DOM selection might be moved to the text node inside the fake selection container.
+			if ( this.isText( container ) ) {
+				container = container.parentNode;
+			}
+
 			const viewSelection = this.fakeSelectionToView( container );
 			const viewSelection = this.fakeSelectionToView( container );
 
 
 			if ( viewSelection ) {
 			if ( viewSelection ) {

+ 2 - 2
packages/ckeditor5-engine/src/view/observer/domeventobserver.js

@@ -23,8 +23,8 @@ import DomEventData from './domeventdata.js';
  *				return 'click';
  *				return 'click';
  *			}
  *			}
  *
  *
- *			onDomEvent( domEvt ) {
- *				this.fire( 'click' );
+ *			onDomEvent( domEvent ) {
+ *				this.fire( 'click', domEvent );
  *			}
  *			}
  *		}
  *		}
  *
  *

+ 0 - 1
packages/ckeditor5-engine/src/view/observer/selectionobserver.js

@@ -124,7 +124,6 @@ export default class SelectionObserver extends Observer {
 		// If there were mutations then the view will be re-rendered by the mutation observer and selection
 		// If there were mutations then the view will be re-rendered by the mutation observer and selection
 		// will be updated, so selections will equal and event will not be fired, as expected.
 		// will be updated, so selections will equal and event will not be fired, as expected.
 		const domSelection = domDocument.defaultView.getSelection();
 		const domSelection = domDocument.defaultView.getSelection();
-
 		const newViewSelection = this.domConverter.domSelectionToView( domSelection );
 		const newViewSelection = this.domConverter.domSelectionToView( domSelection );
 
 
 		if ( this.selection.isEqual( newViewSelection ) ) {
 		if ( this.selection.isEqual( newViewSelection ) ) {

+ 5 - 14
packages/ckeditor5-engine/src/view/renderer.js

@@ -462,30 +462,22 @@ export default class Renderer {
 		const domDocument = domRoot.ownerDocument;
 		const domDocument = domRoot.ownerDocument;
 
 
 		// Create fake selection container if one does not exist.
 		// Create fake selection container if one does not exist.
-		if ( this._fakeSelectionContainer === null ) {
+		if ( !this._fakeSelectionContainer ) {
 			this._fakeSelectionContainer = domDocument.createElement( 'div' );
 			this._fakeSelectionContainer = domDocument.createElement( 'div' );
 			this._fakeSelectionContainer.style.position = 'fixed';
 			this._fakeSelectionContainer.style.position = 'fixed';
 			this._fakeSelectionContainer.style.top = 0;
 			this._fakeSelectionContainer.style.top = 0;
 			this._fakeSelectionContainer.style.left = '-9999px';
 			this._fakeSelectionContainer.style.left = '-9999px';
+			this._fakeSelectionContainer.appendChild( domDocument.createTextNode( '\u00A0' ) );
 		}
 		}
 
 
 		// Add fake container if not already added.
 		// Add fake container if not already added.
-		if ( this._fakeSelectionContainer.parentElement === null ) {
+		if ( !this._fakeSelectionContainer.parentElement ) {
 			domRoot.appendChild( this._fakeSelectionContainer );
 			domRoot.appendChild( this._fakeSelectionContainer );
 		}
 		}
 
 
 		// Update contents.
 		// Update contents.
 		const content = this.selection.fakeSelectionLabel || '\u00A0';
 		const content = this.selection.fakeSelectionLabel || '\u00A0';
-		const textNode = this._fakeSelectionContainer.firstChild;
-
-		if ( !textNode || content !== textNode.textContent ) {
-			if ( textNode ) {
-				this._fakeSelectionContainer.removeChild( textNode );
-			}
-
-			const newTextNode = domDocument.createTextNode( content );
-			this._fakeSelectionContainer.appendChild( newTextNode );
-		}
+		this._fakeSelectionContainer.firstChild.data = content;
 
 
 		// Update selection.
 		// Update selection.
 		const domSelection = domDocument.getSelection();
 		const domSelection = domDocument.getSelection();
@@ -552,9 +544,8 @@ export default class Renderer {
 	_removeFakeSelection() {
 	_removeFakeSelection() {
 		const container = this._fakeSelectionContainer;
 		const container = this._fakeSelectionContainer;
 
 
-		if ( container !== null ) {
+		if ( container ) {
 			container.remove();
 			container.remove();
-			container.textContent = '';
 		}
 		}
 	}
 	}
 
 

+ 2 - 0
packages/ckeditor5-engine/src/view/selection.js

@@ -78,6 +78,8 @@ export default class Selection {
 	setFake( value = true, options = {} ) {
 	setFake( value = true, options = {} ) {
 		this._isFake = value;
 		this._isFake = value;
 		this._fakeSelectionLabel = value ? options.label || '' : '';
 		this._fakeSelectionLabel = value ? options.label || '' : '';
+
+		this.fire( 'change' );
 	}
 	}
 
 
 	/**
 	/**

+ 33 - 12
packages/ckeditor5-engine/tests/view/manual/fakeselection.js

@@ -6,7 +6,7 @@
 /* globals document, console */
 /* globals document, console */
 
 
 import ViewDocument from '/ckeditor5/engine/view/document.js';
 import ViewDocument from '/ckeditor5/engine/view/document.js';
-import ClickObserver from '/ckeditor5/engine/view/observer/clickobserver.js';
+import DomEventObserver from '/ckeditor5/engine/view/observer/domeventobserver.js';
 import ViewRange from '/ckeditor5/engine/view/range.js';
 import ViewRange from '/ckeditor5/engine/view/range.js';
 import { setData } from '/ckeditor5/engine/dev-utils/view.js';
 import { setData } from '/ckeditor5/engine/dev-utils/view.js';
 
 
@@ -15,36 +15,57 @@ const domEditable = document.getElementById( 'editor' );
 const viewRoot = viewDocument.createRoot( domEditable );
 const viewRoot = viewDocument.createRoot( domEditable );
 let viewStrong;
 let viewStrong;
 
 
-viewDocument.addObserver( ClickObserver );
+// Add mouseup oberver.
+viewDocument.addObserver( class extends DomEventObserver {
+	get domEventType() {
+		return [ 'mousedown', 'mouseup' ];
+	}
+
+	onDomEvent( domEvent ) {
+		this.fire( domEvent.type, domEvent );
+	}
+} );
 
 
 viewDocument.on( 'selectionChange', ( evt, data ) => {
 viewDocument.on( 'selectionChange', ( evt, data ) => {
 	viewDocument.selection.setTo( data.newSelection );
 	viewDocument.selection.setTo( data.newSelection );
 	viewDocument.render();
 	viewDocument.render();
 } );
 } );
 
 
-viewDocument.selection.on( 'change', () => {
-	if ( viewStrong && !viewDocument.selection.isFake ) {
-		viewStrong.removeStyle( 'background-color' );
-	}
-} );
-
-viewDocument.on( 'click', ( evt, data ) => {
+viewDocument.on( 'mouseup', ( evt, data ) => {
 	if ( data.target == viewStrong ) {
 	if ( data.target == viewStrong ) {
+		console.log( 'Making selection around the <strong>.' );
+
 		const range = ViewRange.createOn( viewStrong );
 		const range = ViewRange.createOn( viewStrong );
 		viewDocument.selection.setRanges( [ range ] );
 		viewDocument.selection.setRanges( [ range ] );
 		viewDocument.selection.setFake( true, { label: 'fake selection over bar' } );
 		viewDocument.selection.setFake( true, { label: 'fake selection over bar' } );
-		viewStrong.setStyle( 'background-color', 'yellow' );
 
 
 		viewDocument.render();
 		viewDocument.render();
+
+		data.preventDefault();
+	}
+} );
+
+viewDocument.selection.on( 'change', () => {
+	if ( !viewStrong ) {
+		return;
+	}
+
+	const firstPos = viewDocument.selection.getFirstPosition();
+	const lastPos = viewDocument.selection.getLastPosition();
+
+	if ( firstPos && lastPos && firstPos.nodeAfter == viewStrong && lastPos.nodeBefore == viewStrong ) {
+		viewStrong.setStyle( 'background-color', 'yellow' );
+	} else {
+		viewStrong.removeStyle( 'background-color' );
 	}
 	}
 } );
 } );
 
 
 viewDocument.on( 'focus', () => {
 viewDocument.on( 'focus', () => {
-	console.log( 'The document was focused' );
+	console.log( 'The document was focused.' );
 } );
 } );
 
 
 viewDocument.on( 'blur', () => {
 viewDocument.on( 'blur', () => {
-	console.log( 'The document was blurred' );
+	console.log( 'The document was blurred.' );
 } );
 } );
 
 
 setData( viewDocument, '<container:p>{}foo<strong contenteditable="false">bar</strong>baz</container:p>' );
 setData( viewDocument, '<container:p>{}foo<strong contenteditable="false">bar</strong>baz</container:p>' );