Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retain events for dynamically changing elements

The goal

A good and definitively way to recall functions after something happened.

The problem

I'm working with some functions that must to be recalled when something happens. A simple example is a button like Twitter's following button.

Until here, all good. But, I do not know how to recall. Actually, I've already tried to use $.getScript of jQuery, but it causes many requests to the server and I do not feel comfortable with this behavior.

To illustrate the problem, I made this jsFiddle. When you hover the button for the first time, its style changes. When you click on it and click again, the "hover behavior" disappears.

I really do not know how to proceed.

$.getScript it is the best solution for this?

Someone have any suggestion?

The code (if jsFiddle down)

The Knockout on the code is just an example and it is irrelevant. I want to do this with ajax calls and everything what is possible.

HTML:

<div class="container">
    <!-- ko if: isAdded -->
    <button class="btn primary" data-bind="click: add">Add Xbox 360</button>
    <!-- /ko -->

    <!-- ko ifnot: isAdded -->
    <button class="btn btn-success primary remove" data-bind="click: remove">Xbox 360 already added</button>
    <!-- /ko -->
</div>

JavaScript:

$("button.remove").hover(function() {
    $(this)
    .removeClass("btn-success")
    .addClass("btn-danger")
    .text("Click here to remove");
}, function() {
    $(this)
    .removeClass("btn-danger")
    .addClass("btn-success")
    .text("Xbox 360 already added");
});

ViewModel = function() {
    var self = this;

    self.isAdded = ko.observable(false);

    self.add = function(item) {
        item.isAdded(false);
    };

    self.remove = function(item) {
        item.isAdded(true);
    };
};

ko.applyBindings(new ViewModel());
like image 724
Guilherme Oderdenge Avatar asked Mar 24 '23 05:03

Guilherme Oderdenge


2 Answers

You are going to need to use delegated events, which will stay bound as you add/remove/modify elements on the page. See the documenation for jQuery's on() function for more information about event delegation.

Note that this means you will need to use the mouseenter and mouseleave events instead of the hover() convenience method (which is just a wrapper for attaching listeners for mouseenter and mouseleave)

$(document).on('mouseenter', "button.remove", function() {
    $(this)
    .removeClass("btn-success")
    .addClass("btn-danger")
    .text("Click here to remove");
}).on('mouseleave', 'button.remove', function() {
    $(this)
    .removeClass("btn-danger")
    .addClass("btn-success")
    .text("Xbox 360 already added");
});

Working Demo

like image 105
cfs Avatar answered Apr 02 '23 17:04

cfs


You need to use event delegation so the handler is bound for current and future elements:

$('.container').on('mouseenter', 'button.remove', function() {
    ...
}).on('mouseleave', 'button.remove', function() {
    ...
});

http://jsfiddle.net/2KUp8/5/

Read more about event delegation here.

like image 20
jbabey Avatar answered Apr 02 '23 17:04

jbabey