├── .bowerrc
├── example
├── src
│ ├── modules
│ │ ├── module2
│ │ │ ├── testB.tpl.html
│ │ │ ├── testBCtrl.spec.js
│ │ │ └── testBCtrl.js
│ │ └── module1
│ │ │ ├── testA.tpl.html
│ │ │ └── testACtrl.js
│ ├── data
│ │ └── testA.json
│ ├── sharedService.js
│ ├── app.js
│ └── index.html
├── .bowerrc
├── bower.json
├── README.md
└── test
│ └── test-main.js
├── .gitignore
├── bower.json
├── package.json
├── dist
├── angular-lazyload.min.js
└── angular-lazyload.js
├── README.md
├── Gruntfile.js
└── src
└── angular-lazyload.js
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 |
3 | }
4 |
--------------------------------------------------------------------------------
/example/src/modules/module2/testB.tpl.html:
--------------------------------------------------------------------------------
1 | id: {{id}}
--------------------------------------------------------------------------------
/example/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "src/components"
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.psd
2 | .idea
3 | /node_modules
4 | /src/components
5 | /example/src/components
6 | .DS_Store
7 |
--------------------------------------------------------------------------------
/example/src/modules/module1/testA.tpl.html:
--------------------------------------------------------------------------------
1 |
2 | -
3 | {{item.name}}
4 |
5 |
--------------------------------------------------------------------------------
/example/src/data/testA.json:
--------------------------------------------------------------------------------
1 | [
2 | {"name": "ABC", "id": 1},
3 | {"name": "CCC", "id": 2},
4 | {"name": "SDD", "id": 3},
5 | {"name": "AFF", "id": 4}
6 | ]
--------------------------------------------------------------------------------
/example/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-seajs-showcase",
3 | "dependencies": {
4 | "seajs": "*",
5 | "angular": ">=1.2.0-rc.3",
6 | "angular-route": ">=1.2.0-rc.3",
7 | "angular-mocks": ">=1.2.0-rc.3"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/example/src/modules/module2/testBCtrl.spec.js:
--------------------------------------------------------------------------------
1 | define(function (require, exports, module) {
2 | 'use strict';
3 | require('./testBCtrl.js');
4 | describe('controllers', function(){
5 | beforeEach(module('app'));
6 | it('should ....', inject(function() {
7 |
8 | }));
9 | });
10 |
11 | });
--------------------------------------------------------------------------------
/example/src/sharedService.js:
--------------------------------------------------------------------------------
1 | define(function (require, exports, module) {
2 | "use strict";
3 | module.exports = function(app){
4 | app.factory('sharedService', function(){
5 | return {
6 | test: function(){
7 | console.log('loaded service')
8 | }
9 | }
10 | })
11 | }
12 | });
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-lazyload",
3 | "version": "0.4.0",
4 | "author": "TZ ",
5 | "description": "A lazyload service for angular projects, only load-on-demand, support seajs/requirejs/custom.",
6 | "main": ["dist/angular-lazyload.js"],
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/atian25/angular-lazyload"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/example/src/modules/module2/testBCtrl.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 无需外部传入的app, 则直接执行即可
3 | */
4 | define(function (require, exports, module) {
5 | 'use strict';
6 | var app = require('app');
7 |
8 | //注册controller
9 | app.register.controller('testBCtrl', ['$scope', '$routeParams', '$location', '$http',
10 | function($scope, $routeParams, $location, $http){
11 | //获取页面的入参
12 | var id = $routeParams.id;
13 | $scope.id = id;
14 | }]
15 | );
16 |
17 | });
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | ## 源码目录
2 |
3 | - src
4 | - images 图片
5 | - css 样式
6 | - modules 本项目用到的模块, 按模块划分
7 | - module1 具体某个模块
8 | - module1.js 模块用到的js
9 | - module1.spec.js 对应的单元测试
10 | - module1.tpl.html 模板文件
11 | - module2
12 | - ...
13 | - commons 存储我们的通用模块,后期再独立为component
14 | - components 存储第三方的web类库,通过bower来安装,不存储到源码库.
15 | - conf 配置文件
16 | - urlmapping.conf 路由映射
17 | - prototype 存储R.E.D提供的原始HTML+CSS
18 | - test 存储测试相关的一些数据和脚本
19 | - Gruntfile.js 脚本定义
20 | - package.json 自述文件,版本号等信息
21 | - bower.json 定义需要安装到src/components的第三方web类库
22 | - node_modules 开发期需用到的nodejs插件, 无需纳入源码管理, 通过`npm install`安装.
23 |
--------------------------------------------------------------------------------
/example/test/test-main.js:
--------------------------------------------------------------------------------
1 | var alias = {};
2 | for (var file in window.__karma__.files) {
3 | if (window.__karma__.files.hasOwnProperty(file)) {
4 | if (/\/src\//.test(file)) {
5 | var name = file.replace(/^\/base\/src/, '.').replace(/\.js$/, '');
6 | console.log('>',name, file)
7 | alias[name] = file;
8 | }
9 | }
10 | }
11 |
12 | seajs.config({
13 | base: './',
14 | alias: alias
15 | })
16 |
17 | var _fn = window.__karma__.start;
18 | window.__karma__.start = function() {
19 | seajs.use([
20 | './app',
21 | './modules/module2/testBCtrl.spec'
22 | ], function(m) {
23 | angular.bootstrap(document, ['app']);
24 | _fn.call()
25 | })
26 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-lazyload",
3 | "version": "0.4.0",
4 | "author": "TZ ",
5 | "description": "A lazyload service for angular projects, only load-on-demand, support seajs/requirejs/custom.",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/atian25/angular-lazyload"
9 | },
10 | "devDependencies": {
11 | "grunt": "latest",
12 | "grunt-contrib-clean": "latest",
13 | "grunt-contrib-concat": "latest",
14 | "grunt-contrib-copy": "latest",
15 | "grunt-contrib-connect": "latest",
16 | "grunt-contrib-htmlmin": "latest",
17 | "grunt-contrib-uglify": "latest",
18 | "grunt-contrib-watch": "latest",
19 | "matchdep": "latest",
20 | "connect-livereload": "latest",
21 | "connect-route": "latest",
22 | "shelljs": "latest"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/example/src/modules/module1/testACtrl.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 需要外部传入的app, 则`module.exports`为function
3 | */
4 | define(function (require, exports, module) {
5 | 'use strict';
6 |
7 | module.exports = function(app){
8 | //Step6: use `app.register` to register controller/service/directive/filter
9 | app.register.controller('testACtrl', ['$scope', '$routeParams', '$location', '$http',
10 | function($scope, $routeParams, $location, $http){
11 | //获取页面的入参
12 | var id = $routeParams.id;
13 | $http.get('data/testA.json').then(function(res){
14 | $scope.dataObj = res;
15 | }, function(res){
16 | console.log('err', res)
17 | });
18 | }]
19 | );
20 |
21 | //注册directive,简单的渲染HTML
22 | app.register.directive('articleContent', function(){
23 | return function(scope, element, attr) {
24 | element.addClass('ng-binding').data('$binding', attr.articleContent);
25 | scope.$watch(attr.articleContent, function(value) {
26 | element.html(value || '');
27 | });
28 | };
29 | })
30 | }
31 | });
--------------------------------------------------------------------------------
/dist/angular-lazyload.min.js:
--------------------------------------------------------------------------------
1 | /*! angular-lazyload - v0.4.0 - https://github.com/atian25/angular-lazyload - 2013-10-28 */
2 | !function(){"use strict";function a(a,c,d){b(a),this.register=d,this.init=function(b,e){var f=angular.isObject(e)?e:this.loaders[e]||this.loaders.seajs;a.$on("$routeChangeStart",function(e,g){var h=g&&g.$$route;h&&(!angular.isFunction(f.check)||f.check(h))&&(h.resolve=h.resolve||{},h.resolve.loadedModule=function(){var e=c.defer();return f.load(h,function(c){a.safeApply(function(){e.resolve(angular.isFunction(c)?c(b,d):c)})},function(b){a.safeApply(function(){e.reject(b)})}),e.promise})})}}function b(a){a.safeApply=function(a){var b=this.$root.$$phase;"$apply"==b||"$digest"==b?a&&"function"==typeof a&&a():this.$apply(a)}}angular.module("angular-lazyload",[],["$controllerProvider","$compileProvider","$filterProvider","$provide",function(b,c,d,e){e.factory("$lazyload",["$rootScope","$q",function(f,g){var h={controller:b.register,directive:c.directive,filter:d.register,factory:e.factory,service:e.service,decorator:e.decorator};return new a(f,g,h)}])}]),a.prototype.loaders={},a.prototype.loaders.seajs={check:function(a){return"string"==typeof a.controllerUrl},load:function(a,b,c){seajs.use(a.controllerUrl,function(a){angular.isUndefined(a)?c(a):b(a)})}},a.prototype.loaders.requirejs={check:function(a){return"string"==typeof a.controllerUrl},load:function(a,b,c){require(a.controllerUrl,function(a){angular.isUndefined(a)?c(a):b(a)})}}}(this);
--------------------------------------------------------------------------------
/example/src/app.js:
--------------------------------------------------------------------------------
1 | define(function (require, exports, module) {
2 | "use strict";
3 | console.log('init app...' + (new Date().getTime()));
4 |
5 | //Step3: add 'angular-lazyload' to your main module's list of dependencies
6 | var app = angular.module('app', ['angular-lazyload', 'ngRoute']);
7 | require('./sharedService.js')(app);
8 |
9 | //配置期
10 | app.config(['$routeProvider', function($routeProvider) {
11 | //Step4: add `controllerUrl` to your route item config
12 | $routeProvider
13 | .when('/test/a', {
14 | controller: 'testACtrl',
15 | controllerUrl: 'modules/module1/testACtrl.js',
16 | templateUrl: 'modules/module1/testA.tpl.html'
17 | })
18 | .when('/test/b/:id', {
19 | controller: 'testBCtrl',
20 | controllerUrl: 'modules/module2/testBCtrl.js',
21 | templateUrl: 'modules/module2/testB.tpl.html'
22 | })
23 | .when('/main', {
24 | controller: function($scope, $routeParams, $location){
25 | $scope.str = new Date()
26 | //console.log($routeParams,$location)
27 | },
28 | template: '{{str}}
'
29 | })
30 | .otherwise({
31 | redirectTo: '/main'
32 | });
33 | }
34 | ]);
35 |
36 | //运行期
37 | app.run(['$lazyload', 'sharedService', function($lazyload, sharedService){
38 | //Step5: init lazyload & hold refs
39 | $lazyload.init(app);
40 | app.register = $lazyload.register;
41 | sharedService.test()
42 | }]);
43 |
44 | module.exports = app;
45 | });
--------------------------------------------------------------------------------
/example/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | angular-lazyload-showcase
6 |
7 |
8 |
9 | A lazyload service for angular projects, only load-on-demand, support seajs/requirejs/custom.
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # angular-lazyload
2 |
3 | ## **NOT CURRENTLY MAINTAINED, use [ocLazyLoad](https://github.com/ocombe/ocLazyLoad) or angular2**
4 |
5 | #### a lazyload service for angular projects, only load-on-demand, support seajs/requirejs/custom.
6 | ### 按需加载[AngularJS](http://angularjs.org)模块, 支持[Sea.js](http://seajs.org/)和[RequireJS](http://requirejs.org/)。
7 |
8 | ---
9 | **[下载](dist/angular-lazyload.js)** (or **[压缩版](dist/angular-lazyload.min.js)**) **|**
10 | **[使用指南](#使用指南) |**
11 | **[基本原理](#基本原理) |**
12 | **[TODO/贡献代码](#TODO) |**
13 | **[示例使用说明](#示例使用说明)**
14 |
15 | ---
16 |
17 |
18 | ### 使用指南
19 |
20 | **(1)** 安装
21 | - 通过[Bower](http://bower.io/)安装: `bower install angular-lazyload`
22 | - 直接下载: [Download](dist/angular-lazyload.js) (or [Minified](dist/angular-lazyload.min.js))
23 |
24 | **(2)** 在你的`index.html`中引入`angular-lazyload`。
25 | ```
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | ```
34 |
35 | **(3)** 在你的启动文件里面, 手动启动bootstrap。
36 | ```
37 | //Step2: bootstrap youself
38 | seajs.use(['app'], function(app){
39 | angular.bootstrap(document, ['app']);
40 | });
41 | ```
42 |
43 | **(3)** 添加`angular-lazyload`为你的主模块的依赖中。
44 | ```
45 | //Step3: add 'angular-lazyload' to your main module's list of dependencies
46 | var app = angular.module('app', ['angular-lazyload', 'ngRoute']);
47 | ```
48 |
49 | **(4)** 在`app.run`里进行初始化。
50 | ```
51 | app.run(['$lazyload', function($lazyload){
52 | //Step5: init lazyload & hold refs
53 | $lazyload.init(app);
54 | app.register = $lazyload.register;
55 | }]);
56 | ```
57 |
58 | **(5)** 路由映射, 添加`controllerUrl`
59 | ```
60 | //Step4: add `controllerUrl` to your route item config
61 | $routeProvider
62 | .when('/test/a', {
63 | controller: 'testACtrl',
64 | controllerUrl: 'modules/module1/testACtrl.js',
65 | templateUrl: 'modules/module1/testA.tpl.html'
66 | })
67 | }
68 | ```
69 |
70 | **(6)** 在你的模块里进行注册controller。
71 | ```
72 | //Step6: use `app.register` to register controller/service/directive/filter
73 | app.register.controller('testACtrl', ['$scope', function($scope){
74 | ...
75 | }]);
76 | ```
77 |
78 |
79 | ### 基本原理
80 |
81 | - 通过`route`的`resolve`做hack点
82 | - 在`config`期保存`register`的引用
83 | - 监听`$routeChangeStart`事件, 动态添加一个`resolve`
84 | - `resolve`里面通过seajs去动态加载模块,并动态注册
85 |
86 | ### TODO
87 | - 添加测试的示例, 参考https://github.com/seajs/seajs/issues/874
88 | - 欢迎PullRequest贡献代码
89 |
90 | ### 示例使用说明
91 |
92 | 1. 安装[nodejs](http://nodejs.org) -- 下载对应版本并安装
93 | 2. 安装[grunt](http://gruntjs.com) -- 命令行下执行: `npm install -g grunt-cli` (不包含符号` ,下同)
94 | 3. 安装[bower](https://github.com/bower/bower) -- 命令行下执行: `npm install -g bower` (不包含符号` ,下同)
95 | 4. 安装依赖库 -- 命令行到项目根目录,执行 `npm install`
96 | 5. 安装Web类库 -- 命令行到**example**目录,执行 `bower install`
97 | 6. 运行示例 -- 命令行执行 `grunt server`, 将自动打开浏览器显示首页
98 | 7. 若参与开发则 -- 命令行执行 `grunt dev`, 欢迎通过PullRequest贡献代码
99 |
100 |
101 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 自动化脚本定义
3 | */
4 | module.exports = function (grunt) {
5 | 'use strict';
6 |
7 | //load all grunt tasks
8 | require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
9 | require('shelljs/global');
10 | var path = require('path');
11 |
12 | //define tasks
13 | //启动Web服务器,监控变更,自动加载
14 | grunt.registerTask('server', ['connect', 'open', 'watch:server']);
15 | grunt.registerTask('dev', ['connect', 'open', 'watch:dev']);
16 | grunt.registerTask('build', ['clean', 'concat', 'uglify']);
17 |
18 |
19 | //读取配置
20 | var pkg = grunt.file.readJSON('package.json');
21 | var cfg = {
22 | pkg: pkg,
23 | src: './',
24 | // Change 'localhost' to '0.0.0.0' to access the server from outside.
25 | serverHost: '0.0.0.0',
26 | serverPort: 9000,
27 | serverUrl: 'http://localhost:9000/example/src/index.html',
28 | livereload: 35729
29 | };
30 |
31 | //grunt config
32 | grunt.initConfig({
33 | //======== 配置相关 ========
34 | cfg: cfg,
35 |
36 | //======== 开发相关 ========
37 | //开启服务
38 | connect: {
39 | options: {
40 | port: cfg.serverPort,
41 | hostname: cfg.serverHost,
42 | middleware: function(connect, options) {
43 | return [
44 | require('connect-livereload')({
45 | port: cfg.livereload
46 | }),
47 | connect.query(),
48 | // Serve static files.
49 | connect.static(options.base),
50 | // Make empty directories browsable.
51 | connect.directory(options.base),
52 | ];
53 | }
54 | },
55 | server: {
56 | options: {
57 | base: cfg.src
58 | }
59 | }
60 | },
61 |
62 | //监控文件变化
63 | watch: {
64 | options: {
65 | livereload: cfg.livereload,
66 | },
67 | server: {
68 | files: [
69 | cfg.src + '/**'
70 | ],
71 | tasks: []
72 | },
73 | dev: {
74 | files: [
75 | cfg.src + '/**',
76 | '!dist/**'
77 | ],
78 | tasks: ['build']
79 | }
80 | },
81 |
82 | //清理
83 | clean: {
84 | build: ['dist/*']
85 | },
86 |
87 | //复制
88 | concat: {
89 | options: {
90 | banner: '/*! <%= cfg.pkg.name %> - v<%= cfg.pkg.version %> - <%= cfg.pkg.repository.url %> - <%= grunt.template.today("yyyy-mm-dd") %> */\n'
91 | },
92 | build: {
93 | files: [
94 | {expand: true, cwd:'src/', src: ['angular-lazyload.js'], dest: 'dist/'}
95 | ]
96 | }
97 | },
98 |
99 | //压缩
100 | uglify: {
101 | options: {
102 | banner: '/*! <%= cfg.pkg.name %> - v<%= cfg.pkg.version %> - <%= cfg.pkg.repository.url %> - <%= grunt.template.today("yyyy-mm-dd") %> */\n',
103 | mangle: {
104 | except: ['require','exports', 'module']
105 | }
106 | },
107 | build: {
108 | files: {
109 | 'dist/angular-lazyload.min.js' : ['dist/angular-lazyload.js']
110 | }
111 | }
112 | }
113 | });
114 |
115 | /**
116 | * 在跨域chrome中打开首页
117 | */
118 | grunt.registerTask('open', function(crossdomain) {
119 | var url = cfg.serverUrl || 'http://localhost:' + cfg.serverPort;
120 | url = url && url.replace(/"/g, '\\\"') || 'about:blank';
121 | var param = !crossdomain ? '' : ' --user-data-dir=C:/CHROME_DEV --disable-web-security --allow-file-access-from-files ';
122 | var cmd = 'start chrome '+ url + ' ' + param;
123 | exec(cmd);
124 | });
125 | };
126 |
--------------------------------------------------------------------------------
/src/angular-lazyload.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A lazyload service for angular projects, only load-on-demand, support seajs/requirejs/custom.
3 | * support [Sea.js](http://seajs.org/) & [RequireJS](http://requirejs.org/)
4 | *
5 | * @author TZ
6 | * @home https://github.com/atian25/angular-lazyload
7 | */
8 | (function(global, undefined) {
9 | 'use strict';
10 |
11 | /**
12 | * register `angular-lazyload` module & `$lazyload` service
13 | */
14 | angular.module('angular-lazyload', [], ['$controllerProvider', '$compileProvider', '$filterProvider', '$provide',
15 | function ($controllerProvider, $compileProvider, $filterProvider, $provide) {
16 | //register `$lazyload` service
17 | $provide.factory('$lazyload', ['$rootScope', '$q', function($rootScope, $q){
18 | //hold provide's refs, because after ng bootstrap, you can't use `app.controller` to dynamic register controller.
19 | var register = {
20 | controller: $controllerProvider.register,
21 | directive: $compileProvider.directive,
22 | filter: $filterProvider.register,
23 | factory: $provide.factory,
24 | service: $provide.service,
25 | decorator: $provide.decorator
26 | };
27 | return new LazyLoadProvider($rootScope, $q, register);
28 | }]);
29 | }
30 | ]);
31 |
32 | /**
33 | * $lazyload Service
34 | */
35 | function LazyLoadProvider($rootScope, $q, register){
36 | //patch the $rootScope, add `safeApply` function.
37 | patchScope($rootScope);
38 |
39 | /**
40 | * hold provide's refs, because after ng bootstrap, you can't use `app.controller` to dynamic register controller.
41 | */
42 | this.register = register;
43 |
44 | /**
45 | * @param {Object} params This will pass to the lazy load module
46 | * @param {String} eventName Default to `$routeChangeStart`, //TODO: support `ui-route`
47 | * @param {Function/String} loaderType The loader function: //FIXME: only support `seajs` current.
48 | * - 'seajs' : default value, use [Sea.js](http://seajs.org/) to async load modules
49 | * - 'requirejs': use [RequireJS](http://requirejs.org/) to async load modules
50 | * - {Object} : custom loader:
51 | * - check {Function} Optional , check whether need to load by loader
52 | * - load {Function}
53 | * - route : current route item
54 | * - register: register refs object
55 | * - callback : callback function when async load success
56 | */
57 | this.init = function(params, loaderType){
58 | //get loaderFn: if loaderType is function, then just use it, else use build in loader by loaderType, default to seajs
59 | var loader = angular.isObject(loaderType) ? loaderType : this.loaders[loaderType] || this.loaders['seajs'];
60 |
61 | //listen to route change event to hook
62 | $rootScope.$on('$routeChangeStart', function(e, target){
63 | //console.debug(e, '|', target);
64 | var route = target && target.$$route;
65 | if(route){
66 | // if loader provide check(), then check it
67 | if(!angular.isFunction(loader.check) || loader.check(route)){
68 | route.resolve = route.resolve || {};
69 | //keypoint: use `route.resolve`
70 | route.resolve.loadedModule = function(){
71 | var defer = $q.defer();
72 | loader.load(route, function(m){
73 | $rootScope.safeApply(function(){
74 | defer.resolve(angular.isFunction(m) ? m(params, register) : m);
75 | });
76 | }, function(m){
77 | $rootScope.safeApply(function(){
78 | defer.reject(m);
79 | });
80 | });
81 | return defer.promise;
82 | }
83 | }
84 | }
85 | });
86 | }
87 | }
88 |
89 | /**
90 | * build-in loaders
91 | */
92 | LazyLoadProvider.prototype.loaders = {};
93 |
94 | LazyLoadProvider.prototype.loaders['seajs'] = {
95 | check: function(route){
96 | //if exsit `controllerUrl` then trigger seajs async load.
97 | return typeof route.controllerUrl == 'string'
98 | },
99 | load: function(route, suc, fail){
100 | seajs.use(route.controllerUrl, function(m){
101 | if(angular.isUndefined(m)){
102 | fail(m);
103 | }else{
104 | suc(m);
105 | }
106 | });
107 | }
108 | }
109 |
110 | LazyLoadProvider.prototype.loaders['requirejs'] = {
111 | check: function(route){
112 | //if exsit `controllerUrl` then trigger requirejs async load.
113 | return typeof route.controllerUrl == 'string'
114 | },
115 | load: function(route, suc, fail){
116 | require(route.controllerUrl, function(m){
117 | if(angular.isUndefined(m)){
118 | fail(m);
119 | }else{
120 | suc(m);
121 | }
122 | });
123 | }
124 | }
125 |
126 | /**
127 | * 为$rootScope增加safeApply方法, 安全的apply
128 | */
129 | function patchScope($rootScope){
130 | $rootScope.safeApply = function(fn){
131 | var phase = this.$root.$$phase;
132 | if(phase == '$apply' || phase == '$digest') {
133 | if(fn && (typeof(fn) === 'function')) {
134 | fn();
135 | }
136 | } else {
137 | this.$apply(fn);
138 | }
139 | };
140 | }
141 | })(this);
--------------------------------------------------------------------------------
/dist/angular-lazyload.js:
--------------------------------------------------------------------------------
1 | /*! angular-lazyload - v0.4.0 - https://github.com/atian25/angular-lazyload - 2013-10-28 */
2 | /**
3 | * A lazyload service for angular projects, only load-on-demand, support seajs/requirejs/custom.
4 | * support [Sea.js](http://seajs.org/) & [RequireJS](http://requirejs.org/)
5 | *
6 | * @author TZ
7 | * @home https://github.com/atian25/angular-lazyload
8 | */
9 | (function(global, undefined) {
10 | 'use strict';
11 |
12 | /**
13 | * register `angular-lazyload` module & `$lazyload` service
14 | */
15 | angular.module('angular-lazyload', [], ['$controllerProvider', '$compileProvider', '$filterProvider', '$provide',
16 | function ($controllerProvider, $compileProvider, $filterProvider, $provide) {
17 | //register `$lazyload` service
18 | $provide.factory('$lazyload', ['$rootScope', '$q', function($rootScope, $q){
19 | //hold provide's refs, because after ng bootstrap, you can't use `app.controller` to dynamic register controller.
20 | var register = {
21 | controller: $controllerProvider.register,
22 | directive: $compileProvider.directive,
23 | filter: $filterProvider.register,
24 | factory: $provide.factory,
25 | service: $provide.service,
26 | decorator: $provide.decorator
27 | };
28 | return new LazyLoadProvider($rootScope, $q, register);
29 | }]);
30 | }
31 | ]);
32 |
33 | /**
34 | * $lazyload Service
35 | */
36 | function LazyLoadProvider($rootScope, $q, register){
37 | //patch the $rootScope, add `safeApply` function.
38 | patchScope($rootScope);
39 |
40 | /**
41 | * hold provide's refs, because after ng bootstrap, you can't use `app.controller` to dynamic register controller.
42 | */
43 | this.register = register;
44 |
45 | /**
46 | * @param {Object} params This will pass to the lazy load module
47 | * @param {String} eventName Default to `$routeChangeStart`, //TODO: support `ui-route`
48 | * @param {Function/String} loaderType The loader function: //FIXME: only support `seajs` current.
49 | * - 'seajs' : default value, use [Sea.js](http://seajs.org/) to async load modules
50 | * - 'requirejs': use [RequireJS](http://requirejs.org/) to async load modules
51 | * - {Object} : custom loader:
52 | * - check {Function} Optional , check whether need to load by loader
53 | * - load {Function}
54 | * - route : current route item
55 | * - register: register refs object
56 | * - callback : callback function when async load success
57 | */
58 | this.init = function(params, loaderType){
59 | //get loaderFn: if loaderType is function, then just use it, else use build in loader by loaderType, default to seajs
60 | var loader = angular.isObject(loaderType) ? loaderType : this.loaders[loaderType] || this.loaders['seajs'];
61 |
62 | //listen to route change event to hook
63 | $rootScope.$on('$routeChangeStart', function(e, target){
64 | //console.debug(e, '|', target);
65 | var route = target && target.$$route;
66 | if(route){
67 | // if loader provide check(), then check it
68 | if(!angular.isFunction(loader.check) || loader.check(route)){
69 | route.resolve = route.resolve || {};
70 | //keypoint: use `route.resolve`
71 | route.resolve.loadedModule = function(){
72 | var defer = $q.defer();
73 | loader.load(route, function(m){
74 | $rootScope.safeApply(function(){
75 | defer.resolve(angular.isFunction(m) ? m(params, register) : m);
76 | });
77 | }, function(m){
78 | $rootScope.safeApply(function(){
79 | defer.reject(m);
80 | });
81 | });
82 | return defer.promise;
83 | }
84 | }
85 | }
86 | });
87 | }
88 | }
89 |
90 | /**
91 | * build-in loaders
92 | */
93 | LazyLoadProvider.prototype.loaders = {};
94 |
95 | LazyLoadProvider.prototype.loaders['seajs'] = {
96 | check: function(route){
97 | //if exsit `controllerUrl` then trigger seajs async load.
98 | return typeof route.controllerUrl == 'string'
99 | },
100 | load: function(route, suc, fail){
101 | seajs.use(route.controllerUrl, function(m){
102 | if(angular.isUndefined(m)){
103 | fail(m);
104 | }else{
105 | suc(m);
106 | }
107 | });
108 | }
109 | }
110 |
111 | LazyLoadProvider.prototype.loaders['requirejs'] = {
112 | check: function(route){
113 | //if exsit `controllerUrl` then trigger requirejs async load.
114 | return typeof route.controllerUrl == 'string'
115 | },
116 | load: function(route, suc, fail){
117 | require(route.controllerUrl, function(m){
118 | if(angular.isUndefined(m)){
119 | fail(m);
120 | }else{
121 | suc(m);
122 | }
123 | });
124 | }
125 | }
126 |
127 | /**
128 | * 为$rootScope增加safeApply方法, 安全的apply
129 | */
130 | function patchScope($rootScope){
131 | $rootScope.safeApply = function(fn){
132 | var phase = this.$root.$$phase;
133 | if(phase == '$apply' || phase == '$digest') {
134 | if(fn && (typeof(fn) === 'function')) {
135 | fn();
136 | }
137 | } else {
138 | this.$apply(fn);
139 | }
140 | };
141 | }
142 | })(this);
--------------------------------------------------------------------------------