2

I'm trying to integrate this cool sliding underline animation in my Wordpress navigation header (Storefront child theme, if that matters) but it's not functioning as it should (at all). You can see the original codepen here.

Below is my attempt at adapting the code for my site. The author's codepen example shows the animation on mouseclick but I want it to show on hover instead. And I only want the underline animation and do not care for the color-changing of the links, so I've tried removing the unnecessary parts.

I have enqueued my JS file in the Wordpress functions.php. I'm pretty sure it loads, I tested it by adding an alert to the .js that did pop up

When my code runs nothing happens. I'm having trouble debugging this because I'm sort of trapped in the Wordpress sandbox and very inexperienced with both WP and JS. There's a big chance I made a very elementary mistake somewhere in the .js, I might not be targeting the links correctly. Would also be thankful for any suggestions of clever ways to loop the links to point to their respective moveToIndex number!

jQuery(function() {
  var currentIndex = 1;

  // Always moving to same item, just to test
  $(".menu a").hover(function() {
    moveToIndex(2);
  });

  function moveToIndex(idx) {
    if (idx === currentIndex)
      return;

    var fromTab = $(".menu li:nth-child(" + currentIndex + ")"),
      toTab = $(".menu li:nth-child(" + idx + ")"),
      underlineborder = $(".underlineborder"),
      animationDuration = 150;

    var fromLeft = 0,
      fromRight = 0,
      toLeft = toTab.offset().left - toTab.parent().offset().left,
      toRight = toTab.offset().left + $(toTab).width();

    if (fromTab.length > 0) {
      fromLeft = fromTab.offset().left - fromTab.parent().offset().left;
      fromRight = fromLeft + fromTab.width();
    }

    $(".menu a").removeClass("active");
    toTab.addClass("active");

    underlineborder.animate({
      left: currentIndex < idx ? fromLeft : toLeft,
      width: currentIndex < idx ? toRight - fromLeft : fromRight - toLeft
    }, animationDuration).animate({
      left: toLeft,
      width: toTab.width()
    }, animationDuration);

    currentIndex = idx;
  }

  // initialize tabs
  moveToIndex(1);
});
.menu li {
  cursor: pointer;
  display: inline-block;
  margin: 5px 7px 10px 7px;
  opacity: .65;
  transition: .3s transform;
}

.menu li.active {
  cursor: default;
  opacity: 1;
  text-shadow: 0 0 4px rgba(0, 0, 0, .8);
  transform: translateY(-3px);
}

.underlineborder {
  background: red;
  border-radius: 5px;
  cursor: default;
  position: absolute;
  height: 3px;
  width: 10px;
  margin: 0;
  opacity: 1;
  bottom: 0;
  left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="primary-navigation">
  <ul id="menu-main-navigation" class="menu nav-menu">

    <li id="menu-item-428" class="main-nav-item-1 ...">
      <a href="https://link-1.com">Link-1</a></li>

    <li id="menu-item-344" class="main-nav-item-2 ...">
      <a href="https://link-2.com">Link-2</a></li>

    <li id="menu-item-228" class="main-nav-item-3 ...">
      <a href="https://link-3.com">Link-3</a></li>
  </ul>
</div>
halfer
  • 19,824
  • 17
  • 99
  • 186
noob
  • 328
  • 2
  • 13
  • 1
    You can see the error in the snippet. The problem is this line: `underline - border.animate(...`. What are you expecting `underline` to be, given that you don't declare the variable nor assign it a value – Rory McCrossan Jun 03 '19 at 15:05
  • `underline is not defined` – APAD1 Jun 03 '19 at 15:06
  • My .js says `underline-border` as I had defined it (I changed it from the author's `underline` so that it wouldn't potentially conflict with something else in WP. I don't know how those spaces got in my post, I'll edit and fix it – noob Jun 03 '19 at 15:09
  • 1
    The code is a direct copy and paste of what was originally in your question. It's just not valid javascript syntax – Rory McCrossan Jun 03 '19 at 15:18
  • OH I see, I changed the code to declare it properly (at least I think I have), but it still doesn't work. I'll edit the code in my original post to reflect that – noob Jun 03 '19 at 15:29

1 Answers1

1

You were missing one border li (<li class="underline-border"></li>). You already have a style for that. So I have added the li. Apart from that, I have made hover function dynamic so whichever li is hovered gets border. You were always passing 2 instead of hovered index.

$(".nav-menu a").hover(function() {
    var index = $(".menu").children().index($(this).parent());
    moveToIndex(index+1);
});

See the Snippet below:

jQuery(function() {
  var currentIndex = 0;

  // Always moving to same item, just to test
  $(".nav-menu a").hover(function() {
    var index = $(".menu").children().index($(this).parent());
    moveToIndex(index+1);
  });

  function moveToIndex(idx) {
    if (idx === currentIndex)
      return;

    var fromTab = $(".menu li:nth-child(" + currentIndex + ")"),
      toTab = $(".menu li:nth-child(" + idx + ")"),
      underlineborder = $(".underline-border"),
      animationDuration = 150;

    var fromLeft = 0,
      fromRight = 0,
      toLeft = toTab.offset().left - toTab.parent().offset().left,
      toRight = toTab.offset().left + $(toTab).width();

    if (fromTab.length > 0) {
      fromLeft = fromTab.offset().left - fromTab.parent().offset().left;
      fromRight = fromLeft + fromTab.width();
    }

    $(".menu li").removeClass("active");
    toTab.addClass("active");

    underlineborder.animate({
      left: currentIndex < idx ? fromLeft : toLeft,
      width: currentIndex < idx ? toRight - fromLeft : fromRight - toLeft
    }, animationDuration).animate({
      left: toLeft,
      width: toTab.width()
    }, animationDuration);

    currentIndex = idx;
  }

  // initialize tabs
  moveToIndex(1);
});
ul{
  position:relative;
}
.menu li {
  cursor: pointer;
  display: inline-block;
  margin: 5px 7px 10px 7px;
  opacity: .65;
  transition: .3s transform;
}

.menu li.active {
  cursor: default;
  opacity: 1;
  text-shadow: 0 0 4px rgba(0, 0, 0, .8);
  transform: translateY(-3px);
}

.menu li.underline-border {
  background: red;
  border-radius: 5px;
  cursor: default;
  position: absolute;
  height: 3px;
  width: 10px;
  margin: 0;
  opacity: 1;
  bottom: 0;
  left: 0;
  transform: translateY(0px);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="primary-navigation">
  <ul id="menu-main-navigation" class="menu nav-menu">

    <li id="menu-item-428" class="main-nav-item-1">
      <a href="https://link-1.com">Link-1</a></li>

    <li id="menu-item-344" class="main-nav-item-2">
      <a href="https://link-2.com">Link-2</a></li>

    <li id="menu-item-228" class="main-nav-item-3">
      <a href="https://link-3.com">Link-3</a></li>
      
    <li class="underline-border"></li>
  </ul>
</div>

Enjoy!

Nimitt Shah
  • 4,477
  • 2
  • 10
  • 21
  • 1
    Huge thanks for helping me out! And also for helping me with the dynamic hover functionality. I can see that it works well when running the code snippet but I'm unable to test it on my site because I don't know how to create another `li` in a Wordpress menu like that, or if it's even possible – noob Jun 03 '19 at 16:25
  • In case anyone else is interested, I found some threads here on SO explaining how to create `li` classes in Wordpress menus, e.g. https://stackoverflow.com/questions/14464505/how-to-add-class-in-li-using-wp-nav-menu-in-wordpress – noob Jun 03 '19 at 18:35