addeventlistener to <div> appended in d3 - javascript

I am trying to add events (addeventlistner) to multiple elements that are appended with d3.However, when I click on , it won't trigger the attached "alert".Interestingly, this works on <div> that I manually add inside .Could anyone shed light on this?
d3.csv("output1.csv",function(data){
var width = 700,
height = 600;
d3.select('body').selectAll("div")
.data(data)
.enter()
.append("div")
.style("width",30)
.style('height',30)
.style("background-color",function(d){
return d.color;
})
var divs = document.getElementsByTagName("div") // this returns array of div elements
function show(){
alert("ya")
}
for (var i = 0; i < divs.length; i++) {
divs[i].addEventListener('click',function(){
alert("yaho")
})
}
})

Since your are using d3, use d3 event listeners as shown below.
var divs = d3.select('body').selectAll("div")
.data(data)
.enter()
.append("div")
.style("width",30)
.style('height',30)
.style("background-color",function(d){
return d.color;
});
divs.on("click",function(){
alert("yaho")
});
Or
function show(){
alert("Hi");
}
divs.on("click",show);
Listeners bonded with addEventListeners will also work. Here is the working fiddle using similar code. JSFiddle

Related

Not able to append label on edge of graph in d3.js

I am new to js & d3. I am trying to plot a graph with d3.js forced layout.
My purpose is to append labels ("XXX" & "OOO") on either sides of edges but it's not working.
Here the code snippet:
link.append('svg:text')
.attr('class', 'aEnd')
.text(function(d) { return "XXX"; });
link.append('svg:text')
.attr('class', 'zEnd')
.text(function(d) { return "OOO"; });
Here is the complete code I am working on.
JSFIDDLE : d3_graph_labelled_edge.js
Nesting a text element inside a line element is not allowed, as summed up here.
What you can do is wrapping the line elements inside g containers and append the link labels to them:
var glink = vis.selectAll("line.link")
.data(data.links)
.enter().append("svg:g");
var link = glink.append("svg:line")
[...]
glink.append('svg:text')
.attr('class', 'aEnd')
.text(function(d) { return "XXX"; });
Updated fiddle.

How can I append the one SVG (graph) inside another SVG node (rect) after onclick using d3.js?

