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 years ago
parent
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();