1

My regular expression won't return all instances of <li>.+<\/li> found in textarea.

I Googled, and tried /g, but doesn't work.

Here is the Fiddle.

This is my function(){...}:

function doIt() {

    var input = document.getElementById("input");
    var olPatt = /<ol>\s*(?:<li>.+<\/li>\s*)+<\/ol>/,
        ol = input.value.match(olPatt),
        olLi = ol.toString().match(/<li>/g), // MATCH ALL <li> with /g
        olLiB = ol.toString().match(/<\/li>/g); // MATCH ALL </li> with /g
    var i = 1; // start with 1

    input.value = input.value.replace(/<ol>/, "").replace(/<\/ol>/, "").replace(/\s*/, ""); // remove ol tags

    input.value = input.value.replace(olLi, function() {return i++ + "." + " ";}).replace(olLiB, " ");
    // should replace ALL <li> found in <ol> with number starting with 1 </li>        

}

If you're given this:

<ol>
<li>Hello world! :)</li> 
<li>Hello how are you</li> 
<li>good</li>
</ol>

It returns this: (incorrect)

1. Hello world! :)  
<li>Hello how are you</li> 
<li>good</li>

But, I want this: (correct)

1. Hello world! :)  
2. Hello how are you
3. good
11
  • 2
    I believe you just need to add 'g' to the end for a global search. So like this: input.value.replace(/<ol>/g, "") Commented Jun 26, 2014 at 23:11
  • 1
    Also, {1} is redundant, and you should consider using an HTML parser (like the one that’s built into browsers). Commented Jun 26, 2014 at 23:12
  • @false It may be unnecessary, but it's easier to read! Commented Jun 26, 2014 at 23:14
  • 1
    <ol>{1} is easier to read than <ol>? Commented Jun 26, 2014 at 23:14
  • 1
    @Matthew: I would definitely recommend against it; it’s misleading, because the {1} only applies to the >. If you changed it to 2 later, it would match <ol>>, not <ol><ol>. Commented Jun 26, 2014 at 23:17

2 Answers 2

1

http://jsfiddle.net/3jthN/10/

You need to add the global modifier at the point where you do the actual replacing.

In this case it's in this line:

input.value = input.value.replace(olLi, function() {return i++ + "." + " ";}).replace(olLiB, " ");

Because you're specifying the regex pattern from a variable, you need to use the RegExp constructor and pass the global modifier as the second argument. The fiddle demonstrates this.

new RegExp(olLi, 'g')
Sign up to request clarification or add additional context in comments.

Comments

1

Here:

input.value = input.value.replace(olLi, function () {
    return i++ + "." + " ";
}).replace(olLiB, " ");

olLi and olLiB are already matches on ol.toString(). Just keep them as regular expressions, or perform the replacement in another callback (this seems the most correct):

input.value = input.value.replace(/<ol>\s*((?:<li>.+<\/li>\s*)+)<\/ol>/g,
    function (list, listItems) {
        return listItems.replace(/<li>/g, function () {
            return i++ + '. ';
        }).replace(/<\/li>/g, '');
    });

Updated jsFiddle

2 Comments

Thank you, this works great! I have a question; where is the list parameter? Is it just there as a placeholder? The first parameter in function (list, listItems) {...}
@Matthew: Yep! It contains the entire match; listItems is the parenthesized subexpression, i.e. the same thing but minus the <ol> and </ol>.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.