iframeハック(クロスドメインパターン)

css:iframeっぽさを隠す。。

↓ style="overflow: hidden; border: none;" のみ

↓  scrolling="no" 追加


//iframに直接指定
 style="overflow: hidden; border: none;"
 scrolling="no" //廃止予定 スクロール無効
 frameborder="no" //廃止予定 ボーダー無効 必要なし?

//子にスタイル指定するといいらしい。(廃止後に検討)
html {
 overflow-y: hidden;
}

javascript:クロスドメインでiframeに値を渡す「親⇒子」「子⇒親」

window.postMessage()を使う。

window.postMessage()は、 Window オブジェクト間で安全にクロスドメイン通信を可能にするためのメソッド。

ただし、あくまで「ブラウジングコンテキスト間」の通信

ブラウジングコンテキストとは何かというと、これはブラウザのタブの1つ1つのことです。Web Messagingはインターネット上を通信するものではなく、あくまで各個人のPCやスマートフォン等の中で、同じブラウザのタブの間でデータをやり取りできるということです。

親受け場所

※scroll=""no"を指定しないとスクロールバーが表示される

⇒Child


//基本//
//送信
Window.postMessage( 送信データ , "相手のオリジン" , [譲渡データ] ) :Void

オリジン=「プロトコル、ドメイン、ポート番号」の3つを合わせたもの
つまり http://hogehoge.com:8080  な感じ(:8080は略)

[譲渡データ]:送信データとの違い
[譲渡データ]で指定したオブジェクトは、所有権が相手に譲渡されます。
自身からは、アクセス不可能になり、再利用もできません。

//受信//
window.addEventListener("message", hogefunc);
// 親:どのiframeからデータを受信したかは判別できない(e.originやe.sourceでは無理)
// 子からpathを渡せば、iframe[src="hoge"]で、送信元のiframeを特定できる。


//受信時関数の例)返信//
function hogefunc(e) {
  var $origin = e.origin;
  var $target = e.source;
  var receive_obj = {
    message:"返信テスト",
    param:{}
  };
  $target.postMessage (JSON.stringify(receive_obj), $origin);
}


親側
  $('#j4btn').on('click', function() {
    var ifrm = document.getElementById('ifrm').contentWindow;
    let $url = $('#ifrm').attr('src');
    ifrm.postMessage("HELLO!", $url);
  });

//event.origin = プロトコルと "://"、ホスト名(存在する場合)
//event.source 相手の Window オブジェクト
  window.addEventListener('message', function(event) {
    if (event.origin === "http://sample.example.com/") {
      return $('#world').text(event.data);
    }
  }, false);

//このページでは・・、受け取った配列データのkeyで判断
  function receiveMessage(event) {
  var $get = event.data;
  var $ifm = event.source;
    if($get.msg !== undefined) $('#world').text($get.msg + ':e[data][msg]');
    if(($get.path !== undefined) && ($get.height !== undefined)) $('iframe[src="'+ event.origin + $get.url +'"]').css('height',$get.height).attr('scrolling','no');
  }

  window.addEventListener("message", receiveMessage, false);



//子側
if(window != parent){
  $('#msg2').html('

iframeで読み込まれています♪

'); } else { $('#msg2').html('

iframeではないです♪

'); } //受信時 配列で時間差返信 window.addEventListener('message', function(event) { $('#msg').html('

' + event.data + '

'); var $target = event.origin; setTimeout(function(){ var return_obj = { name:"hoge", msg:"WORLD!", url:nAn.vars.thisurl, height:document.body.scrollHeight, }; event.source.postMessage(return_obj, $target); },200); }, false); //子から配列を送信 $('#hogebtn').on('click', function() { var return_obj = { name:"hoge", msg:"HELLO WORLD!", url:nAn.vars.thisurl, height:document.body.scrollHeight, }; window.parent.postMessage(return_obj, document.referrer); }); ※ document.referrer //クロスドメイン時の親のURL parent.location.href //同一ドメインの場合の親のURL top.location.href //同一ドメインの場合の一番親のURL

//子側でファイル名を受けとって、外部js読み込みさせる。

⇒Child2


//親側で読み込ませる外部jsを指定する
window.addEventListener("load", loadaction, false);

function loadaction() {
  let ifrm = document.getElementById('ifrm2').contentWindow;
  let $url = $('#ifrm2').attr('src');
  let load_obj = {
    dynamicjs:"/js/dynamichoge.js",
  };
  ifrm.postMessage(load_obj, $url);
};


//子側でファイル名を受けとって、外部js読み込みさせる。
if (window !== window.parent) {
  window.addEventListener('message', function(e) {
  var $get = e.data;
  if($get.dynamicjs !== undefined) {
    var script = document.createElement("script")
    script.type = "text/javascript";
    script.src = $get.dynamicjs;
    document.body.appendChild(script);
  }
  }, false);
}

//web workerを使うほうが良い?

外部jsでボタン表示!
子側のボタンクリック
⇒ 配列を渡し
⇒ 親で受け取り、編集画面の切り替え


//高さを自動で整える

//幅のみclass="w-100"している場合

⇒Child3

//window.postMessage()で高さを伝達。

⇒Child4



// Child4:iframe内でレンダリングされた場合にのみ発火させる
// iframe内でレンダリングされた場合にのみ発火させる
if (window !== window.parent) {
  window.addEventListener("load", postSize, false);
  window.addEventListener("resize", postSize, false);
}

function postSize() {
  var return_obj = {
    url:nAn.vars.thisurl,
    height:document.body.scrollHeight,
  };
  window.parent.postMessage(return_obj, document.referrer);
}


//同一ドメインパターン



// 子画面の要素を取得
var elm = document.getElementById("parentframe");

// 子画面のコンテンツサイズに合わせてサイズを変更する関数
function changeParentHeight(){
  elm.style.height = elm.contentWindow.document.body.scrollHeight + "px";
}

// 親画面 iframe の高さを変更するイベント
// 1. 子画面の読み込み完了時点で処理を行う
elm.contentWindow.onload = function(){ changeParentHeight(); };

// 2. 子画面のウィンドウサイズ変更が完了した時点で処理を行う
var timer = 0;
elm.contentWindow.onresize = function () {
  if (timer > 0) {
    clearTimeout(timer);
  }
  timer = setTimeout(function () {
    changeParentHeight();
  }, 100);
};