├── .editorconfig ├── .gitignore ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── bower.json ├── changelog.js ├── dist ├── modules │ ├── ocLazyLoad.core.js │ ├── ocLazyLoad.directive.js │ ├── ocLazyLoad.loaders.common.js │ ├── ocLazyLoad.loaders.core.js │ ├── ocLazyLoad.loaders.cssLoader.js │ ├── ocLazyLoad.loaders.jsLoader.js │ ├── ocLazyLoad.loaders.requireJSLoader.js │ ├── ocLazyLoad.loaders.templatesLoader.js │ └── ocLazyLoad.polyfill.ie8.js ├── ocLazyLoad.js ├── ocLazyLoad.min.js ├── ocLazyLoad.require.js └── ocLazyLoad.require.min.js ├── examples ├── complexExample │ ├── README.md │ ├── bower.json │ ├── index.html │ ├── js │ │ ├── AppCtrl.js │ │ ├── app.js │ │ └── gridModule.js │ └── partials │ │ ├── main.html │ │ └── modal.html ├── requireJSExample │ ├── css │ │ └── ng-grid.css │ ├── index.html │ ├── js │ │ ├── angular.min.js │ │ ├── jquery.js │ │ ├── lazymodule.js │ │ ├── main.js │ │ ├── ng-grid-2.0.11.debug.js │ │ ├── require.js │ │ └── testmodule.js │ └── partials │ │ └── grid.html └── simpleExample │ ├── index.html │ └── js │ └── testApp.js ├── gulpfile.js ├── karma.conf.js ├── package.json ├── src ├── ocLazyLoad.core.js ├── ocLazyLoad.directive.js ├── ocLazyLoad.loaders.common.js ├── ocLazyLoad.loaders.core.js ├── ocLazyLoad.loaders.cssLoader.js ├── ocLazyLoad.loaders.jsLoader.js ├── ocLazyLoad.loaders.requireJSLoader.js ├── ocLazyLoad.loaders.templatesLoader.js └── ocLazyLoad.polyfill.ie8.js ├── tests └── unit │ ├── lazyLoad │ ├── myContainer.js │ ├── test.css │ ├── test.html │ ├── testModule.fakejs │ ├── testModule.js │ ├── testModule2.js │ ├── testModule3.js │ ├── testModule4.js │ ├── testModule5.js │ └── testModule6.js │ ├── mocks │ └── app.mock.js │ └── specs │ └── ocLazyLoad.spec.js └── validate-commit-msg.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | # Change these settings to your own preference 9 | indent_style = space 10 | indent_size = 4 11 | 12 | # We recommend you to keep these unchanged 13 | end_of_line = lf 14 | charset = utf-8 15 | trim_trailing_whitespace = true 16 | insert_final_newline = true 17 | 18 | [*.md] 19 | trim_trailing_whitespace = false 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ############# 33 | ## Windows detritus 34 | ############# 35 | 36 | # Windows image file caches 37 | Thumbs.db 38 | ehthumbs.db 39 | 40 | # Folder config file 41 | Desktop.ini 42 | 43 | # Recycle Bin used on file shares 44 | $RECYCLE.BIN/ 45 | 46 | ############# 47 | ## Mac crap 48 | ############# 49 | .DS_Store 50 | 51 | 52 | ############# 53 | ## Intellij 54 | ############# 55 | 56 | nbproject 57 | manifest.mf 58 | build.xml 59 | 60 | .settings 61 | .idea/* 62 | *.iml 63 | 64 | 65 | ############# 66 | ## Project 67 | ############# 68 | public 69 | node_modules/* 70 | npm-debug.log 71 | bower_components 72 | coverage 73 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | **/.* 2 | examples/ 3 | src/ 4 | tests/ 5 | bower.json 6 | changelog.js 7 | gulpfile.js 8 | validate-commit-msg.js 9 | karma.conf.js 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: 2 | - node_js 3 | node_js: 4 | - '0.10' 5 | branches: 6 | only: 7 | - master 8 | before_install: 9 | - "export DISPLAY=:99.0" 10 | - "sh -e /etc/init.d/xvfb start" 11 | before_script: 12 | - npm install 13 | - npm install -g bower 14 | - bower install 15 | script: 16 | - npm test 17 | deploy: 18 | provider: npm 19 | email: olivier.combe@gmail.com 20 | skip_cleanup: true 21 | api_key: 22 | secure: lEMo04/NKEZfen4AKkztLd30SLqFmGLwSqTlUM27In31QbGEpA9pQhrZhkiEPfqDK+hE1E6tFsrWtehYt286S7qBL8ki8eTOPt6Ymy/QbSLn0bIwyDjxI0Pfy/CXk26n9e83+w+W1wz2hgHWTlwfY95cJR76SApYwnZJXBEXsXE= 23 | on: 24 | tags: true 25 | all_branches: true 26 | repo: ocombe/ocLazyLoad 27 | sudo: false 28 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | # 1.1.0 (2017-02-03) 3 | 4 | 5 | ## Bug Fixes 6 | 7 | - resolve the loader with created elements 8 | ([3351e44d](https://github.com/ocombe/ocLazyLoad/commit/3351e44d2d76b7599eadfe59dec5a5674b1aff69), [#292](https://github.com/ocombe/ocLazyLoad/pull/292)) 9 | - ensure CSS loader uses loading patch for PhantomJS 1.9 ([54d68e92](https://github.com/ocombe/ocLazyLoad/commit/54d68e92f83b1c9f5eba805a764c147566843544), [#280](https://github.com/ocombe/ocLazyLoad/pull/280)) 10 | 11 | 12 | ## Features 13 | 14 | - angular 1.6 compatibility 15 | ([17d372fc](https://github.com/ocombe/ocLazyLoad/commit/17d372fce194a840a0d23f7a8b417601f769f52a), 16 | [#377](https://github.com/ocombe/ocLazyLoad/issues/377)) 17 | - allow hot reloading via systemjs-hot-reloader ([94088482](https://github.com/ocombe/ocLazyLoad/commit/94088482aad2bba0f49c3d873886e993bcdfa13c), [#291](https://github.com/ocombe/ocLazyLoad/pull/291)) 18 | 19 | 20 | 21 | # 1.0.9 (2015-11-24) 22 | 23 | 24 | ## Bug Fixes 25 | 26 | - success callback for requirejs wrapper 27 | ([fd9df8d1](https://github.com/ocombe/ocLazyLoad/commit/fd9df8d1507bb4f0c690ef3781b04a15f3b8eb6b), 28 | [#260](https://github.com/ocombe/ocLazyLoad/issues/260)) 29 | 30 | 31 | ## Features 32 | 33 | - adding `_unregister` internal function 34 | ([5aba0dc7](https://github.com/ocombe/ocLazyLoad/commit/5aba0dc77b1fa4f1a1a27419cbc8a54d614a728c), 35 | [#265](https://github.com/ocombe/ocLazyLoad/issues/265)) 36 | 37 | 38 | 39 | # 1.0.8 (2015-11-02) 40 | 41 | 42 | ## Bug Fixes 43 | 44 | - better fix for $compile problems in IE 45 | ([ed4d425b](https://github.com/ocombe/ocLazyLoad/commit/ed4d425bfcf746901e2b956172c6a0b71e237bae), 46 | [#261](https://github.com/ocombe/ocLazyLoad/issues/261)) 47 | 48 | 49 | 50 | # 1.0.7 (2015-11-02) 51 | 52 | 53 | ## Bug Fixes 54 | 55 | - requirejs error callback 56 | ([11130942](https://github.com/ocombe/ocLazyLoad/commit/11130942ab3dbed497a64ab7eac5175e9b3597c4)) 57 | - infinite loop in inject 58 | ([70859980](https://github.com/ocombe/ocLazyLoad/commit/70859980d0537780c46e5a096d8c3c9cff86de83)) 59 | - IE "Invalid calling object" error (attach to DOM and then compile) 60 | ([d99ab925](https://github.com/ocombe/ocLazyLoad/commit/d99ab92533ef4bdfa334926307af9f32097592a3)) 61 | 62 | 63 | 64 | # 1.0.6 (2015-10-01) 65 | 66 | 67 | ## Bug Fixes 68 | - calling inject from loaders should pass the "real" module param 69 | ([953584e8](https://github.com/ocombe/ocLazyLoad/commit/953584e8989de7ed1c2166ca193c899bad8a3478), 70 | [#221](https://github.com/ocombe/ocLazyLoad/issues/221)) 71 | - directive compile original contents after dependency is loaded. 72 | ([a48e3ceb](https://github.com/ocombe/ocLazyLoad/commit/a48e3ceba1945e74478a0a7f964f9aa84e027799), 73 | [#168](https://github.com/ocombe/ocLazyLoad/issues/168), 74 | [#194](https://github.com/ocombe/ocLazyLoad/issues/194)) 75 | 76 | 77 | 78 | # 1.0.5 (2015-09-11) 79 | 80 | 81 | ## Bug Fixes 82 | - loading a module with dependencies with multiple oc-lazy-load directives 83 | ([098e391b](https://github.com/ocombe/ocLazyLoad/commit/098e391b0e084997c95a3125e66a41484a257cc1), 84 | [#213](https://github.com/ocombe/ocLazyLoad/issues/213)) 85 | - changing semver dependency for Angular 86 | ([30626401](https://github.com/ocombe/ocLazyLoad/commit/30626401664d1be8fc748bb53c88f39cb58742c0), 87 | [#195](https://github.com/ocombe/ocLazyLoad/issues/195)) 88 | 89 | 90 | ## Features 91 | 92 | - optimise signature calls and onInvoke function 93 | ([c56e727e](https://github.com/ocombe/ocLazyLoad/commit/c56e727ef832c591920c58a32646c5a8f05f655c)) 94 | 95 | 96 | 97 | # 1.0.4 (2015-07-30) 98 | 99 | 100 | ## Bug Fixes 101 | 102 | - don't let unmet dependencies slip through (thank you unit tests!) 103 | ([23eb666d](https://github.com/ocombe/ocLazyLoad/commit/23eb666d6627416e40aaa97783b9e81ec7153fe9)) 104 | - don't try to call angular.module on config names 105 | ([52219f92](https://github.com/ocombe/ocLazyLoad/commit/52219f923319e0856da47a6bce064b6ffb361641), 106 | [#217](https://github.com/ocombe/ocLazyLoad/issues/217), [#218](https://github.com/ocombe/ocLazyLoad/issues/218)) 107 | 108 | 109 | 110 | # 1.0.3 (2015-07-24) 111 | 112 | 113 | ## Bug Fixes 114 | 115 | - check for config names when needed 116 | ([023e4bb1](https://github.com/ocombe/ocLazyLoad/commit/023e4bb1e43a922ac4b9a4ef09ff475f1fec867a), 117 | [#214](https://github.com/ocombe/ocLazyLoad/issues/214), [#198](https://github.com/ocombe/ocLazyLoad/issues/198)) 118 | 119 | 120 | 121 | # 1.0.2 (2015-07-10) 122 | 123 | 124 | ## Bug Fixes 125 | 126 | - add extra condition to improve karma testing 127 | ([f0c33aae](https://github.com/ocombe/ocLazyLoad/commit/f0c33aaea84511a276dd946dd48bfe2cb20d1e73)) 128 | 129 | 130 | ## Features 131 | 132 | - add interoperability with CommonJS 133 | ([b0536ad4](https://github.com/ocombe/ocLazyLoad/commit/b0536ad4104467922c36bcf55a8a072343d102bc)) 134 | 135 | 136 | 137 | # 1.0.1 (2015-06-01) 138 | 139 | 140 | ## Bug Fixes 141 | 142 | - don't remove filecache for files that were successfully loaded 143 | ([e2ed37c0](https://github.com/ocombe/ocLazyLoad/commit/e2ed37c0eff32d34419af6851bfc355e7fb6f3ad)) 144 | 145 | 146 | 147 | # 1.0.0 (2015-05-29) 148 | 149 | 150 | ## Bug Fixes 151 | 152 | - use parent element instead of head to insert files in native loaded 153 | ([ad4276a3](https://github.com/ocombe/ocLazyLoad/commit/ad4276a39cddf8ebfd8f247690e98fc306c2d3bb), 154 | [#164](https://github.com/ocombe/ocLazyLoad/issues/164)) 155 | - don't compile text nodes in the directive 156 | ([8900e493](https://github.com/ocombe/ocLazyLoad/commit/8900e493b8245084f4871d129250ffc54e565639), 157 | [#168](https://github.com/ocombe/ocLazyLoad/issues/168)) 158 | - files cache should be cleaned upon resolution of the promise 159 | ([9a186c93](https://github.com/ocombe/ocLazyLoad/commit/9a186c93ccb72c63a45e40c6c1e86319d9d004fa), 160 | [#189](https://github.com/ocombe/ocLazyLoad/issues/189)) 161 | - reject promise when calling 'load' instead of 'inject' 162 | ([31595472](https://github.com/ocombe/ocLazyLoad/commit/315954729aaa609d43aa7eb7750e8804cff9bf70), 163 | [#147](https://github.com/ocombe/ocLazyLoad/issues/147)) 164 | - make inject work as a standalone function when no params are given 165 | ([499bd72d](https://github.com/ocombe/ocLazyLoad/commit/499bd72ddaf6addbf2c649a48776bd2b6ff35227), 166 | [#171](https://github.com/ocombe/ocLazyLoad/issues/171)) 167 | - guard against null-refs when parsing Safari user-agents 168 | ([818aa5d0](https://github.com/ocombe/ocLazyLoad/commit/818aa5d0ddaa3909109d42b38f8921e9d4b18cda), 169 | [#188](https://github.com/ocombe/ocLazyLoad/issues/188)) 170 | - checking if we're not registering a component with a reserved name (such at `toString`) 171 | ([7362ca49](https://github.com/ocombe/ocLazyLoad/commit/7362ca493384c5b14e203b9c013085cbcab980f8 ), 172 | [#184](https://github.com/ocombe/ocLazyLoad/issues/184)) 173 | 174 | 175 | 176 | # 1.0.0-beta.2 (2015-04-20) 177 | 178 | 179 | ## Bug Fixes 180 | 181 | - Die infinite loops! You are not fun anymore (with param serie:true) 182 | ([dab34c0a](https://github.com/ocombe/ocLazyLoad/commit/dab34c0a3513061665850f68d983c1f2729f5f5a), 183 | [#166](https://github.com/ocombe/ocLazyLoad/issues/166)) 184 | 185 | 186 | 187 | # 1.0.0-beta.1 (2015-04-16) 188 | 189 | 190 | ## Bug Fixes 191 | 192 | - use document.querySelector for insertBefore when jQuery isn't available 193 | ([6e8fa8c3](https://github.com/ocombe/ocLazyLoad/commit/6e8fa8c37f4305c50241288db7fddc5ecae0ab8f), 194 | [#164](https://github.com/ocombe/ocLazyLoad/issues/164)) 195 | 196 | 197 | ## Documentation 198 | 199 | - adding a plunkr for issues 200 | ([2f408d27](https://github.com/ocombe/ocLazyLoad/commit/2f408d2729eaf3df9cc8434375611a5b26181c0b)) 201 | 202 | 203 | 204 | # 1.0.0-alpha.3 (2015-04-09) 205 | 206 | 207 | ## Bug Fixes 208 | 209 | - components can be registered as object maps now 210 | ([08ed860e](https://github.com/ocombe/ocLazyLoad/commit/08ed860e7051f1f0dd132d760b958c5be1114177), 211 | [#156](https://github.com/ocombe/ocLazyLoad/issues/156)) 212 | - make a real copy of the params 213 | ([6a5d3d4c](https://github.com/ocombe/ocLazyLoad/commit/6a5d3d4ca3fca1e90468aed10ef96f06669cd7f9), 214 | [#160](https://github.com/ocombe/ocLazyLoad/issues/160)) 215 | 216 | 217 | ## Features 218 | 219 | - ES6fy all the things! 220 | ([9cae48c8](https://github.com/ocombe/ocLazyLoad/commit/9cae48c828665e58132950d6db138d082f6bf2a2)) 221 | 222 | 223 | 224 | # 1.0.0-alpha2 (2015-03-23) 225 | 226 | 227 | ## Bug Fixes 228 | 229 | - hash shouldn't prevent file type detection 230 | ([9e1d0894](https://github.com/ocombe/ocLazyLoad/commit/9e1d089413e09b14b7b46d5ff5de4612613be5e9), 231 | [#153](https://github.com/ocombe/ocLazyLoad/issues/153)) 232 | 233 | 234 | 235 | # 1.0.0-alpha1 (2015-03-19) 236 | 237 | 238 | ## Features 239 | 240 | - ocLazyLoad is now modular and (partially) written in ES6! It should be easier to write new loaders (or even extensions), and you can cherry picks the parts that you like. For example, you can use the injector without the loaders. Also, all of the internal functions are available (preceded by an underscore, and undocumented), use them at your own risk (in fact you shouldn't need them unless you're writing an extension). 241 | 242 | 243 | ## Bug Fixes 244 | 245 | - the directive should append the content and not add it after 246 | - only the modules added via angular.bootstrap should be considered "already loaded" 247 | [#147](https://github.com/ocombe/ocLazyLoad/issues/147) 248 | 249 | ## TODO before the release 250 | - try to remove most of the promises for perfs/tests 251 | - use moaaar ES6 252 | - clean up the code 253 | 254 | 255 | 256 | # 0.6.3 (2015-03-09) 257 | 258 | 259 | ## Bug Fixes 260 | 261 | - detect file type when path contains url parameters 262 | ([57e1801d](https://github.com/ocombe/ocLazyLoad/commit/57e1801d933f978060954bd8707f586b51544906), 263 | [#137](https://github.com/ocombe/ocLazyLoad/issues/137)) 264 | - rejected promise should be returned immediately 265 | ([887a67c4](https://github.com/ocombe/ocLazyLoad/commit/887a67c4196fa4bbd65c34f6eba1d8b2bca9fed3)) 266 | 267 | 268 | 269 | # 0.6.2 (2015-03-05) 270 | 271 | 272 | ## Features 273 | 274 | - first step on supporting systemjs & import 275 | ([cb8dd62e](https://github.com/ocombe/ocLazyLoad/commit/cb8dd62ed9052995cbaf132d94092d1d103dd74d)) 276 | 277 | 278 | 279 | # 0.6.1 (2015-03-05) 280 | 281 | 282 | ## Bug Fixes 283 | 284 | - karma hack isn't needed anymore 285 | ([3108296e](https://github.com/ocombe/ocLazyLoad/commit/3108296e9d78da822e58333f2f7d674531ae937b)) 286 | - angular.bootstrap now adds modules to init, not replace them 287 | ([bdc03dd9](https://github.com/ocombe/ocLazyLoad/commit/bdc03dd9128eca7fca2421317b9f7b103c9b419c)) 288 | - fixed TypeError: Converting circular structure to JSON 289 | ([11da36d9](https://github.com/ocombe/ocLazyLoad/commit/11da36d90bc5bae588fa3770430d371d5f935aae)) 290 | - don't watch for angular.module calls when you're not lazy loading 291 | ([35f7eb5b](https://github.com/ocombe/ocLazyLoad/commit/35f7eb5be57f7753a20d7460c5a380f44e3ac175)) 292 | 293 | 294 | ## Performance Improvements 295 | 296 | - hash the signature to optimize memory consumption 297 | ([1cd9676e](https://github.com/ocombe/ocLazyLoad/commit/1cd9676e8799cff03458f7d2d4d144f624da9cfa)) 298 | 299 | 300 | 301 | # 0.6.0 (2015-02-27) 302 | 303 | 304 | ## Bug Fixes 305 | 306 | - staged lines missing from last commit 307 | ([dd24bcdd](https://github.com/ocombe/ocLazyLoad/commit/dd24bcdd573821ce7def60c173a15cbee2540de7)) 308 | - don't throw for karma 309 | ([633bec8b](https://github.com/ocombe/ocLazyLoad/commit/633bec8b38635e7d78aaa0e4ea8f1a8cdb85050e), 310 | [#129](https://github.com/ocombe/ocLazyLoad/issues/129)) 311 | - RequireJS should be able to load js files with no extension (default behavior) 312 | ([4f60d05d](https://github.com/ocombe/ocLazyLoad/commit/4f60d05d02039b700908545b60b71c3e2ca9bbf6)) 313 | - null constants should work 314 | ([83d416f9](https://github.com/ocombe/ocLazyLoad/commit/83d416f97d357d148efe97bafbaf2836ed7b3a3d), 315 | [#111](https://github.com/ocombe/ocLazyLoad/issues/111)) 316 | - keep track of components signatures instead of just the names 317 | ([6bbaed97](https://github.com/ocombe/ocLazyLoad/commit/6bbaed971cf2d23bb35a6ba5f29c6e6162edc5b5), 318 | [#120](https://github.com/ocombe/ocLazyLoad/issues/120)) 319 | - improve bootstrap & added compatibility with karma 320 | ([ff6afcf5](https://github.com/ocombe/ocLazyLoad/commit/ff6afcf5d3ef00e8e931fd548051f3103225cea8), 321 | [#111](https://github.com/ocombe/ocLazyLoad/issues/111)) 322 | 323 | 324 | ## Features 325 | 326 | - you don't need to specify the name of the lazy loaded modules anymore!! 327 | ([6634cbee](https://github.com/ocombe/ocLazyLoad/commit/6634cbee6c5ce84363be84ae5529a61a633585b5)) 328 | - added support for specifying the type of a file. 329 | ([a3549eea](https://github.com/ocombe/ocLazyLoad/commit/a3549eea93c67cfc4881ebe9d44c73c220790461)) 330 | 331 | 332 | ## Documentation 333 | 334 | - adding a table of contents 335 | ([98aad141](https://github.com/ocombe/ocLazyLoad/commit/98aad14141e2eae1d04f9fc1fe09d85cd4b14713)) 336 | 337 | 338 | 339 | # 0.5.2 (2014-12-30) 340 | 341 | 342 | ## Bug Fixes 343 | 344 | - use init for bootstrapped apps & removed the need for loadedModules 345 | ([01936cd6](https://github.com/ocombe/ocLazyLoad/commit/01936cd6fe0e0f89a203408ee0bbb927f5b44d07), 346 | [#84](https://github.com/ocombe/ocLazyLoad/issues/84), [#102](https://github.com/ocombe/ocLazyLoad/issues/102), [#109](https://github.com/ocombe/ocLazyLoad/issues/109)) 347 | 348 | 349 | ## Documentation 350 | 351 | - added a link to a new lesson from egghead.io 352 | ([ef8d2871](https://github.com/ocombe/ocLazyLoad/commit/ef8d2871a445b29588f779a27cb3b702d0da6a13)) 353 | 354 | 355 | 356 | # 0.5.1 (2014-11-20) 357 | 358 | 359 | ## Bug Fixes 360 | 361 | - don't use async when you load files in serie 362 | ([9af93ed3](https://github.com/ocombe/ocLazyLoad/commit/9af93ed30cf05c6c64594d206dc9bf36a318f46e), 363 | [#95](https://github.com/ocombe/ocLazyLoad/issues/95)) 364 | - avoid errors thrown on empty template files 365 | ([768b9d75](https://github.com/ocombe/ocLazyLoad/commit/768b9d751a613a0a10cb476d5c3eac5fdf44f627)) 366 | - compatibility with jasmine 367 | ([d4985e1d](https://github.com/ocombe/ocLazyLoad/commit/d4985e1d7ce98315ca64a72730d8c10524929d58), 368 | [#94](https://github.com/ocombe/ocLazyLoad/issues/94)) 369 | 370 | 371 | 372 | # 0.5.0 (2014-11-11) 373 | 374 | 375 | ## Features 376 | 377 | - added a new param `insertBefore` 378 | ([c4f10385](https://github.com/ocombe/ocLazyLoad/commit/c4f10385cb6a9122c3a03d28b1bb6837710cc3f7), 379 | [#91](https://github.com/ocombe/ocLazyLoad/issues/91)) 380 | - started unit tests 381 | ([dcc4ff63](https://github.com/ocombe/ocLazyLoad/commit/dcc4ff639df23a1b934899b020a483e47e6ab290)) 382 | 383 | 384 | ## Documentation 385 | 386 | - updated loaders signatures 387 | ([ba022894](https://github.com/ocombe/ocLazyLoad/commit/ba022894841222989cf699f07fe21f04f7ad3307)) 388 | 389 | 390 | 391 | # 0.4.2 (2014-11-10) 392 | 393 | 394 | ## Bug Fixes 395 | 396 | - extend config to params for the register method 397 | ([31157941](https://github.com/ocombe/ocLazyLoad/commit/31157941ccabfa8f8c55edc00dc2b5758bf073b2), 398 | [#89](https://github.com/ocombe/ocLazyLoad/issues/89)) 399 | 400 | 401 | 402 | # 0.4.1 (2014-11-09) 403 | 404 | 405 | ## Bug Fixes 406 | 407 | - keep global params pristine when loading files 408 | ([6b2306b7](https://github.com/ocombe/ocLazyLoad/commit/6b2306b71543542c9b592766644c7bba1297bae4), 409 | [#89](https://github.com/ocombe/ocLazyLoad/issues/89)) 410 | - defining new run blocks will replace previous ones 411 | ([af2627b5](https://github.com/ocombe/ocLazyLoad/commit/af2627b5e627b2b4d83cdd043eff68b1c1430740), 412 | [#89](https://github.com/ocombe/ocLazyLoad/issues/89)) 413 | 414 | 415 | 416 | # 0.4.0 (2014-11-09) 417 | 418 | 419 | ## Features 420 | 421 | - new parameter `serie` to load files in serie 422 | ([4ae7a3f3](https://github.com/ocombe/ocLazyLoad/commit/4ae7a3f3de6ad4de74baa6cc771aee556bce812e), 423 | [#47](https://github.com/ocombe/ocLazyLoad/issues/47), [#86](https://github.com/ocombe/ocLazyLoad/issues/86)) 424 | - new parameter `rerun` to rerun the run blocks 425 | ([26a64a38](https://github.com/ocombe/ocLazyLoad/commit/26a64a38b0c21b6ca28cfa7e512b0b290fdca619), 426 | [#89](https://github.com/ocombe/ocLazyLoad/issues/89)) 427 | - new function: `isLoaded` to check if a module has been loaded 428 | ([364c9e9f](https://github.com/ocombe/ocLazyLoad/commit/364c9e9ffd8350e5ca46a708bd3846ea6de9421c), 429 | [#79](https://github.com/ocombe/ocLazyLoad/issues/79)) 430 | 431 | 432 | 433 | # 0.3.10 (2014-11-09) 434 | 435 | 436 | ## Bug Fixes 437 | 438 | - fix for error:[$compile:multidir] Multiple directives 439 | ([61fd4dd3](https://github.com/ocombe/ocLazyLoad/commit/61fd4dd3b8131245d33eb2314dcf37a9188a6728), 440 | [#84](https://github.com/ocombe/ocLazyLoad/issues/84), 441 | [#78](https://github.com/ocombe/ocLazyLoad/issues/78), 442 | [#73](https://github.com/ocombe/ocLazyLoad/issues/73), 443 | [#58](https://github.com/ocombe/ocLazyLoad/issues/58)) 444 | - css onload patch for some old browsers 445 | ([14ce3406](https://github.com/ocombe/ocLazyLoad/commit/14ce34066e0e865c8fa86f663d38e046f7a32abb)) 446 | - content inside the oc-lazy-load directive is now compiled on load 447 | ([9962e2ef](https://github.com/ocombe/ocLazyLoad/commit/9962e2ef163e9449e295dd3297f6019267a0e0e1), 448 | [#80](https://github.com/ocombe/ocLazyLoad/issues/80)) 449 | 450 | 451 | 452 | # 0.3.9 (2014-11-02) 453 | 454 | 455 | ## Bug Fixes 456 | 457 | - allow components with the same name from different types/modules 458 | ([f981c337](https://github.com/ocombe/ocLazyLoad/commit/f981c33749e4e61fa4dfd7c3c41df9beffcbf734), 459 | [#67](https://github.com/ocombe/ocLazyLoad/issues/67)) 460 | - initial modules not registered 461 | ([bcf50004](https://github.com/ocombe/ocLazyLoad/commit/bcf50004b8a1172aff4c769746fdcb9e5d5d9cba), 462 | [#58](https://github.com/ocombe/ocLazyLoad/issues/58), [#71](https://github.com/ocombe/ocLazyLoad/issues/71), [#73](https://github.com/ocombe/ocLazyLoad/issues/73), [#77](https://github.com/ocombe/ocLazyLoad/issues/77)) 463 | - add support for angular 1.3 in bower 464 | ([bda921b6](https://github.com/ocombe/ocLazyLoad/commit/bda921b68ce30645d992982325adc4eebfdcd361), 465 | [#76](https://github.com/ocombe/ocLazyLoad/issues/76)) 466 | 467 | 468 | ## Features 469 | 470 | - broadcast for componentLoaded event provides more info (module name and type) 471 | ([d41b9f53](https://github.com/ocombe/ocLazyLoad/commit/d41b9f53a46ff8c97b780d4c24f6f64e16017b89)) 472 | - example1 now uses ui-grid instead of ng-grid 473 | ([e7cf1e83](https://github.com/ocombe/ocLazyLoad/commit/e7cf1e83ff1453ee5adb8112052d393f9dc09e27)) 474 | 475 | 476 | ## Documentation 477 | 478 | - added link to a new article by @kbdaitch 479 | ([cc6b41db](https://github.com/ocombe/ocLazyLoad/commit/cc6b41db5e0dbcfe68754df325bf9f09e5709bf2)) 480 | - added a link to a new lesson from egghead.io 481 | ([e231f3cb](https://github.com/ocombe/ocLazyLoad/commit/e231f3cbfd6fb3338479a5f4d8a9ce00d374646e)) 482 | - added a link to a new lesson from egghead.io 483 | ([9b3c48e4](https://github.com/ocombe/ocLazyLoad/commit/9b3c48e49800dd3ed6a01dad7c1d958f8625eddb)) 484 | 485 | 486 | 487 | # 0.3.8 (2014-09-25) 488 | 489 | 490 | ## Bug Fixes 491 | 492 | - reject on load error 493 | ([d83f52b5](https://github.com/ocombe/ocLazyLoad/commit/d83f52b56a77a5cdb230260c497ee2db7283e077), 494 | [#66](https://github.com/ocombe/ocLazyLoad/issues/66)) 495 | 496 | 497 | 498 | # 0.3.7 (2014-09-10) 499 | 500 | 501 | ## Bug Fixes 502 | 503 | - don't reload a dependency that was just loaded 504 | ([6752bb94](https://github.com/ocombe/ocLazyLoad/commit/6752bb948093f196311572530d814231dc2dcd3a), 505 | [#64](https://github.com/ocombe/ocLazyLoad/issues/64)) 506 | 507 | 508 | ## Features 509 | 510 | - new event ocLazyLoad.moduleReloaded 511 | ([5010d144](https://github.com/ocombe/ocLazyLoad/commit/5010d144d1b250424be2bcfa98faf50c6782bf96)) 512 | 513 | 514 | 515 | # 0.3.6 (2014-09-02) 516 | 517 | 518 | ## Bug Fixes 519 | 520 | - concurrency lazy loads (thanks @BenBlazely) 521 | ([4899ea1a](https://github.com/ocombe/ocLazyLoad/commit/4899ea1a09bee145f70aec3dd964f885060422d8), 522 | [#44](https://github.com/ocombe/ocLazyLoad/issues/44)) 523 | 524 | 525 | ## Documentation 526 | 527 | - added a few links to other examples 528 | 529 | 530 | 531 | # 0.3.5 (2014-08-26) 532 | 533 | 534 | ## Bug Fixes 535 | 536 | - fixed cases where the config block would not be called 537 | ([1e29c9d4](https://github.com/ocombe/ocLazyLoad/commit/1e29c9d438d494cd053cd7533921e02e3fe5e5d0), 538 | [#5](https://github.com/ocombe/ocLazyLoad/issues/5)). 539 | The config block would not be called if: 540 | - defined multiple times (only the first 1 would be invoked) 541 | - defined with an auto injected module: ['...', function() {}] 542 | - defined after another component: angular.module().controler().config() 543 | 544 | 545 | 546 | # 0.3.4 (2014-08-26) 547 | 548 | 549 | ## Bug Fixes 550 | 551 | - make sure reconfig:true always run all invoke blocks 552 | ([361ae6b7](https://github.com/ocombe/ocLazyLoad/commit/361ae6b7d319cb5ada1ab022a6761d4a67a31b58), 553 | [#54](https://github.com/ocombe/ocLazyLoad/issues/54)) 554 | - the config/run blocks were not invoked without reconfig: true 555 | ([300882a0](https://github.com/ocombe/ocLazyLoad/commit/300882a016e4f9d538e322be9718f21740048296), 556 | [#5](https://github.com/ocombe/ocLazyLoad/issues/5)) 557 | - indexOf polyfill for IE8 558 | ([5f71c09c](https://github.com/ocombe/ocLazyLoad/commit/5f71c09cad4255932e84c760b07d16a4a2b016d9), 559 | [#52](https://github.com/ocombe/ocLazyLoad/issues/52)) 560 | 561 | 562 | ## Features 563 | 564 | - more log messages for debug 565 | ([bcbca814](https://github.com/ocombe/ocLazyLoad/commit/bcbca814049863b4dd7a6c5c1071efd760094966)) 566 | 567 | 568 | 569 | # 0.3.3 (2014-07-23) 570 | 571 | 572 | ## Bug Fixes 573 | 574 | - don't execute config blocks multiple times by default 575 | ([e2fec59e](https://github.com/ocombe/ocLazyLoad/commit/e2fec59ee7ff1e95e7e78ef8397c4fe500d8e7c0), 576 | [#43](https://github.com/ocombe/ocLazyLoad/issues/43), [#41](https://github.com/ocombe/ocLazyLoad/issues/41)) 577 | - don't test for .js in path because of requirejs 578 | ([6045214b](https://github.com/ocombe/ocLazyLoad/commit/6045214b6a4cc2d9dee1c1f2f89946687d963828)) 579 | - test order 580 | ([8412cb43](https://github.com/ocombe/ocLazyLoad/commit/8412cb431bfc742f2c4151e5b089f3313a70035e)) 581 | 582 | 583 | 584 | # 0.3.2 (2014-07-23) 585 | 586 | 587 | ## Bug Fixes 588 | 589 | - allow $ocLazyLoadProvider.config to be called multiple times 590 | ([c590579c](https://github.com/ocombe/ocLazyLoad/commit/c590579c9512e0dd3fae2c33c0aefc0bb0f7ca7e), 591 | [#43](https://github.com/ocombe/ocLazyLoad/issues/43)) 592 | - prevent duplicate loadings 593 | ([12bc6b2b](https://github.com/ocombe/ocLazyLoad/commit/12bc6b2b2d1561517d56c14c56c15c332d578344), 594 | [#35](https://github.com/ocombe/ocLazyLoad/issues/35), 595 | [#38](https://github.com/ocombe/ocLazyLoad/issues/38)) 596 | 597 | 598 | 599 | # 0.3.1 (2014-07-14) 600 | 601 | 602 | ## Bug Fixes 603 | 604 | - don't reject file load with custom file loaders such as requirejs 605 | ([91ed522f](https://github.com/ocombe/ocLazyLoad/commit/91ed522f724c3d384146053623bbd1e7c2c86751), 606 | [#33](https://github.com/ocombe/ocLazyLoad/issues/33)) 607 | 608 | 609 | ## Features 610 | 611 | - auto changelog from commits msg 612 | ([c089e085](https://github.com/ocombe/ocLazyLoad/commit/c089e085431d9f1a968e94c78f3c5ac5af71fa72)) 613 | - prevent duplicate loadings & add a cache busting param 614 | ([5a5d7f10](https://github.com/ocombe/ocLazyLoad/commit/5a5d7f108578fe31c5ca1f7c8dfc2d3bccfd1106), 615 | [#38](https://github.com/ocombe/ocLazyLoad/issues/38)) 616 | 617 | 618 | # 0.3.0 (17 June 2014) 619 | 620 | ## Features 621 | 622 | - $ocLazyLoad will now reject promises on errors 623 | - Use the parameter `debug` to show log messages in the console 624 | - JS / CSS / Template loaders are available by default in $ocLazyLoad but you can overwrite them with the config 625 | - Better doc (finally! \o/) 626 | - Example1 is now much better ! 627 | - Events broadcasted on module / component / file load (#21) 628 | 629 | 630 | # 0.2.0 (20 May 2014) 631 | * Added support for $animateProvider #19 632 | * Added support for CSS Loading (And perhaps other file types in the future) #19 633 | * Added loadAll function for use when a state requires resolve on more than one asset. #19 634 | * FIX: Angular JS 1.3.0-beta.8 changed the way config blocks are handled (now invoked last) #19 635 | * Adopted the MIT license as requested in #20 636 | * Added a gulpfile to build dist files (and, in the future, to do tests before the build). Run `npm install` to install the new dependencies and `npm build` to build the dist files. 637 | * **Breaking change** moved the src files to /src and the dist files to /dist. Installations via bower will only see the dist folder 638 | * Moved the examples to /examples 639 | 640 | # 0.1.3 (30 April 2014) 641 | * Fix for bug #18: merged files and incorrect module loading 642 | 643 | # 0.1.2 (14 April 2014) 644 | * Fix for bug #16: config blocks didn't work for module dependencies 645 | 646 | # 0.1.1 (08 April 2014) 647 | * Fix for bug #8: runBlocks can now load new modules (thanks to @rolandzwaga) 648 | * Added an example that makes use of requirejs and uses ngGrid as a lazy loaded module (thanks to @rolandzwaga) 649 | 650 | # 0.1.0 (04 April 2014) 651 | * Added a changelog ! 652 | * Added ```loadTemplateFile``` function. 653 | * Merge pull request #6 from BenBlazely/master (Extension of lazy loading to the angular.module DI block, refactored to use promises for tracking progress.) 654 | * Merge pull request #7 from rolandzwaga/master (Added some improvements for apps using angular.boostrap & for duplicated modules) 655 | * Fixed a bug with run blocks not working when they used unloaded modules. Not a complete fix though, more to come when bug #8 is fixed 656 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Olivier Combe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ocLazyLoad [![Build Status](https://travis-ci.org/ocombe/ocLazyLoad.svg)](https://travis-ci.org/ocombe/ocLazyLoad) 2 | ========== 3 | 4 | Lazy load modules & components in AngularJS 5 | 6 | ---- 7 |

