0

I'm trying to use Javascript to accomplish two effects: 1) Make the description of navigation links in a menu on the left side of the page fly in from the left when hovering over the icon and fly back out when the mouse is no longer over the icon. 2) Give the user the ability to hide the menu with a button.

I have all the code in a codepen at this link... https://codepen.io/anon/pen/JemLER

Effect #1 is working perfectly until the menu is hidden with effect #2. Then, the descriptions will no longer fly in from the left side when the icon is hovered.

The way I am doing #1 is by using javascript to add or remove a class to the element that translates it to the left off of the page using mouseenter and mouseout event listeners.

Here are the javascript functions...

document.querySelector('.home-icon').addEventListener('mouseenter', () => {
    document.querySelector('.home-desc').classList.remove('side-menu__list-item-desc-hide');
    console.log('hover');
});

document.querySelector('.home-icon').addEventListener('mouseout', () => {
    document.querySelector('.home-desc').classList.add('side-menu__list-item-desc-hide');
});

And this is the class to hide the elements.

.side-menu__list-item-desc-hide {
  transform: translateX(-10rem); 
}

For #2, I am hiding the menu in a similar way with a click event instead.

The javascript code is ...

const foldBtn = document.querySelector('.side-menu__fold-btn');

let isHidden = false;

foldBtn.addEventListener('click', () => {

    if (isHidden == false) {
        sideMenu.classList.add('side-menu-hide');
        sideMenuList.innerHTML = '';
        isHidden = true;
        foldIcon.innerHTML = 'chevron_right'; 
    }
    else {
        sideMenu.classList.remove('side-menu-hide');
        isHidden = false;
        foldIcon.innerHTML = 'chevron_left';
        
        setTimeout(() => {
            sideMenuList.innerHTML = sideMenuListContent;
        }, 400); 
    }
});

And the CSS class is...

.side-menu-hide {
  transform: translateX(-100%); 
}

Any ideas what could be causing the problem?

Thanks!

1 Answers1

1

Hi John and welcome to the SO. The code is a bit overly complicated and there is actually much, much simpler solution.

The whole button click is literary this line of code :)

foldBtn.addEventListener('click', () => {
    sideMenu.classList.toggle('side-menu-hide');
});

Try it. The bug is gone. I'll add more links and further explanation in an edit.

MDN: Element.classList

Element.classList.toggle is extremely useful function and it can save you many lines of code and some potential headache with debugging it. IT basically does exactly what you were doing with add and remove. The "trick" is that it checks if the class is present or not for you. So you don't have to write if/else statements. If there's no class, it will add it. And vice versa. With that new knowledge, can you think of the ways how you can refactor the rest of your code (hint: the classes for the icons)?

EDIT - The explanation for the bug You have hard coded complete children of the ul in a string and stored it in a const called sideMenuListContent. When you first click on the button (when you want to hide the menu), for some reason you have decided to destroy/remove 'innerHtml' of 'ul' with this line of code:

sideMenuList.innerHTML = '';

And later when clicking on the button again (the menu comes back), you were simply setting the innerHtml of the ul, by assigning it to the previously defined sideMenuListContent (and all of that with setTimeout).

setTimeout(() => {
    sideMenuList.innerHTML = sideMenuListContent;
}, 400);

But in the process, you have destroyed all event listeners. That's why your JS code didn't work. This was at least redundant step (which I hopefully explained in the comment below), but more than that - it's "not the best way" (to say the least) to append children to some DOM element. If you ever find a true need to actually append children, you first need to create that child with document.createElement and after that, to use appendChild. You can read more about it in this and this answer on SO. I know hope that my answer is complete and you have better understanding of your code and the DOM.

nemanja
  • 664
  • 5
  • 16
  • Hi Nemanja. Thanks very much for your help! I forgot all about the toggle method. I do wonder though why my code isn't working (even though it's completely unnecessary :) ) – John Deaton Nov 28 '18 at 18:17
  • @JohnDeaton because of this line: `const sideMenuListContent =
  • – nemanja Nov 28 '18 at 18:25
  • @JohnDeaton - I have added very detailed explanation of the bug with two examples if you're still interested in why that happened in the first place. Cheers – nemanja Nov 28 '18 at 19:17
  • Your explanation makes a lot of sense to me. Thanks for taking the time to put it together. Regards. - John – John Deaton Nov 29 '18 at 00:04