How Do I Make Facebook Comments Load with Turbolinks?

I installed Facebook’s Comments plug-in on my site and found that it worked immediately except for one problem. To get it to show on a page, the page had to be reloaded because of Turbolinks. I was able to fix this using Coffeescript with the help of this Stack Overflow post.

Here’s I fixed it:

(1) Created a new file assets/javascripts/fb_turbolinks_fix.js.coffee (replace the values in italics based on the Connect URL Facebook provides you in its code):

$ ->
loadFacebookSDK()
bindFacebookEvents() unless window.fbEventsBound

bindFacebookEvents = ->
$(document)
.on(‘page:fetch’, saveFacebookRoot)
.on(‘page:change’, restoreFacebookRoot)
.on(‘page:load’, ->
FB.XFBML.parse()
)
@fbEventsBound = true

saveFacebookRoot = ->
if $(‘#fb-root’).length
@fbRoot = $(‘#fb-root’).detach()

restoreFacebookRoot = ->
if @fbRoot?
if $(‘#fb-root’).length
$(‘#fb-root’).replaceWith @fbRoot
else
$(‘body’).append @fbRoot

loadFacebookSDK = ->
window.fbAsyncInit = initializeFacebookSDK
$.getScript(“//connect.facebook.net/en_US/sdk.js”)

initializeFacebookSDK = ->
FB.init
appId : # put your app ID
autoLogAppEvents : true
xfbml : true
version: ‘v5.0’

(2) In application.js make sure to include the file (before Turbolinks):

//= require fb_turbolinks_fix

(3) In your view, include this:

<div id="fb-root"></div>
<div class="fb-comments" data-href="https://developers.facebook.com/docs/plugins/comments#configurator" data-width="" data-numposts="5"></div>

Twitter Bootstrap Growls for Rails Flash Messages

I’m using Bootstrap with Rails, but I wanted to replace their alerts with growl messages.  Luckily, I found this JS made by Robert McIntosh.  Bootstrap-notify makes it so easy to turn your flash messages into growl messages.

  1. Download the JS https://github.com/mouse0270/bootstrap-notify
  2. Unzip the JS and place bootstrap-notify.min.js in your assets/javascripts folder
  3. Add this line to application.js: //= require bootstrap-notify.min
  4. Download Animate.css and put in your assets/stylesheets folder (add it to application.css, if you aren’t adding the CSS tree)
  5. Create a flash partial (layouts/_flash.html.erb) – change the options to customize:

<% flash.each do |type, message| %>

$.notify({
// options
message: ”
},{
// settings
type: ”,
placement: {
align: “center”
},
animate: {
enter: ‘animated bounce’,
exit: ‘animated bounce’
}
});

<% end %>

6. Put this in application_helper.rb:

def bootstrap_class_for(flash_type)
case flash_type
when “success”
“success” # Green
when “error”
“danger” # Red
when “alert”
“warning” # Yellow
when “notice”
“info” # Blue
else
flash_type.to_s
end
end

7.  Render the partial by adding this to “layouts/application.html.erb”:

<%= render “layouts/flash” %>

You should be all set!

Triggering jQuery on Page Load

I had some jQuery on a page that changes with a change to a field in a form, like so:

<%= tax.select(:state , Order::STATES ,{:prompt => ‘Select State’}, :id => “state”,:onchange => “render_sales_tax()”) %>

The issue was that when a user received an error with the form and the user populated the field again (ie :state), then when the view was rendered again (ie format.html { render :action=>”new” }  ), the  jQuery would not be triggered again because the field was already populated when rendered again (so no onChange event).

To fix this, I had to add this line above the jQuery function in the <script> section of the page:

window.onload = render_sales_tax();

This way the jQuery triggered and then onChange it would update again (if necessary).

Loading Javascript After Page Load

If the script loads too early and it’s looking for elements on a page, it can generate an error sometimes. To correct that, you can add lines to your script to load after the page is done loading (so it can find the required elements).

If it’s just javascript, you can add:
function afterLoad(){
};

like so:

function afterLoad(){
$(“.alert-message”).alert(‘close’);
};

If you’re using jQuery, you can add (with your script between the brackets):
jQuery(document).ready(function($) {
});