Switching from a click event to a hover event in JavaScript

I've been experimenting with animating a burger bar on hover and came across an example online that I managed to adapt for mouseenter functionality. However, I'm struggling to make it revert back to the burger bar shape once the mouse leaves on mouseleave.

Below is the code snippet. While mouseenter is working as intended, I need help getting it to switch back to the burger bar icon when moving away from it instead of staying as an X.

(function() {"use strict";
  var toggles = document.querySelectorAll(".c-hamburger");
  for (var i = toggles.length - 1; i >= 0; i--) {
    var toggle = toggles[i];
    toggleHandler(toggle);
  };
  function toggleHandler(toggle) {
    toggle.addEventListener("mouseenter", function(e) {
      e.preventDefault();
      (this.classList.contains("is-active") === true) ? this.classList.remove("is-active"): this.classList.add("is-active");
    });
  }
             
})();
.c-hamburger {
  display: block;
  position: relative;
  overflow: hidden;
  margin: 0;
  padding: 0;
  width: 66px;
  height: 55px;
  font-size: 0;
  text-indent: -9999px;
  appearance: none;
  box-shadow: none;
  border-radius: none;
  border: none;
  cursor: pointer;
  transition: background 0.3s;
}

.c-hamburger:focus {
  outline: none;
}

.c-hamburger span {
  display: block;
  position: absolute;
  left: 18px;
  right: 18px;
  height: 2px;
  background: black;
}

.c-hamburger span::before,
.c-hamburger span::after {
  position: absolute;
  display: block;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: black;
  content: "";
}

.c-hamburger span::before {
  top: -10px;
}

.c-hamburger span::after {
  bottom: -10px;
}
.c-hamburger--htx {
  background-color: white;
}

.c-hamburger--htx span {
  transition: background 0s 0.3s;
}

.c-hamburger--htx span::before,
.c-hamburger--htx span::after {
  transition-duration: 0.3s, 0.3s;
  transition-delay: 0.3s, 0s;
}

.c-hamburger--htx span::before {
  transition-property: top, transform;
}

.c-hamburger--htx span::after {
  transition-property: bottom, transform;
}

/* active state, i.e. menu open */
.c-hamburger--htx.is-active {
  background-color: white;
}

.c-hamburger--htx.is-active span {
  background: none;
}

.c-hamburger--htx.is-active span::before {
  top: 0;
  transform: rotate(45deg);
}

.c-hamburger--htx.is-active span::after {
  bottom: 0;
  transform: rotate(-45deg);
}

.c-hamburger--htx.is-active span::before,
.c-hamburger--htx.is-active span::after {
  transition-delay: 0s, 0.3s;
}
<button class="c-hamburger c-hamburger--htx">
  <span>toggle menu</span>
</button>

Answer №1

To toggle a class on mouseenter and remove it on mouseleave events.

(function() {"use strict";
  var toggles = document.querySelectorAll(".c-hamburger");
  for (var i = toggles.length - 1; i >= 0; i--) {
    var toggle = toggles[i];
    toggleHandler(toggle);
  };
  function toggleHandler(toggle) {
    toggle.addEventListener("mouseenter", function(e) {
      e.preventDefault();
      this.classList.add('is-active');
    })
    toggle.addEventListener('mouseleave',function(e) {
      this.classList.remove('is-active');
    });
  }             
})();
.c-hamburger {
  display: block;
  position: relative;
  overflow: hidden;
  margin: 0;
  padding: 0;
  width: 66px;
  height: 55px;
  font-size: 0;
  text-indent: -9999px;
  appearance: none;
  box-shadow: none;
  border-radius: none;
  border: none;
  cursor: pointer;
  transition: background 0.3s;
}

.c-hamburger:focus {
  outline: none;
}

.c-hamburger span {
  display: block;
  position: absolute;
  left: 18px;
  right: 18px;
  height: 2px;
  background: black;
}

.c-hamburger span::before,
.c-hamburger span::after {
  position: absolute;
  display: block;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: black;
  content: "";
}

.c-hamburger span::before {
  top: -10px;
}

.c-hamburger span::after {
  bottom: -10px;
}
.c-hamburger--htx {
  background-color: white;
}

