13

I'm just wondering if there's a way to locate numbers on a page with jQuery or plain Javascript.

Here's what I want to do:

Say "June 23" is on the page. What I want to do is be able to prepend and append some <span> selectors to the number.

Using :contains() with jQuery selects the whole thing, not just the number.

These strings are being generated without any wrapping elements by a Wordpress theme I'm working on, and I only want to select the number.

Any help would be appreciated! Thanks for even thinking about it.
-George

ggwicz
  • 568
  • 1
  • 5
  • 20

4 Answers4

12

You can walk through all the elements, looking at text nodes, and replacing them with updated content that has the number wrapped.

var regex = /(\d+)/,
    replacement = '<span>$1</span>';

function replaceText(el) {
    if (el.nodeType === 3) {
        if (regex.test(el.data)) {
            var temp_div = document.createElement('div');
            temp_div.innerHTML = el.data.replace(regex, replacement);
            var nodes = temp_div.childNodes;
            while (nodes[0]) {
                el.parentNode.insertBefore(nodes[0],el);
            }
            el.parentNode.removeChild(el);
        }
    } else if (el.nodeType === 1) {
        for (var i = 0; i < el.childNodes.length; i++) {
            replaceText(el.childNodes[i]);
        }
    }
}

replaceText(document.body);

Example: http://jsfiddle.net/JVsM4/

This doesn't do any damage to existing elements, and their associated jQuery data.


EDIT: You could shorten it a bit with a little jQuery:

var regex = /(\d+)/g,
    replacement = '<span>$1</span>';

function replaceText(i,el) {
    if (el.nodeType === 3) {
        if (regex.test(el.data)) {
            $(el).replaceWith(el.data.replace(regex, replacement));
        }
    } else {
        $(el).contents().each( replaceText );
    }
}

$('body').each( replaceText );

Example: http://jsfiddle.net/JVsM4/1/

Note that the regex requires the g global modifier.

Probably a little slower this way, so if the DOM is quite large, I'd use the non-jQuery version.

user113716
  • 318,772
  • 63
  • 451
  • 440
1

Just thinking out loud, but do you reckon this would work?

document.body.innerHTML = document.body.innerHTML.replace(/(\d+)/g, "<span class='number'>$1</span>")
Andreas Jansson
  • 3,137
  • 2
  • 30
  • 40
  • @andreas That seems like it would grab the numbers, but I only want to prepend and append the `span`. Would $1 replace the number? (I'm a javascript noob) – ggwicz Jun 25 '11 at 22:25
  • @ggwicz It replaces all numbers N with N, so all numbers get wrapped in s. I just did it on this page and it does tend to break things. :) – Andreas Jansson Jun 25 '11 at 22:30
  • @ggwicz it'll do exactly what you want it to - but instead of appending and prepending (which is only possible with DOM manipulation against elements) it'll take the number (as string) and then prepend <span class='number'> and append &lt/span>, then replacing the number text form the document with the result from the previous operation – planestepper Jun 25 '11 at 22:31
  • 2
    Replacing on `document.body.innerHTML` is a bad idea. For instance, it will destroy any event handlers such as `.click()`. – thirtydot Jun 25 '11 at 22:31
  • 1
    Thanks guys. This solution worked, but, like you said, it crashed some `.click()` and like `.mouseenter()` events I had going on. Patrick DW's solution worked best. – ggwicz Jun 25 '11 at 22:35
  • [You can't parse (X)HTML with regex.](http://stackoverflow.com/a/1732454/1529630). And replacing the entire HTML is completely wrong. – Oriol Jul 31 '16 at 22:26
0

It is fully dependent on what format your date is.

I found this website with a lot of different regular expressions (because you are just searching a normal piece of text for a date).

This seems a good option if this is your format for your date (dd MMM yyyy): http://regexlib.com/REDetails.aspx?regexp_id=405

I assume, because it is a template, that your dates will be the same for all pages. So the format will be the same as well. You can use the regular expression on every piece of text on your template if you define it well.

Marnix
  • 6,384
  • 4
  • 43
  • 78
0

You can also select decimal numbers that contain comma as thousands separators:

let regex = /([,\d]*\.?\d+)/g;

This will match 1234 and 1,234 and 1234.5678 and 1,234.5678 and 0.5678 and .5678.

Refer to the above answer for full solution.

Mahozad
  • 18,032
  • 13
  • 118
  • 133