将 FusionChart objects 从 parent window 写入 child window
Writing FusionChart objects from parent window to child window
所以我有一个问题。正如我们大多数人在提问时所做的那样。
我们的网站应该可以在 IE 中普遍运行,理想情况下至少也可以在 Chrome 中运行。目前 Chrome 可以被诅咒,因为 IE 被证明是不合作的(大惊喜吧?)。
我的任务是制作我们的一份报告,该报告以非常具体的方式混合使用了 Telerik RadGrids 和 Fusion Charts 图表。此过程涉及必须将我的报告 div(以下代码中的 ReportDataContainer)复制到 child window.
在non-compat/edge模式下,它工作正常。主要报告加载。点击打印按钮,弹出,出现新的window。将 ReportDataContainer 内容与 Fusion Charts 渲染方法的 JS 处理程序一起写入新的 window,一旦两者都被渲染 - 调用 print.
然而,在兼容模式下,图表永远不会在新的 window 上加载。不知道为什么 - 它在原始报告中呈现良好。
无论如何,一些代码。
这是我用来弹出新 window 的 JS,写入并打印:-
function PrintDrill() {
var cssArray = document.getElementsByTagName('style');
var css = "";
for (var i = 0; i < cssArray.length; i++) {
css += "<style type='text/css'>" + cssArray[i].innerHTML + "</style>";
}
drill = window.open();
drill.document.write("<html>" +
"<head>" + css +
"<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />" +
"<script type='text/javascript'>" +
"function FC_Rendered(DOMId) { $(\"#\" + DOMId.split(\"_\")[0] + \"Loaded\").val('true'); } " +
"<\/script>" +
"<script type=\"text/javascript\" src='/CTWebScripts/Libraries/jquery-1.5.min.js'><\/script>" +
"<script type=\"text/javascript\" src='/CTWebScripts/Libraries/jquery.color.js'><\/script>" +
"</head>" +
"<body>" +
"<input type='hidden' id='divActualYearGraphLoaded' name='actualYearGraphLoaded' value='false' />" +
"<input type='hidden' id='divParcGraphLoaded' name='parcGraphLoaded' value='false' />" +
$("#ReportDataContainer").html() +
"</body>");
drill.document.close();
setTimeout(finishedRendering, 2000);
}
var drill = null;
function finishedRendering() {
var loadedActualYear = $('#divActualYearGraphLoaded', drill.document).val();
var loadedParc = $('#divParcGraphLoaded', drill.document).val();
if (loadedActualYear == 'true' && loadedParc == 'true') {
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0)
drill.location.reload();
setTimeout(printMyChild, 3000);
} else {
setTimeout(finishedRendering, 1000);
}
}
function printMyChild() {
drill.print();
}
这里是 FusionChart 呈现的两种方式,第一条边(有效的边):-
<div id="divActualYearGraph_Control_ChartDivDiv">
<object width="100%" height="430" class="FusionCharts" id="divActualYearGraph_Control_ChartDiv" data="/CTWebCharts/V3/StackedColumn3DLine.swf" type="application/x-shockwave-flash" lang="EN" style="visibility: visible;">
<param name="scaleMode" value="noScale">
<param name="scale" value="noScale">
<param name="wMode" value="opaque">
<param name="bgColor" value="#ffffff">
<param name="allowScriptAccess" value="always">
<param name="quality" value="best">
<param name="flashvars" value="*snip*">
</object>
其次是兼容模式 - 也就是不起作用的模式(无论如何在新的 window 上 :/ ):-
<DIV id=divActualYearGraph_Control_ChartDivDiv>
<OBJECT lang=EN id=divActualYearGraph_Control_ChartDiv class=FusionCharts style="VISIBILITY: visible" classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 width="100%" height=430>
<PARAM NAME="_cx" VALUE="10081">
<PARAM NAME="_cy" VALUE="11377">
<PARAM NAME="FlashVars" VALUE="*snip*">
<PARAM NAME="Movie" VALUE="/CTWebCharts/V3/StackedColumn3DLine.swf">
<PARAM NAME="Src" VALUE="/CTWebCharts/V3/StackedColumn3DLine.swf">
<PARAM NAME="WMode" VALUE="Opaque">
<PARAM NAME="Play" VALUE="0">
<PARAM NAME="Loop" VALUE="-1">
<PARAM NAME="Quality" VALUE="High">
<PARAM NAME="SAlign" VALUE="LT">
<PARAM NAME="Menu" VALUE="-1">
<PARAM NAME="Base" VALUE="">
<PARAM NAME="AllowScriptAccess" VALUE="always">
<PARAM NAME="Scale" VALUE="NoScale">
<PARAM NAME="DeviceFont" VALUE="0">
<PARAM NAME="EmbedMovie" VALUE="0">
<PARAM NAME="BGColor" VALUE="FFFFFF">
<PARAM NAME="SWRemote" VALUE="">
<PARAM NAME="MovieData" VALUE="">
<PARAM NAME="SeamlessTabbing" VALUE="1">
<PARAM NAME="Profile" VALUE="0">
<PARAM NAME="ProfileAddress" VALUE="">
<PARAM NAME="ProfilePort" VALUE="0">
<PARAM NAME="AllowNetworking" VALUE="all">
<PARAM NAME="AllowFullScreen" VALUE="false">
<PARAM NAME="AllowFullScreenInteractive" VALUE="false">
<PARAM NAME="IsDependent" VALUE="0">
</OBJECT>
所以是的 - 效果图非常不同。只是将新的 window 改为边缘?不起作用。强制主报告首先进入 edge 也会导致一切乱套。不是一个选项。
我试过复制到 iframe 来打印。同样的问题。
也发布在 FusionCharts 论坛上,尽管是以稍微不连贯的方式。
总之。有什么想法吗?
好的,所以我最终想出了一个解决方案。考虑到 FusionCharts 就像 "OMG, you on an old version! Upgrade!",在技术上并不理想,但不幸的是,该解决方案超出了我采取行动的权限。
第一个大的变化?子文档必须完成几乎所有的工作。
其次,我没有依赖简单地复制图表对象并希望它能正常工作,而是存储了生成的图表 XML 以在创建后在父页面上呈现报告,然后传递给子页面并在非常具体地将渲染设置为 javascript 渲染器后重新渲染。
如果您跟随我的脚步,请注意这一点 - 存放时要小心。 XML 如果你将它存储在 HiddenField 或类似的东西中,它很可能会给你带来悲伤。因此,请记住使其 HTML 安全,然后在将其拉出并再次渲染之前将其重新解析为原始值。
以防万一有人感兴趣或只是想告诉我这是多么糟糕的黑客攻击 - 这是生成的代码:-
function UndoSafeForHTML(s) {
s = ReplaceAll(s, "\'", "'");
s = ReplaceAll(s, "<", "<");
s = ReplaceAll(s, ">", ">");
return ReplaceAll(s, "<br>", "\n");
}
function ReplaceAll(s, find, replace) {
return s.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
function escapeRegExp(string) {
return string.replace(/([.*+?^=!:${}()|\[\]\/\])/g, "\");
}
function PrintDrill() {
var cssArray = document.getElementsByTagName('style');
var css = "";
for (var i = 0; i < cssArray.length; i++) {
css += "<style type='text/css'>" + cssArray[i].innerHTML + "</style>";
}
var parcXml = document.getElementById('<%# hdnParcChartXml.ClientID %>').value;
var actualXml = document.getElementById('<%# hdnActualChartXml.ClientID %>').value;
parcXml = UndoSafeForHTML(parcXml);
actualXml = UndoSafeForHTML(actualXml);
drill = window.open();
drill.document.write("<html>" +
"<head>" +
css +
"<script type=\"text/javascript\" src='/CTWebScripts/General.js'><\/script>" +
"<script type=\"text/javascript\" src=\"/CTWebCharts/v3/swfobject.js\"><\/script>" +
"<script type=\"text/javascript\" src=\"/CTWebCharts/V3/FusionCharts.js\"><\/script>" +
"<script type=\"text/javascript\" src='/CTWebScripts/Libraries/jquery-1.5.min.js'><\/script>" +
"<script type=\"text/javascript\" src='/CTWebScripts/Libraries/jquery.color.js'><\/script>" +
"<script type='text/javascript'> " +
"var intervalId = null; " +
"function RenderCharts(){ " +
"FusionCharts.setCurrentRenderer('javascript'); " +
"$('#divActualYearGraph_Control_ChartDivDiv').empty(); " +
"$('#divParcGraph_Control_ChartDivDiv').empty(); " +
"updateFusionChart(\"divActualYearGraph_Control_ChartDivDiv\", \"" + actualXml + "\", \"430px\", \"430px\", \"/CTWebCharts/V3/StackedColumn3DLine.swf\", \"divActualYearGraph\");" +
"updateFusionChart(\"divParcGraph_Control_ChartDivDiv\", \"" + parcXml + "\", \"430px\", \"430px\", \"/CTWebCharts/V3/StackedColumn3DLine.swf\", \"divParcGraph\");" +
"intervalId = setInterval(HaveIRenderedYet, 3000);" +
"} " +
"" +
"function HaveIRenderedYet(){" +
"if($('#divParcGraphLoaded').val()=='true'&&$('#divActualYearGraphLoaded').val()=='true'){" +
"" +
"window.print();" +
"setTimeout(function () { "+
"window.close();"+
"}, 10); " +
"clearInterval(intervalId);" +
"} "+
"} " +
"" +
"function FC_Rendered(DOMId) { " +
"$(\"#\" + DOMId.split(\"_\")[0] + \"Loaded\").val('true'); " +
"}" +
"<\/script>" +
"</head>" +
"<body onload='RenderCharts();'>" +
"<input type='hidden' id='divActualYearGraphLoaded' name='actualYearGraphLoaded' value='false' />" +
"<input type='hidden' id='divParcGraphLoaded' name='parcGraphLoaded' value='false' />" +
"<input type='hidden' id='hdnLoadedGraphs' name='loadedGraphs' value='0' />" +
$("#ReportDataContainer").html() +
"</body>");
drill.document.close();
}
var drill = null;
所以我有一个问题。正如我们大多数人在提问时所做的那样。
我们的网站应该可以在 IE 中普遍运行,理想情况下至少也可以在 Chrome 中运行。目前 Chrome 可以被诅咒,因为 IE 被证明是不合作的(大惊喜吧?)。
我的任务是制作我们的一份报告,该报告以非常具体的方式混合使用了 Telerik RadGrids 和 Fusion Charts 图表。此过程涉及必须将我的报告 div(以下代码中的 ReportDataContainer)复制到 child window.
在non-compat/edge模式下,它工作正常。主要报告加载。点击打印按钮,弹出,出现新的window。将 ReportDataContainer 内容与 Fusion Charts 渲染方法的 JS 处理程序一起写入新的 window,一旦两者都被渲染 - 调用 print.
然而,在兼容模式下,图表永远不会在新的 window 上加载。不知道为什么 - 它在原始报告中呈现良好。
无论如何,一些代码。
这是我用来弹出新 window 的 JS,写入并打印:-
function PrintDrill() {
var cssArray = document.getElementsByTagName('style');
var css = "";
for (var i = 0; i < cssArray.length; i++) {
css += "<style type='text/css'>" + cssArray[i].innerHTML + "</style>";
}
drill = window.open();
drill.document.write("<html>" +
"<head>" + css +
"<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />" +
"<script type='text/javascript'>" +
"function FC_Rendered(DOMId) { $(\"#\" + DOMId.split(\"_\")[0] + \"Loaded\").val('true'); } " +
"<\/script>" +
"<script type=\"text/javascript\" src='/CTWebScripts/Libraries/jquery-1.5.min.js'><\/script>" +
"<script type=\"text/javascript\" src='/CTWebScripts/Libraries/jquery.color.js'><\/script>" +
"</head>" +
"<body>" +
"<input type='hidden' id='divActualYearGraphLoaded' name='actualYearGraphLoaded' value='false' />" +
"<input type='hidden' id='divParcGraphLoaded' name='parcGraphLoaded' value='false' />" +
$("#ReportDataContainer").html() +
"</body>");
drill.document.close();
setTimeout(finishedRendering, 2000);
}
var drill = null;
function finishedRendering() {
var loadedActualYear = $('#divActualYearGraphLoaded', drill.document).val();
var loadedParc = $('#divParcGraphLoaded', drill.document).val();
if (loadedActualYear == 'true' && loadedParc == 'true') {
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0)
drill.location.reload();
setTimeout(printMyChild, 3000);
} else {
setTimeout(finishedRendering, 1000);
}
}
function printMyChild() {
drill.print();
}
这里是 FusionChart 呈现的两种方式,第一条边(有效的边):-
<div id="divActualYearGraph_Control_ChartDivDiv">
<object width="100%" height="430" class="FusionCharts" id="divActualYearGraph_Control_ChartDiv" data="/CTWebCharts/V3/StackedColumn3DLine.swf" type="application/x-shockwave-flash" lang="EN" style="visibility: visible;">
<param name="scaleMode" value="noScale">
<param name="scale" value="noScale">
<param name="wMode" value="opaque">
<param name="bgColor" value="#ffffff">
<param name="allowScriptAccess" value="always">
<param name="quality" value="best">
<param name="flashvars" value="*snip*">
</object>
其次是兼容模式 - 也就是不起作用的模式(无论如何在新的 window 上 :/ ):-
<DIV id=divActualYearGraph_Control_ChartDivDiv>
<OBJECT lang=EN id=divActualYearGraph_Control_ChartDiv class=FusionCharts style="VISIBILITY: visible" classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 width="100%" height=430>
<PARAM NAME="_cx" VALUE="10081">
<PARAM NAME="_cy" VALUE="11377">
<PARAM NAME="FlashVars" VALUE="*snip*">
<PARAM NAME="Movie" VALUE="/CTWebCharts/V3/StackedColumn3DLine.swf">
<PARAM NAME="Src" VALUE="/CTWebCharts/V3/StackedColumn3DLine.swf">
<PARAM NAME="WMode" VALUE="Opaque">
<PARAM NAME="Play" VALUE="0">
<PARAM NAME="Loop" VALUE="-1">
<PARAM NAME="Quality" VALUE="High">
<PARAM NAME="SAlign" VALUE="LT">
<PARAM NAME="Menu" VALUE="-1">
<PARAM NAME="Base" VALUE="">
<PARAM NAME="AllowScriptAccess" VALUE="always">
<PARAM NAME="Scale" VALUE="NoScale">
<PARAM NAME="DeviceFont" VALUE="0">
<PARAM NAME="EmbedMovie" VALUE="0">
<PARAM NAME="BGColor" VALUE="FFFFFF">
<PARAM NAME="SWRemote" VALUE="">
<PARAM NAME="MovieData" VALUE="">
<PARAM NAME="SeamlessTabbing" VALUE="1">
<PARAM NAME="Profile" VALUE="0">
<PARAM NAME="ProfileAddress" VALUE="">
<PARAM NAME="ProfilePort" VALUE="0">
<PARAM NAME="AllowNetworking" VALUE="all">
<PARAM NAME="AllowFullScreen" VALUE="false">
<PARAM NAME="AllowFullScreenInteractive" VALUE="false">
<PARAM NAME="IsDependent" VALUE="0">
</OBJECT>
所以是的 - 效果图非常不同。只是将新的 window 改为边缘?不起作用。强制主报告首先进入 edge 也会导致一切乱套。不是一个选项。
我试过复制到 iframe 来打印。同样的问题。
也发布在 FusionCharts 论坛上,尽管是以稍微不连贯的方式。
总之。有什么想法吗?
好的,所以我最终想出了一个解决方案。考虑到 FusionCharts 就像 "OMG, you on an old version! Upgrade!",在技术上并不理想,但不幸的是,该解决方案超出了我采取行动的权限。
第一个大的变化?子文档必须完成几乎所有的工作。
其次,我没有依赖简单地复制图表对象并希望它能正常工作,而是存储了生成的图表 XML 以在创建后在父页面上呈现报告,然后传递给子页面并在非常具体地将渲染设置为 javascript 渲染器后重新渲染。
如果您跟随我的脚步,请注意这一点 - 存放时要小心。 XML 如果你将它存储在 HiddenField 或类似的东西中,它很可能会给你带来悲伤。因此,请记住使其 HTML 安全,然后在将其拉出并再次渲染之前将其重新解析为原始值。
以防万一有人感兴趣或只是想告诉我这是多么糟糕的黑客攻击 - 这是生成的代码:-
function UndoSafeForHTML(s) {
s = ReplaceAll(s, "\'", "'");
s = ReplaceAll(s, "<", "<");
s = ReplaceAll(s, ">", ">");
return ReplaceAll(s, "<br>", "\n");
}
function ReplaceAll(s, find, replace) {
return s.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
function escapeRegExp(string) {
return string.replace(/([.*+?^=!:${}()|\[\]\/\])/g, "\");
}
function PrintDrill() {
var cssArray = document.getElementsByTagName('style');
var css = "";
for (var i = 0; i < cssArray.length; i++) {
css += "<style type='text/css'>" + cssArray[i].innerHTML + "</style>";
}
var parcXml = document.getElementById('<%# hdnParcChartXml.ClientID %>').value;
var actualXml = document.getElementById('<%# hdnActualChartXml.ClientID %>').value;
parcXml = UndoSafeForHTML(parcXml);
actualXml = UndoSafeForHTML(actualXml);
drill = window.open();
drill.document.write("<html>" +
"<head>" +
css +
"<script type=\"text/javascript\" src='/CTWebScripts/General.js'><\/script>" +
"<script type=\"text/javascript\" src=\"/CTWebCharts/v3/swfobject.js\"><\/script>" +
"<script type=\"text/javascript\" src=\"/CTWebCharts/V3/FusionCharts.js\"><\/script>" +
"<script type=\"text/javascript\" src='/CTWebScripts/Libraries/jquery-1.5.min.js'><\/script>" +
"<script type=\"text/javascript\" src='/CTWebScripts/Libraries/jquery.color.js'><\/script>" +
"<script type='text/javascript'> " +
"var intervalId = null; " +
"function RenderCharts(){ " +
"FusionCharts.setCurrentRenderer('javascript'); " +
"$('#divActualYearGraph_Control_ChartDivDiv').empty(); " +
"$('#divParcGraph_Control_ChartDivDiv').empty(); " +
"updateFusionChart(\"divActualYearGraph_Control_ChartDivDiv\", \"" + actualXml + "\", \"430px\", \"430px\", \"/CTWebCharts/V3/StackedColumn3DLine.swf\", \"divActualYearGraph\");" +
"updateFusionChart(\"divParcGraph_Control_ChartDivDiv\", \"" + parcXml + "\", \"430px\", \"430px\", \"/CTWebCharts/V3/StackedColumn3DLine.swf\", \"divParcGraph\");" +
"intervalId = setInterval(HaveIRenderedYet, 3000);" +
"} " +
"" +
"function HaveIRenderedYet(){" +
"if($('#divParcGraphLoaded').val()=='true'&&$('#divActualYearGraphLoaded').val()=='true'){" +
"" +
"window.print();" +
"setTimeout(function () { "+
"window.close();"+
"}, 10); " +
"clearInterval(intervalId);" +
"} "+
"} " +
"" +
"function FC_Rendered(DOMId) { " +
"$(\"#\" + DOMId.split(\"_\")[0] + \"Loaded\").val('true'); " +
"}" +
"<\/script>" +
"</head>" +
"<body onload='RenderCharts();'>" +
"<input type='hidden' id='divActualYearGraphLoaded' name='actualYearGraphLoaded' value='false' />" +
"<input type='hidden' id='divParcGraphLoaded' name='parcGraphLoaded' value='false' />" +
"<input type='hidden' id='hdnLoadedGraphs' name='loadedGraphs' value='0' />" +
$("#ReportDataContainer").html() +
"</body>");
drill.document.close();
}
var drill = null;