Hello!
My problem is that Bootstrap's dropdown toggle menu has stopped working in the header of Confreaks.TV. I've built a lot of this project learning as I go, without a lot of familiarity with the tools I'm using. The asset pipeline has been particularly frustrating to me. Basically, everything is tangled and messy. I've learned a lot about it since starting the project, but I'm still stumbling around fairly blind. I can grant you access to the private bitbucket repo or provide more information if I haven't provided enough context for the problem here.
The Problem
To start, the dropdown toggle is used in the site's header:
- if user_signed_in?
%li.dropdown
= link_to '#', class: 'dropdown-toggle', 'data-toggle' => 'dropdown' do
= current_user.username
%i.fa.fa-angle-down
%ul.dropdown-menu
%li
...
The dropdown will not toggle with the application.js set up as follows:
//= require jquery
//= require jquery_ujs
//= require bootstrap
...
//= require_tree .
However, if I move
//=require bootstrap
to the top of the file (so that it's above //=require jquery), the dropdown works perfectly. But doing this raises an error in the browser console:
Uncaught Error: Bootstrap's JavaScript requires jQuery
I know that Bootstrap needs jQuery loaded first in order for many of its functions to work. At the moment, there's nothing else I can find on the site which is broken by this error. It's a cause for concern, though, and I'd rather deal with it now than later.
Some solutions I've tried
-
Removing duplicates of bootstrap.js
I read that you only need one copy of bootstrap.js in an application and accidentally including it multiple times in the form of bootstrap.min.js and bootstrap.js can cause dropdown toggles to not work, so I initially removed bootstrap.js (leaving bootstrap.min.js) in application/vendor/template/etc. (where the code for our bootstrap template is located). This didn't solve the problem.
I use the gem 'rails-assets-bootstraps', built from http://rails-assets.org, which makes bootstrap available without including any of the files within the application (except for calling them where appropriate in application.js and application.css (or application.css.scss in my case)). So I thought if I removed all bootstrap.js files from the application (including bootstrap.min.js files), this would get rid of any duplication and fix the issue. So I removed bootstrap.min.js from the template directory as well. Once again, it doesn't break anything, but it doesn't fix the dropdown toggle.
-
Calling the dropdown via javascript in application.js
$('.dropdown-toggle').dropdown()
-
Clearing and precompiling the assets & restarting the server.
rake assets:clobber; rake assets:precompile rake assets:clean; rake assets:precompile
Note: rake assets:clobber, without precompiling the assets again, fixes the dropdown.
-
This Stack Overflow question includes the above suggested solutions & several others, all of which I have tried (where applicable) http://stackoverflow.com/questions/10218587/twitter-bootstrap-drop-down-suddenly-not-working
Solution?
rake assets:clobber
(clearing out public/assets) works, while the public/assets folder is gone, but when I run rake assets:precompile again it stops working. Due to previous struggles with Heroku and the asset pipeline, precompiling my assets is the only way to get the confreaks.tv to deploy currently… I think the long road to solving this problem involves getting to the bottom of that problem. I don't necessarily need that solved this second, though it's something I intend to look at in the future.
Having narrowed the problem down to how the assets are getting precompiled, I'm now feeling like I've been banging my head against a brick wall for way too long, trying to solve a problem that needs a more experienced eye than mine.
tl;dr My recommendation is to figure out why asset precompilation was failing on Heroku push and to stop committing your precompiled assets. That will probably resolve all the other issues. If you share access of the project with me I can take a stab at this for you.
Aside from that, I think I'm following along for the most part. Here's what I suspect (and if I'm not right I think I need to look at the project setup and play with it to debug):
vendor/assets/javascripts
orapp/assets/javascripts
, which you fixed by removing the duplicatespublic/assets
directory (and not to commit it). The risk is that I'll forget and I'll havepublic/assets/application-SOMEHASHSIGNATURE.js
present when I'm in development mode while also having sprockets in development mode. This may technically be supported, but it never works in practice and it will result in exactly the kind of situations you're describing.If you run
RAILS_ENV=production rails s
locally while your precompiled assets are present, does everything work? I suspect they will. However, that's really no way to work, since it means the local server won't pick up any changes you make to the javascript unless you stop everything and re-precompile.I tend not to use asset gems like
rails-boostrap
because it can obfuscate issues like this (whereas dropping files invendor/assets/javascripts
is obvious and straightforward).