views:

390

answers:

3

The dynamically added links (classnames .divToggle and .removeDiv) only function if clicked twice the first time. What is preventing them from working properly right away?

$(document).ready(function(){
// adds click event to links.
$('a.divToggle').live('click', function(event) {
    // Toggles the visibility of divs.
    event.preventDefault;
    $(this).toggle(function(){
            $(this).next(".divToToggle").slideUp("slow");
            $(this).text("show[+]");
    },
    function(){
            $(this).next(".divToToggle").slideDown("slow");
            $(this).text("hide[-]");
    });     
});

// used to remove divs from the page.
$("a.removeDiv").live("click", function(event) {
    event.preventDefault;
    $(this).parent().prev("a").prev("h2").remove();
    $(this).parent().prev("a").remove();
    $(this).parent().next("br").remove();
    $(this).parent().remove();  
}); 

// Used to add new divs to the page.
$(".addDiv").click(function(){
    $("<h2>Title Area</h2><a href='#' class='divToggle'>hide[-]</a>"
    + "<div class='divToToggle'><a href='#' class='removeDiv'>Remove this div</a>"
    + "<ul><li>List element 1</li><li>List element 2</li>"
    + "<li>List element 3</li></ul></div><br />").insertBefore($(this));
});

});

A: 

It's a long shot but it is because you have event.preventDefault; before all other code? I normally use this as the last statement in my function.

Like I said it's a long shot but worth a try!

Have you tried showing an javascript alert or using Firebugs log window to see if the event is being fired the first time? Maybe it's being fired but not doing what you expect and something else is causing it to fail?

Fermin
The `preventDefault` doesn't do anything anyway, because it's not actually called (missing `()` after it).
bobince
+4  A: 

$(...).toggle doesn't do anything straight away. It just binds click events to the selected elements, so that in the future clicking causes one of the two functions to be called. So the first click does nothing but set up the toggle event handler. The second click actually calls the toggle event handler. (And also adds another toggle event handler! So the third click calls two toggle event handlers, and so on.)

.toggle is an alternative to .click binding, not something you would (normally) use inside a .click event handler.

There is no ‘live’ version of toggle, but you can write one yourself, eg.:

function livetoggle(selector, f0, f1) {
    $(selector).live('click', function(event) {
        var t= $(this).data('livetoggle');
        $(this).data('livetoggle', !t);
        (t? f1 : f0).call(this, event);
    });
}


livetoggle('a.divToggle', function() {
    ...
}, function() {
    ...
});
bobince
This works for the first link added to the page, subsequent links still need to be clicked twice.
Kyle
Works for me. Test code: http://pastebin.com/f3715f279
bobince
Thanks to your help it's very close. The behavior I get now is that if you add the group, then add a second group. Click the link to hide the first group, then click the link to hide the second group you need to click the second link twice.
Kyle
Ah! I see what you mean. Yes, I done a mistake. :-) Edited answer to fix the `livetoggle` implementation — try that one.
bobince
I tried this after the alterations and it works, however I went with my code below because I have a better understanding of how it works. You get the answer though.
Kyle
A: 

So this is what i ended up with. Seems to work ok.

$(document).ready(function(){

// adds click event to links.
$('a.divToggle').live('click', function() {
   var testText = $(this).text();
   if(testText == 'hide[-]') {
    $(this).next('.divToToggle').slideUp('slow');
    $(this).text('show[+]');
   } else {
    $(this).next('.divToToggle').slideDown('slow');
    $(this).text('hide[-]');
   }
})

// used to remove divs from the page.
$('a.removeDiv').live('click', function(event) {
    $(this).parent().prev('a').prev('h2').remove();
    $(this).parent().prev('a').remove();
    $(this).parent().next('br').remove();
    $(this).parent().remove();
    return false;
});

// Used to add new divs to the page.
$('.addDiv').click(function(){
    $("<h2>Title Area</h2><a href='#' class='divToggle'>hide[-]</a>"
    + "<div class='divToToggle'><a href='#' class='removeDiv'>Remove this div</a>"
    + "<ul><li>List element 1</li><li>List element 2</li>"
    + "<li>List element 3</li></ul></div><br />").insertBefore($(this));
    return false;
});

});

Kyle