1

ok here is what i have:

<div id="mydiv">
<font color="green"><font size="3"><font face="helvetica">hello world</font></font></font>
</div>

I know the tags are strange, but that's what produced by the website. So basically I want to change the font tag to bbcdoe tag, the jquery code I wrote:

$("#mydiv").find("font").text(function(){
    var text = $(this).text();
    var size = $(this).attr("size");
    var color = $(this).attr("color");
    var face = $(this).attr("face");;
    if(size!=undefined){
        return '[size="'+size+'"]'+text+'[/size]';
    }
    if(color!=undefined){
        return '[color="'+color+'"]'+text+'[/color]';
    }
    if(face!=undefined){
        return '[type="'+face+'"]'+text+'[/type]';
    }

});

so what I got is only: [color="green"] hello world [/color]. always only the first tag. any idea?

ps: I tried each, replaceWith, html(), all the same result. only the first tag is change.

Beny Xu
  • 39
  • 1
  • 6
  • The `.text()` jQuery function returns the text inside the element, not the HTML inside the element, so any HTML tags will be stripped out. There are other issues with your code, such as the last if checking `size` when it should be checking `face`. – Anthony Grist Mar 26 '12 at 15:57
  • By the way, your example code doesn't match your alleged output. If you really want `[color="green"] hello world [/color]`, you should output `'[color="'+color+"]'+text+'[/color]'`, that is, including the `text` and excluding the first `]`. – Mr Lister Mar 26 '12 at 16:14

3 Answers3

1

A room full of sad, wailing kittens wishes that you'd get rid of those <font> tags, but you could probably make it work by explicitly working your way down through the nested tags.

It does what it does now because the outer call to .text() runs for the very first <font> tag, and it obliterates the other tags.

edit — to clarify, when you call

$('#mydiv').find('font')

jQuery will find 3 font tags. The library will therefore call the function you passed into .text() for each of those elements. However, the first call will have the effect of removing the other two <font> elements from the DOM. Even though the library proceeds to call your callback for those elements, there's no effect because they're not on the page anymore.

Here's what could work:

var $fonts = $('#mydiv').find('font');
var text = $fonts.text();

var attrs = {};
$fonts.each(function(_, font) {
  var names = ["size", "color", "face"];
  for (var i = 0; i < names.length; ++i)
    if (font[names[i]]) attrs[names[i]] = font[names[i]];
});

var newText = "";
for (var name in attrs) {
  if (attrs.hasOwnProperty(name))
    newText += '[' + name + '=' + attrs[name] + ']';
}
newText += text;
for (var name in attrs) {
  if (attrs.hasOwnProperty(name))
    newText += '[/' + name + ']';
}

$('#mydiv').text(newText);

Note that I'm not really sure why you want to put the BBCode onto the page like that, but it seems to be the intention.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • 1
    Ehm... but the OP _is_ trying to get rid of the `` elements. – Mr Lister Mar 26 '12 at 16:09
  • but if I put alert, it will still alert 3 times, which mean it found 3 font tag, even though the first process should have eliminate other two. – Beny Xu Mar 26 '12 at 16:15
  • Well jQuery will *find* all three `` elements *before* it calls the outer `.text()`. After that, the second two elements have been removed from the DOM, so updating their contents makes no difference. – Pointy Mar 26 '12 at 16:20
  • 1
    @MrLister good point, I guess, but something's putting them there in the first place, and it's hard to explain such nuances to a sad kitten. – Pointy Mar 26 '12 at 16:22
1

The reason it doesn't work is because when you call

$("#mydiv").find("font").text("New text")

For each font tag, starting from the first tag, it will replace the text within that tag.

Here is an example to show you what's going on.

Example | Code

$fonts = $("font","#mydiv");

console.log($fonts.text());

$fonts.text(function(){
    return "New text";
});

console.log($fonts.text());

Here is an example of how you could do it instead

Example | Code

jQuery.fn.reverse = [].reverse;

var attributes= ["size", "color", "face"];
var text = $.trim($("#mydiv").text());

$("font","#mydiv").reverse().each(function(i, e) {
    for (var i = 0; i < attributes.length; ++i){
        var attr = $(e).attr(attributes[i]);

        if( typeof attr != "undefined")
            text = "["+attributes[i]+"="+attr+"]"+text+"[/"+attributes[i]+"]";
    }
});

$("#mydiv").text(text);
ShadowScripter
  • 7,314
  • 4
  • 36
  • 54
0

Seems to me your first line should be:

$("#mydiv").find("font").each(function(){
graphicdivine
  • 10,937
  • 7
  • 33
  • 59
  • I should've mention it in the question, I tried each, replaceWith, html(), all the same result. only the first tag is change. – Beny Xu Mar 26 '12 at 16:05