xpanta
xpanta

Reputation: 8418

Show and Hide handlers are applied multiple times on each click

This is my html code:

<span id="username_{{ member.id }}" onclick="showMembershipData('{{ member.id }}');">{{ member.user.username }}</span>

and this is my jQuery code

function showMembershipData(id)
    {
        $("#memberInfo_"+id).slideDown();
        $("#username_"+id).click(function(){
            hideMembershipData(id);
        });
    }

    function hideMembershipData(id) {
        $("#memberInfo_" + id).slideUp();
        $("#username_" + id).click(function() {
            showMembershipData(id);
        });
    }

I want the user name to be clickable and when clicked open the "more information" pane, or close it if it is opened. What happens now is:

and so on... Why? What am I doing wrong?

Upvotes: 1

Views: 101

Answers (7)

vittore
vittore

Reputation: 17589

You are assigning handler inside each handler, and you only need to assign handler once or even consider using event delegation $.on(event, selector, handler) if you are adding and removing items.

consider code below, and remove handlers from markup:

  • add class username to elements with id username_xxx

  • add class memberInfo to elements with id memeberInfo_xxx

  • add data-id attribute to elements with id username_xxx

So markup going to look like:

 <span class="username" data-id"{{ member.id }}">{{ member.user.username }}</span>

And the script:

$('body').on('click', '.username', function(e) {
   var id = $(this).data('id') 
   $('#memberInfo_'+id).toggle()
})

Upvotes: 4

JoeCianflone
JoeCianflone

Reputation: 682

Agree with the guys above...you keep registering the events. If all you're doing is opening and closing one:

$('#clickme').click(function() {
    $('#book').slideToggle('slow', function() {
        // Animation complete.
    });
});

http://api.jquery.com/slideToggle/

Upvotes: 1

Alistair Laing
Alistair Laing

Reputation: 973

It is happenign 2 times in a row because each time you call those functions they bind a click function which fires.

try

$("#username_"+id).click(function(){ 
  var $showHideElement =$("#memberInfo_"+id);
  if ($showHideElementis(':visible'){
    $showHideElement.slideUp();
  }else{
    $showHideElement.slideDown();
  }
})

Upvotes: 0

balexandre
balexandre

Reputation: 75103

let's change the code a little bit, shall we

<span 
    id="username_{{ member.id }}" 
    class="member"
    data-memberid="{{ member.id }}">{{ member.user.username }}</span>

on the jQuery side

$(".member").toggle(
    function() {  // click - show
        var id = $(this).attr("data-memberid");
        $("#memberInfo_" + id).stop().slideDown();
    },
    function() {  // click again - hide
        var id = $(this).attr("data-memberid");
        $("#memberInfo_" + id).stop().slideUp();

     });

easy :)

Upvotes: 1

Bojangles
Bojangles

Reputation: 101483

You can make life a whole lot easier by using jQuery's slideToggle() method - try the following:

function showMembershipData(id)
{
    $("#memberInfo_"+id).slideToggle();
}

This will toggle the #memberInfo + id (whatever the ID is) when the link is clicked. Can I suggest using jQuery's click() function? (needs a class added to the username span):

$("#username_span").click(function()
{
    $("#memberInfo_"+id).slideToggle();
});

Don't forget to add it to your $(document).ready() bit or whatever. Once you've done that, you can remove the onClick from the span.

James

Upvotes: 1

Nikhil
Nikhil

Reputation: 3384

The problem with your code is that even handlers are been attached multiple times. Basically with jQuery if you do something like

$("#element").click(functionName);
$("#element").click(functionName);
$("#element").click(functionName);

Then clicking the element once will fire functionName thrice! You need to refactor your code a bit to make sure that the event handlers are added and removed appropriately. Try this

function showMembershipData(id)
    {
        $("#memberInfo_"+id).slideDown();
        $("#username_"+id).unbind("click").bind("click",(function(){
            hideMembershipData(id);
        });
    }

    function hideMembershipData(id) {
        $("#memberInfo_" + id).slideUp();
        $("#username_" + id).unbind("click").bind("click",(function() {
            showMembershipData(id);
        });
    }

Upvotes: 2

Thariama
Thariama

Reputation: 50832

Problem here is that you add an event handler each time showMembershipData gets called. You should make sure only one event handler gets assigned.

Upvotes: 0

Related Questions