foundation/foundation-sites

Foundation 5 topbar incompatible with Rails Turbolinks

DanielKehoe opened this issue · 4 comments

I've built a simple Rails application that includes a Foundation 5 topbar. Here are the relevant files, in an implementation that works:

# app/assets/javascripts/application.js
//= require jquery
//= require jquery_ujs
//= require foundation
//= require_tree .
$(function() {
  $(document).foundation();
});
# app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Test</title>
    <%= stylesheet_link_tag "application", media: "all" %>
    <%# Modernizr is required for Zurb Foundation %>
    <%= javascript_include_tag "vendor/modernizr" %>
    <%= csrf_meta_tags %>
  </head>
  <body>
    <header>
      <%# navigation styled for Zurb Foundation 5 %>
      <nav class="top-bar" data-topbar>
        <ul class="title-area">
          <li class="name"><%= link_to 'Home', root_path %></li>
          <li class="toggle-topbar menu-icon"><a href="#"><span>Menu</span></a></li>
        </ul>
        <div class="top-bar-section">
          <ul>
            <li><%= link_to 'About', root_path %></li>
            <li><%= link_to 'Contact', root_path %></li>
          </ul>
        </div>
      </nav>
    </header>
    <main role="main">
       <%= yield %>
    </main>
    <%= javascript_include_tag "application" %>
  </body>
</html>

If I add Rails Turbolinks, the implementation fails.

Many Rails developers will attempt to use Turbolinks since Turbolinks is part of a standard Rails build. Turbolinks is part of a standard Rails build, with any new Rails application.

Here are the same files, with Turbolinks enabled:

//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require foundation
//= require_tree .
$(function() {
  $(document).foundation();
});
# app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%= content_for?(:title) ? yield(:title) : "Learn Rails" %></title>
    <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
    <%# Modernizr is required for Zurb Foundation %>
    <%= javascript_include_tag "vendor/modernizr" %>
    <%= csrf_meta_tags %>
  </head>
  <body>
    <header>
      <%# navigation styled for Zurb Foundation 5 %>
      <nav class="top-bar" data-topbar>
        <ul class="title-area">
          <li class="name"><%= link_to 'Home', root_path %></li>
          <li class="toggle-topbar menu-icon"><a href="#"><span>Menu</span></a></li>
        </ul>
        <div class="top-bar-section">
          <ul>
            <li><%= link_to 'About', root_path %></li>
            <li><%= link_to 'Contact', root_path %></li>
          </ul>
        </div>
      </nav>
    </header>
    <main role="main">
       <%= yield %>
    </main>
    <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  </body>
</html>

The JavaScript console shows an error:

Uncaught TypeError: Cannot read property 'scrolltop' of undefined foundation.topbar.js?body=1:93

+1 this sucks.

Specifically this won't work because you must include the foundation.js in the BODY tag. With turbolinks JS has to be included in HEAD, as the body gets wiped on each request — as noted in Issue #3643

fny commented

There's a pretty simple fix: /pull/3668

You just need to (re)move FastClick or wrap Foundation in a closure and load when the DOM is ready.

I've written a more detailed explanation in a comment of a related issue.

Thanks for the assist, @fny! I've attached a pull request to #3643 as an alternative to #3668 which still uses FastClick but waits to hook it up until document.ready. I'll close this issue in favor of #3643.

What solved for me was to include "jquery.turbolinks" and bind the initialization to the jquery document ready