Links
- Spec
- https://dom.spec.whatwg.org/
Internal links
Serialize DOM XML
Here’s how to serialize the root document element.
const serializer = new XMLSerializer();
const str = serializer.serializeToString(document.documentElement);
Here’s a way to serialize a document and copy it to the clipboard:
const serializer = new XMLSerializer();
const str = serializer.serializeToString(document.documentElement);
async function writeClipboardText(text) {
try {
await navigator.clipboard.writeText(text);
} catch (error) {
console.error(error.message);
}
}
async function copyxml(event) {
const element2serialize = this;
console.log(`I was clicked`);
const serializer = new XMLSerializer();
const str = serializer.serializeToString(element2serialize);
await writeClipboardText(str);
console.log(`Serialized to clipboard`);
}
function serializeOnClick(el) {
el.addEventListener("click", copyxml, { once: true });
}
Parse DOM
Here’s an example of how to fetch and parse some external XHTML:
const fetchXhtmlDocument = async (url) => {
const res = await fetch(url);
const doc = (new DOMParser()).parseFromString(await res.text(), "application/xhtml+xml");
return doc;
};
XHTML templates
Maybe you’re in a non-XML-serialized HTML document, but you want to make a <template/>
element with XML syntax so your self-closing tags work.
Here’s a function that’ll take in a string and return a DocumentFragment
which you can clone.
function jmmXhtmlFragment(innerHTML) {
return Object.assign(document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", null).createElement('template'), { innerHTML }).content;
};
And here’s how to use it:
// Make a DocumentFragment which you can clone.
df1 = jmmXhtmlFragment(`<b/>This text should not be bold.`);
document.body.append(df1.cloneNode(true));
// If you don’t clone the fragment, it can only be appended once.
document.body.append(df1.cloneNode(true));
More recent DOM APIs
Like, instead of using Node.appendChild()
, you might find Element.append()
to be more ergonomic.
Element.append()
Element.prepend()
Element.before()
Element.after()
Element.replaceChildren()
Element.replaceWith()
Miscellaneous cheatsheet
Function or Property | What it does | Example |
---|---|---|
Element.closest() |
Find nearest ancestor that fulfills some selector. | |
Element.querySelector() |
Find some descendant that matches the CSS selector. | |
Element.classList |
Way to set and remove classes programmatically. |
|
Node.ownerDocument |
Get the Document of the node (sometimes you’re working with multiple documents, like if you have an <iframe/> ).
| |
Document.defaultView |
Get the Window of a Document .
|
Removing and restoring a DOM node
Use case: Imagine someone has CSS turned off.
Normally, let’s say you have a progress bar that’s shown during some action.
When that action isn’t happening, you hide the progress bar with CSS (with something like display: none;
).
People with CSS turned off will still see this thing.
So, instead maybe you want to remove a node completely when it’s not important, and then restore it when necessary.
Note: it seems like the actual right way to do this is to set the HTML hidden
attribute (see MDN’s documentation on HTMLElement hidden attribute).
// Probably preferred way of setting hidden:
someelement.hidden = true;
// Now to unhide it:
someelement.hidden = false;
// Other ways of setting hidden.
someelement.setAttribute("hidden", "true");
// It’s a boolean attribute, so this actually doesn’t work.
// someelement.setAttribute("hidden", "false");
someelement.removeAttribute("hidden");
Let’s say for some reason you don’t want to use the hidden
attribute.
Maybe you’re not using an HTML document, but rather something like SVG or just XML.
Here’s how you can remove and restore an element by using a Range
.
/// Remove and restoring a DOM node
let element1 = document.querySelector("#JID-ZaZ7YZ");
let range1 = element1.ownerDocument.createRange();
range1.selectNode(element1);
// Take out the element, giving you a DocumentFragment.
let df1 = range1.extractContents();
// Now restore it. insertNode can also accept a DocumentFragment.
range1.insertNode(df1);
// If it’s just one element you’re interested in, you don’t have to save the extracted contents.
element1.remove();
// Restore it.
range1.insertNode(element1);
// It seems to be idempotent, so doing this again is fine.
range1.insertNode(element1);