d3 rect not showing up - javascript

I want to display the legend (caption?) of some data.
For each part of the legend, I append a rect and a p to a parent division.
The problem is that rect are not showing up.
Here is my code:
var groups = {{ groups|safe }};
groups.forEach(function(group, i) {
var div = d3.select("#collapse-legend");
div.append("rect")
.attr("width", 17)
.attr("height", 17)
.style("fill-opacity", 1)
.style("fill", function (d) { return c(i); });
div.append("p").text(group)
});
Now, when I check the content of my web page, I get both rect and p, but rect:
is not showing up
seems to have a width of 0 (showing its area with firefox)
Is there some mistake in my code? Are there better ways to achieve this? I am very new to javascript and d3.js so please be indulgent ^^
Update
So this is what I ended with.
HTML:
<div ...>
<svg id="legend-svg"></svg>
</div>
JavaScript:
// set height of svg
d3.select("#legend-svg").attr("height", 18*(groups.length+1));
// for each group, append rect then text
groups.forEach(function(group, i) {
d3.select("#legend-svg").append("rect")
.attr("y", i*20)
.attr("width", 18)
.attr("height", 18)
.style("fill-opacity", 1)
.style("fill", function (d) { return c(i); });
d3.select("#legend-svg").append("text")
.attr("x", 25)
.attr("y", i*20+15)
.text(group);
});

SVG elements like <rect> cannot be direct children of html <div> elements. You must put them inside an <svg> container element.

SET X + Y values for rect :
.attr("x", 50)
.attr("y", 50)

Related

adding input text box on clicking the data labels d3.js

