(angular => { 'use strict'; angular.module('oc.lazyLoad').config(function($provide) { $provide.decorator('$ocLazyLoad', function($delegate, $q) { /** * The function that loads new files * @param config * @param params * @returns {*} */ $delegate.filesLoader = function filesLoader(config, params = {}) { var cssFiles = [], templatesFiles = [], jsFiles = [], promises = [], cachePromise = null, filesCache = $delegate._getFilesCache(); $delegate.toggleWatch(true); // start watching angular.module calls angular.extend(params, config); var pushFile = function(path) { var file_type = null, m; if(angular.isObject(path)) { file_type = path.type; path = path.path; } cachePromise = filesCache.get(path); if(angular.isUndefined(cachePromise) || params.cache === false) { // always check for requirejs syntax just in case if((m = /^(css|less|html|htm|js)?(?=!)/.exec(path)) !== null) { // Detect file type using preceding type declaration (ala requireJS) file_type = m[1]; path = path.substr(m[1].length + 1, path.length); // Strip the type from the path } if(!file_type) { if((m = /[.](css|less|html|htm|js)?((\?|#).*)?$/.exec(path)) !== null) { // Detect file type via file extension file_type = m[1]; } else if(!$delegate.jsLoader.hasOwnProperty('ocLazyLoadLoader') && $delegate.jsLoader.hasOwnProperty('requirejs')) { // requirejs file_type = 'js'; } else { $delegate._$log.error(`File type could not be determined. ${ path }`); return; } } if((file_type === 'css' || file_type === 'less') && cssFiles.indexOf(path) === -1) { cssFiles.push(path); } else if((file_type === 'html' || file_type === 'htm') && templatesFiles.indexOf(path) === -1) { templatesFiles.push(path); } else if(file_type === 'js' || jsFiles.indexOf(path) === -1) { jsFiles.push(path); } else { $delegate._$log.error(`File type is not valid. ${ path }`); } } else if(cachePromise) { promises.push(cachePromise); } }; if(params.serie) { pushFile(params.files.shift()); } else { angular.forEach(params.files, path => { pushFile(path); }); } if(cssFiles.length > 0) { var cssDeferred = $q.defer(); $delegate.cssLoader(cssFiles, err => { if(angular.isDefined(err) && $delegate.cssLoader.hasOwnProperty('ocLazyLoadLoader')) { $delegate._$log.error(err); cssDeferred.reject(err); } else { cssDeferred.resolve(); } }, params); promises.push(cssDeferred.promise); } if(templatesFiles.length > 0) { var templatesDeferred = $q.defer(); $delegate.templatesLoader(templatesFiles, err => { if(angular.isDefined(err) && $delegate.templatesLoader.hasOwnProperty('ocLazyLoadLoader')) { $delegate._$log.error(err); templatesDeferred.reject(err); } else { templatesDeferred.resolve(); } }, params); promises.push(templatesDeferred.promise); } if(jsFiles.length > 0) { var jsDeferred = $q.defer(); $delegate.jsLoader(jsFiles, err => { if(angular.isDefined(err) && ($delegate.jsLoader.hasOwnProperty("ocLazyLoadLoader") || $delegate.jsLoader.hasOwnProperty("requirejs"))) { $delegate._$log.error(err); jsDeferred.reject(err); } else { jsDeferred.resolve(); } }, params); promises.push(jsDeferred.promise); } if(promises.length === 0) { let deferred = $q.defer(), err = "Error: no file to load has been found, if you're trying to load an existing module you should use the 'inject' method instead of 'load'."; $delegate._$log.error(err); deferred.reject(err); return deferred.promise; } else if(params.serie && params.files.length > 0) { return $q.all(promises).then(() => $delegate.filesLoader(config, params)); } else { return $q.all(promises).finally(res => { $delegate.toggleWatch(false); // stop watching angular.module calls return res; }); } }; /** * Load a module or a list of modules into Angular * @param module Mixed the name of a predefined module config object, or a module config object, or an array of either * @param params Object optional parameters * @returns promise */ $delegate.load = function(originalModule, originalParams = {}) { var self = this, config = null, deferredList = [], deferred = $q.defer(), errText; // clean copy var module = angular.copy(originalModule); var params = angular.copy(originalParams); // If module is an array, break it down if(angular.isArray(module)) { // Resubmit each entry as a single module angular.forEach(module, m => { deferredList.push(self.load(m, params)); }); // Resolve the promise once everything has loaded $q.all(deferredList).then(res => { deferred.resolve(res); }, err => { deferred.reject(err); }); return deferred.promise; } // Get or Set a configuration depending on what was passed in if(angular.isString(module)) { config = self.getModuleConfig(module); if(!config) { config = { files: [module] }; } } else if(angular.isObject(module)) { // case {type: 'js', path: lazyLoadUrl + 'testModule.fakejs'} if(angular.isDefined(module.path) && angular.isDefined(module.type)) { config = { files: [module] }; } else { config = self.setModuleConfig(module); } } if(config === null) { var moduleName = self._getModuleName(module); errText = `Module "${ moduleName || 'unknown' }" is not configured, cannot load.`; $delegate._$log.error(errText); deferred.reject(new Error(errText)); return deferred.promise; } else { // deprecated if(angular.isDefined(config.template)) { if(angular.isUndefined(config.files)) { config.files = []; } if(angular.isString(config.template)) { config.files.push(config.template); } else if(angular.isArray(config.template)) { config.files.concat(config.template); } } } var localParams = angular.extend({}, params, config); // if someone used an external loader and called the load function with just the module name if(angular.isUndefined(config.files) && angular.isDefined(config.name) && $delegate.moduleExists(config.name)) { return $delegate.inject(config.name, localParams, true); } $delegate.filesLoader(config, localParams).then(() => { $delegate.inject(null, localParams).then(res => { deferred.resolve(res); }, err => { deferred.reject(err); }); }, err => { deferred.reject(err); }); return deferred.promise; }; // return the patched service return $delegate; }); }); })(angular);