X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;ds=sidebyside;f=src%2Fplugins%2Flegend.js;h=40a486344c5124bf0e303d29fc86bfdef6c66bf4;hb=refs%2Fheads%2Fmaster;hp=2e667d24997b060ffdc55ad55151fc83810a459c;hpb=ce31caf22475e3e1fd6d9fea192d61ff4fcd7fac;p=dygraphs.git
diff --git a/src/plugins/legend.js b/src/plugins/legend.js
index 2e667d2..40a4863 100644
--- a/src/plugins/legend.js
+++ b/src/plugins/legend.js
@@ -35,9 +35,6 @@ Legend.prototype.toString = function() {
return "Legend Plugin";
};
-// (defined below)
-var generateLegendDashHTML;
-
/**
* This is called during the dygraph constructor, after options have been set
* but before the data is available.
@@ -52,7 +49,6 @@ var generateLegendDashHTML;
*/
Legend.prototype.activate = function(g) {
var div;
- var divWidth = g.getOption('labelsDivWidth');
var userLabelsDiv = g.getOption('labelsDiv');
if (userLabelsDiv && null !== userLabelsDiv) {
@@ -62,35 +58,8 @@ Legend.prototype.activate = function(g) {
div = userLabelsDiv;
}
} else {
- // Default legend styles. These can be overridden in CSS by adding
- // "!important" after your rule, e.g. "left: 30px !important;"
- var messagestyle = {
- "position": "absolute",
- "fontSize": "14px",
- "zIndex": 10,
- "width": divWidth + "px",
- "top": "0px",
- "left": (g.size().width - divWidth - 2) + "px",
- "background": "white",
- "lineHeight": "normal",
- "textAlign": "left",
- "overflow": "hidden"};
-
- // TODO(danvk): get rid of labelsDivStyles? CSS is better.
- utils.update(messagestyle, g.getOption('labelsDivStyles'));
div = document.createElement("div");
div.className = "dygraph-legend";
- for (var name in messagestyle) {
- if (!messagestyle.hasOwnProperty(name)) continue;
-
- try {
- div.style[name] = messagestyle[name];
- } catch (e) {
- console.warn("You are using unsupported css properties for your " +
- "browser in labelsDivStyles");
- }
- }
-
// TODO(danvk): come up with a cleaner way to expose this.
g.graphDiv.appendChild(div);
this.is_generated_div_ = true;
@@ -136,7 +105,7 @@ Legend.prototype.select = function(e) {
if (legendMode === 'follow') {
// create floating legend div
var area = e.dygraph.plotter_.area;
- var labelsDivWidth = e.dygraph.getOption('labelsDivWidth');
+ var labelsDivWidth = this.legend_div_.offsetWidth;
var yAxisLabelWidth = e.dygraph.getOptionForAxis('axisLabelWidth', 'y');
// determine floating [left, top] coordinates of the legend div
// within the plotter_ area
@@ -194,11 +163,10 @@ Legend.prototype.predraw = function(e) {
// TODO(danvk): only use real APIs for this.
e.dygraph.graphDiv.appendChild(this.legend_div_);
- var area = e.dygraph.plotter_.area;
- var labelsDivWidth = e.dygraph.getOption("labelsDivWidth");
+ var area = e.dygraph.getArea();
+ var labelsDivWidth = this.legend_div_.offsetWidth;
this.legend_div_.style.left = area.x + area.w - labelsDivWidth - 1 + "px";
this.legend_div_.style.top = area.y + "px";
- this.legend_div_.style.width = labelsDivWidth + "px";
};
/**
@@ -210,7 +178,6 @@ Legend.prototype.destroy = function() {
};
/**
- * @private
* Generates HTML for the legend which is displayed when hovering over the
* chart. If no selected points are specified, a default legend is returned
* (this may just be the empty string).
@@ -221,70 +188,110 @@ Legend.prototype.destroy = function() {
* relevant when displaying a legend with no selection (i.e. {legend:
* 'always'}) and with dashed lines.
* @param {number} row The selected row index.
+ * @private
*/
Legend.generateLegendHTML = function(g, x, sel_points, oneEmWidth, row) {
+ // Data about the selection to pass to legendFormatter
+ var data = {
+ dygraph: g,
+ x: x,
+ series: []
+ };
+
+ var labelToSeries = {};
+ var labels = g.getLabels();
+ if (labels) {
+ for (var i = 1; i < labels.length; i++) {
+ var series = g.getPropertiesForSeries(labels[i]);
+ var strokePattern = g.getOption('strokePattern', labels[i]);
+ var seriesData = {
+ dashHTML: generateLegendDashHTML(strokePattern, series.color, oneEmWidth),
+ label: labels[i],
+ labelHTML: escapeHTML(labels[i]),
+ isVisible: series.visible,
+ color: series.color
+ };
+
+ data.series.push(seriesData);
+ labelToSeries[labels[i]] = seriesData;
+ }
+ }
+
+ if (typeof(x) !== 'undefined') {
+ var xOptView = g.optionsViewForAxis_('x');
+ var xvf = xOptView('valueFormatter');
+ data.xHTML = xvf.call(g, x, xOptView, labels[0], g, row, 0);
+
+ var yOptViews = [];
+ var num_axes = g.numAxes();
+ for (var i = 0; i < num_axes; i++) {
+ // TODO(danvk): remove this use of a private API
+ yOptViews[i] = g.optionsViewForAxis_('y' + (i ? 1 + i : ''));
+ }
+
+ var showZeros = g.getOption('labelsShowZeroValues');
+ var highlightSeries = g.getHighlightSeries();
+ for (i = 0; i < sel_points.length; i++) {
+ var pt = sel_points[i];
+ var seriesData = labelToSeries[pt.name];
+ seriesData.y = pt.yval;
+
+ if ((pt.yval === 0 && !showZeros) || isNaN(pt.canvasy)) {
+ seriesData.isVisible = false;
+ continue;
+ }
+
+ var series = g.getPropertiesForSeries(pt.name);
+ var yOptView = yOptViews[series.axis - 1];
+ var fmtFunc = yOptView('valueFormatter');
+ var yHTML = fmtFunc.call(g, pt.yval, yOptView, pt.name, g, row, labels.indexOf(pt.name));
+
+ utils.update(seriesData, {yHTML});
+
+ if (pt.name == highlightSeries) {
+ seriesData.isHighlighted = true;
+ }
+ }
+ }
+
+ var formatter = (g.getOption('legendFormatter') || Legend.defaultFormatter);
+ return formatter.call(g, data);
+}
+
+Legend.defaultFormatter = function(data) {
+ var g = data.dygraph;
+
// TODO(danvk): deprecate this option in place of {legend: 'never'}
+ // XXX should this logic be in the formatter?
if (g.getOption('showLabelsOnHighlight') !== true) return '';
- // If no points are selected, we display a default legend. Traditionally,
- // this has been blank. But a better default would be a conventional legend,
- // which provides essential information for a non-interactive chart.
- var html, sepLines, i, dash, strokePattern;
- var labels = g.getLabels();
+ var sepLines = g.getOption('labelsSeparateLines');
+ var html;
- if (typeof(x) === 'undefined') {
+ if (typeof(data.x) === 'undefined') {
+ // TODO: this check is duplicated in generateLegendHTML. Put it in one place.
if (g.getOption('legend') != 'always') {
return '';
}
- sepLines = g.getOption('labelsSeparateLines');
html = '';
- for (i = 1; i < labels.length; i++) {
- var series = g.getPropertiesForSeries(labels[i]);
- if (!series.visible) continue;
+ for (var i = 0; i < data.series.length; i++) {
+ var series = data.series[i];
+ if (!series.isVisible) continue;
if (html !== '') html += (sepLines ? '
' : ' ');
- strokePattern = g.getOption("strokePattern", labels[i]);
- dash = generateLegendDashHTML(strokePattern, series.color, oneEmWidth);
- html += "" +
- dash + " " + escapeHTML(labels[i]) + "";
+ html += `${series.dashHTML} ${series.labelHTML}`;
}
return html;
}
- // TODO(danvk): remove this use of a private API
- var xOptView = g.optionsViewForAxis_('x');
- var xvf = xOptView('valueFormatter');
- html = xvf.call(g, x, xOptView, labels[0], g, row, 0);
- if (html !== '') {
- html += ':';
- }
-
- var yOptViews = [];
- var num_axes = g.numAxes();
- for (i = 0; i < num_axes; i++) {
- // TODO(danvk): remove this use of a private API
- yOptViews[i] = g.optionsViewForAxis_('y' + (i ? 1 + i : ''));
- }
- var showZeros = g.getOption("labelsShowZeroValues");
- sepLines = g.getOption("labelsSeparateLines");
- var highlightSeries = g.getHighlightSeries();
- for (i = 0; i < sel_points.length; i++) {
- var pt = sel_points[i];
- if (pt.yval === 0 && !showZeros) continue;
- if (!utils.isOK(pt.canvasy)) continue;
- if (sepLines) html += "
";
-
- var series = g.getPropertiesForSeries(pt.name);
- var yOptView = yOptViews[series.axis - 1];
- var fmtFunc = yOptView('valueFormatter');
- var yval = fmtFunc.call(g, pt.yval, yOptView, pt.name, g, row, labels.indexOf(pt.name));
-
- var cls = (pt.name == highlightSeries) ? " class='highlight'" : "";
-
- // TODO(danvk): use a template string here and make it an attribute.
- html += "" + " " +
- escapeHTML(pt.name) + ": " + yval + "";
+ html = data.xHTML + ':';
+ for (var i = 0; i < data.series.length; i++) {
+ var series = data.series[i];
+ if (!series.isVisible) continue;
+ if (sepLines) html += '
';
+ var cls = series.isHighlighted ? ' class="highlight"' : '';
+ html += ` ${series.labelHTML}: ${series.yHTML}`;
}
return html;
};
@@ -301,12 +308,11 @@ Legend.generateLegendHTML = function(g, x, sel_points, oneEmWidth, row) {
* @param oneEmWidth The width in pixels of 1em in the legend.
* @private
*/
-generateLegendDashHTML = function(strokePattern, color, oneEmWidth) {
+// TODO(danvk): cache the results of this
+function generateLegendDashHTML(strokePattern, color, oneEmWidth) {
// Easy, common case: a solid line
if (!strokePattern || strokePattern.length <= 1) {
- return "