I am trying to implement annotations on my scatterplot using d3.js v3. I want to insert a text box when I click on the text labels on my chart. For which I wrote this code:
circleGroup.selectAll("text")
.data(data)
.enter()
.append("text")
.text(function (d) {
if (d.label) {
return d.label;
}
return "";
})
.attr("x", function (d) {
return x(d.time) + 6;
})
.attr("y", function (d) {
return y(d.plotY) + 4;
})
.attr("font-size", "10px")
.attr("fill", "#2d3d45")
.on("click", function(d) {
d3.select(this).append("input").attr("type", "text").attr("name", "textInput").attr("value", "Text goes here");
});
The selection of the text element is working correctly. Its just not popping text box when i click on the text labels. Where am i going wrong? Is my approach not in right direction ?
You cannot append html element into svg. The only way to do it - use foreignObject element.
The foreignObject SVG element allows for inclusion of a foreign XML
namespace which has its graphical content drawn by a different user
agent. The included foreign graphical content is subject to SVG
transformations and compositing.
Look at the very simplified example:
var texts = ['foo', 'bar'];
var container = d3.select('g');
container
.selectAll('text')
.data(texts)
.enter()
.append('text')
.text(function(d) { return d; })
.attr('y', function(d,i) { return 50 * i })
.on('click', function(d,i) {
container
.append("foreignObject")
.attr("x", 0)
.attr("y", function() { return 50 * i })
.attr("width", 140)
.attr("height", 20)
.html(function(d) {
return '<input type="text" value="Text goes here" />'
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div style="font-size: 12px;">Click on the texts below:</div>
<svg width="300" heigth="400">
<g transform="translate(20, 20)">
</g>
</svg>

Add html content with line break inside d3 circle

Is it possible in d3 to Add html content instead of appending text.In the Following code,
circle.append("circle")
.attr("cx", 65)
.attr("cy", 65)
.attr("r", 65)
.attr('fill','none')
.attr('stroke','#008080')
.attr('class','ourmission')
circle.append('text')
.attr('x', 65)
.attr('y',65)
.attr('dx',65)
.text(function(d){
return d.Some_Value+"<br/>"+d.Some_OtherValue
})
I have appended text,since I need to add line break to my text dynamically based on some condition I need html content to be added instead of text.If am not wrong I think line break is not possible with appending text.
I need to do some thing like this,
.html(function(d){
return d.Some_Value+"<br/>"+d.Some_OtherValue
})
You can do it with <foreignObject> element.
The foreignObject SVG element allows for inclusion of a foreign XML
namespace which has its graphical content drawn by a different user
agent. The included foreign graphical content is subject to SVG
transformations and compositing.
Look at the demo below:
var svg = d3.select("#root")
.append("svg")
.attr("width", 210)
.attr("height", 210);
svg.append("circle")
.style("stroke", "gray")
.style("fill", "white")
.attr("r", 100)
.attr("cx", 105)
.attr("cy", 105)
svg
.data([{ foo: 'foo', bar: 'bar' }])
.append("foreignObject")
.attr("x", 60)
.attr("y", 60)
.attr("width", 100)
.attr("height", 100)
.html(function(d) {
return '<div style="border:1px solid">' + d.foo + '</br>' + d.bar + '</div>'
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>
<div id="root"></div>

Nest multiple rects inside multiple svg containers with d3?

I am trying to nest an individual rect inside each svg element created in the g element, but I can't seem to get it to work.
Here is my code + Plnk;
Plunker
var bar = g.selectAll(".barContainer")
.data(thisData.labels)
.enter()
bar
.append("svg")
.attr("class", "barContainer")
bar
.insert('rect')
.attr('width', function(d) {
console.log(d)
return d.value
})
.attr('height', 20)
.attr('x', 0)
.attr('y', 0)
Currently the DOM is displaying the rect and container class on the same level, where as I would like to nest the rect inside each container.
I've tried a few things but can't seem to crack it, I was hoping someone could point me in the right direction?
Thanks
You have a 'g' element which you append the svg to and then you also append the rect to the 'g'. You want to append the rect to the svg element you create. Something like this :
var bar = g.selectAll(".barContainer")
.data(thisData.labels)
.enter()
var barRectSVG = bar
.append("svg")
.attr("class", "barContainer")
barRectSVG
.insert('rect')
.attr('width', function(d) {
console.log(d)
return d.value
})
.attr('height', 20)
.attr('x', 0)
.attr('y', 0)
Updated plnkr : http://plnkr.co/edit/WYbjT7ekjUuopzs0H9Pi?p=preview

Getting the value of SVG attributes in D3.js

I am new to D3.js and am trying to build rectangles that represent all nodes from an XML file. So far so good but I want interactivity with each of the rectangles I draw and to be able to capture the nodes that have been touched for further processing. So let's say I click on a rectangle, I can make it react by doing an onclick event (like increasing the font size) but I can't seem to retrieve some of the info. I'd like to create an array with the text of each item that was clicked on.
Here's the code for one instance of the rectangle.
d3.select("#chart")
.append("svg")
.attr("width", 600)
.attr("height", 2000)
.style("background", "#93A1A1")
d3.select("svg")
.append("rect").attr("x", 50)
.attr("y", 25)
.attr("height", 20)
.attr("width", 200)
.attr("title", "resourceDef")
.style("fill", "#CB4B19")
d3.select("svg")
.append("text")
.attr("x", 55)
.attr("y", 37)
.attr("font-size", 11)
.attr("font-family", "sans-serif")
.text("resourceDef")
.on("mouseover", function(d) {
tempText = this.text;
alert(tempText);
d3.select(this)
.attr("font-size", 15)})
.on("mouseout", function(d) {
d3.select(this)
.attr("font-size", 11)})
I can grab style info by using but not the title and I can't find that info anywhere. Thanks for your help, I know it's a long question with probably a simple answer.
You can attach a mouse over event on the rectangle DOM by doing something like this:
d3.select("svg")
.append("rect").attr("x", 50)
.attr("y", 25)
.attr("height", 20)
.attr("width", 200)
.attr("title", "resourceDef")
.style("fill", "#CB4B19")
.on("click", function (d) {
var t = d3.select(this).attr("title");
//pushing the title into the array.
clickedTitles.push(t);
console.log(t);
});
You can get the attribute of a DOM(in your case tite) by doing something like this:
.on("click", function (d) {
var t = d3.select(this).attr("title");
clickedTitles.push(t);
console.log(t)
})
You can store the clicked rectangles title in an array like this:
//create an array
var clickedTitles = [];
//in your click function push the title into the array
clickedTitles.push(t);
//use the clickedTitles where ever you need in the code
Full code is here.

d3 How to trigger event on the object behind text

I draw A rect and text on svg.
In order to show text, I render rect first.
I add mouse click event to rect
when I click the text, it seems the rect is not selected, because rect is behind text, so text is selected frist.
I need to select trigger the event when mouse click inside the rect.
How should I do?
Thanks!
Fiddle
You can see, when you mouse click on the text, the rect is not clicked.
var data = ["TEXT SAMPLE TEXT SAMPLE TEXT SAMPLE"];
var svg = d3.select("svg");
var bar = svg.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(100,100)"; });
bar.append("rect")
.attr("width", 200)
.attr("height", 50)
.style("fill", "#f00")
.on("click", function (d) {
alert("text");
});
bar.append("text")
.attr("x", 10)
.attr("y", 25)
.attr("dy", "-.35em")
.text(function(d) { return d; });
You can attach a style to the text to ignore mouse events. Here is the example:
Style:
.bar-text {
pointer-events: none;
}
Modified code:
bar.append("text")
.attr("x", 10)
.attr("y", 25)
.attr("class", "bar-text") // add class
.attr("dy", "-.35em")
.text(function(d) { return d; });
Attach the handler to the g element. Complete demo here.

Categories

Resources