1

私は PrimeFaces 6.0、JSF 2.2 (Mojarra 2.2.7) アプリケーションに取り組んでいます。

外部サイトから Web ページを読み込み、DOM ノードを強調表示する必要があります。私のアプローチは、JavaScript 関数を作成してポップアップ ウィンドウを開き、(クロス ドメインの問題を回避するために) サーブレットを介して Web ページを読み込み、ノードを強調表示することです。関数に送信するパラメーターはマネージド Bean で生成されます。

私は2つの異なる方法でそうしようとしました:

  1. アクションで使用RequestContext.getCurrentInstance().execute("myFunction(...)")します (はい、PrimeFaces を使用しています)。
  2. oncomplete="#{myBean.myJsCall}"コマンドボタンで使用します。

どちらの方法でも呼び出しが実行され、呼び出しは正しいのですが、ブラウザー (Chromium) のポップアップ ブロッカーに遭遇します。

このページでは、次のポップアップがブロックされました

ポップアップをブロックせずにJSFまたは特にPrimeFacesで開く方法はありますか?

これはあまり関係ありませんが、これは私の JavaScript 関数の単純化されたバージョンです。

このスクリプトは、プレーンな HTML と JS を使用して開発しました。そこでは、ブロッカーが干渉することなくポップアップが開かれていました。また、JSF アプリケーションの実行時に呼び出しをコンソールに貼り付けると、ポップアップが開きます。

function myFunction(url, selector) {
    var popup = window.open("", "popup", "height=500,width=700");
    var req = new XMLHttpRequest();
    req.open("GET", url, true);
    req.onreadystatechange = function() {
        if (req.readyState === XMLHttpRequest.DONE) {
            popup.document.open();
            popup.document.write(req.responseText);
            popup.document.close();
            popup.document.addEventListener(
                "DOMContentLoaded",
                function() { /* Some code highlighting the selector */ },
                false
            );
        }
    }
    req.send();
}
4

2 に答える 2

2

ユーザー アクション (クリックなど) によって直接トリガーされるのではなく、たとえば JSF ajax 要求の実行後にトリガーされるコールバックで、JavaScript で新しいウィンドウを開こうとすると、ブラウザーによってブロックされます。

この動作は、次の質問で説明されています: jquery window.open in ajax success being blocked

回避策として、JSF ajax リクエストの前にウィンドウを開くことができます。JSF HTML タグを使用するコマンド ボタンの場合、これは次を使用して実行できます。

<h:commandButton ... onclick="prepareWindow()"/>

onclickそのままレンダリングされます。ただし、PrimeFacesを使用している場合は、次を使用できません

<p:commandButton ... onclick="prepareWindow()"/>

PrimeFacesonclickは間接実行の結果をラップするため、ポップアップはブロックされます。

とにかく、いくつかの追加のハックを使用すると、PrimeFaces ボタンのように見えるある種のボタンでこれを機能させることができます。しかし、ハッキングの数が多すぎました。

代わりにa を使用することにしましp:dialogiframe。まず、 を使用している場合は、ダイアログをどのレイアウト ユニットにも配置しないp:layoutでください。

ダイアログ:

<p:dialog header="Preview"
          widgetVar="previewDlg" modal="true" width="1000" height="600"
          dynamic="true">
    <iframe src="about:blank"
            class="previewIframe"
            style="position:absolute;top:0;left:0;right:0;bottom:0;width:100%;height:100%;border:0"></iframe>
</p:dialog>

ボタン:

<p:commandButton value="Show"
                 ...
                 onclick="PF('previewDlg').show()"
                 action="#{myBean.showPreview('previewIframe')}"/>

アクション:

public void showPreview(String iframeClass) {
    ...
    RequestContext.getCurrentInstance().execute(js);
}

JavaScript 関数:

function myFunction(iframeClass, url, selector) {
    var iframe = $("iframe[class=" + iframeClass + "]")[0];
    iframe.contentDocument.location = "about:blank";
    var req = new XMLHttpRequest();
    req.open("GET", url, true);
    req.onreadystatechange = function() {
        if (req.readyState === XMLHttpRequest.DONE) {
            iframe.contentDocument.open();
            iframe.contentDocument.write(req.responseText);
            iframe.contentDocument.close();
            iframe.contentDocument.addEventListener(
                "DOMContentLoaded",
                function() { /* Some code highlighting the selector */ },
                false
            );
        }
    }
    req.send();
}
于 2016-08-31T08:30:48.470 に答える
0

簡単な方法があります。空のポップアップ onclick を開き (ユーザーによって直接誘導されるため、ブロックされません)、ajax データが送信された後、ウィンドウを更新されたモデルにリダイレクトします。

<p:commandButton value="open popup" process="@form"
                     onclick="myNamespace.openPreview()"
                     oncomplete="myNamespace.relocatePreview()"/>

js は次のようになります。

myNamespace.openPreview = function () {
    myNamespace.prev = window.open('', '_blank');
}

myNamespace.relocatePreview = function () {
    myNamespace.prev.location = 'preview.xhtml?faces-redirect=true';
}
于 2016-10-28T08:22:42.980 に答える