Search code examples
dojographingdojox.charting

Hiding a series by default in a spider plot


I have a spider plot in using the graphing library of Dojo defined like this:

require([
    "dojox/charting/Chart", 
    "dojox/charting/themes/Claro", 
    "dojox/charting/plot2d/Spider", 
    "dojox/charting/action2d/Tooltip", 
    "dojox/charting/widget/SelectableLegend", 
    "dojox/charting/axis2d/Default"
    ], function (Chart, theme, Spider, Tooltip, Legend, Default) {
        var chart = new Chart(element).setTheme(theme).addPlot("default", {
            type: Spider,
            radius: 200,
            fontColor: "black",
            labelOffset: "-20"
        });
        var colors = ["blue", "red", "green", "yellow", "purple", "orange", "teal", 
                    "maroon", "olive", "lime", "aqua", "fuchsia"];
        $.each(factors, function (index, factor) {
            chart.addAxis(factor.name, {
                 type: Default,
                 min: factor.min,
                 max: factor.max
             });
        });
        $.each(presets, function (pIndex, preset) {
            var data = [];
            $.each(factors, function (fIndex, factor) {
                 data[factor.name] = preset.values[fIndex];
            });
            chart.addSeries(preset.short, data, {
                 fill: colors[pIndex % colors.length]
            });
        });
        new Tooltip(chart, "default");
        chart.render();
        new Legend({
            chart: chart,
            horizontal: false
        }, $(element).next(".legend")[0]);
    });

I add a series for every member of an array called presets and I use a selectable legend that lets the user turn them on or off as they want. However, what I can't seem to find in the docs is how to start a series in the unselected, not visible state? What I ideally want to do is cap the number of series visible when the page loads because in some cases I have up to 14 presets and it just looks a mess until the user deselects a bunch. So I'd like to have, say, every preset above the first 5 be hidden at the start.

Here's a crude fiddle I've knocked to demonstrate. What I want is to have some of the series unselected when the plot is first displayed.

Update: I tried adding this after adding my series:

var checkboxes = $(".dijitCheckBoxInput").each((index, elem) => {
     if (index > 4) {
         elem.click();
     }
});

Which works, but seems very fragile. If they change the class assigned to checkboxes, it'll break. Also, it prohibits me using more than one set of dojo checkboxes because I don't have a good way to tell the difference. (Note, the IDs of the checkboxes added by the SelectableLegend are dijit_form_CheckBox_0, dijit_form_CheckBox_1, etc, which also gives no useful information as to what they are related to). I thought I might be able to use the legend placeholder div as a way to select the descendant checkboxes, but it appears that Dojo replaces the placeholder entirely with a table.


Solution

  • i looked into the dojo code and found the area in which the shapes are toggled on & off whitin the SelectableLegend.js :

              var legendCheckBox = query(".dijitCheckBox", legend)[0];
              hub.connect(legendCheckBox, "onclick", this, function(e){
                  this._toggle(shapes, i, legend.vanished, originalDyn, seriesName, plotName);
                  legend.vanished = !legend.vanished;
                  e.stopPropagation();
              });
    

    The toggling process is very complex and is based on many local attributes:

    _toggle: function(shapes, index, isOff, dyn, seriesName, plotName){
                arrayUtil.forEach(shapes, function(shape, i){
                    var startFill = dyn.fills[i],
                        endFill = this._getTransitionFill(plotName),
                        startStroke = dyn.strokes[i],
                        endStroke = this.transitionStroke;
                    if(startFill){
                        if(endFill && (typeof startFill == "string" || startFill instanceof Color)){
                            fx.animateFill({
                                shape: shape,
                                color: {
                                    start: isOff ? endFill : startFill,
                                    end: isOff ? startFill : endFill
                                }
                            }).play();
                        }else{
                            shape.setFill(isOff ? startFill : endFill);
                        }
                    }
                    if(startStroke && !this.outline){
                        shape.setStroke(isOff ? startStroke : endStroke);
                    }
                }, this);
            }
    

    I tried also checking & unchecking the dijit/form/Checkbox in a legend manually, but that does not trigger the _toggle function in any case, even if you do a render() / fullrender() on the chart.

    With that in mind it seems that there is no other possibilty to toggle the series on and off than by firing the onclick events manually.

    To make your code less fragile, you could access the Checkbox widgets within the legend manually using:

    query(".dijitCheckBox", legend); // Should deliver an array containing the widgets.

    and triggering the onclick event on them. Their keynumber in the array should correspond to the order the series where added...

    Dojo is a fine piece of work, please dont stop working with it !