8 | 9 | Find all the documentation (and more) on https://oclazyload.readme.io 10 |

11 | ocLazyLoad 12 | 13 |

14 | ---- 15 | 16 | ## Key features 17 | - Dependencies are automatically loaded 18 | - Debugger friendly (no eval code) 19 | - The ability to mix normal boot and load on demand 20 | - Load via the service or the directive 21 | - Use the embedded async loader or use your own (requireJS, ...) 22 | - Load js (angular or not) / css / templates files 23 | - Compatible with AngularJS 1.2.x/1.3.x/1.4.x/1.5.x/1.6.x 24 | 25 | ## Looking for help 26 | I'm looking for contributors to help me maintain the code (I'm gonna switch to Angular 2 soon, and I won't be much more invested in Angular 1 & ocLazyLoad). If you're interested, send me a tweet [@OCombe](https://twitter.com/OCombe) or an email: [olivier.combe@gmail.com](mailto:olivier.combe@gmail.com) ! 27 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oclazyload", 3 | "version": "1.1.0", 4 | "description": "Load modules on demand (lazy load) with angularJS", 5 | "main": "dist/ocLazyLoad.js", 6 | "homepage": "https://github.com/ocombe/ocLazyLoad", 7 | "authors": [ 8 | "Olivier Combe " 9 | ], 10 | "license": "MIT", 11 | "keywords": [ 12 | "lazy load", 13 | "lazy-load", 14 | "lazyload", 15 | "load on demand", 16 | "module", 17 | "angular", 18 | "angularJS" 19 | ], 20 | "ignore": [ 21 | "**/.*", 22 | "node_modules", 23 | "bower_components", 24 | "src", 25 | "gulpfile.js", 26 | "package.json", 27 | "changelog.js", 28 | "validate-commit-msg.js", 29 | "tests", 30 | "karma.conf.js", 31 | "examples" 32 | ], 33 | "devDependencies": { 34 | "angular-mocks": ">=1.2.0" 35 | }, 36 | "dependencies": { 37 | "angular": ">=1.2.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /changelog.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var child = require('child_process'); 4 | var fs = require('fs'); 5 | var util = require('util'); 6 | var q = require('qq'); 7 | 8 | var GIT_LOG_CMD = 'git log --grep="%s" -E --format=%s %s..HEAD'; 9 | var GIT_TAG_CMD = 'git describe --tags --abbrev=0'; 10 | 11 | var HEADER_TPL = '\n# %s (%s)\n\n'; 12 | var LINK_ISSUE = '[#%s](https://github.com/ocombe/ocLazyLoad/issues/%s)'; 13 | var LINK_COMMIT = '[%s](https://github.com/ocombe/ocLazyLoad/commit/%s)'; 14 | 15 | var EMPTY_COMPONENT = '$$'; 16 | 17 | 18 | var warn = function() { 19 | console.error('WARNING:', util.format.apply(null, arguments)); 20 | }; 21 | 22 | 23 | var parseRawCommit = function(raw) { 24 | if (!raw) return null; 25 | 26 | var lines = raw.split('\n'); 27 | var msg = {}, match; 28 | 29 | msg.hash = lines.shift(); 30 | msg.subject = lines.shift(); 31 | msg.closes = []; 32 | msg.breaks = []; 33 | 34 | lines.forEach(function(line) { 35 | match = line.match(/(?:Closes|Fixes)\s#(\d+)/); 36 | if (match) msg.closes.push(parseInt(match[1])); 37 | }); 38 | 39 | match = raw.match(/BREAKING CHANGE:([\s\S]*)/); 40 | if (match) { 41 | msg.breaking = match[1]; 42 | } 43 | 44 | msg.body = lines.join('\n'); 45 | match = msg.subject.match(/^(\w*)\s?\:\s?(.*)$/); 46 | 47 | if (!match || !match[1] || !match[2]) { 48 | warn('Incorrect message: %s %s', msg.hash, msg.subject); 49 | return null; 50 | } 51 | 52 | msg.type = match[1]; 53 | // msg.component = match[2]; 54 | msg.subject = match[2]; 55 | 56 | return msg; 57 | }; 58 | 59 | 60 | var linkToIssue = function(issue) { 61 | return util.format(LINK_ISSUE, issue, issue); 62 | }; 63 | 64 | 65 | var linkToCommit = function(hash) { 66 | return util.format(LINK_COMMIT, hash.substr(0, 8), hash); 67 | }; 68 | 69 | 70 | var currentDate = function() { 71 | var now = new Date(); 72 | var pad = function(i) { 73 | return ('0' + i).substr(-2); 74 | }; 75 | 76 | return util.format('%d-%s-%s', now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate())); 77 | }; 78 | 79 | 80 | var printSection = function(stream, title, section, printCommitLinks) { 81 | printCommitLinks = printCommitLinks === undefined ? true : printCommitLinks; 82 | var components = Object.getOwnPropertyNames(section).sort(); 83 | 84 | if (!components.length || section['$$'].length <= 0) return; 85 | 86 | stream.write(util.format('\n## %s\n\n', title)); 87 | 88 | components.forEach(function(name) { 89 | var prefix = '-'; 90 | var nested = section[name].length > 1; 91 | 92 | if (name !== EMPTY_COMPONENT) { 93 | if (nested) { 94 | stream.write(util.format('- **%s:**\n', name)); 95 | prefix = ' -'; 96 | } else { 97 | prefix = util.format('- **%s:**', name); 98 | } 99 | } 100 | 101 | section[name].forEach(function(commit) { 102 | if (printCommitLinks) { 103 | stream.write(util.format('%s %s\n (%s', prefix, commit.subject, linkToCommit(commit.hash))); 104 | if (commit.closes.length) { 105 | stream.write(',\n ' + commit.closes.map(linkToIssue).join(', ')); 106 | } 107 | stream.write(')\n'); 108 | } else { 109 | stream.write(util.format('%s %s', prefix, commit.subject)); 110 | } 111 | }); 112 | }); 113 | 114 | stream.write('\n'); 115 | }; 116 | 117 | 118 | var readGitLog = function(grep, from) { 119 | var deferred = q.defer(); 120 | 121 | // TODO(vojta): if it's slow, use spawn and stream it instead 122 | child.exec(util.format(GIT_LOG_CMD, grep, '%H%n%s%n%b%n==END==', from), function(code, stdout, stderr) { 123 | var commits = []; 124 | 125 | stdout.split('\n==END==\n').forEach(function(rawCommit) { 126 | var commit = parseRawCommit(rawCommit); 127 | if (commit) commits.push(commit); 128 | }); 129 | 130 | deferred.resolve(commits); 131 | }); 132 | 133 | return deferred.promise; 134 | }; 135 | 136 | 137 | var writeChangelog = function(stream, commits, version) { 138 | var sections = { 139 | fix: {}, 140 | feat: {}, 141 | perf: {}, 142 | docs: {}, 143 | breaks: {} 144 | }; 145 | 146 | sections.breaks[EMPTY_COMPONENT] = []; 147 | 148 | commits.forEach(function(commit) { 149 | var section = sections[commit.type]; 150 | var component = commit.component || EMPTY_COMPONENT; 151 | 152 | if (section) { 153 | section[component] = section[component] || []; 154 | section[component].push(commit); 155 | } 156 | 157 | if (commit.breaking) { 158 | sections.breaks[component] = sections.breaks[component] || []; 159 | sections.breaks[component].push({ 160 | subject: util.format("due to %s,\n %s", linkToCommit(commit.hash), commit.breaking), 161 | hash: commit.hash, 162 | closes: [] 163 | }); 164 | }; 165 | }); 166 | 167 | stream.write(util.format(HEADER_TPL, version, version, currentDate())); 168 | printSection(stream, 'Bug Fixes', sections.fix); 169 | printSection(stream, 'Features', sections.feat); 170 | printSection(stream, 'Performance Improvements', sections.perf); 171 | printSection(stream, 'Documentation', sections.docs); 172 | printSection(stream, 'Breaking Changes', sections.breaks, false); 173 | } 174 | 175 | 176 | var getPreviousTag = function() { 177 | var deferred = q.defer(); 178 | child.exec(GIT_TAG_CMD, function(code, stdout, stderr) { 179 | if (code) deferred.reject('Cannot get the previous tag.'); 180 | else deferred.resolve(stdout.replace('\n', '')); 181 | }); 182 | return deferred.promise; 183 | }; 184 | 185 | 186 | var generate = function(version, file) { 187 | getPreviousTag().then(function(tag) { 188 | // console.log('Reading git log since', tag); 189 | readGitLog('^fix|^feat|^perf|^docs|BREAKING', tag).then(function(commits) { 190 | // console.log('Parsed', commits.length, 'commits'); 191 | // console.log('Generating changelog to', file || 'stdout', '(', version, ')'); 192 | writeChangelog(file ? fs.createWriteStream(file) : process.stdout, commits, version); 193 | }); 194 | }); 195 | }; 196 | 197 | 198 | // publish for testing 199 | exports.parseRawCommit = parseRawCommit; 200 | 201 | // hacky start if not run by jasmine :-D 202 | if (process.argv.join('').indexOf('jasmine-node') === -1) { 203 | generate(process.argv[2], process.argv[3]); 204 | } -------------------------------------------------------------------------------- /dist/modules/ocLazyLoad.directive.js: -------------------------------------------------------------------------------- 1 | (function (angular) { 2 | 'use strict'; 3 | 4 | angular.module('oc.lazyLoad').directive('ocLazyLoad', ["$ocLazyLoad", "$compile", "$animate", "$parse", "$timeout", function ($ocLazyLoad, $compile, $animate, $parse, $timeout) { 5 | return { 6 | restrict: 'A', 7 | terminal: true, 8 | priority: 1000, 9 | compile: function compile(element, attrs) { 10 | // we store the content and remove it before compilation 11 | var content = element[0].innerHTML; 12 | element.html(''); 13 | 14 | return function ($scope, $element, $attr) { 15 | var model = $parse($attr.ocLazyLoad); 16 | $scope.$watch(function () { 17 | return model($scope) || $attr.ocLazyLoad; // it can be a module name (string), an object, an array, or a scope reference to any of this 18 | }, function (moduleName) { 19 | if (angular.isDefined(moduleName)) { 20 | $ocLazyLoad.load(moduleName).then(function () { 21 | // Attach element contents to DOM and then compile them. 22 | // This prevents an issue where IE invalidates saved element objects (HTMLCollections) 23 | // of the compiled contents when attaching to the parent DOM. 24 | $animate.enter(content, $element); 25 | // get the new content & compile it 26 | $compile($element.contents())($scope); 27 | }); 28 | } 29 | }, true); 30 | }; 31 | } 32 | }; 33 | }]); 34 | })(angular); -------------------------------------------------------------------------------- /dist/modules/ocLazyLoad.loaders.common.js: -------------------------------------------------------------------------------- 1 | (function (angular) { 2 | 'use strict'; 3 | 4 | angular.module('oc.lazyLoad').config(["$provide", function ($provide) { 5 | $provide.decorator('$ocLazyLoad', ["$delegate", "$q", "$window", "$interval", function ($delegate, $q, $window, $interval) { 6 | var uaCssChecked = false, 7 | useCssLoadPatch = false, 8 | anchor = $window.document.getElementsByTagName('head')[0] || $window.document.getElementsByTagName('body')[0]; 9 | 10 | /** 11 | * Load a js/css file 12 | * @param type 13 | * @param path 14 | * @param params 15 | * @returns promise 16 | */ 17 | $delegate.buildElement = function buildElement(type, path, params) { 18 | var deferred = $q.defer(), 19 | el, 20 | loaded, 21 | filesCache = $delegate._getFilesCache(), 22 | cacheBuster = function cacheBuster(url) { 23 | var dc = new Date().getTime(); 24 | if (url.indexOf('?') >= 0) { 25 | if (url.substring(0, url.length - 1) === '&') { 26 | return url + '_dc=' + dc; 27 | } 28 | return url + '&_dc=' + dc; 29 | } else { 30 | return url + '?_dc=' + dc; 31 | } 32 | }; 33 | 34 | // Store the promise early so the file load can be detected by other parallel lazy loads 35 | // (ie: multiple routes on one page) a 'true' value isn't sufficient 36 | // as it causes false positive load results. 37 | if (angular.isUndefined(filesCache.get(path))) { 38 | filesCache.put(path, deferred.promise); 39 | } 40 | 41 | // Switch in case more content types are added later 42 | switch (type) { 43 | case 'css': 44 | el = $window.document.createElement('link'); 45 | el.type = 'text/css'; 46 | el.rel = 'stylesheet'; 47 | el.href = params.cache === false ? cacheBuster(path) : path; 48 | break; 49 | case 'js': 50 | el = $window.document.createElement('script'); 51 | el.src = params.cache === false ? cacheBuster(path) : path; 52 | break; 53 | default: 54 | filesCache.remove(path); 55 | deferred.reject(new Error('Requested type "' + type + '" is not known. Could not inject "' + path + '"')); 56 | break; 57 | } 58 | el.onload = el['onreadystatechange'] = function (e) { 59 | if (el['readyState'] && !/^c|loade/.test(el['readyState']) || loaded) return; 60 | el.onload = el['onreadystatechange'] = null; 61 | loaded = 1; 62 | $delegate._broadcast('ocLazyLoad.fileLoaded', path); 63 | deferred.resolve(el); 64 | }; 65 | el.onerror = function () { 66 | filesCache.remove(path); 67 | deferred.reject(new Error('Unable to load ' + path)); 68 | }; 69 | el.async = params.serie ? 0 : 1; 70 | 71 | var insertBeforeElem = anchor.lastChild; 72 | if (params.insertBefore) { 73 | var element = angular.element(angular.isDefined(window.jQuery) ? params.insertBefore : document.querySelector(params.insertBefore)); 74 | if (element && element.length > 0) { 75 | insertBeforeElem = element[0]; 76 | } 77 | } 78 | insertBeforeElem.parentNode.insertBefore(el, insertBeforeElem); 79 | 80 | /* 81 | The event load or readystatechange doesn't fire in: 82 | - PhantomJS 1.9 (headless webkit browser) 83 | - iOS < 6 (default mobile browser) 84 | - Android < 4.4 (default mobile browser) 85 | - Safari < 6 (desktop browser) 86 | */ 87 | if (type == 'css') { 88 | if (!uaCssChecked) { 89 | var ua = $window.navigator.userAgent.toLowerCase(); 90 | 91 | if (ua.indexOf('phantomjs/1.9') > -1) { 92 | // PhantomJS ~1.9 93 | useCssLoadPatch = true; 94 | } else if (/iP(hone|od|ad)/.test($window.navigator.platform)) { 95 | // iOS < 6 96 | var v = $window.navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/); 97 | var iOSVersion = parseFloat([parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)].join('.')); 98 | useCssLoadPatch = iOSVersion < 6; 99 | } else if (ua.indexOf('android') > -1) { 100 | // Android < 4.4 101 | var androidVersion = parseFloat(ua.slice(ua.indexOf('android') + 8)); 102 | useCssLoadPatch = androidVersion < 4.4; 103 | } else if (ua.indexOf('safari') > -1) { 104 | // Safari < 6 105 | var versionMatch = ua.match(/version\/([\.\d]+)/i); 106 | useCssLoadPatch = versionMatch && versionMatch[1] && parseFloat(versionMatch[1]) < 6; 107 | } 108 | } 109 | 110 | if (useCssLoadPatch) { 111 | var tries = 1000; // * 20 = 20000 miliseconds 112 | var interval = $interval(function () { 113 | try { 114 | el.sheet.cssRules; 115 | $interval.cancel(interval); 116 | el.onload(); 117 | } catch (e) { 118 | if (--tries <= 0) { 119 | el.onerror(); 120 | } 121 | } 122 | }, 20); 123 | } 124 | } 125 | 126 | return deferred.promise; 127 | }; 128 | 129 | return $delegate; 130 | }]); 131 | }]); 132 | })(angular); -------------------------------------------------------------------------------- /dist/modules/ocLazyLoad.loaders.core.js: -------------------------------------------------------------------------------- 1 | (function (angular) { 2 | 'use strict'; 3 | 4 | angular.module('oc.lazyLoad').config(["$provide", function ($provide) { 5 | $provide.decorator('$ocLazyLoad', ["$delegate", "$q", function ($delegate, $q) { 6 | /** 7 | * The function that loads new files 8 | * @param config 9 | * @param params 10 | * @returns {*} 11 | */ 12 | $delegate.filesLoader = function filesLoader(config) { 13 | var params = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 14 | 15 | var cssFiles = [], 16 | templatesFiles = [], 17 | jsFiles = [], 18 | promises = [], 19 | cachePromise = null, 20 | filesCache = $delegate._getFilesCache(); 21 | 22 | $delegate.toggleWatch(true); // start watching angular.module calls 23 | 24 | angular.extend(params, config); 25 | 26 | var pushFile = function pushFile(path) { 27 | var file_type = null, 28 | m; 29 | if (angular.isObject(path)) { 30 | file_type = path.type; 31 | path = path.path; 32 | } 33 | cachePromise = filesCache.get(path); 34 | if (angular.isUndefined(cachePromise) || params.cache === false) { 35 | 36 | // always check for requirejs syntax just in case 37 | if ((m = /^(css|less|html|htm|js)?(?=!)/.exec(path)) !== null) { 38 | // Detect file type using preceding type declaration (ala requireJS) 39 | file_type = m[1]; 40 | path = path.substr(m[1].length + 1, path.length); // Strip the type from the path 41 | } 42 | 43 | if (!file_type) { 44 | if ((m = /[.](css|less|html|htm|js)?((\?|#).*)?$/.exec(path)) !== null) { 45 | // Detect file type via file extension 46 | file_type = m[1]; 47 | } else if (!$delegate.jsLoader.hasOwnProperty('ocLazyLoadLoader') && $delegate.jsLoader.hasOwnProperty('requirejs')) { 48 | // requirejs 49 | file_type = 'js'; 50 | } else { 51 | $delegate._$log.error('File type could not be determined. ' + path); 52 | return; 53 | } 54 | } 55 | 56 | if ((file_type === 'css' || file_type === 'less') && cssFiles.indexOf(path) === -1) { 57 | cssFiles.push(path); 58 | } else if ((file_type === 'html' || file_type === 'htm') && templatesFiles.indexOf(path) === -1) { 59 | templatesFiles.push(path); 60 | } else if (file_type === 'js' || jsFiles.indexOf(path) === -1) { 61 | jsFiles.push(path); 62 | } else { 63 | $delegate._$log.error('File type is not valid. ' + path); 64 | } 65 | } else if (cachePromise) { 66 | promises.push(cachePromise); 67 | } 68 | }; 69 | 70 | if (params.serie) { 71 | pushFile(params.files.shift()); 72 | } else { 73 | angular.forEach(params.files, function (path) { 74 | pushFile(path); 75 | }); 76 | } 77 | 78 | if (cssFiles.length > 0) { 79 | var cssDeferred = $q.defer(); 80 | $delegate.cssLoader(cssFiles, function (err) { 81 | if (angular.isDefined(err) && $delegate.cssLoader.hasOwnProperty('ocLazyLoadLoader')) { 82 | $delegate._$log.error(err); 83 | cssDeferred.reject(err); 84 | } else { 85 | cssDeferred.resolve(); 86 | } 87 | }, params); 88 | promises.push(cssDeferred.promise); 89 | } 90 | 91 | if (templatesFiles.length > 0) { 92 | var templatesDeferred = $q.defer(); 93 | $delegate.templatesLoader(templatesFiles, function (err) { 94 | if (angular.isDefined(err) && $delegate.templatesLoader.hasOwnProperty('ocLazyLoadLoader')) { 95 | $delegate._$log.error(err); 96 | templatesDeferred.reject(err); 97 | } else { 98 | templatesDeferred.resolve(); 99 | } 100 | }, params); 101 | promises.push(templatesDeferred.promise); 102 | } 103 | 104 | if (jsFiles.length > 0) { 105 | var jsDeferred = $q.defer(); 106 | $delegate.jsLoader(jsFiles, function (err) { 107 | if (angular.isDefined(err) && ($delegate.jsLoader.hasOwnProperty("ocLazyLoadLoader") || $delegate.jsLoader.hasOwnProperty("requirejs"))) { 108 | $delegate._$log.error(err); 109 | jsDeferred.reject(err); 110 | } else { 111 | jsDeferred.resolve(); 112 | } 113 | }, params); 114 | promises.push(jsDeferred.promise); 115 | } 116 | 117 | if (promises.length === 0) { 118 | var deferred = $q.defer(), 119 | 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'."; 120 | $delegate._$log.error(err); 121 | deferred.reject(err); 122 | return deferred.promise; 123 | } else if (params.serie && params.files.length > 0) { 124 | return $q.all(promises).then(function () { 125 | return $delegate.filesLoader(config, params); 126 | }); 127 | } else { 128 | return $q.all(promises)['finally'](function (res) { 129 | $delegate.toggleWatch(false); // stop watching angular.module calls 130 | return res; 131 | }); 132 | } 133 | }; 134 | 135 | /** 136 | * Load a module or a list of modules into Angular 137 | * @param module Mixed the name of a predefined module config object, or a module config object, or an array of either 138 | * @param params Object optional parameters 139 | * @returns promise 140 | */ 141 | $delegate.load = function (originalModule) { 142 | var originalParams = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 143 | 144 | var self = this, 145 | config = null, 146 | deferredList = [], 147 | deferred = $q.defer(), 148 | errText; 149 | 150 | // clean copy 151 | var module = angular.copy(originalModule); 152 | var params = angular.copy(originalParams); 153 | 154 | // If module is an array, break it down 155 | if (angular.isArray(module)) { 156 | // Resubmit each entry as a single module 157 | angular.forEach(module, function (m) { 158 | deferredList.push(self.load(m, params)); 159 | }); 160 | 161 | // Resolve the promise once everything has loaded 162 | $q.all(deferredList).then(function (res) { 163 | deferred.resolve(res); 164 | }, function (err) { 165 | deferred.reject(err); 166 | }); 167 | 168 | return deferred.promise; 169 | } 170 | 171 | // Get or Set a configuration depending on what was passed in 172 | if (angular.isString(module)) { 173 | config = self.getModuleConfig(module); 174 | if (!config) { 175 | config = { 176 | files: [module] 177 | }; 178 | } 179 | } else if (angular.isObject(module)) { 180 | // case {type: 'js', path: lazyLoadUrl + 'testModule.fakejs'} 181 | if (angular.isDefined(module.path) && angular.isDefined(module.type)) { 182 | config = { 183 | files: [module] 184 | }; 185 | } else { 186 | config = self.setModuleConfig(module); 187 | } 188 | } 189 | 190 | if (config === null) { 191 | var moduleName = self._getModuleName(module); 192 | errText = 'Module "' + (moduleName || 'unknown') + '" is not configured, cannot load.'; 193 | $delegate._$log.error(errText); 194 | deferred.reject(new Error(errText)); 195 | return deferred.promise; 196 | } else { 197 | // deprecated 198 | if (angular.isDefined(config.template)) { 199 | if (angular.isUndefined(config.files)) { 200 | config.files = []; 201 | } 202 | if (angular.isString(config.template)) { 203 | config.files.push(config.template); 204 | } else if (angular.isArray(config.template)) { 205 | config.files.concat(config.template); 206 | } 207 | } 208 | } 209 | 210 | var localParams = angular.extend({}, params, config); 211 | 212 | // if someone used an external loader and called the load function with just the module name 213 | if (angular.isUndefined(config.files) && angular.isDefined(config.name) && $delegate.moduleExists(config.name)) { 214 | return $delegate.inject(config.name, localParams, true); 215 | } 216 | 217 | $delegate.filesLoader(config, localParams).then(function () { 218 | $delegate.inject(null, localParams).then(function (res) { 219 | deferred.resolve(res); 220 | }, function (err) { 221 | deferred.reject(err); 222 | }); 223 | }, function (err) { 224 | deferred.reject(err); 225 | }); 226 | 227 | return deferred.promise; 228 | }; 229 | 230 | // return the patched service 231 | return $delegate; 232 | }]); 233 | }]); 234 | })(angular); -------------------------------------------------------------------------------- /dist/modules/ocLazyLoad.loaders.cssLoader.js: -------------------------------------------------------------------------------- 1 | (function (angular) { 2 | 'use strict'; 3 | 4 | angular.module('oc.lazyLoad').config(["$provide", function ($provide) { 5 | $provide.decorator('$ocLazyLoad', ["$delegate", "$q", function ($delegate, $q) { 6 | /** 7 | * cssLoader function 8 | * @type Function 9 | * @param paths array list of css files to load 10 | * @param callback to call when everything is loaded. We use a callback and not a promise 11 | * @param params object config parameters 12 | * because the user can overwrite cssLoader and it will probably not use promises :( 13 | */ 14 | $delegate.cssLoader = function (paths, callback, params) { 15 | var promises = []; 16 | angular.forEach(paths, function (path) { 17 | promises.push($delegate.buildElement('css', path, params)); 18 | }); 19 | $q.all(promises).then(function () { 20 | callback(); 21 | }, function (err) { 22 | callback(err); 23 | }); 24 | }; 25 | $delegate.cssLoader.ocLazyLoadLoader = true; 26 | 27 | return $delegate; 28 | }]); 29 | }]); 30 | })(angular); -------------------------------------------------------------------------------- /dist/modules/ocLazyLoad.loaders.jsLoader.js: -------------------------------------------------------------------------------- 1 | (function (angular) { 2 | 'use strict'; 3 | 4 | angular.module('oc.lazyLoad').config(["$provide", function ($provide) { 5 | $provide.decorator('$ocLazyLoad', ["$delegate", "$q", function ($delegate, $q) { 6 | /** 7 | * jsLoader function 8 | * @type Function 9 | * @param paths array list of js files to load 10 | * @param callback to call when everything is loaded. We use a callback and not a promise 11 | * @param params object config parameters 12 | * because the user can overwrite jsLoader and it will probably not use promises :( 13 | */ 14 | $delegate.jsLoader = function (paths, callback, params) { 15 | var promises = []; 16 | angular.forEach(paths, function (path) { 17 | promises.push($delegate.buildElement('js', path, params)); 18 | }); 19 | $q.all(promises).then(function () { 20 | callback(); 21 | }, function (err) { 22 | callback(err); 23 | }); 24 | }; 25 | $delegate.jsLoader.ocLazyLoadLoader = true; 26 | 27 | return $delegate; 28 | }]); 29 | }]); 30 | })(angular); -------------------------------------------------------------------------------- /dist/modules/ocLazyLoad.loaders.requireJSLoader.js: -------------------------------------------------------------------------------- 1 | (function (angular) { 2 | 'use strict'; 3 | 4 | angular.module('oc.lazyLoad').config(["$provide", function ($provide) { 5 | $provide.decorator('$ocLazyLoad', ["$delegate", "$q", function ($delegate, $q) { 6 | /** 7 | * jsLoader function 8 | * @type Function 9 | * @param paths array list of js files to load 10 | * @param callback to call when everything is loaded. We use a callback and not a promise 11 | * @param params object config parameters 12 | * because the user can overwrite jsLoader and it will probably not use promises :( 13 | */ 14 | $delegate.jsLoader = function (paths, callback, params) { 15 | require(paths, callback.bind(null, undefined), callback, params); 16 | }; 17 | $delegate.jsLoader.requirejs = true; 18 | 19 | return $delegate; 20 | }]); 21 | }]); 22 | })(angular); -------------------------------------------------------------------------------- /dist/modules/ocLazyLoad.loaders.templatesLoader.js: -------------------------------------------------------------------------------- 1 | (function (angular) { 2 | 'use strict'; 3 | 4 | angular.module('oc.lazyLoad').config(["$provide", function ($provide) { 5 | $provide.decorator('$ocLazyLoad', ["$delegate", "$templateCache", "$q", "$http", function ($delegate, $templateCache, $q, $http) { 6 | /** 7 | * templatesLoader function 8 | * @type Function 9 | * @param paths array list of css files to load 10 | * @param callback to call when everything is loaded. We use a callback and not a promise 11 | * @param params object config parameters for $http 12 | * because the user can overwrite templatesLoader and it will probably not use promises :( 13 | */ 14 | $delegate.templatesLoader = function (paths, callback, params) { 15 | var promises = [], 16 | filesCache = $delegate._getFilesCache(); 17 | 18 | angular.forEach(paths, function (url) { 19 | var deferred = $q.defer(); 20 | promises.push(deferred.promise); 21 | $http.get(url, params).then(function (response) { 22 | var data = response.data; 23 | if (angular.isString(data) && data.length > 0) { 24 | angular.forEach(angular.element(data), function (node) { 25 | if (node.nodeName === 'SCRIPT' && node.type === 'text/ng-template') { 26 | $templateCache.put(node.id, node.innerHTML); 27 | } 28 | }); 29 | } 30 | if (angular.isUndefined(filesCache.get(url))) { 31 | filesCache.put(url, true); 32 | } 33 | deferred.resolve(); 34 | })['catch'](function (response) { 35 | deferred.reject(new Error('Unable to load template file "' + url + '": ' + response.data)); 36 | }); 37 | }); 38 | return $q.all(promises).then(function () { 39 | callback(); 40 | }, function (err) { 41 | callback(err); 42 | }); 43 | }; 44 | $delegate.templatesLoader.ocLazyLoadLoader = true; 45 | 46 | return $delegate; 47 | }]); 48 | }]); 49 | })(angular); -------------------------------------------------------------------------------- /dist/modules/ocLazyLoad.polyfill.ie8.js: -------------------------------------------------------------------------------- 1 | // Array.indexOf polyfill for IE8 2 | if (!Array.prototype.indexOf) { 3 | Array.prototype.indexOf = function (searchElement, fromIndex) { 4 | var k; 5 | 6 | // 1. Let O be the result of calling ToObject passing 7 | // the this value as the argument. 8 | if (this == null) { 9 | throw new TypeError('"this" is null or not defined'); 10 | } 11 | 12 | var O = Object(this); 13 | 14 | // 2. Let lenValue be the result of calling the Get 15 | // internal method of O with the argument "length". 16 | // 3. Let len be ToUint32(lenValue). 17 | var len = O.length >>> 0; 18 | 19 | // 4. If len is 0, return -1. 20 | if (len === 0) { 21 | return -1; 22 | } 23 | 24 | // 5. If argument fromIndex was passed let n be 25 | // ToInteger(fromIndex); else let n be 0. 26 | var n = +fromIndex || 0; 27 | 28 | if (Math.abs(n) === Infinity) { 29 | n = 0; 30 | } 31 | 32 | // 6. If n >= len, return -1. 33 | if (n >= len) { 34 | return -1; 35 | } 36 | 37 | // 7. If n >= 0, then Let k be n. 38 | // 8. Else, n<0, Let k be len - abs(n). 39 | // If k is less than 0, then let k be 0. 40 | k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); 41 | 42 | // 9. Repeat, while k < len 43 | while (k < len) { 44 | // a. Let Pk be ToString(k). 45 | // This is implicit for LHS operands of the in operator 46 | // b. Let kPresent be the result of calling the 47 | // HasProperty internal method of O with argument Pk. 48 | // This step can be combined with c 49 | // c. If kPresent is true, then 50 | // i. Let elementK be the result of calling the Get 51 | // internal method of O with the argument ToString(k). 52 | // ii. Let same be the result of applying the 53 | // Strict Equality Comparison Algorithm to 54 | // searchElement and elementK. 55 | // iii. If same is true, return k. 56 | if (k in O && O[k] === searchElement) { 57 | return k; 58 | } 59 | k++; 60 | } 61 | return -1; 62 | }; 63 | } -------------------------------------------------------------------------------- /dist/ocLazyLoad.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * oclazyload - Load modules on demand (lazy load) with angularJS 3 | * @version v1.0.10 4 | * @link https://github.com/ocombe/ocLazyLoad 5 | * @license MIT 6 | * @author Olivier Combe 7 | */ 8 | !function(e,n){"use strict";var r=["ng","oc.lazyLoad"],o={},t=[],i=[],a=[],s=[],u=e.noop,c={},d=[],l=e.module("oc.lazyLoad",["ng"]);l.provider("$ocLazyLoad",["$controllerProvider","$provide","$compileProvider","$filterProvider","$injector","$animateProvider",function(l,f,p,m,v,y){function L(n,o,t){if(o){var i,s,l,f=[];for(i=o.length-1;i>=0;i--)if(s=o[i],e.isString(s)||(s=E(s)),s&&-1===d.indexOf(s)&&(!w[s]||-1!==a.indexOf(s))){var h=-1===r.indexOf(s);if(l=g(s),h&&(r.push(s),L(n,l.requires,t)),l._runBlocks.length>0)for(c[s]=[];l._runBlocks.length>0;)c[s].push(l._runBlocks.shift());e.isDefined(c[s])&&(h||t.rerun)&&(f=f.concat(c[s])),j(n,l._invokeQueue,s,t.reconfig),j(n,l._configBlocks,s,t.reconfig),u(h?"ocLazyLoad.moduleLoaded":"ocLazyLoad.moduleReloaded",s),o.pop(),d.push(s)}var p=n.getInstanceInjector();e.forEach(f,function(e){p.invoke(e)})}}function $(n,r){function t(n,r){var o,t=!0;return r.length&&(o=i(n),e.forEach(r,function(e){t=t&&i(e)!==o})),t}function i(n){return e.isArray(n)?M(n.toString()):e.isObject(n)?M(S(n)):e.isDefined(n)&&null!==n?M(n.toString()):n}var a=n[2][0],s=n[1],c=!1;e.isUndefined(o[r])&&(o[r]={}),e.isUndefined(o[r][s])&&(o[r][s]={});var d=function(e,n){o[r][s].hasOwnProperty(e)||(o[r][s][e]=[]),t(n,o[r][s][e])&&(c=!0,o[r][s][e].push(n),u("ocLazyLoad.componentLoaded",[r,s,e]))};if(e.isString(a))d(a,n[2][1]);else{if(!e.isObject(a))return!1;e.forEach(a,function(n,r){e.isString(n)?d(n,a[1]):d(r,n)})}return c}function j(n,r,o,i){if(r){var a,s,u,c;for(a=0,s=r.length;s>a;a++)if(u=r[a],e.isArray(u)){if(null!==n){if(!n.hasOwnProperty(u[0]))throw new Error("unsupported provider "+u[0]);c=n[u[0]]}var d=$(u,o);if("invoke"!==u[1])d&&e.isDefined(c)&&c[u[1]].apply(c,u[2]);else{var l=function(n){var r=t.indexOf(o+"-"+n);(-1===r||i)&&(-1===r&&t.push(o+"-"+n),e.isDefined(c)&&c[u[1]].apply(c,u[2]))};if(e.isFunction(u[2][0]))l(u[2][0]);else if(e.isArray(u[2][0]))for(var f=0,h=u[2][0].length;h>f;f++)e.isFunction(u[2][0][f])&&l(u[2][0][f])}}}}function E(n){var r=null;return e.isString(n)?r=n:e.isObject(n)&&n.hasOwnProperty("name")&&e.isString(n.name)&&(r=n.name),r}function _(n){if(!e.isString(n))return!1;try{return g(n)}catch(r){if(/No module/.test(r)||r.message.indexOf("$injector:nomod")>-1)return!1}}var w={},O={$controllerProvider:l,$compileProvider:p,$filterProvider:m,$provide:f,$injector:v,$animateProvider:y},x=!1,b=!1,z=[],D={};z.push=function(e){-1===this.indexOf(e)&&Array.prototype.push.apply(this,arguments)},this.config=function(n){e.isDefined(n.modules)&&(e.isArray(n.modules)?e.forEach(n.modules,function(e){w[e.name]=e}):w[n.modules.name]=n.modules),e.isDefined(n.debug)&&(x=n.debug),e.isDefined(n.events)&&(b=n.events)},this._init=function(o){if(0===i.length){var t=[o],a=["ng:app","ng-app","x-ng-app","data-ng-app"],u=/\sng[:\-]app(:\s*([\w\d_]+);?)?\s/,c=function(e){return e&&t.push(e)};e.forEach(a,function(n){a[n]=!0,c(document.getElementById(n)),n=n.replace(":","\\:"),"undefined"!=typeof o[0]&&o[0].querySelectorAll&&(e.forEach(o[0].querySelectorAll("."+n),c),e.forEach(o[0].querySelectorAll("."+n+"\\:"),c),e.forEach(o[0].querySelectorAll("["+n+"]"),c))}),e.forEach(t,function(n){if(0===i.length){var r=" "+o.className+" ",t=u.exec(r);t?i.push((t[2]||"").replace(/\s+/g,",")):e.forEach(n.attributes,function(e){0===i.length&&a[e.name]&&i.push(e.value)})}})}0!==i.length||(n.jasmine||n.mocha)&&e.isDefined(e.mock)||console.error("No module found during bootstrap, unable to init ocLazyLoad. You should always use the ng-app directive or angular.boostrap when you use ocLazyLoad.");var d=function l(n){if(-1===r.indexOf(n)){r.push(n);var o=e.module(n);j(null,o._invokeQueue,n),j(null,o._configBlocks,n),e.forEach(o.requires,l)}};e.forEach(i,function(e){d(e)}),i=[],s.pop()};var S=function(n){try{return JSON.stringify(n)}catch(r){var o=[];return JSON.stringify(n,function(n,r){if(e.isObject(r)&&null!==r){if(-1!==o.indexOf(r))return;o.push(r)}return r})}},M=function(e){var n,r,o,t=0;if(0==e.length)return t;for(n=0,o=e.length;o>n;n++)r=e.charCodeAt(n),t=(t<<5)-t+r,t|=0;return t};this.$get=["$log","$rootElement","$rootScope","$cacheFactory","$q",function(n,t,a,c,l){function f(e){var r=l.defer();return n.error(e.message),r.reject(e),r.promise}var p,m=c("ocLazyLoad");return x||(n={},n.error=e.noop,n.warn=e.noop,n.info=e.noop),O.getInstanceInjector=function(){return p?p:p=t.data("$injector")||e.injector()},u=function(e,r){b&&a.$broadcast(e,r),x&&n.info(e,r)},{_broadcast:u,_$log:n,_getFilesCache:function(){return m},toggleWatch:function(e){e?s.push(!0):s.pop()},getModuleConfig:function(n){if(!e.isString(n))throw new Error("You need to give the name of the module to get");return w[n]?e.copy(w[n]):null},setModuleConfig:function(n){if(!e.isObject(n))throw new Error("You need to give the module config object to set");return w[n.name]=n,n},getModules:function(){return r},isLoaded:function(n){var o=function(e){var n=r.indexOf(e)>-1;return n||(n=!!_(e)),n};if(e.isString(n)&&(n=[n]),e.isArray(n)){var t,i;for(t=0,i=n.length;i>t;t++)if(!o(n[t]))return!1;return!0}throw new Error("You need to define the module(s) name(s)")},_getModuleName:E,_getModule:function(e){try{return g(e)}catch(n){throw(/No module/.test(n)||n.message.indexOf("$injector:nomod")>-1)&&(n.message='The module "'+S(e)+'" that you are trying to load does not exist. '+n.message),n}},moduleExists:_,_loadDependencies:function(n,r){var o,t,i,a=[],s=this;if(n=s._getModuleName(n),null===n)return l.when();try{o=s._getModule(n)}catch(u){return f(u)}return t=s.getRequires(o),e.forEach(t,function(o){if(e.isString(o)){var t=s.getModuleConfig(o);if(null===t)return void z.push(o);o=t,t.name=void 0}if(s.moduleExists(o.name))return i=o.files.filter(function(e){return s.getModuleConfig(o.name).files.indexOf(e)<0}),0!==i.length&&s._$log.warn('Module "',n,'" attempted to redefine configuration for dependency. "',o.name,'"\n Additional Files Loaded:',i),e.isDefined(s.filesLoader)?void a.push(s.filesLoader(o,r).then(function(){return s._loadDependencies(o)})):f(new Error("Error: New dependencies need to be loaded from external files ("+o.files+"), but no loader has been defined."));if(e.isArray(o)){var u=[];e.forEach(o,function(e){var n=s.getModuleConfig(e);null===n?u.push(e):n.files&&(u=u.concat(n.files))}),u.length>0&&(o={files:u})}else e.isObject(o)&&o.hasOwnProperty("name")&&o.name&&(s.setModuleConfig(o),z.push(o.name));if(e.isDefined(o.files)&&0!==o.files.length){if(!e.isDefined(s.filesLoader))return f(new Error('Error: the module "'+o.name+'" is defined in external files ('+o.files+"), but no loader has been defined."));a.push(s.filesLoader(o,r).then(function(){return s._loadDependencies(o)}))}}),l.all(a)},inject:function(n){var r=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],o=arguments.length<=2||void 0===arguments[2]?!1:arguments[2],t=this,a=l.defer();if(e.isDefined(n)&&null!==n){if(e.isArray(n)){var s=[];return e.forEach(n,function(e){s.push(t.inject(e,r,o))}),l.all(s)}t._addToLoadList(t._getModuleName(n),!0,o)}if(i.length>0){var u=i.slice(),c=function f(e){z.push(e),D[e]=a.promise,t._loadDependencies(e,r).then(function(){try{d=[],L(O,z,r)}catch(e){return t._$log.error(e.message),void a.reject(e)}i.length>0?f(i.shift()):a.resolve(u)},function(e){a.reject(e)})};c(i.shift())}else{if(r&&r.name&&D[r.name])return D[r.name];a.resolve()}return a.promise},getRequires:function(n){var o=[];return e.forEach(n.requires,function(e){-1===r.indexOf(e)&&o.push(e)}),o},_invokeQueue:j,_registerInvokeList:$,_register:L,_addToLoadList:h,_unregister:function(n){e.isDefined(n)&&e.isArray(n)&&e.forEach(n,function(e){o[e]=void 0})}}}],this._init(e.element(n.document))}]);var f=e.bootstrap;e.bootstrap=function(n,l,g){return r=["ng","oc.lazyLoad"],o={},t=[],i=[],a=[],s=[],u=e.noop,c={},d=[],e.forEach(l.slice(),function(e){h(e,!0,!0)}),f(n,l,g)};var h=function(n,r,o){(s.length>0||r)&&e.isString(n)&&-1===i.indexOf(n)&&(i.push(n),o&&a.push(n))},g=e.module;e.module=function(e,n,r){return h(e,!1,!0),g(e,n,r)},"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="oc.lazyLoad")}(angular,window),function(e){"use strict";e.module("oc.lazyLoad").directive("ocLazyLoad",["$ocLazyLoad","$compile","$animate","$parse","$timeout",function(n,r,o,t,i){return{restrict:"A",terminal:!0,priority:1e3,compile:function(i,a){var s=i[0].innerHTML;return i.html(""),function(i,a,u){var c=t(u.ocLazyLoad);i.$watch(function(){return c(i)||u.ocLazyLoad},function(t){e.isDefined(t)&&n.load(t).then(function(){o.enter(s,a),r(a.contents())(i)})},!0)}}}}])}(angular),function(e){"use strict";e.module("oc.lazyLoad").config(["$provide",function(n){n.decorator("$ocLazyLoad",["$delegate","$q","$window","$interval",function(n,r,o,t){var i=!1,a=!1,s=o.document.getElementsByTagName("head")[0]||o.document.getElementsByTagName("body")[0];return n.buildElement=function(u,c,d){var l,f,h=r.defer(),g=n._getFilesCache(),p=function(e){var n=(new Date).getTime();return e.indexOf("?")>=0?"&"===e.substring(0,e.length-1)?e+"_dc="+n:e+"&_dc="+n:e+"?_dc="+n};switch(e.isUndefined(g.get(c))&&g.put(c,h.promise),u){case"css":l=o.document.createElement("link"),l.type="text/css",l.rel="stylesheet",l.href=d.cache===!1?p(c):c;break;case"js":l=o.document.createElement("script"),l.src=d.cache===!1?p(c):c;break;default:g.remove(c),h.reject(new Error('Requested type "'+u+'" is not known. Could not inject "'+c+'"'))}l.onload=l.onreadystatechange=function(e){l.readyState&&!/^c|loade/.test(l.readyState)||f||(l.onload=l.onreadystatechange=null,f=1,n._broadcast("ocLazyLoad.fileLoaded",c),h.resolve(l))},l.onerror=function(){g.remove(c),h.reject(new Error("Unable to load "+c))},l.async=d.serie?0:1;var m=s.lastChild;if(d.insertBefore){var v=e.element(e.isDefined(window.jQuery)?d.insertBefore:document.querySelector(d.insertBefore));v&&v.length>0&&(m=v[0])}if(m.parentNode.insertBefore(l,m),"css"==u){if(!i){var y=o.navigator.userAgent.toLowerCase();if(y.indexOf("phantomjs/1.9")>-1)a=!0;else if(/iP(hone|od|ad)/.test(o.navigator.platform)){var L=o.navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/),$=parseFloat([parseInt(L[1],10),parseInt(L[2],10),parseInt(L[3]||0,10)].join("."));a=6>$}else if(y.indexOf("android")>-1){var j=parseFloat(y.slice(y.indexOf("android")+8));a=4.4>j}else if(y.indexOf("safari")>-1){var E=y.match(/version\/([\.\d]+)/i);a=E&&E[1]&&parseFloat(E[1])<6}}if(a)var _=1e3,w=t(function(){try{l.sheet.cssRules,t.cancel(w),l.onload()}catch(e){--_<=0&&l.onerror()}},20)}return h.promise},n}])}])}(angular),function(e){"use strict";e.module("oc.lazyLoad").config(["$provide",function(n){n.decorator("$ocLazyLoad",["$delegate","$q",function(n,r){return n.filesLoader=function(o){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],i=[],a=[],s=[],u=[],c=null,d=n._getFilesCache();n.toggleWatch(!0),e.extend(t,o);var l=function(r){var o,l=null;if(e.isObject(r)&&(l=r.type,r=r.path),c=d.get(r),e.isUndefined(c)||t.cache===!1){if(null!==(o=/^(css|less|html|htm|js)?(?=!)/.exec(r))&&(l=o[1],r=r.substr(o[1].length+1,r.length)),!l)if(null!==(o=/[.](css|less|html|htm|js)?((\?|#).*)?$/.exec(r)))l=o[1];else{if(n.jsLoader.hasOwnProperty("ocLazyLoadLoader")||!n.jsLoader.hasOwnProperty("requirejs"))return void n._$log.error("File type could not be determined. "+r);l="js"}"css"!==l&&"less"!==l||-1!==i.indexOf(r)?"html"!==l&&"htm"!==l||-1!==a.indexOf(r)?"js"===l||-1===s.indexOf(r)?s.push(r):n._$log.error("File type is not valid. "+r):a.push(r):i.push(r)}else c&&u.push(c)};if(t.serie?l(t.files.shift()):e.forEach(t.files,function(e){l(e)}),i.length>0){var f=r.defer();n.cssLoader(i,function(r){e.isDefined(r)&&n.cssLoader.hasOwnProperty("ocLazyLoadLoader")?(n._$log.error(r),f.reject(r)):f.resolve()},t),u.push(f.promise)}if(a.length>0){var h=r.defer();n.templatesLoader(a,function(r){e.isDefined(r)&&n.templatesLoader.hasOwnProperty("ocLazyLoadLoader")?(n._$log.error(r),h.reject(r)):h.resolve()},t),u.push(h.promise)}if(s.length>0){var g=r.defer();n.jsLoader(s,function(r){e.isDefined(r)&&(n.jsLoader.hasOwnProperty("ocLazyLoadLoader")||n.jsLoader.hasOwnProperty("requirejs"))?(n._$log.error(r),g.reject(r)):g.resolve()},t),u.push(g.promise)}if(0===u.length){var p=r.defer(),m="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'.";return n._$log.error(m),p.reject(m),p.promise}return t.serie&&t.files.length>0?r.all(u).then(function(){return n.filesLoader(o,t)}):r.all(u)["finally"](function(e){return n.toggleWatch(!1),e})},n.load=function(o){var t,i=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],a=this,s=null,u=[],c=r.defer(),d=e.copy(o),l=e.copy(i);if(e.isArray(d))return e.forEach(d,function(e){u.push(a.load(e,l))}),r.all(u).then(function(e){c.resolve(e)},function(e){c.reject(e)}),c.promise;if(e.isString(d)?(s=a.getModuleConfig(d),s||(s={files:[d]})):e.isObject(d)&&(s=e.isDefined(d.path)&&e.isDefined(d.type)?{files:[d]}:a.setModuleConfig(d)),null===s){var f=a._getModuleName(d);return t='Module "'+(f||"unknown")+'" is not configured, cannot load.',n._$log.error(t),c.reject(new Error(t)),c.promise}e.isDefined(s.template)&&(e.isUndefined(s.files)&&(s.files=[]),e.isString(s.template)?s.files.push(s.template):e.isArray(s.template)&&s.files.concat(s.template));var h=e.extend({},l,s);return e.isUndefined(s.files)&&e.isDefined(s.name)&&n.moduleExists(s.name)?n.inject(s.name,h,!0):(n.filesLoader(s,h).then(function(){n.inject(null,h).then(function(e){c.resolve(e)},function(e){c.reject(e)})},function(e){c.reject(e)}),c.promise)},n}])}])}(angular),function(e){"use strict";e.module("oc.lazyLoad").config(["$provide",function(n){n.decorator("$ocLazyLoad",["$delegate","$q",function(n,r){return n.cssLoader=function(o,t,i){var a=[];e.forEach(o,function(e){a.push(n.buildElement("css",e,i))}),r.all(a).then(function(){t()},function(e){t(e)})},n.cssLoader.ocLazyLoadLoader=!0,n}])}])}(angular),function(e){"use strict";e.module("oc.lazyLoad").config(["$provide",function(n){n.decorator("$ocLazyLoad",["$delegate","$q",function(n,r){return n.jsLoader=function(o,t,i){var a=[];e.forEach(o,function(e){a.push(n.buildElement("js",e,i))}),r.all(a).then(function(){t()},function(e){t(e)})},n.jsLoader.ocLazyLoadLoader=!0,n}])}])}(angular),function(e){"use strict";e.module("oc.lazyLoad").config(["$provide",function(n){n.decorator("$ocLazyLoad",["$delegate","$templateCache","$q","$http",function(n,r,o,t){return n.templatesLoader=function(i,a,s){var u=[],c=n._getFilesCache();return e.forEach(i,function(n){var i=o.defer();u.push(i.promise),t.get(n,s).then(function(o){var t=o.data;e.isString(t)&&t.length>0&&e.forEach(e.element(t),function(e){"SCRIPT"===e.nodeName&&"text/ng-template"===e.type&&r.put(e.id,e.innerHTML)}),e.isUndefined(c.get(n))&&c.put(n,!0),i.resolve()})["catch"](function(e){i.reject(new Error('Unable to load template file "'+n+'": '+e.data))})}),o.all(u).then(function(){a()},function(e){a(e)})},n.templatesLoader.ocLazyLoadLoader=!0,n}])}])}(angular),Array.prototype.indexOf||(Array.prototype.indexOf=function(e,n){var r;if(null==this)throw new TypeError('"this" is null or not defined');var o=Object(this),t=o.length>>>0;if(0===t)return-1;var i=+n||0;if(Math.abs(i)===1/0&&(i=0),i>=t)return-1;for(r=Math.max(i>=0?i:t-Math.abs(i),0);t>r;){if(r in o&&o[r]===e)return r;r++}return-1}); -------------------------------------------------------------------------------- /dist/ocLazyLoad.require.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * oclazyload - Load modules on demand (lazy load) with angularJS 3 | * @version v1.0.10 4 | * @link https://github.com/ocombe/ocLazyLoad 5 | * @license MIT 6 | * @author Olivier Combe 7 | */ 8 | !function(e,n){"use strict";var r=["ng","oc.lazyLoad"],o={},t=[],i=[],a=[],s=[],u=e.noop,c={},d=[],l=e.module("oc.lazyLoad",["ng"]);l.provider("$ocLazyLoad",["$controllerProvider","$provide","$compileProvider","$filterProvider","$injector","$animateProvider",function(l,f,p,m,v,y){function L(n,o,t){if(o){var i,s,l,f=[];for(i=o.length-1;i>=0;i--)if(s=o[i],e.isString(s)||(s=E(s)),s&&-1===d.indexOf(s)&&(!w[s]||-1!==a.indexOf(s))){var h=-1===r.indexOf(s);if(l=g(s),h&&(r.push(s),L(n,l.requires,t)),l._runBlocks.length>0)for(c[s]=[];l._runBlocks.length>0;)c[s].push(l._runBlocks.shift());e.isDefined(c[s])&&(h||t.rerun)&&(f=f.concat(c[s])),j(n,l._invokeQueue,s,t.reconfig),j(n,l._configBlocks,s,t.reconfig),u(h?"ocLazyLoad.moduleLoaded":"ocLazyLoad.moduleReloaded",s),o.pop(),d.push(s)}var p=n.getInstanceInjector();e.forEach(f,function(e){p.invoke(e)})}}function $(n,r){function t(n,r){var o,t=!0;return r.length&&(o=i(n),e.forEach(r,function(e){t=t&&i(e)!==o})),t}function i(n){return e.isArray(n)?M(n.toString()):e.isObject(n)?M(S(n)):e.isDefined(n)&&null!==n?M(n.toString()):n}var a=n[2][0],s=n[1],c=!1;e.isUndefined(o[r])&&(o[r]={}),e.isUndefined(o[r][s])&&(o[r][s]={});var d=function(e,n){o[r][s].hasOwnProperty(e)||(o[r][s][e]=[]),t(n,o[r][s][e])&&(c=!0,o[r][s][e].push(n),u("ocLazyLoad.componentLoaded",[r,s,e]))};if(e.isString(a))d(a,n[2][1]);else{if(!e.isObject(a))return!1;e.forEach(a,function(n,r){e.isString(n)?d(n,a[1]):d(r,n)})}return c}function j(n,r,o,i){if(r){var a,s,u,c;for(a=0,s=r.length;s>a;a++)if(u=r[a],e.isArray(u)){if(null!==n){if(!n.hasOwnProperty(u[0]))throw new Error("unsupported provider "+u[0]);c=n[u[0]]}var d=$(u,o);if("invoke"!==u[1])d&&e.isDefined(c)&&c[u[1]].apply(c,u[2]);else{var l=function(n){var r=t.indexOf(o+"-"+n);(-1===r||i)&&(-1===r&&t.push(o+"-"+n),e.isDefined(c)&&c[u[1]].apply(c,u[2]))};if(e.isFunction(u[2][0]))l(u[2][0]);else if(e.isArray(u[2][0]))for(var f=0,h=u[2][0].length;h>f;f++)e.isFunction(u[2][0][f])&&l(u[2][0][f])}}}}function E(n){var r=null;return e.isString(n)?r=n:e.isObject(n)&&n.hasOwnProperty("name")&&e.isString(n.name)&&(r=n.name),r}function _(n){if(!e.isString(n))return!1;try{return g(n)}catch(r){if(/No module/.test(r)||r.message.indexOf("$injector:nomod")>-1)return!1}}var w={},O={$controllerProvider:l,$compileProvider:p,$filterProvider:m,$provide:f,$injector:v,$animateProvider:y},x=!1,b=!1,z=[],D={};z.push=function(e){-1===this.indexOf(e)&&Array.prototype.push.apply(this,arguments)},this.config=function(n){e.isDefined(n.modules)&&(e.isArray(n.modules)?e.forEach(n.modules,function(e){w[e.name]=e}):w[n.modules.name]=n.modules),e.isDefined(n.debug)&&(x=n.debug),e.isDefined(n.events)&&(b=n.events)},this._init=function(o){if(0===i.length){var t=[o],a=["ng:app","ng-app","x-ng-app","data-ng-app"],u=/\sng[:\-]app(:\s*([\w\d_]+);?)?\s/,c=function(e){return e&&t.push(e)};e.forEach(a,function(n){a[n]=!0,c(document.getElementById(n)),n=n.replace(":","\\:"),"undefined"!=typeof o[0]&&o[0].querySelectorAll&&(e.forEach(o[0].querySelectorAll("."+n),c),e.forEach(o[0].querySelectorAll("."+n+"\\:"),c),e.forEach(o[0].querySelectorAll("["+n+"]"),c))}),e.forEach(t,function(n){if(0===i.length){var r=" "+o.className+" ",t=u.exec(r);t?i.push((t[2]||"").replace(/\s+/g,",")):e.forEach(n.attributes,function(e){0===i.length&&a[e.name]&&i.push(e.value)})}})}0!==i.length||(n.jasmine||n.mocha)&&e.isDefined(e.mock)||console.error("No module found during bootstrap, unable to init ocLazyLoad. You should always use the ng-app directive or angular.boostrap when you use ocLazyLoad.");var d=function l(n){if(-1===r.indexOf(n)){r.push(n);var o=e.module(n);j(null,o._invokeQueue,n),j(null,o._configBlocks,n),e.forEach(o.requires,l)}};e.forEach(i,function(e){d(e)}),i=[],s.pop()};var S=function(n){try{return JSON.stringify(n)}catch(r){var o=[];return JSON.stringify(n,function(n,r){if(e.isObject(r)&&null!==r){if(-1!==o.indexOf(r))return;o.push(r)}return r})}},M=function(e){var n,r,o,t=0;if(0==e.length)return t;for(n=0,o=e.length;o>n;n++)r=e.charCodeAt(n),t=(t<<5)-t+r,t|=0;return t};this.$get=["$log","$rootElement","$rootScope","$cacheFactory","$q",function(n,t,a,c,l){function f(e){var r=l.defer();return n.error(e.message),r.reject(e),r.promise}var p,m=c("ocLazyLoad");return x||(n={},n.error=e.noop,n.warn=e.noop,n.info=e.noop),O.getInstanceInjector=function(){return p?p:p=t.data("$injector")||e.injector()},u=function(e,r){b&&a.$broadcast(e,r),x&&n.info(e,r)},{_broadcast:u,_$log:n,_getFilesCache:function(){return m},toggleWatch:function(e){e?s.push(!0):s.pop()},getModuleConfig:function(n){if(!e.isString(n))throw new Error("You need to give the name of the module to get");return w[n]?e.copy(w[n]):null},setModuleConfig:function(n){if(!e.isObject(n))throw new Error("You need to give the module config object to set");return w[n.name]=n,n},getModules:function(){return r},isLoaded:function(n){var o=function(e){var n=r.indexOf(e)>-1;return n||(n=!!_(e)),n};if(e.isString(n)&&(n=[n]),e.isArray(n)){var t,i;for(t=0,i=n.length;i>t;t++)if(!o(n[t]))return!1;return!0}throw new Error("You need to define the module(s) name(s)")},_getModuleName:E,_getModule:function(e){try{return g(e)}catch(n){throw(/No module/.test(n)||n.message.indexOf("$injector:nomod")>-1)&&(n.message='The module "'+S(e)+'" that you are trying to load does not exist. '+n.message),n}},moduleExists:_,_loadDependencies:function(n,r){var o,t,i,a=[],s=this;if(n=s._getModuleName(n),null===n)return l.when();try{o=s._getModule(n)}catch(u){return f(u)}return t=s.getRequires(o),e.forEach(t,function(o){if(e.isString(o)){var t=s.getModuleConfig(o);if(null===t)return void z.push(o);o=t,t.name=void 0}if(s.moduleExists(o.name))return i=o.files.filter(function(e){return s.getModuleConfig(o.name).files.indexOf(e)<0}),0!==i.length&&s._$log.warn('Module "',n,'" attempted to redefine configuration for dependency. "',o.name,'"\n Additional Files Loaded:',i),e.isDefined(s.filesLoader)?void a.push(s.filesLoader(o,r).then(function(){return s._loadDependencies(o)})):f(new Error("Error: New dependencies need to be loaded from external files ("+o.files+"), but no loader has been defined."));if(e.isArray(o)){var u=[];e.forEach(o,function(e){var n=s.getModuleConfig(e);null===n?u.push(e):n.files&&(u=u.concat(n.files))}),u.length>0&&(o={files:u})}else e.isObject(o)&&o.hasOwnProperty("name")&&o.name&&(s.setModuleConfig(o),z.push(o.name));if(e.isDefined(o.files)&&0!==o.files.length){if(!e.isDefined(s.filesLoader))return f(new Error('Error: the module "'+o.name+'" is defined in external files ('+o.files+"), but no loader has been defined."));a.push(s.filesLoader(o,r).then(function(){return s._loadDependencies(o)}))}}),l.all(a)},inject:function(n){var r=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],o=arguments.length<=2||void 0===arguments[2]?!1:arguments[2],t=this,a=l.defer();if(e.isDefined(n)&&null!==n){if(e.isArray(n)){var s=[];return e.forEach(n,function(e){s.push(t.inject(e,r,o))}),l.all(s)}t._addToLoadList(t._getModuleName(n),!0,o)}if(i.length>0){var u=i.slice(),c=function f(e){z.push(e),D[e]=a.promise,t._loadDependencies(e,r).then(function(){try{d=[],L(O,z,r)}catch(e){return t._$log.error(e.message),void a.reject(e)}i.length>0?f(i.shift()):a.resolve(u)},function(e){a.reject(e)})};c(i.shift())}else{if(r&&r.name&&D[r.name])return D[r.name];a.resolve()}return a.promise},getRequires:function(n){var o=[];return e.forEach(n.requires,function(e){-1===r.indexOf(e)&&o.push(e)}),o},_invokeQueue:j,_registerInvokeList:$,_register:L,_addToLoadList:h,_unregister:function(n){e.isDefined(n)&&e.isArray(n)&&e.forEach(n,function(e){o[e]=void 0})}}}],this._init(e.element(n.document))}]);var f=e.bootstrap;e.bootstrap=function(n,l,g){return r=["ng","oc.lazyLoad"],o={},t=[],i=[],a=[],s=[],u=e.noop,c={},d=[],e.forEach(l.slice(),function(e){h(e,!0,!0)}),f(n,l,g)};var h=function(n,r,o){(s.length>0||r)&&e.isString(n)&&-1===i.indexOf(n)&&(i.push(n),o&&a.push(n))},g=e.module;e.module=function(e,n,r){return h(e,!1,!0),g(e,n,r)},"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="oc.lazyLoad")}(angular,window),function(e){"use strict";e.module("oc.lazyLoad").directive("ocLazyLoad",["$ocLazyLoad","$compile","$animate","$parse","$timeout",function(n,r,o,t,i){return{restrict:"A",terminal:!0,priority:1e3,compile:function(i,a){var s=i[0].innerHTML;return i.html(""),function(i,a,u){var c=t(u.ocLazyLoad);i.$watch(function(){return c(i)||u.ocLazyLoad},function(t){e.isDefined(t)&&n.load(t).then(function(){o.enter(s,a),r(a.contents())(i)})},!0)}}}}])}(angular),function(e){"use strict";e.module("oc.lazyLoad").config(["$provide",function(n){n.decorator("$ocLazyLoad",["$delegate","$q","$window","$interval",function(n,r,o,t){var i=!1,a=!1,s=o.document.getElementsByTagName("head")[0]||o.document.getElementsByTagName("body")[0];return n.buildElement=function(u,c,d){var l,f,h=r.defer(),g=n._getFilesCache(),p=function(e){var n=(new Date).getTime();return e.indexOf("?")>=0?"&"===e.substring(0,e.length-1)?e+"_dc="+n:e+"&_dc="+n:e+"?_dc="+n};switch(e.isUndefined(g.get(c))&&g.put(c,h.promise),u){case"css":l=o.document.createElement("link"),l.type="text/css",l.rel="stylesheet",l.href=d.cache===!1?p(c):c;break;case"js":l=o.document.createElement("script"),l.src=d.cache===!1?p(c):c;break;default:g.remove(c),h.reject(new Error('Requested type "'+u+'" is not known. Could not inject "'+c+'"'))}l.onload=l.onreadystatechange=function(e){l.readyState&&!/^c|loade/.test(l.readyState)||f||(l.onload=l.onreadystatechange=null,f=1,n._broadcast("ocLazyLoad.fileLoaded",c),h.resolve(l))},l.onerror=function(){g.remove(c),h.reject(new Error("Unable to load "+c))},l.async=d.serie?0:1;var m=s.lastChild;if(d.insertBefore){var v=e.element(e.isDefined(window.jQuery)?d.insertBefore:document.querySelector(d.insertBefore));v&&v.length>0&&(m=v[0])}if(m.parentNode.insertBefore(l,m),"css"==u){if(!i){var y=o.navigator.userAgent.toLowerCase();if(y.indexOf("phantomjs/1.9")>-1)a=!0;else if(/iP(hone|od|ad)/.test(o.navigator.platform)){var L=o.navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/),$=parseFloat([parseInt(L[1],10),parseInt(L[2],10),parseInt(L[3]||0,10)].join("."));a=6>$}else if(y.indexOf("android")>-1){var j=parseFloat(y.slice(y.indexOf("android")+8));a=4.4>j}else if(y.indexOf("safari")>-1){var E=y.match(/version\/([\.\d]+)/i);a=E&&E[1]&&parseFloat(E[1])<6}}if(a)var _=1e3,w=t(function(){try{l.sheet.cssRules,t.cancel(w),l.onload()}catch(e){--_<=0&&l.onerror()}},20)}return h.promise},n}])}])}(angular),function(e){"use strict";e.module("oc.lazyLoad").config(["$provide",function(n){n.decorator("$ocLazyLoad",["$delegate","$q",function(n,r){return n.filesLoader=function(o){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],i=[],a=[],s=[],u=[],c=null,d=n._getFilesCache();n.toggleWatch(!0),e.extend(t,o);var l=function(r){var o,l=null;if(e.isObject(r)&&(l=r.type,r=r.path),c=d.get(r),e.isUndefined(c)||t.cache===!1){if(null!==(o=/^(css|less|html|htm|js)?(?=!)/.exec(r))&&(l=o[1],r=r.substr(o[1].length+1,r.length)),!l)if(null!==(o=/[.](css|less|html|htm|js)?((\?|#).*)?$/.exec(r)))l=o[1];else{if(n.jsLoader.hasOwnProperty("ocLazyLoadLoader")||!n.jsLoader.hasOwnProperty("requirejs"))return void n._$log.error("File type could not be determined. "+r);l="js"}"css"!==l&&"less"!==l||-1!==i.indexOf(r)?"html"!==l&&"htm"!==l||-1!==a.indexOf(r)?"js"===l||-1===s.indexOf(r)?s.push(r):n._$log.error("File type is not valid. "+r):a.push(r):i.push(r)}else c&&u.push(c)};if(t.serie?l(t.files.shift()):e.forEach(t.files,function(e){l(e)}),i.length>0){var f=r.defer();n.cssLoader(i,function(r){e.isDefined(r)&&n.cssLoader.hasOwnProperty("ocLazyLoadLoader")?(n._$log.error(r),f.reject(r)):f.resolve()},t),u.push(f.promise)}if(a.length>0){var h=r.defer();n.templatesLoader(a,function(r){e.isDefined(r)&&n.templatesLoader.hasOwnProperty("ocLazyLoadLoader")?(n._$log.error(r),h.reject(r)):h.resolve()},t),u.push(h.promise)}if(s.length>0){var g=r.defer();n.jsLoader(s,function(r){e.isDefined(r)&&(n.jsLoader.hasOwnProperty("ocLazyLoadLoader")||n.jsLoader.hasOwnProperty("requirejs"))?(n._$log.error(r),g.reject(r)):g.resolve()},t),u.push(g.promise)}if(0===u.length){var p=r.defer(),m="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'.";return n._$log.error(m),p.reject(m),p.promise}return t.serie&&t.files.length>0?r.all(u).then(function(){return n.filesLoader(o,t)}):r.all(u)["finally"](function(e){return n.toggleWatch(!1),e})},n.load=function(o){var t,i=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],a=this,s=null,u=[],c=r.defer(),d=e.copy(o),l=e.copy(i);if(e.isArray(d))return e.forEach(d,function(e){u.push(a.load(e,l))}),r.all(u).then(function(e){c.resolve(e)},function(e){c.reject(e)}),c.promise;if(e.isString(d)?(s=a.getModuleConfig(d),s||(s={files:[d]})):e.isObject(d)&&(s=e.isDefined(d.path)&&e.isDefined(d.type)?{files:[d]}:a.setModuleConfig(d)),null===s){var f=a._getModuleName(d);return t='Module "'+(f||"unknown")+'" is not configured, cannot load.',n._$log.error(t),c.reject(new Error(t)),c.promise}e.isDefined(s.template)&&(e.isUndefined(s.files)&&(s.files=[]),e.isString(s.template)?s.files.push(s.template):e.isArray(s.template)&&s.files.concat(s.template));var h=e.extend({},l,s);return e.isUndefined(s.files)&&e.isDefined(s.name)&&n.moduleExists(s.name)?n.inject(s.name,h,!0):(n.filesLoader(s,h).then(function(){n.inject(null,h).then(function(e){c.resolve(e)},function(e){c.reject(e)})},function(e){c.reject(e)}),c.promise)},n}])}])}(angular),function(e){"use strict";e.module("oc.lazyLoad").config(["$provide",function(n){n.decorator("$ocLazyLoad",["$delegate","$q",function(n,r){return n.cssLoader=function(o,t,i){var a=[];e.forEach(o,function(e){a.push(n.buildElement("css",e,i))}),r.all(a).then(function(){t()},function(e){t(e)})},n.cssLoader.ocLazyLoadLoader=!0,n}])}])}(angular),function(e){"use strict";e.module("oc.lazyLoad").config(["$provide",function(e){e.decorator("$ocLazyLoad",["$delegate","$q",function(e,n){return e.jsLoader=function(e,n,r){require(e,n.bind(null,void 0),n,r)},e.jsLoader.requirejs=!0,e}])}])}(angular),function(e){"use strict";e.module("oc.lazyLoad").config(["$provide",function(n){n.decorator("$ocLazyLoad",["$delegate","$templateCache","$q","$http",function(n,r,o,t){return n.templatesLoader=function(i,a,s){var u=[],c=n._getFilesCache();return e.forEach(i,function(n){var i=o.defer();u.push(i.promise),t.get(n,s).then(function(o){var t=o.data;e.isString(t)&&t.length>0&&e.forEach(e.element(t),function(e){"SCRIPT"===e.nodeName&&"text/ng-template"===e.type&&r.put(e.id,e.innerHTML)}),e.isUndefined(c.get(n))&&c.put(n,!0),i.resolve()})["catch"](function(e){i.reject(new Error('Unable to load template file "'+n+'": '+e.data))})}),o.all(u).then(function(){a()},function(e){a(e)})},n.templatesLoader.ocLazyLoadLoader=!0,n}])}])}(angular),Array.prototype.indexOf||(Array.prototype.indexOf=function(e,n){var r;if(null==this)throw new TypeError('"this" is null or not defined');var o=Object(this),t=o.length>>>0;if(0===t)return-1;var i=+n||0;if(Math.abs(i)===1/0&&(i=0),i>=t)return-1;for(r=Math.max(i>=0?i:t-Math.abs(i),0);t>r;){if(r in o&&o[r]===e)return r;r++}return-1}); -------------------------------------------------------------------------------- /examples/complexExample/README.md: -------------------------------------------------------------------------------- 1 | Use `bower install` to download the libraries used in this example. -------------------------------------------------------------------------------- /examples/complexExample/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-ocLazyLoad", 3 | "version": "0.3.9", 4 | "homepage": "https://github.com/ocombe/ocLazyLoad", 5 | "authors": ["ocombe "], 6 | "main": "js/app.js", 7 | "license": "MIT", 8 | "private": true, 9 | "ignore": ["**/.*", "node_modules", "bower_components", "test", "tests"], 10 | "dependencies": { 11 | "angular-ui-router": "~0.2.10", 12 | "ocModal": "~0.1.6", 13 | "bootstrap": "~3.2.0", 14 | "angular-ui-grid": "~3.0.0-rc.12" 15 | } 16 | } -------------------------------------------------------------------------------- /examples/complexExample/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 |

