detect하는 구문
document.querySelectorAll("h2, h3, h4, h5, h6").forEach((entries) => {
observer.observe(entries);
});
entries 하나의 예
<h3 id="filebeat--elastic-search-조회">
<a class="anchor" href="#filebeat--elastic-search-조회">
<span class="icon icon-link"></span>
</a>
Filebeat → Elastic Search 조회
</h3>
const observer = new IntersectionObserver(setCurrent, observerOptions);
react code
"use client";
import React, { useEffect } from "react";
import $ from "jquery";
export default function Toc() {
useEffect(() => {
$("#dvToc").append($("#contents + ul")).prepend($("#contents"));
const setCurrent: IntersectionObserverCallback = (entries) => {
for (let entry of entries) {
const { id } = entry.target;//->href 내용
const enid = encodeURI(id);//->utf-8 한글처리
const tocHeadingEl = document.querySelector(
`#dvToc a[href="#${enid}"]`
);
if (!tocHeadingEl) return;
if (entry.isIntersecting) {
document
.querySelectorAll("#dvToc a")
.forEach((e) => e.classList.remove("active"));
tocHeadingEl.classList.add("active");
}
}
};
const observerOptions = {
threshold: 0.5, //-> 0~1 범위, 1:링크가 root안으로 100%들어와야함
rootMargin: "0px 0px -96%",
};
const observer = new IntersectionObserver(setCurrent, observerOptions);
document.querySelectorAll("h2, h3, h4, h5, h6").forEach((entries) => {
observer.observe(entries);
});
}, []);
return <div id="dvToc" className="mt-3 sticky top-8 "></div>;
}
active css
.active {
@apply font-bold bg-blue-300 dark:bg-indigo-500 dark:text-gray-700;
}