Mforns has submitted this change and it was merged.

Change subject: Sort the legend by value and align it
......................................................................


Sort the legend by value and align it

mforns had this idea of sorting the legend in descending order and I
ignored it because it would've required a big hack.  It turns out that
styling the legend labels requires the big hack anyway, so I did it and
I love it, it makes the graph make so much more sense.

Bug: T131935
Change-Id: I93a749f4d354d1e2ca1ba7c95ef1c21efb19cabd
---
M bower.json
M src/app/require.config.js
M src/components/visualizers/dygraphs-timeseries/bindings.js
M src/components/visualizers/dygraphs-timeseries/dygraphs-timeseries.html
A src/components/visualizers/dygraphs-timeseries/dygraphs.patch.js
5 files changed, 131 insertions(+), 15 deletions(-)

Approvals:
  Mforns: Verified; Looks good to me, approved



diff --git a/bower.json b/bower.json
index df38e55..583feb0 100644
--- a/bower.json
+++ b/bower.json
@@ -20,7 +20,8 @@
     "twix": "~0.9.0",
     "dygraphs": "~1.1.0",
     "lodash": "3.9.0-amd",
-    "pageviews": null
+    "pageviews": null,
+    "numeral": "^1.5.3"
   },
   "resolutions": {
     "d3": "3.5.2"
diff --git a/src/app/require.config.js b/src/app/require.config.js
index 29312a7..196ff05 100644
--- a/src/app/require.config.js
+++ b/src/app/require.config.js
@@ -9,6 +9,7 @@
         // (Issue reported https://github.com/knockout/knockout/issues/1528)
         'knockout'              : 'bower_modules/knockout/dist/knockout.debug',
         'text'                  : 'bower_modules/requirejs-text/text',
+        'numeral'               : 'bower_modules/numeral/numeral',
         'd3'                    : 'bower_modules/d3/d3',
         'vega'                  : 'bower_modules/vega/vega',
         'datepicker'            : 
'bower_modules/semantic-datepicker/daterangepicker',
diff --git a/src/components/visualizers/dygraphs-timeseries/bindings.js 
b/src/components/visualizers/dygraphs-timeseries/bindings.js
index 22b043a..18dff84 100644
--- a/src/components/visualizers/dygraphs-timeseries/bindings.js
+++ b/src/components/visualizers/dygraphs-timeseries/bindings.js
@@ -1,11 +1,13 @@
+'use strict';
 define(function(require) {
-    'use strict';
 
     var ko = require('knockout'),
         _ = require('lodash'),
-        moment = require('moment');
+        moment = require('moment'),
+        numeral = require('numeral');
 
     require('dygraphs');
+    require('./dygraphs.patch');
 
     ko.bindingHandlers.dygraphs = {
         init: function (element, valueAccessor) {
@@ -36,27 +38,22 @@
                                 },
                                 axisLabelWidth: 77,
                             },
+                            y: {
+                                valueFormatter: function(d) {
+                                    return numeral(d).format(d < 1 ? '0.00' : 
'0.0a');
+                                },
+                            },
                         },
                         labels: ['Date'],
                         labelsKMB: true,
-                        labelsDivWidth: 350,
-                        labelsDivStyles: {
-                            'margin-left': '-120px',
-                            'backgroundColor': 'rgba(255, 255, 255, 0.9)',
-                            'padding': '4px',
-                            'border': '1px solid #dadada',
-                            'borderRadius': '5px',
-                            'boxShadow': '2px 2px 2px #aaa',
-                            'textAlign': 'left',
-                            'fontFamily': 'sans-serif',
-                        },
-                        labelsSeparateLines: true,
+                        // labelsDivStyles: defined as CSS in 
dygraphs-timeseries.html
                         strokeWidth: 1.8,
                         gridLineColor: '#cacaca',
                         gridLinePattern: [10, 5],
                         series: {},
                         showRoller: true,
                         animatedZooms: true,
+                        labelsSeparateLines: true,
                     };
 
                 var patterns = _(data.patternLabels)
diff --git 
a/src/components/visualizers/dygraphs-timeseries/dygraphs-timeseries.html 
b/src/components/visualizers/dygraphs-timeseries/dygraphs-timeseries.html
index 34819c4..27db935 100644
--- a/src/components/visualizers/dygraphs-timeseries/dygraphs-timeseries.html
+++ b/src/components/visualizers/dygraphs-timeseries/dygraphs-timeseries.html
@@ -1,3 +1,31 @@
+<style>
+    div.dygraph-legend {
+        background-color: rgba(255, 255, 255, 0.9)!important;
+        padding: 4px;
+        border: 1px solid #dadada;
+        border-radius: 5px;
+        box-shadow: 2px 2px 2px #aaa;
+        margin-left: -120px;
+        pointer-events: none;
+        width: auto!important;
+    }
+
+    div.dygraph-legend > span {
+        font-weight: bold;
+    }
+    div.dygraph-legend > span > span {
+        padding: 1px 3px 1px 1px;
+        text-align: right;
+        font-family: 'courier new';
+        display: inline-block;
+        width: 70px;
+    }
+    div.dygraph-legend > span > label {
+        padding: 1px 1px 1px 2px;
+        text-align: left;
+    }
+</style>
+
 <div class="parent-of-resizable" data-bind="
     if: data && data.header,
     dygraphs: {
diff --git a/src/components/visualizers/dygraphs-timeseries/dygraphs.patch.js 
b/src/components/visualizers/dygraphs-timeseries/dygraphs.patch.js
new file mode 100644
index 0000000..9d6f8f4
--- /dev/null
+++ b/src/components/visualizers/dygraphs-timeseries/dygraphs.patch.js
@@ -0,0 +1,89 @@
+'use strict';
+define(function(require) {
+
+    require('dygraphs');
+
+    var L = window.Dygraph.Plugins.Legend;
+    var escapeHTML = function(str) {
+        return str.replace(/&/g, '&amp;').replace(/'/g, 
'&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+    };
+
+    /* patch the way the legend HTML is generated.
+     * This kind of override appears to be supported in the next version of
+     *   Dygraphs, but that's not out yet
+     */
+    window.Dygraph.Plugins.Legend.generateLegendHTML = function(g, x, 
sel_points, oneEmWidth, row) {
+        // todo(danvk): deprecate this option in place of {legend: 'never'}
+        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();
+        sepLines = g.getOption('labelsSeparateLines');
+
+        if (typeof x === 'undefined') {
+            if (g.getOption('legend') !== 'always') {
+                return '';
+            }
+
+            html = '';
+            for (i = 1; i < labels.length; i++) {
+                var series = g.getPropertiesForSeries(labels[i]);
+                if (!series.visible) { continue; }
+
+                if (html !== '') { html += (sepLines ? '<br/>' : ' '); }
+                strokePattern = g.getOption('strokePattern', labels[i]);
+                dash = L.generateLegendDashHTML(strokePattern, series.color, 
oneEmWidth);
+                html += '<span style="font-weight: bold; color: ' + 
series.color + ';">' +
+                        dash + ' ' + escapeHTML(labels[i]) + '</span>';
+            }
+            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 += sepLines ? '<hr/>' : ':';
+        }
+
+        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');
+        var highlightSeries = g.getHighlightSeries();
+        sel_points = sel_points.sort(function (a, b) {
+            if(!isFinite(a.yval - b.yval)) {
+                return isFinite(a.yval) ? 1 : -1;
+            }
+            return b.yval - a.yval;
+        });
+        for (i = 0; i < sel_points.length; i++) {
+            var pt = sel_points[i];
+            if (pt.yval === 0 && !showZeros) { continue; }
+            if (!window.Dygraph.isOK(pt.canvasy)) { continue; }
+            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 += '<span' + cls + '>' +
+                        '<span>' + yval + '</span>' +
+                        '<label style="color: ' + series.color + ';">' +
+                            escapeHTML(pt.name) +
+                        '</label>' +
+                    '</span>';
+            if (sepLines) { html += '<br/>'; }
+        }
+        return html;
+    };
+});

-- 
To view, visit https://gerrit.wikimedia.org/r/281947
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I93a749f4d354d1e2ca1ba7c95ef1c21efb19cabd
Gerrit-PatchSet: 1
Gerrit-Project: analytics/dashiki
Gerrit-Branch: master
Gerrit-Owner: Milimetric <[email protected]>
Gerrit-Reviewer: Mforns <[email protected]>
Gerrit-Reviewer: Nuria <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to