2016-08-04 141 views
1

我正在使用PrimeFaces 6.0,JSF 2.2(Mojarra 2.2.7)應用程序。如何使用JSF打開彈出窗口而不會被瀏覽器阻止

我需要從外部網站加載網頁並突出顯示一個DOM節點。我的方法是創建一個JavaScript函數來打開彈出窗口,通過servlet加載網頁(以避免跨域問題)並突出顯示節點。我發送給我的函數的參數是在託管bean中生成的。

我試圖在兩種不同的方式這樣做:

  1. 在我的行動使用RequestContext.getCurrentInstance().execute("myFunction(...)")(是的,我使用PrimeFaces)。
  2. 在我的命令按鈕上使用oncomplete="#{myBean.myJsCall}"

呼叫被執行,呼叫是正確的,但我碰到我的瀏覽器(鉻)彈出窗口攔截兩種方式:

The following pop-ups were blocked on this page

有沒有辦法打開彈出窗口在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(); 
} 
+0

這與JSF或PrimeFaces無關。這是一個純粹的客戶端html問題。在這種情況下最好使用PrimeFaces對話框 – Kukeltje

+0

我使用純HTML/JS開發了該腳本。它在那裏工作。將調用粘貼到控制檯也可以。當然,你不能「責怪」JSF,但我希望有一個「解決方法」。在這種情況下,對話框不可選。內容從外部網站加載,並希望CSS混合。 –

+1

在沒有用戶交互的情況下從同一頁面客戶端打開多個彈出窗口/打開新窗口(這是您明確要做的)將導致這些響應(是我的經驗)可能只是在幾次呼叫之後。但是我懷疑你從服務器響應中直接得到這條消息。我看到的一個選擇是使用普通的div並將其居中在屏幕上,並在其中顯示「req.responseText」。但是,如果你特別需要一個新窗口,那麼我不會想到一些事情。 – Kukeltje

回答

2

當您嘗試打開在JavaScript中,不直接由用戶觸發的動作(如點擊)一個新的窗口,但在例如回調觸發執行JSF Ajax請求後,它被封鎖瀏覽器。

在下列問題中描述了此行爲:jquery window.open in ajax success being blocked

作爲解決方法,您可以在JSF ajax請求之前打開一個窗口。在使用JSF HTML標籤可以做到這一點,通過使用命令按鈕的情況下:

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

onclick將呈現爲是。但是,如果你正在使用PrimeFaces,你不能使用:

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

PrimeFaces包裝造成的間接執行onclick,所以彈出被阻止。

無論如何,有了一些額外的黑客,你可以用某種按鈕看起來像PrimeFaces按鈕。但黑客的數量變得太多了。

我選擇使用p:dialog而不是iframe。首先,如果您正在使用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(); 
} 
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'; 
} 
+0

你有試過嗎?當我使用'onclick'時,它用PrimeFaces對象包裝(請參閱問題和我的答案中的註釋)。 –

相關問題