aboutsummaryrefslogtreecommitdiffstats
path: root/ecomp-sdk-app/src/main/webapp/app/fusion/external/d3/js/interactiveLayer.js
diff options
context:
space:
mode:
Diffstat (limited to 'ecomp-sdk-app/src/main/webapp/app/fusion/external/d3/js/interactiveLayer.js')
-rw-r--r--ecomp-sdk-app/src/main/webapp/app/fusion/external/d3/js/interactiveLayer.js251
1 files changed, 251 insertions, 0 deletions
diff --git a/ecomp-sdk-app/src/main/webapp/app/fusion/external/d3/js/interactiveLayer.js b/ecomp-sdk-app/src/main/webapp/app/fusion/external/d3/js/interactiveLayer.js
new file mode 100644
index 000000000..4dfb68dcc
--- /dev/null
+++ b/ecomp-sdk-app/src/main/webapp/app/fusion/external/d3/js/interactiveLayer.js
@@ -0,0 +1,251 @@
+/* Utility class to handle creation of an interactive layer.
+This places a rectangle on top of the chart. When you mouse move over it, it sends a dispatch
+containing the X-coordinate. It can also render a vertical line where the mouse is located.
+
+dispatch.elementMousemove is the important event to latch onto. It is fired whenever the mouse moves over
+the rectangle. The dispatch is given one object which contains the mouseX/Y location.
+It also has 'pointXValue', which is the conversion of mouseX to the x-axis scale.
+*/
+nv.interactiveGuideline = function() {
+ "use strict";
+ var tooltip = nv.models.tooltip();
+ //Public settings
+ var width = null
+ , height = null
+ //Please pass in the bounding chart's top and left margins
+ //This is important for calculating the correct mouseX/Y positions.
+ , margin = {left: 0, top: 0}
+ , xScale = d3.scale.linear()
+ , yScale = d3.scale.linear()
+ , dispatch = d3.dispatch('elementMousemove', 'elementMouseout','elementDblclick')
+ , showGuideLine = true
+ , svgContainer = null
+ //Must pass in the bounding chart's <svg> container.
+ //The mousemove event is attached to this container.
+ ;
+
+ //Private variables
+ var isMSIE = navigator.userAgent.indexOf("MSIE") !== -1 //Check user-agent for Microsoft Internet Explorer.
+ ;
+
+
+ function layer(selection) {
+ selection.each(function(data) {
+ var container = d3.select(this);
+
+ var availableWidth = (width || 960), availableHeight = (height || 400);
+
+ var wrap = container.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([data]);
+ var wrapEnter = wrap.enter()
+ .append("g").attr("class", " nv-wrap nv-interactiveLineLayer");
+
+
+ wrapEnter.append("g").attr("class","nv-interactiveGuideLine");
+
+ if (!svgContainer) {
+ return;
+ }
+
+ function mouseHandler() {
+ var d3mouse = d3.mouse(this);
+ var mouseX = d3mouse[0];
+ var mouseY = d3mouse[1];
+ var subtractMargin = true;
+ var mouseOutAnyReason = false;
+ if (isMSIE) {
+ /*
+ D3.js (or maybe SVG.getScreenCTM) has a nasty bug in Internet Explorer 10.
+ d3.mouse() returns incorrect X,Y mouse coordinates when mouse moving
+ over a rect in IE 10.
+ However, d3.event.offsetX/Y also returns the mouse coordinates
+ relative to the triggering <rect>. So we use offsetX/Y on IE.
+ */
+ mouseX = d3.event.offsetX;
+ mouseY = d3.event.offsetY;
+
+ /*
+ On IE, if you attach a mouse event listener to the <svg> container,
+ it will actually trigger it for all the child elements (like <path>, <circle>, etc).
+ When this happens on IE, the offsetX/Y is set to where ever the child element
+ is located.
+ As a result, we do NOT need to subtract margins to figure out the mouse X/Y
+ position under this scenario. Removing the line below *will* cause
+ the interactive layer to not work right on IE.
+ */
+ if(d3.event.target.tagName !== "svg")
+ subtractMargin = false;
+
+ if (d3.event.target.className.baseVal.match("nv-legend"))
+ mouseOutAnyReason = true;
+
+ }
+
+ if(subtractMargin) {
+ mouseX -= margin.left;
+ mouseY -= margin.top;
+ }
+
+ /* If mouseX/Y is outside of the chart's bounds,
+ trigger a mouseOut event.
+ */
+ if (mouseX < 0 || mouseY < 0
+ || mouseX > availableWidth || mouseY > availableHeight
+ || (d3.event.relatedTarget && d3.event.relatedTarget.ownerSVGElement === undefined)
+ || mouseOutAnyReason
+ )
+ {
+ if (isMSIE) {
+ if (d3.event.relatedTarget
+ && d3.event.relatedTarget.ownerSVGElement === undefined
+ && d3.event.relatedTarget.className.match(tooltip.nvPointerEventsClass)) {
+ return;
+ }
+ }
+ dispatch.elementMouseout({
+ mouseX: mouseX,
+ mouseY: mouseY
+ });
+ layer.renderGuideLine(null); //hide the guideline
+ return;
+ }
+
+ var pointXValue = xScale.invert(mouseX);
+ dispatch.elementMousemove({
+ mouseX: mouseX,
+ mouseY: mouseY,
+ pointXValue: pointXValue
+ });
+
+ //If user double clicks the layer, fire a elementDblclick dispatch.
+ if (d3.event.type === "dblclick") {
+ dispatch.elementDblclick({
+ mouseX: mouseX,
+ mouseY: mouseY,
+ pointXValue: pointXValue
+ });
+ }
+ }
+
+ svgContainer
+ .on("mousemove",mouseHandler, true)
+ .on("mouseout" ,mouseHandler,true)
+ .on("dblclick" ,mouseHandler)
+ ;
+
+ //Draws a vertical guideline at the given X postion.
+ layer.renderGuideLine = function(x) {
+ if (!showGuideLine) return;
+ var line = wrap.select(".nv-interactiveGuideLine")
+ .selectAll("line")
+ .data((x != null) ? [nv.utils.NaNtoZero(x)] : [], String);
+
+ line.enter()
+ .append("line")
+ .attr("class", "nv-guideline")
+ .attr("x1", function(d) { return d;})
+ .attr("x2", function(d) { return d;})
+ .attr("y1", availableHeight)
+ .attr("y2",0)
+ ;
+ line.exit().remove();
+
+ }
+ });
+ }
+
+ layer.dispatch = dispatch;
+ layer.tooltip = tooltip;
+
+ layer.margin = function(_) {
+ if (!arguments.length) return margin;
+ margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
+ margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
+ return layer;
+ };
+
+ layer.width = function(_) {
+ if (!arguments.length) return width;
+ width = _;
+ return layer;
+ };
+
+ layer.height = function(_) {
+ if (!arguments.length) return height;
+ height = _;
+ return layer;
+ };
+
+ layer.xScale = function(_) {
+ if (!arguments.length) return xScale;
+ xScale = _;
+ return layer;
+ };
+
+ layer.showGuideLine = function(_) {
+ if (!arguments.length) return showGuideLine;
+ showGuideLine = _;
+ return layer;
+ };
+
+ layer.svgContainer = function(_) {
+ if (!arguments.length) return svgContainer;
+ svgContainer = _;
+ return layer;
+ };
+
+
+ return layer;
+};
+
+/* Utility class that uses d3.bisect to find the index in a given array, where a search value can be inserted.
+This is different from normal bisectLeft; this function finds the nearest index to insert the search value.
+
+For instance, lets say your array is [1,2,3,5,10,30], and you search for 28.
+Normal d3.bisectLeft will return 4, because 28 is inserted after the number 10. But interactiveBisect will return 5
+because 28 is closer to 30 than 10.
+
+Unit tests can be found in: interactiveBisectTest.html
+
+Has the following known issues:
+ * Will not work if the data points move backwards (ie, 10,9,8,7, etc) or if the data points are in random order.
+ * Won't work if there are duplicate x coordinate values.
+*/
+nv.interactiveBisect = function (values, searchVal, xAccessor) {
+ "use strict";
+ if (! values instanceof Array) return null;
+ if (typeof xAccessor !== 'function') xAccessor = function(d,i) { return d.x;}
+
+ var bisect = d3.bisector(xAccessor).left;
+ var index = d3.max([0, bisect(values,searchVal) - 1]);
+ var currentValue = xAccessor(values[index], index);
+ if (typeof currentValue === 'undefined') currentValue = index;
+
+ if (currentValue === searchVal) return index; //found exact match
+
+ var nextIndex = d3.min([index+1, values.length - 1]);
+ var nextValue = xAccessor(values[nextIndex], nextIndex);
+ if (typeof nextValue === 'undefined') nextValue = nextIndex;
+
+ if (Math.abs(nextValue - searchVal) >= Math.abs(currentValue - searchVal))
+ return index;
+ else
+ return nextIndex
+};
+
+/*
+Returns the index in the array "values" that is closest to searchVal.
+Only returns an index if searchVal is within some "threshold".
+Otherwise, returns null.
+*/
+nv.nearestValueIndex = function (values, searchVal, threshold) {
+ "use strict";
+ var yDistMax = Infinity, indexToHighlight = null;
+ values.forEach(function(d,i) {
+ var delta = Math.abs(searchVal - d);
+ if ( delta <= yDistMax && delta < threshold) {
+ yDistMax = delta;
+ indexToHighlight = i;
+ }
+ });
+ return indexToHighlight;
+}; \ No newline at end of file