81 lines
2.1 KiB
JavaScript
Executable File
81 lines
2.1 KiB
JavaScript
Executable File
"use strict";
|
|
module.exports = ContainerNode;
|
|
|
|
var Node = require('./Node');
|
|
var NodeList = require('./NodeList');
|
|
|
|
// This class defines common functionality for node subtypes that
|
|
// can have children
|
|
|
|
function ContainerNode() {
|
|
Node.call(this);
|
|
this._firstChild = this._childNodes = null;
|
|
}
|
|
|
|
// Primary representation is a circular linked list of siblings
|
|
ContainerNode.prototype = Object.create(Node.prototype, {
|
|
|
|
hasChildNodes: { value: function() {
|
|
if (this._childNodes) {
|
|
return this._childNodes.length > 0;
|
|
}
|
|
return this._firstChild !== null;
|
|
}},
|
|
|
|
childNodes: { get: function() {
|
|
this._ensureChildNodes();
|
|
return this._childNodes;
|
|
}},
|
|
|
|
firstChild: { get: function() {
|
|
if (this._childNodes) {
|
|
return this._childNodes.length === 0 ? null : this._childNodes[0];
|
|
}
|
|
return this._firstChild;
|
|
}},
|
|
|
|
lastChild: { get: function() {
|
|
var kids = this._childNodes, first;
|
|
if (kids) {
|
|
return kids.length === 0 ? null: kids[kids.length-1];
|
|
}
|
|
first = this._firstChild;
|
|
if (first === null) { return null; }
|
|
return first._previousSibling; // circular linked list
|
|
}},
|
|
|
|
_ensureChildNodes: { value: function() {
|
|
if (this._childNodes) { return; }
|
|
var first = this._firstChild,
|
|
kid = first,
|
|
childNodes = this._childNodes = new NodeList();
|
|
if (first) do {
|
|
childNodes.push(kid);
|
|
kid = kid._nextSibling;
|
|
} while (kid !== first); // circular linked list
|
|
this._firstChild = null; // free memory
|
|
}},
|
|
|
|
// Remove all of this node's children. This is a minor
|
|
// optimization that only calls modify() once.
|
|
removeChildren: { value: function removeChildren() {
|
|
var root = this.rooted ? this.ownerDocument : null,
|
|
next = this.firstChild,
|
|
kid;
|
|
while (next !== null) {
|
|
kid = next;
|
|
next = kid.nextSibling;
|
|
|
|
if (root) root.mutateRemove(kid);
|
|
kid.parentNode = null;
|
|
}
|
|
if (this._childNodes) {
|
|
this._childNodes.length = 0;
|
|
} else {
|
|
this._firstChild = null;
|
|
}
|
|
this.modify(); // Update last modified type once only
|
|
}},
|
|
|
|
});
|