3

I've found similarly titled questions on SO, but none seem related to my issue.

This one has been driving me nuts all day and most of the night.

First, the what the running code looks like:

enter image description here

Next, an MCV version of my code:

<!DOCTYPE html>
<!-- file: index2.html -->
<html>
<head>
    <link rel="stylesheet" href="css/style2.css">
</head>
<body>
    <form id="form-container">
        <button id="submit-btn">Make things happen</button>
    </form>
    <div id="toggler">Click this to toggle Stuff</div>
    <div id="stuff-container">
        Stuff
    </div>
    <script src="js/libs/jquery.min.js"></script>
    <script src="js/script2.js"></script>
</body>
</html>
// file: script2.js
function loadData() {
    $('#toggler').hover( 
        function() {
            $(this).css('cursor', 'pointer');
        },
        function() {
            $(this).css('cursor', 'text');
        });

    $('#toggler').click(function() {
        $('#stuff-container').toggle();
    });

    return false;
};
$('#form-container').submit(loadData);
/* file: style2.css */
#stuff-container {
    display: block;
}

And the behavior:

  1. navigate to index2.html

Run #1:

  1. click button "Make things happen"
  2. hover over "Click this to toggle Stuff"
    -- cursor changes to a hand
  3. click "Click this to toggle Stuff"
  4. "Stuff" toggles correctly.

Run #2:
Steps 1, 2, 3 as before.

  1. "Stuff" does not toggle.

Using console.log() calls, I found that each function in script2.js executes multiple times if the "Make things happen" button has been clicked more than once.

e.g., if the button has been clicked 5 times since page reload, when I do Step 2 above, the first .css() in hover() is executed 5 times.

So, if the button has been clicked any even number of times, the toggle() calls have no effect.

The questions:

What (probably very basic) concept am I missing? How do I prevent the multiple executions of each function?

4
  • Can you create a jsFiddle of your code and share it? Commented Feb 4, 2016 at 9:06
  • 2
    Each time you run loadData, you are attaching a function to the click and hover events. Attaching a function several times to an event will trigger it the same number of times you attach it. Commented Feb 4, 2016 at 9:06
  • 1
    The functions .hover()and .click() apply eventhandler to you button so you should define these eventhandlers only once to the element not multiple times. You could apply the eventhandlers when page has finished loading for example. Have a look at api.jquery.com/ready Commented Feb 4, 2016 at 9:10
  • @Rayu: I tried creating a Fiddle but it produced an error ("please use a POST request") so I didn't save it. Probably should have saved it despite the error. Commented Feb 4, 2016 at 13:36

1 Answer 1

1

That is because the $('#toggler').hover and $('#toggler').click() binds new (additional) event handlers each time it is executed. And you execute those each time you press on the button which in turn runs the loadData function.

So,

  • First run, you bind hover/click handlers (one bound handler): runs fine
  • Second run, you bind another hover/click handler (two bound handlers): problem because first handler toggles on while second toggles off
  • third run,.... (three bound handlers): runs fine (but only because it is toggled on/off/on)

In general it will work on the odd runs and fail on the even ones.

You should only bind once.


On solution is to unbind before re-binding

$('#toggler').off('mouseenter mouseleave').hover(...);
$('#toggler').off('click').click(...);

But it really depends on what other things you want to do inside the loadData function.

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

1 Comment

Thanks to all who answered or commented!

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.