为什么PrimeFaces命令按钮无法更新包含JavaScript <script>document.write("some text")</script>
元素的元素?浏览器“挂起”更新此类元素。
例如:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>my page</title>
</h:head>
<h:body>
<h:form>
<p:commandButton
id="pushMeButton"
value="push me"
update="testPanel"
action="#{myManagedBean.doNothing()}">
</p:commandButton>
</h:form>
<p:panel id="testPanel">
<script>
document.write("test text 1");
</script>
<script>
document.write("test text 2");
</script>
<h:outputText value="#{myManagedBean.getSomeText()}" />
</p:panel>
</h:body>
</html>
按下“pushMeButton”后,浏览器只显示带有文本“test text 1”和“hangs”的空白页面(firefox选项卡中的图标显示该页面仍在无限期加载,但在firebug中没有活动请求)。
按下按钮后浏览器收到的部分响应看起来是正确的:
<partial-response id="j_id1">
<changes>
<update id="testPanel">
<![CDATA[
<div id="testPanel" class="ui-panel ui-widget ui-widget-content ui-corner-all" data-widget="widget_testPanel">
<div id="testPanel_content" class="ui-panel-content ui-widget-content">
<script>
document.write("test text 1");
</script>
<script>
document.write("test text 2");
</script>
some text from managed bean method getSomeText()
</div>
</div>
<script id="testPanel_s" type="text/javascript">
PrimeFaces.cw("Panel","widget_testPanel",{id:"testPanel",widgetVar:"widget_testPanel"});
</script>
]]>
</update>
<update id="j_id1:javax.faces.ViewState:0"><![CDATA[1747871418605077113:5684199653317714547]]></update>
</changes>
</partial-response>
我正在使用PrimeFaces:5.2.5和Mojarra:2.2.8
我可以在Firefox v44.0.2和IE v11上重现行为,但在Chrome v48上,一切都按预期工作(显示相同的页面没有更改)。
上面提到的xhtml sniped只是我正在解决的问题的简化版本。我使用“document.write”,因为我的Web应用程序从遗留系统“导入”了一些无法更改的HTML部分(我从Liferay门户导入菜单)。 如果我将“document.write”更改为其他内容,例如document.getElementById('someExistingElementId').innerHTML = 'New text';
一切正常。
看起来像BalusC 的评论“我认为我看到了根本原因。当使用document.write()替换DOM时,IE6 / 7/8不运行嵌入式脚本”(http://forum.primefaces.org/viewtopic.php?f=3&t=18937&start=20)与我的问题有关,但我不明白为什么它不起作用,是否可以使它在现代浏览器上运行。
答案 0 :(得分:3)
问题与PrimeFaces或JSF没有直接关系 - 这是javascript的工作原理。
“如果在HTML文档完全加载后使用它,它将被删除 所有现有的HTML。“(http://www.w3schools.com/jsref/met_doc_write.asp)
我可以使用HTML和JS重现类似的情况:
<!DOCTYPE html>
<html>
<body>
<p>Click the button to trigger a function</p>
<button onclick="myFunction()">Click me</button>
<script>
function myFunction() {
document.write("test text 1");
}
</script>
</body>
</html>
部分更新更新已加载的文档 - 这就是为什么在单击按钮后只显示“测试文本1”的原因。因为在执行第一个<script>document.write("test text 1");<script>
之后会覆盖所有文档。
Firefox“挂起”,因为未调用“document.close”(如果文档输出流未打开,“document.write”将打开它,因此需要将其关闭)。
所以简历是:如果可以使用ajax调用更新页面的那一部分,则无法在JSF页面中使用document.write(...);
。
在大多数情况下,JSF页面中应避免document.write(...)
,因为并不总是可以控制页面的哪个部分将被更新。例如,OmniFace FullAjaxExceptionHandler将在异常后执行update =“@ all”,因此错误页面不能包含任何document.write(...)
语句。