浏览代码

Code refactoring.

Aleksander Nowodzinski 7 年之前
父节点
当前提交
aad6b030a4
共有 1 个文件被更改,包括 99 次插入75 次删除
  1. 99 75
      packages/ckeditor5-engine/src/utils/bindtwostepcarettoattribute.js

+ 99 - 75
packages/ckeditor5-engine/src/utils/bindtwostepcarettoattribute.js

@@ -37,20 +37,11 @@ import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
  * @param {String} attribute Attribute for which this behavior will be added.
  */
 export default function bindTwoStepCaretToAttribute( view, model, emitter, attribute ) {
+	const twoStepCaretHandler = new TwoStepCaretHandler( model, emitter, attribute );
 	const modelSelection = model.document.selection;
-	let overrideUid;
-	let skipNextChangeRange = false;
 
 	// Listen to keyboard events and handle cursor before the move.
 	emitter.listenTo( view.document, 'keydown', ( evt, data ) => {
-		const arrowRightPressed = data.keyCode == keyCodes.arrowright;
-		const arrowLeftPressed = data.keyCode == keyCodes.arrowleft;
-
-		// When neither left or right arrow has been pressed then do noting.
-		if ( !arrowRightPressed && !arrowLeftPressed ) {
-			return;
-		}
-
 		// This implementation works only for collapsed selection.
 		if ( !modelSelection.isCollapsed ) {
 			return;
@@ -62,39 +53,60 @@ export default function bindTwoStepCaretToAttribute( view, model, emitter, attri
 			return;
 		}
 
+		const arrowRightPressed = data.keyCode == keyCodes.arrowright;
+		const arrowLeftPressed = data.keyCode == keyCodes.arrowleft;
+
+		// When neither left or right arrow has been pressed then do noting.
+		if ( !arrowRightPressed && !arrowLeftPressed ) {
+			return;
+		}
+
 		const position = modelSelection.getFirstPosition();
 
 		if ( arrowRightPressed ) {
-			handleArrowRightPress( position, data );
+			twoStepCaretHandler.handleForwardMovement( position, data );
 		} else {
-			handleArrowLeftPress( position, data );
+			twoStepCaretHandler.handleBackwardMovement( position, data );
 		}
 	} );
+}
 
-	emitter.listenTo( modelSelection, 'change:range', ( evt, data ) => {
-		if ( skipNextChangeRange ) {
-			skipNextChangeRange = false;
+class TwoStepCaretHandler {
+	constructor( model, emitter, attribute ) {
+		this.model = model;
+		this.attribute = attribute;
 
-			return;
-		}
+		this._modelSelection = model.document.selection;
+		this._overrideUid = null;
+		this._skipNextChangeRange = false;
 
-		// Skip automatic restore when the gravity is not overridden — simply, there's nothing to restore
-		// at this moment.
-		if ( !overrideUid ) {
-			return;
-		}
+		emitter.listenTo( this._modelSelection, 'change:range', ( evt, data ) => {
+			if ( this._skipNextChangeRange ) {
+				this._skipNextChangeRange = false;
 
-		// Skip automatic restore when the change is indirect AND the selection is at the attribute boundary.
-		// It means that e.g. if the change was external (collaboration) and the user had their
-		// selection around the link, its gravity should remain intact in this change:range event.
-		if ( !data.directChange && isAtBoundary( modelSelection.getFirstPosition(), attribute ) ) {
-			return;
-		}
+				return;
+			}
 
-		restoreGravity( model );
-	} );
+			// Skip automatic restore when the gravity is not overridden — simply, there's nothing to restore
+			// at this moment.
+			if ( !this._isGravityOverridden ) {
+				return;
+			}
+
+			// Skip automatic restore when the change is indirect AND the selection is at the attribute boundary.
+			// It means that e.g. if the change was external (collaboration) and the user had their
+			// selection around the link, its gravity should remain intact in this change:range event.
+			if ( !data.directChange && isAtBoundary( this._modelSelection.getFirstPosition(), attribute ) ) {
+				return;
+			}
+
+			this._restoreGravity();
+		} );
+	}
+
+	handleForwardMovement( position, data ) {
+		const attribute = this.attribute;
 
-	function handleArrowRightPress( position, data ) {
 		// DON'T ENGAGE 2-SCM if gravity is already overridden. It means that we just entered
 		//
 		// 		<paragraph>foo{}<$text attribute>bar</$text>baz</paragraph>
@@ -104,7 +116,7 @@ export default function bindTwoStepCaretToAttribute( view, model, emitter, attri
 		// 		<paragraph>foo<$text attribute>bar</$text>{}baz</paragraph>
 		//
 		// and the gravity will be restored automatically.
-		if ( overrideUid ) {
+		if ( this._isGravityOverridden ) {
 			return;
 		}
 
@@ -114,7 +126,7 @@ export default function bindTwoStepCaretToAttribute( view, model, emitter, attri
 		//
 		//		<paragraph><$text attribute>{}bar</$text>baz</paragraph>
 		//
-		if ( position.isAtStart && modelSelection.hasAttribute( attribute ) ) {
+		if ( position.isAtStart && this._hasAttribute ) {
 			return;
 		}
 
@@ -126,17 +138,17 @@ export default function bindTwoStepCaretToAttribute( view, model, emitter, attri
 		//
 		// 		<paragraph><$text attribute="1">foo</$text>{}<$text attribute="2">bar</$text></paragraph>
 		//
-		if ( isBetweenDifferentValues( position, attribute ) && modelSelection.hasAttribute( attribute ) ) {
-			preventCaretMovement( data );
-			removeSelectionAttribute( model );
+		if ( isBetweenDifferentValues( position, attribute ) && this._hasAttribute ) {
+			this._preventCaretMovement( data );
+			this._removeSelectionAttribute();
 		} else {
 			// ENGAGE 2-SCM when entering an attribute:
 			//
 			// 		<paragraph>foo{}<$text attribute>bar</$text>baz</paragraph>
 			//
 			if ( isAtStartBoundary( position, attribute ) ) {
-				preventCaretMovement( data );
-				overrideGravity( model );
+				this._preventCaretMovement( data );
+				this._overrideGravity();
 
 				return;
 			}
@@ -145,16 +157,18 @@ export default function bindTwoStepCaretToAttribute( view, model, emitter, attri
 			//
 			//		<paragraph>foo<$text attribute>bar{}</$text>baz</paragraph>
 			//
-			if ( isAtEndBoundary( position, attribute ) && modelSelection.hasAttribute( attribute ) ) {
-				preventCaretMovement( data );
-				overrideGravity( model );
+			if ( isAtEndBoundary( position, attribute ) && this._hasAttribute ) {
+				this._preventCaretMovement( data );
+				this._overrideGravity();
 			}
 		}
 	}
 
-	function handleArrowLeftPress( position, data ) {
+	handleBackwardMovement( position, data ) {
+		const attribute = this.attribute;
+
 		// When the gravity is already overridden...
-		if ( overrideUid ) {
+		if ( this._isGravityOverridden ) {
 			// ENGAGE 2-SCM & REMOVE SELECTION ATTRIBUTE
 			// when about to leave one attribute value and enter another:
 			//
@@ -164,10 +178,10 @@ export default function bindTwoStepCaretToAttribute( view, model, emitter, attri
 			//
 			// 		<paragraph><$text attribute="1">foo</$text>{}<$text attribute="2">bar</$text></paragraph>
 			//
-			if ( isBetweenDifferentValues( position, attribute ) && modelSelection.hasAttribute( attribute ) ) {
-				preventCaretMovement( data );
-				restoreGravity( model );
-				removeSelectionAttribute( model );
+			if ( isBetweenDifferentValues( position, attribute ) && this._hasAttribute ) {
+				this._preventCaretMovement( data );
+				this._restoreGravity();
+				this._removeSelectionAttribute();
 			}
 
 			// ENGAGE 2-SCM when at any boundary of the attribute:
@@ -176,8 +190,8 @@ export default function bindTwoStepCaretToAttribute( view, model, emitter, attri
 			// 		<paragraph>foo<$text attribute>{}bar</$text>baz</paragraph>
 			//
 			else {
-				preventCaretMovement( data );
-				restoreGravity( model );
+				this._preventCaretMovement( data );
+				this._restoreGravity();
 
 				// REMOVE SELECTION ATRIBUTE at the beginning of the block.
 				// It's like restoring gravity but towards a non-existent content when
@@ -190,7 +204,7 @@ export default function bindTwoStepCaretToAttribute( view, model, emitter, attri
 				// 		<paragraph>{}<$text attribute>bar</$text></paragraph>
 				//
 				if ( position.isAtStart ) {
-					removeSelectionAttribute( model );
+					this._removeSelectionAttribute();
 				}
 			}
 		} else {
@@ -198,9 +212,9 @@ export default function bindTwoStepCaretToAttribute( view, model, emitter, attri
 			//
 			// 		<paragraph><$text attribute="1">foo</$text>{}<$text attribute="2">bar</$text></paragraph>
 			//
-			if ( isBetweenDifferentValues( position, attribute ) && !modelSelection.hasAttribute( attribute ) ) {
-				preventCaretMovement( data );
-				setSelectionAttributeFromTheNodeBefore( model, position );
+			if ( isBetweenDifferentValues( position, attribute ) && !this._hasAttribute ) {
+				this._preventCaretMovement( data );
+				this._setSelectionAttributeFromTheNodeBefore( position );
 
 				return;
 			}
@@ -210,11 +224,11 @@ export default function bindTwoStepCaretToAttribute( view, model, emitter, attri
 			// 		<paragraph><$text attribute>bar{}</$text></paragraph>
 			//
 			if ( position.isAtEnd && isAtBoundary( position, attribute ) ) {
-				if ( modelSelection.hasAttribute( attribute ) ) {
+				if ( this._hasAttribute ) {
 					return;
 				} else {
-					preventCaretMovement( data );
-					setSelectionAttributeFromTheNodeBefore( model, position );
+					this._preventCaretMovement( data );
+					this._setSelectionAttributeFromTheNodeBefore( position );
 
 					return;
 				}
@@ -226,8 +240,8 @@ export default function bindTwoStepCaretToAttribute( view, model, emitter, attri
 			// 		<paragraph>{}<$text attribute>bar</$text></paragraph>
 			//
 			if ( position.isAtStart && isAtBoundary( position, attribute ) ) {
-				if ( modelSelection.hasAttribute( attribute ) ) {
-					removeSelectionAttribute( model );
+				if ( this._hasAttribute ) {
+					this._removeSelectionAttribute();
 
 					return;
 				}
@@ -245,41 +259,51 @@ export default function bindTwoStepCaretToAttribute( view, model, emitter, attri
 				// Skip the automatic gravity restore upon the next selection#change:range event.
 				// If not skipped, it would automatically restore the gravity, which should remain
 				// overridden.
-				skipNextRangeChange();
-				overrideGravity( model );
+				this._skipNextRangeChange();
+				this._overrideGravity();
 			}
 		}
 	}
 
-	function overrideGravity( model ) {
-		overrideUid = model.change( writer => writer.overrideSelectionGravity() );
+	get _isGravityOverridden() {
+		return !!this._overrideUid;
 	}
 
-	function restoreGravity( model ) {
-		model.change( writer => {
-			writer.restoreSelectionGravity( overrideUid );
-			overrideUid = null;
+	get _hasAttribute() {
+		return this._modelSelection.hasAttribute( this.attribute );
+	}
+
+	_overrideGravity() {
+		this._overrideUid = this.model.change( writer => writer.overrideSelectionGravity() );
+	}
+
+	_restoreGravity() {
+		this.model.change( writer => {
+			writer.restoreSelectionGravity( this._overrideUid );
+			this._overrideUid = null;
 		} );
 	}
 
-	function preventCaretMovement( data ) {
+	_preventCaretMovement( data ) {
 		data.preventDefault();
 	}
 
-	function removeSelectionAttribute( model ) {
-		model.change( writer => {
-			writer.removeSelectionAttribute( attribute );
+	_removeSelectionAttribute() {
+		this.model.change( writer => {
+			writer.removeSelectionAttribute( this.attribute );
 		} );
 	}
 
-	function setSelectionAttributeFromTheNodeBefore( model, position ) {
-		model.change( writer => {
-			writer.setSelectionAttribute( attribute, position.nodeBefore.getAttribute( attribute ) );
+	_setSelectionAttributeFromTheNodeBefore( position ) {
+		const attribute = this.attribute;
+
+		this.model.change( writer => {
+			writer.setSelectionAttribute( this.attribute, position.nodeBefore.getAttribute( attribute ) );
 		} );
 	}
 
-	function skipNextRangeChange() {
-		skipNextChangeRange = true;
+	_skipNextRangeChange() {
+		this._skipNextChangeRange = true;
 	}
 }