I want to populate the data inside the parent graph node, that is I want to add nested svg on click event using d3.js.
I have tried following code but the output is looking very different I want to show the graph inside the after on click event of first svg node.
var svg = d3.select("body").append("svg")
.attr("width", 600)
.attr("height", 400)
svg.append('rect')
.attr('class', 'content shape')
.attr("width", 20)
.attr("height", 20)
.attr("stroke", "black")
.attr("stroke-width", 1)
.style("fill", function (d) {
return d._children ? "lightsteelblue" : "#fff";
})
.on("click", createMap);
var createMap (mapData){
if(mapdata.data){
d3.select(this).attr("width", 200)
.attr("height", 200)
.call(function(d){
var nodeMap = getGeneratedmap(mapdata.data);
return nodeMap
}
}
}
var getGeneratedmap(mapdata){
var generatedmapSVG = d3.select("#subnodeMap").append("svg")
....
....(logic for map generation)
....
return generatedmapSvg
}
<body>
<div id="mainMap">
<svg></svg>
</div>
<div id="subnodeMap"></div>
</body>
Please guide me and give the proper way to solve the above issue. Thanks in advance.
Your first SVG, the var svg is being appended to <body>. The second SVG is being appended to the div with ID #subnodemap, so you are not actually nesting the first SVG inside the second. You probably want to do something like:
var generatedmapSVG = svg.append("svg")
That's about as much as I can help you without a working example in Codepen or similar, hope it gets you towards a solution.

D3:reflect data changes on visualization keeping the same array size. Trying to represent a sort algorithm visually

I'm trying to represent a selection sort visually with d3 to show some students and I'm having problems updating the data once the positions swap(I will add the transitions and delays once it's working). The positional attributes don't seem to be working as well, I don't know why, any ideas?. The codepen is here:
HTML:
<div id="canvas">
</div>
CSS:
rect{
border:1px solid black;
}
JS:
function selectionSort(array,svg){
//where the index will position
var positioningIndex=0;
var aux;
var minIndex;
var minVal=Number.MAX_VALUE;
while(positioningIndex<array.length){
//get the index of the mínimum
for(var i=positioningIndex;i<array.length;i++){
if(array[i]<minVal){
minIndex=i;
minVal=array[i];
}
}
//swap the mínimum to the positioningIndex
aux=array[minIndex];
array[minIndex]=array[positioningIndex];
array[positioningIndex]=aux;
//update visualization
svg.selectAll("rect").data(array);
minVal=Number.MAX_VALUE;
++positioningIndex;
}
return array;
}
var dataSet=[10,7,8,44];
var svg=d3.select("#canvas").selectAll("rect")
.append("svg")
.attr("width", 960)
.attr("height", 500);
var rect=svg.data(dataSet)
.enter()
.append("rect");
rect.text(function(el){
return el;
})
.attr("width", 30)
.attr("height", 30)
.attr("x", function(d, i) {
return i*5;
})
.attr("y", 30);
.style("color","green");
array=selectionSort(dataSet,svg);
You've got a lot of mixing up of html and svg elements going on there
First off, your svg element isn't getting appended:
var svg=d3.select("#canvas").selectAll("rect") // <- selectAll("rect") is causing problems
.append("svg")
No existing rect elements at the start means no svg's getting appended (do you mean to add one for each rect?) Edit: and in fact that one error is the cause of everything that happens afterwards - the selectAll("rect") needs moved to the line where elements are added to the svg - not on the line where the svg itself is added -->
var rect=svg.selectAll("rect").data(dataSet) // rect should really be g
.enter()
.append("rect");
Secondly, and because of the above error, the elements called 'rect' that are added (and added directly to the #canvas id div) aren't svg:rect objects - they're just html elements with the name 'rect' - see Is there a way to create your own html tag in HTML5?. The browser just treats them as inline elements, so none of your x's or y's make a difference they just line up one after the other
Finally, if this was svg you wouldn't be able to add text directly to a rect, you'd need to use a group (g) element and add both rect and text elements to that to keep them associated, and style("transform", translate(x,y)) the group element to move them around.
var g=svg.selectAll("g").data(dataSet) // <-- now changed from rect
.enter()
.append("g") // <-- and here
.attr ("transform", function(d,i) {
return "translate("+(i*35)+" 30)";
})
;
// texts n rects added here
g.append("text").text(function(el){
return el;
})
.attr("dy", "1em")
g.append("rect")
.attr("width", 30)
.attr("height", 30)
;
See http://codepen.io/anon/pen/bwJWEa?editors=1111

Making charts clickable

I am just learning and trying to code it at the same time, this is the code I have, If I take out the drill method and take out the .click(drill) then everything works so far, it draws some silly bar charts from the data I am sending to it
$( document ).ready(function() {
var dataset = gon.data;
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
.click(drill)
.style("height", function(d) {
return d.brand_name + "px";
});
function drill (event) {
var target = event.currentTarget;
var data = $(target).data();
console.log(data);
}
});
But I am not able to add "click" event to those bar charts such that when I click on them I can know which chart I clicked on. The code above is result of my unsuccessful attempt to add "click" event to the charts I have drawn .... What is the correct way?
You can use .on("click", drill) if you want D3 to pass the object and data attached.
function drill(d, i) {
console.log(d); //data object
console.log(i); //array position
console.log(this); //DOM element
}
You can also use .attr("onclick", "drill()") syntax if you want to follow the standard HTML without the D3 wrapper.

animate this element in d3js

Ok so I have the following code example where I have circles in an svg element. Each circle has a click event and I'm trying to animate the circle that was clicked. Currently all circles animate because I'm referring to the bubble object. What I want is to refer to the clicked object its self and not the other ones:
var data_items=[100,200,300];
var svg = d3.select("#chart")
.append("svg").attr("width", 800).attr("height", 600);
var g = svg.selectAll(".bubbleContainer")
.data(data_items)
.enter().append("g")
.attr("class","bubbleContainer");
var bubble = g.append("circle")
.attr("class","bubble")
.attr("cx", function(d) {
return d;
})
.attr("cy", function(d) {
return d
})
.attr("r", function(d) {
return d/2
})
.on("click",function(d){
bubble
.transition()
.duration(1000)
.attr("r",1000)
})
Any help is much appreciated
Thanks!
What Lars Kotthoff wrote would work. Alternatively – and I'm not sure which is more idiomatic:
Inside the click handler, the this context refers to the clicked DOM element.
So the following would do it too:
.on("click",function(d){
d3.select(this)
.transition()
.duration(1000)
.attr("r",1000)
});
You can use d3.event.target to access the element that is being clicked in the event handler. See for example this jsfiddle.

Categories

Resources