views:

58

answers:

5

What I want to do is add and remove list items. I have got it to add new items to the list and I can remove existing ones but not the ones that have been added. It seem like it would work but it doesn't. Any help would be appreciated! Here the code:

JQuery:

<script  type="text/javascript">
$(function(){
    $('a#add').click(function(){
        $('<li><a href="#" id="remove">--</a>List item</li>').appendTo('ul#list');
    });

    $('a#remove').click(function(){ 
        $(this).parent().remove();
    });
});
</script>

HTML:

<a href="#" id="add">Add List Item</a>
<ul id="list">
<li><a href="#" id="remove">--</a> List item</li>
<li><a href="#" id="remove">--</a> List item</li>
<li><a href="#" id="remove">--</a> List item</li>
<li><a href="#" id="remove">--</a> List item</li>
</ul>
+1  A: 

try this

$('a#remove').live('click',function(){ 
        $(this).parent().remove();
    });

or

  $('a#remove').live('click',function(){ 
            $(this).remove();
        });
c0mrade
That wouldn't work, since `this` points to the document object in live events.
Felix
@Felix post your answer then lets see the right solution
c0mrade
I was composing it when I saw your answer. Posted it now :)
Felix
@Felix, I don't think so...
nickf
They both work.
Scott
@Scott gr8, just make sure you change those ID's to classes as others told you as well, and all is kick ass..
c0mrade
A: 

The id attribute is supposed to be unique, your HTML is invalid, thus jQuery doesn't work (I'm betting the a#remove selector only selects the first item). Use something else, like name, which isn't supposed to be unique. Also, you might want to use .parent("li"). Here's how I'd do this:

jQuery:

<script  type="text/javascript">
function setEvents() {
    $("a#add").click(function() {
        $("#list").append(
            $("<li>").append(
                $('<a href="#" name="remove">--</a>').click(removeItem)
            ).append("List item")
        );
    });

    $('a[name=remove]').click(removeItem);
}
function removeItem(e) {
    $(this).parent("li").remove();
}
$(document).ready(setEvents);
</script>

HTML:

<a href="#" id="add">Add List Item</a>
<ul id="list">
<li><a href="#" name="remove">--</a> List item</li>
<li><a href="#" name="remove">--</a> List item</li>
<li><a href="#" name="remove">--</a> List item</li>
<li><a href="#" name="remove">--</a> List item</li>
</ul>
Felix
name? why not `class`?
nickf
Thanks for pointing out the id problem, I did it out of habit I have replaced them with class's.
Scott
@nickf because classes should be used for styling purposes first, javascript second. Why is this downvoted like hell, nobody commented anything negative on it..
Felix
@Felix, well - using `name` isn't right. See the spec: `"The value of this attribute must be a unique anchor name"` http://www.w3.org/TR/html401/struct/links.html#adef-name-A - plus, this is a perfect situation for `.live()`
nickf
Hmm, I think `name` should only be unique for `<a>` elements. Otherwise, why would `document.getElementsByName()` be a JavaScript function? Interesting, didn't know that. Thanks :)
Felix
Why only for <a> elements? You're just as likely to use document.getElementsByName() on other elements. Surely the correct statement should be 'The name attribute should be unique for all elements apart from radio buttons and checkboxes as, in these cases, the matching names are used to groups elements together'
belugabob
+2  A: 

Here you go:

jQuery(function($) {
    $('#add').click(function(e) {
        $('<li><a href="#" class="remove">--</a>List item</li>').appendTo('#list');
        e.preventDefault();
    });

    $('.remove').live('click', function(e) { 
        $(this).parent().remove();
        e.preventDefault();
    });
});
nickf
This looks like the kind of thing that I was thinking of, even down to using a class for the 'remove' identifier.
belugabob
+3  A: 

The issue with the code is not so much the lack of unique id values - although a class of 'remove' should be used instead - the main problem is the fact that the newly added items do not have a click handler associated with them. The code that adds click handlers is executed before any of the new items are created.

The use of the live() method should be investigated - I can't offer much more advice on this front, as I've not had the need to use this myself yet.

belugabob
Thanks for explaining it!
Scott
A: 

Hello,

Ignoring the fact your elements should have unique ID attributes, there's one thing to always keep in mind: when you bind a function to an event -- for example $(selector).bind('click', function) or $(selector).click(function) -- only the elements in the DOM that match the selector at that specific moment in time will behave as you expect. If you add more elements that match the selector at a later time, these won't magically get associated with the desired behavior.

This is one of the reasons the live() jQuery function exists, and I encourage you to take a look. An alternative approach is to manually bind your desired function to the elements you add to the DOM (like Felix showed you).

Dan