Drupal Bootstrap: Navbar drowpdown on hover with fade in transition

I needed to alter the Bootstrap navbar so that the dropdown would appear on mouse hover - Out of the box, it only appears when clicking the link.

Solution One

We need to override bootstrap_menu_link() in our template.php file by commenting out the lines that adds the classes 'dropdown-toggle' and 'dropdown'.

<?php
/**
 * Overrides theme_menu_link().
 */
function THEMENAME_menu_link(array $variables) {
 
$element = $variables['element'];
 
$sub_menu = '';

  if (
$element['#below']) {
   
// Prevent dropdown functions from being added to management menu so it
    // does not affect the navbar module.
   
if (($element['#original_link']['menu_name'] == 'management') && (module_exists('navbar'))) {
     
$sub_menu = drupal_render($element['#below']);
    }
    elseif ((!empty(
$element['#original_link']['depth'])) && ($element['#original_link']['depth'] == 1)) {
     
// Add our own wrapper.
     
unset($element['#below']['#theme_wrappers']);
     
$sub_menu = '<ul class="dropdown-menu">' . drupal_render($element['#below']) . '</ul>';
     
// Generate as standard dropdown.
     
$element['#title'] .= ' <span class="caret"></span>';
     
$element['#attributes']['class'][] = 'dropdown';
     
$element['#localized_options']['html'] = TRUE;

     
// Set dropdown trigger element to # to prevent inadvertant page loading
      // when a submenu link is clicked.
      //$element['#localized_options']['attributes']['data-target'] = '#';
      //$element['#localized_options']['attributes']['class'][] = 'dropdown-toggle';
      //$element['#localized_options']['attributes']['data-toggle'] = 'dropdown';
   
}
  }
 
// On primary navigation menu, class 'active' is not set on active menu item.
  // @see https://drupal.org/node/1896674
 
if (($element['#href'] == $_GET['q'] || ($element['#href'] == '<front>' && drupal_is_front_page())) && (empty($element['#localized_options']['language']))) {
   
$element['#attributes']['class'][] = 'active';
  }
 
$output = l($element['#title'], $element['#href'], $element['#localized_options']);
  return
'<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
?>

Now we need to make the dropdown appear on hover. We can do this by adding the below in our CSS file. Note we are using media query because we don't want this to be included for mobile devices.

@media (min-width: 768px) {
  ul.nav li.dropdown &gt; ul.dropdown-menu {
    display:block;
    visibility:hidden;
    opacity:0;
    transition:visibility 0s linear 0.5s,opacity 0.5s linear;
  }

  ul.nav li.dropdown:hover &gt; ul.dropdown-menu {
    visibility:visible;
    opacity:1;
    transition-delay:0s;
  }
}
Solution Two

This is my preferred way because unlike the above solution the sub menu drops down on mobile devices. The parent link only clicks through when the dropdown is visible. Instead of overriding theme functions like in the first solution, we just need to add the below into a Javascript file.

(function ($) {

Drupal.behaviors.THEMENAME = {
  attach: function (context, settings) {
    if (context == document) {
      $('.dropdown-toggle').click(function() {
        var mq = window.matchMedia('(min-width: 768px)');
        var location = $(this).attr('href');
        if (mq.matches) {
          window.location.href = location;
          return false;
        }
        else {
          if ($(this).next().is(':visible')) {
            window.location.href = location;
            return false;
          }
        }
      });
    }
  }
};

})(jQuery);

Use the same CSS as the first solution

@media (min-width: 768px) {
  ul.nav li.dropdown &gt; ul.dropdown-menu {
    display:block;
    visibility:hidden;
    opacity:0;
    transition:visibility 0s linear 0.5s,opacity 0.5s linear;
  }

  ul.nav li.dropdown:hover &gt; ul.dropdown-menu {
    visibility:visible;
    opacity:1;
    transition-delay:0s;
  }
}