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

Added: dom.getCommonAncestor, dom.getParents.

Szymon Cofalik 9 лет назад
Родитель
Сommit
f175f33371

+ 32 - 0
packages/ckeditor5-utils/src/dom/getcommonancestor.js

@@ -0,0 +1,32 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+import getParents from './getparents.js';
+
+/**
+ * Searches and returns the lowest common ancestor of two given nodes.
+ *
+ * @param {Node} nodeA First node.
+ * @param {Node} nodeB Second node.
+ * @returns {Node|null} Lowest common ancestor of both nodes or `null` if nodes do not have a common ancestor.
+ */
+export default function getCommonAncestor( nodeA, nodeB ) {
+	if ( nodeA == nodeB ) {
+		return nodeA;
+	}
+
+	const parentsA = getParents( nodeA );
+	const parentsB = getParents( nodeB );
+
+	const minLength = Math.min( parentsA.length, parentsB.length );
+
+	for ( let i = minLength - 1; i >= 0; i-- ) {
+		if ( parentsA[ i ] == parentsB[ i ] ) {
+			return parentsA[ i ];
+		}
+	}
+
+	return null;
+}

+ 21 - 0
packages/ckeditor5-utils/src/dom/getparents.js

@@ -0,0 +1,21 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * Returns all parents of given DOM node, starting from the top-most (root). Includes the node itself.
+ *
+ * @param {Node} node DOM node.
+ * @returns {Array.<Node>} Array of given `node` parents.
+ */
+export default function getParents( node ) {
+	const nodes = [];
+
+	while ( node ) {
+		nodes.unshift( node );
+		node = node.parentNode;
+	}
+
+	return nodes;
+}

+ 63 - 0
packages/ckeditor5-utils/tests/dom/getcommonancestor.js

@@ -0,0 +1,63 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals document */
+/* bender-tags: dom, browser-only */
+
+import getCommonAncestor from '/ckeditor5/utils/dom/getcommonancestor.js';
+import createElement from '/ckeditor5/utils/dom/createelement.js';
+
+describe( 'getParents', () => {
+	let b, span1, span2, p1, p2, i, div;
+
+	beforeEach( () => {
+		// DIV
+		//  |- P (1)
+		//  |  |- SPAN (1)
+		//  |  |  |- B
+		//  |  |
+		//  |  |- SPAN (2)
+		//  |
+		//  |- P (2)
+		//     |- I
+		b = createElement( document, 'b' );
+		span1 = createElement( document, 'span', {}, [ b ] );
+		span2 = createElement( document, 'span' );
+		p1 = createElement( document, 'p', {}, [ span1, span2 ] );
+		i = createElement( document, 'i' );
+		p2 = createElement( document, 'p', {}, [ i ] );
+		div = createElement( document, 'div', {}, [ p1, p2 ] );
+	} );
+
+	function test( a, b, lca ) {
+		expect( getCommonAncestor( a, b ) ).to.equal( lca );
+		expect( getCommonAncestor( b, a ) ).to.equal( lca );
+	}
+
+	it( 'should return lowest common ancestor of nodes in different tree branches', () => {
+		test( p1, p2, div );
+		test( span1, span2, p1 );
+		test( b, span2, p1 );
+		test( i, b, div );
+	} );
+
+	it( 'should return one of nodes if it is a parent of another node', () => {
+		test( div, p1, div );
+		test( p1, b, p1 );
+	} );
+
+	it( 'should return the node if both parameters are same', () => {
+		test( div, div, div );
+		test( b, b, b );
+	} );
+
+	it( 'should return null for nodes that do not have common ancestor (different trees)', () => {
+		const diffB = createElement( document, 'b' );
+		const diffDiv = createElement( document, 'div', {}, diffB );
+
+		test( diffB, span1, null );
+		test( diffDiv, p1, null );
+	} );
+} );

+ 29 - 0
packages/ckeditor5-utils/tests/dom/getparents.js

@@ -0,0 +1,29 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals document */
+/* bender-tags: dom, browser-only */
+
+import getParents from '/ckeditor5/utils/dom/getparents.js';
+import createElement from '/ckeditor5/utils/dom/createelement.js';
+
+describe( 'getParents', () => {
+	it( 'should return all parents of given node and the node itself, starting from top-most parent', () => {
+		// DIV
+		//  |- P (1)
+		//  |  |- SPAN (1)
+		//  |     |- B
+		//  |
+		//  |- P (2)
+		//     |- I
+		const b = createElement( document, 'b' );
+		const span = createElement( document, 'span', {}, [ b ] );
+		const p1 = createElement( document, 'p', {}, [ span ] );
+		const p2 = createElement( document, 'p', {}, [ createElement( document, 'i' ) ] );
+		const div = createElement( document, 'div', {}, [ p1, p2 ] );
+
+		expect( getParents( b ) ).to.deep.equal( [ div, p1, span, b ] );
+	} );
+} );