2

I have a piece of code the creates a hovercard (a box with some additional info) on a social network type of site, whenever a user hovers with their mouse over some hyperlink that contains a username:

$(function() {

 $('body').on('mouseenter', 'a', function(){

    $(this).attr('data-value', '10');
    let username = $(this).attr('href');

    $.post("includes/handlers/hovercard.php", {username:username}, function(data){

                     if(data === "yes") 
                        $('a[data-value=10]').wrap("<div class='hov' style='display:inline-block;'></div>");

                     else 
                        $('a[data-value=10]').removeAttr('data-value');

   });  
  $.post("includes/handlers/hovercard_response.php", {username:username}, function(response){
                     $('.hov').append('<span></span>');
                     $(".hov span").html(response);

                     $('.hov').each(function(){

                         $(this).on('mouseover', 'a', function(){
                             return false;
                         });
                     });

           //...and then some buttons, links and etc are displayed...

  }).on('mouseleave', 'a', function(){
             $('a[data-value=10]').removeAttr('data-value');
     });

});

The first ajax response checks if the user is hovering over a link that contains a username, and if so it sends "yes" as the response. If it's a link with a username, then the second call applies the hovercard with all the other stuff that should be displayed (I left that bit out not to clutter the post since it's irrelevant to the problem).

This all works fine. The only problem is that, occasionally, if you hover over the user A, for example, and then over the users B, C, and D it doesn't show the info for A, B, C, and D but A, A, A, A. In other words, it gets stuck and shows the info for only one user, as if you keep hovering over the same link over and over again.

I checked out the console and saw that when this happens, it does not send ajax requests at all. So instead of sending the request for B, it doesn't send anything but just keeps displaying A instead. If I start scrolling the page a bit, or refresh, the problem disappears and it's all normal again. It happens on both Chrome and Firefox.

I first thought it might be some caching issue, so I added $ajaxSetup({ cache:false }) at the very top, but that didn't help.

Any help is much appreciated...

Vlad77
  • 61
  • 1
  • 6
  • what you described suggests `username` wasn't set correctly, can you `console.log` it during hover to verify? – kasperite Dec 13 '18 at 23:14
  • Hi @kasperite I added `console.log(username)` right after this line `let username = $(this).attr('href');` and before any ajax calls. While it works as it should, it logs usernames of the hovered users, but when this starts happening, it stops. Doesn't log anything. – Vlad77 Dec 13 '18 at 23:32
  • Are you sure you don't have other `mouseenter` or `mouseover` listeners elsewhere? – kasperite Dec 13 '18 at 23:41
  • No, apart from the opening and closing `mouseenter/mouseleave`, I have a `mouseover` appearing once, it's visible in the code that I posted. It's to stop the ajax from propagating to the links that will be displayed in the hovercard `$('.hov').each(function(){ $(this).on('mouseover', 'a', function(){ return false; }); }); ` – Vlad77 Dec 13 '18 at 23:55

1 Answers1

1

Ok let's try to solve this issue my way .. you can try the next code .. and please try to add //comments to your code

$(function() {
  // href mouse enter event
  $(document).on('mouseenter', 'a', function(){
      // remove all data-value and empty spans
      $('a[data-value=10]').removeAttr('data-value').find('.hov').remove();
      // set the data-value
      $(this).attr('data-value', '10');
      // get a user name .. using var
      var username = $(this).attr('href').trim();

      // post to hovercard page
      $.post("includes/handlers/hovercard.php", {username:username}, function(data){
        var data = data.trim(); // trim data to avoid right/left white spaces
        if(data === "yes"){
        // run the next ajax post to response
          $.post("includes/handlers/hovercard_response.php", {username:username}, function(response){
             // append .hov with span with response
             $('a[data-value=10]').append("<div class='hov' style='display:inline-block;'><span>"+response+"</span></div>");
           });
        }else{
          $('a[data-value=10]').removeAttr('data-value').find('.hov').remove();
        }
      });  

  }).on('mouseleave', 'a', function(){ // mouse leave event
      $('a[data-value=10]').removeAttr('data-value').find('.hov').remove();
  });

  // stop .hov propagation without need to .each
  $(document).on('mouseover', '.hov', function(e){
      e.stopPropagation();
  });
});

if you found some syntax error just let me know

Note its not a good idea to check for a for users or link .. you can simply add a class for just the users a then use it like a.username then no need to the first $.post you can then go to the response page directly

Mohamed-Yousef
  • 23,946
  • 3
  • 19
  • 28
  • Thanks, Mohamed. This works just as it should, sends a request once per every link hovered :) Much appreciated! May I ask why you used a `var` instead of `let` for getting the username? You also mentioned that in a comment on that line? Btw, sorry for not posting any comments in the code, I'll try to do that in the future. And you're right, I should've added a class for usernames. Never occurred to me, though :) – Vlad77 Dec 14 '18 at 15:55
  • 1
    You're tottaly welcome @Vlad77 .. comments is to simplify your code to yourself not just for us .. and about `let` and `var` you can read [What's the difference between using “let” and “var” to declare a variable in JavaScript?](https://stackoverflow.com/questions/762011/whats-the-difference-between-using-let-and-var-to-declare-a-variable-in-jav) .. Have a great day :-) – Mohamed-Yousef Dec 14 '18 at 19:04