.c-hamburger--htx span {
  transition: background 0s 0.3s;
}

.c-hamburger--htx span::before,
.c-hamburger--htx span::after {
  transition-duration: 0.3s, 0.3s;
  transition-delay: 0.3s, 0s;
}

.c-hamburger--htx span::before {
  transition-property: top, transform;
}

.c-hamburger--htx span::after {
  transition-property: bottom, transform;
}

/* active state, i.e. menu open */
.c-hamburger--htx.is-active {
  background-color: white;
}

.c-hamburger--htx.is-active span {
  background: none;
}

.c-hamburger--htx.is-active span::before {
  top: 0;
  transform: rotate(45deg);
}

.c-hamburger--htx.is-active span::after {
  bottom: 0;
  transform: rotate(-45deg);
}

.c-hamburger--htx.is-active span::before,
.c-hamburger--htx.is-active span::after {
  transition-delay: 0s, 0.3s;
}
<button class="c-hamburger c-hamburger--htx">
  <span>toggle menu</span>
</button>

This behavior can also be achieved using CSS only.

.c-hamburger {
  display: block;
  position: relative;
  overflow: hidden;
  margin: 0;
  padding: 0;
  width: 66px;
  height: 55px;
  font-size: 0;
  text-indent: -9999px;
  appearance: none;
  box-shadow: none;
  border-radius: none;
  border: none;
  cursor: pointer;
  transition: background 0.3s;
}

.c-hamburger:focus {
  outline: none;
}

.c-hamburger span {
  display: block;
  position: absolute;
  left: 18px;
  right: 18px;
  height: 2px;
  background: black;
}

.c-hamburger span::before,
.c-hamburger span::after {
  position: absolute;
  display: block;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: black;
  content: "";
}

.c-hamburger span::before {
  top: -10px;
}

.c-hamburger span::after {
  bottom: -10px;
}
.c-hamburger--htx {
  background-color: white;
}

.c-hamburger--htx span {
  transition: background 0s 0.3s;
}

.c-hamburger--htx span::before,
.c-hamburger--htx span::after {
  transition-duration: 0.3s, 0.3s;
  transition-delay: 0.3s, 0s;
}

.c-hamburger--htx span::before {
  transition-property: top, transform;
}

.c-hamburger--htx span::after {
  transition-property: bottom, transform;
}

/* active state, i.e. menu open */
.c-hamburger--htx.is-active {
  background-color: white;
}

.c-hamburger--htx:hover span {
  background: none;
}

.c-hamburger--htx:hover span::before {
  top: 0;
  transform: rotate(45deg);
}

.c-hamburger--htx:hover span::after {
  bottom: 0;
  transform: rotate(-45deg);
}

.c-hamburger--htx:hover span::before,
.c-hamburger--htx:hover span::after {
  transition-delay: 0s, 0.3s;
}
<button class="c-hamburger c-hamburger--htx">
  <span>toggle menu</span>
</button>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to troubleshoot WordPress Ajax function not getting form data

I am currently working on a form in my plugin where I need to send data to my AJAX action function using the standard WP Ajax techniques. Here is the basic structure of my form: <form role="form" id="signup_widget_form" method="post" action="#"> ...

What could be causing the appearance of a Firefox error message during the execution of a Protractor test?

Currently, I am conducting end-to-end testing on an AngularJS application using Protractor. Every time I execute a spec, Firefox launches and closes with a particular message appearing: After that, Firefox starts working properly and the specs run smooth ...

React - Received an unexpected string containing a template expression with no curly braces present in the string

