[salesforce]標準画面でVFからポーリング処理をJSのリロードで実現する

やりたかった事としては、カスタムオブジェクトの詳細画面に、VisualForceで地図を表示させ、
そのVF内のJSからリロード処理をsettimeoutとかで呼び出してポーリングさせるようにしたかった。

作成したVisualForceのページを詳細画面に埋め込む方法などは、以前に書いた記事を参考にどうぞ。

[salesforce]オブジェクトの詳細ページに作成したVisualForceページを埋め込む

で、上記の方法でVisualForceに埋め込むわけだけれど、そのままそのVisualForce内からJSでリロード処理を書くと、上手く動作しない。
原因は、埋め込まれたVisualForceは標準画面から見るとiframeとなっており、しかもその中身は別のドメインとなっている。
なので、子ページが別ドメインの親ドメインをリロードしようとしてクロスドメインのエラーが発生していた、というわけ。

例えば、詳細ページのURLが以下のようになっている場合、

https://cs6.salesforce.com/xxxxIDxxxx

読み込まれているVFページのURLは以下のようになっていた。

https://c.cs6.visual.force.com/servlet/servlet.Integration?lid=xxxxVFIDxxxx&ic=1

これはJSの仕様でクロスドメイン(オリジン)がダメなので、根本的に回避する手立てはない。

しかし、バッドノウハウ的に対応するならば、以下のように、同じドメインからリロードをかけるようにしてやれば回避できるよう。

  1. 静的リソースに、リロードするためだけのJSを埋め込んだファイルをアップしておく
  2. VFページ上に非表示にしたiframeタグを記述しておく
  3. リロードするタイミングでそのiframeに、1のファイルを表示させる
  4. 静的リソース内からリロードが走り、無事リロードが行われる

現状では、標準ページのドメインと静的リソースの表示ドメインは同じなので動作する。
標準ページから見れば、孫からリロードを要求される形。

1.の中身は以下のような内容

<html><head><script>parent.parent.location.reload();</script></head></html>

これを、OpenerReloadとして静的リソースに登録しておく。
VF側のJSはこんな内容

setTimeout(reloadAndClose, 60000);
function reloadAndClose() {
  var iframe = document.getElementById('iframe');
  var urlbase = 'https://cs6.salesforce.com';
  iframe.src = urlbase + '{!URLFOR($Resource.OpenerReload)}';
}

埋め込むiframeのタグ

<iframe src="about:blank" id="iframe" style="display:none;"></iframe>

静的リソースがいつまで同じドメインでアクセスできるかわからないので、あまりオススメは出来ないけれど、他に方法がなさそう。
仕事でやる場合には避ける方が無難かもしれない。

参考

[Salesforce]標準画面からクロスドメインなVisualforce画面を開き、自分を更新させる : minoawのブログ
ほぼこのまんまです。ありがとうございます。

   このエントリーをはてなブックマークに追加