Browse Source

Removed nodeList.push. Introduced element.insertChildren. Element can be created with children. Parent is added automatically when node is inserted.

Piotr Jasiun 10 năm trước cách đây
mục cha
commit
9c1b9fd2de

+ 2 - 2
packages/ckeditor5-utils/src/document/character.js

@@ -17,8 +17,8 @@ CKEDITOR.define( [ 'document/node' ], function( Node ) {
 		 *
 		 * @param {String} character Described character.
 		 */
-		constructor( parent, character, attrs ) {
-			super( parent, attrs );
+		constructor( character, attrs ) {
+			super( attrs );
 
 			/**
 			 * Described character.

+ 1 - 1
packages/ckeditor5-utils/src/document/document.js

@@ -27,7 +27,7 @@ CKEDITOR.define( [
 			 * @readonly
 			 * @property {String} root
 			 */
-			this.root = new Element( null, 'root' );
+			this.root = new Element( 'root' );
 
 			this.version = 0;
 		}

+ 15 - 3
packages/ckeditor5-utils/src/document/element.js

@@ -21,8 +21,8 @@ CKEDITOR.define( [ 'document/node', 'document/nodelist' ], function( Node, NodeL
 		 * @param {String} name Node name.
 		 * @param {Array} attrs Array of attributes.
 		 */
-		constructor( parent, name, attrs, children ) {
-			super( parent, attrs );
+		constructor( name, attrs, children ) {
+			super( attrs );
 
 			/**
 			 * Element name.
@@ -37,7 +37,19 @@ CKEDITOR.define( [ 'document/node', 'document/nodelist' ], function( Node, NodeL
 			 *
 			 * @property {Array} children
 			 */
-			this.children = new NodeList( children );
+			this.children = new NodeList();
+
+			if ( children ) {
+				this.insertChildren( 0, children );
+			}
+		}
+
+		insertChildren( index, nodes ) {
+			this.children.insert( index, new NodeList( nodes ) );
+
+			for ( var node of this.children ) {
+				node.parent = this;
+			}
 		}
 	}
 

+ 1 - 1
packages/ckeditor5-utils/src/document/insertoperation.js

@@ -23,7 +23,7 @@ CKEDITOR.define( [ 'document/operation', 'document/nodelist', 'document/removeop
 		}
 
 		_execute() {
-			this.position.parent.children.insert( this.position.offset, this.nodeList );
+			this.position.parent.insertChildren( this.position.offset, this.nodeList );
 		}
 
 		reverseOperation() {

+ 1 - 1
packages/ckeditor5-utils/src/document/moveoperation.js

@@ -38,7 +38,7 @@ CKEDITOR.define( [ 'document/operation', 'document/nodelist' ], function( Operat
 				targetOffset -= nodeList.length;
 			}
 
-			targetElement.children.insert( targetOffset, this.nodeList );
+			targetElement.insertChildren( targetOffset, this.nodeList );
 		}
 
 		reverseOperation() {

+ 2 - 2
packages/ckeditor5-utils/src/document/node.js

@@ -20,14 +20,14 @@ CKEDITOR.define( [ 'document/attribute', 'utils' ], function( Attribute, utils )
 		 * @param {document.Element|Null} parent Node parent.
 		 * @param {Array} attrs Array of attributes.
 		 */
-		constructor( parent, attrs ) {
+		constructor( attrs ) {
 			/**
 			 * Parent element.
 			 *
 			 * @readonly
 			 * @property {document.Element} parent
 			 */
-			this.parent = parent;
+			this.parent = null;
 
 			/**
 			 * Array of attributes.

+ 5 - 5
packages/ckeditor5-utils/src/document/nodelist.js

@@ -32,7 +32,7 @@ CKEDITOR.define( [ 'document/character', 'document/node', 'utils' ], function( C
 						this._nodes.push( node );
 					} else {
 						for ( j = 0, nodeLen = node.length; j < nodeLen; j++ ) {
-							this._nodes.push( new Character( null, node[ j ] ) );
+							this._nodes.push( new Character( node[ j ] ) );
 						}
 					}
 				}
@@ -47,10 +47,6 @@ CKEDITOR.define( [ 'document/character', 'document/node', 'utils' ], function( C
 			this._nodes.splice.apply( this._nodes, [ index, 0 ].concat( nodeList._nodes ) );
 		}
 
-		push( nodes ) {
-			this.insert( this._nodes.length, new NodeList( nodes ) );
-		}
-
 		remove( index, number ) {
 			this._nodes.splice( index, number );
 		}
@@ -62,6 +58,10 @@ CKEDITOR.define( [ 'document/character', 'document/node', 'utils' ], function( C
 		get length() {
 			return this._nodes.length;
 		}
+
+		[ Symbol.iterator ]() {
+			return this._nodes[ Symbol.iterator ]();
+		}
 	}
 
 	return NodeList;

+ 31 - 37
packages/ckeditor5-utils/tests/document/changeoperation.js

@@ -14,6 +14,7 @@ var modules = bender.amd.require(
 	'document/range',
 	'document/character',
 	'document/attribute',
+	'document/nodelist',
 	'ckeditorerror' );
 
 describe( 'ChangeOperation', function() {
@@ -22,16 +23,13 @@ describe( 'ChangeOperation', function() {
 		var ChangeOperation = modules[ 'document/changeoperation' ];
 		var Position = modules[ 'document/position' ];
 		var Range = modules[ 'document/range' ];
-		var Character = modules[ 'document/character' ];
 		var Attribute = modules[ 'document/attribute' ];
 
 		var doc = new Document();
 
 		var newAttr = new Attribute( 'isNew', true );
 
-		doc.root.children.push( new Character( doc.root, 'b' ) );
-		doc.root.children.push( new Character( doc.root, 'a' ) );
-		doc.root.children.push( new Character( doc.root, 'r' ) );
+		doc.root.insertChildren( 0, 'bar' );
 
 		doc.applyOperation( new ChangeOperation(
 			new Range( new Position( [ 0 ], doc.root ), new Position( [ 2 ], doc.root ) ),
@@ -51,16 +49,13 @@ describe( 'ChangeOperation', function() {
 		var ChangeOperation = modules[ 'document/changeoperation' ];
 		var Position = modules[ 'document/position' ];
 		var Range = modules[ 'document/range' ];
-		var Character = modules[ 'document/character' ];
 		var Attribute = modules[ 'document/attribute' ];
 
 		var doc = new Document();
 
 		var newAttr = new Attribute( 'isNew', true );
 
-		doc.root.children.push( new Character( doc.root, 'b' ) );
-		doc.root.children.push( new Character( doc.root, 'a' ) );
-		doc.root.children.push( new Character( doc.root, 'r' ) );
+		doc.root.insertChildren( 0, 'bar' );
 
 		doc.applyOperation( new ChangeOperation(
 			[
@@ -92,7 +87,7 @@ describe( 'ChangeOperation', function() {
 		var fooAttr = new Attribute( 'foo', true );
 		var barAttr = new Attribute( 'bar', true );
 
-		doc.root.children.push( new Character( doc.root, 'x', [ fooAttr, barAttr ] ) );
+		doc.root.insertChildren( 0, new Character( 'x', [ fooAttr, barAttr ] ) );
 
 		doc.applyOperation( new ChangeOperation(
 			new Range( new Position( [ 0 ], doc.root ), new Position( [ 1 ], doc.root ) ),
@@ -121,9 +116,10 @@ describe( 'ChangeOperation', function() {
 		var oldAttr = new Attribute( 'isNew', false );
 		var newAttr = new Attribute( 'isNew', true );
 
-		doc.root.children.push( new Character( doc.root, 'b', [ oldAttr ] ) );
-		doc.root.children.push( new Character( doc.root, 'a', [ oldAttr ] ) );
-		doc.root.children.push( new Character( doc.root, 'r', [ oldAttr ] ) );
+		doc.root.insertChildren( 0, [
+			new Character( 'b', [ oldAttr ] ),
+			new Character( 'a', [ oldAttr ] ),
+			new Character( 'r', [ oldAttr ] ) ] );
 
 		doc.applyOperation( new ChangeOperation(
 			[
@@ -157,9 +153,10 @@ describe( 'ChangeOperation', function() {
 		var oldAttr = new Attribute( 'isNew', false );
 		var newAttr = new Attribute( 'isNew', true );
 
-		doc.root.children.push( new Character( doc.root, 'b', [ oldAttr ] ) );
-		doc.root.children.push( new Character( doc.root, 'a', [ oldAttr ] ) );
-		doc.root.children.push( new Character( doc.root, 'r', [ oldAttr ] ) );
+		doc.root.insertChildren( 0, [
+			new Character( 'b', [ oldAttr ] ),
+			new Character( 'a', [ oldAttr ] ),
+			new Character( 'r', [ oldAttr ] ) ] );
 
 		doc.applyOperation( new ChangeOperation(
 			new Range( new Position( [ 0 ], doc.root ), new Position( [ 2 ], doc.root ) ),
@@ -192,7 +189,7 @@ describe( 'ChangeOperation', function() {
 		var x2Attr = new Attribute( 'x', 2 );
 		var barAttr = new Attribute( 'bar', true );
 
-		doc.root.children.push( new Character( doc.root, 'x', [ fooAttr, x1Attr, barAttr ] ) );
+		doc.root.insertChildren( 0, new Character( 'x', [ fooAttr, x1Attr, barAttr ] ) );
 
 		doc.applyOperation( new ChangeOperation(
 			new Range( new Position( [ 0 ], doc.root ), new Position( [ 1 ], doc.root ) ),
@@ -222,7 +219,7 @@ describe( 'ChangeOperation', function() {
 		var xAttr = new Attribute( 'x', true );
 		var barAttr = new Attribute( 'bar', true );
 
-		doc.root.children.push( new Character( doc.root, 'x', [ fooAttr, xAttr, barAttr ] ) );
+		doc.root.insertChildren( 0, new Character( 'x', [ fooAttr, xAttr, barAttr ] ) );
 
 		doc.applyOperation( new ChangeOperation(
 			new Range( new Position( [ 0 ], doc.root ), new Position( [ 1 ], doc.root ) ),
@@ -249,9 +246,10 @@ describe( 'ChangeOperation', function() {
 
 		var fooAttr = new Attribute( 'foo', true );
 
-		doc.root.children.push( new Character( doc.root, 'b', [ fooAttr ] ) );
-		doc.root.children.push( new Character( doc.root, 'a', [ fooAttr ] ) );
-		doc.root.children.push( new Character( doc.root, 'r', [ fooAttr ] ) );
+		doc.root.insertChildren( 0, [
+			new Character( 'b', [ fooAttr ] ),
+			new Character( 'a', [ fooAttr ] ),
+			new Character( 'r', [ fooAttr ] ) ] );
 
 		doc.applyOperation( new ChangeOperation(
 			[
@@ -299,16 +297,13 @@ describe( 'ChangeOperation', function() {
 		var ChangeOperation = modules[ 'document/changeoperation' ];
 		var Position = modules[ 'document/position' ];
 		var Range = modules[ 'document/range' ];
-		var Character = modules[ 'document/character' ];
 		var Attribute = modules[ 'document/attribute' ];
 
 		var doc = new Document();
 
 		var newAttr = new Attribute( 'isNew', true );
 
-		doc.root.children.push( new Character( doc.root, 'b' ) );
-		doc.root.children.push( new Character( doc.root, 'a' ) );
-		doc.root.children.push( new Character( doc.root, 'r' ) );
+		doc.root.insertChildren( 0, 'bar' );
 
 		var oppertaion = new ChangeOperation(
 			new Range( new Position( [ 0 ], doc.root ), new Position( [ 3 ], doc.root ) ),
@@ -342,9 +337,10 @@ describe( 'ChangeOperation', function() {
 		var oldAttr = new Attribute( 'isNew', false );
 		var newAttr = new Attribute( 'isNew', true );
 
-		doc.root.children.push( new Character( doc.root, 'b', [ oldAttr ] ) );
-		doc.root.children.push( new Character( doc.root, 'a', [ oldAttr ] ) );
-		doc.root.children.push( new Character( doc.root, 'r', [ oldAttr ] ) );
+		doc.root.insertChildren( 0, [
+			new Character( 'b', [ oldAttr ] ),
+			new Character( 'a', [ oldAttr ] ),
+			new Character( 'r', [ oldAttr ] ) ] );
 
 		var oppertaion = new ChangeOperation(
 			new Range( new Position( [ 0 ], doc.root ), new Position( [ 3 ], doc.root ) ),
@@ -380,9 +376,10 @@ describe( 'ChangeOperation', function() {
 
 		var fooAttr = new Attribute( 'foo', false );
 
-		doc.root.children.push( new Character( doc.root, 'b', [ fooAttr ] ) );
-		doc.root.children.push( new Character( doc.root, 'a', [ fooAttr ] ) );
-		doc.root.children.push( new Character( doc.root, 'r', [ fooAttr ] ) );
+		doc.root.insertChildren( 0, [
+			new Character( 'b', [ fooAttr ] ),
+			new Character( 'a', [ fooAttr ] ),
+			new Character( 'r', [ fooAttr ] ) ] );
 
 		var oppertaion = new ChangeOperation(
 			new Range( new Position( [ 0 ], doc.root ), new Position( [ 3 ], doc.root ) ),
@@ -411,7 +408,6 @@ describe( 'ChangeOperation', function() {
 		var ChangeOperation = modules[ 'document/changeoperation' ];
 		var Position = modules[ 'document/position' ];
 		var Range = modules[ 'document/range' ];
-		var Character = modules[ 'document/character' ];
 		var Attribute = modules[ 'document/attribute' ];
 		var CKEditorError = modules.ckeditorerror;
 
@@ -419,7 +415,7 @@ describe( 'ChangeOperation', function() {
 
 		var fooAttr = new Attribute( 'foo', true );
 
-		doc.root.children.push( new Character( doc.root, 'x' ) );
+		doc.root.insertChildren( 0, 'x' );
 
 		expect( function() {
 			doc.applyOperation( new ChangeOperation(
@@ -444,7 +440,7 @@ describe( 'ChangeOperation', function() {
 		var x1Attr = new Attribute( 'x', 1 );
 		var x2Attr = new Attribute( 'x', 2 );
 
-		doc.root.children.push( new Character( doc.root, 'x', [ x1Attr ] ) );
+		doc.root.insertChildren( 0, new Character( 'x', [ x1Attr ] ) );
 
 		expect( function() {
 			doc.applyOperation( new ChangeOperation(
@@ -460,7 +456,6 @@ describe( 'ChangeOperation', function() {
 		var ChangeOperation = modules[ 'document/changeoperation' ];
 		var Position = modules[ 'document/position' ];
 		var Range = modules[ 'document/range' ];
-		var Character = modules[ 'document/character' ];
 		var Attribute = modules[ 'document/attribute' ];
 		var CKEditorError = modules.ckeditorerror;
 
@@ -469,7 +464,7 @@ describe( 'ChangeOperation', function() {
 		var fooAttr = new Attribute( 'foo', true );
 		var barAttr = new Attribute( 'bar', true );
 
-		doc.root.children.push( new Character( doc.root, 'x' ) );
+		doc.root.insertChildren( 0, 'x' );
 
 		expect( function() {
 			doc.applyOperation( new ChangeOperation(
@@ -485,7 +480,6 @@ describe( 'ChangeOperation', function() {
 		var ChangeOperation = modules[ 'document/changeoperation' ];
 		var Position = modules[ 'document/position' ];
 		var Range = modules[ 'document/range' ];
-		var Character = modules[ 'document/character' ];
 		var Attribute = modules[ 'document/attribute' ];
 		var CKEditorError = modules.ckeditorerror;
 
@@ -494,7 +488,7 @@ describe( 'ChangeOperation', function() {
 		var x1Attr = new Attribute( 'x', 1 );
 		var x2Attr = new Attribute( 'x', 2 );
 
-		doc.root.children.push( new Character( doc.root, 'x' ) );
+		doc.root.insertChildren( 0, 'x' );
 
 		expect( function() {
 			doc.applyOperation( new ChangeOperation(

+ 5 - 5
packages/ckeditor5-utils/tests/document/character.js

@@ -21,9 +21,8 @@ describe( 'constructor', function() {
 		var Character = modules[ 'document/character' ];
 		var Node = modules[ 'document/node' ];
 
-		var parent = new Element( null, 'parent' );
-
-		var character = new Character( parent, 'f' );
+		var character = new Character( 'f' );
+		var parent = new Element( 'parent', [], character );
 
 		expect( character ).to.be.an.instanceof( Node );
 		expect( character ).to.have.property( 'character' ).that.equals( 'f' );
@@ -37,10 +36,11 @@ describe( 'constructor', function() {
 		var Node = modules[ 'document/node' ];
 		var Attribute = modules[ 'document/attribute' ];
 
-		var parent = new Element( null, 'parent' );
 		var attr = new Attribute( 'key', 'value' );
 
-		var character = new Character( parent, 'f', [ attr ] );
+		var character = new Character( 'f', [ attr ] );
+
+		var parent = new Element( 'parent', [], character );
 
 		expect( character ).to.be.an.instanceof( Node );
 		expect( character ).to.have.property( 'character' ).that.equals( 'f' );

+ 34 - 5
packages/ckeditor5-utils/tests/document/element.js

@@ -19,9 +19,8 @@ describe( 'constructor', function() {
 		var Element = modules[ 'document/element' ];
 		var Node = modules[ 'document/node' ];
 
-		var parent = new Element( null, 'parent' );
-
-		var element = new Element( parent, 'elem' );
+		var element = new Element( 'elem' );
+		var parent = new Element( 'parent', [], [ element ] );
 
 		expect( element ).to.be.an.instanceof( Node );
 		expect( element ).to.have.property( 'name' ).that.equals( 'elem' );
@@ -34,10 +33,11 @@ describe( 'constructor', function() {
 		var Node = modules[ 'document/node' ];
 		var Attribute = modules[ 'document/attribute' ];
 
-		var parent = new Element( null, 'parent' );
 		var attr = new Attribute( 'key', 'value' );
 
-		var element = new Element( parent, 'elem', [ attr ] );
+		var element = new Element( 'elem', [ attr ] );
+
+		var parent = new Element( 'parent', [], [ element ] );
 
 		expect( element ).to.be.an.instanceof( Node );
 		expect( element ).to.have.property( 'name' ).that.equals( 'elem' );
@@ -45,4 +45,33 @@ describe( 'constructor', function() {
 		expect( element ).to.have.property( 'attrs' ).that.is.an( 'array' ).with.length( 1 );
 		expect( element.attrs[ 0 ] ).that.equals( attr );
 	} );
+
+	it( 'should create element with children', function() {
+		var Element = modules[ 'document/element' ];
+
+		var element = new Element( 'elem', [], 'foo' );
+
+		expect( element ).to.have.property( 'name' ).that.equals( 'elem' );
+		expect( element ).to.have.property( 'children' ).with.length( 3 );
+		expect( element.children.get( 0 ) ).to.have.property( 'character' ).that.equals( 'f' );
+		expect( element.children.get( 1 ) ).to.have.property( 'character' ).that.equals( 'o' );
+		expect( element.children.get( 2 ) ).to.have.property( 'character' ).that.equals( 'o' );
+	} );
+} );
+
+describe( 'insertChildren', function() {
+	it( 'should add children to the element', function() {
+		var Element = modules[ 'document/element' ];
+
+		var element = new Element( 'elem', [], [ 'xy' ] );
+		element.insertChildren( 1, 'foo' );
+
+		expect( element ).to.have.property( 'name' ).that.equals( 'elem' );
+		expect( element ).to.have.property( 'children' ).with.length( 5 );
+		expect( element.children.get( 0 ) ).to.have.property( 'character' ).that.equals( 'x' );
+		expect( element.children.get( 1 ) ).to.have.property( 'character' ).that.equals( 'f' );
+		expect( element.children.get( 2 ) ).to.have.property( 'character' ).that.equals( 'o' );
+		expect( element.children.get( 3 ) ).to.have.property( 'character' ).that.equals( 'o' );
+		expect( element.children.get( 4 ) ).to.have.property( 'character' ).that.equals( 'y' );
+	} );
 } );

+ 8 - 22
packages/ckeditor5-utils/tests/document/insertoperation.js

@@ -26,7 +26,7 @@ describe( 'InsertOperation', function() {
 
 		doc.applyOperation( new InsertOperation(
 			new Position( [ 0 ], doc.root ),
-			new Character( null, 'x' ),
+			new Character( 'x' ),
 			doc.version ) );
 
 		expect( doc.version ).to.be.equal( 1 );
@@ -38,14 +38,10 @@ describe( 'InsertOperation', function() {
 		var Document = modules[ 'document/document' ];
 		var InsertOperation = modules[ 'document/insertoperation' ];
 		var Position = modules[ 'document/position' ];
-		var Character = modules[ 'document/character' ];
 
 		var doc = new Document();
 
-		doc.applyOperation( new InsertOperation(
-			new Position( [ 0 ], doc.root ),
-			[ new Character( null, 'b' ), new Character( null, 'a' ), new Character( null, 'r' ) ],
-			doc.version ) );
+		doc.applyOperation( new InsertOperation( new Position( [ 0 ], doc.root ), 'bar', doc.version ) );
 
 		expect( doc.version ).to.be.equal( 1 );
 		expect( doc.root.children.length ).to.be.equal( 3 );
@@ -58,17 +54,12 @@ describe( 'InsertOperation', function() {
 		var Document = modules[ 'document/document' ];
 		var InsertOperation = modules[ 'document/insertoperation' ];
 		var Position = modules[ 'document/position' ];
-		var Character = modules[ 'document/character' ];
 
 		var doc = new Document();
 
-		doc.root.children.push( new Character( doc.root, 'x' ) );
-		doc.root.children.push( new Character( doc.root, 'y' ) );
+		doc.root.insertChildren( 0, 'xy' );
 
-		doc.applyOperation( new InsertOperation(
-			new Position( [ 1 ], doc.root ),
-			[ new Character( null, 'b' ), new Character( null, 'a' ), new Character( null, 'r' ) ],
-			doc.version ) );
+		doc.applyOperation( new InsertOperation( new Position( [ 1 ], doc.root ), 'bar', doc.version ) );
 
 		expect( doc.version ).to.be.equal( 1 );
 		expect( doc.root.children.length ).to.be.equal( 5 );
@@ -89,7 +80,7 @@ describe( 'InsertOperation', function() {
 
 		doc.applyOperation( new InsertOperation(
 			new Position( [ 0 ], doc.root ),
-			[ 'foo', new Character( null, 'x' ), 'bar' ],
+			[ 'foo', new Character( 'x' ), 'bar' ],
 			doc.version ) );
 
 		expect( doc.version ).to.be.equal( 1 );
@@ -108,12 +99,11 @@ describe( 'InsertOperation', function() {
 		var InsertOperation = modules[ 'document/insertoperation' ];
 		var RemoveOperation = modules[ 'document/removeoperation' ];
 		var Position = modules[ 'document/position' ];
-		var Character = modules[ 'document/character' ];
 		var NodeList = modules[ 'document/nodelist' ];
 
 		var doc = new Document();
 
-		var nodeList = new NodeList( [ new Character( null, 'b' ), new Character( null, 'a' ), new Character( null, 'r' ) ] );
+		var nodeList = new NodeList( 'bar' );
 		var position = new Position( [ 0 ], doc.root );
 
 		var operation = new InsertOperation( position, nodeList, 0 );
@@ -136,7 +126,7 @@ describe( 'InsertOperation', function() {
 
 		var operation = new InsertOperation(
 			new Position( [ 0 ], doc.root ),
-			new Character( null, 'x' ),
+			new Character( 'x' ),
 			doc.version );
 
 		var reverse = operation.reverseOperation();
@@ -155,14 +145,10 @@ describe( 'InsertOperation', function() {
 		var Document = modules[ 'document/document' ];
 		var InsertOperation = modules[ 'document/insertoperation' ];
 		var Position = modules[ 'document/position' ];
-		var Character = modules[ 'document/character' ];
 
 		var doc = new Document();
 
-		var operation = new InsertOperation(
-			new Position( [ 0 ], doc.root ),
-			[ new Character( null, 'b' ), new Character( null, 'a' ), new Character( null, 'r' ) ],
-			doc.version );
+		var operation = new InsertOperation( new Position( [ 0 ], doc.root ), 'bar', doc.version );
 
 		var reverse = operation.reverseOperation();
 

+ 9 - 26
packages/ckeditor5-utils/tests/document/moveoperation.js

@@ -24,13 +24,10 @@ describe( 'MoveOperation', function() {
 
 		var doc = new Document();
 
-		var p1 = new Element( doc.root, 'p1' );
-		var p2 = new Element( doc.root, 'p2' );
+		var p1 = new Element( 'p1', [], new Element( 'x' ) );
+		var p2 = new Element( 'p2' );
 
-		doc.root.children.push( p1 );
-		doc.root.children.push( p2 );
-
-		p1.children.push( new Element( doc.p1, 'x' ) );
+		doc.root.insertChildren( 0, [ p1, p2 ] );
 
 		doc.applyOperation( new MoveOperation(
 			new Position( [ 0, 0 ], doc.root ),
@@ -51,15 +48,10 @@ describe( 'MoveOperation', function() {
 		var Document = modules[ 'document/document' ];
 		var MoveOperation = modules[ 'document/moveoperation' ];
 		var Position = modules[ 'document/position' ];
-		var Character = modules[ 'document/character' ];
 
 		var doc = new Document();
 
-		doc.root.children.push( new Character( doc.root, 'x' ) );
-		doc.root.children.push( new Character( doc.root, 'b' ) );
-		doc.root.children.push( new Character( doc.root, 'a' ) );
-		doc.root.children.push( new Character( doc.root, 'r' ) );
-		doc.root.children.push( new Character( doc.root, 'x' ) );
+		doc.root.insertChildren( 0, 'xbarx' );
 
 		doc.applyOperation( new MoveOperation(
 			new Position( [ 2 ], doc.root ),
@@ -80,15 +72,10 @@ describe( 'MoveOperation', function() {
 		var Document = modules[ 'document/document' ];
 		var MoveOperation = modules[ 'document/moveoperation' ];
 		var Position = modules[ 'document/position' ];
-		var Character = modules[ 'document/character' ];
 
 		var doc = new Document();
 
-		doc.root.children.push( new Character( doc.root, 'x' ) );
-		doc.root.children.push( new Character( doc.root, 'b' ) );
-		doc.root.children.push( new Character( doc.root, 'a' ) );
-		doc.root.children.push( new Character( doc.root, 'r' ) );
-		doc.root.children.push( new Character( doc.root, 'x' ) );
+		doc.root.insertChildren( 0, 'xbarx' );
 
 		doc.applyOperation( new MoveOperation(
 			new Position( [ 1 ], doc.root ),
@@ -109,12 +96,11 @@ describe( 'MoveOperation', function() {
 		var Document = modules[ 'document/document' ];
 		var MoveOperation = modules[ 'document/moveoperation' ];
 		var Position = modules[ 'document/position' ];
-		var Character = modules[ 'document/character' ];
 		var NodeList = modules[ 'document/nodelist' ];
 
 		var doc = new Document();
 
-		var nodeList = new NodeList( [ new Character( doc.root, 'b' ), new Character( doc.root, 'a' ), new Character( doc.root, 'r' ) ] );
+		var nodeList = new NodeList( 'bar' );
 
 		var sourcePosition = new Position( [ 0 ], doc.root );
 		var targetPosition = new Position( [ 4 ], doc.root );
@@ -138,13 +124,10 @@ describe( 'MoveOperation', function() {
 
 		var doc = new Document();
 
-		var p1 = new Element( doc.root, 'p1' );
-		var p2 = new Element( doc.root, 'p2' );
-
-		doc.root.children.push( p1 );
-		doc.root.children.push( p2 );
+		var p1 = new Element( 'p1', [], new Element( 'x' ) );
+		var p2 = new Element( 'p2' );
 
-		p1.children.push( new Element( doc.p1, 'x' ) );
+		doc.root.insertChildren( 0, [ p1, p2 ] );
 
 		var operation =  new MoveOperation(
 			new Position( [ 0, 0 ], doc.root ),

+ 18 - 28
packages/ckeditor5-utils/tests/document/node.js

@@ -24,25 +24,16 @@ describe( 'tree', function() {
 		Element = modules[ 'document/element' ];
 		Character = modules[ 'document/character' ];
 
-		root = new Element();
+		charB = new Character( 'b' );
+		charA = new Character( 'a' );
+		img = new Element( 'img' );
+		charR = new Character( 'r' );
 
-		one = new Element( root );
-		two = new Element( root );
-		three = new Element( root );
+		one = new Element( 'one' );
+		two = new Element( 'two', null, [ charB, charA, img, charR ] );
+		three = new Element( 'three' );
 
-		charB = new Character( two, 'b' );
-		charA = new Character( two, 'a' );
-		img = new Element( two, 'img' );
-		charR = new Character( two, 'r' );
-
-		two.children.push( charB );
-		two.children.push( charA );
-		two.children.push( img );
-		two.children.push( charR );
-
-		root.children.push( one );
-		root.children.push( two );
-		root.children.push( three );
+		root = new Element( null, null, [ one, two, three ] );
 	} );
 
 	it( 'should have proper positionInParent', function() {
@@ -104,7 +95,7 @@ describe( 'getAttr', function() {
 		var Attribute = modules[ 'document/attribute' ];
 
 		var fooAttr = new Attribute( 'foo', true );
-		var element = new Element( null, 'foo', [ fooAttr ] );
+		var element = new Element( 'foo', [ fooAttr ] );
 
 		expect( element.getAttr( 'foo' ).isEqual( fooAttr ) ).to.be.true;
 	} );
@@ -114,7 +105,7 @@ describe( 'getAttr', function() {
 		var Attribute = modules[ 'document/attribute' ];
 
 		var fooAttr = new Attribute( 'foo', true );
-		var element = new Element( null, 'foo', [ fooAttr ] );
+		var element = new Element( 'foo', [ fooAttr ] );
 
 		expect( element.getAttr( 'bar' ) ).to.be.null;
 	} );
@@ -125,7 +116,7 @@ describe( 'getAttr', function() {
 
 		var fooAttr = new Attribute( 'foo', true );
 		var foo2Attr = new Attribute( 'foo', true );
-		var element = new Element( null, 'foo', [ fooAttr ] );
+		var element = new Element( 'foo', [ fooAttr ] );
 
 		expect( element.getAttr( foo2Attr ).isEqual( fooAttr ) ).to.be.true;
 	} );
@@ -135,7 +126,7 @@ describe( 'getAttr', function() {
 		var Attribute = modules[ 'document/attribute' ];
 
 		var fooAttr = new Attribute( 'foo', true );
-		var element = new Element( null, 'foo' );
+		var element = new Element( 'foo' );
 
 		expect( element.getAttr( fooAttr ) ).to.be.null;
 	} );
@@ -147,7 +138,7 @@ describe( 'hasAttr', function() {
 		var Attribute = modules[ 'document/attribute' ];
 
 		var fooAttr = new Attribute( 'foo', true );
-		var element = new Element( null, 'foo', [ fooAttr ] );
+		var element = new Element( 'foo', [ fooAttr ] );
 
 		expect( element.hasAttr( 'foo' ) ).to.be.true;
 	} );
@@ -157,7 +148,7 @@ describe( 'hasAttr', function() {
 		var Attribute = modules[ 'document/attribute' ];
 
 		var fooAttr = new Attribute( 'foo', true );
-		var element = new Element( null, 'foo', [ fooAttr ] );
+		var element = new Element( 'foo', [ fooAttr ] );
 
 		expect( element.hasAttr( 'bar' ) ).to.be.false;
 	} );
@@ -168,7 +159,7 @@ describe( 'hasAttr', function() {
 
 		var fooAttr = new Attribute( 'foo', true );
 		var foo2Attr = new Attribute( 'foo', true );
-		var element = new Element( null, 'foo', [ fooAttr ] );
+		var element = new Element( 'foo', [ fooAttr ] );
 
 		expect( element.hasAttr( foo2Attr ) ).to.be.true;
 	} );
@@ -178,7 +169,7 @@ describe( 'hasAttr', function() {
 		var Attribute = modules[ 'document/attribute' ];
 
 		var fooAttr = new Attribute( 'foo', true );
-		var element = new Element( null, 'foo' );
+		var element = new Element( 'foo' );
 
 		expect( element.hasAttr( fooAttr ) ).to.be.false;
 	} );
@@ -188,9 +179,8 @@ describe( 'hasAttr', function() {
 		var Character = modules[ 'document/character' ];
 		var NodeList = modules[ 'document/nodelist' ];
 
-		var foo = new Element( null, 'foo' );
-		var b = new Character( foo, 'b' );
-		foo.children.push( b );
+		var b = new Character( 'b' );
+		var foo = new Element( 'foo', [], [ b ] );
 
 		var parsedFoo = JSON.parse( JSON.stringify( foo ) );
 		var parsedBar = JSON.parse( JSON.stringify( b ) );

+ 19 - 2
packages/ckeditor5-utils/tests/document/nodelist.js

@@ -16,7 +16,7 @@ describe( 'constructor', function() {
 		var NodeList = modules[ 'document/nodelist' ];
 		var Character = modules[ 'document/character' ];
 
-		var nodeList = new NodeList( [ 'foo', new Character( null, 'x' ), 'bar' ] );
+		var nodeList = new NodeList( [ 'foo', new Character( 'x' ), 'bar' ] );
 
 		expect( nodeList.length ).to.be.equal( 7 );
 		expect( nodeList.get( 0 ).character ).to.be.equal( 'f' );
@@ -43,7 +43,7 @@ describe( 'constructor', function() {
 		var NodeList = modules[ 'document/nodelist' ];
 		var Character = modules[ 'document/character' ];
 
-		var nodeList = new NodeList( new Character( null, 'x' ) );
+		var nodeList = new NodeList( new Character( 'x' ) );
 
 		expect( nodeList.length ).to.be.equal( 1 );
 		expect( nodeList.get( 0 ).character ).to.be.equal( 'x' );
@@ -82,4 +82,21 @@ describe( 'remove', function() {
 		expect( nodeList.get( 1 ).character ).to.be.equal( 'o' );
 		expect( nodeList.get( 2 ).character ).to.be.equal( 'r' );
 	} );
+} );
+
+describe( 'iterator', function() {
+	it( 'should iterate over all elements in the collection', function() {
+		var NodeList = modules[ 'document/nodelist' ];
+
+		var characters = 'foo';
+		var nodeList = new NodeList( characters );
+		var i = 0;
+
+		for ( var node of nodeList ) {
+			expect( node.character ).to.be.equal( characters[ i ] );
+			i++;
+		}
+
+		expect( i ).to.be.equal( 3 );
+	} );
 } );

+ 25 - 35
packages/ckeditor5-utils/tests/document/position.js

@@ -12,10 +12,11 @@ var modules = bender.amd.require(
 	'document/character',
 	'document/position',
 	'document/document',
-	'ckeditorerror' );
+	'ckeditorerror',
+	'document/nodelist' );
 
 describe( 'position', function() {
-	var Element, Character, Document;
+	var Element, Character, Document, NodeList;
 
 	var doc, root, p, ul, li1, li2, f, o, z, b, a, r;
 
@@ -34,40 +35,29 @@ describe( 'position', function() {
 		Element = modules[ 'document/element' ];
 		Character = modules[ 'document/character' ];
 		Document = modules[ 'document/document' ];
+		NodeList = modules[ 'document/nodelist' ];
 
 		doc = new Document();
 
 		root = doc.root;
 
-		p = new Element( root, 'p' );
+		f = new Character( 'f' );
+		o = new Character( 'o' );
+		z = new Character( 'z' );
 
-		ul = new Element( root, 'ul' );
+		li1 = new Element( 'li', [], [ f, o, z ] );
 
-		li1 = new Element( ul, 'li' );
+		b = new Character( 'b' );
+		a = new Character( 'a' );
+		r = new Character( 'r' );
 
-		f = new Character( li1, 'f' );
-		o = new Character( li1, 'o' );
-		z = new Character( li1, 'z' );
+		li2 = new Element( 'li', [], [ b, a, r ] );
 
-		li2 = new Element( ul, 'li' );
+		ul = new Element( 'ul', [], [ li1, li2 ] );
 
-		b = new Character( li2, 'b' );
-		a = new Character( li2, 'a' );
-		r = new Character( li2, 'r' );
+		p = new Element( 'p' );
 
-		root.children.push( p );
-		root.children.push( ul );
-
-		ul.children.push( li1 );
-		ul.children.push( li2 );
-
-		li1.children.push( f );
-		li1.children.push( o );
-		li1.children.push( z );
-
-		li2.children.push( b );
-		li2.children.push( a );
-		li2.children.push( r );
+		root.insertChildren( 0, [ p, ul ] );
 	} );
 
 	it( 'should create a position with path and document', function() {
@@ -159,20 +149,20 @@ describe( 'position', function() {
 	it( 'should have parent', function() {
 		var Position = modules[ 'document/position' ];
 
-		// expect( new Position( [ 0 ], doc.root ) ).to.have.property( 'parent' ).that.equals( root );
-		// expect( new Position( [ 1 ], doc.root ) ).to.have.property( 'parent' ).that.equals( root );
-		// expect( new Position( [ 2 ], doc.root ) ).to.have.property( 'parent' ).that.equals( root );
+		expect( new Position( [ 0 ], doc.root ) ).to.have.property( 'parent' ).that.equals( root );
+		expect( new Position( [ 1 ], doc.root ) ).to.have.property( 'parent' ).that.equals( root );
+		expect( new Position( [ 2 ], doc.root ) ).to.have.property( 'parent' ).that.equals( root );
 
 		expect( new Position( [ 0, 0 ], doc.root ) ).to.have.property( 'parent' ).that.equals( p );
 
-		// expect( new Position( [ 1, 0 ], doc.root ) ).to.have.property( 'parent' ).that.equals( ul );
-		// expect( new Position( [ 1, 1 ], doc.root ) ).to.have.property( 'parent' ).that.equals( ul );
-		// expect( new Position( [ 1, 2 ], doc.root ) ).to.have.property( 'parent' ).that.equals( ul );
+		expect( new Position( [ 1, 0 ], doc.root ) ).to.have.property( 'parent' ).that.equals( ul );
+		expect( new Position( [ 1, 1 ], doc.root ) ).to.have.property( 'parent' ).that.equals( ul );
+		expect( new Position( [ 1, 2 ], doc.root ) ).to.have.property( 'parent' ).that.equals( ul );
 
-		// expect( new Position( [ 1, 0, 0 ], doc.root ) ).to.have.property( 'parent' ).that.equals( li1 );
-		// expect( new Position( [ 1, 0, 1 ], doc.root ) ).to.have.property( 'parent' ).that.equals( li1 );
-		// expect( new Position( [ 1, 0, 2 ], doc.root ) ).to.have.property( 'parent' ).that.equals( li1 );
-		// expect( new Position( [ 1, 0, 3 ], doc.root ) ).to.have.property( 'parent' ).that.equals( li1 );
+		expect( new Position( [ 1, 0, 0 ], doc.root ) ).to.have.property( 'parent' ).that.equals( li1 );
+		expect( new Position( [ 1, 0, 1 ], doc.root ) ).to.have.property( 'parent' ).that.equals( li1 );
+		expect( new Position( [ 1, 0, 2 ], doc.root ) ).to.have.property( 'parent' ).that.equals( li1 );
+		expect( new Position( [ 1, 0, 3 ], doc.root ) ).to.have.property( 'parent' ).that.equals( li1 );
 	} );
 
 	it( 'should have offset', function() {

+ 13 - 22
packages/ckeditor5-utils/tests/document/positioniterator.js

@@ -18,7 +18,7 @@ var modules = bender.amd.require(
 describe( 'range iterator', function() {
 	var doc, expectedItems;
 
-	var root, img1, paragraph, charB, charA, charR, img2, charX;
+	var root, img1, paragraph, b, a, r, img2, x;
 
 	var OPENING_TAG, CLOSING_TAG, CHARACTER;
 
@@ -46,37 +46,28 @@ describe( 'range iterator', function() {
 		//     |- img2
 		//     |
 		//     |- X
-		img1 = new Element( root, 'img1' );
-		root.children.push( img1 );
 
-		paragraph = new Element( root, 'p' );
-		root.children.push( paragraph );
+		b = new Character( 'b' );
+		a = new Character( 'a' );
+		r = new Character( 'r' );
+		img2 = new Element( 'img2' );
+		x = new Character( 'x' );
 
-		charB = new Character( paragraph, 'B' );
-		paragraph.children.push( charB );
+		paragraph = new Element( 'p', [], [ b, a, r, img2, x ] );
+		img1 = new Element( 'img1' );
 
-		charA = new Character( paragraph, 'A' );
-		paragraph.children.push( charA );
-
-		charR = new Character( paragraph, 'R' );
-		paragraph.children.push( charR );
-
-		img2 = new Element( paragraph, 'img2' );
-		paragraph.children.push( img2 );
-
-		charX = new Character( paragraph, 'X' );
-		paragraph.children.push( charX );
+		root.insertChildren( 0, [ img1, paragraph ] );
 
 		expectedItems = [
 				{ type: OPENING_TAG, node: img1 },
 				{ type: CLOSING_TAG, node: img1 },
 				{ type: OPENING_TAG, node: paragraph },
-				{ type: CHARACTER, node: charB },
-				{ type: CHARACTER, node: charA },
-				{ type: CHARACTER, node: charR },
+				{ type: CHARACTER, node: b },
+				{ type: CHARACTER, node: a },
+				{ type: CHARACTER, node: r },
 				{ type: OPENING_TAG, node: img2 },
 				{ type: CLOSING_TAG, node: img2 },
-				{ type: CHARACTER, node: charX },
+				{ type: CHARACTER, node: x },
 				{ type: CLOSING_TAG, node: paragraph }
 			];
 	} );

+ 9 - 21
packages/ckeditor5-utils/tests/document/removeoperation.js

@@ -20,11 +20,10 @@ describe( 'RemoveOperation', function() {
 		var Document = modules[ 'document/document' ];
 		var RemoveOperation = modules[ 'document/removeoperation' ];
 		var Position = modules[ 'document/position' ];
-		var Character = modules[ 'document/character' ];
 
 		var doc = new Document();
 
-		doc.root.children.push( new Character( doc.root, 'x' ) );
+		doc.root.insertChildren( 0, 'x' );
 
 		doc.applyOperation( new RemoveOperation(
 			new Position( [ 0 ], doc.root ),
@@ -39,13 +38,10 @@ describe( 'RemoveOperation', function() {
 		var Document = modules[ 'document/document' ];
 		var RemoveOperation = modules[ 'document/removeoperation' ];
 		var Position = modules[ 'document/position' ];
-		var Character = modules[ 'document/character' ];
 
 		var doc = new Document();
 
-		doc.root.children.push( new Character( doc.root, 'b' ) );
-		doc.root.children.push( new Character( doc.root, 'a' ) );
-		doc.root.children.push( new Character( doc.root, 'r' ) );
+		doc.root.insertChildren( 0, 'bar' );
 
 		doc.applyOperation( new RemoveOperation(
 			new Position( [ 0 ], doc.root ),
@@ -60,13 +56,10 @@ describe( 'RemoveOperation', function() {
 		var Document = modules[ 'document/document' ];
 		var RemoveOperation = modules[ 'document/removeoperation' ];
 		var Position = modules[ 'document/position' ];
-		var Character = modules[ 'document/character' ];
 
 		var doc = new Document();
 
-		doc.root.children.push( new Character( doc.root, 'b' ) );
-		doc.root.children.push( new Character( doc.root, 'a' ) );
-		doc.root.children.push( new Character( doc.root, 'r' ) );
+		doc.root.insertChildren( 0, 'bar' );
 
 		doc.applyOperation( new RemoveOperation(
 			new Position( [ 1 ], doc.root ),
@@ -84,17 +77,14 @@ describe( 'RemoveOperation', function() {
 		var InsertOperation = modules[ 'document/insertoperation' ];
 		var RemoveOperation = modules[ 'document/removeoperation' ];
 		var Position = modules[ 'document/position' ];
-		var Character = modules[ 'document/character' ];
 		var NodeList = modules[ 'document/nodelist' ];
 
 		var doc = new Document();
 
-		var nodeList = new NodeList( [ new Character( null, 'b' ), new Character( null, 'a' ), new Character( null, 'r' ) ] );
+		var nodeList = new NodeList( 'bar' );
 		var position = new Position( [ 0 ], doc.root );
 
-		doc.root.children.push( nodeList.get( 0 ) );
-		doc.root.children.push( nodeList.get( 1 ) );
-		doc.root.children.push( nodeList.get( 2 ) );
+		doc.root.insertChildren( 0, nodeList );
 
 		var operation = new RemoveOperation( position, nodeList, 0 );
 
@@ -110,18 +100,16 @@ describe( 'RemoveOperation', function() {
 		var Document = modules[ 'document/document' ];
 		var RemoveOperation = modules[ 'document/removeoperation' ];
 		var Position = modules[ 'document/position' ];
-		var Character = modules[ 'document/character' ];
+		var NodeList = modules[ 'document/nodelist' ];
 
 		var doc = new Document();
 
-		var nodes = [ new Character( null, 'b' ), new Character( null, 'a' ), new Character( null, 'r' ) ];
+		var nodeList = new NodeList( 'bar' );
 		var position = new Position( [ 0 ], doc.root );
 
-		doc.root.children.push( nodes[ 0 ] );
-		doc.root.children.push( nodes[ 1 ] );
-		doc.root.children.push( nodes[ 2 ] );
+		doc.root.insertChildren( 0, nodeList );
 
-		var operation = new RemoveOperation( position, nodes, 0 );
+		var operation = new RemoveOperation( position, nodeList, 0 );
 
 		var reverse = operation.reverseOperation();