JavaScript indlæs ressourcer dynamisk

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 😉

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *

This site uses Akismet to reduce spam. Learn how your comment data is processed.