diff --git a/demo/index.html b/demo/index.html
index f814a5fd0c..489ea1dab7 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -69,8 +69,9 @@
-
+
+
diff --git a/modules/es/bases/es.DocumentBranchNode.js b/modules/es/bases/es.DocumentBranchNode.js
index daac352bc3..e26c758f74 100644
--- a/modules/es/bases/es.DocumentBranchNode.js
+++ b/modules/es/bases/es.DocumentBranchNode.js
@@ -12,6 +12,17 @@ es.DocumentBranchNode = function( nodes ) {
/* Methods */
+/**
+ * Checks if this node has child nodes.
+ *
+ * @method
+ * @see {es.DocumentNode.prototype.hasChildren}
+ * @returns {Boolean} Whether this node has children
+ */
+es.DocumentBranchNode.prototype.hasChildren = function() {
+ return true;
+};
+
/**
* Gets a list of child nodes.
*
@@ -33,21 +44,21 @@ es.DocumentBranchNode.prototype.getChildren = function() {
*/
es.DocumentBranchNode.prototype.getRangeFromNode = function( node, shallow ) {
if ( this.children.length ) {
- var isBranch;
+ var childNode;
for ( var i = 0, length = this.children.length, left = 0; i < length; i++ ) {
- if ( this.children[i] === node ) {
- return new es.Range( left, left + this.children[i].getElementLength() );
+ childNode = this.children[i];
+ if ( childNode === node ) {
+ return new es.Range( left, left + childNode.getElementLength() );
}
- isBranch = typeof this.children[i].getChildren === 'function';
- if ( !shallow && isBranch && this.children[i].getChildren().length ) {
- var range = this.children[i].getRangeFromNode( node );
+ if ( !shallow && childNode.hasChildren() && childNode.getChildren().length ) {
+ var range = childNode.getRangeFromNode( node );
if ( range !== null ) {
// Include opening of parent
left++;
return es.Range.newFromTranslatedRange( range, left );
}
}
- left += this.children[i].getElementLength();
+ left += childNode.getElementLength();
}
}
return null;
@@ -69,19 +80,19 @@ es.DocumentBranchNode.prototype.getRangeFromNode = function( node, shallow ) {
es.DocumentBranchNode.prototype.getOffsetFromNode = function( node, shallow ) {
if ( this.children.length ) {
var offset = 0,
- isBranch;
+ childNode;
for ( var i = 0, length = this.children.length; i < length; i++ ) {
- if ( this.children[i] === node ) {
+ childNode = this.children[i];
+ if ( childNode === node ) {
return offset;
}
- isBranch = typeof this.children[i].getChildren === 'function';
- if ( !shallow && isBranch && this.children[i].getChildren().length ) {
- var childOffset = this.getOffsetFromNode.call( this.children[i], node );
+ if ( !shallow && childNode.hasChildren() && childNode.getChildren().length ) {
+ var childOffset = this.getOffsetFromNode.call( childNode, node );
if ( childOffset !== -1 ) {
return offset + 1 + childOffset;
}
}
- offset += this.children[i].getElementLength();
+ offset += childNode.getElementLength();
}
}
return -1;
@@ -105,20 +116,20 @@ es.DocumentBranchNode.prototype.getNodeFromOffset = function( offset, shallow )
if ( this.children.length ) {
var nodeOffset = 0,
nodeLength,
- isBranch;
+ childNode;
for ( var i = 0, length = this.children.length; i < length; i++ ) {
+ childNode = this.children[i];
if ( offset == nodeOffset ) {
- // The requested offset is right before this.children[i],
+ // The requested offset is right before childNode,
// so it's not inside any of this's children, but inside this
return this;
}
- nodeLength = this.children[i].getElementLength();
+ nodeLength = childNode.getElementLength();
if ( offset >= nodeOffset && offset < nodeOffset + nodeLength ) {
- isBranch = typeof this.children[i].getChildren === 'function';
- if ( !shallow && isBranch && this.children[i].getChildren().length ) {
- return this.getNodeFromOffset.call( this.children[i], offset - nodeOffset - 1 );
+ if ( !shallow && childNode.hasChildren() && childNode.getChildren().length ) {
+ return this.getNodeFromOffset.call( childNode, offset - nodeOffset - 1 );
} else {
- return this.children[i];
+ return childNode;
}
}
nodeOffset += nodeLength;
@@ -155,7 +166,8 @@ es.DocumentBranchNode.prototype.selectNodes = function( range, shallow ) {
start = range.start,
end = range.end,
startInside,
- endInside;
+ endInside,
+ childNode;
if ( start < 0 ) {
throw 'The start offset of the range is negative';
@@ -173,20 +185,21 @@ es.DocumentBranchNode.prototype.selectNodes = function( range, shallow ) {
// This node has children, loop over them
left = 1; // First offset inside the first child. Offset 0 is before the first child
for ( i = 0; i < this.children.length; i++ ) {
- // left <= any offset inside this.children[i] <= right
- right = left + this.children[i].getContentLength();
+ childNode = this.children[i];
+ // left <= any offset inside childNode <= right
+ right = left + childNode.getContentLength();
if ( start == end && ( start == left - 1 || start == right + 1 ) ) {
// Empty range outside of any node
return [];
}
- startInside = start >= left && start <= right; // is the start inside this.children[i]?
- endInside = end >= left && end <= right; // is the end inside this.children[i]?
+ startInside = start >= left && start <= right; // is the start inside childNode?
+ endInside = end >= left && end <= right; // is the end inside childNode?
if ( startInside && endInside ) {
- // The range is entirely inside this.children[i]
- if ( shallow || !this.children[i].children ) {
+ // The range is entirely inside childNode
+ if ( shallow || !childNode.children ) {
// For leaf nodes, use the same behavior as for shallow calls.
// A proper recursive function would let the recursion handle this,
// but the leaves don't have .selectNodes() because they're not DocumentBranchNodes
@@ -194,14 +207,14 @@ es.DocumentBranchNode.prototype.selectNodes = function( range, shallow ) {
// TODO should probably rewrite this recursive function as an iterative function anyway, probably faster
nodes = [
{
- 'node': this.children[i],
+ 'node': childNode,
'range': new es.Range( start - left, end - left ),
'globalRange': new es.Range( start, end )
}
];
} else {
- // Recurse into this.children[i]
- nodes = this.children[i].selectNodes( new es.Range( start - left, end - left ) );
+ // Recurse into childNode
+ nodes = childNode.selectNodes( new es.Range( start - left, end - left ) );
// Adjust globalRange
for ( j = 0; j < nodes.length; j++ ) {
if ( nodes[j].globalRange !== undefined ) {
@@ -209,48 +222,48 @@ es.DocumentBranchNode.prototype.selectNodes = function( range, shallow ) {
}
}
}
- // Since the start and end are both inside this.children[i], we know for sure that we're
+ // Since the start and end are both inside childNode, we know for sure that we're
// done, so return
return nodes;
} else if ( startInside ) {
- // The start is inside this.children[i] but the end isn't
- // Add a range from the start of the range to the end of this.children[i]
+ // The start is inside childNode but the end isn't
+ // Add a range from the start of the range to the end of childNode
nodes.push( {
- 'node': this.children[i],
+ 'node': childNode,
'range': new es.Range( start - left, right - left ),
'globalRange': new es.Range( start, right )
} );
} else if ( endInside ) {
- // The end is inside this.children[i] but the start isn't
- // Add a range from the start of this.children[i] to the end of the range
+ // The end is inside childNode but the start isn't
+ // Add a range from the start of childNode to the end of the range
nodes.push( {
- 'node': this.children[i],
+ 'node': childNode,
'range': new es.Range( 0, end - left ),
'globalRange': new es.Range( left, end )
} );
// We've found the end, so we're done
return nodes;
} else if ( end == right + 1 ) {
- // end is between this.children[i] and this.children[i+1]
- // start is not inside this.children[i], so the selection covers
- // all of this.children[i], then ends
- nodes.push( { 'node': this.children[i] } );
+ // end is between childNode and this.children[i+1]
+ // start is not inside childNode, so the selection covers
+ // all of childNode, then ends
+ nodes.push( { 'node': childNode } );
// We've reached the end so we're done
return nodes;
} else if ( start == left - 1 ) {
- // start is between this.children[i-1] and this.children[i]
- // end is not inside this.children[i], so the selection covers
- // all of this.children[i] and more
- nodes.push( { 'node': this.children[i] } );
+ // start is between this.children[i-1] and childNode
+ // end is not inside childNode, so the selection covers
+ // all of childNode and more
+ nodes.push( { 'node': childNode } );
} else if ( nodes.length > 0 ) {
- // Neither the start nor the end is inside this.children[i], but nodes is non-empty,
- // so this.children[i] must be between the start and the end
+ // Neither the start nor the end is inside childNode, but nodes is non-empty,
+ // so childNode must be between the start and the end
// Add the entire node, so no range property
- nodes.push( { 'node': this.children[i] } );
+ nodes.push( { 'node': childNode } );
}
// Move left to the start of this.children[i+1] for the next iteration
- // We use +2 because we need to jump over the offset between this.children[i] and
+ // We use +2 because we need to jump over the offset between childNode and
// this.children[i+1]
left = right + 2;
if ( end < left ) {
diff --git a/modules/es/bases/es.DocumentLeafNode.js b/modules/es/bases/es.DocumentLeafNode.js
new file mode 100644
index 0000000000..3df2ca488d
--- /dev/null
+++ b/modules/es/bases/es.DocumentLeafNode.js
@@ -0,0 +1,23 @@
+/**
+ * Creates an es.DocumentLeafNode object.
+ *
+ * @class
+ * @abstract
+ * @constructor
+ */
+es.DocumentLeafNode = function() {
+ //
+};
+
+/* Methods */
+
+/**
+ * Checks if this node has child nodes.
+ *
+ * @method
+ * @see {es.DocumentNode.prototype.hasChildren}
+ * @returns {Boolean} Whether this node has children
+ */
+es.DocumentLeafNode.prototype.hasChildren = function() {
+ return false;
+};
diff --git a/modules/es/bases/es.DocumentModelBranchNode.js b/modules/es/bases/es.DocumentModelBranchNode.js
index 28593e67b8..faccc97966 100644
--- a/modules/es/bases/es.DocumentModelBranchNode.js
+++ b/modules/es/bases/es.DocumentModelBranchNode.js
@@ -4,16 +4,16 @@
* @class
* @abstract
* @constructor
- * @extends {es.DocumentModelNode}
* @extends {es.DocumentBranchNode}
+ * @extends {es.DocumentModelNode}
* @param {String} type Symbolic name of node type
* @param {Object} element Element object in document data
* @param {es.DocumentModelBranchNode[]} [contents] List of child nodes to append
*/
es.DocumentModelBranchNode = function( type, element, contents ) {
// Inheritance
- es.DocumentModelNode.call( this, type, element, 0 );
es.DocumentBranchNode.call( this );
+ es.DocumentModelNode.call( this, type, element, 0 );
// Child nodes
if ( es.isArray( contents ) ) {
@@ -240,5 +240,5 @@ es.DocumentModelBranchNode.prototype.clearRoot = function() {
/* Inheritance */
-es.extendClass( es.DocumentModelBranchNode, es.DocumentModelNode );
es.extendClass( es.DocumentModelBranchNode, es.DocumentBranchNode );
+es.extendClass( es.DocumentModelBranchNode, es.DocumentModelNode );
diff --git a/modules/es/bases/es.DocumentModelLeafNode.js b/modules/es/bases/es.DocumentModelLeafNode.js
index 06e64fdd46..bb7545da80 100644
--- a/modules/es/bases/es.DocumentModelLeafNode.js
+++ b/modules/es/bases/es.DocumentModelLeafNode.js
@@ -4,14 +4,15 @@
* @class
* @abstract
* @constructor
+ * @extends {es.DocumentLeafNode}
* @extends {es.DocumentModelNode}
- * @extends {es.DocumentNode}
* @param {String} type Symbolic name of node type
* @param {Object} element Element object in document data
* @param {Integer} [length] Length of content data in document
*/
es.DocumentModelLeafNode = function( type, element, length ) {
// Inheritance
+ es.DocumentLeafNode.call( this );
es.DocumentModelNode.call( this, type, element, length );
// Properties
@@ -80,4 +81,5 @@ es.DocumentModelLeafNode.prototype.getText = function( range ) {
/* Inheritance */
+es.extendClass( es.DocumentModelLeafNode, es.DocumentLeafNode );
es.extendClass( es.DocumentModelLeafNode, es.DocumentModelNode );
diff --git a/modules/es/bases/es.DocumentNode.js b/modules/es/bases/es.DocumentNode.js
index d8f781e583..5689ad0f61 100644
--- a/modules/es/bases/es.DocumentNode.js
+++ b/modules/es/bases/es.DocumentNode.js
@@ -23,6 +23,7 @@ es.DocumentNode = function() {
* Gets the content length.
*
* @method
+ * @abstract
* @returns {Integer} Length of content
*/
es.DocumentNode.prototype.getContentLength = function() {
@@ -33,12 +34,24 @@ es.DocumentNode.prototype.getContentLength = function() {
* Gets the element length.
*
* @method
+ * @abstract
* @returns {Integer} Length of content
*/
es.DocumentNode.prototype.getElementLength = function() {
throw 'DocumentNode.getElementLength not implemented in this subclass:' + this.constructor;
};
+/**
+ * Checks if this node has child nodes.
+ *
+ * @method
+ * @abstract
+ * @returns {Boolean} Whether this node has children
+ */
+es.DocumentNode.prototype.hasChildren = function() {
+ throw 'DocumentNode.hasChildren not implemented in this subclass:' + this.constructor;
+};
+
/* Inheritance */
es.extendClass( es.DocumentNode, es.EventEmitter );
diff --git a/modules/es/bases/es.DocumentViewBranchNode.js b/modules/es/bases/es.DocumentViewBranchNode.js
index 759aea7401..9e4f0cfebe 100644
--- a/modules/es/bases/es.DocumentViewBranchNode.js
+++ b/modules/es/bases/es.DocumentViewBranchNode.js
@@ -4,15 +4,15 @@
* @class
* @abstract
* @constructor
- * @extends {es.DocumentViewNode}
* @extends {es.DocumentBranchNode}
+ * @extends {es.DocumentViewNode}
* @param model {es.ModelNode} Model to observe
* @param {jQuery} [$element] Element to use as a container
*/
es.DocumentViewBranchNode = function( model, $element, horizontal ) {
// Inheritance
- es.DocumentViewNode.call( this, model, $element );
es.DocumentBranchNode.call( this );
+ es.DocumentViewNode.call( this, model, $element );
// Properties
this.horizontal = horizontal || false;
@@ -243,5 +243,5 @@ es.DocumentViewBranchNode.prototype.getRenderedLineRangeFromOffset = function( o
/* Inheritance */
-es.extendClass( es.DocumentViewBranchNode, es.DocumentViewNode );
es.extendClass( es.DocumentViewBranchNode, es.DocumentBranchNode );
+es.extendClass( es.DocumentViewBranchNode, es.DocumentViewNode );
diff --git a/modules/es/bases/es.DocumentViewLeafNode.js b/modules/es/bases/es.DocumentViewLeafNode.js
index 99ff366254..6dea945a44 100644
--- a/modules/es/bases/es.DocumentViewLeafNode.js
+++ b/modules/es/bases/es.DocumentViewLeafNode.js
@@ -4,12 +4,14 @@
* @class
* @abstract
* @constructor
+ * @extends {es.DocumentLeafNode}
* @extends {es.DocumentViewNode}
* @param model {es.ModelNode} Model to observe
* @param {jQuery} [$element] Element to use as a container
*/
es.DocumentViewLeafNode = function( model, $element ) {
// Inheritance
+ es.DocumentLeafNode.call( this );
es.DocumentViewNode.call( this, model, $element );
// Properties
@@ -80,4 +82,5 @@ es.DocumentViewLeafNode.prototype.getRenderedLineRangeFromOffset = function( off
/* Inheritance */
+es.extendClass( es.DocumentViewLeafNode, es.DocumentLeafNode );
es.extendClass( es.DocumentViewLeafNode, es.DocumentViewNode );
diff --git a/tests/es/index.html b/tests/es/index.html
index c0872c5567..abdaf8bd01 100644
--- a/tests/es/index.html
+++ b/tests/es/index.html
@@ -23,8 +23,9 @@
-
+
+