いつの間にこんな便利なやつが・・。
ev.composedPath()
`click`などのイベントが、どういうDOM経路で発生したのかがわかる。
たとえばこういうHTMLのとき。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>composedPath()</title> </head> <body> <section> <div><button>Hi</button></div> </section> </body> </html>
こういうコードを書いて、
document.querySelector("button").addEventListener("click", (ev) => { const path = ev.composedPath(); for (const target of path) { console.log(target.nodeName || "#window"); } });
ボタンをクリックすると。
"BUTTON" "DIV" "SECTION" "BODY" "HTML" "#document" "#window"
という感じに。
Click awayする
「特定の要素の外をクリックしたら」っていうやつで、モーダルやメニューを閉じたいときにやるやつ。
`composedPath()`を使えば、
- `document`に対するすべての`click`イベントを拾って
- そのイベントの`composedPath()`に、特定の要素が含まれていない場合
- コールバックを実行する
という風にできる。
const clickAway = (el, onAway) => { const onClick = (ev) => { const path = ev.composedPath(); // 含まれてる = 内側 = 何もしない if (path.includes(el)) return; onAway(); }; document.addEventListener("click", onClick); return () => { document.removeEventListener("click", onClick); }; }; const $button = document.querySelector("button"); const buttonAway = () => { console.log("Outside!"); } clickAway($button, buttonAway);
って感じ。
この実装、一昔前までは`Element.contains()`とか、もっと前なら`$.closest()`とか、それなりにヘビーなやつを使ってた気がするので、いい時代になったもんだ!