Reputation: 16567
I have an implementation of ABCPdf 13.3.0 that I am trying to render html content on the server. To do so, I am using the Webkit engine because it supports importing custom fonts, and because Gecko does not render the report nearly as well.
Everything was working great, up until I needed to add Highcharts into the mix. I have found a way to generate the highcharts markup, which uses javascript. When I load my raw markup in the browser, the chart shows as expected. However, when I send that same markup through ABCPDF, everything renders except the chart.
Here's an example of the raw html for the area with the chart, with the high charts generated markup included:
<div class="report-all-block">
<div class="graph-block">
<div id="left-projection-chart" class="monthly-projections-chart"><div id='f471be1cb2024da284178920e0794b6d' style='height:170;min-width:;clear:both;margin: 0 auto;'></div><script type='text/javascript'>if (document.addEventListener) {document.addEventListener("DOMContentLoaded", function() {createChartf471be1cb2024da284178920e0794b6d();});} else if (document.attachEvent) {document.attachEvent("onreadystatechange", function(){if (document.readyState === "complete"){document.detachEvent("onreadystatechange", arguments.callee);createChartf471be1cb2024da284178920e0794b6d();}});}function createChartf471be1cb2024da284178920e0794b6d() {var ChartOptions = {"exporting":{"enabled":false},"title":{"text":""},"yAxis":[{"title":{"text":""},"min":0.0}],"xAxis":[{"categories":["62","63","64","65","66","67","68","69","70"]}],"credits":{"enabled":false},"legend":{"enabled":false},"chart":{"marginTop":0.0,"renderTo":"f471be1cb2024da284178920e0794b6d","marginRight":0.0,"height":"170","marginBottom":0.0,"marginLeft":0.0},"series":[{"color":"rgb(217,217,216)","type":"column","data":[{"y":2344.0,"x":62.0},{"y":2597.0,"x":63.0},{"y":2881.0,"x":64.0},{"y":3246.0,"x":65.0},{"y":3635.0,"x":66.0},{"y":4051.0,"x":67.0},{"y":4550.0,"x":68.0},{"y":5082.0,"x":69.0},{"y":5650.0,"x":70.0}],"dataLabels":{"inside":true,"format":"${text}","enabled":true}}],"plotOptions":{"column":{"stacking":"normal","animation":{"duration":0},"dataLabels":{"enabled":false}}}};Highcharts.chart("f471be1cb2024da284178920e0794b6d",ChartOptions);}</script></div>
<label class="label-style w-100 float-left textcenter"><strong>Test</strong></label>
</div>
<div class="graph-block">
</div>
</div>
I have tried various ways of delaying rendering, including attempting to use javascript (works for Gecko, but not Webkit), and I tried using some settings from a post I found:
document.SetInfo(0, "RenderDelay", "500")
document.SetInfo(0, "OneStageRender", 0)
And here is the basic logic of my renderer (.net 9.0)
public async Task<byte[]> RenderMarkupToPdfAsync(PdfOptions options,
CancellationToken cancellationToken = default)
{
if (!XSettings.LicenseValid)
{
//license key installation omitted for brevity
}
using var document = new Doc();
document.HtmlOptions.Engine = EngineType.WebKit;
document.HtmlOptions.UseScript = options.EnableJavascript;
document.HtmlOptions.Media = MediaType.Screen;
document.HtmlOptions.ForWebKit.UseScript = true;
document.HtmlOptions.ForWebKit.OnLoadScript = $"window.ABCpdf_go = false; (function(){{ setTimeout(function(){{ window.ABCpdf_go = true; }}, 2000); }})();";
if (options.EnableJavascript && options.JavascriptWaitDuration.TotalMilliseconds > 0)
{
document.HtmlOptions.OnLoadScript = $"(function(){{ window.ABCpdf_go = false; setTimeout(function(){{ window.ABCpdf_go = true; }}, {options.JavascriptWaitDuration.TotalMilliseconds}); }})();";
}
foreach (var fontUri in options.FontUris)
{
document.AddImageUrl(fontUri.AbsoluteUri);
}
if (options.HorizontalMargin > 0 || options.VerticalMargin > 0)
{
document.Rect.Inset(options.HorizontalMargin, options.VerticalMargin);
}
var imageId = document.AddImageHtml(options.Html, true, 680, true);
while (document.Chainable(imageId))
{
document.Page = document.AddPage();
imageId = document.AddImageToChain(imageId);
}
//remove blank pages
for (var i = document.PageCount; i > 0; i--)
{
document.PageNumber = i;
//get the pdf content
var textContent = document.GetText("Text");
//delete the page if it is blank
if (string.IsNullOrEmpty(textContent))
{
document.Delete(document.Page);
}
}
//add page numbers to all pages after the cover page
if (options.IncludePageNumbers)
{
for (var i = 2; i <= document.PageCount; i++)
{
document.PageNumber = i;
document.Rect.SetRect(280, 15, 280, 15);
document.AddTextStyled("<p align='right'>" + document.PageNumber + "</p>");
document.Flatten();
}
}
var bytes = document.GetData();
document.Clear();
return bytes;
}
Any ideas on how to get ABCPDF to delay rendering so it gives Highcharts a chance to draw the chart?
Here is my chart definition as created using the C# nuget library, just so you can see the options I am setting:
public static Highcharts Create(Dictionary<int, int> data)
{
var chart = new Highcharts()
{
ID = Guid.NewGuid().ToString("N"),
Chart = new Chart()
{
Height = "170",
MarginLeft = 0,
MarginRight = 0,
MarginTop = 0,
MarginBottom = 0
},
Title = new Title()
{
Text = ""
},
XAxis =
[
new XAxis
{
Categories = data.Keys.OrderBy(k => k).Select(k => k.ToString()).ToList()
}
],
YAxis =
[
new YAxis
{
Min = 0,
Title = new YAxisTitle()
{
Text = ""
}
}
],
Series =
[
new ColumnSeries()
{
Data = data.Select(d => new ColumnSeriesData()
{
X = d.Key,
Y = d.Value
}).ToList(),
Color = "rgb(217,217,216)",
DataLabels = new ColumnSeriesDataLabels()
{
Enabled = true,
Inside = true,
Format = "${text}"
}
}
],
PlotOptions = new PlotOptions()
{
Column = new PlotOptionsColumn()
{
Stacking = PlotOptionsColumnStacking.Normal,
//AnimationBool = false,
Animation = new Animation()
{
Duration = 0
},
DataLabels = new PlotOptionsColumnDataLabels()
{
Enabled = false
}
}
},
Exporting = new Exporting()
{
Enabled = false
},
Credits = new Credits()
{
Enabled = false
},
Legend = new Legend()
{
Enabled = false
}
};
return chart;
}
Upvotes: 0
Views: 31