【问题标题】:Turbolinks 5.0 and Facebook SDKTurbolinks 5.0 和 Facebook SDK
【发布时间】:2023-08-17 04:08:01
【问题描述】:

上周我升级到使用 Turbolinks 5.0 的 Rails 5。我使用以下脚本通过 Turbolinks 3.0 加载 Facebook like 按钮:

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

在 Turbolinks 5.0 中,点赞按钮只会在页面重新加载时显示。当我不重新加载页面而只是单击链接时,我收到此错误:

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.

有谁知道如何解决这个问题?

【问题讨论】:

    标签: javascript ruby-on-rails facebook turbolinks


    【解决方案1】:

    这是一种将 Turbolinks 5 与 Facebook SDK 集成的方法。

    在您的布局模板中:

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

    然后在你的 javascript 中使用 jQuery:

    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();
    });
    

    然后使用任何使用 data-turbolinks-no-cache 属性的 Facebook 插件,如下所示:

    <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>
    

    这里是gist,这里是blog post,解释它是如何工作的

    【讨论】:

      【解决方案2】:

      如果您更喜欢使用原生 Turbolinks 5 事件,可以将此脚本添加到您的 Rails 资产中:

      // 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));
      

      发件人:https://gist.github.com/6temes/52648dc6b3adbbf05da3942794b97a00

      【讨论】:

      • 很好的解决方案!
      【解决方案3】:

      这是因为某些事件在Turbolinks 5 中重命名,并且与Turbolinks 3 不兼容。我的建议是尝试在 javascripts/ 文件夹下创建一个名为 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")
      

      【讨论】:

      • 我不需要整个脚本,因为翻译事件就足够了。谢谢!