19

I'm using D3 for drawing on the SVG. What I want is to append DOM element or HTML to the D3, like:

task.append(function(model){
//here return html or dom
};

Documentation says it's possible, but unfortunately I can't find any example or found out how to do this myself.

Jack Spektor
  • 1,097
  • 1
  • 11
  • 30
  • 1
    Need more clarity! Do you wish to add HTML elements to your canvas? What are `task` & `model`? Should you not consider removing the `svg` tag? – Vikram Deshmukh Feb 12 '14 at 12:21
  • Yes, I need to add some HTML to the canvas. Task is d3 selection. – Jack Spektor Feb 12 '14 at 12:22
  • To be more clear I need to append HTML to the d3 selection using it's append method. https://github.com/mbostock/d3/wiki/Selections#wiki-append – Jack Spektor Feb 12 '14 at 12:23
  • 1
    If you wish to draw DOM elements onto a canvas then [here's the link](https://developer.mozilla.org/en/docs/HTML/Canvas/Drawing_DOM_objects_into_a_canvas) on how to do it. But if you wish to *append* HTML elements to canvas then I'm afraid to say [that can't be done](http://stackoverflow.com/questions/2732488/how-can-i-convert-an-html-element-to-a-canvas-element). – Vikram Deshmukh Feb 12 '14 at 12:28
  • Are you using `` or `` for your graph??? Most d3 uses ``, and I'm afraid @srvikram13 is just confusing you in that case. To add an HTML element within SVG, you have to first add a [`` tag](http://www.w3.org/TR/SVG11/extend.html#ForeignObjectElement), then add the HTML element within it. However, be warned that browser support is somewhat buggy. Depending on what you're doing, you might consider drawing the HTML element on top of the SVG but not a child of it. Look up tooltip examples for how to position it. – AmeliaBR Feb 12 '14 at 16:50
  • @AmeliaBR Miss, the question has been edited to replace 'canvas' with 'svg'. In which case, my response was apt, and not confusing. – Vikram Deshmukh Feb 12 '14 at 17:29
  • @srvikram13 yes, sorry for the implied snub -- I checked the edit log after leaving my comment. – AmeliaBR Feb 12 '14 at 17:30
  • Yes, sorry. That was my fault - I wrote canvas, but meant SVG. I found a solution for my problem. I'll update the answer later. – Jack Spektor Feb 12 '14 at 20:35
  • @JackSpektor can you post the update for the solution, I'm struggling with something similar – pedrommuller Nov 03 '14 at 20:09

3 Answers3

26

The selection.append() function accepts one of two types:

  • A string which is the name of an element to create, or
  • A function which is executed (applied on parent) and should return an element or HTML.

Your question wasn't very specific, so I'll do a wild guess here.

Appending custom created elements to a d3 selection

If you created your element using

var newElem = document.createElement(tagname);

or

var newElem = document.createElementNS(d3.ns.prefix.svg, tagname);

and you want to add that new element to your d3 selection then you can use this:

mySelection.node().appendChild(newElem)

This will basically append the new element to the first node from your selection. For appending the element to every node from the selection you'd need to make a loop over mySelection and call node() on every single item.

Adding multiple custom created elements works the same, but you can save yourself some work using element.cloneNode(true)

Note however that you can't use any of d3's magic on plain elements, except you wrap them in d3.select(elem).

Appending a d3 selection to a d3 selection

Let's assume you have two selections s1 and s2 and you want s2 to be appended to s1. If both are selections over only one element respectively, then you can simply use

s1.node().appendChild(s2.node())

or

s1.append(function() {return s2.node()})

If s1 and/or s2 are being selections over multiple elements you need to iterate over both selections first and use

s1[i].node().append(s2[j].node())

or

s1.append(function() {return s2[i].node()})

instead.

Hubert Grzeskowiak
  • 15,137
  • 5
  • 57
  • 74
22

Try this:

d3.select("body").append(function() { return document.createElement("p") });
László Papp
  • 51,870
  • 39
  • 111
  • 135
guest
  • 221
  • 2
  • 3
0

This is how used this information to create dynamic "shapes" in my force-directed chart using a function inside append().

shape = svg.append("g")
  .selectAll("rect") // only a placeholder - does not control the shape
  .data(force.nodes())
  .enter()
  .append(function(d){
   return setshvape(d)
    })


function setshape(d){
   if(d.type == "start"){
     var shape = document.createElementNS(d3.ns.prefix.svg, "circle");
   }else{
    var shape = document.createElementNS(d3.ns.prefix.svg, "rect");
    }
return shape
}
alQemist
  • 362
  • 4
  • 13