Currently, I am enrolled in a React tutorial online. I have inputted the code exactly as it was shown on the screen. Strangely, it seems to be working perfectly fine in the video but not when I try it myself. Below is the code snippet: <Link to={&apos ...

What is the best way to initiate the handling of newly inserted values in a Vuex store?

I am working with a Vuex store that stores entries: const store = createStore({ state() { return { entries: [ { id: 1, date-of-birth: "2020-10-15T14:48:00.000Z", name: "Tom", }, ...

The jQuery function always stops before reaching the else statement

Whenever the check_for_build button is clicked, I have been trying to verify the existence of a specific text file and then display an alert based on whether it is found or not. My approach involves checking if the file contains any text (as I intend to us ...

Checking for the presence of an element prior to moving forward in a selenium and python script

Is there a way to create a loop that runs as long as a specific div element appears on a website? I am trying to navigate through several pages and click the "next" button for each page. The last page does not have the div element I am looking for, so I w ...

The Angular template driven forms are flagging as invalid despite the regExp being a match

My input looks like this: <div class="form-group"> <label for="power">Hero Power</label> <input [(ngModel)]="model.powerNumber" name="powerNumber" type="text" class="form-control" pattern="^[0-9]+$"id= ...

transfer the value of a method to a different component

In my Component called IncomeList, there is a method named sumValue. This method simply adds different numbers together to produce one value, for example 3+5 = 8. Similarly, in another Component named OutputList, the same logic is applied but with a method ...

What is the best way to customize the small square area found between the vertical and horizontal scrollbars?

Please take a look at the images provided below: https://i.stack.imgur.com/QVHfh.jpghttps://i.stack.imgur.com/cubd8.jpg Whenever both vertical and horizontal scrollbars intersect, it results in a square space. This phenomenon occurs not just within the b ...

Issues with the .change(function() JavaScript in Internet Explorer versions less than 9

I'm experiencing issues with this script in Internet Explorer versions below 9. Can someone please help me identify what is wrong with my script? Thank you. IE7 and IE8 are showing the following error: SCRIPT87: Invalid argument. Found ...

I am encountering issues with the responsiveness of my layout as it is

My goal is to create a responsive layout utilizing code and examples from this website: www.responsivegridsystem.com To achieve this, I have nested a few containers to ensure a content area of 960px width centered within a 1000px container. My plan is th ...

Are there any comparable features in Angular 8 to Angular 1's $filter('orderBy') function?

Just starting out with Angular and curious about the alternative for $filter('orderBy') that is used in an AngularJS controller. AngularJS example: $scope.itemsSorted = $filter('orderBy')($scope.newFilteredData, 'page_index&apos ...

An issue occurred while attempting to utilize fs.readFileSync

Attempting to change an uploaded image to base 64 format var file = e.target.files[0]; var imageFile = fs.readFileSync(file); var encoded = new Buffer(imageFile).toString('base64'); An error is encountered: TypeError: __W ...

The error message "Google Heatmap API - visualization_impl.js:2 Uncaught (in promise) TypeError: Cannot read property 'NaN' of undefined" was encountered while using the

I'm currently working on a project that involves utilizing a JSON data structure like the one shown below: [ { "lat": 53.1522756706757, "lon": -0.487157731632087, "size": 63, "field": "TestField", ...

Steps for resolving the "endless redirection loop" issue in Sharepoint

I am currently learning Javascript and working on setting up a multi-language Sharepoint site. I am trying to implement a code into each page that checks the user's email and the language in the URL (Portuguese or Spanish) and then redirects according ...

Is there a different method similar to Textfield onChange that works like the HTML onChange attribute?

In my current setup, I have a Textfield component nested within other components where I pass a function pointer down to it as a prop. The challenge I'm facing is that the function responsible for passing the contents of the Textfield back up to the r ...

The installation of npm modules is failing with the error message: "'react-scripts' is not recognized as a valid command, internally or externally."

As I revisited my old project on GitHub, things were running smoothly a few months prior. However, upon attempting to npm install, I noticed the presence of the node modules folder and encountered some npm errors. https://i.stack.imgur.com/awvjt.png Sub ...

Exploring the utilization of server-side Web Sockets functionality

Recently, I've been diving into the world of Web Sockets and I'm eager to understand how server-side implementation works. While I feel comfortable with writing client-side code using onmessage() in HTML5, JavaScript, etc., I find myself unsure a ...

What is the best way to verify multiple email addresses simultaneously?

Is there a method to validate multiple email addresses entered by users in a textarea? My current approach involves using ng-pattern for validation. ...

Enable Parse5's case sensitivity

Recently, I've attempted to parse Angular Templates into AST using the powerful parse5 library. It seemed like the perfect solution, until I encountered an issue - while parsing HTML, it appears that the library transforms everything to lowercase. Fo ...