├── src
├── version.txt
├── banner.txt
├── ngload.js
├── jshintrc.json
└── angularAMD.js
├── bin
├── karma
├── protractor
└── webdriver-manager
├── .travis.yml
├── test
├── unit
│ ├── lib
│ │ ├── regServices.js
│ │ ├── preService.js
│ │ ├── controllerFn.js
│ │ ├── decoServices.js
│ │ ├── component.js
│ │ ├── regController.js
│ │ ├── app_no_ngload.js
│ │ ├── controller.js
│ │ ├── main.no_ngload.js
│ │ ├── app.js
│ │ ├── services.js
│ │ ├── main.mustache
│ │ └── providerFactory.js
│ ├── regServices.spec.js
│ ├── decoServices.spec.js
│ ├── factory
│ │ ├── utestModule.js
│ │ ├── module.js
│ │ ├── utestProvider.js
│ │ └── provider.js
│ ├── app_no_ngload.spec.js
│ ├── controllerFn.spec.js
│ ├── regController.spec.js
│ ├── services.spec.js
│ ├── controller.spec.js
│ └── app.spec.js
├── conf
│ ├── protractor.e2e.js
│ ├── karma.unit.no_ngload.js
│ └── karma.unit.mustache
└── e2e
│ └── www.spec.js
├── .gitignore
├── dist
├── ngload.min.js
├── ngload.min.map
├── ngload.js
├── angularAMD.min.js
├── angularAMD.min.map
└── angularAMD.js
├── www
├── js
│ ├── scripts
│ │ ├── controller
│ │ │ ├── map_ctrl.js
│ │ │ ├── modules_ctrl.js
│ │ │ ├── home_ctrl.js
│ │ │ └── pictures_ctrl.js
│ │ ├── directive
│ │ │ ├── templates
│ │ │ │ └── navMenu.html
│ │ │ ├── navMenu.js
│ │ │ └── write.js
│ │ ├── service
│ │ │ ├── dataServices.js
│ │ │ ├── mapServices.js
│ │ │ └── picturesService.js
│ │ └── app.js
│ └── main.js
├── views
│ ├── map.html
│ ├── pictures.html
│ ├── modules.html
│ └── home.html
├── index.html
└── css
│ ├── sons-of-obsidian.css
│ └── style.css
├── bower.json
├── .jshintrc
├── LICENSE
├── package.json
├── CHANGELOG.md
├── README.md
└── Gruntfile.js
/src/version.txt:
--------------------------------------------------------------------------------
1 | 0.2.1
--------------------------------------------------------------------------------
/bin/karma:
--------------------------------------------------------------------------------
1 | ../node_modules/karma/bin/karma
--------------------------------------------------------------------------------
/bin/protractor:
--------------------------------------------------------------------------------
1 | ../node_modules/protractor/bin/protractor
--------------------------------------------------------------------------------
/bin/webdriver-manager:
--------------------------------------------------------------------------------
1 | ../node_modules/protractor/bin/webdriver-manager
--------------------------------------------------------------------------------
/src/banner.txt:
--------------------------------------------------------------------------------
1 | /*!
2 | angularAMD v<%= cvars.proj_version %>
3 | (c) 2013-2014 Marcos Lin https://github.com/marcoslin/
4 | License: MIT
5 | */
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - 0.10
5 |
6 | branches:
7 | only:
8 | - master
9 |
10 | before_script:
11 | - npm update -g npm
12 | - npm install grunt-cli
13 |
--------------------------------------------------------------------------------
/test/unit/lib/regServices.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Simulate the creation of provider using app.
3 | */
4 | define(['app', 'test/unit/factory/provider'], function(app, providerFactory) {
5 | return providerFactory(app, "Reg");
6 | });
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore Directory created by tools
2 | node_modules/
3 | bower_components/
4 | www/js/lib/
5 | build/
6 |
7 | # Ignore css sourced from bower
8 | www/css/prettify.css
9 |
10 | # Other
11 | phantomjsdriver.log
12 |
13 |
14 |
--------------------------------------------------------------------------------
/dist/ngload.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | angularAMD v0.2.1
3 | (c) 2013-2014 Marcos Lin https://github.com/marcoslin/
4 | License: MIT
5 | */
6 |
7 | define({load:function(a,b,c){"use strict";b(["angularAMD",a],function(a,b){a.processQueue(),c(b)})}});
8 | //# sourceMappingURL=ngload.min.map
--------------------------------------------------------------------------------
/test/unit/lib/preService.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Simulate the creation of provider using angularAMD. Used before bootstrap
3 | */
4 | define(['angularAMD', 'test/unit/factory/provider'], function(angularAMD, providerFactory) {
5 | return providerFactory(angularAMD, "Pre");
6 | });
7 |
--------------------------------------------------------------------------------
/test/unit/lib/controllerFn.js:
--------------------------------------------------------------------------------
1 | /*jslint nomen: true */
2 | /*globals define, angular */
3 |
4 | define(['app'], function (app) {
5 | 'use strict';
6 | return ["$scope", function ($scope) {
7 | $scope.message = "Message from controllerFn";
8 | }];
9 | });
10 |
--------------------------------------------------------------------------------
/test/unit/regServices.spec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Simulate 3rd party
3 | */
4 | define(['app', 'regServices', 'test/unit/factory/utestProvider' ], function (app, regServices, unitestFactory) {
5 | console.log("* Running regServices.spec.js");
6 | unitestFactory(regServices);
7 | });
8 |
--------------------------------------------------------------------------------
/dist/ngload.min.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"ngload.min.js","sources":["../src/ngload.js"],"names":["define","load","name","req","onload","angularAMD","value","processQueue"],"mappings":";;;;;;AAMAA,QACIC,KAAM,SAAUC,EAAMC,EAAKC,GACvB,YAEAD,IAAK,aAAcD,GAAO,SAAUG,EAAYC,GAE5CD,EAAWE,eACXH,EAAOE"}
--------------------------------------------------------------------------------
/test/unit/decoServices.spec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Test to ensure that services can be created using app.register method.
3 | */
4 | define(['app', 'decoServices', 'test/unit/factory/utestProvider' ], function (app, decoServices, unitestFactory) {
5 | console.log("* Running decoServices.spec.js");
6 | unitestFactory(decoServices);
7 | });
8 |
--------------------------------------------------------------------------------
/test/unit/lib/decoServices.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Simulate the creation of provider using app.register.
3 | * `app.register` is expected to be decommissioned in the future release.
4 | */
5 | define(['angularAMD', 'test/unit/factory/provider'], function(angularAMD, providerFactory) {
6 | var app = angularAMD.getCachedProvider("__orig_app");
7 | return providerFactory(app.register, "Deco");
8 | });
9 |
--------------------------------------------------------------------------------
/www/js/scripts/controller/map_ctrl.js:
--------------------------------------------------------------------------------
1 | define(['app', 'service/mapServices', 'directive/navMenu'], function (app) {
2 | app.controller('MapController', function ($scope, MapService) {
3 | $scope.title = "Where is Colosseo?";
4 | $scope.latitude = 41.8902;
5 | $scope.longitude = 12.4923;
6 |
7 | // Set the location to be Colosseum
8 | MapService.initialize($scope, "map-canvas");
9 | })
10 | });
11 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angularAMD",
3 | "version": "0.2.1",
4 | "dependencies": {
5 | "angular": "^1.3.0",
6 | "requirejs": "~2.1.9"
7 | },
8 | "devDependencies": {
9 | "angular-route": "^1.3.0",
10 | "angular-animate": "^1.3.0",
11 | "angular-mocks": "^1.3.0",
12 | "angular-ui-bootstrap-bower": "~0.6.0",
13 | "requirejs-plugins": "~1.0.2",
14 | "google-code-prettify": "~1.0.1"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/test/unit/lib/component.js:
--------------------------------------------------------------------------------
1 | define(['app', 'angularAMD'], function (app, angularAMD) {
2 | var comp_name = "mainComponent";
3 |
4 | // console.log('component called');
5 |
6 | app.component(comp_name, {
7 | bindings: {
8 | compBind: '@'
9 | },
10 | controller: function() {
11 | this.title = 'Component Title';
12 | },
13 | template: '
{{ $ctrl.title }} {{ $ctrl.compBind }} '
14 | });
15 |
16 | return this;
17 | });
18 |
--------------------------------------------------------------------------------
/www/js/scripts/controller/modules_ctrl.js:
--------------------------------------------------------------------------------
1 | define(['app', 'ngload!service/dataServices', 'directive/write', 'directive/navMenu'], function (app) {
2 | app.controller('ModulesController', function ($scope, $log, DeferredObject, DeferredString, $rootScope) {
3 | DeferredObject.get("This is defered response", 2000).then(function (result) {
4 | $scope.obj_response = result;
5 | });
6 | $scope.str_response = DeferredString.get("Show case ngWrite with promise", 1000);
7 | })
8 | });
9 |
--------------------------------------------------------------------------------
/dist/ngload.js:
--------------------------------------------------------------------------------
1 | /*!
2 | angularAMD v0.2.1
3 | (c) 2013-2014 Marcos Lin https://github.com/marcoslin/
4 | License: MIT
5 | */
6 | define({
7 | load: function (name, req, onload) {
8 | 'use strict';
9 | //console.log("ngamd loaded: ", req.toUrl(name));
10 | req(['angularAMD', name], function (angularAMD, value) {
11 | //console.log("Processing queues.");
12 | angularAMD.processQueue();
13 | onload(value);
14 | });
15 | }
16 | });
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/ngload.js:
--------------------------------------------------------------------------------
1 | /*
2 | angularAMD v<%= cvars.proj_version %>
3 | (c) 2013-2014 Marcos Lin https://github.com/marcoslin/
4 | License: MIT
5 | */
6 |
7 | define({
8 | load: function (name, req, onload) {
9 | 'use strict';
10 | //console.log("ngamd loaded: ", req.toUrl(name));
11 | req(['angularAMD', name], function (angularAMD, value) {
12 | //console.log("Processing queues.");
13 | angularAMD.processQueue();
14 | onload(value);
15 | });
16 | }
17 | });
18 |
19 |
20 |
--------------------------------------------------------------------------------
/www/js/scripts/controller/home_ctrl.js:
--------------------------------------------------------------------------------
1 | define(['app', 'directive/navMenu','prettify'], function (app) {
2 | app.controller('HomeController', function ($scope, $window) {
3 | $scope.title = "angularAMD";
4 | $scope.openGitHubPage = function () {
5 | //console.log("trackEvent: ViewGitHub");
6 | $window._gaq.push(['_trackEvent', 'angularAMD', 'ViewGitHub', 'Clicked on View on GitHub button']);
7 | $window.open("https://github.com/marcoslin/angularAMD", "_blank");
8 | };
9 | });
10 | });
11 |
--------------------------------------------------------------------------------
/www/js/scripts/controller/pictures_ctrl.js:
--------------------------------------------------------------------------------
1 | define(['app', 'service/picturesService', 'ngload!ui-bootstrap', 'directive/navMenu'], function (app) {
2 |
3 | return ['$scope', 'Pictures', function ($scope, Pictures) {
4 | $scope.slideChangeInterval = 4000;
5 |
6 | $scope.$watch('cityModel', function (newValue) {
7 | if (newValue) {
8 | Pictures.query(newValue).then(function (result) {
9 | $scope.rows = result;
10 | });
11 | }
12 | });
13 |
14 | }];
15 |
16 | });
17 |
--------------------------------------------------------------------------------
/test/unit/lib/regController.js:
--------------------------------------------------------------------------------
1 | /*jslint nomen: true */
2 | /*globals define, angular */
3 |
4 | define(['app','regServices'], function (app, utestResult) {
5 | 'use strict';
6 | var ctrl_name = "RegController";
7 |
8 | app.controller(ctrl_name, ['$scope', utestResult.UtestFactory, utestResult.UtestService, function ($scope, UtestFactory, UtestService) {
9 | $scope.ctrl_name = ctrl_name;
10 | $scope.utest_factory = UtestFactory;
11 | $scope.utest_service = UtestService;
12 | }]);
13 |
14 | return {
15 | "ctrl_name": ctrl_name,
16 | "result": utestResult
17 | };
18 | });
19 |
--------------------------------------------------------------------------------
/test/unit/lib/app_no_ngload.js:
--------------------------------------------------------------------------------
1 | /*jslint browser: true, devel: true, node: true, vars: true, nomen: true */
2 | /*globals define, angular */
3 |
4 | define(["angularAMD"], function (angularAMD) {
5 | 'use strict';
6 | /**
7 | * BOOTSTRAP ANGULAR
8 | * Replicating what would normally take place in app.js
9 | */
10 | var app_name = "unitest-no-ngload",
11 | app = angular.module(app_name, []);
12 |
13 | // Add property for unit test
14 | app.__appname = app_name;
15 |
16 | var elem = document.createElement('div');
17 | angularAMD.bootstrap(app, false, elem);
18 | return app;
19 | });
20 |
--------------------------------------------------------------------------------
/src/jshintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "nonew": true,
3 | "plusplus": true,
4 | "curly": true,
5 | "noarg": true,
6 | "trailing": true,
7 | "forin": true,
8 | "noempty": true,
9 | "eqeqeq": true,
10 | "undef": true,
11 | "bitwise": true,
12 | "browser": true,
13 | "node": true,
14 | "globals": {
15 | /* AngularJS */
16 | "angular": false,
17 | /* RequireJS */
18 | "define": false,
19 | "require": false,
20 | /* Jasmine */
21 | "describe" : false,
22 | "it" : false,
23 | "before" : false,
24 | "beforeEach" : false,
25 | "after" : false,
26 | "afterEach" : false,
27 | "expect" : false
28 | }
29 | }
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "globals": {
3 | /* Jasmine */
4 | "describe" : false,
5 | "it" : false,
6 | "before" : false,
7 | "beforeEach" : false,
8 | "after" : false,
9 | "afterEach" : false,
10 | /* RequireJS */
11 | "require" : false,
12 | "define" : false,
13 | /* AngularJS */
14 | "angular" : false
15 | },
16 | "bitwise" : true,
17 | "curly" : true,
18 | "eqeqeq" : true,
19 | "immed" : true,
20 | "latedef" : true,
21 | "newcap" : false,
22 | "noarg" : true,
23 | "quotmark" : "single",
24 | "undef" : true,
25 | "unused" : true,
26 | "strict" : true,
27 | "browser" : true
28 | }
29 |
--------------------------------------------------------------------------------
/test/unit/lib/controller.js:
--------------------------------------------------------------------------------
1 | define(['app', 'angularAMD', 'ngload!services'], function (app, angularAMD) {
2 | var ctrl_name = "MainController",
3 | inject = angularAMD.inject,
4 | utestResult;
5 |
6 | inject(function (UtestServiceResult) {
7 | utestResult = UtestServiceResult;
8 | });
9 |
10 | app.controller(ctrl_name, ["$scope", utestResult.UtestFactory, utestResult.UtestService, utestResult.UtestSubModule, function ($scope, UtestFactory, UtestService, UtestSubModule) {
11 | $scope.ctrl_name = ctrl_name;
12 | $scope.utest_factory = UtestFactory;
13 | $scope.utest_service = UtestService;
14 | $scope.utest_sub_module = UtestSubModule;
15 | }]);
16 |
17 | return {
18 | "ctrl_name": ctrl_name,
19 | "result": utestResult
20 | };
21 | });
22 |
--------------------------------------------------------------------------------
/test/conf/protractor.e2e.js:
--------------------------------------------------------------------------------
1 | // An example configuration file.
2 | exports.config = {
3 | // Remove definition for `seleniumAddress` so that selenium is launched by protractor.
4 | // seleniumAddress: 'http://localhost:4444/wd/hub',
5 |
6 | //Capabilities to be passed to the webdriver instance.
7 | capabilities: {
8 | 'browserName': 'phantomjs',
9 | 'phantomjs.binary.path': './node_modules/karma-phantomjs-launcher/node_modules/phantomjs/bin/phantomjs'
10 | },
11 |
12 | //baseUrl: 'http://localhost:8444',
13 |
14 | // Spec patterns are relative to the current working directly when
15 | // protractor is called.
16 | specs: ['../e2e/*.spec.js'],
17 |
18 | // Options to be passed to Jasmine-node.
19 | jasmineNodeOpts: {
20 | showColors: true,
21 | defaultTimeoutInterval: 30000
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/www/js/scripts/directive/templates/navMenu.html:
--------------------------------------------------------------------------------
1 | angularAMD
2 |
22 |
--------------------------------------------------------------------------------
/test/unit/lib/main.no_ngload.js:
--------------------------------------------------------------------------------
1 | /*jslint browser: true, node: true, nomen: true */
2 |
3 | require.config({
4 | // The baseUrl depends on what is defined in karma.unit.js:basePath
5 | baseUrl: "/base",
6 |
7 | // alias libraries paths
8 | paths: {
9 | 'angular': 'bower_components/angular/angular',
10 | 'angular-mocks': 'bower_components/angular-mocks/angular-mocks',
11 | 'angularAMD': 'src/angularAMD',
12 | 'ngload': 'src/ngload',
13 | 'app_no_ngload': 'test/unit/lib/app_no_ngload'
14 | },
15 |
16 | shim: {
17 | 'angularAMD': ['angular']
18 | },
19 |
20 | // controllerSpec is at the end of dependency tree so kicking it off will start entire test
21 | deps: ['test/unit/app_no_ngload.spec'],
22 |
23 | // start test run, once Require.js is done
24 | callback: window.__karma__.start
25 | });
26 |
--------------------------------------------------------------------------------
/www/js/scripts/directive/navMenu.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 | /*global define */
3 | define(['app'], function (app) {
4 | app.controller("navMenuController", function ($scope, $route, SiteName, $window, $location) {
5 | var tab_name = $route.current.navTab,
6 | ga_path = SiteName + $location.path();
7 |
8 | $scope.isTabActive = function (tabName) {
9 | if (tabName === tab_name) {
10 | return "active";
11 | }
12 | };
13 |
14 | //console.log("Sending to GA: " + ga_path);
15 | $window._gaq.push(['_trackPageview', ga_path]);
16 |
17 | });
18 |
19 | app.directive('navMenu', function () {
20 | return {
21 | restrict: 'A',
22 | controller: 'navMenuController',
23 | templateUrl: 'js/scripts/directive/templates/navMenu.html'
24 | };
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/www/js/main.js:
--------------------------------------------------------------------------------
1 | require.config({
2 |
3 | baseUrl: "js/scripts",
4 |
5 | // alias libraries paths
6 | paths: {
7 | 'angular': '../lib/angular/angular',
8 | 'angular-route': '../lib/angular/angular-route',
9 | 'async': '../lib/requirejs/async',
10 | 'angularAMD': '../lib/requirejs/angularAMD',
11 | 'ngload': '../lib/requirejs/ngload',
12 | 'ui-bootstrap': '../lib/angular-ui-bootstrap/ui-bootstrap-tpls',
13 | 'prettify': '../lib/google-code-prettify/prettify',
14 |
15 | 'HomeController': 'controller/home_ctrl',
16 | 'MapController': 'controller/map_ctrl',
17 | 'ModulesController': 'controller/modules_ctrl'
18 | },
19 |
20 | // Add angular modules that does not support AMD out of the box, put it in a shim
21 | shim: {
22 | 'angularAMD': ['angular'],
23 | 'angular-route': ['angular']
24 | },
25 |
26 | // kick start application
27 | deps: ['app']
28 | });
29 |
--------------------------------------------------------------------------------
/www/js/scripts/directive/write.js:
--------------------------------------------------------------------------------
1 | // customDirectives
2 | define(['app'], function (app) {
3 | app.directive('ngWrite', function ($timeout, $log) {
4 | return {
5 | restrict: 'A',
6 | //require: "^ngController",
7 | link: function (scope, elm, attr) {
8 | // Attempt to read the attribe from scope. If not found, return what's pass to directive
9 | if (scope[attr.ngWrite]) {
10 | // ngWrite is found in scope. Check if promised has been returned
11 | var inval = scope[attr.ngWrite];
12 | if ('then' in inval) {
13 | inval.then(function (data) {
14 | elm.text(data);
15 | });
16 | } else {
17 | elm.text(inval);
18 | }
19 | } else {
20 | elm.text(attr.ngWrite);
21 | }
22 | }
23 | };
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/test/unit/factory/utestModule.js:
--------------------------------------------------------------------------------
1 | define(['angularAMD', 'test/unit/factory/utestProvider'], function (angularAMD, utestProvider) {
2 |
3 | return function (result) {
4 | var inject = angularAMD.inject;
5 |
6 | utestProvider(result);
7 |
8 | /*
9 | There is a problem with having a describe outside of utestProvider
10 | If there is an error, it will always use the title of the last
11 | test in the `utestProvider`
12 | */
13 | describe("Utest " + result.suffix + " Modules", function () {
14 | it(".config check.", inject([result.UtestStoreResult, function (UtestStoreResult) {
15 | if (UtestStoreResult === "undefined") {
16 | console.log("### ERROR on " + result.suffix + ": ", result.config_name);
17 | }
18 | expect(UtestStoreResult).toBe(result.config_name);
19 | }]));
20 |
21 | it(".run check.", inject(function ($rootScope) {
22 | expect($rootScope.run_name).toBe(result.run_name);
23 | }));
24 | });
25 |
26 |
27 |
28 | };
29 |
30 | });
--------------------------------------------------------------------------------
/www/views/map.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Third party Javascript API such as
5 | Google Maps API can be setup for on-demand loading using
6 | async.js
7 | RequireJS plugin as demonstrated in wrapper.
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{title}}
15 | Move the marker to update latitude and logitude.
16 |
17 |
18 |
19 |
20 |
21 |
22 | latitude: {{latitude}}
23 |
24 |
25 |
26 | longitude: {{longitude}}
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/test/unit/lib/app.js:
--------------------------------------------------------------------------------
1 | /*jslint browser: true, devel: true, node: true, vars: true, nomen: true */
2 | /*globals define, angular */
3 |
4 | define(['angularAMD', 'test/unit/lib/preService', 'angular-route', 'angular-animate'], function (angularAMD, preService) {
5 | 'use strict';
6 |
7 | /**
8 | * BOOTSTRAP ANGULAR
9 | * Replicating what would normally take place in app.js
10 | */
11 | var app_name = "unitest-app",
12 | app = angular.module(app_name, ['ngRoute','ngAnimate']);
13 |
14 | // Add property for unit test
15 | app.__appname = app_name;
16 | app.__origAngular = window.angular;
17 | app.__preServiceResult = preService;
18 |
19 | // Define route for unit test
20 | app.config(function ($routeProvider) {
21 | $routeProvider.when("/controllerFn", angularAMD.route({
22 | utestParam: "controllerFn",
23 | template: "{{message}}
",
24 | controllerUrl: "test/unit/lib/controllerFn"
25 | }));
26 | });
27 |
28 | /*
29 | var elem = document.body;
30 | angularAMD.bootstrap(app, elem);
31 | */
32 | return angularAMD.bootstrap(app);
33 | });
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2013-2014 Marcos Lin https://github.com/marcoslin/
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
13 | all 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
21 | THE SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/test/unit/factory/module.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A standard set of code used to simulate creation of independent modules, leveraging `provider` factory.
3 | * Basically, it will do everything `provider` factory do and setup .run and .config blocks.
4 | */
5 | define(["test/unit/factory/provider"], function (providerFactory) {
6 | /**
7 | * A function that will create different AngularJS provider for the given module.
8 | * All module name created will has a suffix
9 | */
10 | return function (module, suffix) {
11 | var result = providerFactory(module, suffix);
12 |
13 | /*
14 | Use the .config block to set the test provider's value
15 | Use the .run block to set value for $rootScope.run_name
16 | */
17 | result.config_name = "module.config YzmACpEVW9" + suffix;
18 | result.run_name = "module.run YzmACpEVW9" + suffix;
19 | module
20 | .config([result.UtestStoreProvider, function (UtestStoreProvider) {
21 | UtestStoreProvider.configureValue(result.config_name);
22 | }])
23 | .run(function ($rootScope) {
24 | $rootScope.run_name = result.run_name;
25 | });
26 |
27 | /*
28 | Return result
29 | */
30 | return result;
31 | };
32 |
33 | });
34 |
35 |
--------------------------------------------------------------------------------
/test/unit/lib/services.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Simulate a 3rd party service. This package loads the 'test/unit/factory/module' using requirejs' sync
3 | * call so it must be pre-loaded by caller first.
4 | */
5 |
6 | !function () {
7 | // Services coded using regular angular approach
8 | var sub_module = angular.module("subModuleServices", []),
9 | services = angular.module("utestServices", ['subModuleServices']),
10 | moduleFactory = require("test/unit/factory/module");
11 |
12 | // Define a simple subModule
13 | angular.module("subModuleServices").factory("SubConfigValue", function () {
14 | return "JwU9YSJMJS-HhRz4nhBuY";
15 | });
16 |
17 |
18 | // Load module factory
19 | var result = moduleFactory(services, "Ng");
20 |
21 | // Add sub-module test
22 | result.UtestSubModule = "UtestSubModule" + result.suffix;
23 | result.sub_module = "utestServices.sub_config_value JwU9YSJMJS-HhRz4nhBuY";
24 | services.factory(result.UtestSubModule, function (SubConfigValue) {
25 | return {
26 | get: function () {
27 | return "utestServices.sub_config_value " + SubConfigValue;
28 | }
29 | };
30 | });
31 |
32 | services.factory('UtestServiceResult', function () {
33 | return result;
34 | });
35 |
36 | }();
37 |
38 |
--------------------------------------------------------------------------------
/test/unit/app_no_ngload.spec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Test focusing on making sure that window.angular has not been modified and
3 | * that .processQueue raises error when enable_ngload is set to false in
4 | * .bootstrap
5 | */
6 | define(['app_no_ngload','angularAMD'], function (app, angularAMD) {
7 | console.log("* Running app_no_ngload.spec.js");
8 | describe('angularAMD_no_ngload', function () {
9 | //console.log("Running app_no_ngload.spec.js");
10 |
11 | it('is created.', function () {
12 | expect(angularAMD).toBeDefined();
13 | });
14 | it('app is defined.', function () {
15 | expect(app.name).toBe(angularAMD.appname());
16 | });
17 | it('original angular should defined.', function () {
18 | var orig_angular = angularAMD.getCachedProvider('__orig_angular');
19 | expect(orig_angular).toBeDefined();
20 | expect(window.angular).toBe(orig_angular);
21 | });
22 | it('alternate angular should not be set.', function () {
23 | expect(angularAMD.getCachedProvider('__alt_angular')).toBeUndefined();
24 | });
25 |
26 | it('.processQueue should throw an error.', function () {
27 | expect(angularAMD.processQueue).toThrow();
28 | });
29 |
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angularAMD",
3 | "version": "0.1.0",
4 | "description": "RequireJS plugin for AngularJS",
5 | "repository": {
6 | "type": "git",
7 | "url": "git://github.com/marcoslin/angularAMD.git"
8 | },
9 | "keywords": [
10 | "angularjs",
11 | "requirejs"
12 | ],
13 | "author": "Marcos Lin",
14 | "license": "MIT",
15 | "bugs": {
16 | "url": "https://github.com/marcoslin/angularAMD/issues"
17 | },
18 | "dependencies": {},
19 | "devDependencies": {
20 | "grunt": "~0.4.1",
21 | "grunt-bower-task": "~0.4.0",
22 | "grunt-contrib-concat": "~0.3.0",
23 | "grunt-contrib-connect": "~0.3.0",
24 | "grunt-contrib-copy": "~0.4.1",
25 | "grunt-contrib-cssmin": "~0.6.0",
26 | "grunt-contrib-htmlmin": "~0.1.3",
27 | "grunt-contrib-requirejs": "~0.4.0",
28 | "grunt-contrib-uglify": "~0.4.0",
29 | "grunt-karma": "~0.6.2",
30 | "grunt-ng-annotate": "~0.2.2",
31 | "grunt-open": "~0.2.2",
32 | "grunt-protractor-runner": "~0.2.4",
33 | "grunt-shell-spawn": "~0.3.0",
34 | "grunt-templater": "0.0.6",
35 | "grunt-usemin": "~0.1.11",
36 | "karma": "~0.10.2",
37 | "load-grunt-tasks": "~0.1.0",
38 | "mustache": "~0.7.2",
39 | "phantomjs-polyfill": "0.0.2",
40 | "protractor": "~0.21.0"
41 | },
42 | "scripts": {
43 | "test": "grunt build-travis"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/www/views/pictures.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Show case on-demand loading of UI Bootstrap
5 | using RequireJS plugin.
6 |
7 |
8 |
9 |
Show pictures from:
10 |
11 | London
12 | Paris
13 | Rome
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
Slide {{$index+1}}: {{row.title}}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/test/unit/controllerFn.spec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Testing declaration of controller following require.js spec and make sure
3 | * it's dependecies are loaded.
4 | */
5 | define(['angularAMD'], function (angularAMD) {
6 | console.log("* Running controllerFn.spec.js");
7 | describe('Utest Controller', function () {
8 | //console.log("Running controllerSpec.js");
9 | var route, location, rootScope;
10 |
11 | angularAMD.inject(function ($route, $location, $rootScope) {
12 | route = $route;
13 | location = $location;
14 | rootScope = $rootScope;
15 | });
16 |
17 | it("route should be undefined.", function () {
18 | expect(route.current).toBeUndefined();
19 | });
20 |
21 | it("controller should load for /controllerFn route.", function () {
22 | location.path('/controllerFn');
23 | rootScope.$digest();
24 |
25 | // Make sure that route has changed
26 | expect(route.current.utestParam).toBe('controllerFn');
27 |
28 | // Controller should be defined
29 | expect(route.current.controller).toBeDefined();
30 |
31 | // Make sure that controller has been set to custom function
32 | expect(route.current.controller.toString()).toMatch(/^\$scope,__AAMDCtrl,\$injector,function/);
33 | });
34 |
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/test/unit/regController.spec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Testing declaration of controller following require.js spec and make sure
3 | * it's dependecies are loaded.
4 | */
5 | define(['app', 'angularAMD', 'regController'], function (app, angularAMD, regController) {
6 | console.log("* Running regController.spec.js");
7 | describe('Utest RegController', function () {
8 | //console.log("Running controllerSpec.js");
9 | var ctrl_name = regController.ctrl_name,
10 | result = regController.result,
11 | scope, ctrl;
12 |
13 | angularAMD.inject(function ($rootScope, $controller) {
14 | scope = $rootScope.$new();
15 | ctrl = $controller(ctrl_name, { $scope: scope });
16 | });
17 |
18 | it("utestResult should exists.", function () {
19 | expect(result).toBeDefined();
20 | });
21 |
22 | it("scope.ctrl_name check", function () {
23 | expect(scope.ctrl_name).toBe(ctrl_name);
24 | });
25 |
26 | it("scope.utest_factory check", function () {
27 | var f = scope.utest_factory;
28 | expect(f.name).toBe(result.factory_name);
29 | expect(f.const_name).toBe(result.constant_name);
30 | });
31 |
32 | it("scope.utest_service check", function () {
33 | var s = scope.utest_service;
34 | expect(s.name).toBe(result.service_name);
35 | expect(s.val_name).toBe(result.value_name);
36 | });
37 |
38 | });
39 | });
40 |
--------------------------------------------------------------------------------
/www/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | angularAMD: The Simple Way to Integrate AngularJS and RequireJS
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/www/js/scripts/service/dataServices.js:
--------------------------------------------------------------------------------
1 | // Services coded using regular angular approach
2 | angular.module("dataServices", [])
3 | .factory("DeferredObject", function ($timeout, $q, ServiceName) {
4 | return {
5 | get: function (message, delay_in_ms) {
6 | //console.log("DeferredObject.get ServiceName: ", ServiceName);
7 | var d = $q.defer();
8 | $timeout(function () {
9 | d.resolve({label: ServiceName, message: message});
10 | }, delay_in_ms);
11 | return d.promise;
12 | }
13 | }
14 | })
15 | .provider("configValue", function () {
16 | var config_value;
17 |
18 | this.set = function(value) {
19 | config_value = value;
20 | };
21 |
22 | this.$get = function () {
23 | return {
24 | get: function () {
25 | return config_value;
26 | }
27 | }
28 | };
29 | })
30 | .constant("ServiceName", "dataServices")
31 | .service("DeferredString", function ($timeout, $q) {
32 | this.get = function (message, delay_in_ms) {
33 | var d = $q.defer();
34 | $timeout(function () {
35 | d.resolve(message);
36 | }, delay_in_ms);
37 | return d.promise;
38 | }
39 | })
40 | .config(function (configValueProvider) {
41 | configValueProvider.set("And config works");
42 | })
43 | .run(function (configValue, $rootScope, $timeout) {
44 | $timeout(function () {
45 | $rootScope.run_block_message = "Greetings from .run";
46 | }, 3000);
47 | $timeout(function () {
48 | $rootScope.config_block_message = configValue.get();
49 | }, 4000);
50 | })
51 | ;
--------------------------------------------------------------------------------
/test/unit/services.spec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Test with 2 main objectives:
3 | * 1. Make sure that ngAMD's cache provider works
4 | * 2. Make sure that independent angular.modules can be incorporated in the project
5 | * by using the ngAMD.processQueue() method to load these modules.
6 | */
7 | define(['app', 'angularAMD', 'test/unit/factory/utestModule', 'ngload!services'], function (app, angularAMD, utestModule) {
8 | console.log("* Running services.spec.js");
9 | var results,
10 | inject = angularAMD.inject;
11 |
12 | inject(function (UtestServiceResult) {
13 | results = UtestServiceResult;
14 | });
15 |
16 | utestModule(results);
17 |
18 | describe('Utest Services', function () {
19 | it("sub module check.", inject([results.UtestSubModule, function (UtestSubModule) {
20 | expect(UtestSubModule.get()).toBe(results.sub_module);
21 | }]));
22 |
23 | it("sub module check module.", function () {
24 | expect(angular.module("subModuleServices")).toBeUndefined();
25 | });
26 |
27 | it("angularAMD.config check.", function () {
28 | var configVal = "B9NmTuDAeU-JO0S1yjKXc";
29 | inject([results.UtestStore, function (UtestStore) {
30 | expect(UtestStore.getValue()).not.toBe(configVal);
31 | }]);
32 | angularAMD.config([results.UtestStoreProvider, function (UtestStoreProvider) {
33 | UtestStoreProvider.configureValue(configVal);
34 | }]);
35 | inject([results.UtestStore, function (UtestStore) {
36 | expect(UtestStore.getValue()).toBe(configVal);
37 | }]);
38 |
39 | });
40 |
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/test/unit/controller.spec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Testing declaration of controller following require.js spec and make sure
3 | * it's dependecies are loaded.
4 | */
5 | define(['app', 'controller', 'angularAMD'], function (app, controller, angularAMD) {
6 | console.log("* Running controller.spec.js");
7 | describe('Utest Controller', function () {
8 | //console.log("Running controllerSpec.js");
9 | var ctrl_name = controller.ctrl_name,
10 | service_results = controller.result,
11 | scope, ctrl;
12 |
13 | angularAMD.inject(function ($rootScope, $controller) {
14 | scope = $rootScope.$new();
15 | ctrl = $controller(ctrl_name, { $scope: scope });
16 | });
17 |
18 | it("service_results should exists.", function () {
19 | expect(service_results).toBeDefined();
20 | });
21 |
22 | it("scope.ctrl_name check", function () {
23 | expect(scope.ctrl_name).toBe(ctrl_name);
24 | });
25 |
26 | it("scope.utest_factory check", function () {
27 | var f = scope.utest_factory;
28 | expect(f.name).toBe(service_results.factory_name);
29 | expect(f.const_name).toBe(service_results.constant_name);
30 | });
31 |
32 | it("scope.utest_service check", function () {
33 | var s = scope.utest_service;
34 | expect(s.name).toBe(service_results.service_name);
35 | expect(s.val_name).toBe(service_results.value_name);
36 | });
37 |
38 | it("scope.subModule check", function () {
39 | // console.log("scope.subModule check", service_results.sub_module);
40 | expect(scope.utest_sub_module.get()).toBe(service_results.sub_module);
41 | });
42 |
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/www/views/modules.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Demonstrate how to create on-demand loaded components such as
5 | and .
6 | Standard AngularJS module is supported
7 | via RequireJS plugin as used in
8 | . Notice that angularAMD
9 | is able to handle out of sequence calls of .factory and .constant in
10 | .
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | .ng-write directive:
19 | ngWrite FAILED!!!
20 |
21 |
22 |
23 | Value set in .config:
24 | {{config_block_message}}
25 |
26 |
27 |
28 | Value set in .run:
29 | {{run_block_message}}
30 |
31 |
32 |
33 | DeferredObject:
34 | {{obj_response.message}}
35 | .label:
36 | {{obj_response.label}}
37 |
38 |
39 |
40 | DeferredString:
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/www/css/sons-of-obsidian.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Derived from einaros's Sons of Obsidian theme at
3 | * http://studiostyl.es/schemes/son-of-obsidian by
4 | * Alex Ford of CodeTunnel:
5 | * http://CodeTunnel.com/blog/post/71/google-code-prettify-obsidian-theme
6 | */
7 |
8 | .str
9 | {
10 | color: #EC7600;
11 | }
12 | .kwd
13 | {
14 | color: #93C763;
15 | }
16 | .com
17 | {
18 | color: #66747B;
19 | }
20 | .typ
21 | {
22 | color: #678CB1;
23 | }
24 | .lit
25 | {
26 | color: #FACD22;
27 | }
28 | .pun
29 | {
30 | color: #F1F2F3;
31 | }
32 | .pln
33 | {
34 | color: #F1F2F3;
35 | }
36 | .tag
37 | {
38 | color: #8AC763;
39 | }
40 | .atn
41 | {
42 | color: #E0E2E4;
43 | }
44 | .atv
45 | {
46 | color: #EC7600;
47 | }
48 | .dec
49 | {
50 | color: purple;
51 | }
52 | pre.prettyprint
53 | {
54 | border: 0px solid #888;
55 | }
56 | ol.linenums
57 | {
58 | margin-top: 0;
59 | margin-bottom: 0;
60 | }
61 | .prettyprint {
62 | background: #000;
63 | }
64 | li.L0, li.L1, li.L2, li.L3, li.L4, li.L5, li.L6, li.L7, li.L8, li.L9
65 | {
66 | color: #555;
67 | list-style-type: decimal;
68 | }
69 | li.L1, li.L3, li.L5, li.L7, li.L9 {
70 | background: #111;
71 | }
72 | @media print
73 | {
74 | .str
75 | {
76 | color: #060;
77 | }
78 | .kwd
79 | {
80 | color: #006;
81 | font-weight: bold;
82 | }
83 | .com
84 | {
85 | color: #600;
86 | font-style: italic;
87 | }
88 | .typ
89 | {
90 | color: #404;
91 | font-weight: bold;
92 | }
93 | .lit
94 | {
95 | color: #044;
96 | }
97 | .pun
98 | {
99 | color: #440;
100 | }
101 | .pln
102 | {
103 | color: #000;
104 | }
105 | .tag
106 | {
107 | color: #006;
108 | font-weight: bold;
109 | }
110 | .atn
111 | {
112 | color: #404;
113 | }
114 | .atv
115 | {
116 | color: #060;
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/www/js/scripts/service/mapServices.js:
--------------------------------------------------------------------------------
1 | // convert Google Maps into an AMD module
2 | define(['app', 'async!//maps.google.com/maps/api/js?v=3&sensor=false'], function (app) {
3 | app.service('MapService', function () {
4 | var gmaps = window.google.maps,
5 | mapOptions = {
6 | zoom: 15,
7 | draggable: true,
8 | mapTypeId: gmaps.MapTypeId.ROADMAP,
9 | panControl: false,
10 | disableDoubleClickZoom: true,
11 | disableDefaultUI: true,
12 | zoomControl: false
13 | },
14 | latLng;
15 |
16 | /**
17 | * Create map with initial position given by scope.latitude and scope.longitude.
18 | * Default to LatLng of Colosseo in Rome
19 | */
20 | this.initialize = function (scope, elementName) {
21 | var lat = scope.latitude || 41.8902,
22 | lng = scope.longitude || 12.4923,
23 | map = new gmaps.Map(document.getElementById(elementName), mapOptions);
24 |
25 | // Set initial position
26 | if (!latLng) {
27 | latLng = new gmaps.LatLng(lat, lng);
28 | } else {
29 | scope.latitude = latLng.lat();
30 | scope.longitude = latLng.lng();
31 | }
32 | map.setCenter(latLng);
33 | var marker = new gmaps.Marker({position: latLng, draggable: true, map: map});
34 |
35 | // Keep track of position of marker
36 | gmaps.event.addListener(marker, 'dragend', function (movedMarker) {
37 | latLng = movedMarker.latLng;
38 | scope.latitude = latLng.lat();
39 | scope.longitude = latLng.lng();
40 | scope.$apply(function () {
41 | marker.setPosition(latLng);
42 | });
43 | });
44 | };
45 |
46 | });
47 | });
48 | // REF: http://blog.millermedeiros.com/requirejs-2-0-delayed-module-evaluation-and-google-maps/
--------------------------------------------------------------------------------
/test/conf/karma.unit.no_ngload.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // http://karma-runner.github.io/0.10/config/configuration-file.html
3 | /*jslint node: true */
4 |
5 | module.exports = function (config) {
6 | config.set({
7 | // base path, note that this is expected to be ran under build directory
8 | basePath: '../..',
9 |
10 | // testing framework to use (jasmine/mocha/qunit/...)
11 | frameworks: ['jasmine', 'requirejs'],
12 |
13 | // list of files / patterns to load in the browser
14 | files: [
15 | {pattern: 'bower_components/angular/*.js', watched: false, included: false},
16 | {pattern: 'src/*.js', watched: true, included: false},
17 | {pattern: 'test/unit/app_no_ngload.spec.js', watched: true, included: false},
18 | {pattern: 'test/unit/lib/app_no_ngload.js', watched: true, included: false},
19 | 'bower_components/requirejs/require.js',
20 | 'node_modules/phantomjs-polyfill/bind-polyfill.js',
21 | 'test/unit/lib/main.no_ngload.js'
22 | ],
23 |
24 | // files: ['test/conf/testSpec.js'],
25 |
26 | // list of files / patterns to exclude
27 | exclude: [],
28 |
29 | // web server port
30 | port: 9898,
31 |
32 | // level of logging
33 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
34 | logLevel: config.LOG_INFO,
35 |
36 |
37 | // enable / disable watching file and executing tests whenever any file changes
38 | autoWatch: true,
39 |
40 |
41 | // Start these browsers, currently available:
42 | // - Chrome
43 | // - ChromeCanary
44 | // - Firefox
45 | // - Opera
46 | // - Safari (only Mac)
47 | // - PhantomJS
48 | // - IE (only Windows)
49 | browsers: ['PhantomJS'],
50 |
51 |
52 | // Continuous Integration mode
53 | // if true, it capture browsers, run tests and exit
54 | singleRun: true
55 | });
56 | };
57 |
--------------------------------------------------------------------------------
/www/js/scripts/service/picturesService.js:
--------------------------------------------------------------------------------
1 | // dataServices
2 | define(['app'], function (app) {
3 | app.factory('Pictures', function ($http, $q, $log) {
4 | var feed_url = "http://ycpi.api.flickr.com/services/feeds/photos_public.gne?format=json&jsoncallback=JSON_CALLBACK&tags=";
5 | return {
6 | query: function (tag_name) {
7 | var d = $q.defer();
8 | if (typeof tag_name === "undefined" || tag_name === "") {
9 | $log.error("Pictures.query: missing tag_name.");
10 | d.reject("tag must be provided");
11 | } else {
12 | $http.jsonp(feed_url + tag_name).success(function (data) {
13 | d.resolve(data.items);
14 | }).error(function (data, status, headers, config) {
15 | $log.error("Error: ", headers);
16 | d.reject(data);
17 | });
18 | }
19 |
20 | return d.promise;
21 | }
22 | };
23 | });
24 |
25 | });
26 |
27 | /*
28 | Another way to code this:
29 | -------------------------
30 | // define(['app','angular-resource'], function (app) {
31 | angular.module("dataServices", ['ngResource'])
32 | .factory('Pictures', ['$http', '$q', '$log', '$resource', function ($http, $q, $log, $resource) {
33 | var feed_url = "http://ycpi.api.flickr.com/services/feeds/photos_public.gne?format=json&tags=London&jsoncallback=JSON_CALLBACK";
34 | return {
35 | query: function () {
36 | var d = $q.defer();
37 |
38 | $http.jsonp(feed_url).success(function (data) {
39 | d.resolve(data.items);
40 | }).error(function (data, status, headers, config) {
41 | $log.error("Error: ", headers);
42 | d.reject(data);
43 | });
44 |
45 | return d.promise;
46 | }
47 | };
48 | }]);
49 |
50 | Need to update require.config:
51 | ------------------------------
52 | shim : {
53 | 'dataServices' : {
54 | exports: "dataServices",
55 | deps: ['angular-resource']
56 | }
57 | }
58 |
59 | */
--------------------------------------------------------------------------------
/test/conf/karma.unit.mustache:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // http://karma-runner.github.io/0.10/config/configuration-file.html
3 | /*jslint node: true */
4 |
5 | module.exports = function (config) {
6 | config.set({
7 | // base path, note that this is expected to be ran under build directory
8 | basePath: '../../..',
9 |
10 | // testing framework to use (jasmine/mocha/qunit/...)
11 | frameworks: ['jasmine', 'requirejs'],
12 |
13 | // list of files / patterns to load in the browser
14 | files: [
15 | {pattern: 'bower_components/**/*.js', watched: false, included: false},
16 | {pattern: 'build/*.js', watched: true, included: false},
17 | {pattern: 'src/*.js', watched: true, included: false},
18 | {pattern: 'test/unit/*.spec.js', watched: true, included: false},
19 | {pattern: 'test/unit/factory/*.js', watched: true, included: false},
20 | {pattern: 'test/unit/lib/*.js', watched: true, included: false},
21 | 'bower_components/requirejs/require.js',
22 | 'node_modules/phantomjs-polyfill/bind-polyfill.js',
23 | '{{{main-js-file}}}'
24 | ],
25 |
26 | // files: ['test/conf/testSpec.js'],
27 |
28 | // list of files / patterns to exclude
29 | exclude: [],
30 |
31 | // web server port
32 | port: 9898,
33 |
34 | // level of logging
35 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
36 | logLevel: config.LOG_INFO,
37 |
38 |
39 | // enable / disable watching file and executing tests whenever any file changes
40 | autoWatch: true,
41 |
42 |
43 | // Start these browsers, currently available:
44 | // - Chrome
45 | // - ChromeCanary
46 | // - Firefox
47 | // - Opera
48 | // - Safari (only Mac)
49 | // - PhantomJS
50 | // - IE (only Windows)
51 | browsers: ['PhantomJS'],
52 |
53 |
54 | // Continuous Integration mode
55 | // if true, it capture browsers, run tests and exit
56 | singleRun: true
57 | });
58 | };
59 |
--------------------------------------------------------------------------------
/www/js/scripts/app.js:
--------------------------------------------------------------------------------
1 | define(['angularAMD', 'angular-route'], function (angularAMD) {
2 | var app = angular.module("ngreq-app", ['ngRoute']);
3 |
4 | /**
5 | * Configure Angular ngApp with route and cache the needed providers
6 | */
7 | app.config(function ($routeProvider) {
8 | $routeProvider
9 | .when("/home", angularAMD.route({
10 | templateUrl: 'views/home.html', controller: 'HomeController', navTab: "home"
11 | }))
12 | .when("/pictures", angularAMD.route({
13 | templateUrl: 'views/pictures.html', controllerUrl: 'controller/pictures_ctrl', navTab: "pictures"
14 | }))
15 | .when("/modules", angularAMD.route({
16 | templateUrl: 'views/modules.html', controller: 'ModulesController', navTab: "modules"
17 | }))
18 | .when("/map", angularAMD.route({
19 | templateUrl: 'views/map.html', controller: 'MapController', navTab: "map"
20 | }))
21 | .otherwise({redirectTo: '/home'})
22 | ;
23 | });
24 |
25 | // Define constant to be used by Google Analytics
26 | app.constant("SiteName", "/angularAMD");
27 |
28 |
29 | // Create function to link to GitHub
30 | app.directive('ghLink', function () {
31 | return {
32 | restrict: 'A',
33 | scope: true,
34 | template: '{{filename}} ',
35 | controller: function ($scope, $attrs) {
36 | var gh_root = "https://github.com/marcoslin/angularAMD/blob/master/www/",
37 | relfile = $attrs.ghLink,
38 | fullpath = gh_root + relfile;
39 | $scope.fullpath = fullpath;
40 | $scope.filename = relfile.replace(/^.*[\\\/]/, '');
41 | }
42 | };
43 | });
44 |
45 | // Add support for pretty print
46 | app.directive('prettyprint', function() {
47 | return {
48 | restrict: 'C',
49 | link: function postLink(scope, element, attrs) {
50 | element.html(prettyPrint(scope.dom));
51 | }
52 | };
53 | });
54 |
55 | // Bootstrap Angular when DOM is ready
56 | return angularAMD.bootstrap(app);
57 |
58 | });
59 |
--------------------------------------------------------------------------------
/www/css/style.css:
--------------------------------------------------------------------------------
1 | #map-canvas {
2 | height: 500px;
3 | }
4 |
5 | /* Google Map Fix: http://stackoverflow.com/questions/9141249/twitter-bootstrap-css-affecting-google-maps*/
6 | #map-canvas img {
7 | max-width: none;
8 | }
9 | #map-canvas label {
10 | width: auto; display:inline;
11 | }
12 |
13 | #slide-carousel {
14 | height: 250px;
15 | width: 400px;
16 | }
17 |
18 | #slide-image {
19 | height: 250px;
20 | width: 400px;
21 | }
22 |
23 | .main-content {
24 | padding: 0 10% 0 10%;
25 | }
26 |
27 | .main-content .break {
28 | margin: 25px 0;
29 | }
30 |
31 | .text-justify {
32 | text-align:justify;
33 | }
34 |
35 | .vam {
36 | vertical-align: middle;
37 | }
38 |
39 | /**
40 | * Bootstrap's "Justified nav" Theme
41 | * URL: http://getbootstrap.com/2.3.2/examples/justified-nav.html
42 | */
43 | body {
44 | padding-top: 20px;
45 | padding-bottom: 60px;
46 | }
47 |
48 | /* Custom container */
49 | .container {
50 | margin: 0 auto;
51 | max-width: 1000px;
52 | }
53 | .container > hr {
54 | margin: 30px 0;
55 | }
56 |
57 | /* Main marketing message and sign up button */
58 | .jumbotron {
59 | margin: 50px 0;
60 | text-align: center;
61 | }
62 | .jumbotron h1 {
63 | font-size: 100px;
64 | line-height: 1;
65 | }
66 | .jumbotron .lead {
67 | font-size: 24px;
68 | line-height: 1.25;
69 | }
70 | .jumbotron .btn {
71 | font-size: 21px;
72 | padding: 14px 24px;
73 | }
74 |
75 | /* Supporting marketing content */
76 | .marketing {
77 | margin: 60px 0;
78 | }
79 | .marketing p + h4 {
80 | margin-top: 28px;
81 | }
82 |
83 |
84 | /* Customize the navbar links to be fill the entire space of the .navbar */
85 | .navbar .navbar-inner {
86 | padding: 0;
87 | }
88 | .navbar .nav {
89 | margin: 0;
90 | display: table;
91 | width: 100%;
92 | }
93 | .navbar .nav li {
94 | display: table-cell;
95 | width: 1%;
96 | float: none;
97 | }
98 | .navbar .nav li a {
99 | font-weight: bold;
100 | text-align: center;
101 | border-left: 1px solid rgba(255,255,255,.75);
102 | border-right: 1px solid rgba(0,0,0,.1);
103 | }
104 | .navbar .nav li:first-child a {
105 | border-left: 0;
106 | border-radius: 3px 0 0 3px;
107 | }
108 | .navbar .nav li:last-child a {
109 | border-right: 0;
110 | border-radius: 0 3px 3px 0;
111 | }
112 |
113 |
--------------------------------------------------------------------------------
/www/views/home.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{title}}
5 |
6 | AngularJS + RequireJS: The Proper and Easier Way
7 |
8 |
9 |
10 |
11 |
12 | Integrating AngularJS and RequireJS shouldn't be complicated, and it isn't with angularAMD.
13 | To see it in action, checkout this website that show case key features. Make sure to
14 | load your favorite Developer Tools to see the on-demand loading of *.js files
15 | as you switch tabs.
16 |
17 |
18 |
19 |
20 |
A quick AngularJS + RequireJS how-to using angularAMD:
21 |
22 |
Step 1:
23 | Define components and dependencies in
main.js:
24 |
25 |
require.config({
26 | baseUrl: "js",
27 | paths: {
28 | 'angular': '.../angular.min',
29 | 'angular-route': '.../angular-route.min',
30 | 'angularAMD': '.../angularAMD.min'
31 | },
32 | shim: { 'angularAMD': ['angular'], 'angular-route': ['angular'] },
33 | deps: ['app']
34 | });
35 |
36 | and load RequireJS, and only RequireJS, in
index.html:
37 |
38 |
<head>
39 | <script data-main="js/main.js" src=".../require.js"></script>
40 | </head>
41 |
42 |
Step 2:
43 | Create
app.js using RequireJS's
define statement:
44 |
define(['angularAMD', 'angular-route'], function (angularAMD) {
45 | var app = angular.module("webapp", ['ngRoute']);
46 | app.config(function ($routeProvider) {
47 | $routeProvider.when("/home", angularAMD.route({
48 | templateUrl: 'views/home.html', controller: 'HomeCtrl',
49 | controllerUrl: 'ctrl/home'
50 | }))
51 | });
52 | return angularAMD.bootstrap(app);
53 | });
54 |
55 |
Step 3:
56 | Create controller using
app.register method:
57 |
define(['app'], function (app) {
58 | app.controller('HomeCtrl', function ($scope) {
59 | $scope.message = "Message from HomeCtrl";
60 | });
61 | });
62 |
63 |
64 | Check out this Gist
65 | for a simple implementation. Then, head over to github for detail documentation.
66 |
67 |
68 |
69 |
70 |
71 |
77 |
78 |
--------------------------------------------------------------------------------
/test/unit/lib/main.mustache:
--------------------------------------------------------------------------------
1 | /*jslint browser: true, node: true, nomen: true */
2 |
3 | !function () {
4 | // Create basic requirejs config
5 | var rconfig = {
6 | // The baseUrl depends on what is defined in karma.unit.js:basePath
7 | baseUrl: "/base",
8 |
9 | // alias libraries paths
10 | paths: {
11 | 'angular': 'bower_components/angular/angular',
12 | 'angular-route': 'bower_components/angular-route/angular-route',
13 | 'angular-animate': 'bower_components/angular-animate/angular-animate',
14 | 'angular-mocks': 'bower_components/angular-mocks/angular-mocks',
15 | 'angularAMD': '{{{angularAMD-js-file}}}',
16 | 'ngload': '{{{ngload-js-file}}}',
17 | 'app': 'test/unit/lib/app',
18 | 'app_no_ngload': 'test/unit/lib/app_no_ngload',
19 | 'services': 'test/unit/lib/services',
20 | 'regServices': 'test/unit/lib/regServices',
21 | 'controller': 'test/unit/lib/controller',
22 | 'component' : 'test/unit/lib/component',
23 | 'regController': 'test/unit/lib/regController',
24 | 'decoServices': 'test/unit/lib/decoServices'
25 | },
26 |
27 | shim: {
28 | 'app': ['angular'],
29 | 'angularAMD': ['angular'],
30 | 'angular-route': ['angular'],
31 | 'angular-animate': ['angular'],
32 | 'angular-mocks': ['angular'],
33 |
34 | /*
35 | 'services' in this case is a regular angular.js module which calls moduleFactory using
36 | requirejs' sync method. As result, test/unit/factory/module must be called first.
37 | */
38 | 'services': ['test/unit/factory/module']
39 | },
40 |
41 | // start test run, once Require.js is done
42 | callback: window.__karma__.start
43 | };
44 |
45 |
46 | // Look for .spec.js files and created linked dependencies starting with app.spec to one spec at a time
47 | var prevSpec = "test/unit/app.spec",
48 | reSkip = new RegExp("app\\.spec\\.js|app_no_ngload\\.spec\\.js"),
49 | reSpec = new RegExp("^\\/base\\/(\\S+\\.spec)\\.js$");
50 |
51 | console.log("* Setting unit test sequence:");
52 | for (var file in window.__karma__.files) {
53 | // Ignore the app and app_no_ngload files
54 | if (reSkip.test(file)) {
55 | continue;
56 | }
57 |
58 | // Find the *.spec.js files and extract just the name without initial "/base/" and ending ".js"
59 | if (window.__karma__.files.hasOwnProperty(file)) {
60 | var matches = reSpec.exec(file);
61 | if(matches && matches.length > 1) {
62 | var curSpec = matches[1];
63 | rconfig.shim[curSpec] = [prevSpec];
64 | console.log(" - " + curSpec + ": " + prevSpec);
65 | prevSpec = curSpec;
66 | }
67 | }
68 | }
69 |
70 | // Kick off the test from the last spec.js file
71 | rconfig.deps = [prevSpec];
72 | console.log(" - " + prevSpec + " [KICK-OFF]");
73 |
74 | // Update requirejs config
75 | require.config(rconfig);
76 | }();
77 |
78 |
79 |
--------------------------------------------------------------------------------
/dist/angularAMD.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | angularAMD v0.2.1
3 | (c) 2013-2014 Marcos Lin https://github.com/marcoslin/
4 | License: MIT
5 | */
6 |
7 | define(function(){"use strict";function a(){if(!l)throw new Error("angularAMD not initialized. Need to call angularAMD.bootstrap(app) first.")}function b(){if(k)throw new Error("setAlternateAngular can only be called once.");k={},a(),j.extend(k,j),k.module=function(a,b){if("undefined"==typeof b)return q.hasOwnProperty(a)?p[a]:j.module(a);var c=j.module.apply(null,arguments),d={name:a,module:c};return r.push(d),j.extend(c,n),q[a]=!0,p[a]=c,c},window.angular=k}function c(){}function d(a){return function(b,c){return l?n[a](b,c):o.push({recipe:a,name:b,constructor:c}),this}}var e,f,g,h,i,j,k,l=!1,m={},n={},o=[],p={},q={},r=[];return c.prototype.route=function(a){var b;if(a.hasOwnProperty("controllerUrl")?(b=a.controllerUrl,delete a.controllerUrl,"undefined"==typeof a.controller&&(a.controller=["$scope","__AAMDCtrl","$injector",function(a,b,c){"undefined"!=typeof b&&c.invoke(b,this,{$scope:a})}])):"string"==typeof a.controller&&(b=a.controller),b){var c=a.resolve||{};c.__AAMDCtrl=["$q","$rootScope",function(a,c){var d=a.defer();return require([b],function(a){d.resolve(a),c.$apply()}),d.promise}],a.resolve=c}return a},c.prototype.appname=function(){return a(),e},c.prototype.processQueue=function(){function b(a){h.invoke(a)}if(a(),"undefined"==typeof k)throw new Error("Alternate angular not set. Make sure that `enable_ngload` option has been set when calling angularAMD.bootstrap");for(;r.length;){var c,d=r.shift(),e=d.module._invokeQueue;for(c=0;c0){for(var k=0;k");
42 | $compile(elm)(scope);
43 | expect(elm.text()).toBe(result.directive_name);
44 | });
45 | });
46 |
47 | it(".filter check.", function () {
48 | inject(function ($filter) {
49 | var ufilter = $filter(result.utestFilter);
50 | expect(ufilter).toBeDefined();
51 | expect(ufilter("hello")).toBe("hello " + result.filter_name);
52 | });
53 | });
54 | });
55 |
56 | describe("Utest " + result.suffix + " Animation", function () {
57 | var scope, animate, elem;
58 |
59 | beforeEach(function () {
60 | module("ngAnimateMock");
61 | inject(function ($rootScope, $compile, $rootElement, $animate) {
62 | var html_text = "
";
63 | scope = $rootScope;
64 | animate = $animate;
65 | elem = $compile(html_text)(scope);
66 | $rootElement.append(elem);
67 | });
68 | });
69 |
70 | //TODO: fix animate test
71 | it(".animation check.", function () {
72 | animate.addClass(elem, "custom-hide");
73 | scope.$digest();
74 | expect(elem.css("opacity")).toBe("");//.toBe("0");
75 |
76 | animate.removeClass(elem, "custom-hide");
77 | scope.$digest();
78 | expect(elem.css("opacity")).toBe("");//.toBe("1");
79 | });
80 | });
81 |
82 | describe("UTest " + result.suffix + " Component", function() {
83 | var element, scope;
84 | beforeEach(function() {
85 | inject(function($rootScope, $compile) {
86 | scope = $rootScope.$new();
87 | element = angular.element(' ');
88 | element = $compile(element)(scope);
89 | scope.prop = 'loaded';
90 | scope.$digest();
91 | })
92 | });
93 |
94 | it(".component check.", function() {
95 | var h3 = element.find('h3');
96 | expect(h3.text()).toBe('Component Title loaded');
97 | });
98 | })
99 | };
100 | });
--------------------------------------------------------------------------------
/test/unit/app.spec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Test focusing on setup of ngAMD making sure that cached provider are defined.
3 | */
4 | define(['app','angularAMD', 'test/unit/factory/utestProvider'], function (app, angularAMD, utestProvider) {
5 | console.log("* Running app.spec.js");
6 |
7 | describe('angularAMD', function () {
8 |
9 | describe("basics", function () {
10 | it('should be defined.', function () {
11 | expect(angularAMD).toBeDefined();
12 | });
13 | it('app should be defined.', function () {
14 | expect(app.name).toBe(angularAMD.appname());
15 | });
16 | it('app.__origAngular should be defined.', function () {
17 | var orig_angular = angularAMD.getCachedProvider('__orig_angular');
18 | expect(app.__origAngular).toBeDefined();
19 | expect(app.__origAngular).toBe(orig_angular);
20 | });
21 | it('app.__preServiceResult should be defined.', function () {
22 | expect(app.__preServiceResult).toBeDefined();
23 | });
24 | it('alternate angular should be defined.', function () {
25 | var alt_angular = angularAMD.getCachedProvider('__alt_angular');
26 | expect(alt_angular).toBeDefined();
27 | expect(window.angular).toBe(alt_angular);
28 | });
29 | });
30 |
31 | describe('cached property', function () {
32 | it('controllerProvider', function () {
33 | expect(angularAMD.getCachedProvider("$controllerProvider")).toBeDefined();
34 | });
35 | it('compileProvider', function () {
36 | expect(angularAMD.getCachedProvider("$compileProvider")).toBeDefined();
37 | });
38 | it('filterProvider', function () {
39 | expect(angularAMD.getCachedProvider("$filterProvider")).toBeDefined();
40 | });
41 | it('animateProvider', function () {
42 | expect(angularAMD.getCachedProvider("$animateProvider")).toBeDefined();
43 | });
44 | it('provide', function () {
45 | expect(angularAMD.getCachedProvider("$provide")).toBeDefined();
46 | });
47 | it('injector', function () {
48 | expect(angularAMD.getCachedProvider("$injector")).toBeDefined();
49 | });
50 | it('orig_angular', function () {
51 | // Access the 'hidden' provider created for unit test purpose
52 | expect(angularAMD.getCachedProvider("__orig_angular")).toBe(app.__origAngular);
53 | });
54 | });
55 |
56 | describe('.router', function () {
57 |
58 | it('should be simple pass-through', function () {
59 | var utestConfig = { one: "m45awKLtbM", two: "IZh0o0almb", make: "FB7T7WefnD" };
60 | expect(angularAMD.route(utestConfig)).toBe(utestConfig);
61 | });
62 |
63 | describe('with controllerURL param:', function () {
64 | var tabName = "6oO33kWCB2", r;
65 | beforeEach(function () {
66 | r = angularAMD.route({ controllerUrl: 'test/unit/lib/controller', navtab: tabName });
67 | });
68 |
69 | it('navtab should be defined.', function () {
70 | expect(r.navtab).toBe(tabName);
71 | });
72 |
73 | it('controllerUrl should have been deleted.', function () {
74 | expect(r.controllerUrl).toBeUndefined();
75 | });
76 |
77 | it('resolve should have been populated.', function () {
78 | expect(r.resolve["__AAMDCtrl"]).toBeDefined(); //jshint ignore:line
79 | });
80 | });
81 |
82 | describe('with controller param: ', function () {
83 | var tabName = "ioOc7ZIofT", r;
84 | beforeEach(function () {
85 | r = angularAMD.route({ controller: 'controller' });
86 | });
87 |
88 | it('controller should be defined.', function () {
89 | expect(r.controller).toBeDefined();
90 | });
91 |
92 | it('resolve should have been populated.', function () {
93 | expect(r.resolve["__AAMDCtrl"]).toBeDefined(); //jshint ignore:line
94 | });
95 | });
96 | });
97 |
98 | // Perform test to ensure preService loaded before bootstrap works.
99 | utestProvider(app.__preServiceResult);
100 |
101 | });
102 |
103 | });
104 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | # 0.2.1 (2014-08-08)
3 |
4 | ## Bug Fixes
5 |
6 | - **AngularJS 1.3.x**: Animation unit test now works and added fix for `.processQueue`
7 | ([e0ded6f](https://github.com/marcoslin/angularAMD/commit/e0ded6ffd290299322a721f7c669867151e9d435)
8 | [#80](https://github.com/marcoslin/angularAMD/issues/80))
9 |
10 | - **IE8**: Removed the use of `.const` breaking IE8.
11 | ([e0ded6f](https://github.com/marcoslin/angularAMD/commit/e0ded6ffd290299322a721f7c669867151e9d435)
12 | [#84](https://github.com/marcoslin/angularAMD/issues/84))
13 |
14 |
15 | # 0.2.0 (2014-07-23)
16 | *0.2.0-rc.1 (2014-06-28)*
17 |
18 | ## Bug Fixes
19 |
20 | - **ngload**: ngload now correctly load module that creates submodules internally
21 | ([e8b74af](https://github.com/marcoslin/angularAMD/commit/e8b74afd8e8de40accd15d40ea58b2d4fbb53ca5)
22 | [#67](https://github.com/marcoslin/angularAMD/issues/67))
23 |
24 | ## Features
25 |
26 | - **angularAMD.<>**: modules now can be defined before bootstrap using `angularAMD.factory`
27 | ([81a5495](https://github.com/marcoslin/angularAMD/commit/81a54955080cff296118321ee993eb66d95507a5)
28 | [#14](https://github.com/marcoslin/angularAMD/issues/14))
29 |
30 | - **.config**: New method allowing changing of configuration post bootstrap
31 | ([d3ebfed](https://github.com/marcoslin/angularAMD/commit/d3ebfed13bc83fea326ef1dca98a82977782cd40)
32 | [#71](https://github.com/marcoslin/angularAMD/issues/71))
33 |
34 | - **.route**: `controller` parameter can now be omitted if module specified in `controllerUrl` returns
35 | a function.
36 | ([550cd28](https://github.com/marcoslin/angularAMD/commit/550cd2832d0bdeac73d9c50b1ec68e7c087e9d93)
37 | [#72](https://github.com/marcoslin/angularAMD/issues/72))
38 |
39 | ## Breaking Changes
40 |
41 | - **app.<>**: `app.register` is now deprecated so a factory creation using `app.register.factory`
42 | is now `app.factory`. To support this, `.bootstrap` creates a alternate `app` that need to be used
43 | instead of the `app` created using `angular.module(...)`.
44 | ([54b5ec2](https://github.com/marcoslin/angularAMD/commit/54b5ec2d2553b30cff60dde94e9b06b0be5bf435)
45 | [1c7922b](https://github.com/marcoslin/angularAMD/commit/1c7922b9ecd6b04f80f97085edf8debb346c83b8)
46 | [#63](https://github.com/marcoslin/angularAMD/pull/63)
47 | [#70](https://github.com/marcoslin/angularAMD/issues/70))
48 |
49 |
50 |
51 |
52 | # 0.1.1 (2014-05-28)
53 |
54 | ## Bug Fixes
55 |
56 | - **ngload**: On-demand loading of animation now works
57 | ([eae2e56](https://github.com/marcoslin/angularAMD/commit/eae2e5623d742bc0ef1e6c10eb74da7ae9e367a0)
58 | [#31](https://github.com/marcoslin/angularAMD/issues/31))
59 | - **.bootstrap** Fixed Firefox Right-Click bug in Html5Mode
60 | [as per this post](https://groups.google.com/d/msg/angular/LAk9oZqRx24/mPXPj495WlEJ)
61 | ([9ce8ca1](https://github.com/marcoslin/angularAMD/commit/9ce8ca18d2b69b4779714bb6a49feee784450458)
62 | [#41](https://github.com/marcoslin/angularAMD/issues/41))
63 | - **www**: As result of
64 | [40a6dd0](https://github.com/marcoslin/angularAMD/commit/40a6dd0c89f49926fc4f5be4c5450f9eb61dcd42),
65 | removed `$rootScope` from `.config` block and replaced with custom `configValue` provider.
66 | ([6e4f7d1](https://github.com/marcoslin/angularAMD/commit/6e4f7d154879abd11c8292ded2e947e55e580347)
67 | [#60](https://github.com/marcoslin/angularAMD/issues/60))
68 | - **www**: Sample Plunk doesn't execute due to MIME type error. Switched to use `jsdelivr` instead of `raw.github.com` and from Plunker to `bl.ocks.org`
69 | ([cf8c0ff](https://github.com/marcoslin/angularAMD/commit/cf8c0fffdc47fe2e85d36dfaf46365ed2d6ec66f)
70 | [#59](https://github.com/marcoslin/angularAMD/issues/59)
71 | [#54](https://github.com/marcoslin/angularAMD/issues/54))
72 |
73 | ## Features
74 |
75 | - **unittest** Unit Test now include Registered Controller with Registered Factory
76 | ([c40bc19](https://github.com/marcoslin/angularAMD/commit/c40bc194983cc7d34b4c38e43405acf6591a1f6c)
77 | [#27](https://github.com/marcoslin/angularAMD/issues/27))
78 | - **e2e**: Added Protractor e2e testing. Need to run manually using `grunt test-e2e` and excluded from Travis-CI for now.
79 | ([4efc87d](https://github.com/marcoslin/angularAMD/commit/4efc87d9c4ce4db8ac9f67752a448536e08d56af)
80 | [5f746ef](https://github.com/marcoslin/angularAMD/commit/5f746ef3f7554a8e068557b0e8b79e52cc7d114d)
81 | [6299430](https://github.com/marcoslin/angularAMD/commit/6299430877278dfb8e919bc5a872d0974543743d))
82 |
83 |
84 | ## Breaking Changes
85 |
86 | - **ngload**: `ngload` did not correctly execute the `.config` block causing `.provider` to fail
87 | ([40a6dd0](https://github.com/marcoslin/angularAMD/commit/40a6dd0c89f49926fc4f5be4c5450f9eb61dcd42)
88 | [#28](https://github.com/marcoslin/angularAMD/issues/28)
89 | [#21](https://github.com/marcoslin/angularAMD/issues/21)).
90 | Prior to this fix, module loaded using `ngload` allowed for `.config` block to load instance such as `$rootScope`. Loading these module now will result in error.
91 |
92 |
93 | # 0.1.0 (2013-11-13)
94 |
95 | ### Initial Public Release with `ngload`
96 |
--------------------------------------------------------------------------------
/dist/angularAMD.min.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"angularAMD.min.js","sources":["../src/angularAMD.js"],"names":["define","checkBootstrapped","bootstrapped","Error","setAlternateAngular","alt_angular","orig_angular","extend","module","name","requires","alternate_modules_tracker","hasOwnProperty","alternate_modules","orig_mod","apply","arguments","item","alternate_queue","push","onDemandLoader","window","angular","AngularAMD","executeProvider","providerRecipe","constructor","preBootstrapLoaderQueue","recipe","this","app_name","orig_app","alt_app","run_injector","config_injector","app_cached_providers","prototype","route","config","load_controller","controllerUrl","controller","$scope","__AAMDCtrl","$injector","invoke","resolve","$q","$rootScope","defer","require","ctrl","$apply","promise","appname","processQueue","processRunBlock","block","length","y","shift","invokeQueue","_invokeQueue","q","provider","method","args","cachedProvider","console","error","_configBlocks","configBlocks","cf","cf_method","cf_args","_runBlocks","forEach","getCachedProvider","provider_name","inject","reset","undefined","bootstrap","app","enable_ngload","elem","document","documentElement","controllerProvider","compileProvider","filterProvider","animateProvider","provide","injector","$controllerProvider","$compileProvider","$filterProvider","$animateProvider","$provide","register","directive","filter","factory","service","constant","value","animation","bind","run","iq","element","ready"],"mappings":";;;;;;AAMAA,OAAO,WACH,YAyBA,SAASC,KACL,IAAMC,EACF,KAAM,IAAIC,OAAM,8EAqBxB,QAASC,KAEL,GAAIC,EACA,KAAM,IAAIF,OAAM,+CAEhBE,MAIJJ,IAGAK,EAAaC,OAAOF,EAAaC,GAGjCD,EAAYG,OAAS,SAAUC,EAAMC,GACjC,GAAwB,mBAAbA,GAEP,MAAIC,GAA0BC,eAAeH,GAClCI,EAAkBJ,GAElBH,EAAaE,OAAOC,EAG/B,IAAIK,GAAWR,EAAaE,OAAOO,MAAM,KAAMC,WAC3CC,GAASR,KAAMA,EAAMD,OAAQM,EAajC,OAZAI,GAAgBC,KAAKF,GACrBX,EAAaC,OAAOO,EAAUM,GAO9BT,EAA0BF,IAAQ,EAClCI,EAAkBJ,GAAQK,EAGnBA,GAIfO,OAAOC,QAAUjB,EAIrB,QAASkB,MA2WT,QAASC,GAAgBC,GACrB,MAAO,UAAUhB,EAAMiB,GAWnB,MAVIxB,GACAkB,EAAeK,GAAgBhB,EAAMiB,GAGrCC,EAAwBR,MACpBS,OAAUH,EACVhB,KAAQA,EACRiB,YAAeA,IAGhBG,MApdf,GAGIC,GACAC,EACAC,EACAC,EACAC,EAIA5B,EACAD,EAZAH,GAAe,EAQfiC,KAOAf,KACAO,KAGAd,KACAF,KACAO,IAudJ,OAhYAK,GAAWa,UAAUC,MAAQ,SAAUC,GAEnC,GAAIC,EA4BJ,IAnBKD,EAAO1B,eAAe,kBACvB2B,EAAkBD,EAAOE,oBAClBF,GAAOE,cACmB,mBAAtBF,GAAOG,aAEdH,EAAOG,YACH,SAAU,aAAc,YACxB,SAAUC,EAAQC,EAAYC,GACA,mBAAfD,IACPC,EAAUC,OAAOF,EAAYd,MAAQa,OAAUA,QAK3B,gBAAtBJ,GAAOG,aACrBF,EAAkBD,EAAOG,YAIzBF,EAAiB,CACjB,GAAIO,GAAUR,EAAOQ,WACrBA,GAAoB,YAAK,KAAM,aAAc,SAAUC,EAAIC,GACvD,GAAIC,GAAQF,EAAGE,OAKf,OAJAC,UAASX,GAAkB,SAAUY,GACjCF,EAAMH,QAAQK,GACdH,EAAWI,WAERH,EAAMI,UAEjBf,EAAOQ,QAAUA,EAGrB,MAAOR,IAOXf,EAAWa,UAAUkB,QAAU,WAE3B,MADArD,KACO6B,GAkBXP,EAAWa,UAAUmB,aAAe,WAQhC,QAASC,GAAgBC,GAErBxB,EAAaY,OAAOY,GAPxB,GAFAxD,IAE2B,mBAAhBI,GACP,KAAM,IAAIF,OAAM,mHASpB,MAAOe,EAAgBwC,QAAQ,CAC3B,GAEIC,GAFA1C,EAAOC,EAAgB0C,QACvBC,EAAc5C,EAAKT,OAAOsD,YAK9B,KAAKH,EAAI,EAAGA,EAAIE,EAAYH,OAAQC,GAAK,EAAG,CACxC,GAAII,GAAIF,EAAYF,GAChBK,EAAWD,EAAE,GACbE,EAASF,EAAE,GACXG,EAAOH,EAAE,EAGb,IAAI5B,EAAqBvB,eAAeoD,GAAW,CAC/C,GAAIG,EAEAA,GADa,cAAbH,GAAuC,WAAXC,EACX/B,EAEAC,EAAqB6B,GAG1CG,EAAeF,GAAQlD,MAAM,KAAMmD,OAG9B7C,QAAO+C,SACR/C,OAAO+C,QAAQC,MAAM,IAAML,EAAW,kBASlD,GAAI/C,EAAKT,OAAO8D,cAAe,CAC3B,GAAIC,GAAetD,EAAKT,OAAO8D,aAG/B,KAAKX,EAAI,EAAGA,EAAIY,EAAab,OAAQC,GAAK,EAAG,CACzC,GAAIa,GAAKD,EAAaZ,GAClBc,EAAYD,EAAG,GACfE,EAAUF,EAAG,EAEjBtC,GAAgBuC,GAAW1D,MAAM,KAAM2D,IAM3CzD,EAAKT,OAAOmE,YACZrD,QAAQsD,QAAQ3D,EAAKT,OAAOmE,WAAYnB,GAO5C3C,OASRU,EAAWa,UAAUyC,kBAAoB,SAAUC,GAC/C7E,GAEA,IAAIkE,EAEJ,QAAOW,GACH,IAAK,iBACDX,EAAiB7D,CACjB,MACJ,KAAK,gBACD6D,EAAiB9D,CACjB,MACJ,KAAK,aACD8D,EAAiBpC,CACjB,MACJ,KAAK,YACDoC,EAAiBnC,CACjB,MACJ,SACImC,EAAiBhC,EAAqB2C,GAG9C,MAAOX,IAOX5C,EAAWa,UAAU2C,OAAS,WAE1B,MADA9E,KACOgC,EAAaY,OAAO9B,MAAM,KAAMC,YAQ3CO,EAAWa,UAAUE,OAAS,WAE1B,MADArC,KACOiC,EAAgBW,OAAO9B,MAAM,KAAMC,YAM9CO,EAAWa,UAAU4C,MAAQ,WACG,mBAAjB1E,KAKXe,OAAOC,QAAUhB,EAGjByB,EAAWkD,OACXjD,EAAUiD,OAGV5E,EAAc4E,OACd3E,EAAe2E,OACf7D,KACAO,KAGAT,KACAY,EAAWmD,OACXhD,EAAegD,OACf/C,EAAkB+C,OAClB9C,KAGAjC,GAAe,IASnBqB,EAAWa,UAAU8C,UAAY,SAAUC,EAAKC,EAAeC,GAE3D,GAAInF,EACA,KAAMC,OAAM,qCAoFhB,IAjF6B,mBAAlBiF,KACPA,GAAgB,GAIpB9E,EAAegB,QAGfS,EAAWoD,EACXnD,KACA1B,EAAaC,OAAOyB,EAASD,GAG7BsD,EAAOA,GAAQC,SAASC,gBAGxBJ,EAAI7C,QACC,sBAAuB,mBAAoB,kBAAmB,mBAAoB,WAAY,YAAa,SAAUkD,EAAoBC,EAAiBC,EAAgBC,EAAiBC,EAASC,GAEjM3D,EAAkB2D,EAClB1D,GACI2D,oBAAqBN,EACrBO,iBAAkBN,EAClBO,gBAAiBN,EACjBO,iBAAkBN,EAClBO,SAAUN,GAIdtE,QAAQf,OAAOa,GACX4C,SAAW,SAASvD,EAAMiB,GAEtB,MADAkE,GAAQ5B,SAASvD,EAAMiB,GAChBG,MAEXY,WAAa,SAAShC,EAAMiB,GAExB,MADA8D,GAAmBW,SAAS1F,EAAMiB,GAC3BG,MAEXuE,UAAY,SAAS3F,EAAMiB,GAEvB,MADA+D,GAAgBW,UAAU3F,EAAMiB,GACzBG,MAEXwE,OAAS,SAAS5F,EAAMiB,GAEpB,MADAgE,GAAeS,SAAS1F,EAAMiB,GACvBG,MAEXyE,QAAU,SAAS7F,EAAMiB,GAGrB,MADAkE,GAAQU,QAAQ7F,EAAMiB,GACfG,MAEX0E,QAAU,SAAS9F,EAAMiB,GAErB,MADAkE,GAAQW,QAAQ9F,EAAMiB,GACfG,MAEX2E,SAAW,SAAS/F,EAAMiB,GAEtB,MADAkE,GAAQY,SAAS/F,EAAMiB,GAChBG,MAEX4E,MAAQ,SAAShG,EAAMiB,GAEnB,MADAkE,GAAQa,MAAMhG,EAAMiB,GACbG,MAEX6E,UAAWpF,QAAQqF,KAAKhB,EAAiBA,EAAgBQ,YAE7D7E,QAAQf,OAAOyB,EAASZ,MAMhC+D,EAAIyB,KAAK,YAAa,SAAUhE,GAE5BX,EAAeW,EACfT,EAAqBS,UAAYX,KAIrCH,EAAWqD,EAAI1E,KAGXkB,EAAwB+B,OAAS,EAAG,CACpC,IAAK,GAAImD,GAAK,EAAGA,EAAKlF,EAAwB+B,OAAQmD,GAAM,EAAG,CAC3D,GAAI5F,GAAOU,EAAwBkF,EACnC9E,GAASd,EAAKW,QAAQX,EAAKR,KAAMQ,EAAKS,aAE1CC,KAoBJ,MAhBAI,GAASoE,SAAW/E,EAGpBd,EAAawG,QAAQxB,UAAUyB,MAAM,WACjCzG,EAAa4E,UAAUG,GAAOvD,IAE9B5B,GAAe,EAGXkF,GAEAhF,MAKD4B,GAqBXT,EAAWa,UAAU4B,SAAWxC,EAAgB,YAEhDD,EAAWa,UAAUK,WAAajB,EAAgB,cAElDD,EAAWa,UAAUgE,UAAY5E,EAAgB,aAEjDD,EAAWa,UAAUiE,OAAS7E,EAAgB,UAE9CD,EAAWa,UAAUkE,QAAU9E,EAAgB,WAE/CD,EAAWa,UAAUmE,QAAU/E,EAAgB,WAE/CD,EAAWa,UAAUoE,SAAWhF,EAAgB,YAEhDD,EAAWa,UAAUqE,MAAQjF,EAAgB,SAE7CD,EAAWa,UAAUsE,UAAYlF,EAAgB,aAG1C,GAAID"}
--------------------------------------------------------------------------------
/test/unit/factory/provider.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A standard set of code used to create different AngularJS provider. They considerations:
3 | * 1. Out of sequence creation: .value and .constant used by .factory and .service are created later
4 | *
5 | * `module` object is used to create provider and `suffix` is used as part of the name of provider to
6 | * make it unique. A `result` object is returned with name of provider created and the expected value
7 | * associated with that provider.
8 | */
9 | define(function () {
10 | /**
11 | * A function that will create different AngularJS provider for the given module.
12 | * All module name created will has a suffix
13 | */
14 | return function (module, suffix) {
15 | var result = { suffix: suffix };
16 |
17 | /*
18 | Create Test Provider to store configuration value and a associated .factory
19 | to return the value stored in the .config block.
20 |
21 | Also test chained call
22 | */
23 | result.UtestStore = "UtestStore" + suffix;
24 | result.UtestStoreProvider = "UtestStore" + suffix + "Provider";
25 | result.UtestStoreResult = 'UtestStoreResult' + suffix;
26 | module
27 | .provider(result.UtestStore, function () {
28 | var config_value;
29 |
30 | this.configureValue = function(value) {
31 | config_value = value;
32 | };
33 |
34 | this.$get = function () {
35 | return {
36 | getValue: function () {
37 | return config_value;
38 | }
39 | };
40 | };
41 | })
42 | .factory(result.UtestStoreResult, [result.UtestStore, function (UtestStore) {
43 | return UtestStore.getValue();
44 | }]);
45 |
46 | /*
47 | Create a .factory using the UtestConstant declared later
48 | */
49 | result.UtestConstant = "UtestConstant" + suffix;
50 | result.UtestFactory = "UtestFactory" + suffix;
51 | result.factory_name = "UtestFactory.name nSg56eHrWo" + suffix;
52 | module.factory(result.UtestFactory, [result.UtestConstant, function (UtestConstant) {
53 | // Make sure that constant_name is setup after this factory.
54 | return { name: result.factory_name, const_name: UtestConstant };
55 | }]);
56 |
57 | /*
58 | Create a .service using the UtestValue declared later
59 | */
60 | result.UtestValue = "UtestValue" + suffix;
61 | result.UtestService = "UtestService" + suffix;
62 | result.service_name = "UtestService.name ySg56eHrWo" + suffix;
63 | module.service(result.UtestService, ["UtestValue" + suffix, function (UtestValue) {
64 | // Make sure that value_name is defined after this service
65 | this.name = result.service_name;
66 | this.val_name = UtestValue;
67 | }]);
68 |
69 | /*
70 | Define out of sequence constant and value, used by .factory and .service earlier
71 |
72 | Also test chained call
73 | */
74 | result.constant_name = "utestmod.constant_name xHf71eVzxd" + suffix;
75 | result.value_name = "utestmod.value_name ih3zRvZofo" + suffix;
76 | module
77 | .constant(result.UtestConstant, result.constant_name)
78 | .value(result.UtestValue, result.value_name);
79 |
80 | /*
81 | Create .directive. The name of directive is different as for consumer, it has to
82 | be converted to - based from the Camel case.
83 | */
84 | result.utestDirective = "utest-directive-" + suffix.toLowerCase();
85 | result.directive_name = "utestmod.directive_name Krloe7G1CH" + suffix;
86 | module.directive('utestDirective' + suffix, function () {
87 | return {
88 | restrict: 'A',
89 | link: function (scope, elm, attr) {
90 | elm.text(result.directive_name);
91 | }
92 | };
93 | });
94 |
95 | /*
96 | Create .filter
97 | */
98 | result.utestFilter = 'utestFilter' + suffix;
99 | result.filter_name = "utestmod.filter_name 0WWb0usFCB" + suffix;
100 | module.filter(result.utestFilter, function () {
101 | return function (input) {
102 | return input + " " + result.filter_name;
103 | };
104 | });
105 |
106 |
107 | /*
108 | Create .animation
109 | For some reason, addClass and removeClass no longer works in the unit test
110 | in AngularJS 13.0.x (tested under 1.3.0-beta.17). As the intent of this
111 | test is to ensure that animation is loaded, changed to before* version.
112 |
113 | Created following plunker to ensure that addClass/removeClass works inder 1.3.x
114 | http://plnkr.co/edit/VsWfqqbAnqrr7cE3toYn
115 | */
116 | result.utestAnimation = ".animation-" + suffix.toLowerCase();
117 | module.animation(result.utestAnimation, function ($log, $interval) {
118 | return {
119 | beforeAddClass : function(element, className, done) {
120 | if ( className === "custom-hide") {
121 | element.css('opacity',0);
122 | done();
123 | }
124 | },
125 | beforeRemoveClass : function(element, className, done) {
126 | if ( className === "custom-hide") {
127 | element.css('opacity',1);
128 | done();
129 | }
130 | }
131 | };
132 | });
133 |
134 | /*
135 | Return result
136 | */
137 | return result;
138 | };
139 |
140 | });
141 |
142 |
--------------------------------------------------------------------------------
/test/unit/lib/providerFactory.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A standard set of code used to create different AngularJS provider. They considerations:
3 | * 1. Out of sequence creation: .value and .constant used by .factory and .service are created later
4 | * 2. config block is tested by using a custom provider UtestStore and result given by a UtestStoreResult
5 | *
6 | * `module` object is used to create provider and `suffix` is used as part of the name of provider to
7 | * make it unique. A `result` object is returned with name of provider created and the expected value
8 | * associated with that provider.
9 | */
10 | define(function () {
11 | /**
12 | * A function that will create different AngularJS provider for the given module.
13 | * All module name created will has a suffix
14 | */
15 | return function (module, suffix) {
16 | var result = { suffix: suffix };
17 |
18 | /*
19 | Create Test Provider to store configuration value and a associated .factory
20 | to return the value stored in the .config block
21 | */
22 | result.UtestStore = "UtestStore" + suffix;
23 | result.UtestStoreProvider = "UtestStore" + suffix + "Provider";
24 | module.provider(result.UtestStore, function () {
25 | var config_value;
26 |
27 | this.configureValue = function(value) {
28 | config_value = value;
29 | };
30 |
31 | this.$get = function () {
32 | return {
33 | getValue: function () {
34 | return config_value;
35 | }
36 | };
37 | };
38 | });
39 |
40 | result.UtestStoreResult = 'UtestStoreResult' + suffix;
41 | module.factory(result.UtestStoreResult, [result.UtestStore, function (UtestStore) {
42 | return UtestStore.getValue();
43 | }]);
44 |
45 | /*
46 | Use the .config block to set the test provider's value
47 | */
48 | result.config_name = "module.config SDkWRXOgII" + suffix;
49 | module.config([result.UtestStoreProvider, function (UtestStoreProvider) {
50 | UtestStoreProvider.configureValue(result.config_name);
51 | }]);
52 |
53 | /*
54 | Use the .run block to set value for $rootScope.run_name
55 | */
56 | result.run_name = "module.run sOdq6GNsaW" + suffix;
57 | module.run(function ($rootScope) {
58 | $rootScope.run_name = result.run_name;
59 | });
60 |
61 | /*
62 | Create a .factory using the UtestConstant declared later
63 | */
64 | result.UtestConstant = "UtestConstant" + suffix;
65 | result.UtestFactory = "UtestFactory" + suffix;
66 | result.factory_name = "UtestFactory.name nSg56eHrWo" + suffix;
67 | module.factory(result.UtestFactory, [result.UtestConstant, function (UtestConstant) {
68 | // Make sure that constant_name is setup after this factory.
69 | return { name: result.factory_name, const_name: UtestConstant };
70 | }]);
71 |
72 | /*
73 | Create a .service using the UtestValue declared later
74 | */
75 | result.UtestValue = "UtestValue" + suffix;
76 | result.UtestService = "UtestService" + suffix;
77 | result.service_name = "UtestService.name ySg56eHrWo" + suffix;
78 | module.service(result.UtestService, ["UtestValue" + suffix, function (UtestValue) {
79 | // Make sure that value_name is defined after this service
80 | this.name = result.service_name;
81 | this.val_name = UtestValue;
82 | }]);
83 |
84 | /*
85 | Define out of sequence constant and value, used by .factory and .service earlier
86 | */
87 | result.constant_name = "utestmod.constant_name xHf71eVzxd" + suffix;
88 | module.constant(result.UtestConstant, result.constant_name);
89 |
90 | result.value_name = "utestmod.value_name ih3zRvZofo" + suffix;
91 | module.value(result.UtestValue, result.value_name);
92 |
93 | /*
94 | Create .directive. The name of directive is different as for consumer, it has to
95 | be converted to - based from the Camel case.
96 | */
97 | result.utestDirective = "utest-directive-" + suffix.toLowerCase();
98 | result.directive_name = "utestmod.directive_name Krloe7G1CH" + suffix;
99 | module.directive('utestDirective' + suffix, function () {
100 | return {
101 | restrict: 'A',
102 | link: function (scope, elm, attr) {
103 | elm.text(result.directive_name);
104 | }
105 | };
106 | });
107 |
108 | /*
109 | Create .filter
110 | */
111 | result.utestFilter = 'utestFilter' + suffix;
112 | result.filter_name = "utestmod.filter_name 0WWb0usFCB" + suffix;
113 | module.filter(result.utestFilter, function () {
114 | return function (input) {
115 | return input + " " + result.filter_name;
116 | };
117 | });
118 |
119 |
120 | /*
121 | Create .animation
122 | */
123 | result.utestAnimation = ".animation-" + suffix.toLowerCase();
124 | module.animation(result.utestAnimation, function ($log, $interval) {
125 | return {
126 | addClass : function(element, className, done) {
127 | if ( className === "custom-hide") {
128 | element.css('opacity',0);
129 | done();
130 | }
131 | },
132 | removeClass : function(element, className, done) {
133 | if ( className === "custom-hide") {
134 | element.css('opacity',1);
135 | done();
136 | }
137 | }
138 | };
139 | });
140 |
141 | /*
142 | Return result
143 | */
144 | return result;
145 | };
146 |
147 | });
148 |
149 |
--------------------------------------------------------------------------------
/test/e2e/www.spec.js:
--------------------------------------------------------------------------------
1 | var url = require("url");
2 |
3 | describe('angularAMD', function() {
4 | var ptor = protractor.getInstance(),
5 | default_wait_ms = 15000;
6 |
7 | /**
8 | * Function used to in place of `ptor.get` as the native version will not wait for manual bootstrapping.
9 | * It adds an 0.5 sec wait before checking that url has been correctly set.
10 | */
11 | function ptor_get(rel_path) {
12 | ptor.driver.get(url.resolve(ptor.baseUrl, rel_path));
13 | ptor.wait(function () {
14 | return ptor.driver.getCurrentUrl().then(function(in_url) {
15 | var re = new RegExp(rel_path, "i");
16 | return re.test(in_url);
17 | });
18 | }, default_wait_ms, "Taking too long to load " + rel_path);
19 | ptor.sleep(1000);
20 | }
21 |
22 | function ptor_waitForElementById(nameId) {
23 | ptor.wait(function () {
24 | //console.log("Checking if " + nameId + " exists");
25 | return ptor.driver.isElementPresent(by.id(nameId)).then(function (is_present) {
26 | return is_present;
27 | });
28 | }, default_wait_ms, "Taking too long waiting for element id '" + nameId + "' to be present.");
29 | return element(by.id(nameId));
30 | }
31 |
32 | describe("home", function () {
33 | it('tab should be active', function() {
34 | ptor_get('#/home');
35 | var navElem = ptor_waitForElementById("nav-home");
36 | expect(navElem.getAttribute("class")).toBe("active");
37 | expect(ptor.getCurrentUrl()).toContain('#/home');
38 | });
39 |
40 | it("View on GitHub button should exists", function () {
41 | expect($("#view-on-github").getAttribute('class')).toBe("btn btn-large");
42 | });
43 |
44 | it("View on GitHub button should exists", function () {
45 | expect($("#view-on-github").getAttribute('class')).toBe("btn btn-large");
46 | expect($("#view-on-github i").getAttribute('class')).toBe("icon-github-sign");
47 | });
48 | });
49 |
50 | describe("map", function () {
51 | // As map tab takes a bit longer to become active, probably due to the work to load google map
52 | it("tab should be active", function () {
53 | ptor_get('#/map');
54 | var navElem = ptor_waitForElementById("nav-map");
55 | ptor.wait(function () {
56 | return navElem.getAttribute("class").then(function (class_value) {
57 | return class_value == "active";
58 | });
59 | }, default_wait_ms, "Taking too long for map tab to become active");
60 | });
61 |
62 | // As map takes a bit to load, give it up to 5 secs for it to load
63 | it("should be loaded", function () {
64 | ptor_waitForElementById("map-canvas");
65 | expect($('#map-canvas .gm-style').getAttribute("style")).toBeDefined();
66 | });
67 | })
68 |
69 | describe("module", function () {
70 | it("modules tab should be active", function () {
71 | ptor_get('#/modules');
72 | var navElem = ptor_waitForElementById("nav-modules");
73 | ptor.wait(function () {
74 | return navElem.getAttribute("class").then(function (class_value) {
75 | return class_value == "active";
76 | });
77 | }, default_wait_ms, "Taking too long for map tab to become active");
78 | });
79 |
80 | it("ng-write to output correct value", function () {
81 | expect($("#output-ng-write").getText()).toBe("Output from Directive");
82 | });
83 |
84 | it("DeferredString to output correct value", function () {
85 | expect($("#output-deferred-string").getText()).toBe("Show case ngWrite with promise");
86 | });
87 |
88 | it("DeferredObject to output correct value", function () {
89 | expect($("#output-deferred-object").getText()).toBe("This is defered response");
90 | });
91 |
92 | it(".run to output correct value", function () {
93 | expect($("#output-run").getText()).toBe("Greetings from .run");
94 | });
95 |
96 | it(".config to output correct value", function () {
97 | expect($("#output-config").getText()).toBe("And config works");
98 | });
99 |
100 |
101 | });
102 |
103 | // This has to be the last as ignoreSynchronization seems to impact remaining tests
104 | describe("pictures", function () {
105 | it("tab should be active", function () {
106 | ptor_get('#/pictures');
107 | var navElem = ptor_waitForElementById("nav-pictures");
108 | ptor.wait(function () {
109 | return navElem.getAttribute("class").then(function (class_value) {
110 | return class_value == "active";
111 | });
112 | }, default_wait_ms, "Taking too long for pictures tab to become active");
113 | });
114 |
115 | // Ignoring sync due to use of $timer in ui-bootstrap to change pictures
116 | describe("ignore sync", function () {
117 | beforeEach(function () {
118 | ptor.ignoreSynchronization = true;
119 | });
120 | afterEach(function () {
121 | ptor.ignoreSynchronization = false;
122 | });
123 |
124 | it("london clicked", function () {
125 | var btn_london = $('#btn-london'),
126 | pictures = element.all(by.repeater('row in rows')),
127 | pictures_count = 0;
128 |
129 | btn_london.click().then(function () {
130 | expect(btn_london.getAttribute("class")).toMatch('active');
131 |
132 | // Get the pictures_count using repeater
133 | ptor.wait(function () {
134 | return pictures.count().then( function (row_count) {
135 | if (row_count > 0) {
136 | pictures_count = row_count;
137 | return true;
138 | } else {
139 | return false;
140 | }
141 | });
142 | }, default_wait_ms, "Taking too long to load pictures");
143 |
144 | // Make sure that number of `slide_image` is the same as pictures_count
145 | var slideimages = element.all(by.css('.slide-image'));
146 | slideimages.count().then(function (row_count) {
147 | expect(row_count).toBe(pictures_count);
148 | })
149 | });
150 | });
151 |
152 | it("rome clicked", function () {
153 | var btn_rome = $('#btn-rome');
154 | btn_rome.click().then(function () {
155 | expect(btn_rome.getAttribute("class")).toMatch('active');
156 | });
157 | });
158 |
159 | });
160 | })
161 |
162 | });
163 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | angularAMD v0.2.1 [](https://travis-ci.org/marcoslin/angularAMD)
2 | ==========
3 | angularAMD is an utility that facilitates the use of RequireJS in AngularJS applications supporting on-demand loading
4 | of 3rd party modules such as [angular-ui](git@github.com:marcoslin/bower-angularAMD.git).
5 |
6 | Installation
7 | ==========
8 |
9 | ### bower
10 | bower install angularAMD
11 |
12 | ### cdn
13 | //cdn.jsdelivr.net/angular.amd/0.2/angularAMD.min.js
14 |
15 |
16 | Usage
17 | ==========
18 |
19 | http://marcoslin.github.io/angularAMD/ has been created as a working demo for `angularAMD`. The source code
20 | can be found in the `www/` directory of this project.
21 |
22 | Additional, the following project has been created to illustrate how to build an `r.js` optmized distribution:
23 | * https://github.com/marcoslin/angularAMD-sample
24 |
25 | ### RequireJS data-main
26 |
27 | Starting point for any RequireJS app is a `main.js`, which should be used to define the components and their
28 | dependencies. Use `deps` to kick off `app.js`:
29 |
30 | ```Javascript
31 | require.config({
32 | baseUrl: "js",
33 | paths: {
34 | 'angular': '//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min',
35 | 'angularAMD': 'lib/angularAMD.min',
36 | 'ngload': 'lib/ngload.min'
37 | },
38 | shim: {
39 | 'angularAMD': ['angular'],
40 | 'ngload': ['angularAMD']
41 | },
42 | deps: ['app']
43 | });
44 | ```
45 |
46 | ### Bootstrapping AngularJS
47 |
48 | Once all component dependencies have been defined, use a `app.js` to create the AngularJS application and perform the bootstrapping:
49 |
50 | ```Javascript
51 | define(['angularAMD'], function (angularAMD) {
52 | var app = angular.module(app_name, ['webapp']);
53 | ... // Setup app here. E.g.: run .config with $routeProvider
54 | return angularAMD.bootstrap(app);
55 | });
56 | ```
57 |
58 | Since bootstrapping is taking place manually, `ng-app` should not be used in HTML. `angularAMD.bootstrap(app);` will take care of bootstraping AngularJS.
59 |
60 | ### On-Demand Loading of Controllers
61 |
62 | Use `angularAMD.route` when configuring routes using `$routeProvider` to enable the on-demand loading of controllers:
63 |
64 | ```Javascript
65 | app.config(function ($routeProvider) {
66 | $routeProvider.when(
67 | "/home",
68 | angularAMD.route({
69 | templateUrl: 'views/home.html',
70 | controller: 'HomeController',
71 | controllerUrl: 'scripts/controller'
72 | })
73 | );
74 | });
75 | ```
76 |
77 | The primary purpose of `angularAMD.route` is to set the `.resolve` property to load controller using a `require` statement.
78 | Any attribute you pass into this method will simply be returned, with exception of `controllerUrl`.
79 |
80 | #### route without `controllerUrl`
81 |
82 | You can avoid passing of `controllerUrl` if you define it in your `main.js` as:
83 |
84 | ```Javascript
85 | paths: { 'HomeController': 'scripts/controller' }
86 | ```
87 |
88 |
89 | #### route without `controller`
90 |
91 | When the `controller` option is omitted, `angularAMD.route` assumes that a function will be returned from the module defined
92 | by `controllerUrl`. As a result, you can avoid giving an explicit name to your controller by doing:
93 |
94 | ```Javascript
95 | define(['app'], function (app) {
96 | return ["$scope", function ($scope) {
97 | ...
98 | }];
99 | });
100 | ```
101 |
102 |
103 | ### Creating a Module
104 |
105 | Any subsequent module definitions would simply need to require `app` to create the desired AngularJS services:
106 |
107 | ```Javascript
108 | define(['app'], function (app) {
109 | app.factory('Pictures', function (...) {
110 | ...
111 | });
112 | });
113 | ```
114 |
115 | Here is the list of methods supported:
116 |
117 | * `.provider` **
118 | * `.controller`
119 | * `.factory`
120 | * `.service`
121 | * `.constant`
122 | * `.value`
123 | * `.directive`
124 | * `.filter`
125 | * `.animation`
126 |
127 | ** Only as of 0.2.x
128 |
129 | #### Loading Application Wide Module
130 |
131 | Normally, application wide features are created as independent modules and added as dependency to your `app`.
132 | 3rd party packages such as [ui-bootstrap](http://angular-ui.github.io/bootstrap/) is a perfect example. However,
133 | what if you have a single directive? `angularAMD` simplifies such tasks by exposing the provider recipe so you can do something like:
134 |
135 | **directive/navMenu.js**
136 | ```Javascript
137 | define(['angularAMD'], function (angularAMD) {
138 | angularAMD.directive('navMenu', function (...) {
139 | ...
140 | });
141 | });
142 | ```
143 |
144 | **app.js**
145 | ```Javascript
146 | define(['angularAMD', 'directive/navMenu'], function (angularAMD) {
147 | var app = angular.module(app_name, ['webapp']);
148 | ...
149 | // `navMenu` is automatically registered bootstrap
150 | return angularAMD.bootstrap(app);
151 | });
152 | ```
153 |
154 | In this case, `angularAMD.directive` will detect that boostraping hasn't taken place yet and it will queue up the
155 | directive creation request and apply that request directly on the `app` object passed to `angularAMD.bootstrap`. If bootstraping has taken place already, it will essentially do the same thing `app.directive`. As a result, services created using `angularAMD.<>` can be loaded before and after bootstraping.
156 |
157 | ### 3rd Party AngularJS Modules
158 |
159 | 3rd party AngularJS modules, meaning any module created using `angular.module` syntax, can be loaded as any normal
160 | JavaScript file *before* `angularAMD.bootstrap` is called. After bootstraping, any AngularJS module must be loaded
161 | using the included `ngload` RequireJS plugin.
162 |
163 | ```Javascript
164 | define(['app', 'ngload!dataServices'], function (app) {...});
165 | ```
166 |
167 | In case you need to load your module using the RequireJS plugin or if you have complex dependecies, you can create a wrapper RequireJS module as below:
168 |
169 | ```Javascript
170 | define(['angularAMD', 'ui-bootstrap'], function (angularAMD) {
171 | angularAMD.processQueue();
172 | });
173 | ```
174 |
175 | In this case, all dependencies will be queued up and when `.processQueue()` is called, it will go through the queue and copy them into current app using `app.register`:
176 |
177 | #### Module without `.run` or `.config`
178 |
179 | If you have your own module that does not use `.run` or `.config`, you can avoid the use of `ngload` as any module
180 | created after bootstrap will support on-demand loading. For example:
181 |
182 | **common.js**
183 | ```Javascript
184 | define(['ngload!restangular'], function() {
185 | return angular.module('common', ['restangular']);
186 | });
187 | ```
188 |
189 | **user.js**
190 | ```Javascript
191 | define(['common'], function(common) {
192 | common.factory("User", function () { ... });
193 | });
194 | ```
195 |
196 | **controller/home_ctrl**
197 | ```Javascript
198 | define(['app', 'user'], function(app) {
199 | app.controller("HomeCtrl", ["$scope", "User", function ($scope, User) {
200 | ...
201 | }]);
202 | });
203 | ```
204 |
205 | In this example, the `user` package does not need to be loaded in the `app.js` as it's loaded on demand when `HomeCtrl` is called.
206 |
207 | Running Sample Project
208 | ==========
209 |
210 | Prerequisites:
211 | * node and npm
212 | * grunt-cli installed globally as per [Grunt Getting started](http://gruntjs.com/getting-started).
213 |
214 | Run the following command after cloning this project:
215 |
216 | ```bash
217 | npm install
218 | grunt build
219 | grunt serve-www
220 | ```
221 | * The default build will test angularAMD using following browsers: 'PhantomJS', 'Chrome' and 'Firefox'
222 |
223 | History
224 | ==========
225 | This project was inpired by [Dan Wahlin's blog](http://weblogs.asp.net/dwahlin/archive/2013/05/22/dynamically-loading-controllers-and-views-with-angularjs-and-requirejs.aspx)
226 | where he explained the core concept of what is needed to make RequireJS works with AngularJS. It is a *must* read
227 | if you wish to better understand implementation detail of `angularAMD`.
228 |
229 | As I started to implement RequireJS in my own project, I got stuck trying to figure out how to load my existing modules without re-writting them. After exhausive search with no satisfactory answer, I posted following question on [StackOverflow](http://stackoverflow.com/questions/19134023/lazy-loading-angularjs-modules-with-requirejs).
230 | [Nikos Paraskevopoulos](http://stackoverflow.com/users/2764255/nikos-paraskevopoulos) was kind enough to share his
231 | solution with me but his implementation did not handle `.config` method calls and out of order definition in modules. However, his implementation gave me the foundation I needed to create `angularAMD` and his project is where the idea for `alt_angular` came from.
232 |
233 |
234 | References
235 | ==========
236 |
237 | * [Dynamically Loading Controllers and Views with AngularJS and RequireJS](http://weblogs.asp.net/dwahlin/archive/2013/05/22/dynamically-loading-controllers-and-views-with-angularjs-and-requirejs.aspx) by Dan Wahlin
238 | * [Dependency Injection using RequireJS & AngularJS](http://solutionoptimist.com/2013/09/30/requirejs-angularjs-dependency-injection/) by Thomas Burleson
239 | * [Lazy loading AngularJS modules with RequireJS](http://stackoverflow.com/questions/19134023/lazy-loading-angularjs-modules-with-requirejs) stackoverflow
240 | * [angular-require-lazy](https://github.com/nikospara/angular-require-lazy) by Nikos Paraskevopoulos
241 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | // Gruntfile
2 | /*jslint devel: true, node: true, white:true */
3 |
4 | module.exports = function (grunt) {
5 | 'use strict';
6 | require('load-grunt-tasks')(grunt);
7 |
8 | // Config variables
9 | var configVars = {
10 | 'build': 'build',
11 | 'dist': 'dist',
12 | 'dist_www': '../gh-pages',
13 | 'dist_bower': '../bower-repo',
14 | 'www_server': 'localhost',
15 | 'www_port': '9768',
16 | 'e2e_port': '9769'
17 | };
18 |
19 | // Read version and banner files
20 | configVars.proj_version = grunt.file.read('src/version.txt');
21 | configVars.proj_banner = grunt.file.read('src/banner.txt');
22 |
23 |
24 | grunt.initConfig({
25 | cvars: configVars,
26 | bower: {
27 | setup: {
28 | options: { install: true, copy: false }
29 | }
30 | },
31 | shell: {
32 | 'webdriver-manager-update': {
33 | command: 'node_modules/protractor/bin/webdriver-manager update',
34 | options: {
35 | async: false
36 | }
37 | }
38 | },
39 | copy: {
40 | 'setup-www': {
41 | files: [
42 | {
43 | expand: true, cwd: 'src/',
44 | src: 'angularAMD.js', dest: 'www/js/lib/requirejs/'
45 | },
46 | {
47 | expand: true, cwd: 'src/',
48 | src: 'ngload.js', dest: 'www/js/lib/requirejs/'
49 | },
50 | {
51 | expand: true, cwd: 'bower_components/angular/',
52 | src: 'angular.js', dest: 'www/js/lib/angular/'
53 | },
54 | {
55 | expand: true, cwd: 'bower_components/angular-route/',
56 | src: 'angular-route.js', dest: 'www/js/lib/angular/'
57 | },
58 | {
59 | expand: true, cwd: 'bower_components/angular-ui-bootstrap-bower/',
60 | src: ['ui-bootstrap-tpls.js'], dest: 'www/js/lib/angular-ui-bootstrap/'
61 | },
62 | {
63 | expand: true, cwd: 'bower_components/requirejs/',
64 | src: 'require.js', dest: 'www/js/lib/requirejs/'
65 | },
66 | {
67 | expand: true, cwd: 'bower_components/requirejs-plugins/src/',
68 | src: 'async.js', dest: 'www/js/lib/requirejs/'
69 | },
70 | {
71 | expand: true, cwd: 'bower_components/google-code-prettify/src/',
72 | src: 'prettify.js', dest: 'www/js/lib/google-code-prettify/'
73 | },
74 | {
75 | expand: true, cwd: 'bower_components/google-code-prettify/src/',
76 | src: 'prettify.css', dest: 'www/css/'
77 | }
78 | ]
79 | },
80 | 'build-www': {
81 | files: [
82 | {
83 | expand: true, cwd: 'www/',
84 | src: ['index.html','css/**', 'views/**', 'js/main.js', 'js/scripts/**'],
85 | dest: '<%= cvars.build %>/www/'
86 | }
87 | ]
88 | },
89 | 'dist-www': {
90 | files: [
91 | {
92 | src: '<%= cvars.build %>/angularAMD.min.js',
93 | dest: '<%= cvars.dist_www %>/js/lib/requirejs/angularAMD.js'
94 | },
95 | {
96 | src: '<%= cvars.build %>/ngload.min.js',
97 | dest: '<%= cvars.dist_www %>/js/lib/requirejs/ngload.js'
98 | },
99 | {
100 | src: 'bower_components/angular/angular.min.js',
101 | dest: '<%= cvars.dist_www %>/js/lib/angular/angular.js'
102 | },
103 | {
104 | src: 'bower_components/angular-route/angular-route.min.js',
105 | dest: '<%= cvars.dist_www %>/js/lib/angular/angular-route.js'
106 | },
107 | {
108 | src: 'bower_components/angular-ui-bootstrap-bower/ui-bootstrap-tpls.min.js',
109 | dest: '<%= cvars.dist_www %>/js/lib/angular-ui-bootstrap/ui-bootstrap-tpls.js'
110 | },
111 | {
112 | expand: true, cwd: 'bower_components/google-code-prettify/src/',
113 | src: 'prettify.js', dest: '<%= cvars.dist_www %>/js/lib/google-code-prettify/'
114 | }
115 | ]
116 | },
117 | 'dist-bower' : {
118 | files: [
119 | {
120 | expand: true, cwd: '<%= cvars.build %>',
121 | src: ['*.js','*.map'],
122 | dest: '<%= cvars.dist %>/'
123 | },
124 | {
125 | expand: true, cwd: '<%= cvars.build %>',
126 | src: ['*.js','*.map'],
127 | dest: '<%= cvars.dist_bower %>/'
128 | }
129 | ]
130 | }
131 |
132 | },
133 | connect: {
134 | // URL should be: http://localhost:9768/www/ to simulate github pages
135 | options : {
136 | hostname: '<%= cvars.www_server %>'
137 | },
138 | 'serve-www': {
139 | options : {
140 | port: '<%= cvars.www_port %>',
141 | base: '.',
142 | keepalive: true
143 | }
144 | },
145 | 'e2e-www': {
146 | options : {
147 | port: '<%= cvars.e2e_port %>',
148 | base: './www',
149 | keepalive: false
150 | }
151 | }
152 | },
153 | open: {
154 | 'serve-www': {
155 | path: 'http://<%= cvars.www_server %>:<%= cvars.www_port %>/www/',
156 | app: 'Google Chrome'
157 | }
158 | },
159 | karma: {
160 | 'unit': {
161 | configFile: '<%= cvars.build %>/test/conf/karma.unit.js',
162 | singleRun: false
163 | },
164 | 'unit-no-ngload': {
165 | configFile: 'test/conf/karma.unit.no_ngload.js',
166 | singleRun: false
167 | },
168 | 'build': {
169 | configFile: '<%= cvars.build %>/test/conf/karma.unit.js',
170 | browsers: ['PhantomJS','Chrome','Firefox']
171 | },
172 | 'build-min': {
173 | configFile: '<%= cvars.build %>/test/conf/karma.unit.min.js',
174 | browsers: ['PhantomJS','Chrome','Firefox']
175 | },
176 | 'build-travis': {
177 | configFile: '<%= cvars.build %>/test/conf/karma.unit.min.js'
178 | }
179 | },
180 | protractor: {
181 | options: {
182 | configFile: 'test/conf/protractor.e2e.js'
183 | },
184 | 'e2e-www': {
185 | options: {
186 | keepAlive: true,
187 | args: {
188 | browser: 'chrome',
189 | baseUrl: 'http://<%= cvars.www_server %>:<%= cvars.e2e_port %>'
190 | }
191 | }
192 | },
193 | 'build-travis': {
194 | options: {
195 | keepAlive: false,
196 | args: {
197 | browser: 'phantomjs',
198 | baseUrl: 'http://<%= cvars.www_server %>:<%= cvars.e2e_port %>'
199 | }
200 | }
201 | }
202 | },
203 | template: {
204 | 'main-js': {
205 | src: 'test/unit/lib/main.mustache',
206 | dest: '<%= cvars.build %>/test/unit/lib/main.js',
207 | variables: {
208 | 'angularAMD-js-file': 'src/angularAMD',
209 | 'ngload-js-file': 'src/ngload'
210 | }
211 | },
212 | 'main-min-js': {
213 | src: 'test/unit/lib/main.mustache',
214 | dest: '<%= cvars.build %>/test/unit/lib/main.min.js',
215 | variables: {
216 | 'angularAMD-js-file': '<%= cvars.build %>/angularAMD.min',
217 | 'ngload-js-file': '<%= cvars.build %>/ngload.min'
218 | }
219 | },
220 | 'karma-js': {
221 | src: 'test/conf/karma.unit.mustache',
222 | dest: '<%= cvars.build %>/test/conf/karma.unit.js',
223 | variables: {
224 | 'main-js-file': '<%= cvars.build %>/test/unit/lib/main.js'
225 | }
226 | },
227 | 'karma-min-js': {
228 | src: 'test/conf/karma.unit.mustache',
229 | dest: '<%= cvars.build %>/test/conf/karma.unit.min.js',
230 | variables: {
231 | 'main-js-file': '<%= cvars.build %>/test/unit/lib/main.min.js'
232 | }
233 | }
234 | },
235 | concat: {
236 | 'build': {
237 | options: {
238 | 'banner': configVars.proj_banner,
239 | 'stripBanners': true
240 | },
241 | files: {
242 | '<%= cvars.build %>/angularAMD.js': ['src/angularAMD.js'],
243 | '<%= cvars.build %>/ngload.js': ['src/ngload.js']
244 | }
245 | }
246 | },
247 | ngAnnotate: {
248 | 'dist-www': {
249 | files: [{
250 | expand: true,
251 | cwd: 'www/js/scripts/',
252 | src: '**/*.js',
253 | dest: '<%= cvars.dist_www %>/js/scripts/'
254 | }]
255 | }
256 | },
257 | uglify: {
258 | 'build': {
259 | options: {
260 | 'report': true,
261 | 'banner': configVars.proj_banner,
262 | 'stripBanners': true,
263 | 'sourceMap': true
264 | },
265 | files: {
266 | '<%= cvars.build %>/angularAMD.min.js': ['src/angularAMD.js'],
267 | '<%= cvars.build %>/ngload.min.js': ['src/ngload.js']
268 | }
269 | },
270 | 'dist-www': {
271 | files: [
272 | {
273 | expand: true, cwd: 'www/js/',
274 | src: 'main.js', dest: '<%= cvars.dist_www %>/js/'
275 | },
276 | {
277 | expand: true, cwd: '<%= cvars.dist_www %>/js/scripts/',
278 | src: '**/*.js', dest: '<%= cvars.dist_www %>/js/scripts/'
279 | },
280 | {
281 | src: 'bower_components/requirejs/require.js',
282 | dest: '<%= cvars.dist_www %>/js/lib/requirejs/require.js'
283 | },
284 | {
285 | expand: true, cwd: 'bower_components/requirejs-plugins/src/',
286 | src: 'async.js', dest: '<%= cvars.dist_www %>/js/lib/requirejs/'
287 | }
288 | ]
289 | }
290 | },
291 | cssmin: {
292 | 'dist-www': {
293 | files: {
294 | '<%= cvars.dist_www %>/css/style.css': 'www/css/style.css',
295 | '<%= cvars.dist_www %>/css/prettify.css': 'www/css/prettify.css',
296 | '<%= cvars.dist_www %>/css/sons-of-obsidian.css': 'www/css/sons-of-obsidian.css'
297 | }
298 | }
299 | },
300 | htmlmin : {
301 | 'dist-www': {
302 | options: {
303 | removeComments: true,
304 | collapseWhitespace: true
305 | },
306 | files: [{
307 | expand: true, cwd: 'www/',
308 | src: '**/*.html', dest: '<%= cvars.dist_www %>/'
309 | }]
310 | }
311 | }
312 | });
313 |
314 |
315 | /* BASIC TASKS */
316 | grunt.registerTask('setup', [
317 | 'bower:setup',
318 | 'shell:webdriver-manager-update'
319 | ]);
320 | grunt.registerTask('genTestTemplates', [
321 | 'template:main-js','template:karma-js',
322 | 'template:main-min-js','template:karma-min-js'
323 | ]);
324 |
325 |
326 | /*
327 | Designed to be used during the dev and contains 2 distinct tests:
328 | - unit
329 | - unit-no-ngload
330 |
331 | The `grunt test` will kick off the `unit` test first, and after
332 | `ctrl-c` will kick off `unit-no-ngload` test. This is needed as
333 | it was dificult to load 2 different instance of angularAMD. The
334 | race condition was redering subsequent test with both ngload and
335 | no-ngload version unpredictable.
336 | */
337 | grunt.registerTask('test-base', [
338 | 'setup'
339 | ]);
340 | grunt.registerTask('test-unit', [
341 | 'test-base',
342 | 'genTestTemplates',
343 | 'karma:unit',
344 | 'karma:unit-no-ngload'
345 | ]);
346 | grunt.registerTask('test-e2e', [
347 | 'test-base',
348 | 'setup-www',
349 | 'connect:e2e-www',
350 | 'protractor:e2e-www'
351 | ]);
352 |
353 |
354 | /* Done with dev, build it by creating a minified version */
355 | grunt.registerTask('build', [
356 | 'setup',
357 | 'genTestTemplates',
358 | 'karma:build',
359 | 'uglify:build',
360 | 'concat:build',
361 | 'karma:build-min'
362 | ]);
363 | grunt.registerTask('build-travis', [
364 | 'setup',
365 | 'genTestTemplates',
366 | 'uglify:build',
367 | 'concat:build',
368 | 'karma:build-travis',
369 | 'setup-www',
370 | 'connect:e2e-www'
371 | // 'protractor:build-travis'
372 | ]);
373 |
374 | /* Run sample website */
375 | grunt.registerTask('setup-www', ['copy:setup-www']);
376 | grunt.registerTask('serve-www', [
377 | 'setup-www', 'open',
378 | 'connect:serve-www'
379 | ]);
380 |
381 | /* Create github pages */
382 | grunt.registerTask('dist-www', [
383 | 'test-e2e',
384 | 'ngAnnotate:dist-www',
385 | 'cssmin:dist-www',
386 | 'uglify:dist-www',
387 | 'htmlmin:dist-www',
388 | 'copy:dist-www'
389 | ]);
390 |
391 | /* Update bower repository -- must run build manually before this */
392 | grunt.registerTask('dist-bower', [
393 | 'copy:dist-bower'
394 | ]);
395 |
396 | };
397 |
398 |
399 |
400 |
--------------------------------------------------------------------------------
/dist/angularAMD.js:
--------------------------------------------------------------------------------
1 | /*
2 | angularAMD v<%= cvars.proj_version %>
3 | (c) 2013-2014 Marcos Lin https://github.com/marcoslin/
4 | License: MIT
5 | */
6 |
7 | define(function () {
8 | 'use strict';
9 | var bootstrapped = false,
10 |
11 | // Used in .bootstrap
12 | app_name,
13 | orig_app,
14 | alt_app,
15 | run_injector,
16 | config_injector,
17 | app_cached_providers = {},
18 |
19 | // Used in setAlternateAngular(), alt_angular is set to become angular.module
20 | orig_angular,
21 | alt_angular,
22 |
23 | // Object that wrap the provider methods that enables lazy loading
24 | onDemandLoader = {},
25 | preBootstrapLoaderQueue = [],
26 |
27 | // Used in setAlternateAngular() and .processQueue
28 | alternate_modules = {},
29 | alternate_modules_tracker = {},
30 | alternate_queue = [];
31 |
32 | // Private method to check if angularAMD has been initialized
33 | function checkBootstrapped() {
34 | if ( !bootstrapped ) {
35 | throw new Error('angularAMD not initialized. Need to call angularAMD.bootstrap(app) first.');
36 | }
37 | }
38 |
39 | /**
40 | * Create an alternate angular so that subsequent call to angular.module will queue up
41 | * the module created for later processing via the .processQueue method.
42 | *
43 | * This delaying processing is needed as angular does not recognize any newly created
44 | * module after angular.bootstrap has ran. The only way to add new objects to angular
45 | * post bootstrap is using cached provider.
46 | *
47 | * Once the modules has been queued, processQueue would then use each module's _invokeQueue
48 | * and _runBlock to recreate object using cached $provider. In essence, creating a duplicate
49 | * object into the current ng-app. As result, if there are subsequent call to retrieve the
50 | * module post processQueue, it would retrieve a module that is not integrated into the ng-app.
51 | *
52 | * Therefore, any subsequent to call to angular.module after processQueue should return undefined
53 | * to prevent obtaining a duplicated object. However, it is critical that angular.module return
54 | * appropriate object *during* processQueue.
55 | */
56 | function setAlternateAngular() {
57 | // This method cannot be called more than once
58 | if (alt_angular) {
59 | throw new Error('setAlternateAngular can only be called once.');
60 | } else {
61 | alt_angular = {};
62 | }
63 |
64 | // Make sure that bootstrap has been called
65 | checkBootstrapped();
66 |
67 | // Create a a copy of orig_angular with on demand loading capability
68 | orig_angular.extend(alt_angular, orig_angular);
69 |
70 | // Custom version of angular.module used as cache
71 | alt_angular.module = function (name, requires) {
72 | if (typeof requires === 'undefined') {
73 | // Return module from alternate_modules if it was created using the alt_angular
74 | if (alternate_modules_tracker.hasOwnProperty(name)) {
75 | return alternate_modules[name];
76 | } else {
77 | return orig_angular.module(name);
78 | }
79 | } else {
80 | var orig_mod = orig_angular.module.apply(null, arguments),
81 | item = { name: name, module: orig_mod};
82 | alternate_queue.push(item);
83 | orig_angular.extend(orig_mod, onDemandLoader);
84 |
85 | /*
86 | Use `alternate_modules_tracker` to track which module has been created by alt_angular
87 | but use `alternate_modules` to cache the module created. This is to simplify the
88 | removal of cached modules after .processQueue.
89 | */
90 | alternate_modules_tracker[name] = true;
91 | alternate_modules[name] = orig_mod;
92 |
93 | // Return created module
94 | return orig_mod;
95 | }
96 | };
97 |
98 | window.angular = alt_angular;
99 |
100 | if (require.defined('angular')) {
101 | require.undef('angular');
102 | define('angular', [], alt_angular);
103 | }
104 | }
105 |
106 | // Constructor
107 | function AngularAMD() {}
108 |
109 |
110 | /**
111 | * Helper function to generate angular's $routeProvider.route. 'config' input param must be an object.
112 | *
113 | * Populate the resolve attribute using either 'controllerUrl' or 'controller'. If 'controllerUrl'
114 | * is passed, it will attempt to load the Url using requirejs and remove the attribute from the config
115 | * object. Otherwise, it will attempt to populate resolve by loading what's been passed in 'controller'.
116 | * If neither is passed, resolve is not populated.
117 | *
118 | * This function works as a pass-through, meaning what ever is passed in as 'config' will be returned,
119 | * except for 'controllerUrl' attribute.
120 | *
121 | */
122 | AngularAMD.prototype.route = function (config) {
123 | // Initialization not necessary to call this method.
124 | var load_controller;
125 |
126 | /*
127 | If `controllerUrl` is provided, load the provided Url using requirejs. If `controller` is not provided
128 | but `controllerUrl` is, assume that module to be loaded will return a function to act as controller.
129 |
130 | Otherwise, attempt to load the controller using the controller name. In the later case, controller name
131 | is expected to be defined as one of 'paths' in main.js.
132 | */
133 | if ( config.hasOwnProperty('controllerUrl') ) {
134 | load_controller = config.controllerUrl;
135 | delete config.controllerUrl;
136 | if (typeof config.controller === 'undefined') {
137 | // Only controllerUrl is defined. Attempt to set the controller to return value of package loaded.
138 | config.controller = [
139 | '$scope', '__AAMDCtrl', '$injector',
140 | function ($scope, __AAMDCtrl, $injector) {
141 | if (typeof __AAMDCtrl !== 'undefined' ) {
142 | $injector.invoke(__AAMDCtrl, this, { '$scope': $scope });
143 | }
144 | }
145 | ];
146 | }
147 | } else if (typeof config.controller === 'string') {
148 | load_controller = config.controller;
149 | }
150 |
151 | // If controller needs to be loaded, append to the resolve property
152 | if (load_controller) {
153 | var resolve = config.resolve || {};
154 | resolve['__AAMDCtrl'] = ['$q', '$rootScope', function ($q, $rootScope) { // jshint ignore:line
155 | var defer = $q.defer();
156 | require([load_controller], function (ctrl) {
157 | defer.resolve(ctrl);
158 | $rootScope.$apply();
159 | });
160 | return defer.promise;
161 | }];
162 | config.resolve = resolve;
163 | }
164 |
165 | return config;
166 | };
167 |
168 |
169 | /**
170 | * Expose name of the app that has been bootstrapped
171 | */
172 | AngularAMD.prototype.appname = function () {
173 | checkBootstrapped();
174 | return app_name;
175 | };
176 |
177 |
178 | /**
179 | * Recreate the modules created by alternate angular in ng-app using cached $provider.
180 | * As AMD loader does not guarantee the order of dependency in a require([...],...)
181 | * clause, user must make sure that dependecies are clearly setup in shim in order
182 | * for this to work.
183 | *
184 | * HACK ALERT:
185 | * This method relay on inner working of angular.module code, and access _invokeQueue
186 | * and _runBlock private variable. Must test carefully with each release of angular.
187 | *
188 | * As of AngularJS 1.3.x, there is new _configBlocks that get populated with configuration
189 | * blocks, thus replacing the need for "provider === '$injector' && method === 'invoke'"
190 | * logic.
191 | */
192 | AngularAMD.prototype.processQueue = function () {
193 | checkBootstrapped();
194 |
195 | if (typeof alt_angular === 'undefined') {
196 | throw new Error('Alternate angular not set. Make sure that `enable_ngload` option has been set when calling angularAMD.bootstrap');
197 | }
198 |
199 | // Process alternate queue in FIFO fashion
200 | function processRunBlock(block) {
201 | //console.info('"' + item.name + '": executing run block: ', run_block);
202 | run_injector.invoke(block);
203 | }
204 |
205 | // Process the config blocks
206 | for (var i=0;i 0) {
455 | for (var iq = 0; iq < preBootstrapLoaderQueue.length; iq += 1) {
456 | var item = preBootstrapLoaderQueue[iq];
457 | orig_app[item.recipe](item.name, item.constructor);
458 | }
459 | preBootstrapLoaderQueue = [];
460 | }
461 |
462 | // Create a app.register object to keep backward compatibility
463 | orig_app.register = onDemandLoader;
464 |
465 | // Bootstrap Angular
466 | orig_angular.element(document).ready(function () {
467 | orig_angular.bootstrap(elem, [app_name]);
468 | // Indicate bootstrap completed
469 | bootstrapped = true;
470 |
471 | // Replace angular.module
472 | if (enable_ngload) {
473 | //console.info('Setting alternate angular');
474 | setAlternateAngular();
475 | }
476 | });
477 |
478 | // Return app
479 | return alt_app;
480 | };
481 |
482 | // Define provider
483 | function executeProvider(providerRecipe) {
484 | return function (name, constructor) {
485 | if (bootstrapped) {
486 | onDemandLoader[providerRecipe](name, constructor);
487 | } else {
488 | // Queue up the request to be used during .bootstrap
489 | preBootstrapLoaderQueue.push({
490 | 'recipe': providerRecipe,
491 | 'name': name,
492 | 'constructor': constructor
493 | });
494 | }
495 | return this;
496 | };
497 | }
498 |
499 | // .provider
500 | AngularAMD.prototype.provider = executeProvider('provider');
501 | // .controller
502 | AngularAMD.prototype.controller = executeProvider('controller');
503 | // .directive
504 | AngularAMD.prototype.directive = executeProvider('directive');
505 | // .filter
506 | AngularAMD.prototype.filter = executeProvider('filter');
507 | // .factory
508 | AngularAMD.prototype.factory = executeProvider('factory');
509 | // .service
510 | AngularAMD.prototype.service = executeProvider('service');
511 | // .constant
512 | AngularAMD.prototype.constant = executeProvider('constant');
513 | // .value
514 | AngularAMD.prototype.value = executeProvider('value');
515 | // .animation
516 | AngularAMD.prototype.animation = executeProvider('animation');
517 | // .component
518 | AngularAMD.prototype.component = executeProvider('component');
519 |
520 | // Create a new instance and return
521 | return new AngularAMD();
522 |
523 | });
524 |
--------------------------------------------------------------------------------
/src/angularAMD.js:
--------------------------------------------------------------------------------
1 | /*
2 | angularAMD v<%= cvars.proj_version %>
3 | (c) 2013-2014 Marcos Lin https://github.com/marcoslin/
4 | License: MIT
5 | */
6 |
7 | define(function () {
8 | 'use strict';
9 | var bootstrapped = false,
10 |
11 | // Used in .bootstrap
12 | app_name,
13 | orig_app,
14 | alt_app,
15 | run_injector,
16 | config_injector,
17 | app_cached_providers = {},
18 |
19 | // Used in setAlternateAngular(), alt_angular is set to become angular.module
20 | orig_angular,
21 | alt_angular,
22 |
23 | // Object that wrap the provider methods that enables lazy loading
24 | onDemandLoader = {},
25 | preBootstrapLoaderQueue = [],
26 |
27 | // Used in setAlternateAngular() and .processQueue
28 | alternate_modules = {},
29 | alternate_modules_tracker = {},
30 | alternate_queue = [];
31 |
32 | // Private method to check if angularAMD has been initialized
33 | function checkBootstrapped() {
34 | if ( !bootstrapped ) {
35 | throw new Error('angularAMD not initialized. Need to call angularAMD.bootstrap(app) first.');
36 | }
37 | }
38 |
39 | /**
40 | * Create an alternate angular so that subsequent call to angular.module will queue up
41 | * the module created for later processing via the .processQueue method.
42 | *
43 | * This delaying processing is needed as angular does not recognize any newly created
44 | * module after angular.bootstrap has ran. The only way to add new objects to angular
45 | * post bootstrap is using cached provider.
46 | *
47 | * Once the modules has been queued, processQueue would then use each module's _invokeQueue
48 | * and _runBlock to recreate object using cached $provider. In essence, creating a duplicate
49 | * object into the current ng-app. As result, if there are subsequent call to retrieve the
50 | * module post processQueue, it would retrieve a module that is not integrated into the ng-app.
51 | *
52 | * Therefore, any subsequent to call to angular.module after processQueue should return undefined
53 | * to prevent obtaining a duplicated object. However, it is critical that angular.module return
54 | * appropriate object *during* processQueue.
55 | */
56 | function setAlternateAngular() {
57 | // This method cannot be called more than once
58 | if (alt_angular) {
59 | throw new Error('setAlternateAngular can only be called once.');
60 | } else {
61 | alt_angular = {};
62 | }
63 |
64 | // Make sure that bootstrap has been called
65 | checkBootstrapped();
66 |
67 | // Create a a copy of orig_angular with on demand loading capability
68 | orig_angular.extend(alt_angular, orig_angular);
69 |
70 | // Custom version of angular.module used as cache
71 | alt_angular.module = function (name, requires) {
72 | if (typeof requires === 'undefined') {
73 | // Return module from alternate_modules if it was created using the alt_angular
74 | if (alternate_modules_tracker.hasOwnProperty(name)) {
75 | return alternate_modules[name];
76 | } else {
77 | return orig_angular.module(name);
78 | }
79 | } else {
80 | var orig_mod = orig_angular.module.apply(null, arguments),
81 | item = { name: name, module: orig_mod};
82 | alternate_queue.push(item);
83 | orig_angular.extend(orig_mod, onDemandLoader);
84 |
85 | /*
86 | Use `alternate_modules_tracker` to track which module has been created by alt_angular
87 | but use `alternate_modules` to cache the module created. This is to simplify the
88 | removal of cached modules after .processQueue.
89 | */
90 | alternate_modules_tracker[name] = true;
91 | alternate_modules[name] = orig_mod;
92 |
93 | // Return created module
94 | return orig_mod;
95 | }
96 | };
97 |
98 | window.angular = alt_angular;
99 |
100 | if (require.defined('angular')) {
101 | require.undef('angular');
102 | define('angular', [], alt_angular);
103 | }
104 | }
105 |
106 | // Constructor
107 | function AngularAMD() {}
108 |
109 |
110 | /**
111 | * Helper function to generate angular's $routeProvider.route. 'config' input param must be an object.
112 | *
113 | * Populate the resolve attribute using either 'controllerUrl' or 'controller'. If 'controllerUrl'
114 | * is passed, it will attempt to load the Url using requirejs and remove the attribute from the config
115 | * object. Otherwise, it will attempt to populate resolve by loading what's been passed in 'controller'.
116 | * If neither is passed, resolve is not populated.
117 | *
118 | * This function works as a pass-through, meaning what ever is passed in as 'config' will be returned,
119 | * except for 'controllerUrl' attribute.
120 | *
121 | */
122 | AngularAMD.prototype.route = function (config) {
123 | // Initialization not necessary to call this method.
124 | var load_controller;
125 |
126 | /*
127 | If `controllerUrl` is provided, load the provided Url using requirejs. If `controller` is not provided
128 | but `controllerUrl` is, assume that module to be loaded will return a function to act as controller.
129 |
130 | Otherwise, attempt to load the controller using the controller name. In the later case, controller name
131 | is expected to be defined as one of 'paths' in main.js.
132 | */
133 | if ( config.hasOwnProperty('controllerUrl') ) {
134 | load_controller = config.controllerUrl;
135 | delete config.controllerUrl;
136 | if (typeof config.controller === 'undefined') {
137 | // Only controllerUrl is defined. Attempt to set the controller to return value of package loaded.
138 | config.controller = [
139 | '$scope', '__AAMDCtrl', '$injector',
140 | function ($scope, __AAMDCtrl, $injector) {
141 | if (typeof __AAMDCtrl !== 'undefined' ) {
142 | $injector.invoke(__AAMDCtrl, this, { '$scope': $scope });
143 | }
144 | }
145 | ];
146 | }
147 | } else if (typeof config.controller === 'string') {
148 | load_controller = config.controller;
149 | }
150 |
151 | // If controller needs to be loaded, append to the resolve property
152 | if (load_controller) {
153 | var resolve = config.resolve || {};
154 | resolve['__AAMDCtrl'] = ['$q', '$rootScope', function ($q, $rootScope) { // jshint ignore:line
155 | var defer = $q.defer();
156 | require([load_controller], function (ctrl) {
157 | defer.resolve(ctrl);
158 | $rootScope.$apply();
159 | });
160 | return defer.promise;
161 | }];
162 | config.resolve = resolve;
163 | }
164 |
165 | return config;
166 | };
167 |
168 |
169 | /**
170 | * Expose name of the app that has been bootstrapped
171 | */
172 | AngularAMD.prototype.appname = function () {
173 | checkBootstrapped();
174 | return app_name;
175 | };
176 |
177 |
178 | /**
179 | * Recreate the modules created by alternate angular in ng-app using cached $provider.
180 | * As AMD loader does not guarantee the order of dependency in a require([...],...)
181 | * clause, user must make sure that dependecies are clearly setup in shim in order
182 | * for this to work.
183 | *
184 | * HACK ALERT:
185 | * This method relay on inner working of angular.module code, and access _invokeQueue
186 | * and _runBlock private variable. Must test carefully with each release of angular.
187 | *
188 | * As of AngularJS 1.3.x, there is new _configBlocks that get populated with configuration
189 | * blocks, thus replacing the need for "provider === '$injector' && method === 'invoke'"
190 | * logic.
191 | */
192 | AngularAMD.prototype.processQueue = function () {
193 | checkBootstrapped();
194 |
195 | if (typeof alt_angular === 'undefined') {
196 | throw new Error('Alternate angular not set. Make sure that `enable_ngload` option has been set when calling angularAMD.bootstrap');
197 | }
198 |
199 | // Process alternate queue in FIFO fashion
200 | function processRunBlock(block) {
201 | //console.info('"' + item.name + '": executing run block: ', run_block);
202 | run_injector.invoke(block);
203 | }
204 |
205 | // Process the config blocks
206 | for (var i=0;i 0) {
455 | for (var iq = 0; iq < preBootstrapLoaderQueue.length; iq += 1) {
456 | var item = preBootstrapLoaderQueue[iq];
457 | orig_app[item.recipe](item.name, item.constructor);
458 | }
459 | preBootstrapLoaderQueue = [];
460 | }
461 |
462 | // Create a app.register object to keep backward compatibility
463 | orig_app.register = onDemandLoader;
464 |
465 | // Bootstrap Angular
466 | orig_angular.element(document).ready(function () {
467 | orig_angular.bootstrap(elem, [app_name]);
468 | // Indicate bootstrap completed
469 | bootstrapped = true;
470 |
471 | // Replace angular.module
472 | if (enable_ngload) {
473 | //console.info('Setting alternate angular');
474 | setAlternateAngular();
475 | }
476 | });
477 |
478 | // Return app
479 | return alt_app;
480 | };
481 |
482 | // Define provider
483 | function executeProvider(providerRecipe) {
484 | return function (name, constructor) {
485 | if (bootstrapped) {
486 | onDemandLoader[providerRecipe](name, constructor);
487 | } else {
488 | // Queue up the request to be used during .bootstrap
489 | preBootstrapLoaderQueue.push({
490 | 'recipe': providerRecipe,
491 | 'name': name,
492 | 'constructor': constructor
493 | });
494 | }
495 | return this;
496 | };
497 | }
498 |
499 | // .provider
500 | AngularAMD.prototype.provider = executeProvider('provider');
501 | // .controller
502 | AngularAMD.prototype.controller = executeProvider('controller');
503 | // .directive
504 | AngularAMD.prototype.directive = executeProvider('directive');
505 | // .filter
506 | AngularAMD.prototype.filter = executeProvider('filter');
507 | // .factory
508 | AngularAMD.prototype.factory = executeProvider('factory');
509 | // .service
510 | AngularAMD.prototype.service = executeProvider('service');
511 | // .constant
512 | AngularAMD.prototype.constant = executeProvider('constant');
513 | // .value
514 | AngularAMD.prototype.value = executeProvider('value');
515 | // .animation
516 | AngularAMD.prototype.animation = executeProvider('animation');
517 | // .component
518 | AngularAMD.prototype.component = executeProvider('component');
519 |
520 | // Create a new instance and return
521 | return new AngularAMD();
522 |
523 | });
524 |
--------------------------------------------------------------------------------