Question

I had this jquery function to do a slideDown effect on dropdowns:

jQuery(window).ready(function(){

    jQuery('.menu li').hover(function(){
         jQuery(this).children('ul').delay(20).slideDown(200);
}, 
function(){
         jQuery(this).children('ul').delay(20).slideUp(200);
    });

});

I realized it was annoying dropping every time one hovered, so I wanted to add a timeout function but got stuck. I could no longer use "this", I guess because of scope. Now I have the below function, but it drops both the .menu li ul, and .menu li ul ul.... how would I get around to using "this" again, or making sure only the child of the hovered element is dropped down? thanks!

jQuery(window).ready(function(){

var timeoutId;
jQuery('.menu li').hover(function() {
    if (!timeoutId) {
        timeoutId = window.setTimeout(function() {
            timeoutId = null;
            jQuery('.menu li').children('ul').delay(20).slideDown(200);
       }, 500);
    }
},

function () {
    if (timeoutId) {
        window.clearTimeout(timeoutId);
        timeoutId = null;
    }
    else {
       jQuery(this).children('ul').delay(20).slideUp(200);
    }
});

});

Also, my CSS is below:

#mainMenu { /*don't change width or height here. use #menurow in template.css*/
  float: right;
  width: 100%;
}

.menu
{
  margin:0;
  padding:0;
}

.menu ul{
  list-style: none;
  margin: 0;
  padding: 0; 
}

.menu > li
{
  list-style:none;
  float:left;
  margin:0;
  padding:0;
  position:relative;
  text-align: left;
  line-height: 37px;
  font-size: 13px;
}

.menu > li ul
{
  margin:0;
  padding:0;
  width:190px;
  position:absolute;
  display:none;
  background: #666666;
  z-index: 999;
}
.menu > li ul ul
{
  margin:0;
  padding:0;
  width:190px;
  position:absolute;
  display:none;
  left:190px;
  top:0;
  z-index: 999;
}
.menu > li ul li
{
  margin:0;
  padding:0;
  list-style:none;
  position:relative;
}

.menu a {
  display: block;
  font-weight: bold;
  text-decoration: none;
  color: #fff;
  margin: 0;
  padding-left: 30px;
  padding-right: 30px;
}

.menu li.active a {
  background: #454545;
}

.menu a:hover{
 color: #FBF4B6;
 background: #333;
}

.menu li ul li a {
  padding-left: 30px;
  padding-bottom:2px;
  padding-top:2px;
  border-bottom: 1px solid #999;
}

.menu li.active ul li a:hover {
  background: #333;
}
Was it helpful?

Solution

You can use bind to reuse this:

timeoutId = window.setTimeout(function() {
    timeoutId = null;
    jQuery(this).children('ul').delay(20).slideDown(200);
}.bind(this), 500);

Alternatively, you can save the this reference into a variable outside the scope :

if (!timeoutId) {
    var $this = $(this);
    timeoutId = window.setTimeout(function() {
        timeoutId = null;
        $this.children('ul').delay(20).slideDown(200);
   }, 500);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top