diff --git a/package-lock.json b/package-lock.json
index 8364a5932..8098a1cdf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "marko",
- "version": "4.13.4",
+ "version": "4.13.4-4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index 070f3740a..af5593b72 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "marko",
- "version": "4.13.4",
+ "version": "4.13.4-4",
"license": "MIT",
"description": "UI Components + streaming, async, high performance, HTML templating for Node.js and the browser.",
"scripts": {
diff --git a/src/morphdom/fragment.js b/src/morphdom/fragment.js
index 11047bce6..8eb6be7ac 100644
--- a/src/morphdom/fragment.js
+++ b/src/morphdom/fragment.js
@@ -40,13 +40,13 @@ var fragmentPrototype = {
insertInto: function(newParentNode, referenceNode) {
this.nodes.forEach(function(node) {
insertBefore(node, referenceNode, newParentNode);
- });
+ }, this);
return this;
},
remove: function() {
this.nodes.forEach(function(node) {
this.detachedContainer.appendChild(node);
- });
+ }, this);
}
};
diff --git a/src/runtime/dom-insert.js b/src/runtime/dom-insert.js
index bebcb9197..6e5e44588 100644
--- a/src/runtime/dom-insert.js
+++ b/src/runtime/dom-insert.js
@@ -2,6 +2,11 @@ var extend = require("raptor-util/extend");
var componentsUtil = require("../components/util");
var destroyComponentForNode = componentsUtil.___destroyComponentForNode;
var destroyNodeRecursive = componentsUtil.___destroyNodeRecursive;
+var helpers = require("../morphdom/helpers");
+
+var insertBefore = helpers.___insertBefore;
+var insertAfter = helpers.___insertAfter;
+var removeChild = helpers.___removeChild;
function resolveEl(el) {
if (typeof el == "string") {
@@ -24,20 +29,21 @@ module.exports = function(target, getEl, afterInsert) {
appendTo: function(referenceEl) {
referenceEl = resolveEl(referenceEl);
var el = getEl(this, referenceEl);
- referenceEl.appendChild(el);
+ insertBefore(el, null, referenceEl);
return afterInsert(this, referenceEl);
},
prependTo: function(referenceEl) {
referenceEl = resolveEl(referenceEl);
var el = getEl(this, referenceEl);
- referenceEl.insertBefore(el, referenceEl.firstChild || null);
+ insertBefore(el, referenceEl.firstChild || null, referenceEl);
return afterInsert(this, referenceEl);
},
replace: function(referenceEl) {
referenceEl = resolveEl(referenceEl);
var el = getEl(this, referenceEl);
beforeRemove(referenceEl);
- referenceEl.parentNode.replaceChild(el, referenceEl);
+ insertBefore(el, referenceEl, referenceEl.parentNode);
+ removeChild(referenceEl);
return afterInsert(this, referenceEl);
},
replaceChildrenOf: function(referenceEl) {
@@ -52,25 +58,19 @@ module.exports = function(target, getEl, afterInsert) {
}
referenceEl.innerHTML = "";
- referenceEl.appendChild(el);
+ insertBefore(el, null, referenceEl);
return afterInsert(this, referenceEl);
},
insertBefore: function(referenceEl) {
referenceEl = resolveEl(referenceEl);
var el = getEl(this, referenceEl);
- referenceEl.parentNode.insertBefore(el, referenceEl);
+ insertBefore(el, referenceEl, referenceEl.parentNode);
return afterInsert(this, referenceEl);
},
insertAfter: function(referenceEl) {
referenceEl = resolveEl(referenceEl);
var el = getEl(this, referenceEl);
- var nextSibling = referenceEl.nextSibling;
- var parentNode = referenceEl.parentNode;
- if (nextSibling) {
- parentNode.insertBefore(el, nextSibling);
- } else {
- parentNode.appendChild(el);
- }
+ insertAfter(el, referenceEl, referenceEl.parentNode);
return afterInsert(this, referenceEl);
}
});
diff --git a/test/components-browser/fixtures/append-prepend/components/app-hello/index.marko b/test/components-browser/fixtures/append-prepend/components/app-hello/index.marko
new file mode 100644
index 000000000..2b1322cea
--- /dev/null
+++ b/test/components-browser/fixtures/append-prepend/components/app-hello/index.marko
@@ -0,0 +1,3 @@
+
+ Hello ${input.value}
+
diff --git a/test/components-browser/fixtures/append-prepend/index.marko b/test/components-browser/fixtures/append-prepend/index.marko
new file mode 100644
index 000000000..58133f769
--- /dev/null
+++ b/test/components-browser/fixtures/append-prepend/index.marko
@@ -0,0 +1,5 @@
+class {}
+
+
+ ref
+
\ No newline at end of file
diff --git a/test/components-browser/fixtures/append-prepend/test.js b/test/components-browser/fixtures/append-prepend/test.js
new file mode 100644
index 000000000..2077adbd6
--- /dev/null
+++ b/test/components-browser/fixtures/append-prepend/test.js
@@ -0,0 +1,15 @@
+var expect = require("chai").expect;
+
+module.exports = function(helpers) {
+ var component = helpers.mount(require.resolve("./index.marko"));
+ var hello = require("./components/app-hello");
+
+ var renderTarget = component.getEl("renderTarget");
+ expect(renderTarget.innerHTML).to.equal("ref");
+
+ hello.renderSync({ value: "before" }).prependTo(renderTarget);
+ hello.renderSync({ value: "after" }).appendTo(renderTarget);
+ expect(renderTarget.innerHTML).to.equal(
+ "Hello before
refHello after
"
+ );
+};
diff --git a/test/components-browser/fixtures/component-api-move-root/index.marko b/test/components-browser/fixtures/component-api-move-root/index.marko
new file mode 100644
index 000000000..d73fad23f
--- /dev/null
+++ b/test/components-browser/fixtures/component-api-move-root/index.marko
@@ -0,0 +1,10 @@
+class {
+ onCreate() {
+ this.state = { count:0 };
+ }
+ increment() {
+ this.state.count++;
+ }
+}
+
+-- Hello World ${state.count}
\ No newline at end of file
diff --git a/test/components-browser/fixtures/component-api-move-root/test.js b/test/components-browser/fixtures/component-api-move-root/test.js
new file mode 100644
index 000000000..705ac1e3c
--- /dev/null
+++ b/test/components-browser/fixtures/component-api-move-root/test.js
@@ -0,0 +1,14 @@
+var expect = require("chai").expect;
+
+module.exports = function(helpers) {
+ var component = helpers.mount(require.resolve("./index"), {});
+ var newTarget = document.createElement("div");
+ document.body.appendChild(newTarget);
+ component.increment();
+ component.update();
+ component.appendTo(newTarget);
+ expect(newTarget.innerHTML).to.equal("Hello World 1");
+ component.increment();
+ component.update();
+ expect(newTarget.innerHTML).to.equal("Hello World 2");
+};
diff --git a/test/components-browser/fixtures/insert-before-after/components/app-hello/index.marko b/test/components-browser/fixtures/insert-before-after/components/app-hello/index.marko
new file mode 100644
index 000000000..2b1322cea
--- /dev/null
+++ b/test/components-browser/fixtures/insert-before-after/components/app-hello/index.marko
@@ -0,0 +1,3 @@
+
+ Hello ${input.value}
+
diff --git a/test/components-browser/fixtures/insert-before-after/index.marko b/test/components-browser/fixtures/insert-before-after/index.marko
new file mode 100644
index 000000000..58133f769
--- /dev/null
+++ b/test/components-browser/fixtures/insert-before-after/index.marko
@@ -0,0 +1,5 @@
+class {}
+
+
+ ref
+
\ No newline at end of file
diff --git a/test/components-browser/fixtures/insert-before-after/test.js b/test/components-browser/fixtures/insert-before-after/test.js
new file mode 100644
index 000000000..331cdc5de
--- /dev/null
+++ b/test/components-browser/fixtures/insert-before-after/test.js
@@ -0,0 +1,16 @@
+var expect = require("chai").expect;
+
+module.exports = function(helpers) {
+ var component = helpers.mount(require.resolve("./index.marko"));
+ var hello = require("./components/app-hello");
+
+ var renderTarget = component.getEl("renderTarget");
+ var referenceElement = component.getEl("referenceElement");
+ expect(renderTarget.innerHTML).to.equal("ref");
+
+ hello.renderSync({ value: "before" }).insertBefore(referenceElement);
+ hello.renderSync({ value: "after" }).insertAfter(referenceElement);
+ expect(renderTarget.innerHTML).to.equal(
+ "Hello before
refHello after
"
+ );
+};