Search code examples
javascriptregexnodelist

How do I use match() method with a for loop over a nodelist


When I collect a nodelist of p elements and apply a simple regex pattern using a match() method in a for loop, I get no matches in my test HTML which contains a known match.

When I use the same regex pattern on the whole document or on a string containing the pattern I am looking for I get a match. Doh!

I have demonstrated it in jsfiddle here https://jsfiddle.net/rusty1642/fdcmn81h/

I tried using paraText[i].innerHTML.match(), to no avail. I tried simply matching a known string like (/email/gi), I tried combinations of 'g' and 'i' qualifiers. Still nothing.

var demo = document.getElementById('demo');
var paraText = document.querySelectorAll('p');
var listing = [];
for(var i=0;i<paraText.length;i++) {

listing += i+' '+paraText[i].textContent + '<br>';

var firstMatch = paraText[i].textContent.match(/\d{4}\s\d{3}\s\d{4}/gi);

}

var telString = "help@yay.com tel.. 0330 122 6000  postal address here";
var secondMatch = telString.match(/\d{4}\s\d{3}\s\d{4}/gi);

demo.innerHTML = listing;
demo.innerHTML +='<br>1 match with nodelist';
demo.innerHTML +='<br> result =>  '+firstMatch;
demo.innerHTML +='<br>2 match with simple string';
demo.innerHTML +='<br>result =>  '+secondMatch;
<div>some SAMPLE address details in a page</div>
<p>Tel: 0330 122 6000</p>
<p>Email: help@yay.com</p>
<p>Address: New House Bedford Road Guildford Surrey GU1 4SJ</p>
<hr>
<div>
<b>the nodelist</b>
</div>
<div id="demo">nothing yet</div>

//the results some SAMPLE address details in a page:

Tel: 0330 122 6000
Email: help@yay.com
Address: New House Bedford Road Guildford Surrey GU1 4SJ
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
the nodelist
  0 Tel: 0330 122 6000
  1 Email: help@yay.com
  2 Address: New House Bedford Road Guildford Surrey GU1 4SJ

1 match with nodelist
   result => null
2 match with simple string
   result => 0330 122 6000

I would expect the match() method to find the telephone number in the nodelist as it looped thro, but it has not.

Can anyone explain please?


Solution

  • The problem is you're only looking at the result of the last match in the loop. Since the last p doens't have the text, naturally that's null.

    Perhaps you want to stop the loop when you find a match, see comments:

    var demo = document.getElementById('demo');
    var paraText = document.querySelectorAll('p');
    var listing = [];
    var firstMatch = null; // <=== Moved declaration
    for (var i = 0; !firstMatch && i < paraText.length; i++) {
    // Added -------^^^^^^^^^^^^^^^
    
      listing += i + ' ' + paraText[i].textContent + '<br>';
    
      firstMatch = paraText[i].textContent.match(/\d{4}\s\d{3}\s\d{4}/gi);
    }
    

    Live Example:

    var demo = document.getElementById('demo');
    var paraText = document.querySelectorAll('p');
    var listing = [];
    var firstMatch = null; // <=== Moved declaration
    for (var i = 0; !firstMatch && i < paraText.length; i++) {
    // Added -------^^^^^^^^^^^^^^^
    
      listing += i + ' ' + paraText[i].textContent + '<br>';
    
      firstMatch = paraText[i].textContent.match(/\d{4}\s\d{3}\s\d{4}/gi);
    }
    
    var telString = "help@yay.com tel.. 0330 122 6000  postal address here";
    var secondMatch = telString.match(/\d{4}\s\d{3}\s\d{4}/gi);
    
    demo.innerHTML = listing;
    demo.innerHTML += '<br>1 match with nodelist';
    demo.innerHTML += '<br> result =>  ' + firstMatch;
    demo.innerHTML += '<br>2 match with simple string';
    demo.innerHTML += '<br>result =>  ' + secondMatch;
    <div>some SAMPLE address details in a page</div>
    <p>Tel: 0330 122 6000</p>
    <p>Email: help@yay.com</p>
    <p>Address: New House Bedford Road Guildford Surrey GU1 4SJ</p>
    <hr>
    <div>
    <b>the nodelist</b>
    </div>
    <div id="demo">nothing yet</div>

    Or if you want an array of the results attempting to match each paragraph:

    var matches = []; // <=====
    for (var i = 0; i < paraText.length; i++) {
    
      listing += i + ' ' + paraText[i].textContent + '<br>';
    
      matches.push(paraText[i].textContent.match(/\d{4}\s\d{3}\s\d{4}/gi));
    // ^^^^
    }
    

    Live Example:

    var demo = document.getElementById('demo');
    var paraText = document.querySelectorAll('p');
    var listing = [];
    var matches = []; // <=====
    for (var i = 0; i < paraText.length; i++) {
    
      listing += i + ' ' + paraText[i].textContent + '<br>';
    
      matches.push(paraText[i].textContent.match(/\d{4}\s\d{3}\s\d{4}/gi));
    // ^^^^
    }
    
    var telString = "help@yay.com tel.. 0330 122 6000  postal address here";
    var secondMatch = telString.match(/\d{4}\s\d{3}\s\d{4}/gi);
    
    demo.innerHTML = listing;
    demo.innerHTML += '<br>matches with nodelist:';
    demo.innerHTML += matches.map(function(match) { return "<br>result => " + match; });
    demo.innerHTML += '<br>match with simple string';
    demo.innerHTML += '<br>result =>  ' + secondMatch;
    <div>some SAMPLE address details in a page</div>
    <p>Tel: 0330 122 6000</p>
    <p>Email: help@yay.com</p>
    <p>Address: New House Bedford Road Guildford Surrey GU1 4SJ</p>
    <hr>
    <div>
    <b>the nodelist</b>
    </div>
    <div id="demo">nothing yet</div>