Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

jquery

each

xfbml

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/

like image 536
Eric Avatar asked Aug 19 '13 01:08

Eric


2 Answers

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.

like image 130
Grin Avatar answered Sep 28 '22 06:09

Grin


In my case the accepted solution wouldn't work, because the FB posts are appended in the same DOM container.

What i ended up doing, is run a FB.XFBML.parse() to the container, use an .each loop and removeClass the fb-post, add class facebook-post-loaded. Then on subsequent Ajax calls and fetches of new fb posts, the FB.XFBML.parse() would not pick the already loaded elements since they don't have the fb-post class anymore.

like image 33
ilias-sp Avatar answered Sep 28 '22 06:09

ilias-sp