FB.XFBML.parse() on individual element does nothing

Eric picture Eric · Aug 19, 2013 · Viewed 10.1k times · Source

I have a big page with a "load more" button at the bottom; each click on "load more" loads more content via AJAX. Part of that content is Facebook like buttons:

<div class="fb-like" data-href="http://mysite.com/a<?=$x ?>" data-width="100" data-layout="button_count" data-show-faces="false" data-send="false"></div>

After loading the additional content, I can ask Facebook to re-parse the entire page with FB.XFBML.parse(); (which causes those divs to turn into actual like buttons). This works perfectly, however, it gets slow right away, since Facebook re-parses the content that was already on the page, not just the new content. Every time the user clicks "load more" it parses the entire page, so there's just more and more for the FB function to do.

Now here's the good news: the docs for FB's parse method say:

...to only evaluate a portion of a document, you can pass in a single element.

FB.XFBML.parse(document.getElementById('foo'));

So I thought, okay, when the user clicks "load more," I'll wrap that fresh HTML in a unique div, then use jQuery to walk through the div, find all the Facebook tags and ask Facebook to parse just those. Good idea, right? But it doesn't work. The code seems to be passing the elements to Facebook after they're loaded, but they aren't parsing. Code:

// "c" is my container div (a jQuery object, i.e. c = $('#container'); ) 
// "load more" button
$('#loadmore').click(function() {
    $.ajax({
        url: "/loadmore.php",
        success: function(html) {
            if(html) {
                // wrap new HTML in special div & append
                newDivName = "d"+String(new Date().valueOf());
                var $newHtml = $("<div id='"+newDivName+"'>"+html+"</div>");
                c.append($newHtml);

                // walk through new HTML and get all Facebook "like" buttons and parse them
                $('#'+newDivName+' .fb-like').each(function() {
                    FB.XFBML.parse(this);
                });
            }
        }
    });

});

There's no error message, it just doesn't produce any results. The debug code to the console looks perfect, it's finding all the right elements.

UPDATE play with it at this simple jsfiddle: http://jsfiddle.net/pnoeric/NF2jz/4372/

UPDATE 2 I also tried changing the code from HTML5 to FBML (click "Get Code" on this page to see the difference), which not only had the same result but now also would only load one additional button on the ajax call, instead of two. So it got worse! You can play with the FBML version here: http://jsfiddle.net/pnoeric/4QkbX/2/

Answer

Grin picture Grin · Aug 24, 2013

The docs specifies that the dom element should be root DOM node, defaults to body. So I replace.each function call with a single call to a .parse method with the created DOM element. Here is a jsfiddle.

 FB.XFBML.parse($newhtml[0]);

Note: FB.XFBML.parse() should be called on a parent element of the widget, not directly on the XFBML element itself.