Turbolinks 5.0 and Facebook SDK

2019-03-22 09:41发布

Last week I upgraded to Rails 5 which is using Turbolinks 5.0. I used the following script to load the Facebook like button with Turbolinks 3.0:

fb_root = null
fb_events_bound = false

$ ->
  loadFacebookSDK()
  bindFacebookEvents() unless fb_events_bound

bindFacebookEvents = ->
  $(document)
    .on('page:fetch', saveFacebookRoot)
    .on('page:change', restoreFacebookRoot)
    .on('page:load', ->
      FB?.XFBML.parse()
    )
  fb_events_bound = true

saveFacebookRoot = ->
  fb_root = $('#fb-root').detach()

restoreFacebookRoot = ->
  if $('#fb-root').length > 0
    $('#fb-root').replaceWith fb_root
  else
    $('body').append fb_root

loadFacebookSDK = ->
  window.fbAsyncInit = initializeFacebookSDK
  $.getScript("//connect.facebook.net/nl_NL/all.js#xfbml=1")

initializeFacebookSDK = ->
  FB.init
    appId     : 'YOUR_APP_ID'
    channelUrl: '//WWW.YOUR_DOMAIN.COM/channel.html'
    status    : true
    cookie    : true
    xfbml     : true

With Turbolinks 5.0 the like button will only show when the page gets reloaded. When I don't reload the page and just click on a link I get this error:

Blocked a frame with origin "https://www.facebook.com" from accessing a frame with origin "http://localhost:3000".  The frame requesting access has a protocol of "https", the frame being accessed has a protocol of "http". Protocols must match.

Does anyone know how to fix this?

3条回答
贪生不怕死
2楼-- · 2019-03-22 10:01

Here is a way to integrate Turbolinks 5 with Facebook SDK.

In your layout template:

// /source/layouts/layout.erb
<body class="<%= page_classes %>">
  <%= yield %>
  <div id='permanent' data-turbolinks-permanent></div>
</body>

Then in your javascript using jQuery here:

function FBInit() {
  FB.init({
    appId      : 'YOUR_KEY',
    xfbml      : true,
    version    : 'v2.8'
  });
  $('#permanent').append( $('#fb-root').detach() );
};

$(document).ready(function(){
  $.getScript( "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.8", FBInit);
});

$(document).on('turbolinks:load', function(event){
  if (typeof FB !== "undefined" && FB !== null) {
    FB.XFBML.parse();
  }
});

$(document).on("turbolinks:before-cache", function() {
    $('[data-turbolinks-no-cache]').remove();
});

Then use any Facebook plugins using the data-turbolinks-no-cache attribute like this:

<div data-turbolinks-no-cache 
  class="fb-like" 
  data-href="#" 
  data-layout="standard" 
  data-action="like" 
  data-size="small" 
  data-show-faces="true" 
  data-share="true"></div>

Here is the gist and here is a blog post explaining how it works

查看更多
家丑人穷心不美
3楼-- · 2019-03-22 10:15

If you prefer to use native Turbolinks 5 events, you can add this script to your Rails assets:

// FacebookSDK
// https://developers.facebook.com/docs/plugins/page-plugin/
(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.8";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk')); // Replace 'facebook-jssdk' with your page id.

// Compatibility with Turbolinks 5
(function($) {
  var fbRoot;

  function saveFacebookRoot() {
    if ($('#fb-root').length) {
      fbRoot = $('#fb-root').detach();
    }
  };

  function restoreFacebookRoot() {
    if (fbRoot != null) {
      if ($('#fb-root').length) {
        $('#fb-root').replaceWith(fbRoot);
      } else {
        $('body').append(fbRoot);
      }
    }

    if (typeof FB !== "undefined" && FB !== null) { // Instance of FacebookSDK
      FB.XFBML.parse();
    }
  };

  document.addEventListener('turbolinks:request-start', saveFacebookRoot)
  document.addEventListener('turbolinks:load', restoreFacebookRoot)
}(jQuery));

From: https://gist.github.com/6temes/52648dc6b3adbbf05da3942794b97a00

查看更多
SAY GOODBYE
4楼-- · 2019-03-22 10:20

The reasons for this is because some of the events was renamed in Turbolinks 5 and its not compatible with Turbolinks 3. my suggestion is try creating a file under javascripts/ folder called compatibility.coffee

compatibility.coffee

{defer, dispatch} = Turbolinks

handleEvent = (eventName, handler) ->
  document.addEventListener(eventName, handler, false)

translateEvent = ({from, to}) ->
  handler = (event) ->
    event = dispatch(to, target: event.target, cancelable: event.cancelable, data: event.data)
    event.preventDefault() if event.defaultPrevented
  handleEvent(from, handler)

translateEvent from: "turbolinks:click", to: "page:before-change"
translateEvent from: "turbolinks:request-start", to: "page:fetch"
translateEvent from: "turbolinks:request-end", to: "page:receive"
translateEvent from: "turbolinks:before-cache", to: "page:before-unload"
translateEvent from: "turbolinks:render", to: "page:update"
translateEvent from: "turbolinks:load", to: "page:change"
translateEvent from: "turbolinks:load", to: "page:update"

loaded = false
handleEvent "DOMContentLoaded", ->
  defer ->
    loaded = true
handleEvent "turbolinks:load", ->
  if loaded
    dispatch("page:load")

jQuery?(document).on "ajaxSuccess", (event, xhr, settings) ->
  if jQuery.trim(xhr.responseText).length > 0
    dispatch("page:update")
查看更多
登录 后发表回答