开发者

jQuery very strange behavior - output html not in same order as appending

I have a function that refreshes queue of elements - each one have to be represented by div, but effect is total WTF for me. Here is the function:

this.refreshQueue = function( ) {
    $("#queue").html('');
    for( var id in self.queue ) {
        console.log('Opening div');
        $("#queue").html( $("#queue").html()+'&开发者_StackOverflow社区lt;div class="queueelement">');
        self.appendUser( self.queue[id].data );
        console.log('Closing div');
        $("#queue").html( $("#queue").html()+'</div>');
    }
} 

this.appendUser = function( data ) {
    console.log('Appending h4');
    $("#queue").html( $("#queue").html()+'<h4>'+data.login +'</h4>' );
}

I See in firebug log:

Opening div
Appending h4
Closing div

That's ok, but HTML after that operation looks like that:

<div class="queueelement"></div>
<h4>Somelogin</h4>

Instead of:

<div class="queueelement">
<h4>Somelogin</h4>
</div>

Any ideas what causes this ?

Early i have tried with .append() - same effect.


See the documentation:

This method uses the browser's innerHTML property.

You cannot set an opening tag and later add a closing tag. The browser is correcting the opening tag by adding a closing one automatically.

You are not just setting HTML (as text), it is also parsed and DOM elements are created and inserted into the tree. To be parseable, the HTML has to be correct.

This will happen with any method you use. You can also try it in the console:

> d = document.createElement('div');
  <div>​</div>​
> d.innerHTML = '<span>';
  "<span>"
> d.innerHTML += 'foo';
  "<span></span>foo"
> d.innerHTML += '</span>';
  "<span></span>foo</span>"
> d.innerHTML
  "<span></span>foo"

You have to build the whole string and insert it at once.


The problem is that you're trying to put HTML into a DOM as if it was an HTML document. When a browser reads an HTML page, it converts it into a DOM structure. This is a tree-like system of related nodes. It bears some resemblance to the original HTML and can be serialised to it, but you can't just add HTML to it and expect it to work as if you were adding content to the original document.

$("#queue").html( $("#queue").html()+'<div class="queueelement">');

That says "add a div node to the end of the HTML". Since every node must be closed or self-closing, the browser automatically closes it.

When you add the </div> later, it is nonsensical -- a closing tag can't exist on its own, so it is ignored.

The solution is to add all the HTML together and insert it in one go, or to modify the div element from within appendUser.


I think you'll have to build a string and output to the html at once, instead of inserting unfinished elements using .html().

Something like this:

    this.refreshQueue = function () {
        var output = "";
        for (var id in self.queue) {
            output += "<div class=\"queueelement\">";
            output += appendUser(self.queue[id].data);
            output += "<\div>";
        }
        $("#queue").html(output);
    }

    this.appendUser = function (data) {
        return "<h4>" + data.login + "</h4>";
    }


html() closes any unclosed tags automatically. So when you try and add more html it has already closed the div. Why not just use wrap() ?

self.appendUser( self.queue[id].data ).wrap($('<div />').addClass('queueelement')).parent().appendTo($("#queue"));

You'd have the function itself just return the $('<h4 />)' element


You could also put the tag into its own variable and then add your inner string to that div variable, and then append it to a container div.

    var div = $("<div class='elem'></div>");
    div.append("<h4>Some Login</h4>");

    $("#out").append(div);

http://jsfiddle.net/Gz3qR/

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