Get all items that start with class name
Asked Answered
M

4

29

I'm trying to only show certain divs. The way I have decided to do this is to first hide all elements that start with "page" and then only show the correct divs. Here's my (simplified) code:

<form>    
    <input type="text" onfocus="showfields(1);">
    <input type="text" onfocus="showfields(2);">
</form>
<div class="page1 row">Some content</div>
<div class="page1 row">Some content</div>
<div class="page2 row">Some content</div>
<div class="page2 row">Some content</div>
<script>
    function showfields(page){
        //hide all items that have a class starting with page*
        var patt1 = /^page/;
        var items = document.getElementsByClassName(patt1);
        console.log(items);
        for(var i = 0; i < items.length; i++){
            items[i].style.display = "none";
        }

        //now show all items that have class 'page'+page
        var item = document.getElementsByClassName('page' + page);
        item.style.display = '';
    }
</script>

When I console.log(items); I get a blank array. I'm pretty sure the regexp is right (get all items starting with 'page'). The code I'm using is old school JS, but I'm not adverse to using jQuery. Also if there is a solution that doesn't use regexp, that's fine too as I'm new to using regexp's.

Mosher answered 4/4, 2016 at 7:10 Comment(0)
N
61

getElementsByClassName only matches on classes, not bits of classes. You can't pass a regular expression to it (well, you can, but it will be type converted to a string, which is unhelpful).

The best approach is to use multiple classes…

<div class="page page1">

i.e. This div is a page, it is also a page1.

Then you can simply document.getElementsByClassName('page').


Failing that, you can look to querySelector and a substring matching attribute selector:

document.querySelectorAll("[class^=page]")

… but that will only work if pageSomething is the first listed class name in the class attribute.

document.querySelectorAll("[class*=page]")

… but that will match class attributes which mention "page" and not just those with classes which start with "page" (i.e. it will match class="not-page".

That said, you could use the last approach and then loop over .classList to confirm if the element should match.

var potentials = document.querySelectorAll("[class*=page]");
console.log(potentials.length);
elementLoop:
  for (var i = 0; i < potentials.length; i++) {
    var potential = potentials[i];
    console.log(potential);
    classLoop:
      for (var j = 0; j < potential.classList.length; j++) {
        if (potential.classList[j].match(/^page/)) {
          console.log("yes");
          potential.style.background = "green";
          continue elementLoop;
        }
      }
    console.log("no");
    potential.style.background = "red";
  }
<div class="page">Yes</div>
<div class="notpage">No</div>
<div class="some page">Yes</div>
<div class="pageXXX">Yes</div>
<div class="page1">Yes</div>
<div class="some">Unmatched entirely</div>
New answered 4/4, 2016 at 7:19 Comment(0)
M
23

Previous answers contain parts of the correct one, but none really gives it.

To do this, you need to combine two selectors in a single query, using the comma , separator.

The first part would be [class^="page"], which will find all the elements whose class attribute begins with page, this selector is thus not viable for elements with multiple classes, but this can be fixed by [class*=" page"] which will find all the elements whose class attribute have somewhere the string " page" (note the space at the beginning).

By combining both selectors, we have our classStartsWith selector:

document.querySelectorAll('[class^="page"],[class*=" page"]')
  .forEach(el => el.style.backgroundColor = "green");
<div class="page">Yes</div>
<div class="notpage">No</div>
<div class="some page">Yes</div>
<div class="pageXXX">Yes</div>
<div class="page1">Yes</div>
<div class="some">Unmatched entirely</div>
Massproduce answered 10/2, 2019 at 14:37 Comment(1)
This should be the accepted answer..Lyonnais
T
0

You can use jQuery solution..

var $divs = $('div[class^="page"]');

This will get all the divs which start with classname page

Tinge answered 4/4, 2016 at 7:16 Comment(5)
A better answer would explain what that syntax actually did (and point out that it doesn't do exactly what was asked for).New
@New it is a simple solution, which gets all the divs whose class starts with page.. which is exactly what the user wants. I thought it is unnecessary to explain the implicit things..Tinge
It gets all the divs which have a class attribute which starts with page, that isn't the same as having a class which starts with page since the class attribute takes a space separated list of classes.New
@New I agree.. But I think simple and tweaked solution for a simple scenario is better than complicated and perfect solution.Tinge
Possibly (although adding additional semantics based on the position of a class is a good way for future development in a years time to break old JS) but it's important to at least document the limitations correctly.New
D
-2
 $(document).ready(function () {
        $("[class^=page]").show();
        $("[class^=page]").hide();
    });

Use this to show hide div's with specific css class it will show/hide all div's with css class mention.

Disinterested answered 4/4, 2016 at 7:39 Comment(1)
The question is asking how to match elements where one of the class names starts with the work "page", it isn't trying to match on whole class names.New

© 2022 - 2024 — McMap. All rights reserved.