Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

checkboxes in legend to control visibility #355

Open
danvk opened this issue Oct 20, 2014 · 5 comments
Open

checkboxes in legend to control visibility #355

danvk opened this issue Oct 20, 2014 · 5 comments

Comments

@danvk
Copy link
Owner

danvk commented Oct 20, 2014

From m...@google.com on April 25, 2012 15:41:14

It would be nice to have an option to show checkboxes in the legend, using which a user can switch the visibility of curves on/off.

Original issue: http://code.google.com/p/dygraphs/issues/detail?id=326

@danvk
Copy link
Owner Author

danvk commented Oct 20, 2014

From da...@google.com on April 30, 2012 16:25:26

This is a fairly common request/addition. It should be implemented in a plugin.

Status: Accepted
Labels: -Type-Defect Type-Enhancement

@danvk
Copy link
Owner Author

danvk commented Oct 20, 2014

From konigsb...@gmail.com on December 04, 2012 04:36:22

Labels: Plugins Component-UI

@danvk
Copy link
Owner Author

danvk commented Oct 20, 2014

From sitnikov...@gmail.com on March 01, 2013 11:02:31

Do you mean plugins/legend.js or some other kind of plugin?

@danvk
Copy link
Owner Author

danvk commented Oct 20, 2014

From dite...@quick.cz on June 14, 2013 02:18:24

It would be handy, to have curves visibility option integrated into legend.

@ben-spiller
Copy link

ben-spiller commented Dec 26, 2019

The good news is that it's possible to get this working fairly well without changes to dygraphs itself using the excellent legendFormatter feature... and I've shared what I came up with below in case it helps others (or is useful for implementing this as a full dygraphs plugin or option).

However there are a couple of limitations in dygraphs that make this a little harder than it could be (would be great if these could be fixed):

  1. There's no way to look up a Dygraph object from event handlers since there's no id in the graphDiv generated by Dygraph (or any way to get the Dygraph instance from the graphDiv once looked up). To save people having to stash these into a custom data structure to permit lookup by id (when they have many or a dynamic number of charts), would be great to have the Dygraph constructor do something similar to what I've put into the legendFormatter, i.e. ensure a graphDiv.id is set and provide a graphDiv.dygraph attribute.
  2. Dygraph.prototype.setColors_ removes the color setting from any series with visibility=false, making it difficult to show the line color in the legend after visibility has been toggled. Think it would make more sense to keep coloring based on index of series and unaffected by which are currently visible, i.e. remove the isVisible check in that function.

Anyway, JavaScript code to add clickable legends is here:

function legendFormatter(data) {
	var dygraph = data.dygraph;
	var html = "";
	var showvalues = data.x != null; // false if there's no selected value currently
	
	// Need a way to lookup the JavaScript dygraph object later from the onclick listener 
	// (using just a javascript string), so assign a unique id to the div and add a data attribute to it
	// (would be great if the dygraphs constructor did this automatically, could be useful for other use cases also)
	if (!dygraph.graphDiv.id) {
		var i = 1;
		while (document.getElementById("__dygraph"+i)) 
			i++;
		dygraph.graphDiv.id = "__dygraph"+i;
	}
	if (!dygraph.graphDiv.dygraph) { dygraph.graphDiv.dygraph = data.dygraph; }
	
	var seriesIndex = 0;
	data.series.forEach(function(series) 
	{
		html += "<label><input type='checkbox' onclick=\\"document.getElementById('"+dygraph.graphDiv.id+"').dygraph.setVisibility("+seriesIndex+", ";
		// nb: we have to use dygraph.visibility() here as series.isVisible has incorrect value for points where y value is undefined
		if (dygraph.visibility()[seriesIndex]) { 
			html += "false);\\" checked>";
		} else {
			html += "true);\\" >"; 
		}
		
		var labeledData = series.labelHTML;
		
		// workaround for the bug where Dygraph.prototype.setColors_ un-sets color for any series where visibility=false; 
		// this workaround gives correct color if configured using options{colors:[...]} and falls back to transparent if not
		series.dashHTML = series.dashHTML.replace("color: undefined;", "color: "+(dygraph.getOption('colors')[seriesIndex] || "rgba(255,255,255,0.0)")+";");
		
		if (showvalues && series != undefined && series.y != undefined) { labeledData += ': ' + series.yHTML; }
		if (series.isHighlighted) { labeledData = '<b>' + labeledData + '</b>'; }
		html += series.dashHTML + " " + labeledData + "</label><br>\\n";
		seriesIndex += 1;
	});
	// Display x value at the end, after all the series (to avoid making them jump up/down when there's no selection)
	if (showvalues) {
		html += this.getLabels()[0] + ': '+data.xHTML;
	}

	return html;
}

var g = new Dygraph(parentdiv, [ ... ], {
	"labels": ["time", "series 1", "series 2"], 
	"colors": ["red", "teal"], // at present, dash color can be shown only in legend only if explicitly specified like this (not when automatic)
	"labelsSeparateLines": true, 
	"legend": "always", // keep legend visible so it's always possible to un-hide series
	"legendFormatter":legendFormatter // override formatting of legend to add checkboxes
	});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants