我正在使用PrimeFaces 6.0,JSF 2.2(Mojarra 2.2.7)应用程序。
我需要从外部网站加载网页并突出显示DOM节点。我的方法是创建一个JavaScript函数来打开一个弹出窗口,通过servlet加载网页(以避免跨域问题)并突出显示该节点。我发送给我的函数的参数是在托管bean中生成的。
我尝试以两种不同的方式这样做:
RequestContext.getCurrentInstance().execute("myFunction(...)")
(是的,我使用的是PrimeFaces)。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();
}
答案 0 :(得分:2)
当您尝试在JavaScript中打开一个新窗口时,该窗口不是由用户操作(如点击)直接触发,而是例如在执行JSF ajax请求后触发的回调,它会被浏览器阻止。 / p>
以下问题描述了此行为: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();
}
答案 1 :(得分: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';
}