/**
* Load modules and components asynchronously for angular 1.x application.
*
* https://github.com/subchen/angular-async-loader
*
* subchen@gmail.com
*/
(function() {
function factory(angular, undefined) {
var VERSION = '1.3.2';
// Support require.js, sea.js, system.js
var amdRequire = (function() {
if (typeof(require) === 'function') {
if (typeof(require.async) === 'function') {
return require.async;
} else {
return require;
}
} else if (typeof(seajs) === 'object' && typeof(seajs.use) === 'function') {
return seajs.use;
} else if (typeof(System) === 'object' && typeof(System.amdRequire) === 'function') {
return System.amdRequire;
}
throw new Error('No amd/cmd module loader found.');
}());
/**
* Load external dependencies, such as Controller, Service, etc.
*
* @private
* @param {String|Array} dependencies
* @returns {*} a promised function to ajax load dependencies
*/
function resolveDependencies(dependencies) {
if (typeof(dependencies) === 'string') {
dependencies = [dependencies];
}
return ['$q', function($q) {
var defer = $q.defer();
amdRequire(dependencies, function() {
defer.resolve(arguments);
});
return defer.promise;
}];
}
/**
* Rewrite route config for $routeProvider.when or $stateProvider.state.
*
* Transform 'controllerUrl' and 'dependencies' attrs into resolve object.
*
* @private
* @param {Object} config
* @returns {Object} the modified config
*/
function route(config) {
function collectDependencies(config, dependencies) {
if (config.controllerUrl) {
dependencies.push(config.controllerUrl);
//delete config.controllerUrl;
}
if (config.dependencies) {
if (typeof(config.dependencies) === 'string') {
dependencies.push(config.dependencies);
} else {
[].push.apply(dependencies, config.dependencies);
}
//delete config.dependencies;
}
}
var dependencies = [];
collectDependencies(config, dependencies);
if (config.hasOwnProperty('views')) {
// multiple views support
Object.keys(config.views).forEach(function(view) {
collectDependencies(config.views[view], dependencies);
});
}
if (dependencies.length > 0) {
var resolve = config.resolve || {};
resolve['$dummy'] = resolveDependencies(dependencies);
config.resolve = resolve;
}
return config;
}
return {
/**
* Version of npm package.
*/
VERSION: VERSION,
/**
* Configure angular module instance to support async load components.
*
* @param {angular.Module} app
*/
configure: function(app) {
app.provider('ngProviders', ['$controllerProvider', '$compileProvider', '$filterProvider', '$provide', '$injector',
function($controllerProvider, $compileProvider, $filterProvider, $provide, $injector) {
this.$get = function() {
return {
$controllerProvider: $controllerProvider,
$compileProvider: $compileProvider,
$filterProvider: $filterProvider,
$provide: $provide,
$injector: $injector
};
};
}
]);
app.run(['ngProviders', '$injector', function(ngProviders, $injector) {
var $controllerProvider = ngProviders.$controllerProvider;
var $compileProvider = ngProviders.$compileProvider;
var $filterProvider = ngProviders.$filterProvider;
var $provide = ngProviders.$provide;
/**
* Register an angular module for dependency.
*
* @param {String} name - module name
*/
app.useModule = function (name) {
var module = angular.module(name);
if (module.requires) {
for (var i = 0; i < module.requires.length; i++) {
app.useModule(module.requires[i]);
}
}
angular.forEach(module._invokeQueue, function(args) {
var provider = ngProviders[args[0]] || $injector.get(args[0]);
provider[args[1]].apply(provider, args[2]);
});
angular.forEach(module._configBlocks, function(args) {
var provider = ngProviders.$injector.get(args[0]);
provider[args[1]].apply(provider, args[2]);
});
angular.forEach(module._runBlocks, function(args) {
$injector.invoke(args);
});
return app;
};
app.value = function(name, value) {
$provide.value(name, value);
return app;
};
app.constant = function(name, value) {
$provide.constant(name, value);
return app;
};
app.factory = function(name, factory) {
$provide.factory(name, factory);
return app;
};
app.service = function(name, service) {
$provide.service(name, service);
return app;
};
app.filter = function(name, filter) {
$filterProvider.register(name, filter);
return app;
};
app.directive = function(name, directive) {
$compileProvider.directive(name, directive);
return app;
};
app.controller = function(name, controller) {
$controllerProvider.register(name, controller);
return app;
};
app.decorator = function(name, decorator) {
$provide.decorator(name, decorator);
return app;
};
app.provider = function(name, service) {
$provide.provider(name, service);
return app;
};
/**
* Get angular injector object by name in module scope.
*
* @param {String} name
* @returns {*} the injected object
*/
app.get = function(name) {
return $injector.get(name);
};
}]);
// rewrite $routeProvider.when
if (app.requires && app.requires.indexOf('ngRoute') !== -1) {
app.config(['$routeProvider', function($routeProvider) {
var whenFn = $routeProvider.when;
$routeProvider.when = function(path, config) {
return whenFn.call($routeProvider, path, route(config));
};
}]);
}
// rewrite $stateProvider.state
if (app.requires && app.requires.indexOf('ui.router') !== -1) {
app.config(['$stateProvider', function($stateProvider) {
var stateFn = $stateProvider.state;
$stateProvider.state = function(state, config) {
return stateFn.call($stateProvider, state, route(config));
};
}]);
}
}
};
}
/**
* @exports
*/
if (typeof(define) === 'function' && define.amd) {
define(['angular'], function(angular) {
return factory(angular);
});
} else {
window.asyncLoader = factory(window.angular);
}
}());