环境:BIEE 11.1.1.7...
背景:
工作中经常会遇到在仪表盘内用HTML脚本写iFrame内嵌BIEE仪表盘的场景。可传参是最最头大的问题,大家经常是八仙过海各显神通。
下面就拿一个实例说明如何处理这种跨iFrame传参的实现情况。
仪表盘A内静态文本用HTML写了菜单栏和iFrame框架,其中点击菜单,变更内嵌的iFrame的src导航到不同的仪表盘。这样的实例应该是大家工作中的标配了。
类似于这样的仪表盘展示,当点击不同的标签A1\A2\A3\A4导航至不同的仪表盘页B1\B2\B3\B4。其中B1\B2\B3\B4都有区域org维度筛选条件的提示器。
那么某天需求来了。业务说当点击不同标签切换B1\B2\B3\B4的时候,在前一页中选择的org过滤条件,要在切换后的页面中再重复选择一次,不方便操作,需要把提示器拿到外层,当在外层选择了org筛选条件,下面内容可以生效,当点击上面菜单栏,导航的页面该org筛选条件继续生效。
需求修改后的大体仪表盘展示类似于上图。那么怎么解决当修改菜单层级的org提示器后,iframe里面的仪表盘页面生效筛选条件后重新加载呢?
JAVA呀。用JAVA写出模拟提示器的样子,参数想怎么传就怎么传。可当碰到有特殊字符的情况呢?提示器可以多选,提示器内容不规则,期间还会碰到URL超出长度的问题,当新员工不懂java的问题。。。。头大。可行但不完美!
BIEE的呢?试过了。跨iFrame后同一仪表盘的不同page页设置生效范围为仪表盘,但传参是传递不了的。。。。
真的么?该万能的F12君上场了。。。跟踪提交按钮的脚本。。。然后发现导航函数了obidash.navToBI,那么动起来。
剥离,放入外层框架的静态文本中,修改之,
<script type="text/javascript">
function getLinkUrlProperties(d){
var c=d;
var e;
var b;
var f;
var h=saw.catalog.getCatalogManager().getItemInfo(c,true);
var a=h.itemInfo;
var g=a.signature||a.targetSignature||a.getCompositeSignature();
if(g==saw.catalog.ItemCategory.REQUEST){
e="report";
}else{
if(g=="dashboardfolder1"){
e="dashboard";
b=c;
}else{
if(g=="dashboardpageitem1"){
e="page";
f=obips.catalog.Path.getItemName(c);
b=obips.catalog.Path.getParentPath(c);
}
}
}
return {
sPath:c,eType:e,sPortalPath:b,sPortalPage:f
};
}
obidash.navToBI=function(path,isNew,target){
var a=this.dashStyle||"";
var k=true;
var b="";
var c=getLinkUrlProperties(path);
var n=c.eType;
var e=c.sPortalPath;
var m=c.sPortalPage;
var h=document.getElementById("idViewStateDiv");
var q=h.getAttribute("statePath");
var j=obips.views.ViewController.getController(q);
var g=j.getViewEnvParam("PortalPath");
var p=j.getViewEnvParam("Page");
var i=h.getAttribute("stateID");
if(n=="report"){
if(k||saw.userAgent.is_smrtphone){
b=saw.commandToURL("GO");
}else{
b=saw.commandToURL(j.getViewEnvParam("GoCommand")||"PortalGo");
b+="&PortalPath="+saw.encodeURIComponent(g);
}
b+="&Path="+saw.encodeURIComponent(path);
if(a.length>0){
b+="&Style="+saw.encodeURIComponent(a);
}
if(k){done="Close";}else{
done=j.getViewEnvParam("CurrentCommand")||"Dashboard";
done+="&PortalPath="+saw.encodeURIComponent(g);
done+="&Page="+saw.encodeURIComponent(p);
done+="&ViewState="+saw.encodeURIComponent(i);
}
b+="&Done="+saw.encodeURIComponent(done);
b+="&Options=mfrdg";
b+="&Acton=Prompt";
}else{
if(k){
b=saw.commandToURL("PortalPages");
}else{
b=saw.commandToURL(j.getViewEnvParam("CurrentCommand")||"Dashboard);
}
b+="&PortalPath="+saw.encodeURIComponent(e);
if(n=="page"){
b+="&Page="+saw.encodeURIComponent(m);
}
b+="&P1=dashboard";
b+="&Action=Navigate";
}
b+="&ViewState="+saw.encodeURIComponent(i);
b+="&P16=NavRuleDefault";
b+="&NavFromViewID="+saw.encodeURIComponent(q);
//这里是自己需要往URL后面拼接的参数
b+="&relogon=1";
var l={mobileModel:n};
if(isNew!=null && isNew==true){
var o=obips.launcher.lunchNewWindow(b,"_blank","resizable=1,scrollbars=1",1);
if(o){o.focus();}
}else{
if(target!=null && document.getElementById(target)){
var objEle=document.getElementById(target);
objEle.setAttribute("src",b);
}else{
obips.luncher.lunchURL(b,l);
}
}
}
</script>
大功告成。测试下,改变org提示器的值,点击菜单A1\A2\A3\A4,值可以顺利传入,可。。。当不点击菜单A1\A2\A3\A4的时候,变更值,应用了iFrame无响应!
嗯,得监控这个提示器,当值变更的时候就点击菜单(其实就是调用点击参数时候的函数)传值。
这个简单,新增提示器个数的DIV,设置隐藏,设置div的默认text为对应提示器的默认值,新增函数FA用jquery去抓取提示器的值和对应div的text对比,若相同则不调用,若不相同则先赋值新值到对应的div,然后调用点击菜单的函数执行。接着轮到setInterval出场,页面加载后每1秒调用一次函数FA。
嗯。动起来了。完美解决。
谷歌(25)OK,IE10 OK,开心ing。。。
这个时候轮到IE8给我上课了,什么叫兼容性,什么叫缓存,让我再次感觉到自己的渺小和不足。。。