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

Removed unnecessary looping through collapsed selection ranges.

Oskar Wrobel 9 лет назад
Родитель
Сommit
5838e327a3

+ 8 - 18
packages/ckeditor5-link/src/linkcommand.js

@@ -70,27 +70,17 @@ export default class LinkCommand extends Command {
 			const batch = document.batch();
 
 			if ( selection.isCollapsed ) {
-				const ranges = selection.getRanges();
-				const updatedRanges = [];
+				const position = selection.getFirstPosition();
+				const parent = position.parent;
 
-				for ( let range of ranges ) {
-					// Get parent of current selection position.
-					const parent = range.start.parent;
-
-					// Insert Text node with link attribute if is allowed in parent.
-					if ( document.schema.check( { name: '$text', attributes: 'link', inside: parent.name } ) ) {
-						const node = new Text( href, { link: href } );
+				// Insert Text node with link attribute if is allowed in parent.
+				if ( document.schema.check( { name: '$text', attributes: 'link', inside: parent.name } ) ) {
+					const node = new Text( href, { link: href } );
 
-						batch.insert( range.start, node );
-						// Create new range wrapping just created node.
-						updatedRanges.push( Range.createOn( node ) );
-					}
-				}
+					batch.insert( position, node );
 
-				// Update selection.
-				// If there is no updatedRanges it means that each insertion was disallowed.
-				if ( updatedRanges.length ) {
-					selection.setRanges( updatedRanges, selection.isBackward );
+					// Create new range wrapping just created node.
+					selection.setRanges( [ Range.createOn( node ) ] );
 					selection.setAttribute( 'link', href );
 				}
 			} else {

+ 34 - 51
packages/ckeditor5-link/src/unlinkcommand.js

@@ -4,7 +4,6 @@
  */
 
 import Command from '../core/command/command.js';
-import Range from '../engine/model/range.js';
 
 /**
  * The unlink command. It is used by the {@link Link.Link link feature}.
@@ -12,7 +11,7 @@ import Range from '../engine/model/range.js';
  * @memberOf link
  * @extends core.command.Command
  */
-export default class LinkCommand extends Command {
+export default class UnlinkCommand extends Command {
 	/**
 	 * Executes the command.
 	 *
@@ -26,65 +25,49 @@ export default class LinkCommand extends Command {
 	_doExecute() {
 		const document = this.editor.document;
 		const selection = document.selection;
-		const ranges = selection.getRanges();
-		let rangesToUpdate = [];
 
 		document.enqueueChanges( () => {
-			// When selection is collapsed we have to find link bounds.
+			// Keep it as one undo step.
+			const batch = document.batch();
+
+			// When selection is collapsed we have to remove link attribute from every stick sibling with the same attribute value.
 			if ( selection.isCollapsed ) {
-				// Loop through each selection.
-				for ( let range of ranges ) {
-					// Get searching area.
-					const parentNodeRange = Range.createIn( range.start.parent );
+				const linkValue = selection.getAttribute( 'link' );
+				const position = selection.getFirstPosition();
+				let sibling;
 
-					// Create walker instances for going forward and backward.
-					const walker = parentNodeRange.getWalker( { startPosition: range.start } );
-					const backwardWalker = parentNodeRange.getWalker( { startPosition: range.start, direction: 'backward' } );
+				// Get node on the right side of the selection. When selection is inside TextNode then get this node.
+				sibling = position.textNode === null ? position.nodeAfter : position.textNode;
+
+				// Walk forward and remove link attribute from each stick element with the same attribute value.
+				while ( sibling ) {
+					if ( sibling.getAttribute( 'link' ) == linkValue ) {
+						batch.removeAttribute( sibling, 'link' );
+						sibling = sibling.nextSibling;
+					} else {
+						sibling = null;
+					}
+				}
 
-					// Store current link attribute value.
-					const attributeValue = selection.getAttribute( 'link' );
+				// Get node on the left side of the selection. When selection is inside TextNode then get node just after
+				// TextNode because link attribute has been already removed from TextNode during forward walking.
+				sibling = position.textNode === null ? position.nodeBefore : position.textNode.previousSibling;
 
-					// Search link bounds and store found range.
-					rangesToUpdate.push(
-						new Range( getLinkBound( backwardWalker, attributeValue ), getLinkBound( walker, attributeValue ) )
-					);
+				// Walk backward and remove link attribute from each stick element with the same attribute value.
+				while ( sibling ) {
+					if ( sibling.getAttribute( 'link' ) == linkValue ) {
+						batch.removeAttribute( sibling, 'link' );
+						sibling = sibling.previousSibling;
+					} else {
+						sibling = null;
+					}
 				}
 			} else {
 				// When selection is non-collapsed then we are unlinking selected ranges.
-				rangesToUpdate = ranges;
-			}
-
-			// Keep it as one undo step.
-			const batch = document.batch();
-
-			// Remove attribute from each range.
-			for ( let range of rangesToUpdate ) {
-				batch.removeAttribute( range, 'link' );
+				for ( let range of selection.getRanges() ) {
+					batch.removeAttribute( range, 'link' );
+				}
 			}
-
-			// Remove attribute from selection.
-			selection.removeAttribute( 'link' );
 		} );
 	}
 }
-
-// Walk trough the range and search for link bound.
-//
-// @param {engine.model.TreeWalker} walker TreeWalker instance.
-// @param {String} linkValue Value of searching link.
-// @returns {engine.model.Position} Position of link bound.
-function getLinkBound( walker, linkValue ) {
-	let lastPosition = walker.position;
-	let current = walker.next();
-
-	while ( !current.done ) {
-		if ( current.value.item.getAttribute( 'link' ) != linkValue ) {
-			return lastPosition;
-		}
-
-		lastPosition = walker.position;
-		current = walker.next();
-	}
-
-	return lastPosition;
-}