Extending mouseover to another target element - javascript

This is my first question ever.
So, I tried to run a mouseover in my D3 script to trigger a hovered textfield (which is a div object) when moving the mouse over a certain button. Works pretty well so far.
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
.
.
.
node.append("foreignObject")
.attr("class", "info")
.attr("x", 55)
.attr("y", -85)
.attr("width", 30)
.attr("height", 30)
.append("xhtml:body")
.html('<img src="images/information-icon.png" width=20 height=20>')
.on("mouseover", function (d) {
div.transition()
.duration(200)
.style("opacity", 0.9);
div.html("text")
.style("left", (d3.event.pageX - 5) + "px")
.style("top", (d3.event.pageY - 10) + "px");
})
.on("mouseout", function (d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
The problem now is that the textfield vanishes once I move my mouse away from the button. I somehow want to "extend" my mouseover target from the button to the textfield also, so that I'm still able to click links on it etc. Does someone have an idea how to establish that? I already tried to put the mouseout event on my textfield instead like that:
.on("mouseover", function (d) {
div.transition()
.duration(200)
.style("opacity", 0.9);
div.html("text")
.style("left", (d3.event.pageX - 5) + "px")
.style("top", (d3.event.pageY - 10) + "px")
.on("mouseout", function (d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
This won't work though, as the textfield won't vanish at all then. Does someone have an idea?
**EDIT:**Defined my question a bit different, I hope it won't be that confusing now...

Ok,
when the text is displayed you should un-register the mouse over event from the button, so that the text does not move when you run your mouse over the div.
When the text is opacity 0 then register the mouse over event back to the div.

Related

Change style of the data point based on the text area

I have implemented a scatterplot using d3.js v3.
I would like to change the color of the datapoint if for that particular data point annotation has been added.
But when I try to do so, it is changing the color of the first data point in the array instead of the the circle where the annotation has been added.
The way I am implementing is :
eventGroup.select("circle")
.attr("class", "dot")
.attr("r", 4)
.attr("cx", 10)
.attr("cy", 10)
.attr("fill", function(d) {
return d.evtColor ? d.evtColor : "#229ae5";
})
.attr("stroke", function(d) {
return d.evtColor ? d.evtColor : "#229ae5";
})
.attr("stroke-width", 2)
.on("contextmenu", function(d) {
var position = d3.mouse(this.parentNode);
d3.event.stopPropagation(); // to avoid over-ridding of click event on the chart background
d3.select("#context-menu")
.style("position", "absolute")
.style("left", (d3.event.pageX - 220) + "px")
.style("top", (d3.event.pageY - 70) + "px")
.style("display", "inline-block")
.on("click", function() {
d3.select("#context-menu").style("display", "none");
d3.select("#annotateBox")
.style("position", "absolute")
.style("left", (d3.event.pageX - 220) + "px")
.style("top", (d3.event.pageY - 70) + "px")
.style("display", "inline-block");
d3.select("#eventLabel").text(d.label);
d3.select("#eventTime").text(d.time);
d3.select("#textArea").node().value = d.textArea || "";
d3.select("#done").on("click", function() {
d.textArea = d3.select("#textArea").node().value;
d3.select("#annotateBox").style("display", "none");
if (d.textArea) {
d3.select("circle.dot").style("fill", "#ed6a1c");
}
});
});
});
I cannot do d3.select(this.parentNode) as the parent element is not the circle.dot. What element should be selected in order to change the color of datum where annotation text has been added?
Keep a reference to the clicked DOM element (i.e., the circle)...
.on("contextmenu", function(d) {
var thisCircle = this
etc...
And use it afterwards:
if (d.textArea) {
d3.select(thisCircle).style("fill", "#ed6a1c");
}

D3.js tool tips on hover

I,m following this tutorial for tool tips for my graph :
http://bl.ocks.org/d3noob/c37cb8e630aaef7df30d
and its working like a charm !
However there is one issue...
The current graph showing in the tutorial has black dots on the line...
I want the tool tips and black dots to appear only when i hover on them and not always like it is currently showing.
Is there a way to do that ?
Updated answer with mouseout:
https://plnkr.co/edit/9Ej1MYpGqxBdeWO2FUNO?p=preview
.on("mouseover", function(d) {
// show circle selected
d3.select(this)
.transition()
.duration(200)
.style("opacity", 0.9);
.on('mouseout', function(d) {
// hide the circle
d3.select(this)
.transition()
.duration(100)
.style("opacity", 0);
// hide the tooltip
d3.selectAll(".tooltip")
.transition()
.duration(100)
.style("opacity",0);
To use mouseout, you need to move the tooltip slightly up, and move the whole svg a bit downwards.
div.html(
'<a href= "http://google.com">' + // The first <a> tag
formatTime(d.date) +
"</a>" + // closing </a> tag
"<br/>" + d.close)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 42) + "px"); // up a bit
var margin = {top: 50, right: 20, bottom: 30, left: 50}, // down a bit
Since mouseout is very sensitive, the circle will disappear immediately after you move away your mouse, so it is better to increase the radius a bit:
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 8) // slightly bigger for human reaction
Still, I think without mouseout is a better and more intuitive approach:
Old working example (takes a few seconds to load): https://plnkr.co/edit/IitMgKW0jDYlWifokcZB?p=preview
The changes you need to make is in .on("mouseover", function(d), add the following code:
.on("mouseover", function(d) {
// hide other circles
d3.selectAll('circle')
.style("opacity", 0);
// show circle selected
d3.select(this)
.transition()
.duration(200)
.style("opacity", 0.9);
.on("mouseout", function(d) would not work for this case because the circles overlap with the tooltip.
This is a simple d3 tooltip you can look the code! (It's very little )
https://github.com/cbertelegni/tooltip_d3js/
function tooltipd3(tltp_name){
"use strict";
var s = {};
s.name = tltp_name ? tltp_name : "tooltipd3";
s.w = 0; // width tooltip
s.h = 0; // height tooltip
s.t = d3.select("body").append("div") // tooltip html node
.attr("class", s.name)
.style("opacity", 1e-6)
.style("position", "absolute");
s.mouseover = function(html) {
/** #param {string} html - Is the content for tooltip */
s.t.html(html)
.transition()
.duration(300)
.style("opacity", 1);
/** After innerhtml on tooltip get w & h */
s.get_t_size();
};
s.mousemove = function(){
s.t.style("left", (d3.event.pageX - s.w/2) + "px")
.style("top", (d3.event.pageY - s.h - 5) + "px")
.style("opacity", 1);
};
s.mouseout = function() {
s.t.transition()
.duration(300)
.style("opacity", 1e-6)
.each("end", function(){
s.t.html("");
});
};
/** Get width and height of tooltip and set w & h of Tooltip class */
s.get_t_size = function(){
var size = s.t.node().getBoundingClientRect();
s.w = size.width;
s.h= size.height;
};
return s;
}
As Eric said in the comments, this approach is not exactly user-friendly. But, if you want it, here it is:
First, set the opacity of the circles to 0:
.attr("opacity", 0)
Then, on mousemove:
.on("mouseover", function(d) {
d3.select(this).attr("opacity", 1);
div.transition()//the rest of the code
Don't forget to create a mouse out to make them transparent again:
.on("mouseout", function(d) {
d3.select(this).attr("opacity", 0);

Add tooltip to d3 scatter plot

I've got the following scatter plot usind d3.js http://gkalliatakis.github.io./
and now I want to add tootltip of time (value of x axis) every time the mouse is over a triangle. I read lots of examples:
http://bl.ocks.org/weiglemc/6185069
but I was not able to modify them for my project.
Any thoughts?
I've modified your code to incorporate the tooltip from your example link. The keys are this:
1.) Append the div tooltip to your html body (note, your html was malformed, it didn't have a body, I added those tags):
var tooltip = d3.select('body')
.append('div')
.attr('class', 'tooltip')
.style("opacity", 0);
2.) On mouseover/mouseout of your points update the div's html and show/hide the tooltip:
svg.selectAll(".point")
.data(session_data)
.enter()
.append("path")
.on("mouseover", function(d, i) { // show it and update html
d3.select('.tooltip')
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html(d.x)
.style("left", (d3.event.pageX + 5) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d, i) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
})
.attr("class", "point")
...
Working example here.

Calculate coordinates of div elements using d3 and d3.tip

I want my tooltip using d3-tip to dynamically be placed next to the text I'm writing out with this code:
in the Javascript
$(".intro h2").html("Nextbus prediction of " + "<font size=5>" + cutoff + "</font>" + "minutes really means:")
.on('mouseover', tip2.show)
.on('mouseout', tip2.hide);
in the HTML...
<div class="intro">
<span class="underline"><h2></h2></span>
</div>
I can make the tooltip appear in an absolute place when I define it like this with the style("left", 300+"px")
var tip2 = d3.tip()
.attr('class', 'd3-tip')
.direction("s")
.html(function(d) {
return "this my text for the hover over of the sentence!"
})
.style("left", 300+"px")
.style("top", 150+"px")
But when I take out the style("left", 300+"px"), the text is placed in the bottom left corner of the graph, no matter how much I try to hack it offset.
I want to replace 300 with something that retrieves to coordinates of the div that I'm hovering over with the mouse.
Here's my fiddle: http://jsfiddle.net/0yfbhtcv/1/ (Nevermind the plot that doesn't appear... that's just lost in translation from my code to jsfiddle and shouldn't be necessary for this problem)
This doesn't use d3.tip, but I think it does what you want with plain ol d3, it makes a div that you can put HTML or text into that pops up where your mouse is:
var div = d3.select("body").append("div") // put the tooltip in a separate div
.attr("class", "tooltip");
then
d3.selectAll(".your_class")
.on("mouseover", function (d) {
div.transition()
.duration(200)
.style("opacity", 0.9);
div.html( d.whatever + <somehtml> + "etc")
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px"); })
.on("mouseout", function (d) {
div.transition()
.duration(300)
.style("opacity", 0)
});

Positioning SVG elements with CSS. Having some problems

Ive added 20 SVG squares to a trend graph I made using D3.js. Ech square is a clickable object which toggles lines on and off the graph. In Firefox the squares appear in the right lace, in Chrome, the CSS apparently stops working completely and the squares just drop to the bottom of the page.
Heres a link to the graph, http://www.andkensol.com/dataviz/TrendGraph/trendMov.html
And here is some of the JavaScript and CSS I used to make and then position the squares. Using position:relative is probably the cause. Would anyone have any advice or suggestions?
//JS
//AVENGERS CONTROLS
d3.select(".chart").append("svg")
.attr("class", "AvengeDot")
.on("mouseover", function(d) {
nameInfo.transition()
.duration(100)
.style("opacity", .9);
nameInfo.html("Marvel's The Avengers")
.style("left", (d3.event.pageX + 10) + "px")
.style("top", (d3.event.pageY - 30) + "px");
})
.on("mouseout", function(d) {
nameInfo.transition()
.duration(200)
.style("opacity", 0);
})
//HUNGER GAMES CONTROLS
d3.select(".chart").append("svg")
.attr("class", "HungerDot")
.on("mouseover", function(d) {
nameInfo.transition()
.duration(100)
.style("opacity", .9);
nameInfo.html("Hunger Games")
.style("left", (d3.event.pageX + 10) + "px")
.style("top", (d3.event.pageY - 30) + "px");
})
.on("mouseout", function(d) {
nameInfo.transition()
.duration(200)
.style("opacity", 0);
})
//CSS
.AvengeDot{
position:relative;
left:77%;
bottom:118%;
width:15px;
height:15px;
background-color:#FF9604;
cursor:pointer;
}
.HungerDot{
position:relative;
left:75.5%;
bottom:114%;
width:15px;
height:15px;
background-color:#FF9F18;
cursor:pointer;
}

Categories