jQuery не работает после загрузки контента через AJAX

На этой странице у меня есть всплывающее окно jQuery и уменьшенные изображения с изменяемыми размерами. Если я наведу курсор мыши на миниатюры, изображения изменят размеры идеально. Кроме того, когда я нажимаю на большую желтую кнопку ТВ "QuickBook TV" в нижнем колонтитуле, всплывающее окно отображается идеально, как я хочу.

Однако, когда я нажимаю кнопки "Далее" или "Предыдущий", AJAX используется для загрузки нового содержимого, и мой jQuery больше не работает для всплывающих окон или изображений в виде миниатюр. Я искал несколько форумов в поисках информации по этой проблеме, но из-за ограниченных знаний jQuery я не смог понять, что мне нужно делать.

Ниже приводится всплывающее окно JQuery

$(document).ready(function() {

        $(".iframe").colorbox({ iframe: true, width: "1000px", height: "500px" });
        $(".inline").colorbox({ inline: true, width: "50%" });
        $(".callbacks").colorbox({
            onOpen: function() { alert('onOpen: colorbox is about to open'); },
            onLoad: function() { alert('onLoad: colorbox has started to load the targeted content'); },
            onComplete: function() { alert('onComplete: colorbox has displayed the loaded content'); },
            onCleanup: function() { alert('onCleanup: colorbox has begun the close process'); },
            onClosed: function() { alert('onClosed: colorbox has completely closed'); }
        });

        //Example of preserving a JavaScript event for inline calls.
        $("#click").click(function() {
            $('#click').css({ "background-color": "#f00", "color": "#fff", "cursor": "inherit" }).text("Open this window again and this message will still be here.");
            return false;
        });
    });

И это эскизы JQuery

$(function() {

var xwidth = ($('.image-popout img').width())/1;
var xheight = ($('.image-popout img').height())/1;

$('.image-popout img').css(
        {'width': xwidth, 'height': xheight}
); //By default set the width and height of the image.

$('.image-popout img').parent().css(
        {'width': xwidth, 'height': xheight}
);

$('.image-popout img').hover(
    function() {
        $(this).stop().animate( {
            width   : xwidth * 3,
            height  : xheight * 3,
            margin : -(xwidth/3)
            }, 200
        ); //END FUNCTION

        $(this).addClass('image-popout-shadow');

    }, //END HOVER IN
    function() {
        $(this).stop().animate( {
            width   : xwidth,
            height  : xheight,
            margin : 0
            }, 200, function() {
                $(this).removeClass('image-popout-shadow');
    }); //END FUNCTION

    }
);

});

6 ответов

Решение

Селекторы jQuery выбирают подходящие элементы, которые существуют в DOM при выполнении кода, и не обновляются динамически. Когда вы вызываете функцию, такую ​​как .hover() чтобы добавить обработчик событий, он добавляет их только к этим элементам. Когда вы делаете вызов AJAX и заменяете часть своей страницы, вы удаляете эти элементы с привязанными к ним обработчиками событий и заменяете их новыми элементами. Даже если эти элементы теперь будут соответствовать этому селектору, они не будут привязаны к обработчику событий, потому что код для выполнения уже выполнен.

Обработчики событий

Специально для обработчиков событий (т.е. .click()) вы можете использовать делегирование событий, чтобы обойти это. Основной принцип заключается в том, что вы привязываете обработчик событий к статическому (существует, когда страница загружается, никогда не заменяется) элементу, который будет содержать весь ваш динамический (загруженный AJAX) контент. Вы можете прочитать больше о делегировании событий в документации по jQuery.

Для тебя click обработчик события, обновленный код будет выглядеть так:

$(document).on('click', "#click", function () {
    $('#click').css({
        "background-color": "#f00",
        "color": "#fff",
        "cursor": "inherit"
    }).text("Open this window again and this message will still be here.");
    return false;
});

Это связывало бы обработчик событий со всем документом (поэтому никогда не будет удален, пока страница не будет выгружена), который будет реагировать на click события на элементе с id собственностью click, В идеале вы должны использовать что-то ближе к вашим динамическим элементам в DOM (возможно, <div> на вашей странице, которая всегда есть и содержит все содержимое вашей страницы), так как это немного повысит эффективность.

Проблема возникает, когда вам нужно справиться .hover(), хоть. Там нет фактического hover событие в JavaScript, jQuery просто предоставляет эту функцию в качестве удобного сокращения для привязки обработчиков событий к mouseenter а также mouseleave События. Однако вы можете использовать делегирование событий:

