-1

The title of this question reflects the final goal, which is preventing .hover() to be bind more than once to the same element.

Before asking I did a search on SO and I have found this question which is already answered: Checking if jQuery .hover action is already binded

Also I've Googled a lot about it and it looks like the accepted answer to that question is correct.

With that, I came up with a small piece of code which tries to do the following:

  1. Loop over all elements with a class class-name
  2. Obtain all the events on that element
  3. Check if the .hover() event is already bind on it
  4. If it's not, then add it.

$(document).ready(function() {
  $('.class-name').each(function() {
    var events = $._data($(this)[0], 'events');

    if ( !(events['mouseover'] && events['mouseout']) ) {
      $(this).hover(
        function() { alert('IN'); },
        function() { alert('OUT'); }
      );
    }
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<a class="class-name">a</a>

The code above doesn't work and I cannot figure out where the error is. According to the JS console output, the events variable is undefined.

Any help appreciated. Thanks.

  • I find it easier to check for the existence of a class -- When I add the original hover, check for existence of "hover-set" class, or similar. If not there, add my listener and add the class. Helps also during debugging because it's easy to see which classes have the hover set. – pbuck Nov 02 '17 at 16:35

2 Answers2

0

I've found the problem.

At the beginning no events at all have been bind to the element, so $._data($(this)[0], 'events') is undefined. Therefore the events variable is undefined as well.

The if clause needs to follow this logic:

if ( (no events at all) OR (mousever and mouseout events don't exist) )

Below the fixed code snippet:

$(document).ready(function() {
  $('.class-name').each(function() {
    var events = $._data($(this)[0], 'events');

    if ( typeof(events) === 'undefined' || !(events['mouseover'] && events['mouseout']) ) {
      $(this).hover(
        function() { alert('IN'); },
        function() { alert('OUT'); }
      );
    }
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<a class="class-name">a</a>
-1

You forgot to bind the events to the <a> element before you checked them in your if statement

$(document).ready(function() 
{
  $('.class-name').each(function() 
  {
    var events = $(this);
    //set the events first
    events.on("mouseover", mouseover);
    events.on("mouseout", mouseout);
    
    if ( (events['mouseover'] && events['mouseout']) ) {
      console.log("both events bound to <a> tag");
    }
    
    //output all event handlers in console
    console.log('Event handlers :', $._data(events[0], "events"));
  });
});

var mouseover = function(){console.log('IN');};
var mouseout = function(){console.log('OUT');};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<a class="class-name">a</a>
Master Yoda
  • 4,334
  • 10
  • 43
  • 77
  • Adding the events first and then checking is not the point of this question. You need to be able to check without knowing if the events have been bind or not. – Vicente Olivert Riera Nov 03 '17 at 12:56