behz4d
behz4d

Reputation: 1849

jQuery events fire more than once

first of all, I did my home work, I already searched Google and used evt.stopPropagation(); and unbind method, but not fixing my problem... .

Here is my case:

Imagine I have a left sidebdar with some linkes, on click of each link the middle col will be reloaded by ajax with some code like this:

<script>
$('.leftsidebar a').on('click', function(){
    var page = $(this).attr('class')
    $('#middleCol').load('loader.php?page='+ page);
});
</script>

So on each click on the left side bar a tag, the middle col will loads that a tag class.php, it's just fine.

now in the pages that I'm loading in the middle col, at the end of the page I have some javascripts,, for example if it loads by loader.php?page=test in test page I have some new jQuery lines, an example:

<script>
$('#blah').on('click', function(){
    $.ajax({
        type: 'POST',
        url: 'server.php',
        success: function(response){
            //blah  
        }   
    }); 
});
</script>

Now the problem is, when the first time, I load test page by clicking on leftside bar a tag, it works just fine, on click of #blah only 1 request will be sent to server.php, but when I click on another a from leftsidebar, then come back to the test, now if I click on blah, the ajax request will be sent twice to the server.php, and so on..., if I try it again, request will be sent for 3 times!

How can I prevent such behavior? what is the solution?

I appreciate helps.

Upvotes: 2

Views: 1810

Answers (5)

Tom Pietrosanti
Tom Pietrosanti

Reputation: 4294

Each time your sidebar ajax fires, it adds a script to the page, which adds a click event to #blah. So when #blah is clicked, it is firing each of those handlers.

You can either override the click event each time by assigning the onclick handler using plain old javascript document.getElementById('blah').onclick = yourClickFunction or you can first turn off the click events, then add a new one with jquery

$('#blah').off('click').on('click', yourFunction);

Another suggestion is to use event delegation for your sidebar links, so instead of this: $('.leftsidebar a').on('click', function(){ do this: $('.leftsidebar').on('click', 'a', function(){

This creates a single handler for all 40 or so of those links, which is a bit more efficient. Plus any links that get added later will automatically have the click handler, without you needing to attach it.

Upvotes: 1

Explosion Pills
Explosion Pills

Reputation: 191809

A fairly simple solution would be to bind data to #blah to determine whether that click event is already bound to prevent it from binding again.

$("#blah:not([data-bound])").on('click', function () {
    /* your code */
});
//not using .data to ensure attribute string set for selector use.
$("#blah").attr('data-bound', 'bound');

Upvotes: 3

Alvaro
Alvaro

Reputation: 41605

You should separate your js files from the views including them in the header of the site:

<script src="yourPath/actions.js"></script>

This is usually the correct way to do it.

Include the file only ONCE in the parent .php file and get rid of mistakes like the one you are having.

Your loader.php should not include any Javascript code. There's no need.

Upvotes: 2

A. Wolff
A. Wolff

Reputation: 74410

You could do that too if no more than one click handler is bounded to this element:

$('#blah').off('click').on('click', function(){...});

But better would be to not include useless/redundant code

Upvotes: 5

Dylan Hayes
Dylan Hayes

Reputation: 2366

Every time you're loading your inner page you are rebinding blah click event. Try moving your blah click to your outter script.

Upvotes: 0

Related Questions