D3 v4 add another node to array

I got the following D3 playground in place. The goal for now is to create a fixed hard coded new node .on("click",..) I understand that the node do not get the initial x and y position (i guess). The error message which gives me headache is Unexpected value NaN parsing x1 attribute.

As a beginner I appreciate if somebody could steer my mind into the correct direction.

<!DOCTYPE html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<html>
    <head>
        <title>Play with D3</title>
        <!-- favcon -->
        <link rel="icon" href="https://networkrepository.com/favicon.png">
        <!-- call external d3.js framework -->
        <script src="https://d3js.org/d3.v4.js"></script>
        <!-- load "font awesome" stylesheet https://fontawesome.com/ -->
        <script src="https://kit.fontawesome.com/39094309d6.js" crossorigin="anonymous"></script>   
    </head>

    <style>
        body {
            overflow: hidden;
            margin: 0px;
            font-family: "Open Sans", sans-serif;
        }

        .canvas {
            background-color: rgb(220,220,220);
        }

        .link {
            stroke: rgb(0,0,0);
            stroke-width: 2px;
        }

        .node {
            stroke: rgb(255,255,255);
            stroke-width: 2px;    
        }

        .icon {
            fill: rgb(0,0,0);
            pointer-events: none;    
        }       

        .node:hover{
            cursor: pointer;
        }
    </style>

    <body>
         <!-- SVG area for the whole graph -->
        <svg id="svg"> </svg>

        <!-- call app.js where the application is written -->
        <script>
            
// define different variables
var width = window.innerWidth
    height = window.innerHeight
    boolColor = true
    boolOpacity = true
    color = null
    nodes = null
    
// define cavnas area to draw everything
var svg = d3.select("svg")
            .attr("class", "canvas")
            .attr("width", width)
            .attr("height", height)
            .call(d3.zoom().on("zoom", function() {
                svg.attr("transform", d3.event.transform)
            }))
            .append("g")

// Removes zoom on doubleclick listener
d3.select("svg").on("dblclick.zoom", null)

var simulation = d3.forceSimulation()
                .force("link", d3.forceLink().id(function(d) { return d.id; }).distance(100))
                .force("charge", d3.forceManyBody().strength(-400))
                .force("center", d3.forceCenter(width / 2, height / 2))
                .force("attraceForce",d3.forceManyBody().strength(70));

// load data from json file
var data_nodes = [
    {
        "id": "00000", 
        "type": "company", 
        "name": "Test", 
        "context": "",
        "icon": "\uf1ad"
    },
    {
        "id": "00100",
        "type": "software",
        "name": "Jira",
        "context":"Jira",
        "icon": "\uf7b1",
        "parent" : "00000"
    },
    {
        "id": "00200",
        "type": "software",
        "name": "Confluence",
        "context":"Confluence",
        "icon": "\uf78d",
        "parent" : "00000"
    },
    {
        "id": "00300",
        "type": "software",
        "name": "IVIS",
        "context":"IVIS",
        "icon": "\ue084",
        "parent" : "00000"
    },
    {
        "id": "00400",
        "type": "software",
        "name": "IPOS",
        "context":"IPOS",
        "icon": "\ue084",
        "parent" : "00000"
    },
    {
        "id": "00500",
        "type": "software",
        "name": "IDAS",
        "context":"IDAS",
        "icon": "\ue084",
        "parent" : "00000"
    },
    {
        "id": "99997",
        "type": "hardware",
        "name": "power-plug",
        "context": "power-plug",
        "icon": "\uf1e6",
        "parent" : "00000"
    },
    {
        "id": "99998",
        "type": "hardware",
        "name": "usv",
        "context": "usv",
        "icon": "\uf5df",
        "parent" : "00000"
    },
]

var data_links = [ 
   
    {"source": "99998", "target": "00000"},
    {"source": "99997", "target": "00000"},
    {"source": "00100", "target": "00000"},
    {"source": "00200", "target": "00000"},
    {"source": "00300", "target": "00000"},
    {"source": "00400", "target": "00000"},
    {"source": "00500", "target": "00000"},
    
]

    
    
    

    // create links which visualize relationships
    var links = svg.selectAll("svg")
                .data(data_links) 
                .enter()
                    .append("line")
                    .attr("class", "link")
                    .style("stroke-width", 3)
                    .style("stroke-linecap", "round")
                    // disable browser context menu on link
                    .on("contextmenu", function (d, i){
                        d3.event.preventDefault()
                    })
                    .on("mouseenter", function(d) {
                        d3.select(this)
                            .style("stroke", "red")
                    })
                    .on("mouseleave", function(d) {
                        d3.select(this)
                            .style("stroke", "black")
                    }) 

                    var nodes = svg.selectAll("svg")
                    .data(data_nodes)
                    .enter()
                        .append("circle")
                        .attr("r", 30)
                        .attr("class", "node")
                        .attr("fill", entryColor)
                        .call(d3.drag()
                            .on("start", dragStarted)
                            .on("drag", dragged)
                            .on("end", dragEnded)
                        )
                        .on("click", click) 
       
    var icons = svg.selectAll("svg")
                .data(data_nodes)
                .enter()
                    //.append("g")
                    .append("text")
                    .attr("class", "icon")
                    .attr("text-anchor", "middle")
                    .attr("dominant-baseline", "central")
                    .style("font-family","FontAwesome")
                    .style("font-size","30px")
                    .text(function (d) {return d.icon;})
                    .call(d3.drag()
                        .on("start", dragStarted)
                        .on("drag", dragged)
                        .on("end", dragEnded)
                    )
                     // disable browser context menu on icon
                    .on("contextmenu", function (d, i){
                        d3.event.preventDefault()
                    })
                    .on("mouseenter", function(d) {
                        d3.event.preventDefault()
                    })
                
    simulation
        .nodes(data_nodes)
        .on("tick", ticked);
        
    simulation
        .force("link")
        .links(data_links);
    
    

    function ticked() {
        // update link positions
        links
            .attr("x1", function(d) { return d.source.x; })
            .attr("y1", function(d) { return d.source.y; })
            .attr("x2", function(d) { return d.target.x; })
            .attr("y2", function(d) { return d.target.y; });
        
        // update node positions
        nodes
            .attr("cx", function(d) { return d.x; })
            .attr("cy", function(d) { return d.y; })
        
        // update icon positions
        icons
            .attr("x", function(d) {return d.x})
            .attr("y", function(d) {return d.y})

    }


    function click(d) {
        addNode()
    }

    function addNode() {
        var obj = {
            "id": "66000", 
            "type": "company", 
            "name": "Test1", 
            "context": "",
            "icon": "\uf1ad"
        }

        data_nodes.push(obj)
    }


/*
    Set the color of each node in dependency of their d.name attribute.
*/
function entryColor(d) {
    switch (d.name) {
        case "power-plug":
            return "lightgreen"
        case "usv":
            return "orange" 
        case "diesel":
            return "orange"
        default:
            return "whitesmoke"
    }
}

/*
    dragStarted() / dragged() and dragEnded() controlling the drag behaviour of each
    object. In case all drag events are not desired, simple comment out the .call(d3.drag())
    execution during the object(node) creation
*/
function dragStarted(d) {
    if (!d3.event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
}
    
function dragged(d) {
    d.fx = d3.event.x;
    d.fy = d3.event.y;
}
    
function dragEnded(d) {
    if (!d3.event.active) simulation.alphaTarget(0);
        d.fx = null;
        d.fy = null;
}

        </script>
    </body>
</html>

126 thoughts on “D3 v4 add another node to array”

  1. Pingback: 120 mg priligy