adding labels to d3 elements without nesting

I need help creating HTML with tooltips and tooltip text for each <p> tag. While I know this can be achieved using d3, I am currently using a CSS approach because it feels more familiar to me.

In an ideal scenario, the desired HTML output should resemble the following structure:

<p class="tooltip" style="font-size: 73.6207pt;">eyes.
  <span class="tooltiptext">Tooltip text</span>
</p>
<br>
<p class="tooltip" style="font-size: 73.6207pt;">eyes.
  <span class="tooltiptext">filler text</span>
</p>

To prevent the text inside the p tags from appearing on the same line, I have included a <br>. However, the issue arises when the <br> becomes nested within the span tags, resulting in an undesirable HTML structure as shown below.

<p class="tooltip" style="font-size: 73.6207pt;">eyes.
  <span class="tooltiptext">Tooltip text <br></span>
</p>
<p class="tooltip" style="font-size: 73.6207pt;">eyes.
  <span class="tooltiptext">filler text <br></span>
</p>

The current d3 code snippet is as follows:

Despite attempting to rearrange the .append("d3"), I have encountered challenges where it either disrupts the tooltip functionality or interferes with the visualization entirely.

div.selectAll(null)
  .data(myData)
  .enter()
  .append("p")
  .attr("class", "tooltip")
  .text(function(d) {
     return d.word;
  })
  .style("font-size", function(d) {
     return scale(parseInt(d.score))  + "pt";
  })
  .append('span')
  .attr("class", "tooltiptext")
  .text("filler text")
  .append("br")

Your assistance in resolving this matter is greatly appreciated.

Answer №1

When using d3's .insert() method from either the v3 or v4+ selection APIs, keep in mind that it only inserts an element once, which may not be ideal for scenarios with more than two <p> elements. A workaround is to iterate through all <p> nodes and utilize JavaScript's native Element.insertBefore() method to achieve the desired outcome of inserting a <br /> after each <p> element.

In this situation, skipping the call to insertBefore() for the first encountered <p> element and applying it subsequently to the rest can be effective.

var paragraphs = div.selectAll(null)
  .data(myData)
  .enter()
  .append("p")
  .attr("class", "tooltip")
  .text(function(d) {
     return d.word;
  })

paragraphs.append('span')
  .attr("class", "tooltiptext")
  .text("filler text");

// Loop through all inserted paragraphs
paragraphs.each(function(d, i) {

  // Skip insertion for the first `<p>`
  if (i === 0)
    return;

  this.parentNode.insertBefore(document.createElement('br'), this);
});

Check out the proof-of-concept below:

var div = d3.select('div');
var myData = [{
  word: 'Lorem ipsum dolor sit amet'
}, {
  word: 'Consectetur adipiscing elit'
}, {
  word: 'Nam id sollicitudin magna'
}, {
  word: 'Pharetra rutrum nisl'
}];

var paragraphs = div.selectAll(null)
  .data(myData)
  .enter()
  .append("p")
  .attr("class", "tooltip")
  .text(function(d) {
     return d.word;
  })

paragraphs.append('span')
  .attr("class", "tooltiptext")
  .text("filler text");

