如何在不被浏览器阻止的情况下使用JSF打开弹出窗口 [英] How to open a pop-up using JSF without it being blocked by the browser
问题描述
我正在开发PrimeFaces 6.0,JSF 2.2(Mojarra 2.2.7)应用程序.
I'm working on a PrimeFaces 6.0, JSF 2.2 (Mojarra 2.2.7) application.
我需要从外部站点加载网页并突出显示DOM节点.我的方法是创建一个JavaScript函数来打开一个弹出窗口,通过servlet加载网页(以避免跨域问题)并突出显示该节点.我发送给函数的参数是在托管bean中生成的.
I need to load a web page from an external site and highlight a DOM node. My approach is to create a JavaScript function to open a pop-up window, load the web page through a servlet (to avoid cross domain issues) and highlight the node. The parameters I send to my function are generated in a managed bean.
我试图通过两种不同的方式来做到这一点:
I tried to do so in two different ways:
- 在操作中使用
RequestContext.getCurrentInstance().execute("myFunction(...)")
(是的,我正在使用PrimeFaces). - 在命令按钮上使用
oncomplete =#{myBean.myJsCall}"
.
- Using
RequestContext.getCurrentInstance().execute("myFunction(...)")
in my action (yes, I'm using PrimeFaces). - Using
oncomplete="#{myBean.myJsCall}"
on my command button.
执行调用和调用正确的两种方式,但是我遇到了浏览器的(Chromium)弹出窗口阻止程序:
Both ways the call is executed and the call is correct, but I run into my browser's (Chromium) pop-up blocker:
有没有一种方法可以在JSF或PrimeFaces中打开弹出窗口而不会被阻止?
Is there a way to open pop-ups in JSF or specifically in PrimeFaces without them being blocked?
这并不是很重要,但这是我的JavaScript函数的简化版本.
This is not really relevant, but this is the simplified version of my JavaScript function.
我使用纯HTML和JS开发了此脚本.在那里,它打开了弹出窗口,而没有阻止程序进行干预.另外,在运行JSF应用程序时将呼叫粘贴到控制台中时,将弹出窗口.
I developed this script using plain HTML and JS. There it was opening the pop-up without the blocker interfering. Also, when pasting the call into the console when running the JSF application, the pop-up is opened.
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();
}
推荐答案
当您尝试在JavaScript中打开新窗口时,该窗口不是由用户操作(例如点击)直接触发的,而是例如由回调触发的执行JSF ajax请求后,浏览器将阻止它.
When you try to open a new window in JavaScript, which is not directly triggered by a user action (like a click), but in for example a callback triggered after executing JSF ajax requests, it is blocked by the browser.
以下问题描述了此行为: jquery window.open阻止ajax成功.
This behavior is described in the following question: jquery window.open in ajax success being blocked.
作为一种解决方法,您可以在JSF ajax请求之前打开一个窗口.如果是使用JSF HTML标签的命令按钮,则可以使用以下方法完成:
As a workaround you could open a window before the JSF ajax request. In case of a command button using the JSF HTML tags this can be done by using:
< h:commandButton ... onclick ="prepareWindow()"/>
onclick
将按原样呈现.但是,当您使用 PrimeFaces 时,您不能使用:
The onclick
will be rendered as is. But, when you are using PrimeFaces, you cannot use:
< p:commandButton ... onclick ="prepareWindow()"/>
PrimeFaces包装 onclick
导致间接执行,因此弹出窗口被阻止.
PrimeFaces wraps the onclick
resulting in indirect execution, so the pop-up is blocked.
无论如何,通过一些额外的技巧,您可以使用某种类似于PrimeFaces按钮的按钮来使用此按钮.但是黑客的数量越来越多.
Anyhow, with some extra hacks you could get this working with some sort of button which looks like a PrimeFaces button. But the number of hacks was getting too much.
我选择使用 p:dialog
和 iframe
.首先,如果您使用的是 p:layout
,请不要将对话框放置在任何布局单位中.
I opted to use a p:dialog
with an iframe
instead. To start of, if you are using p:layout
, don't place the dialog in any of the layout units.
对话框:
<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函数:
The JavaScript function:
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();
}
这篇关于如何在不被浏览器阻止的情况下使用JSF打开弹出窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!