3

I want to change a link color to orange on hover.

On a mobile device, when the user touches the link, it becomes orange and will remain orange until the user clicks away. So I want to manually trigger the mouseout event so that the link looses it's hover effect after 1 seconds.

This is what I have tried but the link remains orange after 1 second:

$(window).on('load', function() {
  $('a').on('click', function() {
    
    // on a mobile device, I want the hover effect to end after 1 seconds
    window.setTimeout(function() {
      $('a').trigger('mouseout');
    }, 1000);
  
  });
});
a {
  font-size: 2rem;
}

a:hover {
  color: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <a href='#'>Test</a>
</div>


Note: this is a simplified example, in my code I am not using a timer instead I want to trigger the mouseout event on ajaxcomplete

$(document).on('ajaxComplete', function () {
    $('a').trigger('mouseout');
});
2
  • 1
    Wouldn't it be easier if you simply add a class on click and just remove the class after the ajaxComplete is triggered? Commented Sep 28, 2021 at 23:37
  • 1
    For what it is worth, it seems like most solutions would involve some hack-ish workarounds for a hover state that doesn't really make much sense in the context of a cursor-less environment. Might it be better to just suppress hover states for small screens or touch interfaces if the hover visual treatment represents a problem? Commented Sep 29, 2021 at 0:10

2 Answers 2

2

The problem is trying to force a mouseout event doesn't seem to work on a touch device.

The series of events that is fired on a touch device starts with a touchstart event - see e.g. MDN

If the browser fires both touch and mouse events because of a single user input, the browser must fire a touchstart before any mouse events.

This snippet remembers that the user has started a touch event and instead of acting on mouse events it sets a class which changes the text color. The same is done on mouse events, which are only acted on when the user is not appearing to be using a touch device on this element.

While it would seem logical to look subsequently for the touchend event on the element, it seems that if the user does a long touch on it, given it is an anchor element, the touchend event is not fired on the element when they remove their finger/pointing device. It is however still fired on the window and so we catch that event and remove the hover class.

let usingTouch = false;
const a = document.querySelector('a');
a.addEventListener('touchstart', function() {
  usingTouch = true;
  a.classList.add('hover');
});
window.addEventListener('touchend', function() {
  usingTouch = true;
  setTimeout(function() {
    a.classList.remove('hover');
  }, 1000);
});
a.addEventListener('mouseover', function() {
  if (!usingTouch) a.classList.add('hover');
});
a.addEventListener('mouseout', function() {
  if (!usingTouch) a.classList.remove('hover');
});
a {
  font-size: 2rem;
}

.hover {
  color: orange;
}
<div>
  <a href='#'>Test</a>
</div>

Sign up to request clarification or add additional context in comments.

Comments

2

a {
  font-size: 2rem;
}

a:hover {
  color: myanimation 1s 1;
  -webkit-animation:myanimation 1s 1;
}

@keyframes myanimation
{
    0%      {color:orange;}
    100%    {color:orange;}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <a href='#'>Test</a>
</div>

This is solvable via a CSS animation, see the snippet above.

5 Comments

Thanks but this would break the desktop functionality as orange will disappear after one second... also the 1 second was for demonstration I wanted to trigger the event on ajaxcomplete
@HoomanBahreini you can add a class called mobile to body when it's mobile and change the rule to .mobile a:hover.
@HoomanBahreini you can also apply media queries to differentiate between the hovers, have your previous hover effect for large screens and the suggested one for smaller screens.
Unfortunately 'testing for mobile' won't work given small viewports can be on mouse-enabled devices too and touch devices can be large. You'd need to check whether the user was using touch or mouse - and that's not reliable, they could be using both.
@AHaworth if such worries are present, then one can read information from the user agent and use that in order to determine whether it's a touch screen or not. In our example the device is a mobile device as specified in the question, this is why I assumed a small screen, as it's hard to imagine a person carrying a large TV screen on the street and using it. Yet, if we broaden the problem-space to touchscreens, then user agent data comes to our aid.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.