简体   繁体   中英

How to select the second to last tag in a list?

I am new to frontend developing and working with d3.js. I have a problem with selecting a certain tag in a list of tags.

I created some graphs and I need to add an image to certain nodes. I tried to select the needed tag with d3.select('g') , but this selects the first tag. But I think the big problem is that the tags are called the same, and I don't know how to select the penultimate tag for example.

Here is my HTML code (short version):

<svg _ngcontent-c1="" width="1366" height="99">
   <gr _ngcontent-c1="" ng-reflect-zoomable-of="[object SVGSVGElement]">
      <g _ngcontent-c1="" _nghost-c2="" ng-reflect-link="[object Object]">
         <line _ngcontent-c2="" class="link" x1="1" y1="-2" x2="3" y2="-1"> </line>
      </g>
      <g _ngcontent-c1="" _nghost-c2="" ng-reflect-link="[object Object]">
         <line _ngcontent-c2="" class="link" x1="5" y1="2" x2="9" y2="4"> </line>
      </g>

   <g _ngcontent-c1="" ng-reflect-node="[object Object]" ng-reflect-draggable-node="[object Object]" ng-reflect-draggable-in-graph="[object Object]">
      <g transform="translate(3,4)">
         <text class="node-name" x="13" y="-3" font-size="20px">one</text>
      </g>
   </g>

   <g _ngcontent-c1="" ng-reflect-node="[object Object]" ng-reflect-draggable-node="[object Object]" ng-reflect-draggable-in-graph="[object Object]">
      <g transform="translate(5,6)">
             <text class="node-name" x="13" y="-3" font-size="20px">two </text>
          </g>
       </gr>

And my attempt to add an image:

var svg = d3.select('svg').select('gr').select('g')
  .append('svg')
  .attr('width', 64)
  .attr('height', 64)
  .style('border', '1px solid black');
var imgs = svg.selectAll('image').data([0]);
imgs.enter()
  .append('image')
  .attr('xlink:href', '/assets/ToNode.png')
  .attr('width', '64')
  .attr('height', '64');

Judging only by the title your question is a duplicate, :last-child being the obvious choice. There are several duplicate targets, like this one . However, there is no answer showing how to select the penultimate element. Actually, if you search penultimate in the tag, your question is the only result.

For selecting an element by a given index :nth-child() is the most common option, or, since you are counting from the end, :nth-last-child() . But I'd like to give you an answer showing how to use the second and third parameters (of most D3 methods) combined.

In several D3 methods (like filter , which I'll use in this answer), the second parameter is the index of the element relative to the selection, while the third parameter is the current group, or nodes, which make up that selection. Those parameters are normally named i and n , but you can name them anyway you want. The important information here is that n.length gives us the number of elements.

So, if we select all <g> elements, we can get the penultimate one using:

yourSelection.filter(function(_, i, n) {
    return i === n.length - 2
  })

Here, I'm using n.length - 2 because the indices are zero-based, therefore n.length - 1 is the last element. Also, _ is just a convention that says that we are not using the first parameter anywhere in the function.

Here is a demo, if you inspect the SVG you'll see that a dummy element <foo> was added to the penultimate group:

 d3.selectAll("g").filter(function(_, i, n) { return i === n.length - 2 }) .append("foo")
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <svg> <g></g> <g></g> <g></g> <g></g> <g></g> </svg>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM