はじめに
ページ内のクリックを検知して処理を実行する実装をしていた際に、ページ内のiframe表示している部分のクリックイベントが上手く取得出来ておらず、検知する為に取った方法を記します。
この記事の対象者
- クリックイベントを検知するような処理で、iframe内のクリックも検知したい人
- ページで埋め込んだiframe部分に対し、addEventlistenerを付与したい人
- ページで埋め込んだiframe部分のwindowオブジェクトを取得したい人
iframe表示部分のクリックイベントを取得する
前提
あなたが作成中のページにiframe表示している部分があるとします。作成中のページのどこかをクリックしたら検知して、何かしらの処理を実行したいと思っています。
使用するHTML部分
<div class="pageWrapper">
<iframe src="~~~"></iframe>
</div>
(失敗)window.addEventlistenerでclickイベントを検知する
当然のように最初に試したことは、window.addEventlistenerでclickイベントを検知する方法です。造作もなくこれで完了だと思っていました。
以下script部分になります。
window.addEventListener("click", () => {
alert("clickを検知しました");
})
これで画面内を触ってみます。以下確認環境です。
iframeエリア外をクリックするとalertが表示されますが、iframeエリアをクリックしてもalertが表示されないことがわかると思います。
どうやらiframe内のイベントは親フレームでは取得出来ないようです。ではどうしても親フレームでイベントを検知したい場合はどのようにすれば良いでしょうか?
方法1.iframe要素のcontentWindowに対しaddEventlistenerを登録する
まずiframe要素を取得します。私はquerySelectorを使用しました。そして取得したiframe要素に対してcontentWindowプロパティを使用することで、iframe内部のWindowオブジェクトにアクセスすることが出来ます。
iframe内部のWindowオブジェクトにアクセスすることが出来たら、親ページと同様addEventlistenerを登録することでiframeに対して
イベントを検知することが可能になりました。
window.addEventListener("click", () => {
alert("clickを検知しました");
})
// DOMツリー構築後にiframe要素を取得して、addEventlistenerを登録する
window.addEventListener("DOMContentLoaded", () => {
const iframeElement = document.querySelector("iframe");
iframeElement.contentWindow.addEventListener("click", () => {
alert("clickを検知しました");
})
})
これでiframeエリアのclickイベントも検知することが出来ました。
注意点
埋め込んだiframeのWindowオブジェクトにアクセスするには、埋め込んだ親ページとiframeのページが同一のオリジンである必要があります。
なので自身のページに埋め込んだ全く無関係のページに対しcontentWindowにアクセスしてどうこうすることは出来ませんのでご注意ください。
さいごに
この記事ではページに埋め込んだiframe要素に対して、contentWindowにアクセスしてaddEventListenerを登録する方法を説明しました。
それ以外の方法では、iframe内と親ページとでpostMessageを利用してやり取りする方法があります。そのやり方については別の記事で紹介しようと思います。