Navigating the DOM upwards using D3 and CSS to make targeted selections

In my HTML code, I have a structured calendar representation as follows:

<table>
  <thead>...</thead>
  <tbody>
    <tr>...</tr>
    <tr>
      <td day="4">...</td>
      <td day="5">...</td>
      <td day="6" class="is-startrange">...</td>
      <td day="7">...</td>
      <td day="8">...</td>
    </tr>
    <tr>
      <td day="9">...</td>
      <td day="10">...</td>
      <td day="11">...</td>
      <td day="12">
        <button class="day" type="button">12</button>
      </td>
      <td day="13">...</td>
    </tr>
  </tbody>
</table>

I am trying to figure out how to navigate from the button labeled under day 12, moving upwards to select all the button elements until reaching one with an is-startrange class. All table cells contain buttons that represent dates and each button has event listeners attached. Whenever a date is clicked, it becomes the selected starting point.

My goal is to apply styling to all button elements between the start date and the selected date (either by adding a class or through solely CSS).

Could anyone provide helpful insights on achieving this with D3 selection or purely using CSS?

Answer №1

Gerardo Furtado has pointed out in a comment that the question does not really involve traversing the DOM upwards, but rather focuses on iterating through td elements. This task can be easily accomplished by using d3.selectAll("td"), which will provide a flat selection of all td elements present on the page. Depending on the layout, you may need to refine the selection further to target a specific table, such as "table.myTable td" or "#tableId td".

Once you have this selection, you can add a class, like range, using

selection.classed(names[, value])
. The second argument value can be a function, allowing for dynamic assignment of classes based on certain criteria.

If the value is a function, the function evaluates each selected element one by one, receiving the current data (d), index (i), and group (nodes) along with the current DOM element via this. The return value of the function decides whether to apply or remove classes on each element.

The final step involves creating a filter function to determine if an element falls within a desired range and consequently assign the range class accordingly.

The code snippet below demonstrates how to combine all these steps using a custom filter function named rangeFilter() within .classed():

// The day parameter sets the stopping point
function rangeFilter(day) {  
  // This property is captured by the following function to track the
  // range status. When true, the current element and subsequent elements are part
  // of the range until encountering the button's td.
  var inRange = false;   
  
  // Filter function returns true if the element belongs to the range.
  return function(d) {
    element = d3.select(this);   // Current td element during iteration.
    // Determine if the element is still in the range, or if the range hasn't started yet,
    // check if we've reached the td.is-startrange.
    inRange = (inRange && element.attr("day") != day) 
            || element.classed("is-startrange");      

    // XOR operation to exclude the .is-startrange element.
    return inRange != element.classed("is-startrange"); 
  }
}

d3.selectAll("button")
  .on("click", function() {
    // Check all tds for range inclusion and set class based on filter function result
     passing in the clicked button's value.
    d3.selectAll("td")
        .classed("range", rangeFilter(d3.select(this).text())); 
  });
.is-startrange {
  background-color: limegreen;
}

.range {
  background-color: red;
}
<script src="https://d3js.org/d3.v4.js"></script>
<h1>Hit the button</h1>
<table>
  <thead>...</thead>
  <tbody>
    <tr>...</tr>
    <tr>
      <td day="4">...4...</td>
      <td day="5">...5...</td>
      <td day="6" class="is-startrange">...6...</td>
      <td day="7">...7...</td>
      <td day="8">...8...</td>
    </tr>
    <tr>
      <td day="9">...9...</td>
      <td day="10">...10...</td>
      <td day="11">...11...</td>
      <td day="12">
        <button class="day" type="button">12</button>
      </td>
      <td day="13">...13...</td>
    </tr>
  </tbody>
</table>

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

Tips for achieving seamless map rotation in Mapbox

I need assistance with slowly rotating a map to a specific angle in Mapbox-gl js. I have tried two options for rotating the map, but I am struggling to achieve a slow rotation. 1. map.rotateTo() When I use map.rotateTo(angle,{duration: 2000}), I encounte ...

Puzzled by the CSS Box Model - There's a piece of the puzzle I

Check out my simplified fluid layout right here at this link. I've been trying to figure out why the alignment between the right column and the header above it seems off, even though there's no padding involved. Both have the same border styles, ...

What steps can I take to prevent a JavaScript element from clearing everything when clicked?

After clicking on "add more," the first delete function works correctly, but the subsequent delete element deletes everything on the page. I suspect there may be an issue with the 'ele' variable in the JavaScript code. Since I am not very experie ...

How come the div element is not rendering the CSS styles?

What could be the reason for .header not displaying the background color and height settings? https://jsfiddle.net/f3puaeq6/1/ .header{ background-color: black; height: 300px; } ...

What is the latest CSS browser support for the min() and max() functions in 2018?

I am considering implementing the use of the min() and max() functions in my project. I'm curious about the current browser support as of 2018. Do you think it is necessary to include the @supports at-rule? For example, I could write: .px-4-safe { ...

Transform an array into a string with spaces in between each value by combining the elements

I have a complex select input on my website. By using jQuery, I can easily extract the selected values of all child option elements like this: $("#select").val(); This action returns an array as demonstrated below: ["Hello", "Test", "Multiple Words"] N ...

Definition of a Typescript Global.d.ts module for a function that is nested within another function

Simply put, I have a npm module that exports a function along with another function attached to it: // @mycompany/module ... const someTool = (options) => { // do some cool stuff }; someTool.canUseFeature1 = () => { return canUseSomeFeature1(); ...

Is it possible to include a conditional statement in a variable declaration?

I need to increase the value of + 450 to var threshold only when the page is on body.home. Here's an example: var headHeight = jQuery('#masthead-space').height() + 23; var threshold = jQuery('.PopularTabsWidget').offset().top - ...

Ways to detect the use of vue.js on a webpage without relying on vue-devtools

One way to determine if the page is utilizing Angular or AngularJS is by inspecting window.ng and window.angular. Is there a similar method to identify whether Vue is being used on the page directly from the console, without relying on vue-devtools? ...

By utilizing the window.history.back() function, it takes me four clicks to navigate back one page

I find it peculiar that my back button is using the JS method window.history.back() to return to the previous page. However, I have noticed a strange behavior with this button. When I click on it before the entire document loads, it functions as expected a ...

Continue to run upon clicking the button in the Document Object Model

I want the code to constantly change instead of executing only once. By default, the button has a dark mode for text and the background color is pink. When you click the button, the background color changes to black and the text in the button turns into li ...

Steps to update the toolbar color of Mui DataGrid

Check out this unique custom Toolbar I created specifically for Mui dataGrid function CustomToolbar() { return ( <GridToolbarContainer> <GridToolbarColumnsButton /> <GridToolbarFilterButton /> <GridToolbarDensit ...

Using Jquery to detect changes in a Datalist element in an HTML5 document

This snippet illustrates the code: <input name="cmbname" type="text" id="cmbname" list="listcmbname" autocomplete="off" runat="server"> <datalist id="listcmbname"> <option data-id="1" value="a"></option> <optio ...

What could be causing the header to not be perfectly centered vertically between the navigation and footer sections when using Bootstrap 5?

header contains an element of h1. I made a modification to header: added the class "d-flex flex-column justify-content-center align-items-center min-vh-100", which caused a vertical scrollbar to appear. To fix this, I included the class "overflow-hidden" ...

Can a web application access USB devices across different browsers and operating systems?

I am curious about how we can achieve this particular task. I have heard various things about Silverlight 4, JavaScript, or ActiveX control, but I have yet to see a demonstration of code for any of them. Is there a web component available for this, or is ...

Iterate over the array elements in React by using Hooks on click

I am facing an issue with loading objects separately from a JSON file when a button is clicked. The problem occurs when the index goes out of bounds, resulting in a TypeError "Cannot read property 'content' of undefined" message. I have tried u ...

Firestore's get document method may cause an unmounted warning

I've been working on a React.js project that integrates with Firestore, and I ran into an issue where using the get method for fetching documents resulted in a "Can't perform a React state update on an unmounted component" warning. However, when ...

Using jQuery to alter the background color when a div reaches a specific height

Is there a way to make my sidebar change color gradually as the user scrolls below a certain point on the page? I want the background to transition from transparent to black, giving it a fading effect. I attempted to modify some existing code without succe ...

Generating @click handlers dynamically within a v-for loop

I am working on populating a v-menu in Vuetify with an array passed as a prop to be used in a v-for loop. Each menu item needs to have @click events assigned, and the names of the functions are provided in the array as strings (for example, the "CanResolve ...

How can you align an icon to the right in a Bootstrap4 navbar while keeping it separate from the toggle menu?

Looking to utilize the Twitter Bootstrap framework for structuring my navbar with distinct "left", "middle", and "right" sections, where the middle portion collapses beneath the navbar-toggler (burger menu) when space is limited. For a self-contained exam ...