DocumentFragment: moveBefore() method
Limited availability
This feature is not Baseline because it does not work in some of the most widely-used browsers.
The moveBefore()
method of the DocumentFragment
interface moves a given Node
inside the invoking DocumentFragment
as a direct child, before a given reference node.
Syntax
moveBefore(movedNode, referenceNode)
Parameters
movedNode
-
A
Node
representing the node to be moved. referenceNode
-
A
Node
thatmovedNode
will be moved before, ornull
. If the value isnull
,movedNode
is inserted at the end of the invokingDocumentFragment
's child nodes.
Return value
None (undefined
).
Exceptions
HierarchyRequestError
TypeError
-
Thrown in either of the following situations:
- The specified
movedNode
is already added to the DOM, and you are trying to move it inside aDocumentFragment
. - You are trying to move
movedNode
between two different document fragments.
- The specified
NotFoundError
TypeError
-
The specified
referenceNode
is not a child of theDocumentFragment
you are callingmoveBefore()
on, that is, the fragment you are trying to movemovedNode
inside. TypeError
TypeError
-
The second argument was not supplied.
Description
The moveBefore()
method moves a given node to a new place in the DocumentFragment
. It provides similar functionality to the Node.insertBefore()
method, except that it doesn't remove and then reinsert the node. This means that the state of the node (which would be reset if moving it with insertBefore()
and similar mechanisms) is preserved after the move. This includes:
- Animation and transition state.
<iframe>
loading state.- Interactivity states (for example,
:focus
and:active
). - Fullscreen element state.
- Open/close state of popovers.
- Modal state of
<dialog>
elements (modal dialogs will not be closed).
The play state of <video>
and <audio>
elements is not included in the above list, as these elements retain their state when removed and reinserted, regardless of the mechanism used.
When observing changes to the DOM using a MutationObserver
, nodes moved with moveBefore()
will be recorded with a removed node and an added node.
moveBefore()
constraints
There are some constraints to be aware of when using moveBefore()
:
- It can only work when moving a node within the same document fragment.
- It won't work if you try to move a node that is already added to the DOM inside a
DocumentFragment
.
In such cases, moveBefore()
will fail with a HierarchyRequestError
exception. If the above constraints are requirements for your particular use case, you should use Node.insertBefore()
instead, or use try...catch
to handle the errors that arise from such cases.
Examples
Basic moveBefore()
usage
In this demo we illustrate basic usage of moveBefore()
.
HTML
The HTML features three <button>
elements, and an <article>
element. We will use the buttons to control inserting DocumentFragment
instances into the <article>
and emptying it.
<button id="insert1">Insert fragment</button>
<button id="insert2">Insert modified fragment</button>
<button id="clear">Clear</button>
<article id="wrapper"></article>
CSS
We provide some rudimentary styling for the look and feel and spacing of elements that will later be inserted into the page as children of JavaScript-generated DocumentFragment
s.
#section1,
#section2,
#mover {
display: inline-block;
width: 200px;
height: 30px;
border: 5px solid rgb(0 0 0 / 0.25);
margin-top: 10px;
}
#section1,
#section2 {
background-color: hotpink;
}
#mover {
background-color: orange;
}
JavaScript
In our script, we define a function, createFragment()
, which creates a DocumentFragment
containing a <div>
element and two <section>
elements as immediate children.
We then attach a click event listener to each <button>
via addEventListener()
:
- The first button appends the
DocumentFragment
to the#wrapper
<article>
element, unmodified. - The second button appends the
DocumentFragment
to the#wrapper
<article>
element, but first usesmoveBefore()
to move the<div>
to be the second child of theDocumentFragment
rather than the first. - The third button empties the
#wrapper
<article>
element usinginnerHTML
.
const wrapper = document.getElementById("wrapper");
const insertBtn1 = document.getElementById("insert1");
const insertBtn2 = document.getElementById("insert2");
const clearBtn = document.getElementById("clear");
function createFragment() {
const fragment = new DocumentFragment();
const divElem = document.createElement("div");
const section1 = document.createElement("section");
const section2 = document.createElement("section");
divElem.id = "mover";
section1.id = "section1";
section2.id = "section2";
fragment.appendChild(divElem);
fragment.appendChild(section1);
fragment.appendChild(section2);
return fragment;
}
insertBtn1.addEventListener("click", () => {
const fragment = createFragment();
wrapper.appendChild(fragment);
});
insertBtn2.addEventListener("click", () => {
const fragment = createFragment();
fragment.moveBefore(
fragment.querySelector("#mover"),
fragment.querySelector("#section2"),
);
wrapper.appendChild(fragment);
});
clearBtn.addEventListener("click", () => {
wrapper.innerHTML = "";
});
Result
The rendered example looks like this:
Try clicking the first two buttons a few times and note how the DocumentFragment
structure is modified by the second button.
Specifications
Specification |
---|
DOM # dom-parentnode-movebefore |