I wrote a little factory to dynamically load assets in angular resolve. Is it well structured and can it be made prettier?
app.factory('loadAssets', function ($q) {
var jsPath = "scripts/",
cssPath = "css/",
imagesPath = "images/",
head = document.getElementsByTagName("head")[0]; // define starting paths for each file tile
return {
startLoad: function (url) {
var fileType = url.split(".");
fileType = fileType[fileType.length - 1]; // we must get (length - 1) because filenames like jquery.min.js
/* prevent duplicate loading -
check if url exist in already loaded assets
1. If asset exist, return true and quit.
2. If asset doesn't exist - add it.
3. If loadedAssets is undefined (first time you load something) - create this array.
*/
if (this.loadedAssets == undefined || this.loadedAssets == null) {
this.loadedAssets = [];
}
if (this.loadedAssets.indexOf(url) >= 0) { // note that indexOf supported only in ie9+ , add fallback if you want to support legacy browsers.
return true;
} else {
this.loadedAssets.push.apply(this.loadedAssets, [url]);
// load js files
if (fileType == "js") {
var jsFile = document.createElement("script");
jsFile.src = jsPath + url;
head.appendChild(jsFile);
var waitforload = $q.defer();
jsFile.onload = function () {
waitforload.resolve(jsFile);
};
jsFile.onerror = function (e) {
waitforload.reject(e);
console.log("Could not load " + jsFile.src);
};
return waitforload.promise;
}
// load css files
if (fileType == "css") {
var cssFile = document.createElement("link");
cssFile.setAttribute("rel", "stylesheet");
cssFile.setAttribute("type", "text/css");
cssFile.setAttribute("href", cssPath+url);
head.appendChild(cssFile);
}
// load images
if (fileType == "jpg" || fileType == "jpeg" || fileType == "png" || fileType == "gif") {
var waitforload = $q.defer();
var image = new Image();
image.src = imagesPath + url;
image.onload = function () {
waitforload.resolve(image);
};
image.onerror = function (e) {
waitforload.reject(e);
console.log("Could not load " + image.src);
};
return waitforload.promise;
}
}
},
loadedAssets: this.loadedAssets
}
});
USAGE
app.config(function ($routeProvider, $controllerProvider) {
$routeProvider.when('/somepath', {
resolve: {
load: function ($q, loadAssets) {
files = ['somePathController.js', 'somePath.css', 'somePath.jpg'];
return $q.all(files.map(loadAssets.startLoad));
}
},
templateUrl: 'views/somePath.html'
}).otherwise({
redirectTo: '/somepath'
});
app.controllerProvider = $controllerProvider.register; // create reference to $controllerProvider.register - so we can dynamically register controllers oustide the app.config
});
somePathController.js
app.controllerProvider('somePathCtrl', function () {
// controller functionality here
});
somePath.html (view)
<div ng-controller="somePathCtrl">HTML HERE.</div>