skip to Main Content

I would like a JS function to remove a class from any div that has a class name ending with a specific value.

Here’s my example:

const elements = document.querySelectorAll('[class$="-lvl1"]');

elements.forEach(element => {
    element.classList.remove('hidden');
});
.hidden
{
  display: none;
}
<div class="A-lvl1 hidden">
A
</div>
<div class="B-lvl1 hidden">
B
</div>
<div class="C-lvl1 hidden">
C
</div>
<div class="D-lvl2 hidden">
D
</div>

I would like the "hidden" class removed from any element that has has a classname ending in "-lvl1". Currently querySelectorAll does not return any elements.

I have tried printing the output of "elements" to the console, but it does not return any. If I try to select a specific class querySelectorAll(‘.A-lvl1’), it works, so I presume there is an issue with the selector (‘[class$=-lvl1]’)

I’m expecting all of the "-lvl1" divs to appear after the code runs, as the "hidden" class should be removed.

3

Answers


  1. Based on the order of your classes, you should be using *= in your selector, rather than $= because your class attributes actually end with hidden. The *= allows for matching against values that contain the specified string. But note that using this wildcard search could wind up matching on classes you didn’t intend to match.

    document.querySelectorAll('[class*="-lvl1"]').forEach(element => {
        element.classList.remove('hidden');
    });
    .hidden { display: none; }
    <div class="A-lvl1 hidden">A</div>
    <div class="B-lvl1 hidden">B</div>
    <div class="C-lvl1 hidden">C</div>
    <div class="D-lvl2 hidden">D</div>

    You could also just swap the order of the class names so that hidden is listed first and then use $=.

    document.querySelectorAll('[class$="-lvl1"]').forEach(element => {
        element.classList.remove('hidden');
    });
    .hidden { display: none; }
    <div class="hidden A-lvl1">A</div>
    <div class="hidden B-lvl1">B</div>
    <div class="hidden C-lvl1">C</div>
    <div class="hidden D-lvl2">D</div>
    Login or Signup to reply.
  2. Use a data attribute with ends with and not a class

    document.querySelectorAll('[data-id$="-lvl1"]').forEach(element => {
        element.removeAttribute("hidden")
    });
    <div data-id="A-lvl1" hidden>A</div>
    <div data-id="B-lvl1" hidden>B</div>
    <div data-id="C-lvl1" hidden>C</div>
    <div data-id="D-lvl2" hidden>D</div>

    You could break it up into just the levels

    document.querySelectorAll('[data-level="1"]').forEach(element => {
        element.removeAttribute("hidden")
    });
    <div data-group="A" data-level="1" hidden>A</div>
    <div data-group="B" data-level="1" hidden>B</div>
    <div data-group="C" data-level="1" hidden>C</div>
    <div data-group="D" data-level="2" hidden>D</div>
    Login or Signup to reply.
  3. There is no selector which will target elements containing at least one class name having a specific suffix. However, you can use a short series of steps to find such elements.

    First, you can use the wildcard equality attribute selector (*=) to initially select elements which contain the suffix in the class attribute. Then, for each candidate element, iterate over its classList to determine if one endsWith the target suffix.

    You could also use a regular expression (e.g. /-lvl1s*/) to test the entire class attribute string instead of the iteration/endsWith approach.

    Below is a functional example:

    function findElementsWithClassNameSuffix(suffix, rootNode = window.document) {
      const elements = [];
      for (
        const element of rootNode.querySelectorAll(
          `[class*=${JSON.stringify(suffix)}]`,
        )
      ) {
        for (const className of element.classList) {
          if (className.endsWith(suffix)) {
            elements.push(element);
            break;
          }
        }
      }
      return elements;
    }
    
    for (const element of findElementsWithClassNameSuffix("-lvl1")) {
      element.classList.remove("hidden");
    }
    .hidden { display: none; }
    <div class="A-lvl1 hidden">A</div>
    <div class="B-lvl1 hidden">B</div>
    <div class="C-lvl1 hidden">C</div>
    <div class="D-lvl2 hidden">D</div>

    Code in TypeScript Playground

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search