Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does ie apparently reflow DOM when encountering <fb:xxx> fbml elements when correctly using the fbml xmlns?

I have a page containing a number of facebook "Like" buttons, embedded using the inline fbml technique (as opposed to iframe). Simple enough. The page renders fine, everything works as expected.

HOWEVER...

Once I add the xmlns:fb="http://www.facebook.com/2008/fbml" namespace declaration to the document I am noticing a radical degradation of initial page render times in IE. Closer inspection (using the ie8 developer tools) reveals that the entire DOM appears to be "refreshing" or "reflowing" over and over again, for a short period after the page has initally loaded. Some further mucking about reveals that the number of reflows is apparently proportional to the number of <fb:xxx> elements in the document.

Removing the xmlns declaration makes the problem go away.

Anyone experienced this before?

UPDATE:

Some further digging has revealed some more specifics... The issue is indeed that IE is re-flowing the page, including re-executing any inline scripts and so forth. The cause does not appear to be the inclusion of the xmlns per se, rather the xfbml rendering of the buttons themselves. Adding the xmlns simply triggered the xfbml rendering, without the xmlns, the buttons never rendered in the first place. The following markup illustrates the issue.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" xmlns:fb="http://www.facebook.com/2008/fbml">
  <head>  
    <script type="text/javascript">
      alert('some inline js');
    </script>
  </head>
  <body>
    <div id="fb-root"></div>

    <div>
      <fb:like href="http://example.local/1" layout="button_count" show_faces="false" width="80" action="like" font="arial" colorscheme="light"></fb:like>
      <fb:like href="http://example.local/2" layout="button_count" show_faces="false" width="80" action="like" font="arial" colorscheme="light"></fb:like>
      <fb:like href="http://example.local/3" layout="button_count" show_faces="false" width="80" action="like" font="arial" colorscheme="light"></fb:like>
    </div>

    <script src="http://connect.facebook.net/en_US/all.js#xfbml=1" type="text/javascript"></script>

  </body>
</html>

When run in ie, the above example generates 3 alerts, I'd expect to see only one.

like image 252
Bernos Avatar asked May 04 '11 11:05

Bernos


1 Answers

You seem to be experiencing facebook bug 9777. It's been around since the beginning of the new all.js. I think there have been a couple of attempts at fixing it, which hasn't really worked. Looks like the priority just got pushed up a notch last week. Let's see if it gets fixed anytime soon.

In any case, the problem you are seeing is not caused by the DOM tree being modified. In fact, the javascript being triggered isn't even in your page ... your "top" page that is.

The script is in the iframes created by the facebook script in place of your fb:like elements.

Instead of "some inline js", if your alert shows the following:

alert("This: " + window.location.href + "\nTop: " + window.top.location.href);

you will see where it is coming from. In the "This" URLs you'll see fb_xd_fragment along with a whole bunch of parameters appended to your url. Basically the facebook script is redirecting each iframe window to the URLs you are seeing, which is kicking off your scripts.

In http://developers.facebook.com/docs/reference/javascript/FB.init/ they discuss the Custom Channel URL (channelURL) init param as a workaround, which doesn't seem to have worked for many people. And many people are getting request floods on the path they provide as the channelURL.

 

Just a thought ... Have you tried loading the "like" buttons using the iframe method? Was that any quicker?

Otherwise you could try lazy loading the all.js script ...

(function() {
  var e = document.createElement('script');
  e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js#xfbml=1';
  e.async = true;
  document.getElementById('fb-root').appendChild(e);
}());
like image 173
musaul Avatar answered Oct 15 '22 08:10

musaul