Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Add a custom hover control for bar charts. #1209

Merged
merged 1 commit into from over 1 year ago

2 participants

Mike Cooper ricky rosario
Mike Cooper
Collaborator

The default hover detail for Rickshaw works really well for line plots and scatter plots, but pretty crappy for bar charts, which we are using. This adds a subclass of the default hover detail that is specialized for bar charts.

I'm going to try and get this accepted up stream at some point.

r?

Mike Cooper mythmon Add a custom hover control for bar charts.
I'm going to try and get this accepted up stream at some point.
ed37a08
ricky rosario
Collaborator
rlr commented

oh i like that much better! ship it! r+

Mike Cooper mythmon merged commit ed37a08 into from
Mike Cooper mythmon closed this
Mike Cooper
Collaborator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Mar 19, 2013
Mike Cooper mythmon Add a custom hover control for bar charts.
I'm going to try and get this accepted up stream at some point.
ed37a08
This page is out of date. Refresh to see the latest.
153 media/js/Rickshaw.Graph.BarHoverDetail.js
... ... @@ -0,0 +1,153 @@
  1 +Rickshaw.namespace('Rickshaw.Graph.BarHoverDetail');
  2 +
  3 +/* This is a mostly intact version of Rickshaw.Graph.HoverDetail that
  4 + * is modified to work nicer with the Bar renderer. The data point
  5 + * chosen is based on the rectangle rendered by the Bar renderer, and
  6 + * the tool tip points to the center of that rectangle.
  7 + *
  8 + * The `update` method has changed to modify the hover behavior, and the
  9 + * `render` method has changed to modify the tool tip behavior.
  10 + */
  11 +
  12 +Rickshaw.Graph.BarHoverDetail = Rickshaw.Class.create(Rickshaw.Graph.HoverDetail, {
  13 +
  14 + update: function(e) {
  15 +
  16 + e = e || this.lastEvent;
  17 + if (!e) return;
  18 + this.lastEvent = e;
  19 +
  20 + if (!e.target.nodeName.match(/^(path|svg|rect)$/)) return;
  21 +
  22 + var graph = this.graph;
  23 + var barWidth = graph.renderer.barWidth() + graph.renderer.gapSize;
  24 +
  25 + var eventX = e.offsetX || e.layerX;
  26 + var eventY = e.offsetY || e.layerY;
  27 +
  28 + var j = 0;
  29 + var points = [];
  30 + var nearestPoint;
  31 +
  32 + // Iterate through each series, and find the point that most closely
  33 + // matches the mouse pointer.
  34 + this.graph.series.active().forEach( function(series) {
  35 +
  36 + var data = this.graph.stackedData[j++];
  37 + var domainX = graph.x.invert(eventX);
  38 +
  39 + var domainIndexScale = d3.scale.linear()
  40 + .domain([data[0].x, data.slice(-1)[0].x])
  41 + .range([0, data.length - 1]);
  42 +
  43 + var approximateIndex = Math.round(domainIndexScale(domainX));
  44 + var dataIndex = Math.min(approximateIndex || 0, data.length - 1);
  45 +
  46 + var i = approximateIndex;
  47 + while (i < data.length - 1) {
  48 +
  49 + if (!data[i] || !data[i + 1]) break;
  50 +
  51 + if (data[i].x <= domainX && data[i + 1].x > domainX) {
  52 + dataIndex = i;
  53 + break;
  54 + }
  55 +
  56 + if (data[i + 1].x <= domainX) { i++; } else { i--; }
  57 + }
  58 +
  59 + if (dataIndex < 0) dataIndex = 0;
  60 + var value = data[dataIndex];
  61 +
  62 + var left = graph.x(value.x);
  63 + var right = left + barWidth;
  64 + var bottom = graph.y(value.y0);
  65 + var top = graph.y(value.y + value.y0);
  66 +
  67 + var point = {
  68 + series: series,
  69 + value: value,
  70 + order: j,
  71 + name: series.name
  72 + };
  73 +
  74 + if (left <= eventX && eventX < right &&
  75 + top <= eventY && eventY < bottom) {
  76 +
  77 + nearestPoint = point;
  78 + }
  79 +
  80 + points.push(point);
  81 +
  82 + }, this );
  83 +
  84 + var renderArgs = {
  85 + points: points,
  86 + detail: points,
  87 + mouseX: eventX,
  88 + mouseY: eventY
  89 + };
  90 +
  91 + if (nearestPoint) {
  92 + nearestPoint.active = true;
  93 + }
  94 +
  95 + if (this.visible) {
  96 + this.render(renderArgs);
  97 + }
  98 + },
  99 +
  100 + render: function(args) {
  101 +
  102 + var graph = this.graph;
  103 + var points = args.points;
  104 + var barWidth = graph.renderer.barWidth() + graph.renderer.gapSize;
  105 +
  106 + var point = points.filter(function(p) {return p.active;}).shift();
  107 +
  108 + if (!point || point.value.y === null) {
  109 + return;
  110 + }
  111 +
  112 + var formattedXValue = this.xFormatter(point.value.x);
  113 + var formattedYValue = this.yFormatter(point.value.y);
  114 +
  115 + this.element.innerHTML = '';
  116 + this.element.style.left = (graph.x(point.value.x) + barWidth / 2) + 'px';
  117 +
  118 + var xLabel = document.createElement('div');
  119 +
  120 + xLabel.className = 'x_label';
  121 + xLabel.innerHTML = formattedXValue;
  122 + this.element.appendChild(xLabel);
  123 +
  124 + var item = document.createElement('div');
  125 +
  126 + item.className = 'item';
  127 + item.innerHTML = this.formatter(point.series, point.value.x, point.value.y,
  128 + formattedXValue, formattedYValue, point);
  129 + item.style.top = this.graph.y(point.value.y0 + point.value.y / 2) + 'px';
  130 +
  131 + this.element.appendChild(item);
  132 +
  133 + var dot = document.createElement('div');
  134 +
  135 + dot.className = 'dot';
  136 + dot.style.top = item.style.top;
  137 + dot.style.borderColor = point.series.color;
  138 +
  139 + this.element.appendChild(dot);
  140 +
  141 + if (point.active) {
  142 + item.className = 'item active';
  143 + dot.className = 'dot active';
  144 + }
  145 +
  146 + this.show();
  147 +
  148 + if (typeof this.onRender == 'function') {
  149 + this.onRender(args);
  150 + }
  151 + }
  152 +});
  153 +
2  media/js/questions.stats.js
@@ -11,7 +11,7 @@ function makeGraph($elem, data) {
11 11 renderer: 'bar'
12 12 });
13 13
14   - var hoverDetail = new Rickshaw.Graph.HoverDetail( {
  14 + var hoverDetail = new Rickshaw.Graph.BarHoverDetail( {
15 15 graph: graph
16 16 });
17 17
1  settings.py
@@ -678,6 +678,7 @@ def JINJA_CONFIG():
678 678 'js/libs/d3.v3.min.js',
679 679 'js/libs/d3.layout.min.js',
680 680 'js/libs/rickshaw.min.js',
  681 + 'js/Rickshaw.Graph.BarHoverDetail.js',
681 682 'js/questions.stats.js',
682 683 ),
683 684 'mobile/questions': (

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.