score:0

Accepted answer

My question is why the d3 selectAll statement (above the createNode function) does not work when I run the script after page load, though it all runs fine when I cut and paste that same statement into the browser console.

Currently you append a factory node that creates new nodes on click.

Then you select all existing circles with class node. At this point there are none.

Then you can click on the factory node, create a new one, but you don't re-run the selectAll statement. The selection of all circles is not updated because a new circle is created afterwards.

What you could do is run the selectAll statement again after you append a node, but you only add one node at a time, and you already have a selection of that node in the createNode function. So you can just add the event listener here:

 function createNode(x,y) { 
    var r=30; var lx=random(100+r,w-r); var ly=random(0+r,h-r); 
    var rx=svg.append('circle')
      .attr('class','nodes')
      ...
      .on(...

     ...
}

    var w=500,h=400,ctr=0; //define bounds of svg

        var ND=[]; //holder of all node data

    var svg = d3.select('body').append('svg') //base svg element
          .attr('width',w)
          .attr('height',h);

    function random(p,q) { return p+Math.floor(Math.random()*(q-p)); }

    var factory=svg.append('circle') //draw the factory widget
        .attr('class','perms') //one of the perm objects
        .attr('cx',50)
        .attr('cy',50)
        .attr('r',30)
        .attr('stroke','black')
        .attr('fill','teal');

    factory.on('click',createNode); //create a new node when factory is clicked


    function createNode(x,y) //create a new node and render on screen
    { var r=30; var lx=random(100+r,w-r); var ly=random(0+r,h-r); 
      var rx=svg.append('circle').attr('class','nodes').attr('id',ctr)
        .attr('cx',lx).attr('cy',ly).attr('r',r)
        .attr('stroke','red').attr('fill','yellow')
        .on('click',function(e,d){ var did=this.id; console.log(did); 
                            d3.select(this).transition().delay(1000).style('fill','orange').remove();});
                            
      var rn={id:ctr++, x:lx, y:ly, r:30, clr:'yellow',lnk:[],ptr:0};
      ND.push(rn);
      return rn;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.0.0/d3.min.js"></script>

The selectAll code works in the console after you add circles because now there are circles to select - otherwise you have an empty selection. One way you can check to see if you are indeed selecting anything is to use selection.size() to return how many elements are selected.


Related Query

More Query from same tag