Skip to content

Instantly share code, notes, and snippets.

@galanggg
Created October 20, 2024 03:09
Show Gist options
  • Save galanggg/ed11823dd9540c6a3a1d00a8bce3d92b to your computer and use it in GitHub Desktop.
Save galanggg/ed11823dd9540c6a3a1d00a8bce3d92b to your computer and use it in GitHub Desktop.
Mutation Observer Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Frontend System Design Fundamentals</title>
<link rel="stylesheet" href="../../styles/index.css">
<template id="card_template">
<article class="card">
<h3 class="card__title"></h3>
<div class="card__body">
<div class='card__body__image'></div>
<section contenteditable="true" class='card__body__content'>
</section>
</div>
</article>
</template>
</head>
<body>
<main id="container">
<div id="list"></div>
<div id="bottom-observer">
Bottom Observer
</div>
</main>
<script type="module">
import {createCardElement, getHeading} from "./utils.js";
import {initMockDB} from "../../utils/db.js";
const SUPPORTED_ELEMENTS = new Set([
'/h1',
'/h2',
'/h3',
'/p',
'/li'
]);
const db = initMockDB({
title: "Fundamentals of Frontend System Design",
body: "Learning to use Intersection Observer"
});
const list = document.getElementById('list');
const observerElement = document.getElementById('bottom-observer');
const mutationObserver = new MutationObserver((mutationList) => {
/*
* @todo
*
* 1. Loop through mutations (first arg of callback)
* 2. use mutation.type === 'characterData'
* 3. When the content matches with any supported tag in SUPPORTED_ELEMENTS
* use getHeading function to convert text to HTMLHeading element
* 4. Replace the node with a newly created node
* 5. Keep focus on the element
*/
for(const mutation of mutationList) {
const target = mutation.target;
if(mutation.type === 'characterData' && SUPPORTED_ELEMENTS.has(target.textContent)) {
const heading = getHeading(target);
target.replaceWith(heading)
heading.focus();
}
}
});
let page = 0;
const observer = new IntersectionObserver(async ([bottom]) => {
if (bottom.isIntersecting) {
observerElement.textContent = "Loading";
const data = await db.getPage(page++);
const fragment = new DocumentFragment();
data.forEach(({title, body}) => {
const card = createCardElement(title, body);
fragment.appendChild(card);
// @todo register observer
mutationObserver.observe(card, {characterData: true, subtree: true});
});
list.appendChild(fragment);
}
}, {threshold: 0.1})
observer.observe(observerElement);
mutationObserver.disconnect()
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment