Home > Software design >  Adding a class to a TD tag and an A tag
Adding a class to a TD tag and an A tag

Time:02-18

In a previous question I was provided with a small script by sean-7777 Creating a selected tab in a HTML tabstrip. It works the way he wrote it, but there are 2 issues with it.

First, while it looks for the 'current' class in the TD, it only applies it to the A tag. Second, if I add 'current' to the A tag the script does not find it, but does find it if I add it to the TD tag.

In my CSS I had to apply the :hover class to both the TD (.td1:hover) and the A (.anchor:hover) in order to get the colors I wanted. The A tag overrides the TD when it comes to the text color and that is why I had to apply the hover css to both.

I can preselect the "selected tab" by including the current class to both the TD (class='td1 bold center smaller current') and the A (class='anchor current'), but the script does not remove it when I click another tab, and as I stated above, if I only add it to the A tag the script does not find it, and if I add it only to the TD the link text does not reflect the selected color.

If I click the pre-selected tab after clicking on another tab then the script will remove the hilite when I next click on a different tab. I have been trying different things, but my lack of knowledge of this version of JavaScript is making it impossible to get anything to work properly.

So my questions are:

  1. How do I get the preselected tab to de-select when I click another tab?
  2. How do I get the 'current' class to be added and removed from both the TD and the A tags?

Edit: I finally got the cascading thing figured out. Changes in the CSS below. The script still looks for the current class in the TD but only applies it to the link text in the A tag. The pre-selected tab still remains hilited on the link text, TD de-selected, when you click another link. I believe this is also the script, and still doesn't deselect entirely until after clicking on it a second time and then clicking a different tab.

// this script by sean-7777 on stackoverflow
// https://stackoverflow.com/users/14884338/sean-7777
// https://stackoverflow.com/questions/70724038/creating-a-selected-tab-in-a-html-tabstrip
// Get all the tabs
const tabs = document.querySelectorAll("td.td1");
// Store the previous selected tab so we know which one to remove the class from
let prevSelected;
// Give each tab code
for (const tab of tabs) {
  // Add a function to run when it is clicked
  tab.addEventListener("click", evt => {
    // Remove the current class from the last selected element
    // On first run, prevSelected is not defined, so we need to check
    if (prevSelected) prevSelected.classList.remove("current");
    // Update prevSelected
    prevSelected = evt.srcElement;
    // Add the current class
    evt.srcElement.classList.add("current");
  });
  // I added this line attempting to make the pre-selected TD get added on the initial execution
  // It was this, plus using the Web Developer Tools in Firefox that enabled me to see what was going on
  if (!prevSelected && tab.classList.contains('current')) prevSelected = tab;
}
table {
  margin-left: auto;
  margin-right: auto;
  border: none;
  border-spacing: 1px;
}

.bold {
  font-weight: 700;
}

.center {
  text-align: center;
}

.td1 {
  background-color: springgreen;
  font-family: Arial, sans-serif;
  white-space: nowrap;
  padding: 0 0 0.5pt 0;
  vertical-align: middle;
}

.td1:hover, .td1 .anchor:hover {
  background-color: lightyellow;
  color: orange;
}

.smaller {
  font-size: small;
}

.anchor {
  text-decoration: none;
  color: darkgreen;
}

.td1.current, .td1 .anchor.current
{
  background-color: aliceblue;
  color: deepskyblue;
}
<TABLE>
  <TR>
    <TD class='td1 bold center smaller current'>&nbsp;<a class='anchor current' href='Items/sheet001.htm' target='frSheet'>One-Handed Weapons</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet002.htm' target='frSheet'>Two-Handed Weapons</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet003.htm' target='frSheet'>Ranged Weapons</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet004.htm' target='frSheet'>Ammunition</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet005.htm' target='frSheet'>Shields & Armor</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet006.htm' target='frSheet'>Accessories</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet007.htm' target='frSheet'>Technicks & Magicks</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet008.htm' target='frSheet'>Augments</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet009.htm' target='frSheet'>Items</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet010.htm' target='frSheet'>The Bazaar</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet011.htm' target='frSheet'>Grimoires</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet012.htm' target='frSheet'>Bazaar Packages</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet013.htm' target='frSheet'>Shops</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet014.htm' target='frSheet'>License Board</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet015.htm' target='frSheet'>Lower Half</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet016.htm' target='frSheet'>Upper Half</a>&nbsp;</TD>
  </TR>
