Loading multiple Flot pie charts from external js

2019-08-11 17:30发布

问题:

Using Flot to create a whole bunch of pie charts across a site.

I'm finding that if a chart is defined, but on a given page the div it's assigned to isn't there or doesn't have the height/width set, that chart and all those defined thereafter do not display.

The issue is that some charts are needed in some pages and not in others. I'd like to define the charts all in one place and place them in their appropriate views as needed, but with Flot Pie it seems that as soon as the script comes up with no place to put a given chart, the script thereafter simply blows up and no chart is loaded after that point. This even happens if those subsequent charts are on another page/view.

Here's a fiddle illustrating the issue. If you remove the commented div in the HTML, the rest of the charts will then load when run. But comment out any of these divs, console will throw the error:

Uncaught Error: Invalid dimensions for plot, width = null, height = null

...and the charts will thereafter fail to load. Since there's nowhere to put the chart, I understand the error. But shouldn't it simply be ignored and the rest of the script executed?

This issue has been asked about before on SO, but didn't draw so much as a comment until I came along with the same issue. I'd have to agree with Richard that this seems like this would be a common problem if it's inherent in the implementation. Is there no way around this?

HTML:

<h2>Performance</h2>
<div id="container-flot-districtLMCore">
  <div id="flot-placeholder-DistrictLMCore" style="width:340px;height:300px"></div>
</div>
<!--<h2>Creative Thinking</h2>
<div id="container-flot-creative">
  <div id="flot-placeholder-creative" style="width:505px;height:300px"></div>
</div> Commenting this out blows up the script thereafter -->
<h2>Critical Thinking</h2>
<div id="container-flot-critical">
  <div style="width:505px;height:300px;text-align:center;" id="flot-placeholder-critical"></div>
</div>
<h2>Affective Domain</h2>
<div id="container-flot-affective">
  <div style="width:505px;height:300px;text-align:center;" id="flot-placeholder-affective"></div>
</div>
<h2>Attitudes</h2>
<div id="container-flot-attitudes">
  <div style="width:505px;height:300px;text-align:center;" id="flot-placeholder-attitudes"></div>
</div>

JQuery:

$(document).ready(function () {
    var dataSetDistrictLMCore = [
    {label: "95% - 100%", data: 56, color: "#006837" },
    { label: "80% - 94%", data: 10, color: "#18859d" },
    { label: "70% - 79%", data: 9, color: "#ef9521" },
    { label: "Below 70%", data: 25, color: "#c62037" }   
];
  var dataSetCreative = [
    {label: "Mastered", data: 26, color: "#007700" },
    { label: "Not Mastered", data: 14, color: "#cc0000" },
    { label: "Not Attempted", data: 60, color: "#ACAAA5" }   
];
    var dataSetCritical = [
    {label: "Mastered", data: 24, color: "#007700" },
    { label: "Not Mastered", data: 49, color: "#cc0000" },
    { label: "Not Attempted", data: 27, color: "#ACAAA5" }   
];
    var dataSetAffective = [
    {label: "Best Answer", data: 33.3, color: "#007700" },
    { label: "Other Answer", data: 33.3, color: "#cc0000" },
    { label: "No Answer", data: 33.3, color: "#ACAAA5" }   
];
    var dataSetAttitudes = [
    {label: "Best Answer", data: 43.3, color: "#007700" },
    { label: "Other Answer", data: 13.3, color: "#cc0000" },
    { label: "No Answer", data: 43.3, color: "#ACAAA5" }   
];


    var options2 = {
        series: {
            pie: {
                show: true,
                innerRadius: 0.5,
                label: {
                    show: true
                },
                offset: {
                    left: 0,
                    top: -24
                }
            }
        }
    };  

$(window).load(function () {
        $.plot($("#flot-placeholder-DistrictLMCore"), dataSetDistrictLMCore, options2);
        $("#flot-placeholder-DistrictLMCore").showMemo();
        $.plot($("#flot-placeholder-creative"), dataSetCreative, options2);
        $("#flot-placeholder-creative").showMemo();
        $.plot($("#flot-placeholder-critical"), dataSetCritical, options2);
        $("#flot-placeholder-critical").showMemo();
        $.plot($("#flot-placeholder-affective"), dataSetAffective, options2);
        $("#flot-placeholder-affective").showMemo();
        $.plot($("#flot-placeholder-attitudes"), dataSetAttitudes, options2);
        $("#flot-placeholder-affective").showMemo();/**/
    });



    $.fn.showMemo = function () {
        $(this).bind("plothover", function (event, pos, item) {
            if (!item) { return; }
            console.log(item.series.data)
            var html = [];
            var percent = parseFloat(item.series.percent).toFixed(2);        

            html.push("<div style=\"border:1px solid grey;background-color:",
          item.series.color,
          "\">",
          "<span style=\"color:white\">",
          item.series.label,
          " : ",
          $.formatNumber(item.series.data[0][1], { format: "#,###", locale: "us" }),
          " (", percent, "%)",
          "</span>", 
          "</div>");
            $("#flot-memo").html(html.join(''));
        });
    };


    });

EDIT: I should mention that the issue persists even if I were to try to load different charts from a different docready or even a different js file.

回答1:

You try to draw a chart inside a non-existing div element, so you get an error and execution of your JavaScript holds. The best way to handle this is to only draw the charts you want on this specific page.

Another way to get this working would be to catch the exceptions for each chart, so that the following charts will be drawn regardless of errors with the previous charts. This works for all kinds of problems, not only the "container not found" one. See this fiddle:

function drawChart(container, data) {
    try {
        $.plot($("#" + container), data, options2);
        $("#" + container).showMemo();
    } catch (ex) {
        console.log(ex);
    }
}

$(window).load(function () {
    drawChart("flot-placeholder-DistrictLMCore", dataSetDistrictLMCore);
    drawChart("flot-placeholder-creative", dataSetCreative);
    drawChart("flot-placeholder-critical", dataSetCritical);
    drawChart("flot-placeholder-affective", dataSetAffective);
    drawChart("flot-placeholder-attitudes", dataSetAttitudes);
});