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 😉