// Iterate through all inserted paragraphs
paragraphs.each(function(d, i) {

  // Do not insert if first `<p>` is encountered
  if (i === 0)
    return;
    
  this.parentNode.insertBefore(document.createElement('br'), this);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<div></div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Step-by-step guide on accessing values from a JavaScript object

I have a dictionary variable declared within a script tag on an HTML page. My goal is to retrieve the values associated with the "Roads" and "Intersections" keys, which change each time the page is refreshed. By capturing these values, I can then use JavaS ...

.post method reveals parameter in URL upon submission

Currently, I am utilizing the $.post method to send a value to a PHP page for processing after replacing the serialize utility with a more specific element: $("button").click(function(event) { $.post( "php/index.php", { seq: $("seq").v ...

How can nextJS leverage async getInitialProps() method in combination with AWS S3?

I'm currently facing a challenge with executing an s3.getObject() function within an async getInitialProps() method in a nextJS project. I'm struggling to properly format the results so that they can be returned as an object, which is essential f ...

Modifying arrays in ReactJS

Having trouble editing my array list, need some help. I can update a single input value successfully, but struggling with updating the entire array. Any suggestions on why the method isn't working and how to edit the array? When I try to store data ...

Passing a JSON file name as an argument to a command line in Node.js

When I run app.js using the command node app.js, it will execute const inputData = require('./input.json'); Now, my question is - can I pass the file name as an argument to const inputData = require('./file.json'); directly from the co ...

Make a POST request using AJAX to the current page and retrieve a value using the $_POST method

I've been trying to solve this puzzle, but I can't seem to figure out what's going wrong... Here's the situation: I'm passing a value to a function and using AJAX to send this value via a POST request to the same page. Upon succes ...

Error: Unable to access the 'classList' property of null in HTMLSpanElement.expand function

Encountering a minor issue with my javascript code. Following a tutorial for a seemingly simple task: link What I did: Adapted the HTML from the tutorial to fit my desired visual outcome while maintaining correct class and id attributes. Utilized identic ...

Leverage more information by clicking on the xAxis element - Highcharts.js

Currently encountering challenges implementing a 'xAxis clickable' column chart. The goal is to display additional Pie charts below the column chart when a user clicks on an element in the xAxis. https://i.sstatic.net/cXUf2.png The structure of ...

Keypress in JavaScript

Consider the function below: function CheckInputType(Input) { inputType: Input } If a key is pressed, I want to cycle through different input values like this: window.addEventListener('keydown', e => { if (9 === e.keyCode) ...

Adjust the height of an element when the maximum height is set to none

I am trying to add animation to the opening of a menu on my website. This is achieved by adjusting the max-height property of the <div> element that represents the menu, as well as changing the display property. The max-height value is being changed ...

Can Vue2-Google-Maps dynamically load API keys using props?

Is there a way to access the component props before it gets rendered? I want to dynamically load the Google Maps API based on a passed prop value. import * as VueGoogleMaps from 'vue2-google-maps'; import GmapCluster from 'vue2-google-maps/ ...

When attempting to access index.html, the Express Server responds with a "Page Not Found"

I have encountered a problem while trying to run my Index.html file through an Express server. Despite referring to previously asked questions, I couldn't resolve the issue. The error message 'Cannot GET /' keeps popping up. Below is the sn ...

What specific portion of the code will be transformed into a virtual DOM?

As a newcomer to the virtual DOM concept, I have been pondering how it functions over the past few days. Let's envision that I have integrated a simple template engine like twig into my project, and I am utilizing vue.js as my chosen javascript frame ...

Get rid of the margins on your Wordpress theme

Currently, my Wordpress site is using the Tesseract theme which can be found at (http:// instantiwebs . com) I am interested in removing the left/right margins on all elements, similar to what has been done on this website: . Interestingly enough, they al ...

Ways to identify faces of a 3D form obscured by other surfaces (undetectable from a specific viewpoint)

Imagine a scenario where we have a 3D cube positioned in a XYS coordinate system. While shapes can vary in complexity, let's begin with a simple cube. We are observing the cube from a distant point at a specific angle to the front face, similar to how ...

Using React components to create an anchor element for a popover display

Hey, I'm just starting out with React and trying to wrap my head around Hooks like useState. It's a bit challenging for me, and I want to keep things simple without making them too complex. I've encountered an issue when transitioning a Rea ...

Formik React struggling with error management and handling tasks accurately

I am currently using the Formik template to develop a Login Form. onSubmit={( values, { setSubmitting, setErrors /* setValues and other goodies */ } ) => { props.logMeIn(va ...

Is it possible to execute ng-repeat on-click when ng-show evaluates to true?

I am currently facing an issue with my table that populates using ng-repeat. The table contains 100 rows, and clicking on any row reveals a new table (using ng-show) with more detailed product information. However, the performance of my web app is being af ...

Nuxt.js implemented with Auth using jwt refresh tokens

I've implemented the Auth library in my Vue/Nuxt project and have successfully set up JWT Authentication. However, I'm encountering an issue with the refresh token. The refreshToken cookie is consistently being set to null: https://i.sstatic.ne ...

Two variations of identical descriptions within a single div container

Is there a way for me to use an item, specifically an img, within the same div class but with different definitions? For example: section .row img { margin: 0 0 30px; width: 100%; border: 4px solid #18a00e; } section .row img { margin: 0 ...