ThomasNL
ThomasNL

Reputation: 359

How to turn off animation when hovering for the first time with this "sliding animation on menu hover with jQuery" Fiddle?

I found this awesome sliding animation on menu hover using jQuery, but i was wondering how i could make it so that when hovering for the first time it does not animate the left and width property but immediately jumps to the hovered item. After that, it does animate the background's position. Only when re-entering it again it will stop animating the first time.

// insert slider
$('ul').append('<div id="slider"></div>');

// initially reset
var left = $('ul li:first-child a').parent().position().left;
var width = $('ul li:first-child a').width();
$('#slider').css({'left' : left, 'width' : width});

// sliding
$('ul li a').hover(function(){

    var left = $(this).parent().position().left;
    var width = $(this).width();

    $('#slider').stop().animate({
        'left' : left,
        'width' : width
    });
});

Hope i explained this well enough...

Thanks in advance!

Here is the fiddle: http://jsfiddle.net/5wPQa/2/

Upvotes: 0

Views: 216

Answers (3)

nimsrules
nimsrules

Reputation: 2064

Although this approach is a lot similar to 04FS's answer, I'll recommend you to go ahead with their solution as it dissolves redundant code.

$(document).ready(function() {
  $('ul li a').hover(function() {
    var a = $(this);
    var left = a.parent().position().left;
    var width = a.width();
    var nav = a.parent().parent('ul');

    if (!nav.find('#slider').length) {
      nav.append('<div id="slider"></div>');
    }

    if (!nav.hasClass('animated')) {
      $('#slider').css({
        'left': left,
        'width': width
      });

      nav.addClass('animated');
    } else {
      $('#slider').stop().animate({
        'left': left,
        'width': width
      });
    }
  })
});
ul {
  position: relative;
  margin: 20px;
}

ul li {
  display: inline-block;
}

ul li a {
  padding: 5px 15px;
  border: 1px solid #000;
  color: #000;
  text-decoration: none;
}

#slider {
  position: absolute;
  top: -5px;
  left: 0;
  height: 100%;
  width: 0;
  padding: 5px 15px;
  margin-left: 1px;
  background-color: #f00;
  z-index: -1;
}
<script src="https://code.jquery.com/jquery.min.js"></script>
<ul>
  <li><a href="#">Link 1</a></li>
  <li><a href="#">Link number 2</a></li>
  <li><a href="#">Link 3</a></li>
  <li><a href="#">Link something 4</a></li>
  <li><a href="#">Link 5</a></li>
</ul>

Upvotes: 1

04FS
04FS

Reputation: 5820

I’m assuming that you don’t want the first link to be highlighted by default then either? Then the // initially reset part can be removed.

Let’s store the reference to the ul element in $ul, because we’re gonna need access to that element inside the link hover handler as well, and we don’t want to look it up in there every time using .parents() or something like that.

Let’s add a class to the ul right away, no-animation. That is going to be used for two things, to hide the slider-div initially (via the stylesheet), and to determine whether or not we want to animate when the links get hovered.

Having the slider “jump” to a position instantly, instead of animating, can be done by simply calling .css() instead of .animate() - the rest of the code stays the same, so rather than repeating it, I’m gonna store the name of the method to execute in a variable, method.

Now when the links get hovered, we check if the parent ul has that class no-animation first. If so, we remove that class, and set the method to css instead of animate.

$('#slider').stop()[method]() then calls .css() or .animate(), depending on what method contains.

And to reset the effect we simply add the class again, when the ul itself gets un-hovered. That hides the slider-div again (due to rule in the stylesheet), and helps us determine that this is a “first hover” again next time.

// insert slider
var $ul = $('ul');
$ul.addClass('no-animation').append('<div id="slider"></div>');

$ul.on('mouseleave', function() {
  $(this).addClass('no-animation')
});

// sliding
$('ul li a').hover(function() {
  var left = $(this).parent().position().left;
  var width = $(this).width();
  var method = 'animate';

  if ($ul.hasClass('no-animation')) {
    $ul.removeClass('no-animation');
    method = 'css';
  } 
  $('#slider').stop()[method]({
    'left': left,
    'width': width
  });
});
ul {
  position: relative;
  margin: 50px;
}

ul.no-animation #slider {
  display: none;
}

ul li {
  display: inline-block;
}

ul li a {
  padding: 5px 15px;
  border: 1px solid #000;
  color: #000;
  text-decoration: none;
}

#slider {
  position: absolute;
  top: -5px;
  left: 0;
  height: 100%;
  width: 0;
  padding: 5px 15px;
  margin-left: 1px;
  background-color: #f00;
  z-index: -1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<ul>
  <li><a href="#">Link 1</a></li>
  <li><a href="#">Link number 2</a></li>
  <li><a href="#">Link 3</a></li>
  <li><a href="#">Link something 4</a></li>
  <li><a href="#">Link 5</a></li>
</ul>

Upvotes: 3

Rachel Gallen
Rachel Gallen

Reputation: 28573

If I understand you correctly, and you want for the 'currently-selected' link to be highlighted on opening the page, you could add a "selected" class to your li and adjust the jquery slightly, to replace the "first-child" with your "selected" class. This would still work to slide to the other nav items, but would highlight your desired link first. (note: I first tried this with ":active" but it wasn't as successful)

See snippet (best viewed in "full screen" mode)

$('ul').append('<div id="slider"></div>');

// initially reset
var left = $('ul li.selected a').parent().position().left;
var width = $('ul li.selected a').width();
$('#slider').css({'left' : left, 'width' : width});

// sliding
$('ul li a').hover(function(){
   
    var left = $(this).parent().position().left;
    var width = $(this).width();
    
    $('#slider').stop().animate({
        'left' : left,
        'width' : width
    });
});
ul {
    position:relative;
    margin: 50px;
}

ul li {
    display: inline-block;
}

ul li a {
    padding: 5px 15px;
    border: 1px solid #000;
    color: #000;
    text-decoration: none;
}

#slider {
    position:absolute;
    top: -5px;
    left: 0;
    height: 100%;
    width: 0;
    padding: 5px 15px;
    margin-left: 1px;
    background-color: #f00;
    z-index:-1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<ul>
    <li><a href="#">Link 1</a></li>
    <li><a href="#">Link number 2</a></li>
    <li class="selected"><a href="#">Link 3</a></li>
    <li><a href="#">Link something 4</a></li>
    <li><a href="#">Link 5</a></li>
</ul>

Edit: To remove the 'hover' but keep the sliding effect, change the 'hover' to 'click' in the jquery.

$('ul li a').click(function(){...

Hope this helps

Upvotes: 0

Related Questions