(function (angular) { 'use strict'; angular.module('oc.lazyLoad').config(["$provide", function ($provide) { $provide.decorator('$ocLazyLoad', ["$delegate", "$q", function ($delegate, $q) { /** * The function that loads new files * @param config * @param params * @returns {*} */ $delegate.filesLoader = function filesLoader(config) { var params = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 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 pushFile(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, function (path) { pushFile(path); }); } if (cssFiles.length > 0) { var cssDeferred = $q.defer(); $delegate.cssLoader(cssFiles, function (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, function (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, function (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) { var 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(function () { return $delegate.filesLoader(config, params); }); } else { return $q.all(promises)['finally'](function (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) { var originalParams = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 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, function (m) { deferredList.push(self.load(m, params)); }); // Resolve the promise once everything has loaded $q.all(deferredList).then(function (res) { deferred.resolve(res); }, function (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(function () { $delegate.inject(null, localParams).then(function (res) { deferred.resolve(res); }, function (err) { deferred.reject(err); }); }, function (err) { deferred.reject(err); }); return deferred.promise; }; // return the patched service return $delegate; }]); }]); })(angular);