diff --git a/README.md b/README.md index 1f95434..c5d6952 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ require.config({ paths: { 'angular': 'assets/angular/angular.min', 'angular-ui-router': 'assets/angular-ui-router/release/angular-ui-router.min', - 'angular-async-loader': 'assets/angular-async-loader/angular-async-loader' + 'angular-async-loader': 'assets/angular-async-loader/dist/angular-async-loader.min' }, shim: { 'angular': {exports: 'angular'}, diff --git a/angular-async-loader.js b/angular-async-loader.js index 7e67156..df18620 100644 --- a/angular-async-loader.js +++ b/angular-async-loader.js @@ -9,7 +9,7 @@ function factory(angular, undefined) { - var VERSION = '1.2.0'; + var VERSION = '1.2.1'; // Support require.js, sea.js, system.js var amdRequire = (function() { @@ -34,15 +34,14 @@ * @param {String|Array} dependencies * @returns {*} a promised function to ajax load dependencies */ - function requireLoadFn(dependencies) { + function resolveDependencies(dependencies) { if (typeof(dependencies) === 'string') { dependencies = [dependencies]; } - return ['$q', '$rootScope', function($q, $rootScope) { + return ['$q', function($q) { var defer = $q.defer(); amdRequire(dependencies, function() { - defer.resolve(Array.prototype.slice.call(arguments)); - $rootScope.$apply(); + defer.resolve(arguments); }); return defer.promise; }]; @@ -74,7 +73,7 @@ delete config.controllerUrl; var resolve = config.resolve || {}; - resolve['$dummy'] = requireLoadFn(dependencies); + resolve['$dummy'] = resolveDependencies(dependencies); config.resolve = resolve; } } diff --git a/dist/angular-async-loader.js b/dist/angular-async-loader.js new file mode 100644 index 0000000..df18620 --- /dev/null +++ b/dist/angular-async-loader.js @@ -0,0 +1,235 @@ +/** + * async loader for angular 1.x. + * + * https://github.com/subchen/angular-async-loader + * + * subchen@gmail.com + */ +(function() { + + function factory(angular, undefined) { + + var VERSION = '1.2.1'; + + // 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 rewriteConfig(config) { + if (config.hasOwnProperty('controllerUrl') || config.hasOwnProperty('dependencies')) { + var dependencies = config.dependencies; + if (dependencies === undefined) { + dependencies = []; + } else if (typeof(dependencies) === 'string') { + dependencies = [dependencies]; + } + if (config.controllerUrl) { + dependencies.push(config.controllerUrl); + } + delete config.dependencies; + delete config.controllerUrl; + + var resolve = config.resolve || {}; + resolve['$dummy'] = resolveDependencies(dependencies); + config.resolve = resolve; + } + } + + // multiple views support + if (config.hasOwnProperty('views')) { + Object.keys(config.views).forEach(function(view) { + rewriteConfig(config.views[view]); + }); + } else { + rewriteConfig(config); + } + + 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('$asyncLoader', [ + '$controllerProvider', + '$compileProvider', + '$provide', + '$filterProvider', + function($controllerProvider, + $compileProvider, + $provide, + $filterProvider) { + this.$get = function() { + return { + $controllerProvider: $controllerProvider, + $compileProvider: $compileProvider, + $provide: $provide, + $filterProvider: $filterProvider + }; + }; + } + ]); + + app.run(['$asyncLoader', function($asyncLoader) { + var $controllerProvider = $asyncLoader.$controllerProvider; + var $compileProvider = $asyncLoader.$compileProvider; + var $provide = $asyncLoader.$provide; + var $filterProvider = $asyncLoader.$filterProvider; + + 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; + }; + }]); + + // 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)); + }; + }]); + } + + + var injector; + + /** + * Get angular injector object by name in module scope. + * + * @param {String} name + * @returns {*} the injected object + */ + app.get = function(name) { + if (injector === undefined) { + var elements = [app.element, document, 'html', 'body']; + for (var i = 0; i < elements.length; i++) { + injector = angular.element(elements[i]).injector(); + if (injector !== undefined) { + break; + } + } + } + return injector.get(name); + }; + + } + }; + } + + /** + * @exports + */ + if (typeof(define) === 'function' && define.amd) { + define(['angular'], function(angular) { + return factory(angular); + }); + } else { + window.asyncLoader = factory(window.angular); + } + +}()); diff --git a/dist/angular-async-loader.min.js b/dist/angular-async-loader.min.js new file mode 100644 index 0000000..2900b6d --- /dev/null +++ b/dist/angular-async-loader.min.js @@ -0,0 +1,2 @@ +!function(){function e(e,r){function n(e){return"string"==typeof e&&(e=[e]),["$q",function(r){var n=r.defer();return i(e,function(){n.resolve(arguments)}),n.promise}]}function t(e){function t(e){if(e.hasOwnProperty("controllerUrl")||e.hasOwnProperty("dependencies")){var t=e.dependencies;t===r?t=[]:"string"==typeof t&&(t=[t]),e.controllerUrl&&t.push(e.controllerUrl),delete e.dependencies,delete e.controllerUrl;var o=e.resolve||{};o.$dummy=n(t),e.resolve=o}}return e.hasOwnProperty("views")?Object.keys(e.views).forEach(function(r){t(e.views[r])}):t(e),e}var o="1.2.1",i=function(){if("function"==typeof require)return"function"==typeof require.async?require.async:require;if("object"==typeof seajs&&"function"==typeof seajs.use)return seajs.use;if("object"==typeof System&&"function"==typeof System.amdRequire)return System.amdRequire;throw new Error("No amd/cmd module loader found.")}();return{VERSION:o,configure:function(n){n.provider("$asyncLoader",["$controllerProvider","$compileProvider","$provide","$filterProvider",function(e,r,n,t){this.$get=function(){return{$controllerProvider:e,$compileProvider:r,$provide:n,$filterProvider:t}}}]),n.run(["$asyncLoader",function(e){var r=e.$controllerProvider,t=e.$compileProvider,o=e.$provide,i=e.$filterProvider;n.value=function(e,r){return o.value(e,r),n},n.constant=function(e,r){return o.constant(e,r),n},n.factory=function(e,r){return o.factory(e,r),n},n.service=function(e,r){return o.service(e,r),n},n.filter=function(e,r){return i.register(e,r),n},n.directive=function(e,r){return t.directive(e,r),n},n.controller=function(e,t){return r.register(e,t),n},n.decorator=function(e,r){return o.decorator(e,r),n},n.provider=function(e,r){return o.provider(e,r),n}}]),n.requires&&-1!==n.requires.indexOf("ngRoute")&&n.config(["$routeProvider",function(e){var r=e.when;e.when=function(n,o){return r.call(e,n,t(o))}}]),n.requires&&-1!==n.requires.indexOf("ui.router")&&n.config(["$stateProvider",function(e){var r=e.state;e.state=function(n,o){return r.call(e,n,t(o))}}]);var o;n.get=function(t){if(o===r)for(var i=[n.element,document,"html","body"],u=0;u