[salesforce]標準画面でVFからポーリング処理をJSのリロードで実現する
やりたかった事としては、カスタムオブジェクトの詳細画面に、VisualForceで地図を表示させ、
そのVF内のJSからリロード処理をsettimeoutとかで呼び出してポーリングさせるようにしたかった。
作成したVisualForceのページを詳細画面に埋め込む方法などは、以前に書いた記事を参考にどうぞ。
[salesforce]オブジェクトの詳細ページに作成したVisualForceページを埋め込む
で、上記の方法でVisualForceに埋め込むわけだけれど、そのままそのVisualForce内からJSでリロード処理を書くと、上手く動作しない。
原因は、埋め込まれたVisualForceは標準画面から見るとiframeとなっており、しかもその中身は別のドメインとなっている。
なので、子ページが別ドメインの親ドメインをリロードしようとしてクロスドメインのエラーが発生していた、というわけ。
例えば、詳細ページのURLが以下のようになっている場合、
読み込まれているVFページのURLは以下のようになっていた。
https://c.cs6.visual.force.com/servlet/servlet.Integration?lid=xxxxVFIDxxxx&ic=1
これはJSの仕様でクロスドメイン(オリジン)がダメなので、根本的に回避する手立てはない。
しかし、バッドノウハウ的に対応するならば、以下のように、同じドメインからリロードをかけるようにしてやれば回避できるよう。
- 静的リソースに、リロードするためだけのJSを埋め込んだファイルをアップしておく
- VFページ上に非表示にしたiframeタグを記述しておく
- リロードするタイミングでそのiframeに、1のファイルを表示させる
- 静的リソース内からリロードが走り、無事リロードが行われる
現状では、標準ページのドメインと静的リソースの表示ドメインは同じなので動作する。
標準ページから見れば、孫からリロードを要求される形。
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のブログ
ほぼこのまんまです。ありがとうございます。