Mutation Observer を使ってiframe内の要素を監視する

Mutation Observer を使ってiframe内の要素を監視する

JavaScript

JavaScript の 要素の監視ができる Mutation Observer を使う機会があったので使い方をご紹介します。

この記事を書いた人

かみーゆ/フロントエンドエンジニア

資金ゼロからフィリピンで起業した海外ノマドエンジニア。IT業界10年以上でテクニカルディレクター(技術責任者)・エンジニア講師・ブリッジSEを経てLenzTechnologies Inc.を設立し、代表を務める。CMS concreteCMSエバンジェリスト。テックブログ以外も「磨耗しない人生」や「海外ノマド」のライフスタイルについて発信。好きなものは肉とハイボール。

Mutation Observer とは?

MDN Web Docs によるとMutationObserver インターフェイスは、 DOM ツリーへ変更が加えられたことを監視できる機能
参照 : insertAdjacentElement MDN

Mutation とは突然変異の意味です。

今回は画面操作するたびに変更されるiframe内の高さを取得して、スクロールさせないようにしたかったのでその方法をそのまま記しておきます。

frameまたはiframe要素で読み込まれているページが別ドメインである場合、クロスドメインの制約に引っかかり取得できない場合があります。

iframe 内の必要な要素の値を取得する

ajaxなどで非同期で読み込んだコンテンツの表示が終わったら、iframeの高さを取得しiframeに直接スタイルを書き込みます。スクロールバーの表示されないので、埋め込み感がなくなります。

今回はiframe内で読み込まれるローディング画像の表示/非表示の変化を監視します。

HTML
<iframe src="index.html" frameborder="0" class="element"></iframe>
JavaScript
const iframe = document.querySelector(".element");

function setHeight() {
  iframe.height = `${iframe.contentDocument.documentElement.offsetHeight}px`
}
document.addEventListener('DOMContentLoaded', event => {
  iframe.onload = () => {
    //ローディング用の画像要素
    const app = iframe.contentDocument.querySelector('#app img')
    setHeight()
    const observer = new MutationObserver(function (mutations) {
      if (mutations[0].target.className === '') {
        setHeight()
      }
    });
    const options = {
      attributes: true,
      attributeOldValue: false,
      subtree: false
    }
    observer.observe(app, options)
  };
});

contentDocumentで要素の中身を取得します。

HTML の領域のサイズを得るためにdocumentElementオブジェクトを参照します。

iframe.height = `${iframe.contentDocument.documentElement.offsetHeight}px`
高さ詳細
offsetHeightボーダーやスクロールバーを含む高さ
scrollHeightマージン・スクロールバーを含まない内側の高さ
clientHeightボーダーやスクロールバーを含まない内側の高さ

observe(監視)に追加できるオプションです。

オプション説明
subtreetargetをルートとしたNodeのサブツリーをモニタリングするか
childListターゲットノードの子ノードの追加や削除を監視
attributesターゲットの属性の変化を監視。
attributeFilter監視する特定の属性名の配列。このプロパティが含まれていない場合、すべての属性の変更は変異通知を引き起こすデフォルトはfalse。
attributeOldValueターゲットの古い属性の値を記録
characterData文字の変更を監視。
characterDataOldValue古い文字のデータを記録。

observe(監視)以外のメソットです。

メソッド説明
disconnect()MutationObserver のインスタンスが今後の通知を受け取ることを、 observe() が再び呼び出されるまで停止します。
takeRecords()MutationObserver の通知キューから保留中の通知をすべて削除し、 MutationRecord の新しい配列 (Array) で返します。

参照 : MutationObserver MDN

おまけ・iframe内のデータ操作

iframe内の要素の操作方法の要素の削除方法のご紹介です。

iframe内の要素の削除

iframe.contentDocument.querySelector('header').remove()

iframe の head内に style 追加

iframeを親要素になじませるためにスタイルを追加することも可能です。

const styleTag = document.createElement('style')
styleTag.innerText = `
body {
  background: none;
}
`;
iframe.contentDocument.querySelector('head').insertAdjacentElement('beforeend', styleTag);

insertAdjacentElement の使い方です。呼び出された要素から相対的に指定された位置に、指定された要素ノードを追加できます。

メソッド説明
beforebeginターゲットの前
afterendターゲットの後
afterbeginターゲット内の最初の子要素の前
beforeendターゲット内の最後の子要素の後

insertAdjacentElement MDN

同じ要領で、他の要素も追加できます。

iframe内の要素のクラスの削除や追加

//追加
iframe.contentDocument.querySelector('main').classList.add('is-show')
//削除
iframe.contentDocument.querySelector('main').classList.remove('is-show')

まとめ・Mutation Observerを使えばイベント発火に関係なく監視したい要素の変化をキャッチできる

今回iframe内の要素の変化を監視して、iframeを操作する方法をご紹介しました。

Mutation Observer の他の使い方はまだやってませんが、可能性のあるAPIでした。

この記事がみなさんのコーディングライフの一助となれば幸いです。

最後までお読みいただきありがとうございました。

参照 : insertAdjacentElement MDN

関連記事もあわせてお読みください

Intersection Observer API の使ってQiita風目次を作ってみる

要素の監視ができる、Intersection Observer APIの使い方をご紹介。もう、scroll量に応じて処理...