$ocLazyLoad

20 |

21 | With ocLazyLoad you can lazy load js / css / templates with a service and/or a directive.
22 | If you get on error, or cannot see anything below this line when you load the page the first time, check if you called `bower install` to download the libraries used in this example. 23 |

24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/complexExample/js/AppCtrl.js: -------------------------------------------------------------------------------- 1 | angular.module('app').controller('AppCtrl', function($scope, $ocLazyLoad) { 2 | $scope.$on('ocLazyLoad.moduleLoaded', function(e, params) { 3 | //console.log('event module loaded', params); 4 | }); 5 | 6 | $scope.$on('ocLazyLoad.componentLoaded', function(e, params) { 7 | //console.log('event component loaded', params); 8 | }); 9 | 10 | $scope.$on('ocLazyLoad.fileLoaded', function(e, file) { 11 | console.log('event file loaded', file); 12 | }); 13 | 14 | $scope.loadBootstrap = function() { 15 | // use events to know when the files are loaded 16 | var unbind = $scope.$on('ocLazyLoad.fileLoaded', function(e, file) { 17 | if(file === 'bower_components/bootstrap/dist/css/bootstrap.css') { 18 | $scope.bootstrapLoaded = true; 19 | unbind(); 20 | } 21 | }); 22 | // we could use .then here instead of events 23 | $ocLazyLoad.load([ 24 | 'bower_components/bootstrap/dist/js/bootstrap.js', 25 | 'bower_components/bootstrap/dist/css/bootstrap.css' 26 | ]); 27 | }; 28 | }); 29 | -------------------------------------------------------------------------------- /examples/complexExample/js/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Declare app level module which depends on filters, and services 4 | var App = angular.module('app', ['ui.router', 'oc.lazyLoad']) 5 | .config(function($stateProvider, $locationProvider, $urlRouterProvider, $ocLazyLoadProvider) { 6 | $urlRouterProvider.otherwise("/"); 7 | $locationProvider.hashPrefix('!'); 8 | 9 | // You can also load via resolve 10 | $stateProvider 11 | .state('index', { 12 | url: "/", // root route 13 | views: { 14 | "lazyLoadView": { 15 | controller: 'AppCtrl', // This view will use AppCtrl loaded below in the resolve 16 | templateUrl: 'partials/main.html' 17 | } 18 | }, 19 | resolve: { // Any property in resolve should return a promise and is executed before the view is loaded 20 | loadMyCtrl: ['$ocLazyLoad', function($ocLazyLoad) { 21 | // you can lazy load files for an existing module 22 | return $ocLazyLoad.load('js/AppCtrl.js'); 23 | }] 24 | } 25 | }) 26 | .state('modal', { 27 | parent: 'index', 28 | resolve: { // Any property in resolve should return a promise and is executed before the view is loaded 29 | loadOcModal: ['$ocLazyLoad', '$injector', '$rootScope', function($ocLazyLoad, $injector, $rootScope) { 30 | // Load 'oc.modal' defined in the config of the provider $ocLazyLoadProvider 31 | console.log('load'); 32 | return $ocLazyLoad.load([ 33 | 'bower_components/bootstrap/dist/css/bootstrap.css', // will use the cached version if you already loaded bootstrap with the button 34 | 'bower_components/ocModal/dist/css/ocModal.animations.css', 35 | 'bower_components/ocModal/dist/css/ocModal.light.css', 36 | 'bower_components/ocModal/dist/ocModal.js', 37 | 'partials/modal.html' 38 | ]).then(function() { 39 | console.log('--------then'); 40 | $rootScope.bootstrapLoaded = true; 41 | // inject the lazy loaded service 42 | var $ocModal = $injector.get("$ocModal"); 43 | console.log($ocModal); 44 | $ocModal.open({ 45 | url: 'modal', 46 | cls: 'fade-in' 47 | }); 48 | }); 49 | }], 50 | 51 | // resolve the sibling state and use the service lazy loaded 52 | setModalBtn: ['loadOcModal', '$rootScope', '$ocModal', function(loadOcModal, $rootScope, $ocModal) { 53 | $rootScope.openModal = function() { 54 | $ocModal.open({ 55 | url: 'modal', 56 | cls: 'flip-vertical' 57 | }); 58 | } 59 | }] 60 | } 61 | }); 62 | 63 | // Without server side support html5 must be disabled. 64 | $locationProvider.html5Mode(false); 65 | 66 | // We configure ocLazyLoad to use the lib script.js as the async loader 67 | $ocLazyLoadProvider.config({ 68 | //debug: true, 69 | //events: true, 70 | modules: [{ 71 | name: 'gridModule', 72 | files: [ 73 | 'js/gridModule.js' 74 | ] 75 | }] 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /examples/complexExample/js/gridModule.js: -------------------------------------------------------------------------------- 1 | // ngGrid is also lazy loaded by $ocLazyLoad thanks to the module dependency injection ! 2 | angular.module('gridModule', [[ // you don't even need to set the name of the module that you want to lazy load ! 3 | 'bower_components/angular-ui-grid/ui-grid.js', 4 | 'bower_components/angular-ui-grid/ui-grid.css' 5 | ]]).controller('GridModuleCtrl', function($scope) { 6 | console.log('------- grid module ctrl'); 7 | $scope.myData = [{name: "Moroni", age: 50}, 8 | {name: "Teancum", age: 43}, 9 | {name: "Jacob", age: 27}, 10 | {name: "Nephi", age: 29}, 11 | {name: "Enos", age: 34}]; 12 | $scope.gridOptions = {data: 'myData'}; 13 | }).config(function() { 14 | console.warn('config gridModule'); 15 | }).config(['$ocLazyLoadProvider', function($ocLazyLoadProvider) { 16 | console.warn('config 2 gridModule'); 17 | }]).run(function() { 18 | console.warn('run gridModule'); 19 | }); 20 | -------------------------------------------------------------------------------- /examples/complexExample/partials/main.html: -------------------------------------------------------------------------------- 1 |
2 |

Load external libs (not angular-based):

3 |

4 |
5 | 6 |
7 |

Load a module by loading a state:

8 |

Go to "modal" state

9 |

10 |
11 | 12 |
13 |

Autoload a complete module with dependencies and templates using the directive:

14 | 15 | 16 |
17 |
18 | {{test}}
19 |
20 |
21 |
22 |
23 | -------------------------------------------------------------------------------- /examples/complexExample/partials/modal.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/requireJSExample/css/ng-grid.css: -------------------------------------------------------------------------------- 1 | .ngGrid { 2 | background-color: #fdfdfd; 3 | } 4 | .ngGrid input[type="checkbox"] { 5 | margin: 0; 6 | padding: 0; 7 | } 8 | .ngGrid input { 9 | vertical-align: top; 10 | } 11 | .ngGrid.unselectable { 12 | -moz-user-select: none; 13 | -khtml-user-select: none; 14 | -webkit-user-select: none; 15 | -o-user-select: none; 16 | user-select: none; 17 | } 18 | .ngViewport { 19 | overflow: auto; 20 | min-height: 20px; 21 | } 22 | .ngViewport:focus { 23 | outline: none; 24 | } 25 | .ngCanvas { 26 | position: relative; 27 | } 28 | .ngVerticalBar { 29 | position: absolute; 30 | right: 0; 31 | width: 0; 32 | } 33 | .ngVerticalBarVisible { 34 | width: 1px; 35 | background-color: #d4d4d4; 36 | } 37 | .ngHeaderContainer { 38 | position: relative; 39 | overflow: hidden; 40 | font-weight: bold; 41 | background-color: inherit; 42 | } 43 | .ngHeaderCell { 44 | position: absolute; 45 | top: 0; 46 | bottom: 0; 47 | background-color: inherit; 48 | } 49 | .ngHeaderCell.pinned { 50 | z-index: 1; 51 | } 52 | .ngHeaderSortColumn { 53 | position: absolute; 54 | overflow: hidden; 55 | } 56 | .ngTopPanel { 57 | position: relative; 58 | z-index: 1; 59 | background-color: #eaeaea; 60 | border-bottom: 1px solid #d4d4d4; 61 | } 62 | .ngSortButtonDown { 63 | position: absolute; 64 | top: 3px; 65 | left: 0; 66 | right: 0; 67 | margin-left: auto; 68 | margin-right: auto; 69 | border-color: gray transparent; 70 | border-style: solid; 71 | border-width: 0 5px 5px 5px; 72 | height: 0; 73 | width: 0; 74 | } 75 | .ngNoSort { 76 | cursor: default; 77 | } 78 | .ngHeaderButton { 79 | position: absolute; 80 | right: 2px; 81 | top: 8px; 82 | -moz-border-radius: 50%; 83 | -webkit-border-radius: 50%; 84 | border-radius: 50%; 85 | width: 14px; 86 | height: 14px; 87 | z-index: 1; 88 | background-color: #9fbbb4; 89 | cursor: pointer; 90 | } 91 | .ngSortButtonUp { 92 | position: absolute; 93 | top: 3px; 94 | left: 0; 95 | right: 0; 96 | margin-left: auto; 97 | margin-right: auto; 98 | border-color: gray transparent; 99 | border-style: solid; 100 | border-width: 5px 5px 0 5px; 101 | height: 0; 102 | width: 0; 103 | } 104 | .ngHeaderScroller { 105 | position: absolute; 106 | background-color: inherit; 107 | } 108 | .ngSortPriority { 109 | position: absolute; 110 | top: -5px; 111 | left: 1px; 112 | font-size: 6pt; 113 | font-weight: bold; 114 | } 115 | .ngHeaderGrip { 116 | cursor: col-resize; 117 | width: 10px; 118 | right: -5px; 119 | top: 0; 120 | height: 100%; 121 | position: absolute; 122 | background-color: transparent; 123 | } 124 | .ngHeaderText { 125 | padding: 5px; 126 | -moz-box-sizing: border-box; 127 | -webkit-box-sizing: border-box; 128 | box-sizing: border-box; 129 | white-space: nowrap; 130 | -ms-text-overflow: ellipsis; 131 | -o-text-overflow: ellipsis; 132 | text-overflow: ellipsis; 133 | overflow: hidden; 134 | } 135 | .ngHeaderButtonArrow { 136 | position: absolute; 137 | top: 4px; 138 | left: 3px; 139 | width: 0; 140 | height: 0; 141 | border-style: solid; 142 | border-width: 6.5px 4.5px 0 4.5px; 143 | border-color: #4d4d4d transparent transparent transparent; 144 | } 145 | .ngPinnedIcon { 146 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABp0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuMTAw9HKhAAAAmElEQVQoU33PQapBURjA8UtkwJuaWYGSgfQWYBMvczPmTCzAAGVuaA228BZhRCkDGSmE31FucuRfvzq3vr5zT/JSjSU7DsypEPXDkDVn2hSIytJhw4kWGaLCxgHh2gt/RBuLzNhz5caWPjnSqqw4EraFfwznf8qklWjwy4IRTerkiQoPGtPl40OehcEJvcfXl8LglLfBJLkDcMgbgHlHhK8AAAAASUVORK5CYII=); 147 | background-repeat: no-repeat; 148 | position: absolute; 149 | right: 5px; 150 | top: 5px; 151 | height: 10px; 152 | width: 10px; 153 | } 154 | .ngUnPinnedIcon { 155 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABp0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuMTAw9HKhAAAAlElEQVQoU33PPQrCQBRF4fFnI2KfZVi5ARvdgo1l6mwmkCJVOgluwd5OwUoDtnoOxAei8cLXTN7cvEl/skCNDCMPfsUPO5zQwOHIDEvYtMURHe6wOVLgigvOePRyeDkyR4ln7wZ//7XfFBu8B23+aDJjrHGAwza7hjtHJvDmHg7b7Bru7AMjK7Rw2ObBVHDY5oGk9AKQNB2zy8MBTgAAAABJRU5ErkJggg==); 156 | background-repeat: no-repeat; 157 | position: absolute; 158 | height: 10px; 159 | width: 10px; 160 | right: 5px; 161 | top: 5px; 162 | } 163 | .ngColMenu { 164 | right: 2px; 165 | padding: 5px; 166 | top: 25px; 167 | -moz-border-radius: 3px; 168 | -webkit-border-radius: 3px; 169 | border-radius: 3px; 170 | background-color: #bdd0cb; 171 | position: absolute; 172 | border: 2px solid #d4d4d4; 173 | z-index: 1; 174 | } 175 | .ngColListCheckbox { 176 | position: relative; 177 | right: 3px; 178 | top: 4px; 179 | } 180 | .ngColList { 181 | list-style-type: none; 182 | } 183 | .ngColListItem { 184 | position: relative; 185 | right: 17px; 186 | top: 2px; 187 | white-space: nowrap; 188 | } 189 | .ngMenuText { 190 | position: relative; 191 | top: 2px; 192 | left: 2px; 193 | } 194 | .ngGroupPanel { 195 | background-color: #eaeaea; 196 | overflow: hidden; 197 | border-bottom: 1px solid #d4d4d4; 198 | } 199 | .ngGroupPanelDescription { 200 | margin-top: 5px; 201 | margin-left: 5px; 202 | } 203 | .ngGroupList { 204 | list-style-type: none; 205 | margin: 0; 206 | padding: 0; 207 | } 208 | .ngAggHeader { 209 | position: absolute; 210 | border: none; 211 | } 212 | .ngGroupElement { 213 | float: left; 214 | height: 100%; 215 | width: 100%; 216 | } 217 | .ngGroupIcon { 218 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAYAAACZ3F9/AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAEFJREFUKFNjoAhISkr+h2J5JDZODNXGwGBsbPwfhIGAA8bGh6HaGBiAGhxAGJmND4M1gQCSM0adCsVQbcPcqQwMALWDGyDvWPefAAAAAElFTkSuQmCC); 219 | background-repeat: no-repeat; 220 | height: 15px; 221 | width: 15px; 222 | position: absolute; 223 | right: -2px; 224 | top: 2px; 225 | } 226 | .ngGroupedByIcon { 227 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAYAAACZ3F9/AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAElJREFUKFNjoAhISkr+R8LyaHwMDNXGwGBsbPwfhoGAA5mPDUO1oWpE52PDYE0gALTFAYbR+dgwWBMIoPlh1I9ADNU2NPzIwAAAFQYI9E4OLvEAAAAASUVORK5CYII=); 228 | background-repeat: no-repeat; 229 | height: 15px; 230 | width: 15px; 231 | position: absolute; 232 | right: -2px; 233 | top: 2px; 234 | } 235 | .ngGroupName { 236 | background-color: #fdfdfd; 237 | border: 1px solid #d4d4d4; 238 | padding: 3px 10px; 239 | float: left; 240 | margin-left: 0; 241 | margin-top: 2px; 242 | -moz-border-radius: 3px; 243 | -webkit-border-radius: 3px; 244 | border-radius: 3px; 245 | font-weight: bold; 246 | } 247 | .ngGroupArrow { 248 | width: 0; 249 | height: 0; 250 | border-top: 6px solid transparent; 251 | border-bottom: 6px solid transparent; 252 | border-left: 6px solid black; 253 | margin-top: 10px; 254 | margin-left: 5px; 255 | margin-right: 5px; 256 | float: right; 257 | } 258 | .ngGroupingNumber { 259 | position: absolute; 260 | right: -10px; 261 | top: -2px; 262 | } 263 | .ngAggArrowCollapsed { 264 | position: absolute; 265 | left: 8px; 266 | bottom: 10px; 267 | width: 0; 268 | height: 0; 269 | border-style: solid; 270 | border-width: 5px 0 5px 8.7px; 271 | border-color: transparent transparent transparent #000000; 272 | } 273 | .ngGroupItem { 274 | float: left; 275 | } 276 | .ngGroupItem:first-child { 277 | margin-left: 2px; 278 | } 279 | .ngRemoveGroup { 280 | width: 5px; 281 | -moz-opacity: 0.4; 282 | opacity: 0.4; 283 | margin-top: -1px; 284 | margin-left: 5px; 285 | } 286 | .ngRemoveGroup:hover { 287 | color: black; 288 | text-decoration: none; 289 | cursor: pointer; 290 | -moz-opacity: 0.7; 291 | opacity: 0.7; 292 | } 293 | .ngAggArrowExpanded { 294 | position: absolute; 295 | left: 8px; 296 | bottom: 10px; 297 | width: 0; 298 | height: 0; 299 | border-style: solid; 300 | border-width: 0 0 9px 9px; 301 | border-color: transparent transparent #000000 transparent; 302 | } 303 | .ngAggregate { 304 | position: absolute; 305 | background-color: #c9dde1; 306 | border-bottom: 1px solid beige; 307 | overflow: hidden; 308 | top: 0; 309 | bottom: 0; 310 | right: -1px; 311 | left: 0; 312 | } 313 | .ngAggregateText { 314 | position: absolute; 315 | left: 27px; 316 | top: 5px; 317 | line-height: 20px; 318 | white-space: nowrap; 319 | } 320 | .ngRow { 321 | position: absolute; 322 | border-bottom: 1px solid #d4d4d4; 323 | } 324 | .ngRow.odd { 325 | background-color: #fdfdfd; 326 | } 327 | .ngRow.even { 328 | background-color: #f3f3f3; 329 | } 330 | .ngRow.selected { 331 | background-color: #c9dde1; 332 | } 333 | .ngCell { 334 | overflow: hidden; 335 | position: absolute; 336 | top: 0; 337 | bottom: 0; 338 | background-color: inherit; 339 | } 340 | .ngCell.pinned { 341 | z-index: 1; 342 | } 343 | .ngCellText { 344 | padding: 5px; 345 | -moz-box-sizing: border-box; 346 | -webkit-box-sizing: border-box; 347 | box-sizing: border-box; 348 | white-space: nowrap; 349 | -ms-text-overflow: ellipsis; 350 | -o-text-overflow: ellipsis; 351 | text-overflow: ellipsis; 352 | overflow: hidden; 353 | } 354 | .ngSelectionCell { 355 | margin-top: 9px; 356 | margin-left: 6px; 357 | } 358 | .ngSelectionHeader { 359 | position: absolute; 360 | top: 11px; 361 | left: 6px; 362 | } 363 | .ngCellElement:focus { 364 | outline: 0; 365 | background-color: #b3c4c7; 366 | } 367 | .ngRow.canSelect { 368 | cursor: pointer; 369 | } 370 | .ngSelectionCheckbox { 371 | margin-top: 9px; 372 | margin-left: 6px; 373 | } 374 | .ngFooterPanel { 375 | background-color: #eaeaea; 376 | padding: 0; 377 | border-top: 1px solid #d4d4d4; 378 | position: relative; 379 | } 380 | .nglabel { 381 | display: block; 382 | float: left; 383 | font-weight: bold; 384 | padding-right: 5px; 385 | } 386 | .ngTotalSelectContainer { 387 | float: left; 388 | margin: 5px; 389 | margin-top: 7px; 390 | } 391 | .ngFooterSelectedItems { 392 | padding: 2px; 393 | } 394 | .ngFooterTotalItems.ngnoMultiSelect { 395 | padding: 0 !important; 396 | } 397 | .ngPagerFirstBar { 398 | width: 10px; 399 | border-left: 2px solid #4d4d4d; 400 | margin-top: -6px; 401 | height: 12px; 402 | margin-left: -3px; 403 | } 404 | .ngPagerButton { 405 | height: 25px; 406 | min-width: 26px; 407 | } 408 | .ngPagerFirstTriangle { 409 | width: 0; 410 | height: 0; 411 | border-style: solid; 412 | border-width: 5px 8.7px 5px 0; 413 | border-color: transparent #4d4d4d transparent transparent; 414 | margin-left: 2px; 415 | } 416 | .ngPagerNextTriangle { 417 | margin-left: 1px; 418 | } 419 | .ngPagerPrevTriangle { 420 | margin-left: 0; 421 | } 422 | .ngPagerLastTriangle { 423 | width: 0; 424 | height: 0; 425 | border-style: solid; 426 | border-width: 5px 0 5px 8.7px; 427 | border-color: transparent transparent transparent #4d4d4d; 428 | margin-left: -1px; 429 | } 430 | .ngPagerLastBar { 431 | width: 10px; 432 | border-left: 2px solid #4d4d4d; 433 | margin-top: -6px; 434 | height: 12px; 435 | margin-left: 1px; 436 | } 437 | .ngFooterTotalItems { 438 | padding: 2px; 439 | } 440 | -------------------------------------------------------------------------------- /examples/requireJSExample/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | {{test}} 18 | 19 |
20 | 21 | -------------------------------------------------------------------------------- /examples/requireJSExample/js/lazymodule.js: -------------------------------------------------------------------------------- 1 | angular.module('lazymodule', ['ngGrid']) 2 | .controller('lazyController', ['$scope', function($scope){ 3 | $scope.test = "Hey again"; 4 | $scope.myData = [{name: "Moroni", age: 50}, 5 | {name: "Tiancum", age: 43}, 6 | {name: "Jacob", age: 27}, 7 | {name: "Nephi", age: 29}, 8 | {name: "Enos", age: 34}]; 9 | $scope.gridOptions = { data: 'myData' }; 10 | }]); -------------------------------------------------------------------------------- /examples/requireJSExample/js/main.js: -------------------------------------------------------------------------------- 1 | require.config({ 2 | baseUrl: 'js/', 3 | paths: { 4 | 'jquery': 'jquery', 5 | 'angular': 'angular.min', 6 | 'test': 'testmodule', 7 | 'ngGrid': 'ng-grid-2.0.11.debug', 8 | 'ocLazyLoad': '../../../dist/ocLazyLoad.require' 9 | }, 10 | shim: { 11 | 'angular': ['jquery'], 12 | 'ocLazyLoad': ['angular'], 13 | 'ngGrid': ['angular'], 14 | 'lazymodule': ['test', 'ngGrid'], 15 | 'test': ['ocLazyLoad'] 16 | } 17 | }); 18 | 19 | // Start the main app logic. 20 | require(['test'], function() { 21 | angular.bootstrap(document.body, ['test']); 22 | }); 23 | -------------------------------------------------------------------------------- /examples/requireJSExample/js/require.js: -------------------------------------------------------------------------------- 1 | /* 2 | RequireJS 2.1.20 Copyright (c) 2010-2015, The Dojo Foundation All Rights Reserved. 3 | Available via the MIT or new BSD license. 4 | see: http://github.com/jrburke/requirejs for details 5 | */ 6 | var requirejs,require,define; 7 | (function(ba){function G(b){return"[object Function]"===K.call(b)}function H(b){return"[object Array]"===K.call(b)}function v(b,c){if(b){var d;for(d=0;dthis.depCount&&!this.defined){if(G(l)){if(this.events.error&&this.map.isDefine||e.onError!==ca)try{f=h.execCb(c,l,b,f)}catch(d){a=d}else f=h.execCb(c,l,b,f);this.map.isDefine&& 19 | void 0===f&&((b=this.module)?f=b.exports:this.usingExports&&(f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",w(this.error=a)}else f=l;this.exports=f;if(this.map.isDefine&&!this.ignore&&(q[c]=f,e.onResourceLoad))e.onResourceLoad(h,this.map,this.depMaps);y(c);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete= 20 | !0)}}else t(h.defQueueMap,c)||this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=i(a.prefix);this.depMaps.push(d);s(d,"defined",u(this,function(f){var l,d;d=n(aa,this.map.id);var g=this.map.name,P=this.map.parentMap?this.map.parentMap.name:null,p=h.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(g=f.normalize(g,function(a){return c(a,P,!0)})||""),f=i(a.prefix+"!"+g,this.map.parentMap),s(f,"defined",u(this,function(a){this.init([],function(){return a}, 21 | null,{enabled:!0,ignore:!0})})),d=n(m,f.id)){this.depMaps.push(f);if(this.events.error)d.on("error",u(this,function(a){this.emit("error",a)}));d.enable()}}else d?(this.map.url=h.nameToUrl(d),this.load()):(l=u(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),l.error=u(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];A(m,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&y(a.map.id)});w(a)}),l.fromText=u(this,function(f,c){var d=a.name,g=i(d),P=M;c&&(f=c);P&& 22 | (M=!1);r(g);t(k.config,b)&&(k.config[d]=k.config[b]);try{e.exec(f)}catch(m){return w(B("fromtexteval","fromText eval for "+b+" failed: "+m,m,[b]))}P&&(M=!0);this.depMaps.push(g);h.completeLoad(d);p([d],l)}),f.load(a.name,p,l,k))}));h.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){V[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,u(this,function(a,b){var c,f;if("string"===typeof a){a=i(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c= 23 | n(L,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;s(a,"defined",u(this,function(a){this.undefed||(this.defineDep(b,a),this.check())}));this.errback?s(a,"error",u(this,this.errback)):this.events.error&&s(a,"error",u(this,function(a){this.emit("error",a)}))}c=a.id;f=m[c];!t(L,c)&&(f&&!f.enabled)&&h.enable(a,this)}));A(this.pluginMaps,u(this,function(a){var b=n(m,a.id);b&&!b.enabled&&h.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]= 24 | []);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};h={config:k,contextName:b,registry:m,defined:q,urlFetched:S,defQueue:C,defQueueMap:{},Module:Z,makeModuleMap:i,nextTick:e.nextTick,onError:w,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=k.shim,c={paths:!0,bundles:!0,config:!0,map:!0};A(a,function(a,b){c[b]?(k[b]||(k[b]={}),U(k[b],a,!0,!0)):k[b]=a});a.bundles&&A(a.bundles,function(a,b){v(a, 25 | function(a){a!==b&&(aa[a]=b)})});a.shim&&(A(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=h.makeShimExports(a);b[c]=a}),k.shim=b);a.packages&&v(a.packages,function(a){var b,a="string"===typeof a?{name:a}:a;b=a.name;a.location&&(k.paths[b]=a.location);k.pkgs[b]=a.name+"/"+(a.main||"main").replace(ha,"").replace(Q,"")});A(m,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=i(b,null,!0))});if(a.deps||a.callback)h.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b; 26 | a.init&&(b=a.init.apply(ba,arguments));return b||a.exports&&da(a.exports)}},makeRequire:function(a,j){function g(c,d,p){var k,n;j.enableBuildCallback&&(d&&G(d))&&(d.__requireJsBuild=!0);if("string"===typeof c){if(G(d))return w(B("requireargs","Invalid require call"),p);if(a&&t(L,c))return L[c](m[a.id]);if(e.get)return e.get(h,c,a,g);k=i(c,a,!1,!0);k=k.id;return!t(q,k)?w(B("notloaded",'Module name "'+k+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):q[k]}J();h.nextTick(function(){J(); 27 | n=r(i(null,a));n.skipMap=j.skipMap;n.init(c,d,p,{enabled:!0});D()});return g}j=j||{};U(g,{isBrowser:z,toUrl:function(b){var d,e=b.lastIndexOf("."),j=b.split("/")[0];if(-1!==e&&(!("."===j||".."===j)||1g.attachEvent.toString().indexOf("[native code"))&&!Y?(M=!0,g.attachEvent("onreadystatechange",b.onScriptLoad)):(g.addEventListener("load",b.onScriptLoad,!1),g.addEventListener("error",b.onScriptError,!1));g.src=d;J=g;D?y.insertBefore(g,D):y.appendChild(g);J=null;return g}if(ea)try{importScripts(d),b.completeLoad(c)}catch(i){b.onError(B("importscripts", 35 | "importScripts failed for "+c+" at "+d,i,[c]))}};z&&!s.skipDataMain&&T(document.getElementsByTagName("script"),function(b){y||(y=b.parentNode);if(I=b.getAttribute("data-main"))return r=I,s.baseUrl||(E=r.split("/"),r=E.pop(),O=E.length?E.join("/")+"/":"./",s.baseUrl=O),r=r.replace(Q,""),e.jsExtRegExp.test(r)&&(r=I),s.deps=s.deps?s.deps.concat(r):[r],!0});define=function(b,c,d){var e,g;"string"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(ja,"").replace(ka, 36 | function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(M){if(!(e=J))N&&"interactive"===N.readyState||T(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return N=b}),e=N;e&&(b||(b=e.getAttribute("data-requiremodule")),g=F[e.getAttribute("data-requirecontext")])}g?(g.defQueue.push([b,c,d]),g.defQueueMap[b]=!0):R.push([b,c,d])};define.amd={jQuery:!0};e.exec=function(b){return eval(b)};e(s)}})(this); 37 | -------------------------------------------------------------------------------- /examples/requireJSExample/js/testmodule.js: -------------------------------------------------------------------------------- 1 | var testModule = angular.module('test', ['oc.lazyLoad']); 2 | 3 | testModule.config(['$ocLazyLoadProvider', function($ocLazyLoadProvider) { 4 | $ocLazyLoadProvider.config({ 5 | jsLoader: requirejs, 6 | debug: true 7 | }); 8 | }]); 9 | 10 | testModule.controller('mainController', ['$scope', '$ocLazyLoad', function($scope, $ocLazyLoad) { 11 | $scope.test = "Hi there"; 12 | $scope.partialUrl = ''; 13 | 14 | $scope.load = function() { 15 | $ocLazyLoad.load('lazymodule').then(function() { 16 | $scope.partialUrl = 'partials/grid.html'; 17 | }, function(e) { 18 | console.log(e); 19 | }); 20 | } 21 | }]); 22 | -------------------------------------------------------------------------------- /examples/requireJSExample/partials/grid.html: -------------------------------------------------------------------------------- 1 |
2 | {{test}}
3 |
4 |
-------------------------------------------------------------------------------- /examples/simpleExample/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Lazy load succeded if you can see 'Hello world' below

12 |
13 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /examples/simpleExample/js/testApp.js: -------------------------------------------------------------------------------- 1 | angular.module("testApp", []).directive("sayHello", function() { 2 | return { 3 | scope: { 4 | to: '@to' 5 | }, 6 | restrict: "E", 7 | template: '

Hello {{to}}

' 8 | }; 9 | }); 10 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | runSequence = require('run-sequence'), 3 | newVer; 4 | 5 | gulp.task('karma', function(done) { 6 | var karma = require('karma').server; 7 | karma.start({ 8 | configFile: __dirname + '/karma.conf.js', 9 | singleRun: true 10 | }, done); 11 | }); 12 | 13 | gulp.task('clean', function() { 14 | var clean = require('gulp-clean'); 15 | 16 | return gulp.src('dist') 17 | .pipe(clean()); 18 | }); 19 | 20 | gulp.task('build-minify', ['build-files-require'], function() { 21 | var rename = require('gulp-rename'), 22 | uglify = require('gulp-uglify'), 23 | header = require('gulp-header'), 24 | pkg = require('./package.json'), 25 | banner = ['/**', 26 | ' * <%= pkg.name %> - <%= pkg.description %>', 27 | ' * @version v' + (newVer ? newVer : '<%= pkg.version %>'), 28 | ' * @link <%= pkg.homepage %>', 29 | ' * @license <%= pkg.license %>', 30 | ' * @author <%= pkg.author %>', 31 | ' */', 32 | ''].join('\n'); 33 | 34 | return gulp.src([ 35 | 'dist/ocLazyLoad.js', 36 | 'dist/ocLazyLoad.require.js' 37 | ]) 38 | .pipe(uglify()) 39 | .pipe(header(banner, {pkg: pkg})) 40 | .pipe(rename({suffix: '.min'})) 41 | .pipe(gulp.dest('dist')); 42 | 43 | }); 44 | 45 | gulp.task('build-files-require', ['build-files'], function() { 46 | var rename = require('gulp-rename'), 47 | uglify = require('gulp-uglify'), 48 | header = require('gulp-header'), 49 | babel = require('gulp-babel'), 50 | ngAnnotate = require('gulp-ng-annotate'), 51 | pkg = require('./package.json'), 52 | concat = require('gulp-concat'), 53 | banner = ['/**', 54 | ' * <%= pkg.name %> - <%= pkg.description %>', 55 | ' * @version v' + (newVer ? newVer : '<%= pkg.version %>'), 56 | ' * @link <%= pkg.homepage %>', 57 | ' * @license <%= pkg.license %>', 58 | ' * @author <%= pkg.author %>', 59 | ' */', 60 | ''].join('\n'); 61 | 62 | return gulp.src([ 63 | 'src/ocLazyLoad.core.js', 64 | 'src/ocLazyLoad.directive.js', 65 | 'src/ocLazyLoad.loaders.common.js', 66 | 'src/ocLazyLoad.loaders.core.js', 67 | 'src/ocLazyLoad.loaders.cssLoader.js', 68 | 'src/ocLazyLoad.loaders.requireJSLoader.js', 69 | 'src/ocLazyLoad.loaders.templatesLoader.js', 70 | 'src/ocLazyLoad.polyfill.ie8.js' 71 | ]) 72 | .pipe(babel({ blacklist: ["strict"] })) 73 | .pipe(ngAnnotate()) 74 | .pipe(gulp.dest('dist/modules')) 75 | .pipe(concat('ocLazyLoad.require.js')) 76 | .pipe(header(banner, {pkg: pkg})) 77 | .pipe(gulp.dest('dist')); 78 | }); 79 | 80 | gulp.task('build-files', ['clean'], function() { 81 | var rename = require('gulp-rename'), 82 | uglify = require('gulp-uglify'), 83 | header = require('gulp-header'), 84 | babel = require('gulp-babel'), 85 | ngAnnotate = require('gulp-ng-annotate'), 86 | pkg = require('./package.json'), 87 | concat = require('gulp-concat'), 88 | banner = ['/**', 89 | ' * <%= pkg.name %> - <%= pkg.description %>', 90 | ' * @version v' + (newVer ? newVer : '<%= pkg.version %>'), 91 | ' * @link <%= pkg.homepage %>', 92 | ' * @license <%= pkg.license %>', 93 | ' * @author <%= pkg.author %>', 94 | ' */', 95 | ''].join('\n'); 96 | 97 | return gulp.src([ 98 | 'src/ocLazyLoad.core.js', 99 | 'src/ocLazyLoad.directive.js', 100 | 'src/ocLazyLoad.loaders.common.js', 101 | 'src/ocLazyLoad.loaders.core.js', 102 | 'src/ocLazyLoad.loaders.cssLoader.js', 103 | 'src/ocLazyLoad.loaders.jsLoader.js', 104 | 'src/ocLazyLoad.loaders.templatesLoader.js', 105 | 'src/ocLazyLoad.polyfill.ie8.js' 106 | ]) 107 | .pipe(babel({ blacklist: ["strict"] })) 108 | .pipe(ngAnnotate()) 109 | .pipe(gulp.dest('dist/modules')) 110 | .pipe(concat('ocLazyLoad.js')) 111 | .pipe(header(banner, {pkg: pkg})) 112 | .pipe(gulp.dest('dist')); 113 | }); 114 | 115 | gulp.task('build', function(done) { 116 | runSequence('karma', 'build-files', done); 117 | }); 118 | 119 | gulp.task('promptBump', function() { 120 | var prompt = require('gulp-prompt'), 121 | semver = require('semver'), 122 | pkg = require('./package.json'); 123 | 124 | return gulp.src('') 125 | .pipe(prompt.prompt({ 126 | type: 'list', 127 | name: 'bump', 128 | message: 'What type of version bump would you like to do ? (current version is ' + pkg.version + ')', 129 | choices: [ 130 | 'patch (' + pkg.version + ' --> ' + semver.inc(pkg.version, 'patch') + ')', 131 | 'minor (' + pkg.version + ' --> ' + semver.inc(pkg.version, 'minor') + ')', 132 | 'major (' + pkg.version + ' --> ' + semver.inc(pkg.version, 'major') + ')', 133 | 'none (exit)' 134 | ] 135 | }, function(res) { 136 | if(res.bump.match(/^patch/)) { 137 | newVer = semver.inc(pkg.version, 'patch'); 138 | } else if(res.bump.match(/^minor/)) { 139 | newVer = semver.inc(pkg.version, 'minor'); 140 | } else if(res.bump.match(/^major/)) { 141 | newVer = semver.inc(pkg.version, 'major'); 142 | } 143 | })); 144 | }); 145 | 146 | 147 | gulp.task('changelog', function() { 148 | var streamqueue = require('streamqueue'), 149 | stream = streamqueue({objectMode: true}), 150 | exec = require('gulp-exec'), 151 | concat = require('gulp-concat'), 152 | clean = require('gulp-clean'); 153 | 154 | stream.queue(gulp.src('').pipe(exec('node ./changelog.js ' + newVer, {pipeStdout: true}))); 155 | stream.queue(gulp.src('CHANGELOG.md').pipe(clean())); 156 | 157 | return stream.done() 158 | .pipe(concat('CHANGELOG.md')) 159 | .pipe(gulp.dest('./')); 160 | }); 161 | 162 | gulp.task('updatePackage', function() { 163 | var jeditor = require("gulp-json-editor"); 164 | 165 | return gulp.src('package.json') 166 | .pipe(jeditor({ 167 | 'version': newVer 168 | })) 169 | .pipe(gulp.dest("./")) 170 | }); 171 | 172 | gulp.task('updateBower', function() { 173 | var jeditor = require("gulp-json-editor"); 174 | 175 | return gulp.src('bower.json') 176 | .pipe(jeditor({ 177 | 'version': newVer 178 | })) 179 | .pipe(gulp.dest("./")); 180 | }); 181 | 182 | gulp.task('release', ['karma'], function(done) { 183 | runSequence('promptBump', 'updatePackage', 'updateBower', 'changelog', 'build-minify', done); 184 | }); 185 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | module.exports = function(config) { 2 | config.set(module.exports.conf); 3 | 4 | if(process.env.TRAVIS) { 5 | config.logLevel = config.LOG_DEBUG; 6 | config.captureTimeout = 0; // rely on SL timeout 7 | } 8 | }; 9 | 10 | module.exports.conf = { 11 | 12 | // base path that will be used to resolve all patterns (eg. files, exclude) 13 | basePath: '', 14 | 15 | // frameworks to use 16 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 17 | frameworks: ['jasmine'], 18 | 19 | // list of files / patterns to load in the browser 20 | files: [ 21 | 'bower_components/angular/angular.js', 22 | 'bower_components/angular-mocks/angular-mocks.js', 23 | 'src/ocLazyLoad.polyfill.ie8.js', 24 | 'src/ocLazyLoad.core.js', 25 | 'src/ocLazyLoad.directive.js', 26 | 'src/ocLazyLoad.loaders.core.js', 27 | 'src/ocLazyLoad.loaders.common.js', 28 | 'src/ocLazyLoad.loaders.jsLoader.js', 29 | 'src/ocLazyLoad.loaders.cssLoader.js', 30 | 'src/ocLazyLoad.loaders.templatesLoader.js', 31 | 'tests/unit/**/*.spec.js', 32 | 'tests/unit/**/*.mock.js', 33 | {pattern: 'tests/unit/lazyLoad/**/*', included: false} 34 | ], 35 | 36 | // list of files to exclude 37 | exclude: [], 38 | 39 | // preprocess matching files before serving them to the browser 40 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 41 | preprocessors: { 42 | 'src/**/*.js': ['babel', 'coverage'] 43 | }, 44 | 45 | 'babelPreprocessor': { 46 | options: { 47 | sourceMap: 'inline' 48 | } 49 | }, 50 | 51 | // test results reporter to use 52 | // possible values: 'dots', 'progress' 53 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 54 | reporters: ['progress', 'coverage'], 55 | 56 | // web server port 57 | port: 9876, 58 | 59 | // enable / disable colors in the output (reporters and logs) 60 | colors: true, 61 | 62 | // enable / disable watching file and executing tests whenever any file changes 63 | autoWatch: true, 64 | 65 | // we use Firefox because it's the only one available in travis 66 | browsers: ['Firefox'], 67 | 68 | // Continuous Integration mode 69 | // if true, Karma captures browsers, runs the tests and exits 70 | singleRun: true, 71 | 72 | // Increase timeout in case connection in CI is slow 73 | captureTimeout: 120000, 74 | 75 | browserDisconnectTimeout: 10000, 76 | 77 | browserDisconnectTolerance: 2, 78 | 79 | browserNoActivityTimeout: 30000 80 | }; 81 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oclazyload", 3 | "version": "1.1.0", 4 | "description": "Load modules on demand (lazy load) with angularJS", 5 | "main": "dist/ocLazyLoad.js", 6 | "author": "Olivier Combe ", 7 | "license": "MIT", 8 | "homepage": "https://github.com/ocombe/ocLazyLoad", 9 | "directories": { 10 | "example": "examples" 11 | }, 12 | "scripts": { 13 | "bower": "bower install", 14 | "test": "karma start karma.conf.js", 15 | "test-dev": "karma start karma.conf.js --single-run=false", 16 | "build": "gulp build-minify" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "git://github.com/ocombe/ocLazyLoad.git" 21 | }, 22 | "keywords": [ 23 | "lazy load", 24 | "lazy-load", 25 | "load on demand", 26 | "module", 27 | "angular", 28 | "angularJS" 29 | ], 30 | "bugs": { 31 | "url": "https://github.com/ocombe/ocLazyLoad/issues" 32 | }, 33 | "devDependencies": { 34 | "bower": "~1.4.1", 35 | "gulp": "~3.9.0", 36 | "gulp-babel": "~5.1.0", 37 | "gulp-clean": "~0.3.1", 38 | "gulp-concat": "~2.5.2", 39 | "gulp-exec": "~2.1.1", 40 | "gulp-header": "~1.2.2", 41 | "gulp-json-editor": "~2.2.1", 42 | "gulp-ng-annotate": "~1.0.0", 43 | "gulp-prompt": "~0.1.2", 44 | "gulp-rename": "~1.2.2", 45 | "gulp-uglify": "~1.2.0", 46 | "jasmine-core": "~2.3.4", 47 | "karma": "~0.12.35", 48 | "karma-babel-preprocessor": "~5.2.1", 49 | "karma-chrome-launcher": "~0.1.12", 50 | "karma-cli": "~0.0.4", 51 | "karma-coverage": "~0.3.1", 52 | "karma-firefox-launcher": "~0.1.6", 53 | "karma-jasmine": "~0.3.5", 54 | "qq": "~0.3.5", 55 | "requirejs": "~2.1.18", 56 | "run-sequence": "~1.1.0", 57 | "semver": "~4.3.6", 58 | "streamqueue": "~0.1.3" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/ocLazyLoad.directive.js: -------------------------------------------------------------------------------- 1 | (angular => { 2 | 'use strict'; 3 | 4 | angular.module('oc.lazyLoad').directive('ocLazyLoad', function($ocLazyLoad, $compile, $animate, $parse, $timeout) { 5 | return { 6 | restrict: 'A', 7 | terminal: true, 8 | priority: 1000, 9 | compile: function(element, attrs) { 10 | // we store the content and remove it before compilation 11 | var content = element[0].innerHTML; 12 | element.html(''); 13 | 14 | return function($scope, $element, $attr) { 15 | var model = $parse($attr.ocLazyLoad); 16 | $scope.$watch(() => { 17 | return model($scope) || $attr.ocLazyLoad; // it can be a module name (string), an object, an array, or a scope reference to any of this 18 | }, moduleName => { 19 | if(angular.isDefined(moduleName)) { 20 | $ocLazyLoad.load(moduleName).then(() => { 21 | // Attach element contents to DOM and then compile them. 22 | // This prevents an issue where IE invalidates saved element objects (HTMLCollections) 23 | // of the compiled contents when attaching to the parent DOM. 24 | $animate.enter(content, $element); 25 | // get the new content & compile it 26 | $compile($element.contents())($scope); 27 | }); 28 | } 29 | }, true); 30 | }; 31 | } 32 | }; 33 | }); 34 | 35 | })(angular); 36 | -------------------------------------------------------------------------------- /src/ocLazyLoad.loaders.common.js: -------------------------------------------------------------------------------- 1 | (angular => { 2 | 'use strict'; 3 | 4 | angular.module('oc.lazyLoad').config($provide => { 5 | $provide.decorator('$ocLazyLoad', function($delegate, $q, $window, $interval) { 6 | var uaCssChecked = false, 7 | useCssLoadPatch = false, 8 | anchor = $window.document.getElementsByTagName('head')[0] || $window.document.getElementsByTagName('body')[0]; 9 | 10 | /** 11 | * Load a js/css file 12 | * @param type 13 | * @param path 14 | * @param params 15 | * @returns promise 16 | */ 17 | $delegate.buildElement = function buildElement(type, path, params) { 18 | var deferred = $q.defer(), 19 | el, 20 | loaded, 21 | filesCache = $delegate._getFilesCache(), 22 | cacheBuster = function cacheBuster(url) { 23 | var dc = new Date().getTime(); 24 | if(url.indexOf('?') >= 0) { 25 | if(url.substring(0, url.length - 1) === '&') { 26 | return `${ url }_dc=${ dc }`; 27 | } 28 | return `${ url }&_dc=${ dc }`; 29 | } else { 30 | return `${ url }?_dc=${ dc }`; 31 | } 32 | }; 33 | 34 | // Store the promise early so the file load can be detected by other parallel lazy loads 35 | // (ie: multiple routes on one page) a 'true' value isn't sufficient 36 | // as it causes false positive load results. 37 | if(angular.isUndefined(filesCache.get(path))) { 38 | filesCache.put(path, deferred.promise); 39 | } 40 | 41 | // Switch in case more content types are added later 42 | switch(type) { 43 | case 'css': 44 | el = $window.document.createElement('link'); 45 | el.type = 'text/css'; 46 | el.rel = 'stylesheet'; 47 | el.href = params.cache === false ? cacheBuster(path) : path; 48 | break; 49 | case 'js': 50 | el = $window.document.createElement('script'); 51 | el.src = params.cache === false ? cacheBuster(path) : path; 52 | break; 53 | default: 54 | filesCache.remove(path); 55 | deferred.reject(new Error(`Requested type "${ type }" is not known. Could not inject "${ path }"`)); 56 | break; 57 | } 58 | el.onload = el['onreadystatechange'] = function(e) { 59 | if((el['readyState'] && !/^c|loade/.test(el['readyState'])) || loaded) return; 60 | el.onload = el['onreadystatechange'] = null; 61 | loaded = 1; 62 | $delegate._broadcast('ocLazyLoad.fileLoaded', path); 63 | deferred.resolve(el); 64 | }; 65 | el.onerror = function() { 66 | filesCache.remove(path); 67 | deferred.reject(new Error(`Unable to load ${ path }`)); 68 | }; 69 | el.async = params.serie ? 0 : 1; 70 | 71 | var insertBeforeElem = anchor.lastChild; 72 | if(params.insertBefore) { 73 | var element = angular.element(angular.isDefined(window.jQuery) ? params.insertBefore : document.querySelector(params.insertBefore)); 74 | if(element && element.length > 0) { 75 | insertBeforeElem = element[0]; 76 | } 77 | } 78 | insertBeforeElem.parentNode.insertBefore(el, insertBeforeElem); 79 | 80 | /* 81 | The event load or readystatechange doesn't fire in: 82 | - PhantomJS 1.9 (headless webkit browser) 83 | - iOS < 6 (default mobile browser) 84 | - Android < 4.4 (default mobile browser) 85 | - Safari < 6 (desktop browser) 86 | */ 87 | if(type == 'css') { 88 | if(!uaCssChecked) { 89 | var ua = $window.navigator.userAgent.toLowerCase(); 90 | 91 | if (ua.indexOf('phantomjs/1.9') > -1) { 92 | // PhantomJS ~1.9 93 | useCssLoadPatch = true; 94 | } else if (/iP(hone|od|ad)/.test($window.navigator.platform)) { 95 | // iOS < 6 96 | var v = $window.navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/); 97 | var iOSVersion = parseFloat([parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)].join('.')); 98 | useCssLoadPatch = iOSVersion < 6; 99 | } else if (ua.indexOf('android') > -1) { 100 | // Android < 4.4 101 | var androidVersion = parseFloat(ua.slice(ua.indexOf('android') + 8)); 102 | useCssLoadPatch = androidVersion < 4.4; 103 | } else if (ua.indexOf('safari') > -1) { 104 | // Safari < 6 105 | var versionMatch = ua.match(/version\/([\.\d]+)/i); 106 | useCssLoadPatch = (versionMatch && versionMatch[1] && parseFloat(versionMatch[1]) < 6); 107 | } 108 | } 109 | 110 | if(useCssLoadPatch) { 111 | var tries = 1000; // * 20 = 20000 miliseconds 112 | var interval = $interval(() => { 113 | try { 114 | el.sheet.cssRules; 115 | $interval.cancel(interval); 116 | el.onload(); 117 | } catch(e) { 118 | if(--tries <= 0) { 119 | el.onerror(); 120 | } 121 | } 122 | }, 20); 123 | } 124 | } 125 | 126 | return deferred.promise; 127 | }; 128 | 129 | return $delegate; 130 | }) 131 | }); 132 | 133 | })(angular); 134 | -------------------------------------------------------------------------------- /src/ocLazyLoad.loaders.core.js: -------------------------------------------------------------------------------- 1 | (angular => { 2 | 'use strict'; 3 | 4 | angular.module('oc.lazyLoad').config(function($provide) { 5 | $provide.decorator('$ocLazyLoad', function($delegate, $q) { 6 | /** 7 | * The function that loads new files 8 | * @param config 9 | * @param params 10 | * @returns {*} 11 | */ 12 | $delegate.filesLoader = function filesLoader(config, params = {}) { 13 | var cssFiles = [], 14 | templatesFiles = [], 15 | jsFiles = [], 16 | promises = [], 17 | cachePromise = null, 18 | filesCache = $delegate._getFilesCache(); 19 | 20 | $delegate.toggleWatch(true); // start watching angular.module calls 21 | 22 | angular.extend(params, config); 23 | 24 | var pushFile = function(path) { 25 | var file_type = null, m; 26 | if(angular.isObject(path)) { 27 | file_type = path.type; 28 | path = path.path; 29 | } 30 | cachePromise = filesCache.get(path); 31 | if(angular.isUndefined(cachePromise) || params.cache === false) { 32 | 33 | // always check for requirejs syntax just in case 34 | if((m = /^(css|less|html|htm|js)?(?=!)/.exec(path)) !== null) { // Detect file type using preceding type declaration (ala requireJS) 35 | file_type = m[1]; 36 | path = path.substr(m[1].length + 1, path.length); // Strip the type from the path 37 | } 38 | 39 | if(!file_type) { 40 | if((m = /[.](css|less|html|htm|js)?((\?|#).*)?$/.exec(path)) !== null) { // Detect file type via file extension 41 | file_type = m[1]; 42 | } else if(!$delegate.jsLoader.hasOwnProperty('ocLazyLoadLoader') && $delegate.jsLoader.hasOwnProperty('requirejs')) { // requirejs 43 | file_type = 'js'; 44 | } else { 45 | $delegate._$log.error(`File type could not be determined. ${ path }`); 46 | return; 47 | } 48 | } 49 | 50 | if((file_type === 'css' || file_type === 'less') && cssFiles.indexOf(path) === -1) { 51 | cssFiles.push(path); 52 | } else if((file_type === 'html' || file_type === 'htm') && templatesFiles.indexOf(path) === -1) { 53 | templatesFiles.push(path); 54 | } else if(file_type === 'js' || jsFiles.indexOf(path) === -1) { 55 | jsFiles.push(path); 56 | } else { 57 | $delegate._$log.error(`File type is not valid. ${ path }`); 58 | } 59 | 60 | } else if(cachePromise) { 61 | promises.push(cachePromise); 62 | } 63 | }; 64 | 65 | if(params.serie) { 66 | pushFile(params.files.shift()); 67 | } else { 68 | angular.forEach(params.files, path => { 69 | pushFile(path); 70 | }); 71 | } 72 | 73 | if(cssFiles.length > 0) { 74 | var cssDeferred = $q.defer(); 75 | $delegate.cssLoader(cssFiles, err => { 76 | if(angular.isDefined(err) && $delegate.cssLoader.hasOwnProperty('ocLazyLoadLoader')) { 77 | $delegate._$log.error(err); 78 | cssDeferred.reject(err); 79 | } else { 80 | cssDeferred.resolve(); 81 | } 82 | }, params); 83 | promises.push(cssDeferred.promise); 84 | } 85 | 86 | if(templatesFiles.length > 0) { 87 | var templatesDeferred = $q.defer(); 88 | $delegate.templatesLoader(templatesFiles, err => { 89 | if(angular.isDefined(err) && $delegate.templatesLoader.hasOwnProperty('ocLazyLoadLoader')) { 90 | $delegate._$log.error(err); 91 | templatesDeferred.reject(err); 92 | } else { 93 | templatesDeferred.resolve(); 94 | } 95 | }, params); 96 | promises.push(templatesDeferred.promise); 97 | } 98 | 99 | if(jsFiles.length > 0) { 100 | var jsDeferred = $q.defer(); 101 | $delegate.jsLoader(jsFiles, err => { 102 | if(angular.isDefined(err) && ($delegate.jsLoader.hasOwnProperty("ocLazyLoadLoader") || $delegate.jsLoader.hasOwnProperty("requirejs"))) { 103 | $delegate._$log.error(err); 104 | jsDeferred.reject(err); 105 | } else { 106 | jsDeferred.resolve(); 107 | } 108 | }, params); 109 | promises.push(jsDeferred.promise); 110 | } 111 | 112 | if(promises.length === 0) { 113 | let deferred = $q.defer(), 114 | 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'."; 115 | $delegate._$log.error(err); 116 | deferred.reject(err); 117 | return deferred.promise; 118 | } else if(params.serie && params.files.length > 0) { 119 | return $q.all(promises).then(() => $delegate.filesLoader(config, params)); 120 | } else { 121 | return $q.all(promises).finally(res => { 122 | $delegate.toggleWatch(false); // stop watching angular.module calls 123 | return res; 124 | }); 125 | } 126 | }; 127 | 128 | /** 129 | * Load a module or a list of modules into Angular 130 | * @param module Mixed the name of a predefined module config object, or a module config object, or an array of either 131 | * @param params Object optional parameters 132 | * @returns promise 133 | */ 134 | $delegate.load = function(originalModule, originalParams = {}) { 135 | var self = this, 136 | config = null, 137 | deferredList = [], 138 | deferred = $q.defer(), 139 | errText; 140 | 141 | // clean copy 142 | var module = angular.copy(originalModule); 143 | var params = angular.copy(originalParams); 144 | 145 | // If module is an array, break it down 146 | if(angular.isArray(module)) { 147 | // Resubmit each entry as a single module 148 | angular.forEach(module, m => { 149 | deferredList.push(self.load(m, params)); 150 | }); 151 | 152 | // Resolve the promise once everything has loaded 153 | $q.all(deferredList).then(res => { 154 | deferred.resolve(res); 155 | }, err => { 156 | deferred.reject(err); 157 | }); 158 | 159 | return deferred.promise; 160 | } 161 | 162 | // Get or Set a configuration depending on what was passed in 163 | if(angular.isString(module)) { 164 | config = self.getModuleConfig(module); 165 | if(!config) { 166 | config = { 167 | files: [module] 168 | }; 169 | } 170 | } else if(angular.isObject(module)) { 171 | // case {type: 'js', path: lazyLoadUrl + 'testModule.fakejs'} 172 | if(angular.isDefined(module.path) && angular.isDefined(module.type)) { 173 | config = { 174 | files: [module] 175 | }; 176 | } else { 177 | config = self.setModuleConfig(module); 178 | } 179 | } 180 | 181 | if(config === null) { 182 | var moduleName = self._getModuleName(module); 183 | errText = `Module "${ moduleName || 'unknown' }" is not configured, cannot load.`; 184 | $delegate._$log.error(errText); 185 | deferred.reject(new Error(errText)); 186 | return deferred.promise; 187 | } else { 188 | // deprecated 189 | if(angular.isDefined(config.template)) { 190 | if(angular.isUndefined(config.files)) { 191 | config.files = []; 192 | } 193 | if(angular.isString(config.template)) { 194 | config.files.push(config.template); 195 | } else if(angular.isArray(config.template)) { 196 | config.files.concat(config.template); 197 | } 198 | } 199 | } 200 | 201 | var localParams = angular.extend({}, params, config); 202 | 203 | // if someone used an external loader and called the load function with just the module name 204 | if(angular.isUndefined(config.files) && angular.isDefined(config.name) && $delegate.moduleExists(config.name)) { 205 | return $delegate.inject(config.name, localParams, true); 206 | } 207 | 208 | $delegate.filesLoader(config, localParams).then(() => { 209 | $delegate.inject(null, localParams).then(res => { 210 | deferred.resolve(res); 211 | }, err => { 212 | deferred.reject(err); 213 | }); 214 | }, err => { 215 | deferred.reject(err); 216 | }); 217 | 218 | return deferred.promise; 219 | }; 220 | 221 | // return the patched service 222 | return $delegate; 223 | }); 224 | }); 225 | 226 | })(angular); 227 | -------------------------------------------------------------------------------- /src/ocLazyLoad.loaders.cssLoader.js: -------------------------------------------------------------------------------- 1 | (angular => { 2 | 'use strict'; 3 | 4 | angular.module('oc.lazyLoad').config(function($provide) { 5 | $provide.decorator('$ocLazyLoad', function ($delegate, $q) { 6 | /** 7 | * cssLoader function 8 | * @type Function 9 | * @param paths array list of css files to load 10 | * @param callback to call when everything is loaded. We use a callback and not a promise 11 | * @param params object config parameters 12 | * because the user can overwrite cssLoader and it will probably not use promises :( 13 | */ 14 | $delegate.cssLoader = function(paths, callback, params) { 15 | var promises = []; 16 | angular.forEach(paths, path => { 17 | promises.push($delegate.buildElement('css', path, params)); 18 | }); 19 | $q.all(promises).then(() => { 20 | callback(); 21 | }, err => { 22 | callback(err); 23 | }); 24 | }; 25 | $delegate.cssLoader.ocLazyLoadLoader = true; 26 | 27 | return $delegate; 28 | }) 29 | }); 30 | 31 | })(angular); 32 | -------------------------------------------------------------------------------- /src/ocLazyLoad.loaders.jsLoader.js: -------------------------------------------------------------------------------- 1 | (angular => { 2 | 'use strict'; 3 | 4 | angular.module('oc.lazyLoad').config(function($provide) { 5 | $provide.decorator('$ocLazyLoad', function ($delegate, $q) { 6 | /** 7 | * jsLoader function 8 | * @type Function 9 | * @param paths array list of js files to load 10 | * @param callback to call when everything is loaded. We use a callback and not a promise 11 | * @param params object config parameters 12 | * because the user can overwrite jsLoader and it will probably not use promises :( 13 | */ 14 | $delegate.jsLoader = function(paths, callback, params) { 15 | var promises = []; 16 | angular.forEach(paths, path => { 17 | promises.push($delegate.buildElement('js', path, params)); 18 | }); 19 | $q.all(promises).then(() => { 20 | callback(); 21 | }, err => { 22 | callback(err); 23 | }); 24 | }; 25 | $delegate.jsLoader.ocLazyLoadLoader = true; 26 | 27 | return $delegate; 28 | }) 29 | }); 30 | 31 | })(angular); 32 | -------------------------------------------------------------------------------- /src/ocLazyLoad.loaders.requireJSLoader.js: -------------------------------------------------------------------------------- 1 | (angular => { 2 | 'use strict'; 3 | 4 | angular.module('oc.lazyLoad').config(function($provide) { 5 | $provide.decorator('$ocLazyLoad', function ($delegate, $q) { 6 | /** 7 | * jsLoader function 8 | * @type Function 9 | * @param paths array list of js files to load 10 | * @param callback to call when everything is loaded. We use a callback and not a promise 11 | * @param params object config parameters 12 | * because the user can overwrite jsLoader and it will probably not use promises :( 13 | */ 14 | $delegate.jsLoader = function (paths, callback, params) { 15 | require(paths, callback.bind(null, undefined), callback, params); 16 | }; 17 | $delegate.jsLoader.requirejs = true; 18 | 19 | return $delegate; 20 | }) 21 | }); 22 | 23 | })(angular); 24 | -------------------------------------------------------------------------------- /src/ocLazyLoad.loaders.templatesLoader.js: -------------------------------------------------------------------------------- 1 | (angular => { 2 | 'use strict'; 3 | 4 | angular.module('oc.lazyLoad').config(function($provide) { 5 | $provide.decorator('$ocLazyLoad', function ($delegate, $templateCache, $q, $http) { 6 | /** 7 | * templatesLoader function 8 | * @type Function 9 | * @param paths array list of css files to load 10 | * @param callback to call when everything is loaded. We use a callback and not a promise 11 | * @param params object config parameters for $http 12 | * because the user can overwrite templatesLoader and it will probably not use promises :( 13 | */ 14 | $delegate.templatesLoader = function(paths, callback, params) { 15 | var promises = [], 16 | filesCache = $delegate._getFilesCache(); 17 | 18 | angular.forEach(paths, url => { 19 | var deferred = $q.defer(); 20 | promises.push(deferred.promise); 21 | $http.get(url, params).then(response => { 22 | let data = response.data; 23 | if(angular.isString(data) && data.length > 0) { 24 | angular.forEach(angular.element(data), node => { 25 | if(node.nodeName === 'SCRIPT' && node.type === 'text/ng-template') { 26 | $templateCache.put(node.id, node.innerHTML); 27 | } 28 | }); 29 | } 30 | if(angular.isUndefined(filesCache.get(url))) { 31 | filesCache.put(url, true); 32 | } 33 | deferred.resolve(); 34 | }).catch(response => { 35 | deferred.reject(new Error(`Unable to load template file "${ url }": ${ response.data }`)); 36 | }); 37 | }); 38 | return $q.all(promises).then(() => { 39 | callback(); 40 | }, err => { 41 | callback(err); 42 | }); 43 | }; 44 | $delegate.templatesLoader.ocLazyLoadLoader = true; 45 | 46 | return $delegate; 47 | }) 48 | }); 49 | 50 | })(angular); 51 | -------------------------------------------------------------------------------- /src/ocLazyLoad.polyfill.ie8.js: -------------------------------------------------------------------------------- 1 | // Array.indexOf polyfill for IE8 2 | if(!Array.prototype.indexOf) { 3 | Array.prototype.indexOf = function(searchElement, fromIndex) { 4 | var k; 5 | 6 | // 1. Let O be the result of calling ToObject passing 7 | // the this value as the argument. 8 | if(this == null) { 9 | throw new TypeError('"this" is null or not defined'); 10 | } 11 | 12 | var O = Object(this); 13 | 14 | // 2. Let lenValue be the result of calling the Get 15 | // internal method of O with the argument "length". 16 | // 3. Let len be ToUint32(lenValue). 17 | var len = O.length >>> 0; 18 | 19 | // 4. If len is 0, return -1. 20 | if(len === 0) { 21 | return -1; 22 | } 23 | 24 | // 5. If argument fromIndex was passed let n be 25 | // ToInteger(fromIndex); else let n be 0. 26 | var n = +fromIndex || 0; 27 | 28 | if(Math.abs(n) === Infinity) { 29 | n = 0; 30 | } 31 | 32 | // 6. If n >= len, return -1. 33 | if(n >= len) { 34 | return -1; 35 | } 36 | 37 | // 7. If n >= 0, then Let k be n. 38 | // 8. Else, n<0, Let k be len - abs(n). 39 | // If k is less than 0, then let k be 0. 40 | k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); 41 | 42 | // 9. Repeat, while k < len 43 | while(k < len) { 44 | // a. Let Pk be ToString(k). 45 | // This is implicit for LHS operands of the in operator 46 | // b. Let kPresent be the result of calling the 47 | // HasProperty internal method of O with argument Pk. 48 | // This step can be combined with c 49 | // c. If kPresent is true, then 50 | // i. Let elementK be the result of calling the Get 51 | // internal method of O with the argument ToString(k). 52 | // ii. Let same be the result of applying the 53 | // Strict Equality Comparison Algorithm to 54 | // searchElement and elementK. 55 | // iii. If same is true, return k. 56 | if(k in O && O[k] === searchElement) { 57 | return k; 58 | } 59 | k++; 60 | } 61 | return -1; 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /tests/unit/lazyLoad/myContainer.js: -------------------------------------------------------------------------------- 1 | angular.module('myContainer', []).directive('myContainer', function() { 2 | return { 3 | restrict: 'E', 4 | template: '', 5 | controllerAs: 'vm', 6 | bindToController: true, 7 | controller: function($element) { 8 | var vm = this; 9 | vm.highlanders = $element[0].getElementsByTagName('highlander'); 10 | } 11 | }; 12 | }); 13 | -------------------------------------------------------------------------------- /tests/unit/lazyLoad/test.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #111; 3 | } 4 | -------------------------------------------------------------------------------- /tests/unit/lazyLoad/test.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests/unit/lazyLoad/testModule.fakejs: -------------------------------------------------------------------------------- 1 | // ngGrid is also lazy loaded by $ocLazyLoad thanks to the module dependency injection ! 2 | var testModuleNoExt = angular.module('testModuleNoExt', []); 3 | 4 | // config blocks 5 | testModuleNoExt.config(function() { 6 | spy.config('config1'); 7 | }); 8 | 9 | testModuleNoExt.config(function() { 10 | spy.config('config2'); 11 | }); 12 | 13 | // run blocks 14 | testModuleNoExt.run(function() { 15 | spy.run('run1'); 16 | }); 17 | 18 | testModuleNoExt.run(function() { 19 | spy.run('run2'); 20 | }); 21 | 22 | // controllers 23 | testModuleNoExt.controller('TestCtrlNoExt', function($scope) { 24 | spy.ctrl('ctrl'); 25 | }); 26 | 27 | // 28 | testModuleNoExt.factory('testServiceNoExt', [function () { 29 | spy.service('service'); 30 | return {}; 31 | }]); 32 | 33 | testModuleNoExt.filter('testFilterNoExt', function () { 34 | spy.filter('filter'); 35 | return function (input) { 36 | return input; 37 | } 38 | }); 39 | 40 | testModuleNoExt.directive("testNoExt", function () { 41 | spy.directive('directive'); 42 | return { 43 | restrict: 'E', 44 | replace: true, 45 | template: '
Test template {{1 + 1}}
' 46 | }; 47 | }); 48 | 49 | // redefine directive to check that both won't be invoked (it would throw a [$compile:multidir] Multiple directives) 50 | testModuleNoExt.directive("testNoExt", function () { 51 | spy.directive('directive'); 52 | return { 53 | restrict: 'E', 54 | replace: true, 55 | template: '
Test template {{1 + 1}}
' 56 | }; 57 | }); 58 | -------------------------------------------------------------------------------- /tests/unit/lazyLoad/testModule.js: -------------------------------------------------------------------------------- 1 | var testModule = angular.module('testModule', []); 2 | 3 | // config blocks 4 | testModule.config(function() { 5 | spy.config('config1'); 6 | }); 7 | 8 | testModule.config(function() { 9 | spy.config('config2'); 10 | }); 11 | 12 | // run blocks 13 | testModule.run(function() { 14 | spy.run('run1'); 15 | }); 16 | 17 | testModule.run(function() { 18 | spy.run('run2'); 19 | }); 20 | 21 | // controllers 22 | testModule.controller('TestCtrl', function($scope) { 23 | spy.ctrl('ctrl'); 24 | }); 25 | 26 | // services 27 | testModule.factory('testService', [function () { 28 | spy.service('service'); 29 | return {}; 30 | }]); 31 | 32 | // filters 33 | angular.module('testModule').filter('testFilter', function () { 34 | spy.filter('filter'); 35 | return function (input) { 36 | return input; 37 | } 38 | }); 39 | 40 | // directives 41 | testModule.directive("test", function () { 42 | spy.directive('directive'); 43 | return { 44 | restrict: 'E', 45 | replace: true, 46 | template: '
Test template {{1 + 1}}
' 47 | }; 48 | }); 49 | 50 | if(angular.version.minor > 3) { // only in angular 1.4+ 51 | // decorators 52 | testModule.decorator("testService", function($delegate) { 53 | spy.decorator('decorator'); 54 | return $delegate; 55 | }); 56 | } 57 | 58 | // redefine directive to check that both won't be invoked (it would throw a [$compile:multidir] Multiple directives) 59 | testModule.directive("test", function () { 60 | spy.directive('directive'); 61 | return { 62 | restrict: 'E', 63 | replace: true, 64 | template: '
Test template {{1 + 1}}
' 65 | }; 66 | }); 67 | 68 | // constants 69 | testModule.constant("myConst0", {bar: 'foo'}); 70 | testModule.constant("myConst1", "something"); 71 | testModule.constant("myConst2", undefined); 72 | testModule.constant("myConst3", null); 73 | testModule.constant("myConst4", function() {}); 74 | -------------------------------------------------------------------------------- /tests/unit/lazyLoad/testModule2.js: -------------------------------------------------------------------------------- 1 | var mod2 = angular.module('testModule2', []); 2 | -------------------------------------------------------------------------------- /tests/unit/lazyLoad/testModule3.js: -------------------------------------------------------------------------------- 1 | angular.module('testModule3', ['testModule2']); 2 | -------------------------------------------------------------------------------- /tests/unit/lazyLoad/testModule4.js: -------------------------------------------------------------------------------- 1 | var testModule = angular.module('testModule4', []); 2 | -------------------------------------------------------------------------------- /tests/unit/lazyLoad/testModule5.js: -------------------------------------------------------------------------------- 1 | var testModule = angular.module('testModule5', []); 2 | 3 | testModule.controller({ 4 | "testModule5Ctrl": angular.noop 5 | }); 6 | -------------------------------------------------------------------------------- /tests/unit/lazyLoad/testModule6.js: -------------------------------------------------------------------------------- 1 | var testModule = angular.module('testModule6', []); 2 | -------------------------------------------------------------------------------- /tests/unit/mocks/app.mock.js: -------------------------------------------------------------------------------- 1 | angular.module('app1', ['oc.lazyLoad']) 2 | .config(['$ocLazyLoadProvider', function($ocLazyLoadProvider) { 3 | $ocLazyLoadProvider.config({ 4 | modules: [{ 5 | name: 'test', 6 | files: [] 7 | }] 8 | }); 9 | }]); 10 | -------------------------------------------------------------------------------- /tests/unit/specs/ocLazyLoad.spec.js: -------------------------------------------------------------------------------- 1 | describe('Module: oc.lazyLoad', function() { 2 | 'use strict'; 3 | 4 | var $ocLazyLoad, 5 | $rootScope, 6 | $controller, 7 | $injector, 8 | $filter, 9 | $compile, 10 | $httpBackend, 11 | $log, 12 | element, 13 | lazyLoadUrl = '/base/tests/unit/lazyLoad/', 14 | triggerDigests = function() { 15 | return setInterval(function() { 16 | $rootScope.$digest(); 17 | }, 10) 18 | }; 19 | 20 | describe('with app1', function() { 21 | 22 | beforeEach(function() { 23 | module('app1'); 24 | 25 | // get the $httpBackend from E2E tests (because the one for unit tests sucks) 26 | module('ngMockE2E'); 27 | module(function($provide) { 28 | //retrieve the $httpBackend from module ng and override $delegate from ngMockE2E 29 | angular.injector(['ng']) 30 | .invoke(function($httpBackend) { 31 | $provide.value('$delegate', $httpBackend); 32 | }); 33 | 34 | //retrieve the $httpBackend from module ng and override $delegate from ngMockE2E 35 | angular.injector(['ngMockE2E']) 36 | .invoke(['$httpBackend', function(_$httpBackend_) { 37 | $httpBackend = _$httpBackend_; 38 | }]); 39 | 40 | $provide.value('$httpBackend', $httpBackend); 41 | }); 42 | 43 | // get the services for all tests 44 | inject(function(_$ocLazyLoad_, _$rootScope_, _$controller_, _$injector_, _$filter_, _$compile_, _$log_) { 45 | $ocLazyLoad = _$ocLazyLoad_; 46 | $rootScope = _$rootScope_; 47 | $controller = _$controller_; 48 | $injector = _$injector_; 49 | $filter = _$filter_; 50 | $compile = _$compile_; 51 | $log = _$log_; 52 | }); 53 | 54 | // allow requests for lazy loaded files 55 | $httpBackend.when('GET', new RegExp(lazyLoadUrl)).passThrough(); 56 | }); 57 | 58 | it('service should be defined', function() { 59 | expect($ocLazyLoad).toBeDefined(); 60 | }); 61 | 62 | it('getModules should be working', function() { 63 | expect($ocLazyLoad.getModules).toBeDefined(); 64 | expect(angular.isArray($ocLazyLoad.getModules())).toBe(true); 65 | }); 66 | 67 | it('loadedModules should be working', function() { 68 | expect($ocLazyLoad.getModules()).toEqual(['ng', 'oc.lazyLoad']); 69 | }); 70 | 71 | it('angular.bootstrap should add the module to the loaded list', function() { 72 | angular.bootstrap(document, ['app1']); 73 | expect($ocLazyLoad.getModules()).toEqual(['ng', 'oc.lazyLoad', 'app1']); 74 | }); 75 | 76 | it('isLoaded should be working', function() { 77 | expect($ocLazyLoad.isLoaded).toBeDefined(); 78 | expect($ocLazyLoad.isLoaded).toThrowError('You need to define the module(s) name(s)'); 79 | expect($ocLazyLoad.isLoaded('app1')).toBe(true); // string arg 80 | expect($ocLazyLoad.isLoaded(['ng', 'app1'])).toBe(true); // array arg 81 | expect($ocLazyLoad.isLoaded('noModule')).toBe(false); 82 | expect($ocLazyLoad.isLoaded(['ng', 'noModule'])).toBe(false); 83 | }); 84 | 85 | it('getModuleConfig should be working', function() { 86 | expect($ocLazyLoad.getModuleConfig).toBeDefined(); 87 | expect($ocLazyLoad.getModuleConfig).toThrowError('You need to give the name of the module to get'); 88 | expect($ocLazyLoad.getModuleConfig('noModule')).toBe(null); 89 | expect($ocLazyLoad.getModuleConfig('test')).toEqual({name: 'test', files: []}); 90 | }); 91 | 92 | it('setModuleConfig should be working', function() { 93 | expect($ocLazyLoad.setModuleConfig).toBeDefined(); 94 | expect($ocLazyLoad.setModuleConfig).toThrowError('You need to give the module config object to set'); 95 | expect($ocLazyLoad.setModuleConfig({name: 'test2'})).toEqual({name: 'test2'}); 96 | expect($ocLazyLoad.getModuleConfig('test2')).toEqual({name: 'test2'}); // check if set worked 97 | }); 98 | 99 | it('should be able to lazy load a module', function(done) { 100 | var interval = triggerDigests(), 101 | templateUrl = lazyLoadUrl + 'test.html', 102 | testModule = [ 103 | lazyLoadUrl + 'testModule.js', 104 | lazyLoadUrl + 'test.css', 105 | templateUrl 106 | ]; 107 | 108 | // create spies for the following tests 109 | window.spy = jasmine.createSpyObj('spy', ['config', 'run', 'ctrl', 'service', 'filter', 'directive', 'decorator']); 110 | 111 | $ocLazyLoad.load(testModule).then(function success(res) { 112 | window.clearInterval(interval); 113 | 114 | // Test the module loading 115 | expect(function() { 116 | angular.module('testModule') 117 | }).not.toThrow(); 118 | expect(angular.module('testModule')).toBeDefined(); 119 | 120 | // execute controller 121 | expect(function() { 122 | $controller('TestCtrl', {$scope: $rootScope.$new()}); 123 | }).not.toThrow(); 124 | 125 | // instantiate service 126 | expect(function() { 127 | $injector.get('testService'); 128 | }).not.toThrow(); 129 | 130 | // execute filter 131 | expect(function() { 132 | $filter('testFilter'); 133 | }).not.toThrow(); 134 | 135 | // Compile a piece of HTML containing the directive 136 | element = $compile("")($rootScope.$new()); 137 | 138 | // Test the template loading 139 | var $templateCache; 140 | expect(function() { 141 | $templateCache = $injector.get('$templateCache'); 142 | }).not.toThrow(); 143 | expect($templateCache.get('/partials/test.html')).toEqual('Test partial content'); 144 | 145 | // Test the css loading 146 | var links = document.getElementsByTagName('link'); 147 | expect(links.length).toBeGreaterThan(0); 148 | expect(function() { 149 | links[links.length - 1].sheet.cssRules; 150 | }).not.toThrow(); // this only works if a stylesheet has been loaded 151 | expect(links[links.length - 1].sheet.cssRules).toBeDefined(); 152 | 153 | // because debug is set to false, we shouldn't have any log 154 | $log.assertEmpty(); 155 | 156 | done(); 157 | }, function error(err) { 158 | window.clearInterval(interval); 159 | throw err; 160 | }); 161 | }); 162 | 163 | it('should be able to execute config blocks', function() { 164 | expect(window.spy.config).toHaveBeenCalledWith('config1'); 165 | expect(window.spy.config).toHaveBeenCalledWith('config2'); 166 | expect(window.spy.config.calls.count()).toEqual(2); 167 | }); 168 | 169 | it('should be able to execute run blocks', function() { 170 | expect(window.spy.run).toHaveBeenCalledWith('run1'); 171 | expect(window.spy.run).toHaveBeenCalledWith('run2'); 172 | expect(window.spy.run.calls.count()).toEqual(2); 173 | }); 174 | 175 | it('should be able to define controllers', function() { 176 | expect(window.spy.ctrl).toHaveBeenCalledWith('ctrl'); 177 | expect(window.spy.ctrl.calls.count()).toEqual(1); 178 | }); 179 | 180 | it('should be able to define services', function() { 181 | expect(window.spy.service).toHaveBeenCalledWith('service'); 182 | expect(window.spy.service.calls.count()).toEqual(1); 183 | }); 184 | 185 | it('should be able to define filters', function() { 186 | expect(window.spy.filter).toHaveBeenCalledWith('filter'); 187 | expect(window.spy.filter.calls.count()).toEqual(1); 188 | }); 189 | 190 | it('should be able to define directives', function() { 191 | expect(window.spy.directive).toHaveBeenCalledWith('directive'); 192 | expect(window.spy.directive.calls.count()).toEqual(1); 193 | expect(element.html()).toContain("Test template"); 194 | }); 195 | 196 | if(angular.version.minor > 3) { // only in angular 1.4+ 197 | it('should be able to define decorators', function() { 198 | expect(window.spy.decorator).toHaveBeenCalledWith('decorator'); 199 | expect(window.spy.service.calls.count()).toEqual(1); 200 | }); 201 | } 202 | 203 | it('should be able to resolve a file name with url parameters', function(done) { 204 | var interval = triggerDigests(), 205 | testModule = [ 206 | lazyLoadUrl + 'test.html?v=xy12' 207 | ]; 208 | 209 | $ocLazyLoad.load(testModule).then(function success(res) { 210 | window.clearInterval(interval); 211 | 212 | var $templateCache = $injector.get('$templateCache'); 213 | expect($templateCache.get('/partials/test.html')).toEqual('Test partial content'); 214 | 215 | // because debug is set to false, we shouldn't have any log 216 | $log.assertEmpty(); 217 | 218 | done(); 219 | }, function error(err) { 220 | window.clearInterval(interval); 221 | throw err; 222 | }); 223 | }); 224 | 225 | it('should be able to lazy load a module when specifying a file type', function(done) { 226 | var interval = triggerDigests(), 227 | testModuleNoExt = [ 228 | {type: 'js', path: lazyLoadUrl + 'testModule.fakejs'}, 229 | lazyLoadUrl + 'test.css', 230 | 'html!' + lazyLoadUrl + 'test.html' 231 | ]; 232 | 233 | $ocLazyLoad.load(testModuleNoExt).then(function success(res) { 234 | window.clearInterval(interval); 235 | 236 | // Test the module loading 237 | expect(angular.module('testModuleNoExt')).toBeDefined(); 238 | 239 | // execute controller 240 | $controller('TestCtrlNoExt', {$scope: $rootScope.$new()}); 241 | 242 | // instantiate service 243 | $injector.get('testServiceNoExt'); 244 | 245 | // execute filter 246 | $filter('testFilterNoExt'); 247 | 248 | // Compile a piece of HTML containing the directive 249 | element = $compile("")($rootScope.$new()); 250 | 251 | // Test the template loading 252 | var $templateCache = $injector.get('$templateCache'); 253 | expect($templateCache.get('/partials/test.html')).toEqual('Test partial content'); 254 | 255 | // Test the css loading 256 | var links = document.getElementsByTagName('link'); 257 | expect(links.length).toBeGreaterThan(0); 258 | expect(function() { 259 | links[links.length - 1].sheet.cssRules; 260 | }).not.toThrow(); // this only works if a stylesheet has been loaded 261 | expect(links[links.length - 1].sheet.cssRules).toBeDefined(); 262 | 263 | // because debug is set to false, we shouldn't have any log 264 | $log.assertEmpty(); 265 | 266 | done(); 267 | }, function error(err) { 268 | window.clearInterval(interval); 269 | throw err; 270 | }); 271 | }); 272 | 273 | it('should be able to lazy load a module when the url ends with a hash', function(done) { 274 | var interval = triggerDigests(); 275 | 276 | $ocLazyLoad.load(lazyLoadUrl + 'testModule4.js#hash').then(function success(res) { 277 | window.clearInterval(interval); 278 | 279 | // Test the module loading 280 | expect(angular.module('testModule4')).toBeDefined(); 281 | 282 | // Test the module loading 283 | expect(res).toBeDefined(); 284 | 285 | // because debug is set to false, we shouldn't have any log 286 | $log.assertEmpty(); 287 | 288 | done(); 289 | }, function error(err) { 290 | window.clearInterval(interval); 291 | throw err; 292 | }); 293 | }); 294 | 295 | it('should reject the promise when the jsLoader is unable to load a file', function(done) { 296 | var interval = triggerDigests(); 297 | 298 | $ocLazyLoad.load(lazyLoadUrl + 'noFile.js').then(function success(res) { 299 | window.clearInterval(interval); 300 | throw(new Error('failed!')); 301 | }, function error(err) { 302 | expect(err.message).toEqual('Unable to load ' + lazyLoadUrl + 'noFile.js'); 303 | window.clearInterval(interval); 304 | done(); 305 | }); 306 | }); 307 | 308 | // test 17 309 | it('should reject the promise when the cssLoader is unable to load a file', function(done) { 310 | var interval = triggerDigests(); 311 | 312 | $ocLazyLoad.load(lazyLoadUrl + 'noFile.css').then(function success(res) { 313 | window.clearInterval(interval); 314 | throw(new Error('failed!')); 315 | }, function error(err) { 316 | expect(err.message).toEqual('Unable to load ' + lazyLoadUrl + 'noFile.css'); 317 | window.clearInterval(interval); 318 | done(); 319 | }); 320 | }); 321 | 322 | it('should reject the promise when the templateLoader is unable to load a file', function(done) { 323 | var interval = triggerDigests(); 324 | 325 | $ocLazyLoad.load(lazyLoadUrl + 'noFile.html').then(function success(res) { 326 | window.clearInterval(interval); 327 | throw(new Error('failed!')); 328 | }, function error(err) { 329 | expect(err.message).toEqual('Unable to load template file "' + lazyLoadUrl + 'noFile.html": NOT FOUND'); 330 | window.clearInterval(interval); 331 | done(); 332 | }); 333 | }); 334 | 335 | it('should throw if you try to load a module with missing dependencies', function(done) { 336 | var interval = triggerDigests(); 337 | 338 | $ocLazyLoad.load([lazyLoadUrl + 'testModule3.js']).then(function success(res) { 339 | window.clearInterval(interval); 340 | throw(new Error('failed!')); 341 | }, function error(err) { 342 | expect(err).toBeDefined(); 343 | window.clearInterval(interval); 344 | done(); 345 | }); 346 | }); 347 | 348 | it('should be able to load a module with dependencies', function(done) { 349 | var interval = triggerDigests(); 350 | 351 | $ocLazyLoad.load([lazyLoadUrl + 'testModule2.js', lazyLoadUrl + 'testModule3.js']).then(function success(res) { 352 | expect(function() { 353 | angular.module('testModule2'); 354 | angular.module('testModule3'); 355 | }).not.toThrow(); 356 | window.clearInterval(interval); 357 | done(); 358 | }, function error(err) { 359 | window.clearInterval(interval); 360 | throw err; 361 | }); 362 | }); 363 | 364 | it('should be able to load a module with params', function(done) { 365 | var interval = triggerDigests(); 366 | 367 | $ocLazyLoad.load({files: [lazyLoadUrl + 'testModule2.js'], cache: false}).then(function success(res) { 368 | expect(function() { 369 | angular.module('testModule2'); 370 | }).not.toThrow(); 371 | window.clearInterval(interval); 372 | done(); 373 | }, function error(err) { 374 | window.clearInterval(interval); 375 | throw err; 376 | }); 377 | }); 378 | 379 | it('should be able to load a component defined as an object', function(done) { 380 | var interval = triggerDigests(); 381 | 382 | $ocLazyLoad.load(lazyLoadUrl + 'testModule5.js').then(function success(res) { 383 | expect(function() { 384 | angular.module('testModule5'); 385 | }).not.toThrow(); 386 | 387 | // execute controller 388 | expect(function() { 389 | $controller('testModule5Ctrl', {$scope: $rootScope.$new()}); 390 | }).not.toThrow(); 391 | 392 | window.clearInterval(interval); 393 | done(); 394 | }, function error(err) { 395 | window.clearInterval(interval); 396 | throw err; 397 | }); 398 | }); 399 | 400 | it('should be able to load a module with insertBefore', function(done) { 401 | var interval = triggerDigests(); 402 | 403 | $ocLazyLoad.load({files: [lazyLoadUrl + 'testModule6.js'], insertBefore: "title"}).then(function success(res) { 404 | expect(function() { 405 | angular.module('testModule6'); 406 | }).not.toThrow(); 407 | window.clearInterval(interval); 408 | done(); 409 | }, function error(err) { 410 | window.clearInterval(interval); 411 | throw err; 412 | }); 413 | }); 414 | 415 | it('should be able to load files with the param serie set to true', function(done) { 416 | var interval = triggerDigests(), 417 | params = {files: [lazyLoadUrl + 'testModule5.js', lazyLoadUrl + 'testModule6.js'], serie: true}; 418 | 419 | $ocLazyLoad.load(params).then(function success(res) { 420 | expect(function() { 421 | angular.module('testModule5'); 422 | angular.module('testModule6'); 423 | }).not.toThrow(); 424 | 425 | expect(params.files.length).toEqual(2); // it should not change the original params 426 | 427 | window.clearInterval(interval); 428 | done(); 429 | }, function error(err) { 430 | window.clearInterval(interval); 431 | throw err; 432 | }); 433 | }); 434 | 435 | it('should attach and then compile an element', function(done) { 436 | var fileToLoad = lazyLoadUrl + 'myContainer.js'; 437 | var scope = $rootScope.$new(); 438 | var interval; 439 | 440 | $ocLazyLoad.load(fileToLoad).then(function success(res) { 441 | scope.fileToLoad = fileToLoad; 442 | var element = $compile('
')(scope); 443 | setTimeout(function() { 444 | // Should be able to save an element during compilation and reference 445 | // it after the element has been attached to the parent DOM. 446 | // IE throws "Invalid calling object" if the element is compiled and then attached. 447 | expect(scope.vm.highlanders.length).toBe(1); 448 | 449 | window.clearInterval(interval); 450 | done(); 451 | }, interval * 2); 452 | }); 453 | 454 | interval = triggerDigests(); 455 | }); 456 | }); 457 | }); 458 | -------------------------------------------------------------------------------- /validate-commit-msg.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Git COMMIT-MSG hook for validating commit message 5 | * See https://docs.google.com/document/d/1rk04jEuGfk9kYzfqCuOlPTSJw3hEDZJTBN5E5f1SALo/edit 6 | * 7 | * Installation: 8 | * >> cd 9 | * >> ln -s ../../validate-commit-msg.js .git/hooks/commit-msg 10 | */ 11 | var fs = require('fs'); 12 | var util = require('util'); 13 | 14 | 15 | var MAX_LENGTH = 100; 16 | var PATTERN = /^(?:fixup!\s*)?(\w*)(\(([\w\$\.\-\*/]*)\))?\: (.*)$/; 17 | var IGNORED = /^WIP\:/; 18 | var TYPES = { 19 | feat: true, 20 | fix: true, 21 | docs: true, 22 | style: true, 23 | refactor: true, 24 | perf: true, 25 | test: true, 26 | chore: true, 27 | revert: true 28 | }; 29 | 30 | 31 | var error = function() { 32 | // gitx does not display it 33 | // http://gitx.lighthouseapp.com/projects/17830/tickets/294-feature-display-hook-error-message-when-hook-fails 34 | // https://groups.google.com/group/gitx/browse_thread/thread/a03bcab60844b812 35 | console.error('INVALID COMMIT MSG: ' + util.format.apply(null, arguments)); 36 | }; 37 | 38 | 39 | var validateMessage = function(message) { 40 | var isValid = true; 41 | 42 | if (IGNORED.test(message)) { 43 | console.log('Commit message validation ignored.'); 44 | return true; 45 | } 46 | 47 | if (message.length > MAX_LENGTH) { 48 | error('is longer than %d characters !', MAX_LENGTH); 49 | isValid = false; 50 | } 51 | 52 | var match = PATTERN.exec(message); 53 | 54 | if (!match) { 55 | error('does not match "(): " ! was: ' + message); 56 | return false; 57 | } 58 | 59 | var type = match[1]; 60 | var scope = match[3]; 61 | var subject = match[4]; 62 | 63 | if (!TYPES.hasOwnProperty(type)) { 64 | error('"%s" is not allowed type !', type); 65 | return false; 66 | } 67 | 68 | // Some more ideas, do want anything like this ? 69 | // - allow only specific scopes (eg. fix(docs) should not be allowed ? 70 | // - auto correct the type to lower case ? 71 | // - auto correct first letter of the subject to lower case ? 72 | // - auto add empty line after subject ? 73 | // - auto remove empty () ? 74 | // - auto correct typos in type ? 75 | // - store incorrect messages, so that we can learn 76 | 77 | return isValid; 78 | }; 79 | 80 | 81 | var firstLineFromBuffer = function(buffer) { 82 | return buffer.toString().split('\n').shift(); 83 | }; 84 | 85 | 86 | 87 | // publish for testing 88 | exports.validateMessage = validateMessage; 89 | 90 | // hacky start if not run by jasmine :-D 91 | if (process.argv.join('').indexOf('jasmine-node') === -1) { 92 | var commitMsgFile = process.argv[2]; 93 | var incorrectLogFile = commitMsgFile.replace('COMMIT_EDITMSG', 'logs/incorrect-commit-msgs'); 94 | 95 | fs.readFile(commitMsgFile, function(err, buffer) { 96 | var msg = firstLineFromBuffer(buffer); 97 | 98 | if (!validateMessage(msg)) { 99 | fs.appendFile(incorrectLogFile, msg + '\n', function() { 100 | process.exit(1); 101 | }); 102 | } else { 103 | process.exit(0); 104 | } 105 | }); 106 | } 107 | --------------------------------------------------------------------------------