Marko v3: Better handling of detaching and moving child nodes

This commit is contained in:
Patrick Steele-Idem 2016-02-08 17:03:02 -07:00
parent 4b3c738a8d
commit e576718d11
5 changed files with 61 additions and 3 deletions

View File

@ -162,9 +162,16 @@ class Generator {
typeof node === 'boolean') {
this.write(node);
return;
} else if (isArray(node) || (node instanceof Container)) {
} else if (isArray(node)) {
node.forEach(this.generateCode, this);
return;
} else if (node instanceof Container) {
node.forEach((child) => {
if (child.container === node) {
this.generateCode(child);
}
});
return;
}
let oldCurrentNode = this._currentNode;

View File

@ -29,7 +29,7 @@ class ArrayContainer extends Container {
var curChild = array[i];
if (curChild === oldChild) {
array[i] = newChild;
oldChild.container = null;
oldChild.detach();
newChild.container = this;
return true;
}
@ -42,8 +42,11 @@ class ArrayContainer extends Container {
var childIndex = this.array.indexOf(child);
if (childIndex !== -1) {
this.array.splice(childIndex, 1);
child.detach();
return true;
} else {
return false;
}
child.container = null;
}
prependChild(newChild) {
@ -54,6 +57,7 @@ class ArrayContainer extends Container {
appendChild(newChild) {
ok(newChild, 'Invalid child');
newChild.detach();
this.array.push(newChild);
newChild.container = this;
}
@ -92,6 +96,20 @@ class ArrayContainer extends Container {
throw new Error('Reference node not found');
}
moveChildrenTo(target) {
ok(target.appendChild, 'Node does not support appendChild(node): ' + target);
var array = this.array;
var len = array.length;
for (var i=0; i<len; i++) {
var curChild = array[i];
curChild.container = null; // Detach the child from this container
target.appendChild(curChild);
}
this.array.length = 0; // Clear out this container
}
forEachNextSibling(node, callback, thisObj) {
if (node.container !== this) {
throw new Error('Node does not belong to container: ' + node);

View File

@ -108,6 +108,13 @@ class Node {
}
}
moveChildrenTo(targetNode) {
ok(this.body, 'Node does not support child nodes: ' + this);
ok(this !== targetNode, 'Target node cannot be the same as the source node');
this.body.moveChildrenTo(targetNode);
}
forEachNextSibling(callback, thisObj) {
var container = this.container;
@ -146,6 +153,7 @@ class Node {
detach() {
if (this.container) {
this.container.removeChild(this);
this.container = null;
}
}

View File

@ -0,0 +1 @@
out.w("<div></div><span>FooHello World</span>");

View File

@ -0,0 +1,24 @@
'use strict';
module.exports = function(builder) {
var div = builder.htmlElement(
'div',
[],
[
builder.text(builder.literal('Hello World'))
]);
var span = builder.htmlElement(
'span',
[],
[
builder.text(builder.literal('Foo'))
]);
div.moveChildrenTo(span);
return [
div,
span
];
};