Dav
Dav

Reputation: 150

Javascript/ActionScript do for each indexOf?

The screenshot below the code shows me issue. It only rainbowfies one instance of text.

How can I get this code to do each [rainbow]specified[/rainbow] text?

It's actually for ActionScript but it works in Javascript too so I've been testing on http://jsfiddle.net

var txt = "This is a [rainbow]test to show that I can[/rainbow] make whatever I want [rainbow]appear as a rainbow[/rainbow] because I am [rainbow]awesome[/rainbow].";

if ((txt.indexOf("[rainbow]") > -1) && (txt.indexOf("[/rainbow]") > -1)) {
    var firstChar = txt.indexOf("[rainbow]") + 9;
    var lastChar = txt.indexOf("[/rainbow]");

    var RAINBOWTEXT = '';
    var i = firstChar;

    while (i < lastChar) {
        RAINBOWTEXT += txt.charAt(i);
        i++
    }
    var text = RAINBOWTEXT;
    var texty = '';

    colors = new Array('ff00ff', 'ff00cc', 'ff0099', 'ff0066', 'ff0033', 'ff0000', 'ff3300', 'ff6600', 'ff9900', 'ffcc00', 'ffff00', 'ccff00', '99ff00', '66ff00', '33ff00', '00ff00', '00ff33', '00ff66', '00ff99', '00ffcc', '00ffff', '00ccff', '0099ff', '0066ff', '0033ff', '0000ff', '3300ff', '6600ff', '9900ff', 'cc00ff');
    var i = 0;

    while (i <= text.length) {
        var t = text.charAt(i);

        if (t != undefined) {
            texty += "<font color=\"#" + colors[i % colors.length] + "\">" + t + "</font>";
            i++;
        }
    }

    texty = texty.replace("> <", ">&nbsp;<");
    var REPLACEME = "[rainbow]" + RAINBOWTEXT + "[/rainbow]";
    txt = txt.replace(REPLACEME, texty);
    document.write(txt);
}​

enter image description here

Upvotes: 0

Views: 373

Answers (3)

jimbo
jimbo

Reputation: 11042

var colors = [
  'f0f', 'f0c', 'f09', 'f06', 'f03', 'f00', 'f30', 'f60', 'f90', 'fc0',
  'ff0', 'cf0', '9f0', '6f0', '3f0', '0f0', '0f3', '0f6', '0f9', '0fc', 
  '0ff', '0cf', '09f', '06f', '03f', '00f', '30f', '60f', '90f', 'c0f'
];
function rainbowify(text) {
  return text.replace(/\[rainbow\](.*)\[\/rainbow\]/g, function(_, inner){
    return inner.replace(/./g, function(ch, i){
      return '<span style="color:#' + colors[i % colors.length] + ';">' + ch + '</span>';
    });
  })
}

Here's how I'd do it.

Upvotes: 2

apsillers
apsillers

Reputation: 115940

If we can make assumptions about no interleaving or nesting of [rainbow] tags, I'd just use a regular expression with a simple replacer callback:

var rainbowified = txt.replace(/\[rainbow\](.*?)\[\/rainbow\]/, function(textWithTags, textBetweenTheseTags) {
    var text = textBetweenTheseTags;
    ....
    for(var i = 0; i < text.length; ++i) {
        // rainbowify each letter of text...
    }
    ...
    return textWithFontTags;
}

You can use this to get a new string with the transformation you want.

Also, the font tag is depricated; you should use span with color:#XXXXXX in the style attribute.

Upvotes: 3

Bergi
Bergi

Reputation: 664484

Make it a loop. .indexOf can take a starting point as the second parameter, so with starting the next iteration at lastChar+10 should work.

Apart from that, it might be easier to do it fully with regex and .replace:

return txt.replace(/\[rainbow\](.+?)\[\/rainbow\]/g, function(all, match, index, str) {
    return createRGBrainbowArray(match.length).map(function(color, i) {
        return '<span style="color:#'+color+'">'+match[i]+'</span>';
    }).join("");
});
function createRGBrainbowArray(l) {
    // should return an Array of length l with hexadecimal color strings,
    // representing a nice rainbow
}

Upvotes: 1

Related Questions