Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bootstrap Dropdowns working Intermittently with Rails 4

I'm working on a Rails application with a persistent navigation bar including bootstrap dropdowns. For whatever reason it's working sporadically; on launch or refresh the dropdowns will always work, after the first redirect they will never work, and after that it seems to essentially alternate between working and not working. When it doesn't work, simply nothing happens when the dropdown is clicked. My initial suspicion was that Turbolinks was to blame, but I haven't and I have been able to verify this (see edit below). After spending a few hours reading up, I've tried all the "obvious" fixes I could find, with no luck as of yet.

It is worth noting that the problem persists...

  • with or without turbolinks.jquery
  • with bootstrap OR bootstrap-sprockets
  • across all recent version of the bootstrap-sass gem
  • whether or not a rearrange my application.js file
  • with application.js data-turbolinks-track set to true OR false
  • whether in development OR production

EDITED:

By disabling Turbolinks completely (removing the turboling and jquery-turbolinks gems, removing references to them both in application.js, and removing the data-turbolinks-track attributes in application.html.erb), I no have working dropdowns. That said, I would still like to know why this is not working, as I am hoping to re-enable turbolinks prior to release. /end-of-edit

These are the files I believe to be relevant:

application.js

Note that //= require tree . is not present. This is deliberate (I have a number of page-specific javascripts, and I include them with yields into the application.html.erb).

//= require jquery
//= require jquery_ujs
//= require jquery.turbolinks
//= require turbolinks
//= require bootstrap-sprockets

Gemfile.rb

source 'https://rubygems.org'


# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.0'

# Bootstrap
gem 'bootstrap-sass', '3.3.4.1'
gem 'autoprefixer-rails'

# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'

# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'

# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.1.0'

# Use jquery as the JavaScript library
gem 'jquery-rails'

# Make Turbolinks play nice with JQuery
gem 'jquery-turbolinks'

# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'

# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'

# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc

# Gems for interfacing with SQL Server
gem 'tiny_tds'
gem 'activerecord-sqlserver-adapter'

# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'


group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug'

  # Access an IRB console on exception pages or by using <%= console %> in views
  gem 'web-console', '~> 2.0'

  # Test DB
  gem 'sqlite3'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

application.css.scss

(just to prove that I included the other parts of bootstrap effectively)

/* CHARSET
-------------------------------------------------- */
@charset "utf-8";


/* IMPORTS - BOOTSTRAP
-------------------------------------------------- */
@import "bootstrap-sprockets";
@import "bootstrap";


/* IMPORTS - SCSS MIXINS
-------------------------------------------------- */
@import "mixins/*";


/* IMPORTS - LAYOUT CSS
-------------------------------------------------- */
@import "layout";


/* IMPORTS - CONTROLLERS' CSS
-------------------------------------------------- */
@import "controllers/*";

application.html.erb

Note that there are two different possible navigation bars (one when logged in, the other when logged out) that render from partials. Only the _nav_logged_in.html.erb contains drop downs, and I'll include that next.

Also note that all javascript loads are at the bottom of the file.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="This is APO Lite in the context of Ruby on Rails">
    <meta name="author" content="Connor McKee">
    <title>APO Lite</title>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
    <%= csrf_meta_tags %>

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!--[if lt IE 9]>
        <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
        <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
</head>

<body role="document">

<!-- Fixed navbar -->
<nav class="navbar navbar-inverse navbar-fixed-top">
    <div class="container">
        <div class="navbar-header">
            <%= link_to "APO Lite", root_url, id: "navLogo", class: "navbar-brand" %>
        </div>


        <% if logged_in? %>
            <%= render 'layouts/nav_logged_in' %>
        <% else %>
            <%= render 'layouts/nav_logged_out' %>
        <% end %>

        <!--/.nav-collapse --> 
    </div>
</nav>

<header class="jumbotron subhead <%= 'expandedJumbotron' if current_page? root_url %>" id="overview">
  <div class="container">
    <% if has_project? && !current_page?( root_url ) %>
        <h1><%= current_project.name %></h1>
        <p class="lead"><%= current_project.description %></p>
    <% else %>
        <h1>WELCOME TO APO LITE</h1>
        <p class="lead">Your Journey towards a Better Project Management Experience Starts Here</p>
    <% end %>
  </div>
</header>

<div class="container">

    <!-- Page Description a.k.a. "Context" -->
    <% if content_for?(:context) %>
        <div class="row" id="context">
            <div class="col-md-12">
                <%= yield :context %>
            </div>
        </div>
    <% end %>

    <!-- Page Content -->
    <%= yield %>

    <!-- This is debug info -->
    <% if Rails.env.development? %>
        <div class="row">
            <div class="col-md-12">
                <%= debug(params) %>
            </div>
        </div>
    <% end %>

</div>


<!-- Javascripts -->
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<% if content_for?(:page_js) %>
    <%= yield :page_js %>
<% end %>

</body>
</html>

_nav_logged_in.html.erb

At last, here are the dropdowns themselves.

