How to properly destroy a Fancybox instance after AJAX loading in Bitrix?
I’m trying to restart Fancybox after AJAX loading in the Bitrix catalog.element component. The code for the glide.js slider works correctly:
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]");
}
However, Bitrix outputs ‘processing’ to the console and gives an error: TypeError: fancyboxInstance.destroy is not a function. The close() method also doesn’t work. How do I properly destroy the previous Fancybox instance before creating a new one after AJAX loading?
Properly Destroying Fancybox Instances After AJAX Loading in Bitrix
To properly destroy a Fancybox instance after AJAX loading in Bitrix, you need to use the static method destroy() instead of calling it on the instance. Your problem is that the destroy() method is a static method of the Fancybox object, not an instance method.
Table of Contents
- Main Problem and Solution
- Correct Code for Bitrix
- Differences Between Fancybox Versions
- Full Implementation with Error Handling
- Alternative Destruction Methods
- Integration with Bitrix AJAX
- Conclusion
Main Problem and Solution
The error TypeError: fancyboxInstance.destroy is not a function occurs because you’re trying to call the destroy() method on a Fancybox instance when it’s actually a static method. According to Fancybox documentation, the correct call is:
// Close all instances and unbind all events
$.fancybox.destroy();
or for modern versions:
Fancybox.destroy();
Correct Code for Bitrix
Here’s the fixed version of your code:
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;
// Destroy all existing Fancybox instances
if (typeof Fancybox !== 'undefined') {
Fancybox.destroy();
}
// Or for older versions:
// if (typeof $.fancybox !== 'undefined') {
// $.fancybox.destroy();
// }
// Create a new instance
fancyboxInstance = Fancybox.bind("[data-fancybox]");
}
Differences Between Fancybox Versions
It’s important to note that different Fancybox versions have different APIs:
- Fancybox 2: Doesn’t include
destroyorupdatemethods according to StackOverflow - Fancybox 3+: Includes the static
destroy()method as shown in the documentation - Fancybox 4: Modern version with full API
// For Fancybox 3/4
Fancybox.destroy();
// For older versions (alternative)
$(document).unbind('click.fb-start');
$('[data-fancybox]').unbind('click.fb');
Full Implementation with Error Handling
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;
}
// Destroy previous instances
destroyFancybox();
// Initialize a new instance
fancyboxInstance = Fancybox.bind("[data-fancybox]", {
// your options
});
} catch (error) {
console.error('Fancybox initialization error:', error);
}
}
function destroyFancybox() {
try {
// Check if Fancybox is available
if (typeof Fancybox !== 'undefined') {
Fancybox.destroy();
} else if (typeof $.fancybox !== 'undefined') {
// For older versions
$.fancybox.close();
$(document).unbind('click.fb-start');
$('[data-fancybox]').unbind('click.fb');
}
// Reset the instance variable
fancyboxInstance = null;
} catch (error) {
console.error('Fancybox destruction error:', error);
}
}
Alternative Destruction Methods
If the destroy() method isn’t available in your Fancybox version, you can use alternative approaches:
1. Event Unbinding
function destroyFancyboxLegacy() {
// Unbind all Fancybox events
$(document).unbind('click.fb-start');
$(document).unbind('click.fb');
$(document).unbind('click.fb-close');
// Unbind events from elements
$('[data-fancybox]').unbind('click.fb');
// Close all open instances
if (typeof $.fancybox !== 'undefined') {
$.fancybox.close();
}
}
2. Setting the live: false Option
When initializing Fancybox, add the live: false option:
fancyboxInstance = Fancybox.bind("[data-fancybox]", {
live: false // This prevents automatic binding to new elements
});
As noted on StackOverflow, “Unbinding the .fancybox links only works if the live parameter is set to false.”
Integration with Bitrix AJAX
When working with Bitrix AJAX, it’s important to consider event handling specifics:
document.addEventListener('DOMContentLoaded', function() {
initFancybox();
});
// Handle successful AJAX requests
BX.addCustomEvent("onAjaxSuccess", function() {
// Small delay to ensure DOM is updated
setTimeout(initFancybox, 100);
});
// Handle AJAX errors
BX.addCustomEvent("onAjaxFailure", function() {
destroyFancybox();
});
function initFancybox() {
const fancyboxElements = document.querySelectorAll('[data-fancybox]');
if (fancyboxElements.length === 0) {
return;
}
// Check that content is actually loaded
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]", {
// Options for Bitrix
touch: false,
// other options
});
} catch (error) {
console.error('Error initializing Fancybox in Bitrix:', error);
}
}
Conclusion
- Use the static method
Fancybox.destroy()or$.fancybox.destroy()instead of calling it on an instance - Check the Fancybox version and use the appropriate API
- Handle errors during initialization and destruction
- Use a delay when handling Bitrix AJAX events to ensure DOM updates
- Consider alternative methods for older Fancybox versions involving event unbinding
Proper implementation will prevent conflicts when reloading content via AJAX in Bitrix and ensure popup windows work correctly.