</TABLE>

CodePudding user response:

I've updated your code with the following changes:

  • I added evt.preventDefault() just for this demonstration, so that clicking on the anchor does not navigate to a non-existent page. Remove this when you copy it back to your own code.
  • I set prevSelected to the td element by assigning the evt Event's currentTarget property, which always refers to the element on which the event was bound (in this case, tab).
  • I changed the CSS selector for your final rule from .td1.current, .td1 .anchor.current to .td1.current, .td1.current .anchor. This simplifies the JavaScript, as we only need to apply the current class to the tab/td element, not to both the td and the a. As you can see when you run the code, the text is highlighted appropriately.

I'm assuming that the pages linked to (e.g., Items/sheet002.htm) have their corresponding HTML updated to have the correct classes applied? If not you'll need to add some code to check the current URL against the href of the anchor and update the corresponding tab's classList to add the current class. Should be as simple as updating that final if to be something like:

  if (!prevSelected && location.href.includes(tab.querySelector('a').pathname)) {
    prevSelected = tab;
    tab.classList.add("current"); // this won't add it twice if it's already there.
  }

// this script by sean-7777 on stackoverflow
// https://stackoverflow.com/users/14884338/sean-7777
// https://stackoverflow.com/questions/70724038/creating-a-selected-tab-in-a-html-tabstrip
// Get all the tabs
const tabs = document.querySelectorAll("td.td1");
// Store the previous selected tab so we know which one to remove the class from
let prevSelected;
// Give each tab code
for (const tab of tabs) {
  // Add a function to run when it is clicked
  tab.addEventListener("click", evt => {
    // NOTE: The following line prevents the anchor from navigating to the 
    // href as expected. This is so that you can see the classes getting 
    // applied. Otherwise the snippet would be navigated to a non-existent
    // page. 
    evt.preventDefault();
    // Remove the current class from the last selected element
    // On first run, prevSelected is not defined, so we need to check
    if (prevSelected) prevSelected.classList.remove("current");
    // Update prevSelected to the td element, not the anchor, no matter
    // which we clicked on
    prevSelected = evt.currentTarget;
    // Add the current class
    prevSelected.classList.add("current");
  });
  // I added this line attempting to make the pre-selected TD get added on the initial execution
  // It was this, plus using the Web Developer Tools in Firefox that enabled me to see what was going on
  if (!prevSelected && tab.classList.contains("current")) {
    prevSelected = tab;
  }
}
table {
  margin-left: auto;
  margin-right: auto;
  border: none;
  border-spacing: 1px;
}

.bold {
  font-weight: 700;
}

.center {
  text-align: center;
}

.td1 {
  background-color: springgreen;
  font-family: Arial, sans-serif;
  white-space: nowrap;
  padding: 0 0 0.5pt 0;
  vertical-align: middle;
}

.td1:hover,
.td1 .anchor:hover {
  background-color: lightyellow;
  color: orange;
}

.smaller {
  font-size: small;
}

.anchor {
  text-decoration: none;
  color: darkgreen;
}

.td1.current,
.td1.current .anchor {
  background-color: aliceblue;
  color: deepskyblue;
}
<TABLE>
  <TR>
    <TD class='td1 bold center smaller current'>&nbsp;<a class='anchor' href='Items/sheet001.htm' target='frSheet'>One-Handed Weapons</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet002.htm' target='frSheet'>Two-Handed Weapons</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet003.htm' target='frSheet'>Ranged Weapons</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet004.htm' target='frSheet'>Ammunition</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet005.htm' target='frSheet'>Shields & Armor</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet006.htm' target='frSheet'>Accessories</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet007.htm' target='frSheet'>Technicks & Magicks</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet008.htm' target='frSheet'>Augments</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet009.htm' target='frSheet'>Items</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet010.htm' target='frSheet'>The Bazaar</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet011.htm' target='frSheet'>Grimoires</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet012.htm' target='frSheet'>Bazaar Packages</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet013.htm' target='frSheet'>Shops</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet014.htm' target='frSheet'>License Board</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet015.htm' target='frSheet'>Lower Half</a>&nbsp;</TD>
    <TD class='td1 bold center smaller'>&nbsp;<a class='anchor' href='Items/sheet016.htm' target='frSheet'>Upper Half</a>&nbsp;</TD>
  </TR>
</TABLE>

  • Related