//-------------------------------------------------------------------// // // // MAKE TOOLTIP // // // //-------------------------------------------------------------------// function make_tooltip(obj, text_array, chart_group, canvas, margins) { // get the x and y coordinates of the object to apply tooltip too var x = obj.node().transform.baseVal.consolidate().matrix.e var y = obj.node().transform.baseVal.consolidate().matrix.f // for convenience var tooltip_config = charts_config.plot_attributes.tooltip var sep = tooltip_config.default_seperation_from_object // Add the tooltip to the chart and as a child - the text group var tooltip = chart_group.append("g").attr("class", "tooltip_group") var text_group = tooltip.append("g").attr("class", "tooltip_text_group") // Add text in reverse order placing low to high text_array.reverse() for (var i = 0; i < text_array.length; i++) { var text = text_group.append("text") .text(text_array[i]) .attr("font-size", tooltip_config.size) .attr("text-anchor", "middle") .attr("x", x) .attr("y", y - sep - tooltip_config.curve - (i * tooltip_config.size)) .attr("class", "tooltipText") .attr("fill", tooltip_config.emphasis) .attr("font-family", tooltip_config.family) .attr("font-weight", "normal") // The first line in the tooltip gets different coloration if (i < text_array.length - 1) { text.attr("fill", tooltip_config.text) .attr("font-family", tooltip_config.family) .attr("font-weight", "normal") } } // Make the bubble around the text var bubble = tooltip.append("path") .attr("d", make_tooltip_bubble(text_group)) .attr("fill", tooltip_config.fill) .attr("stroke", tooltip_config.stroke) .attr("opacity", tooltip_config.opacity) // Text goes in front of the box text_group.raise() // Get the bounding box of the bubble var bubble_box = bubble.node().getBBox() // Calculate the limits to contain the tooltip var limits = { "top": margins.y.top + margins.buttons + margins.title, "bottom": canvas.y - margins.axes.x - margins.y.bottom, "left": margins.x.left + margins.axes.y, "right": canvas.x - margins.x.right } // Get the boundaries of the object var object_boundaries = { "left": x, "right": x + obj.node().getBBox().width, "top": y, "bottom": y + obj.node().getBBox().height } // Calculate putative tooltip placements var tooltip_placements = { "upper_left": {"x": object_boundaries.left - bubble_box.width - sep, "y":object_boundaries.top - bubble_box.height - sep}, "upper_right": {"x":object_boundaries.right + sep, "y": object_boundaries.top - bubble_box.height - sep}, "lower_left": {"x":object_boundaries.left - bubble_box.width - sep, "y": object_boundaries.bottom + sep}, "lower_right": {"x":object_boundaries.right + sep, "y":object_boundaries.bottom + sep} } // Figure out which placements fall within the limits var valid_placments = { "upper_left": {"x": tooltip_placements.upper_left.x > limits.left, "y": tooltip_placements.upper_left.y > limits.top}, "upper_right": {"x": tooltip_placements.upper_right.x + bubble_box.width < limits.right, "y": tooltip_placements.upper_right.y > limits.top}, "lower_left": {"x": tooltip_placements.lower_left.x > limits.left, "y": tooltip_placements.lower_left.y + bubble_box.height < limits.bottom}, "lower_right": {"x": tooltip_placements.lower_right.x + bubble_box.width < limits.right, "y": tooltip_placements.lower_right.y + bubble_box.height < limits.bottom} } var placements = keys(valid_placments) var tooltip_placement for (var i = 0; i < placements.length; i++) { var current_placement = valid_placments[placements[i]] if (current_placement.x && current_placement.y) { tooltip_placement = tooltip_placements[placements[i]] break } } // Reposition the tooltip to its correct location tooltip.attr("transform", "translate("+(tooltip_placement.x - bubble_box.x)+","+(tooltip_placement.y - bubble_box.y)+")") } function transform_values(selection) { return { "x": selection.node().transform.baseVal.consolidate().matrix.e, "y": selection.node().transform.baseVal.consolidate().matrix.f } } function make_tooltip_bubble(text_group) { var textBox = text_group.node().getBBox() var x = textBox.x var y = textBox.y var width = textBox.width var height = textBox.height var point = charts_config.plot_attributes.tooltip.point var curve = charts_config.plot_attributes.tooltip.curve // Start at bottom center and work around left - up - right - down - close d = "M " + (x + width / 2) + " " + (y + height + curve) // go left d += "l -" + (width / 2) + " 0 " // curve left and up d += "q -" + curve + " 0 -" + curve + " -" + curve + " " // go up d += "l 0 -" + (height) + " " // curve up and right d += "q 0 -" + curve + " " + curve + " -" + curve + " " // go right d += "l " + (width) + " 0 " // curve right and down d += "q " + curve + " 0 " + curve + " " + curve + " " // go down d += "l 0 " + (height) + " " // curve down and left d += "q 0 " + curve + " -" + curve + " " + curve + " " // go left d += "l -" + (width / 2) + " 0 " // close d += " z" return d }