103 lines
No EOL
2.6 KiB
JavaScript
103 lines
No EOL
2.6 KiB
JavaScript
/**
|
|
* SVG Symbol Loader
|
|
* Loads external SVG symbols into the document, similar to CSS stylesheets
|
|
*/
|
|
class SymbolLoader {
|
|
constructor() {
|
|
this.loaded = new Set();
|
|
this.cache = new Map();
|
|
}
|
|
|
|
/**
|
|
* Load SVG symbols from an external file
|
|
* @param {string} url - Path to the SVG file containing symbols
|
|
* @param {string} containerId - Optional ID for the container element
|
|
* @returns {Promise<void>}
|
|
*/
|
|
async loadSymbols(url, containerId = 'svg-symbols') {
|
|
if (this.loaded.has(url)) {
|
|
return; // Already loaded
|
|
}
|
|
|
|
try {
|
|
// Check cache first
|
|
let svgContent = this.cache.get(url);
|
|
|
|
if (!svgContent) {
|
|
const response = await fetch(url);
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to load symbols from ${url}: ${response.status}`);
|
|
}
|
|
svgContent = await response.text();
|
|
this.cache.set(url, svgContent);
|
|
}
|
|
|
|
// Create or get container
|
|
let container = document.getElementById(containerId);
|
|
if (!container) {
|
|
container = document.createElement('div');
|
|
container.id = containerId;
|
|
container.style.display = 'none';
|
|
document.body.appendChild(container);
|
|
}
|
|
|
|
// Insert SVG content
|
|
container.innerHTML += svgContent;
|
|
this.loaded.add(url);
|
|
|
|
console.log(`✅ SVG symbols loaded from: ${url}`);
|
|
} catch (error) {
|
|
console.error(`❌ Failed to load SVG symbols from ${url}:`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Preload multiple symbol files
|
|
* @param {string[]} urls - Array of SVG file URLs
|
|
* @returns {Promise<void[]>}
|
|
*/
|
|
async preloadSymbols(urls) {
|
|
return Promise.all(urls.map(url => this.loadSymbols(url)));
|
|
}
|
|
|
|
/**
|
|
* Clear cache and loaded symbols
|
|
*/
|
|
clearCache() {
|
|
this.loaded.clear();
|
|
this.cache.clear();
|
|
}
|
|
|
|
/**
|
|
* Check if symbols from a URL are loaded
|
|
* @param {string} url - SVG file URL
|
|
* @returns {boolean}
|
|
*/
|
|
isLoaded(url) {
|
|
return this.loaded.has(url);
|
|
}
|
|
}
|
|
|
|
// Global instance
|
|
window.SymbolLoader = new SymbolLoader();
|
|
|
|
// Auto-load symbols on DOM ready
|
|
document.addEventListener('DOMContentLoaded', async () => {
|
|
// Auto-discover symbol files from data attributes
|
|
const elements = document.querySelectorAll('[data-symbol-src]');
|
|
const urls = [...new Set([...elements].map(el => el.dataset.symbolSrc))];
|
|
|
|
if (urls.length > 0) {
|
|
try {
|
|
await window.SymbolLoader.preloadSymbols(urls);
|
|
} catch (error) {
|
|
console.warn('Some symbol files failed to load:', error);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Export for module systems
|
|
if (typeof module !== 'undefined' && module.exports) {
|
|
module.exports = SymbolLoader;
|
|
} |