|
|
@@ -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;
|
|
|
-}
|