9

Last week I added Facebook and Twitter share buttons to my rails app. I thought they were working fine but it seems they were not reliably loaded and required a refresh to get them to show. I thought this was a turbolinks issue as these things often are so I installed the 'jquery-turbolinks'gem. It isn't a turbolinks issue.

After looking around I found answers like this one and whilst adding twttr.widgets.load(); to the end of my twitter function solved that problem, I've had no luck with getting FB.XFBML.parse(); to make the Facebook share button to load without a refresh. On this Facebook dev page it doesn't list the share button as one of the things that can be fixed with that code.

My code, which is in a partial, is as follows:

<script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.0";
      fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk')); FB.XFBML.parse();</script>

<div class="share-buttons">
   <div id="fb-root"></div>
      <div class="fb-share-button" data-href="#{request.original_url}" data-width="110"></div>
</div>
Community
  • 1
  • 1
Ossie
  • 1,103
  • 2
  • 13
  • 31
  • What do you mean "required a refresh?". If you mean that a browser tab left open from before your deploy didn't update itself automatically after the deploy, then there's no reason why it should (unless you specifically put in some javascript to refresh some or all of the page at regular intervals). – Max Williams Aug 04 '14 at 12:57
  • No, no, I mean the first time you load a page it doesn't have the Facebook share button. If you then click refresh, it does. Across all pages with the link. As reported in the linked answer and for lots of issues with JS find & replace scripts like this. – Ossie Aug 04 '14 at 13:03
  • 1
    I have the same issue. Open the page and twitter and fb divs are empty. Refresh the page, and there they are. Lots of supposed solutions that don't change anything. Do I need a piece of js running that just repeatedly fires these off until they load? – JosephK Aug 15 '14 at 14:24
  • 1
    Disabling turbolnks in links to the page solved the problem for me. If you have these on many/most pages, best to disable Turbolinks on the entire app. – JosephK Aug 16 '14 at 04:18
  • I guess that's one solution but it seems very destructive especially when the fix for the twitter button worked a treat. I just need a similar javascript tweak for the FB one surely? Unsatisfactory business all round. – Ossie Aug 18 '14 at 13:55
  • Can you show a live example of the problem? – CBroe Aug 21 '14 at 10:38
  • https://minilegions.com/miniatures/637 for instance. – Ossie Aug 21 '14 at 10:42

5 Answers5

9

It is because sometimes your FB object is not even defined, and your FB.XFBML.parse() function gets called. You need to make calls to FB object when it has initialized. So your code changes to this :

<script>
   (function(d, s, id) {
          var js, fjs = d.getElementsByTagName(s)[0];
          if (d.getElementById(id)) return;
          js = d.createElement(s); js.id = id;
          js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.0";
          fjs.parentNode.insertBefore(js, fjs);
        }(document, 'script', 'facebook-jssdk'));

     window.fbAsyncInit = function(){  // this gets triggered when FB object gets initialized
            console.log("FB Object initiated");
            FB.XFBML.parse(); // now we can safely call parse method
       };

</script>
DhruvPathak
  • 42,059
  • 16
  • 116
  • 175
  • It's still not loading until after refresh. – Ossie Aug 28 '14 at 10:19
  • @WorldOfProper Can you please provide a link to that page – DhruvPathak Aug 28 '14 at 10:20
  • Sorry there's something wrong on my end. Just testing it. – Ossie Aug 28 '14 at 10:23
  • Here is an example of that code not working until after refresh https://minilegions.com/collections/1139 – Ossie Aug 28 '14 at 11:10
  • It shows for me first time in all browsers. Also there is a typing error in your javascript ` twttr.widgets.load()`, it should be twitter. – DhruvPathak Aug 28 '14 at 11:19
  • I don't know what to say now. I have it working in Chrome. Only after refresh in Safari and in Firefox it only loads before refresh some of the time. You've got it working in all browsers? As for the twttr.widgets.load, that's the code that Twitter themselves recommend https://dev.twitter.com/discussions/890 – Ossie Aug 28 '14 at 11:33
  • It works for me in firefox and chrome, do check your firebug console to fix the javascript errors you might be gettting in your browser – DhruvPathak Aug 28 '14 at 12:10
  • Safari reports this error "Blocked a frame with origin "https://minilegions.com" from accessing a frame with origin "https://www.facebook.com". The frame being accessed set "document.domain" to "facebook.com", but the frame requesting access did not. Both must set "document.domain" to the same value to allow access." Firefox reports "Invalid App Id: Must be a number or numeric string representing the application id." and "The "fb-root" div has not been created, auto-creating". – Ossie Aug 28 '14 at 12:30
  • Have awarded the bounty since it works in Chrome but I'll have to keep working on a solution for Firefox and Safari. Thank you. – Ossie Aug 29 '14 at 10:12
2

why not try a client side share button rather then the server side share button. Server side is only needed if you where going to do extra processing after it renders on the server side. Chances are you don't need to render on the server.

<a href="https://www.facebook.com/sharer/sharer.php?u=example.org" target="_blank">
  Share on Facebook
</a>

you could also just go to https://developers.facebook.com/docs/plugins/share-button/ pass in the url you would like to share it will generate example code for you. you can then based on that code, change the url of the shared page on the server side using a variable in its place. This would let you have a reusable code snippet that can be used for every page on your site.

<a href="https://www.facebook.com/sharer/sharer.php?u={$pageURLValue}" target="_blank">
  Share on Facebook
</a>

When you're rendering the page just set {$pageURLValue} to what the current page is. Sorry i don't know rails so the variable tag may be different. replace {$pageURLValue} with what ever the value tag is for rails.

Patrick W. McMahon
  • 3,488
  • 1
  • 20
  • 31
  • I will test these out again but as I remember it they don't do what I want. The code I'm using gives you the option to choose where to share (Timeline/Friend/Group) and the Privacy setting. It also opens a nice neat little popup rather than a new window. It matches the behaviour of the twitter code. I'll test it out though. – Ossie Aug 27 '14 at 16:07
  • you will notice the facebook url has the shared url change that to a variable in your server side code and pass in what ever url you want to share to it. That's all you need to make it work. It's going to make a popup every time the user needs to log in. If the user is already logged into facebook it may not ask them to login. – Patrick W. McMahon Aug 27 '14 at 16:10
0

I was struggeling with the same problem - I had a div popup with an iframe pointing to a html page containing the twitter button. I had the popup hidden from start. This apparently causes the twitter button not to render.. instead of hiding it with display:none / visibility:hidden position the popup far far away (left : -10000px) and reset the left position when you want to show the popup.. Hope it might help someone..

Ghost1
  • 320
  • 3
  • 5
0

I embedded a Facebook page widget into my website which was an Angular SPA and I had the same "needs a refresh" problem because I had mistakenly put the Script in a parent containing view page called "index.html", but I'd put the embedded DIV in a different sub view specifically on a "social_media.html" page. "index.html" loaded and fired the script on first visit to any page of my website, but at that point had no visibility of the DIV on my as of yet unused and un-requested "social_media.html" view, so when the user eventually navigates to a link that uses the sub view for "social_media.html", "index.html" was not "re-loaded" and thus did not re-fire the script unless I clicked refresh. To fix it I just put the Script and DIVS all into the same "social_media.html" to load and fire at once on all requests for the "social_media.html" to be loaded as a view page. Note: I also had to add DhruvPathak's approach too.

Ade
  • 1
  • 1
0

Just call function FB.XFBML.parse(); dynamicaly instead of reloading the page.