$(document).on({
    mouseenter: function () {
        $(this).stop().animate({
            width: xwidth * 3,
            height: xheight * 3,
            margin: -(xwidth / 3)
        }, 200); //END FUNCTION

        $(this).addClass('image-popout-shadow');
    },
    mouseleave: function () {
        $(this).stop().animate({
            width: xwidth,
            height: xheight,
            margin: 0
        }, 200, function () {
            $(this).removeClass('image-popout-shadow');
        }); //END FUNCTION

    }
}, '.image-popout img');

плагины jQuery

Это охватывает привязки обработчиков событий. Однако это еще не все, что вы делаете. Вы также инициализируете плагин jQuery (colorbox), и нет возможности делегировать их элементам. Вам придется просто снова вызывать эти строки, когда вы загрузите свой AJAX-контент; самый простой способ - переместить их в отдельную именованную функцию, которую затем можно вызывать в обоих местах (при загрузке страницы и в ваших AJAX-запросах). success Перезвоните):

function initialiseColorbox() {
    $(".iframe").colorbox({
        iframe: true,
        width: "1000px",
        height: "500px"
    });
    $(".inline").colorbox({
        inline: true,
        width: "50%"
    });
    $(".callbacks").colorbox({
        onOpen: function () {
            alert('onOpen: colorbox is about to open');
        },
        onLoad: function () {
            alert('onLoad: colorbox has started to load the targeted content');
        },
        onComplete: function () {
            alert('onComplete: colorbox has displayed the loaded content');
        },
        onCleanup: function () {
            alert('onCleanup: colorbox has begun the close process');
        },
        onClosed: function () {
            alert('onClosed: colorbox has completely closed');
        }
    });
}

Была такая же проблема, прежде чем я смог найти решение, которое работало для меня. Так что если кто-то в будущем сможет сделать ему попытку и сообщить мне, правильно ли это, так как все решения, которые я смог найти, были немного сложнее, чем это.

Как сказал Тамер Дургун, мы также поместим ваш код в ajaxStop, поэтому ваш код будет восстанавливаться каждый раз, когда любое событие завершается ajax.

$( document ).ajaxStop(function() {

//your code

}

Работал для меня:)

            // EXAMPLE FOR JQUERY AJAX COMPLETE FUNC.
            $.ajax({
            // get a form template first
            url: "../FPFU/templates/yeni-workout-form.html",
            type: "get",
            success: function(data){
            // insert this template into your container
                $(".content").html(data);
            },
            error: function(){
                alert_fail.removeClass("gizle");
                alert_fail.addClass("goster");
                alert_fail.html("Template getirilemedi.");
            },
            complete: function(){
                // after all done you can manupulate here your new content
                // tinymce yükleme
                tinymce.init({
                    selector: '#workout-aciklama'
                });
            }

Ваши обработчики событий теряются при замене контента. Когда вы установите hover события, jQuery устанавливает их на события на странице в настоящее время. Поэтому, когда вы заменяете их на ajax, события не связываются с этими элементами, потому что они являются новыми.

Чтобы это исправить, вы можете либо снова вызвать функцию, которая их связывает, либо вместо этого установить обработчик событий в документе, как в этом ответе, используя $(document).on

Таким образом, событие устанавливается в документе, и любые новые элементы будут вызывать событие.

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

этот $(selector).click(function(e){}

стать этим после использования метода делегата ()

$( "body" ).delegate( "selector", "click", function(e) {}

Надеюсь, это поможет;)

Я опаздываю на вечеринку, но я бы совмещал два ответа. Что сработало для моих конкретных потребностей, так это включение ajaxstop в полный

complete: function () {
     $( document ).ajaxStop(function() {
         //now that all have been added to the dom, you can put in some code for your needs.
         console.log($(".subareafilterActive").get().length)

     })
}

Вы можете использовать функцию завершения jQuery ajax после получения формы данных где-то, она будет видеть обновленные элементы после завершения ajax

Просто альтернатива.

$(window).on('load', _ => {
    // some jQuery code ..
})

Это связывает любой делегированный обработчик с окном. Он будет срабатывать после полной загрузки окна, включая всю графику / включает / хуки / запросы, а не только DOM.

$(document).ready(_ => ...сохраняет события, которые будут запускаться только после того, как будет готова модель DOM, что не применяется к динамически загружаемому контенту с помощью AJAX. Либо вы можете запустить функцию, либо любое событие, когда определенный элемент полностью загружен, определив его как @Anthony Grist, объясненный в его ответе, или привязать событие загрузки к окну, как показано выше.

https://api.jquery.com/load-event/
https://api.jquery.com/on/

Это сработало для меня,

вместо того:

$(document).ready(function(){
//code
});

Я сделал:

$(document).on('mouseenter', function(){
//code
});
Другие вопросы по тегам