Javascript 自定义错误XPage:浏览器能够在错误加载后加载并执行JS脚本链接或块
形势 我使用的是一个自定义错误XPage,它高度依赖于。它工作得相当好,但我希望浏览器执行客户端JavaScript块(或从给定URL加载并运行JS文件)。如果我直接导航到自定义错误XPage,它会正确加载,但考虑到它如何从SSJS运行时错误重定向加载的性质,它似乎会加载任何试图在head标记中、body标记内加载脚本块的尝试。我尝试在正文中传递JS脚本标记(如下面的代码所示),尝试,尝试 浏览器视角 从浏览器的角度来看,在部分刷新期间调用SSJS的事件中遇到运行时错误后,被调用的xhr返回500并将内容设置到body标记中(屏幕截图)Javascript 自定义错误XPage:浏览器能够在错误加载后加载并执行JS脚本链接或块,javascript,dojo,xpages,xpages-ssjs,Javascript,Dojo,Xpages,Xpages Ssjs,形势 我使用的是一个自定义错误XPage,它高度依赖于。它工作得相当好,但我希望浏览器执行客户端JavaScript块(或从给定URL加载并运行JS文件)。如果我直接导航到自定义错误XPage,它会正确加载,但考虑到它如何从SSJS运行时错误重定向加载的性质,它似乎会加载任何试图在head标记中、body标记内加载脚本块的尝试。我尝试在正文中传递JS脚本标记(如下面的代码所示),尝试,尝试 浏览器视角 从浏览器的角度来看,在部分刷新期间调用SSJS的事件中遇到运行时错误后,被调用的xhr返回50
<script>
alert('hi Marky!');
</script>
查看响应内容时,整个自定义错误XPage都在那里,包括console.log(“hello world”)代码>。这似乎不会触发或向浏览器的JS控制台输出任何内容。通过JS控制台可以看到dojo的一些垃圾,它们抱怨返回了响应代码为500的XHR(我的dojoConfig在xsp属性中通过xsp.client.script.dojo.djConfig设置为isDebug:true
)
问题
在加载自定义错误XPage期间发生错误500后,是否有方法让客户端JS脚本标记加载并在浏览器中执行
这是我的错误页面的代码。要重现我的结果,请调用一个SSJS操作,该操作会导致运行时错误(例如Paul Withers的OpenLog Logger for XPages项目中包含的错误)和部分刷新事件
Error.xsp(设置为xsp属性中的错误页)
值得一提的是:我没有通过搜索谷歌或StackOverflow找到任何关于这个主题的明确信息
更新1:
这要么是咖啡因缺乏,要么就是看不见树林。在HTML代码中不使用CDATA块会有所帮助。我的懒惰开发人员尝试在xp:script块和HTML块之间复制和粘贴,并保留它。现在来谈谈在亚特兰大购买Marky啤酒的公众羞辱
更新2:
Marky选择的饮料可能会有危险。虽然我似乎在复制CDATA标记时遇到了问题,但问题仍然存在。在我试图生成一个带有出错按钮的简化页面(松散地基于上面提到的XPages ErrorOnClick.xsp的OpenLog Logger中的XPage)时,我错误地取出了导致问题的部分原因,即部分刷新。当我进行完全刷新时,没有问题,但当我进行部分刷新时,它不会加载。我附上了一个示例页面,用两个按钮触发一个错误;一个是诱导一个完全的,另一个是部分的。所以,在完全刷新之后,我得到了一个“hello world…”的警报,带有部分,无骰子
MakeSomeError.xsp
更新3:
可以斯文的第二个答案让我非常接近,但出于某种原因,我无法推断出我想要发生的事情。我在我的结果下面加了一张GIF。唯一不同的是,我希望我的Error.xsp(自定义错误XPage)在遇到错误后继续加载(似乎我需要将beforeRenderResponse块更改为afterRenderResponse脚本)。我想附加脚本,而不是替换Error.xsp加载。基本上,我尝试在加载错误XPage后运行脚本(我尝试将一个helper JS文件加载到我的自定义错误XPage中,CSS加载正常,而不是JS库)。我很乐意:
让它工作起来
分享它是什么(如果我自己这么说的话,它有点酷)
不要在脚本
标记中使用CDATA
var ex = facesContext.getExternalContext();
var pMap = com.ibm.xsp.util.TypedUtil().getRequestParameterMap(ex);
var refreshId = pMap.get("$$ajaxid");
警惕(“你好,马克!”);
对我来说很有用。之所以这样做是因为这是一种安全功能。如果浏览器是通过Ajax加载的,则不会执行
块。
但有一个解决办法:
首先,您必须添加一个div以替换呼叫XPage:
var resp:com.ibm.xsp.webapp.XspHttpServletResponse = facesContext.getExternalContext().getResponse();
resp.setStatus(200);
现在必须将响应状态代码设置为200,否则将调用事件中的错误方法:
resp.setHeader('X-XspRefreshId', 'errRefresh' );
然后,您可以添加CSJS块,该块必须如下所示:
facesContext.responseComplete();
<xp:text
escape="true"
id="executeOnAjax"
tagName="img">
<xp:this.attrs>
<xp:attr
name="src"
value="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==">
</xp:attr>
<xp:attr
name="onload"
value="alert('Hello World!');this.parentNode.removeChild(this);">
</xp:attr>
</xp:this.attrs>
<xp:this.rendered>
<![CDATA[#{javascript:
var ex = facesContext.getExternalContext();
var pMap = com.ibm.xsp.util.TypedUtil().getRequestParameterMap(ex);
var refreshId = pMap.get("$$ajaxid");
refreshId?true:false;}]]>
</xp:this.rendered>
</xp:text>
最后但并非最不重要的一点是,我们必须跳过JSF生命周期:
<script>
if( !dojo._xhr )
dojo._xhr = dojo.xhr;
var myHandler = function(){
var xhrObj = arguments[1].xhr;
var response = xhrObj.response;
var header = xhrObj.getResponseHeader('X-XspRefreshId');
if( header == "@error" ){
eval( response );
}else{
arguments[1]["error"]( arguments[0], arguments[1]);
}
}
dojo.xhr = function(){
try{
var args = arguments[1];
args["failOk"] = true;
args["error"] = myHandler;
arguments[1] = args;
}catch(e){}
dojo._xhr( arguments[0], arguments[1], arguments[2] );
}
</script>
就这样
以下是错误页面的beforeRenderResponse事件的完整代码:
<xp:this.beforeRenderResponse>
<![CDATA[#{javascript:
var ex = facesContext.getExternalContext();
var pMap = com.ibm.xsp.util.TypedUtil().getRequestParameterMap(ex);
var refreshId = pMap.get("$$ajaxid");
if( refreshId ){
var resp:com.ibm.xsp.webapp.XspHttpServletResponse = facesContext.getExternalContext().getResponse();
var writer:java.io.PrintWriter = resp.getWriter();
writer.write( "alert('Hello World!' );\n" );
resp.setHeader('X-XspRefreshId', '@error' );
facesContext.responseComplete();
}
}]]>
</xp:this.beforeRenderResponse>
Marky还有一个好主意:劫持响应
这可能是这样的:
facesContext.responseComplete();
<xp:text
escape="true"
id="executeOnAjax"
tagName="img">
<xp:this.attrs>
<xp:attr
name="src"
value="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==">
</xp:attr>
<xp:attr
name="onload"
value="alert('Hello World!');this.parentNode.removeChild(this);">
</xp:attr>
</xp:this.attrs>
<xp:this.rendered>
<![CDATA[#{javascript:
var ex = facesContext.getExternalContext();
var pMap = com.ibm.xsp.util.TypedUtil().getRequestParameterMap(ex);
var refreshId = pMap.get("$$ajaxid");
refreshId?true:false;}]]>
</xp:this.rendered>
</xp:text>
如果(!dojo._xhr)
dojo.xhr=dojo.xhr;
var myHandler=function(){
var xhrObj=参数[1].xhr;
var响应=xhrObj.response;
var header=xhrObj.getResponseHeader('X-XspRefreshId');
如果(标题==“@错误”){
评价(反应);
}否则{
参数[1][“错误”](参数[0],参数[1]);
}
}
dojo.xhr=函数(){
试一试{
var args=参数[1];
args[“failOk”]=真;
args[“error”]=myHandler;
参数[1]=args;
}捕获(e){}
dojo.xhr(参数[0],参数[1],参数[2]);
}
必须修改beforeRenderResponse事件,如下所示:
facesContext.responseComplete();
<xp:text
escape="true"
id="executeOnAjax"
tagName="img">
<xp:this.attrs>
<xp:attr
name="src"
value="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==">
</xp:attr>
<xp:attr
name="onload"
value="alert('Hello World!');this.parentNode.removeChild(this);">
</xp:attr>
</xp:this.attrs>
<xp:this.rendered>
<![CDATA[#{javascript:
var ex = facesContext.getExternalContext();
var pMap = com.ibm.xsp.util.TypedUtil().getRequestParameterMap(ex);
var refreshId = pMap.get("$$ajaxid");
refreshId?true:false;}]]>
</xp:this.rendered>
</xp:text>
<
<xp:text
escape="true"
id="executeOnAjax"
tagName="img">
<xp:this.attrs>
<xp:attr
name="src"
value="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==">
</xp:attr>
<xp:attr
name="onload"
value="alert('Hello World!');this.parentNode.removeChild(this);">
</xp:attr>
</xp:this.attrs>
<xp:this.rendered>
<![CDATA[#{javascript:
var ex = facesContext.getExternalContext();
var pMap = com.ibm.xsp.util.TypedUtil().getRequestParameterMap(ex);
var refreshId = pMap.get("$$ajaxid");
refreshId?true:false;}]]>
</xp:this.rendered>
</xp:text>