0

I'm using HTML, CSS and jQuery to build a shopping list in which items are dynamically added to the list through an <input> field. It's still very much work in progress but here is what it looks like now to get an idea: http://lucymac.github.io/shopping-list/

The list is called ul.list-items and it has 2 types of items: li.pending and li.done. I've included some static items to show what it is meant to look like: 2 'pending' items ("eggs" and "bacon" in black font), and one 'done' item ("baked beans" in grey font, strikethrough).

When the user hovers on one of these, a green tick span.tick appears for 'pending' items, or a red cross span.delete for 'done' items. I've achieved this through using the .hover() method in jQuery. However, this does not work for dynamically added items: items added through the input field don't get a green tick when hovered on.

I've researched this rather extensively and several sources (incl. this one) advise using .on() rather than .hover() but I must not be getting the syntax right because it's still not working.

Could you help?? I know many people have asked questions about dynamic elements and the .on() method but I really can't make it work and I really think this is not a duplicate as none of the existing questions/answers have helped me this far. I'm a beginner so I appreciate this may be because I don't understand all the other cases brought up in other questions, but I have hit a wall.

jQuery code to show green tick span.tick on hover for 'pending' items li.pending:

1st attempt: the following only works on static items, doesn't work on items added dynamically

$("li.pending")
            .hover(
                function() {
                $(this).append($('<span class="tick"> </span>'));
            }, function() {
                $(this).find('span:last').remove();
            })

2nd attempt: trying other option with .on() so it works for dynamically-added items but this doesn't work at all

$(document)
            .on("hover", "li.pending", function() {
                $("li.pending").append('<span class="tick"> </span>');
            }, function() {
                $("li.pending").find('span:last').remove();
            })

Many thanks in advance for your help :)

Lucy Mac
  • 71
  • 6

1 Answers1

1

You should use mouseenter and mouseleave event

$(document).on("mouseenter", "li.pending", function() {
                $(this).append('<span class="tick"> </span>');
            }).on("mouseleave", "li.pending", function() {
                $(this).find('span.tick').remove();
            });

As .hover() is shorthand for:

$( selector ).mouseenter( handlerIn ).mouseleave( handlerOut );


Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the event binding call.

You need to use Event Delegation using .on() delegated-events approach for dynamically created elements.

i.e.

$(document).on('event','selector',callback_function)

In place of document you should use closest static container for better performance.

The delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, we can use delegated events to bind the click event to dynamically created elements and also to avoid the need to frequently attach and remove event handlers.

Satpal
  • 132,252
  • 13
  • 159
  • 168
  • Thanks @Satpal. I just thought if it was 'shorthand' it meant I could use it just the same? Why would it have a different result from the 'long' version? – Lucy Mac Mar 31 '15 at 13:14