Keenan Payne
Keenan Payne

Reputation: 816

Create dropdown navigation on hover and on click

I have a dropdown menu that I have created using CSS and jQuery that I am trying to make dropdown either on on hover and on click.

By default I want the dropdown to be displayed on click, but given the class .dropdown-hover I want it to be displayed when hovered over.

Here is a JSFiddle of what I currently have: http://jsfiddle.net/dR8hL/1/

Right now, no matter what class is applied to the dropdown it is displayed on hover and I am unsure of how to fix that.

HTML

<div class="dropdown dropdown-hover">Dropdown on hover                
    <ul class="dropdown-menu">
        <li><a href="#">Profile</a></li>
        <li><a href="#">Settings</a></li>
        <li><a href="#">Log out</a></li>
    </ul>
</div>

<div class="dropdown">Dropdown on click                
    <ul class="dropdown-menu">
        <li><a href="#">Profile</a></li>
        <li><a href="#">Settings</a></li>
        <li><a href="#">Log out</a></li>
    </ul>
</div>

CSS

.dropdown {
    cursor: pointer;
    outline: none;
    position: relative;
    width: auto;
}

.dropdown .dropdown-menu {
    background-color: #fff;
    border: 1px solid #eee;
    border-radius: inherit;
    font-weight: inherit;
    left: 0;
    margin-left: 0px;
    opacity: 0;
    pointer-events: none;
    position: absolute;
    right: 0;
    text-transform: none;
    width: 200px;
    z-index: 99999;

    -webkit-transition: all 0.3s ease-in;
    -moz-transition: all 0.3s ease-in;
    -ms-transition: all 0.3s ease-in;
    -o-transition: all 0.3s ease-in;
    transition: all 0.3s ease-in;
}

.dropdown .dropdown-menu a { text-decoration: none; }

.dropdown .dropdown-menu p { 
    margin: 0; 
    padding: 10px 15px; 
}

.dropdown .dropdown-menu span { line-height: inherit; }

.dropdown ul.dropdown-menu { list-style-type: none; }

.dropdown .dropdown-menu li {
    display: block;
    padding: 5px 10px;
}

.dropdown .dropdown-menu li:hover { background-color: #f3f8f8; }

.dropdown.dropdown-active .dropdown-menu {
    opacity: 1;
    pointer-events: auto;
}

jQuery

function DropDown(el) {
    this.dd = el;
    this.initEvents();
}

DropDown.prototype = {
    initEvents: function () {
        var obj = this;

        // Determine if dropdown is on hover or on click
        if ($(".dropdown").hasClass("dropdown-hover")) {
            // Toggle .dropdown-active on hover
            $(".dropdown").mouseenter(function (event) {
                $(this).addClass("dropdown-active");
                event.stopPropagation();
            });

            $(".dropdown-menu").mouseleave(function () {
                $(".dropdown").removeClass("dropdown-active");
            });
        } else {
            // Toggle .dropdown-active on click
            obj.dd.on('click', function (event) {
                $(this).toggleClass('dropdown-active');
                event.stopPropagation();
            });
        }
    }
}

$(function () {
    var dd = new DropDown($('.dropdown'));

    $(document).click(function () {

        // Remove class from all dropdowns
        $('.dropdown').removeClass('dropdown-active');
    });
});

Upvotes: 1

Views: 5426

Answers (2)

Nitish Dhar
Nitish Dhar

Reputation: 2312

You can implement this via simple CSS & little bit of JS -

WORKING DEMO - http://codepen.io/nitishdhar/pen/rpqct

HTML Snippet to Use

<ul class="drop">
  <li>Dropdown on Hover
    <ul>
      <li>Profile</li>
      <li>Settings</li>
      <li>Log out</li>
    </ul>
  </li>
</ul>

<ul class="drop-on-click">
  <li>Dropdown on Click
    <ul>
      <li>Profile</li>
      <li>Settings</li>
      <li>Log out</li>
    </ul>
  </li>
</ul>

You need to assign the class 'drop' to the menu that should open on hover. Also, assign just the class 'drop-on-click' to the one that you want to open on click.

Important CSS

ul li ul {
  padding: 0;
  position: absolute;
  top: 48px;
  left: 0;
  width: 150px;
  display: none;
  opacity: 0;
  visibility: hidden;
}
ul.drop li:hover ul {
  display: block;
  opacity: 1;
  visibility: visible;
}

There is more CSS in the demo link but that mostly handles the UI aspects.

Now the JS that handles the click scenario -

$(document).ready(function() {
   $('.drop-on-click').click(function(){
     $(this).toggleClass('drop');
   });

   $('.drop-on-click ul li').hover(
     function() {
        $('.drop-on-click').addClass('drop');
      }, function() {
        $('.drop-on-click').removeClass('drop');
      }
    );
});

So basically the JS is adding the already handled class 'drop' that will give the menu the property to dropdown as per the written CSS. Now when we move over the dropped down menu, we need to retain the drop class until we are over the li elements, once we move out, we remove the class.

Upvotes: 1

LifeOnLars
LifeOnLars

Reputation: 398

Could you not just target the .dropdown-hover class. You shouldn't need the if statement

        $(".dropdown-hover").mouseenter(function (event) {
            event.stopPropagation();
            $(this).addClass("dropdown-active");                
        });
        $(".dropdown-hover").mouseleave(function () {
            $(".dropdown").removeClass("dropdown-active");
        });

        // Toggle .dropdown-active on click
        obj.dd.on('click', function (event) {
            event.stopPropagation();
            $(this).toggleClass('dropdown-active');                
        });

Updated JSFiddle http://jsfiddle.net/47mSS/

Upvotes: 3

Related Questions