Da jeg for nyligt sad og arbejdede på et projekt der involverede modals, manglede jeg en måde at kunne indlæse ressourcer på dynamisk med JavaScript, der samtidigt ville sørge for kun at indlæse dem én gang.
Det lykkedes mig ikke at finde noget der kunne klare den opgave, så jeg satte mig for selv at skrive det.
Løsningen blev to simple funktioner loadAsset()
og loadAssetDetectExisting()
.
loadAsset()
bruges til at indlæse en ressource, samt holde styr på hvilke ressourcer der er blevet indlæst.
loadAssetDetectExisting()
bruges til at opdage hvilke ressourcer der allerede er blevet indlæst via <script>
og <link>
tags.
Herunder de to funktioner loadAsset()
og loadAssetDetectExisting()
:
/** * Load an asset dynamically * @param string url * @param function callback * @return boolean */ function loadAsset(url, callback){ // Array for loaded assets loadAsset.loaded = loadAsset.loaded || []; // Check if asset has allready been loaded if (loadAsset.loaded.indexOf(url) != -1){ // Check if callback is supplied if (callback){ // Invoke the callback function callback(); } // Asset has allready been loaded, return true return true; } // JS if (url.indexOf('.js') != -1){ // Build element elm = document.createElement('script'); elm.setAttribute('type','text/javascript'); elm.setAttribute('src', url); // Check if callback is supplied if (callback){ // Add callback for when element is loaded elm.onload = callback; } // Append element to body document.getElementsByTagName('body')[0].appendChild(elm) // Add to array of loaded assets loadAsset.loaded.push(url); // Asset loaded, return true return true; } // CSS if (url.indexOf('.css') != -1){ // Build element elm = document.createElement('link'); elm.setAttribute('rel', 'stylesheet'); elm.setAttribute('type', 'text/css'); elm.setAttribute('href', url); // Check if callback is supplied if (callback){ // Add callback for when element is loaded elm.onload = callback; } // Append element to head document.getElementsByTagName('head')[0].appendChild(elm); // Add to array of loaded assets loadAsset.loaded.push(url); // Asset loaded, return true return true; } // Return false, unrecognized asset return false; } /** * Detect existing assets * @return boolean */ function loadAssetDetectExisting(){ // Array for loaded assets loadAsset.loaded = loadAsset.loaded || []; // Loop through script tags for (i = 0; i < document.getElementsByTagName('script').length; i++){ // Check if javascript if (document.getElementsByTagName('script')[i].type == 'text/javascript'){ // Add to loaded assets loadAsset.loaded.push(document.getElementsByTagName('script')[i].src); } } // Loop through link tags for (i = 0; i < document.getElementsByTagName('link').length; i++){ // Check if stylesheet if (document.getElementsByTagName('link')[i].type == 'text/css' || document.getElementsByTagName('link')[i].rel == 'stylesheet'){ // Add to loaded assets loadAsset.loaded.push(document.getElementsByTagName('link')[i].href); } } // Return true return true; }
Eksempler på brug af loadAsset()
funktionen:
// Load asset dynamically loadAsset('path/to/asset/file.css'); // Load asset dynamically, and provide a callback when loaded loadAsset('path/to/asset/file.js', function(){ alert('asset file loaded'); });
Eksempel på brug af loadAssetDetectExisting()
funktionen, her med assistance fra jQuery:
// Trigger detecting existing assets $(document).ready(function(){ loadAssetDetectExisting(); });
Kom endeligt med ris/ros og forslag til forbedringer af de to funktioner 😉