views:

86

answers:

2

Currently I have:

this.html(this.html().replace(/<\/?([i-z]+)[^>]*>/gi, function(match, tag) { 
            return (tag === 'p') ? match : '<p>';
            return (tag === '/p') ? match : '</p>';
            return (tag === 'script') ? match : 'script';
            return (tag === '/script') ? match : '/script';
        }));

However, the <p> and <script> tags are still being removed, what am I doing wrong?

+7  A: 

You can't use multiple return statements with ternary operators like that. The first one will be evaluated and all the rest will be ignored. Use proper if statements or a switch statement,

        if (tag === 'p') 
            return '<p>';
        else if (tag === '/p')
            return '</p>';
        else if (tag === 'script') 
            return 'script';
        else if (tag === '/script') 
            return '/script';
        else 
            return match;

switch example:

switch (tag) {
    case 'p': return '<p>';
    case '/p': return '</p>';
    //...
    case default: return match;
}

You could also use an object as a map,

var map { 'p': '<p>', '/p' : '</p>' /*, ... */ };
return map[tag] || match;

or nested ternary operators,

return tag === 'p' ? '<p>' 
       : tag === '/p' ? '</p>'
       : tag === 'script' ? '<script>'
       : tag === '/script' ? '</script>'
       : match;

But these are often less readable and harder to maintain.

Andy E
Or you might want to use a switch statement for your multiple if / else if / else construction - I guess that's just a matter of personal preference.
Ken Ray
@Ken, yes that's another option and I've added an example.
Andy E
Couldn't you reduce a lot of duplication by having an array `['p','script']`, and only wrapping the variable in `<>` if it matches `x` or `/x`? Just seems like `p` and `script` get written a lot there..
Jeriko
@Jeriko: of course you could, but I don't want to do *all* the work ;-)
Andy E
@Andy :P [stupidlimit]
Jeriko
+3  A: 

Am pretty sure of this now, the regex doesnt work for closing tags, and only looking for i-z isnt catching the full tag.

Try the regex of:

/<\(/?[a-z]+)[^>]*>/gi

something odd happens with the code though when trying to return '<script>' when matching script so in these cases maybe return match

Andy E's head's suggestion of changing the if statement structure I think helps too, the main thing is the

    else 
        return match;

or even do this as a default instead of specifically looking for p and script tags, it will return the match value of the matched tag if no if statement is met.

Code I wrote for testing:

<!DOCTYPE HTML>
<html>
<body>
<div id="manipulate">
<p>Hello</p>
<script type="text/ecmascript">
// test
</script>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/ecmascript"></script>
<script type="text/ecmascript">
$(document).ready(function(){
alert("start");
$("#manipulate").html($("#manipulate").html().replace(/<\/?([a-z]+)[^>]*>/gi, function(match, tag) { 
            alert(tag);
            alert(match);
        if (tag === 'p') 
            return '<p>';
        else if (tag === '/p')
            return '</p>';
        else if (tag === 'script') 
            return match;
        else if (tag === '/script') 
            return match;
        else 
            return match;
        }));
});
</script>
</body>
</html>
Luke Duddridge
Worked groovy, cheers v. much.
Neurofluxation
+1, didn't see the [i-z] bit at all, my attention got drawn by those ternary operators :-)
Andy E
@Andy: shame you cannot make a combined correct answer so everyone involved gets points.
Luke Duddridge
@Luke: don't worry, I got a few upvotes to keep me sweet ;-)
Andy E