Как правильно уничтожить (destroy) экземпляр Fancybox после AJAX-загрузки в Bitrix?
Я пытаюсь перезапустить Fancybox после AJAX-загрузки в компоненте catalog.element Bitrix. Код для слайдера glide.js работает корректно:
let fancyboxInstance = null;
document.addEventListener('DOMContentLoaded', function() {
createOrUpdateFancybox();
});
BX.addCustomEvent("onAjaxSuccess", function() {
createOrUpdateFancybox();
});
function createOrUpdateFancybox() {
const slElements = document.querySelectorAll('[data-fancybox]');
const slExist = slElements.length > 0;
if (!slExist) return;
if (fancyboxInstance) {
fancyboxInstance.destroy();
}
fancyboxInstance = Fancybox.bind("[data-fancybox]");
}
Однако Bitrix выводит в консоли ‘processing’ и ошибку: TypeError: fancyboxInstance.destroy is not a function. Метод close() также не работает. Как правильно уничтожить предыдущий экземпляр Fancybox перед созданием нового после AJAX-загрузки?
Для правильного уничтожения экземпляра Fancybox после AJAX-загрузки в Bitrix необходимо использовать статический метод destroy() вместо вызова его на экземпляре. Ваша проблема заключается в том, что метод destroy() является статическим методом объекта Fancybox, а не методом экземпляра.
Содержание
- Основная проблема и решение
- Правильный код для Bitrix
- Различия между версиями Fancybox
- Полная реализация с обработкой ошибок
- Альтернативные методы уничтожения
- Интеграция с Bitrix AJAX
- Заключение
Основная проблема и решение
Ошибка TypeError: fancyboxInstance.destroy is not a function возникает потому, что в вашем коде вы пытаетесь вызвать метод destroy() на экземпляре Fancybox, в то время как этот метод является статическим. Согласно документации Fancybox, правильный вызов:
// Закрываем все экземпляры и отвязываем все события
$.fancybox.destroy();
или для современных версий:
Fancybox.destroy();
Правильный код для Bitrix
Вот исправленная версия вашего кода:
let fancyboxInstance = null;
document.addEventListener('DOMContentLoaded', function() {
createOrUpdateFancybox();
});
BX.addCustomEvent("onAjaxSuccess", function() {
createOrUpdateFancybox();
});
function createOrUpdateFancybox() {
const slElements = document.querySelectorAll('[data-fancybox]');
const slExist = slElements.length > 0;
if (!slExist) return;
// Уничтожаем все существующие экземпляры Fancybox
if (typeof Fancybox !== 'undefined') {
Fancybox.destroy();
}
// Или для старых версий:
// if (typeof $.fancybox !== 'undefined') {
// $.fancybox.destroy();
// }
// Создаем новый экземпляр
fancyboxInstance = Fancybox.bind("[data-fancybox]");
}
Различия между версиями Fancybox
Важно учитывать, что разные версии Fancybox имеют разные API:
- Fancybox 2: Не включает методы
destroyилиupdateсогласно StackOverflow - Fancybox 3+: Включает статический метод
destroy()как показано в документации - Fancybox 4: Современная версия с полным API
// Для Fancybox 3/4
Fancybox.destroy();
// Для старых версий (альтернатива)
$(document).unbind('click.fb-start');
$('[data-fancybox]').unbind('click.fb');
Полная реализация с обработкой ошибок
let fancyboxInstance = null;
document.addEventListener('DOMContentLoaded', function() {
initFancybox();
});
BX.addCustomEvent("onAjaxSuccess", function() {
initFancybox();
});
function initFancybox() {
try {
const fancyboxElements = document.querySelectorAll('[data-fancybox]');
if (fancyboxElements.length === 0) {
return;
}
// Уничтожаем предыдущие экземпляры
destroyFancybox();
// Инициализируем новый экземпляр
fancyboxInstance = Fancybox.bind("[data-fancybox]", {
// ваши опции
});
} catch (error) {
console.error('Ошибка инициализации Fancybox:', error);
}
}
function destroyFancybox() {
try {
// Проверяем доступность Fancybox
if (typeof Fancybox !== 'undefined') {
Fancybox.destroy();
} else if (typeof $.fancybox !== 'undefined') {
// Для старых версий
$.fancybox.close();
$(document).unbind('click.fb-start');
$('[data-fancybox]').unbind('click.fb');
}
// Сбрасываем переменную экземпляра
fancyboxInstance = null;
} catch (error) {
console.error('Ошибка уничтожения Fancybox:', error);
}
}
Альтернативные методы уничтожения
Если метод destroy() недоступен в вашей версии Fancybox, можно использовать альтернативные подходы:
1. Отвязка событий
function destroyFancyboxLegacy() {
// Отвязываем все Fancybox события
$(document).unbind('click.fb-start');
$(document).unbind('click.fb');
$(document).unbind('click.fb-close');
// Отвязываем события с элементов
$('[data-fancybox]').unbind('click.fb');
// Закрываем все открытые экземпляры
if (typeof $.fancybox !== 'undefined') {
$.fancybox.close();
}
}
2. Установка опции live: false
При инициализации Fancybox добавьте опцию live: false:
fancyboxInstance = Fancybox.bind("[data-fancybox]", {
live: false // Это предотвращает автоматическую привязку к новым элементам
});
Как указано в StackOverflow, “Unbinding the .fancybox links only works if the live parameter is set to false.”
Интеграция с Bitrix AJAX
При работе с Bitrix AJAX важно учитывать особенности обработки событий:
document.addEventListener('DOMContentLoaded', function() {
initFancybox();
});
// Обработка успешного AJAX-запроса
BX.addCustomEvent("onAjaxSuccess", function() {
// Небольшая задержка для гарантии, что DOM обновлен
setTimeout(initFancybox, 100);
});
// Обработка ошибок AJAX
BX.addCustomEvent("onAjaxFailure", function() {
destroyFancybox();
});
function initFancybox() {
const fancyboxElements = document.querySelectorAll('[data-fancybox]');
if (fancyboxElements.length === 0) {
return;
}
// Проверяем, что контент действительно загружен
let hasValidContent = false;
fancyboxElements.forEach(element => {
if (element.getAttribute('href') && element.getAttribute('href').trim() !== '') {
hasValidContent = true;
}
});
if (!hasValidContent) {
return;
}
destroyFancybox();
try {
fancyboxInstance = Fancybox.bind("[data-fancybox]", {
// Опции для Bitrix
touch: false,
// другие опции
});
} catch (error) {
console.error('Ошибка при инициализации Fancybox в Bitrix:', error);
}
}
Заключение
- Используйте статический метод
Fancybox.destroy()или$.fancybox.destroy()вместо вызова на экземпляре - Проверяйте версию Fancybox и используйте соответствующий API
- Обрабатывайте ошибки при инициализации и уничтожении
- Используйте задержку при обработке событий Bitrix AJAX для гарантии обновления DOM
- Рассмотрите альтернативные методы для старых версий Fancybox отвязки событий
Правильная реализация позволит избежать конфликтов при перезагрузке контента через AJAX в Bitrix и обеспечит корректную работу всплывающих окон.