敲碎时间,铸造不朽的个人专栏
上一篇

CKEditor5——Position源码分析(三)

广告
选中文字可对指定文章内容进行评论啦,→和←可快速切换按钮,绿色背景文字可以点击查看评论额。
大纲

CKEditor5——Position源码分析(三)

上一节我们学习了比较两个Position之间的关系,它们可能属于不同的根节点,它们可能完全相同,它们也可能存在前后关系。

今天我们继续学习这个类的另一个关键方法:那就是

getTransformedByOperation( operation ) → Position

getTransformedByOperation( operation ) {
	let result;

	switch ( operation.type ) {
		case 'insert':
			result = this._getTransformedByInsertOperation( operation );
			break;
		case 'move':
		case 'remove':
		case 'reinsert':
			result = this._getTransformedByMoveOperation( operation );
			break;
		case 'split':
			result = this._getTransformedBySplitOperation( operation );
			break;
		case 'merge':
			result = this._getTransformedByMergeOperation( operation );
			break;
		default:
			result = Position._createAt( this );
			break;
	}
	return result;
}

首先说明一下这个方法:

返回由给定操作转换的此位置的副本。新位置的参数会根据操作的效果进行相应更新。例如,如果在位置之前插入n个节点,则返回的位置偏移量将增加n。如果该位置在合并元素中,它将相应地移动到新元素等。这种方法可以安全地用于不存在的位置(例如在操作转换期间)。

从以上说明,我们可以看出,这个方法是当前位置应用一个给定的操作后返回一个新的位置,具体的操作有六类:insert,move,remove,reinsert,split,merge,而move,remove,reinsert又是同一种情况,我们先看看insert的情况:this._getTransformedByInsertOperation( operation );

_getTransformedByInsertOperation( operation ) {
	return this._getTransformedByInsertion( operation.position, operation.howMany );
}
_getTransformedByInsertion( insertPosition, howMany ) {
	const transformed = Position._createAt( this );

	// This position can't be affected if insertion was in a different root.
	if ( this.root != insertPosition.root ) {
		return transformed;
	}

	if ( compareArrays( insertPosition.getParentPath(), this.getParentPath() ) == 'same' ) {
		// If nodes are inserted in the node that is pointed by this position...
		if ( insertPosition.offset < this.offset || ( insertPosition.offset == this.offset && this.stickiness != 'toPrevious' ) ) {
			// And are inserted before an offset of that position...
			// "Push" this positions offset.
			transformed.offset += howMany;
		}
	} else if ( compareArrays( insertPosition.getParentPath(), this.getParentPath() ) == 'prefix' ) {
		// If nodes are inserted in a node that is on a path to this position...
		const i = insertPosition.path.length - 1;

		if ( insertPosition.offset <= this.path[ i ] ) {
			// And are inserted before next node of that path...
			// "Push" the index on that path.
			transformed.path[ i ] += howMany;
		}
	}

	return transformed;
}

我们看到insert的情况实际上分为三类,

1、如果当前位置的根节点与操作对应的位置的根节点不一致,那么直接返回当前位置,实际上可能啥都没有做,因为操作对应的位置没有啥效果

2、如果当前位置的parentPath与插入操作的位置的parentPath一致,那么这里分两种情况:

//第一种情况
// should increment offset if insertion is in the same parent and the same offset
const position = new Position( root, [ 1, 2, 3 ] );
position.stickiness = 'toNext';
const transformed = position._getTransformedByInsertion( new Position( root, [ 1, 2, 3 ] ), 2 );

expect( transformed.offset ).to.equal( 5 );
//第二种情况
//should increment offset if insertion is in the same parent and closer offset
const position = new Position( root, [ 1, 2, 3 ] );
const transformed = position._getTransformedByInsertion( new Position( root, [ 1, 2, 2 ] ), 2 );
expect( transformed.offset ).to.equal( 5 );

3、如果插入位置的parentPath在当前位置的parentPath之前,那么这种情况如下:

//should update path if insertion position parent is a node from that path and offset is before next node on that path
const position = new Position( root, [ 1, 2, 3 ] );
const transformed = position._getTransformedByInsertion( new Position( root, [ 1, 2 ] ), 2 );

expect( transformed.path ).to.deep.equal( [ 1, 4, 3 ] );

另外的其他情况的话,返回的位置都不会发生变化,因此,以上就是插入操作的情况下,可能发生新位置偏移的情况。另外move的情况比较复杂,我们以后分析。

 

 

版权声明:著作权归作者所有。