diff --git a/Makefile b/Makefile index c3abbe2a..52d079dc 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,7 @@ JS_FILES=\ src/js/Rickshaw.Graph.Behavior.Series.Order.js\ src/js/Rickshaw.Graph.Behavior.Series.Toggle.js\ src/js/Rickshaw.Graph.HoverDetail.js\ + src/js/Rickshaw.Graph.ClickDetail.js\ src/js/Rickshaw.Graph.JSONP.js\ src/js/Rickshaw.Graph.Legend.js\ src/js/Rickshaw.Graph.RangeSlider.js\ diff --git a/src/js/Rickshaw.Graph.ClickDetail.js b/src/js/Rickshaw.Graph.ClickDetail.js new file mode 100644 index 00000000..32eae1f2 --- /dev/null +++ b/src/js/Rickshaw.Graph.ClickDetail.js @@ -0,0 +1,99 @@ +Rickshaw.namespace('Rickshaw.Graph.ClickDetail'); + +Rickshaw.Graph.ClickDetail = Rickshaw.Class.create({ + + initialize: function(args) { + + var graph = this.graph = args.graph; + + this._addListeners(); + + this.onClick = args.onClick; + + }, + + update: function(e) { + + if (!e.target.nodeName.match(/^(path|svg|rect|circle)$/)) return; + + var graph = this.graph; + + var eventX = e.offsetX || e.layerX; + var eventY = e.offsetY || e.layerY; + + var j = 0; + var points = []; + var nearestPoint; + + this.graph.series.active().forEach( function(series) { + + var data = this.graph.stackedData[j++]; + + if (!data.length) + return; + + var domainX = graph.x.invert(eventX); + + var domainIndexScale = d3.scale.linear() + .domain([data[0].x, data.slice(-1)[0].x]) + .range([0, data.length - 1]); + + var approximateIndex = Math.round(domainIndexScale(domainX)); + if (approximateIndex == data.length - 1) approximateIndex--; + + var dataIndex = Math.min(approximateIndex || 0, data.length - 1); + + for (var i = approximateIndex; i < data.length - 1;) { + + if (!data[i] || !data[i + 1]) break; + + if (data[i].x <= domainX && data[i + 1].x > domainX) { + dataIndex = Math.abs(domainX - data[i].x) < Math.abs(domainX - data[i + 1].x) ? i : i + 1; + break; + } + + if (data[i + 1].x <= domainX) { i++ } else { i-- } + } + + if (dataIndex < 0) dataIndex = 0; + var value = data[dataIndex]; + + var distance = Math.sqrt( + Math.pow(Math.abs(graph.x(value.x) - eventX), 2) + + Math.pow(Math.abs(graph.y(value.y + value.y0) - eventY), 2) + ); + + var point = { + yValue: series.scale ? series.scale.invert(value.y) : value.y, + series: series, + value: value, + distance: distance, + order: j, + name: series.name + }; + + if (!nearestPoint || distance < nearestPoint.distance) { + nearestPoint = point; + } + + points.push(point); + + }, this ); + + if (!nearestPoint) + return; + + this.onClick(nearestPoint); + + }, + + _addListeners: function() { + this.graph.element.addEventListener( + 'click', + function(e) { + this.update(e); + }.bind(this), + false + ); + } +});