2

I'm trying to have plain (no jQuery, mootools, etc) JavaScript add span tags with numbered ID's to each word within a certain class.

For example:

<p class="read-aloud">
  Here's a test.
</p>

would become

<p class="read-aloud">
  <span id="word001">Here's</span> <span id="word002">a</span> <span id="word003">test.</span>
</p>`

Punctuation needs to be included, but not quotes.

I have this (which I've modified from another post):

function add-readAloud-uIDs(matchClass)
    {
    var elems = document.getElementsByTagName('*'),i;
    for (i in elems)
        {
        if((" "+elems[i].className+" ").indexOf(" "+matchClass+" ") > -1)
            {
            elems[i].innerHTML.replace(/\b([A-Za-z][a-z]*?-?’?'?[a-z]*?\.?,?!?\??)([ | ”])("?)/g, '<span id="word">$1</span>$2$3');
            }
        }
    }

window.onload = function ()
    {
    add-readAloud-uIDs("read-aloud");
    }

​ Also at jsfiddle

I'm having trouble finding a way to increment the ID's. How might I go about this?

Also, the reason I don't want to use a js library is because this is going to be running on the iPad. Performance is important, as well as the flexibility to use whichever library for other purposes needed without conflict.

Arktype
  • 95
  • 1
  • 6
  • Your function name is invalid (the hyphens), so in fact nothing is being executed. Is this your actual code? – pimvdb Mar 10 '12 at 21:34
  • @pimvdb This was my actual code, but it wasn't working. Now I know why... Thank you. – Arktype Mar 10 '12 at 23:40

2 Answers2

1

I think the basic idea will be to use regexp replace with a function. The small example below can hopefully be a starting point:

var text = "Here's a test";
var rx = /\b[\w']+\b/g;

var fn = function(str)  {
    fn.wordCount += 1;      
    return '<span id="word' + fn.wordCount + '">' + str + '</span>';
}
fn.wordCount = 0;

result = text.replace(rx, fn);  
// result has '<span id="word1">Here's</span> <span id="word2">a</span> <span id="word3">test</span>'

You will need to modify the regexp to match words, probably there are more characters you will want to match within the [\w'] set.

The replacement function uses something like a static variable wordCount to keep track of how many replacements have happened and use that as the id in the span.

Each call to replace text would have to set fn.wordCount = 0;

yas
  • 3,520
  • 4
  • 25
  • 38
1

You can use a custom replace function like this:

var items = document.getElementsByClassName('readAloud');

var idCntr = 1, item;
for (var i = 0; i < items.length; i++) {
    item = items[i];
    item.innerHTML = item.innerHTML.replace(/[^\s]+/g, function(match) {
        return('<span id="word' + idCntr++ + '">' + match + '</span>');
    });
}

Demonstration: http://jsfiddle.net/jfriend00/5v54f/

For the definition of a word, I chose any sequence of characters that does not include whitespace, but you can obviously tweak the regular expression to your liking.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • This works great, thanks! I thought you couldn't get elements by a class name that easily with JavaScript, only IDs. – Arktype Mar 10 '12 at 23:39
  • @Arktype - just so you know, `getElementsByClassName` is not supported in IE before IE9 (you can see browser support [here](http://caniuse.com/getelementsbyclassname)). If you plan on using it, you can implement a short shim that provides that functionality in IE if the native functionality doesn't exist. You can see an implmentation of it [here](http://stackoverflow.com/a/1820237/816620) and read about some of the speed issues [here](http://ejohn.org/blog/getelementsbyclassname-speed-comparison/). – jfriend00 Mar 10 '12 at 23:45
  • @Arktype - personally, I either use jQuery, YUI or the Sizzle library in my projects and all of them come with a full blown selector library that takes care of all DOM queries and browser support for all old browsers. It saves a ton of time worry about cross browser stuff and saves a ton of bugs. Sizzle is very lightweight if all you need is selector queries and don't want a larger library. – jfriend00 Mar 10 '12 at 23:52
  • that is good to know. For this application it will be strictly webkit so it won't be a problem. I'll look into Sizzle, most of the time all I'm after is simple things like this. I see the reasoning in using a JS library, and I guess there really isn't a reason not to use one. Thanks! – Arktype Mar 10 '12 at 23:54