Функция jQuery click vs inline onclick

Я пытаюсь реорганизовать свой код и сделать его более ненавязчивым.

В основном, есть ссылка для выполнения действия. Если вы нажмете на ссылку, действие выполняется через ajax (здесь код ajax отсутствует здесь), а текст заменяется другим текстом, предлагая пользователю возможность отменить действие. Если пользователь нажимает на ссылку "Отменить", ajax восстанавливает предыдущую ситуацию и текст, предлагающий пользователю выполнить действие, которое он показал снова.

Я сделал более простую версию моей проблемы в одном html файле (код ниже). Есть два абзаца. Если вы нажмете на ссылку первого абзаца, в которой используется встроенный вызов onclick, код работает так, как ожидалось. Но если вы нажмете на ссылку второго абзаца, в которой используется функция jQuery onclick, ссылка Undo не работает, и я не могу понять, почему.

Любая помощь? Большое спасибо!

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
    <title></title>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
    <script>
        $(function() {      
            $(".add2").click(function(){
                var placeId = $(this).parents(".place").attr("id");
                $("#" + placeId + " .add2").remove();
                $("#" + placeId + " .actions").append("<span class=\"added\">Added!</span> <a class=\"undoadd2\" href=\"#\">Undo</a>");
                return false;
            })
            $(".undoadd2").click(function(){
                var placeId = $(this).parents(".place").attr("id");
                $("#" + placeId + " .actions").find("span.added, a.add2").remove();
                $("#" + placeId + " .actions").append("<a class='add2' onclick='copyPlace(\"" + placeId + "\"); return false;' href='#'>Add place</a>");
                return false;
            })
        });

        function addPlace(placeId){
            $("#" + placeId + " .add").remove();
            $("#" + placeId + " .actions").append("<span class=\"added\">Added!</span> <a class=\"undoadd\" href=\"#\" onclick=\"undoAddPlace('" + placeId + "'); return false;\">Undo</a>");
            return false;
        }

        function undoAddPlace(placeId){
            $("#" + placeId + " .actions").find("span.added, a.undoadd").remove();
            $("#" + placeId + " .actions").append("<a class='add' onclick='addPlace(\"" + placeId + "\"); return false;' href='#'>Add place</a>");
            return false;
        }
    </script>

</head>
<body id="home">
    <div class="place" id="3435910">
        <p class="actions"><a href="#" onclick="addPlace('3435910'); return false;" class="add">Add place</a></p>
    </div>

    <div class="place" id="3435912">
        <p class="actions"><a href="#" class="add2">Add place</a></p>
    </div>
</body>
</html>

Ответ 1

Поскольку вы динамически добавляете новые пунктов в DOM, вам придется снова зарегистрируйте обработчик кликов новые элементы.

Вы можете использовать .live для этого.


Обновление

Поскольку jQuery 1.7, метод .on является предпочтительным способом для этого.

Так как jQuery 1.9 был удален метод .live.

Ответ 2

Просто демонстрируя использование .end() для более жидкого решения:

$(function() {          
    $(".add2").click(function(){
            return $(this).parents(".place")
                .find(".add2")
                    .hide()
                .end()
                .find(".actions")
                    .append("<span class=\"added\">Added!</span> <a class=\"undoadd2\" href=\"#\">Undo</a>");
    });
    $('.undoadd2').live('click', function(){ 
            return $(this).parents(".place")
                .find(".actions")
                    .find("span.added, a.undoadd2")
                        .remove()
                    .end()
                .end()
                .find(".add2")
                    .show();
    });
});

Ответ 3

Поскольку вы динамически добавляете новые элементы в DOM, вам придется снова регистрировать обработчик click на новых элементах. jQuery устанавливает обработчик при вызове $('...').click(...).

Ответ 4

Вау!! Спасибо всем вам!

Я прочитал о реальном событии, и последний рабочий код:

$(function() {      
            $(".add2").click(function(){
                var placeId = $(this).parents(".place").attr("id");
                $("#" + placeId + " .add2").hide();
                $("#" + placeId + " .actions").append("<span class=\"added\">Added!</span> <a class=\"undoadd2\" href=\"#\">Undo</a>");
                return false;
            })
            $('.undoadd2').live('click', function(){ 
                var placeId = $(this).parents(".place").attr("id");
                $("#" + placeId + " .actions").find("span.added, a.undoadd2").remove();
                $("#" + placeId + " .add2").show();
                return false;
            });

Раньше я использовал remove() для удаления текста, который предлагает выполнить действие. Я изменил его для hide/show, поэтому мне не нужно использовать live также в первой функции.

Еще раз спасибо!

Ответ 5

Обработчик кликов не подбирается, когда вы добавляете элемент в DOM. Попробуйте использовать jQuery для регистрации обработчика кликов, изменив строки (строки), которые выглядят следующим образом:

$("#" + placeId + " .actions").append("<span class=\"added\">Added!</span> <a class=\"undoadd\" href=\"#\" onclick=\"undoAddPlace('" + placeId + "'); return false;\">Undo</a>")

Для

$("#" + placeId + " .actions").append("<span class=\"added\">Added!</span> <a class=\"undoadd\" href=\"#\" >Undo</a>");
$('#' + placeId + " .actions").find("span:last").find("a").click( function() {
    undoAddPlace( placeId );
    return false;
});

Возможно, вы сможете сделать это проще, но похоже, что вы можете добавить несколько абзацев в абзац, чтобы я стал консервативным. Возможно, вы также могли бы подключить добавление, но я подумал, что повторный выбор стал более ясным.