<div id="navbar" class="navbar-collapse collapse">
    <ul class="nav navbar-nav">
        <li>
            <% if has_project? %>
                <%= link_to current_project.name, current_project %>
            <% else %>
                <a href="#about">My Project Name</a>
            <% end %>
        </li>
        <li class="dropdown">
            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Administer<span class="caret"></span></a><!--class="active"-->
            <ul class="dropdown-menu" role="menu">
                <li><a href="#">Questionnaires</a></li>
                <li><a href="#">Reports</a></li>
            </ul>
        </li>
        <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Support<span class="caret"></span></a><!--class="active"-->
            <ul class="dropdown-menu" role="menu">
                <li><a href="#">Documentation</a></li>
                <li><a href="#">Help Desk</a></li>
            </ul>
        </li>
    </ul>
    <ul class="nav navbar-nav navbar-right">
        <li><%= link_to "Log out", logout_path, method: "delete" %></li>
        <li class="dropdown">
            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><%= current_user.first_name %><span class="caret"></span></a><!--class="active"-->
            <ul class="dropdown-menu" role="menu">
                <li><%= link_to "My Profile", current_user %></li>
                <li><%= link_to "Log out", logout_path, method: "delete" %></li>
            </ul>
        </li>
    </ul>

</div>

And finally, here is how the scripts are loaded when the application is running

This is with bootstrap-sprockets, but bootstrap by itself causes the same problems. Please observe the lack of duplication anywhere.

<!-- Javascripts -->
<script src="/assets/jquery.self-d03a5518f45df77341bdbe6201ba3bfa547ebba8ed64f0ea56bfa5f96ea7c074.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/jquery_ujs.self-8e98a7a072a6cee1372d19fff9ff3e6aa1e39a37d89d6f06861637d061113ee7.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/jquery.turbolinks.self-176b9819f30444d441e820bbccd3264fe57753aeafd54dec732b0dbc77129a2a.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/turbolinks.self-c37727e9bd6b2735da5c311aa83fead54ed0be6cc8bd9a65309e9c5abe2cbfff.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/bootstrap/affix.self-68d1a5161d04ca9fe1b9d9f4114d9426c7798bf90f2703a97aca35c8113469bb.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/bootstrap/alert.self-15ce09eba576e56db3edfd87accc0ff48823df915169e350b4fd97290f96aee1.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/bootstrap/button.self-37c62bff1d75f86f3348b8679873d5156d8b9938b62841038dca21690f4740f1.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/bootstrap/carousel.self-9aaab1a477b9c1156bab751cb8da47f77dace6da88eef8ae830e60f3cff3a8be.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/bootstrap/collapse.self-eeece00cd06a3d7cc071ab7845b549d4991edd0f0895e4be70fe40bac2fb5f4b.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/bootstrap/dropdown.self-a3998e7ca949c04cb86b5c635deb0abcc7a24dc02e81be66b8acfef02d811e45.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/bootstrap/modal.self-f2759e138605770e60526c00c6d86cbb3378da203641f9d6b204c9f0192b9267.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/bootstrap/scrollspy.self-5ea180afe4404f83fc97d997833f2edefd34475b0b5ddab310e27abc2bbd5f2f.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/bootstrap/tab.self-e1bba7115c90301056ee94c4716de2fcbe4498015def2dab9ff9879f339bd245.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/bootstrap/transition.self-7742dca5e6acf313fbb217811b48468282cddf1a9baea5c89ec92e367ef242cb.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/bootstrap/tooltip.self-c3b5c16f394ab9c0391db4431aac4f2d2ddf1bba4c5d3228ed343de05ecc8e83.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/bootstrap/popover.self-2674d99c3ab0415dba0b958a80b3840f70ff6368b155d890306c0291be49453b.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/bootstrap-sprockets.self-fbfa5ad7d9aa0afe439ec4ff3883acc4cb92b62cb67c40d674320c9aa1d4642d.js?body=1" data-turbolinks-track="false"></script>
<script src="/assets/application.self-f98a0dd27ad1c55b2b9cfe97296d4887e5d4a4535b3bbbf9130c1050771738b2.js?body=1" data-turbolinks-track="false"></script>
like image 627
ConnorCMcKee Avatar asked Nov 10 '22 14:11

ConnorCMcKee


1 Answers

I'm pretty sure that jquery.turbolinks must be loaded before jquery_ujs.

Try this in your application.js file:

//= require jquery
//= require jquery.turbolinks
//= require jquery_ujs
//= require bootstrap
//= require turbolinks
//= require_tree .

Revision | removed extraneous load logs

Revision | added

I don't think you should have a container div in the middle of your nav block. You might want to try copy / paste just this simple example structure (from a working app).

<ul class="nav navbar-nav  pull-right">

      <li class="dropdown">
        <a href="#" class="dropdown-toggle" data-toggle="dropdown">
          Dropdown <b class="caret"></b>
        </a>
        <ul class="dropdown-menu">
            <li><%= link_to "A", some_working_url %></li>
            <li><%= link_to "A", some_working_url %></li>
            <li><%= link_to "A", some_working_url %></li>

        </ul>
      </li>
    </li>
     ...
   </ul>
like image 117
Elvn Avatar answered Nov 14 '22 22:11

Elvn