5

How do I assign id attribute to each append of circle so that I can later use the circles based on its id. For now I am able to clone the circle on drag with out any id.

Demo: https://jsbin.com/zuxetokigi/1/edit?html,output

Code:

 <!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.js"></script>
        <script>
            svg = d3.select("body").append("svg")
                    .attr("width", 960)
                    .attr("height", 500);

            circle1 = svg.append("circle")
                    .attr("id", "circleToClone")
                    .attr("cx", 100)
                    .attr("cy", 100)
                    .attr("r", 20);

            var drag = d3.behavior.drag()
                    .origin(function ()
                    {
                        var t = d3.select(this);
                        return {x: t.attr("cx"), y: t.attr("cy")};
                    })

                    .on('dragend', function (d) {
                        var mouseCoordinates = d3.mouse(this);
                        if (mouseCoordinates[0] > 120) {
                            //Append new element
                            var circle2 = d3.select("svg").append("circle")
                                    .classed("drg", true)
                                    .attr("cx", 100)
                                    .attr("cy", 100)
                                    .attr("r", 20)
                                    .attr("cx", mouseCoordinates[0])
                                    .attr("cy", mouseCoordinates[1])
                                    .style("fill", "green");
                        }
                    });
            circle1.call(drag);
        </script>
    </body>
</html>
kittu
  • 5,835
  • 18
  • 72
  • 142
  • Try to use the [general update pattern](http://bl.ocks.org/mbostock/3808218) and array of objects to mantain a list of objects. These objects can be as you want, the mapping is done in via callbacks in the attr function. Good Luck! – David Lemon Jul 13 '15 at 11:50

2 Answers2

6

If you want to give every circle a unique id, you could use a function to generate a GUID/UUID ('Globally Unique Identifier') for every circle.

You could add the following function from Salvik Meltser's GUID/UUID function to your code (anywhere before the drag function):

function guid() {
    function _random_letter() {
        return String.fromCharCode(97+Math.floor(Math.random() * 26));
    }
    function _p8(s) {
        var p = (Math.random().toString(16)+"000000000").substr(2,8);
        return s ? "-" + p.substr(0,4) + "-" + p.substr(4,4) : _random_letter() + p.substr(0, 7);
    }
    return _p8() + _p8(true) + _p8(true) + _p8();
}

I modified Salvik's original function a little bit because HTML element IDs need to start with a letter in HTML 4 or contain at least one letter in HTML 5.

And then where you append the new circle, just use .attr("id", guid()) to generate a new id for the circle.

var circle2 = d3.select("svg").append("circle")
    .attr("id", guid())  
    .classed("drg", true)
    ...
D Malan
  • 6,941
  • 3
  • 21
  • 34
  • this generates ids that are not selectable: `Error: Failed to execute 'querySelector' on 'Element': '#5881847f-04d9-38fd-4c44-a420cdb1110a' is not a valid selector.` – mangei Dec 17 '19 at 15:19
  • @mangei [looks like](https://stackoverflow.com/a/79022/3486675) IDs must technically start with a letter or in HTML 5 contain at least one letter. I'll modify the `guid` function to ensure that the first character is a letter. – D Malan Dec 17 '19 at 18:07
1

You can assign new id attribute to each element created using its index:

   var circle2 = d3.select("svg").append("circle")
                                    .classed("drg", true)
                                    .attr("cx", 100)
                                    .attr("cy", 100)
                                    .attr("r", 20)
                                    .attr("cx", mouseCoordinates[0])
                                    .attr("cy", mouseCoordinates[1])
                                    .style("fill", "green");

    circle2.selectAll("circle").attr("id", function(d,i) { return i; });
Chetabahana
  • 7,806
  • 2
  • 50
  • 70