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
});