{# Master Feature Loader - Manages all optional features efficiently #} {# Usage: {% include "../../includes/features/feature-loader.html" %} #} {# Features can be enabled via: 1. Template variables: {% set enable_code_highlighting = true %} 2. Module fields: {{ module.features.code_highlighting }} 3. Page meta: {{ content.meta_description contains "code-highlight" }} 4. Auto-detection based on content #} {# Auto-detect features if not explicitly set #} {% set auto_detect = auto_detect|default(true) %} {% if auto_detect %} {# Auto-detect code highlighting need #} {% if not enable_code_highlighting is defined %} {% set enable_code_highlighting = false %} {% if content.post_body %} {% if '
// Feature detection and lazy loading manager
(function() {
'use strict';
// Track loaded features to prevent duplicates
window.loadedFeatures = window.loadedFeatures || new Set();
// Feature configuration
const features = {
codeHighlighting: {
enabled: {{ enable_code_highlighting|lower }},
selectors: ['pre code', '.highlight-code', '[class*="language-"]'],
loaded: false
},
qrCode: {
enabled: {{ enable_qr_code|lower }},
selectors: ['.qr-code-container', '[data-qr-content]', '#qr-generator-widget'],
loaded: false
},
charts: {
enabled: {{ enable_charts|lower }},
selectors: ['.chart-container', 'canvas[data-chart]', '[data-chart-config]', '#chart-builder'],
loaded: false
},
pdfExport: {
enabled: {{ enable_pdf_export|lower }},
selectors: ['.generate-pdf', '[data-pdf-export]', '#pdf-toolbar'],
loaded: false
},
accordionEnhancement: {
enabled: {{ enable_accordion_js|lower }},
selectors: ['[data-exclusive]', '.accordion-group[data-exclusive]'],
loaded: false,
script: '{{ get_asset_url("../../js/components/accordion.js") }}'
}
};
// Check if any feature elements exist on the page
function checkForFeatures() {
Object.keys(features).forEach(featureName => {
const feature = features[featureName];
if (!feature.enabled || feature.loaded) return;
const hasElements = feature.selectors.some(selector =>
document.querySelector(selector) !== null
);
if (hasElements) {
loadFeature(featureName);
}
});
}
// Load a specific feature
function loadFeature(featureName) {
if (window.loadedFeatures.has(featureName)) return;
window.loadedFeatures.add(featureName);
features[featureName].loaded = true;
// Dispatch custom event for feature loading
window.dispatchEvent(new CustomEvent('featureLoading', {
detail: { feature: featureName }
}));
// Load accordion enhancement script if needed
if (featureName === 'accordionEnhancement' && features.accordionEnhancement.script) {
const script = document.createElement('script');
script.src = features.accordionEnhancement.script;
script.async = true;
script.onload = function() {
console.log('Accordion enhancement loaded');
};
document.body.appendChild(script);
}
console.log(`Loading feature: ${featureName}`);
}
// Monitor DOM changes for dynamically added content
if ('MutationObserver' in window) {
const observer = new MutationObserver((mutations) => {
let shouldCheck = false;
mutations.forEach(mutation => {
if (mutation.addedNodes.length > 0) {
shouldCheck = true;
}
});
if (shouldCheck) {
// Debounce the check
clearTimeout(window.featureCheckTimeout);
window.featureCheckTimeout = setTimeout(checkForFeatures, 100);
}
});
// Start observing once DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
observer.observe(document.body, {
childList: true,
subtree: true
});
checkForFeatures();
});
} else {
observer.observe(document.body, {
childList: true,
subtree: true
});
checkForFeatures();
}
} else {
// Fallback for older browsers
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', checkForFeatures);
} else {
checkForFeatures();
}
}
// Public API for manually loading features
window.loadFeature = loadFeature;
window.features = features;
})();
{# Include individual feature files based on what's enabled #}
{# These files contain their own lazy loading logic #}
{% if enable_code_highlighting %}
{% include "./code-highlighting.html" %}
{% endif %}
{% if enable_qr_code %}
{% include "./qr-code.html" %}
{% endif %}
{% if enable_charts %}
{% include "./charts.html" %}
{% endif %}
{% if enable_pdf_export %}
{% include "./pdf-generator.html" %}
{% endif %}
{# Feature status indicator for debugging (only in preview mode) #}
{% if request.query_dict.hs_preview %}
Features:
Code: {{ enable_code_highlighting|default(false) ? '✓' : '✗' }}
QR: {{ enable_qr_code|default(false) ? '✓' : '✗' }}
Charts: {{ enable_charts|default(false) ? '✓' : '✗' }}
PDF: {{ enable_pdf_export|default(false) ? '✓' : '✗' }}
Accordion JS: {{ enable_accordion_js|default(false) ? '✓' : '✗' }}
{% endif %}