diff --git a/angularFiles.js b/angularFiles.js index 37dff5c05028..2a102a18b1e0 100644 --- a/angularFiles.js +++ b/angularFiles.js @@ -1,28 +1,33 @@ angularFiles = { 'angularSrc': [ 'src/Angular.js', + 'src/AngularPublic.js', 'src/JSON.js', - 'src/Compiler.js', - 'src/Scope.js', 'src/Injector.js', - 'src/parser.js', 'src/Resource.js', - 'src/Browser.js', 'src/sanitizer.js', 'src/jqLite.js', 'src/apis.js', - 'src/filters.js', + 'src/service/browser.js', + 'src/service/compiler.js', 'src/service/cookieStore.js', 'src/service/cookies.js', 'src/service/defer.js', 'src/service/document.js', 'src/service/exceptionHandler.js', + 'src/service/filter.js', + 'src/service/filter/filter.js', + 'src/service/filter/filters.js', + 'src/service/filter/limitTo.js', + 'src/service/filter/orderBy.js', 'src/service/formFactory.js', 'src/service/location.js', 'src/service/log.js', 'src/service/resource.js', + 'src/service/parse.js', 'src/service/route.js', 'src/service/routeParams.js', + 'src/service/scope.js', 'src/service/sniffer.js', 'src/service/window.js', 'src/service/xhr.bulk.js', @@ -35,8 +40,7 @@ angularFiles = { 'src/widgets.js', 'src/widget/form.js', 'src/widget/input.js', - 'src/widget/select.js', - 'src/AngularPublic.js' + 'src/widget/select.js' ], 'angularScenario': [ @@ -70,12 +74,12 @@ angularFiles = { 'src/jstd-scenario-adapter/*.js', 'src/scenario/*.js', 'src/angular-mocks.js', - 'test/mocks.js', 'test/scenario/*.js', 'test/scenario/output/*.js', 'test/jstd-scenario-adapter/*.js', 'test/*.js', 'test/service/*.js', + 'test/service/filter/*.js', 'test/widget/*.js', 'example/personalLog/test/*.js' ], @@ -83,8 +87,7 @@ angularFiles = { 'jstdExclude': [ 'test/jquery_alias.js', 'src/angular-bootstrap.js', - 'src/scenario/angular-bootstrap.js', - 'src/AngularPublic.js' + 'src/scenario/angular-bootstrap.js' ], 'jstdScenario': [ @@ -115,8 +118,7 @@ angularFiles = { 'jstdPerfExclude': [ 'src/angular-bootstrap.js', - 'src/scenario/angular-bootstrap.js', - 'src/AngularPublic.js' + 'src/scenario/angular-bootstrap.js' ], 'jstdJquery': [ @@ -133,7 +135,6 @@ angularFiles = { 'src/jstd-scenario-adapter/*.js', 'src/scenario/*.js', 'src/angular-mocks.js', - 'test/mocks.js', 'test/scenario/*.js', 'test/scenario/output/*.js', 'test/jstd-scenario-adapter/*.js', @@ -145,7 +146,6 @@ angularFiles = { 'jstdJqueryExclude': [ 'src/angular-bootstrap.js', - 'src/AngularPublic.js', 'src/scenario/angular-bootstrap.js', 'test/jquery_remove.js' ] diff --git a/css/angular.css b/css/angular.css index 8b55f7849051..0c90b569411d 100644 --- a/css/angular.css +++ b/css/angular.css @@ -4,10 +4,6 @@ display: none; } -.ng-format-negative { - color: red; -} - ng\:form { display: block; } diff --git a/docs/content/api/angular.module.ng.ngdoc b/docs/content/api/angular.module.ng.ngdoc new file mode 100644 index 000000000000..2ac39e5602fd --- /dev/null +++ b/docs/content/api/angular.module.ng.ngdoc @@ -0,0 +1,5 @@ +@ngdoc overview +@name angular.module.ng +@description + +The `ng` is an angular module which contains all of the core angular services. diff --git a/docs/content/api/angular.module.ngdoc b/docs/content/api/angular.module.ngdoc new file mode 100644 index 000000000000..ccfec6b79496 --- /dev/null +++ b/docs/content/api/angular.module.ngdoc @@ -0,0 +1,54 @@ +@ngdoc overview +@name angular.module +@description + +The angular.module namespace is a global place for registering angular modules. All modules +(angular core or 3rd party) that should be available to an application must be registered in this +namespace. + +# Module + +A module is a function that is used to register new service providers and configure existing +providers. Once a provider is registered, {@link angular.module.AUTO.$injector $injector} will use +it to ask for a service instance when it is resolving a dependency for the first time. + +
+// Declare the module configuration function.
+// The function arguments are fully injectable so that the module function
+// can create new providers or configure existing ones.
+function MyModule($provide, $locationProvider){
+  // see $provide for more information.
+  $provide.value('appName', 'MyCoolApp');
+
+  // Configure existing providers
+  $locationProvider.hashPrefix = '!';
+};
+
+ +See: {@link angular.module.AUTO.$provide $provide}, {@link angular.module.ng.$locationProvider $locationProvider}. + +# Registering Module Function + +In your JavaScript file: +
+// Create the angular.module namespace if one does not exist
+// This allows the module code to be loaded before angular.js code.
+if (!window.angular) window.angular = {};
+if (!angular.module) angular.module = {};
+
+angular.module.MyModule = function(){
+  // add configuration code here.
+};
+
+ +Then you can refer to your module like this: + +
+var injector = angular.injector('ng', 'MyModule')
+
+ +Or + +
+var injector = angular.injector('ng', angular.module.MyModule)
+
diff --git a/docs/content/api/angular.service.ngdoc b/docs/content/api/angular.service.ngdoc deleted file mode 100644 index 02d689f2bc85..000000000000 --- a/docs/content/api/angular.service.ngdoc +++ /dev/null @@ -1,25 +0,0 @@ -@ngdoc overview -@name angular.service -@description - -The services API provides objects for carrying out common web app tasks. Service objects are -managed by angular's {@link guide/dev_guide.di dependency injection system}. - -* {@link angular.service.$browser $browser } - Provides an instance of a browser object -* {@link angular.service.$cookieStore $cookieStore } - Provides key / value storage backed by -session cookies -* {@link angular.service.$cookies $cookies } - Provides read / write access to browser cookies -* {@link angular.service.$defer $defer } - Defers function execution and try / catch block -* {@link angular.service.$document $document } - Provides reference to `window.document` element -* {@link angular.service.$exceptionHandler $exceptionHandler } - Receives uncaught angular -exceptions -* {@link angular.service.$location $location } - Parses the browser location URL -* {@link angular.service.$log $log } - Provides logging service -* {@link angular.service.$resource $resource } - Creates objects for interacting with RESTful -server-side data sources -* {@link angular.service.$route $route } - Provides deep-linking services -* {@link angular.service.$window $window } - References the browsers `window` object -* {@link angular.service.$xhr $xhr} - Generates an XHR request. - -For information on how angular services work and how to write your own services, see {@link -guide/dev_guide.services Angular Services} in the angular Developer Guide. diff --git a/docs/content/api/index.ngdoc b/docs/content/api/index.ngdoc index f48a2b385753..ccacef80a964 100644 --- a/docs/content/api/index.ngdoc +++ b/docs/content/api/index.ngdoc @@ -7,23 +7,23 @@ * {@link angular.widget Widgets} - Angular custom DOM element * {@link angular.directive Directives} - Angular DOM element attributes * {@link angular.markup Markup} and {@link angular.attrMarkup Attribute Markup} -* {@link angular.filter Filters} - Angular output filters -* {@link angular.compile angular.compile()} - Template compiler +* {@link angular.module.ng.$filter Filters} - Angular output filters +* {@link angular.module.ng.$compile $compile} - Template compiler ## Angular Scope API -* {@link angular.scope Scope Object} - Angular scope object +* {@link angular.module.ng.$rootScope.Scope Scope Object} - Angular scope object ## Angular Services & Dependency Injection API -* {@link angular.service Angular Services} +* {@link angular.module.ng Angular Services} * {@link angular.injector angular.injector() } ## Angular Testing API -* {@link angular.mock Testing Mocks API} - Mock objects for testing +* {@link angular.module.ngMock Testing Mocks API} - Mock objects for testing * {@link guide/dev_guide.e2e-testing Angular Scenario Runner} - Automated scenario testing documentation @@ -63,9 +63,3 @@ documentation * {@link angular.fromJson angular.fromJson() } * {@link angular.toJson angular.toJson() } - - - -## Utility methods for JavaScript types -* {@link angular.Object Object API} - Utility functions for JavaScript objects -* {@link angular.Array Array API} - Utility functions for JavaScript arrays diff --git a/docs/content/cookbook/advancedform.ngdoc b/docs/content/cookbook/advancedform.ngdoc index 19b8284f1dcd..e973e30feeab 100644 --- a/docs/content/cookbook/advancedform.ngdoc +++ b/docs/content/cookbook/advancedform.ngdoc @@ -34,7 +34,28 @@ detection, and preventing invalid form submission. save: function() { this.master = this.form; this.cancel(); + }, + + addContact: function() { + this.form.contacts.push({type:'', value:''}); + }, + + removeContact: function(contact) { + for ( var i = 0, ii = this.form.contacts.length; i < ii; i++) { + if (contact === this.form.contacts[i]) { + this.form.contacts.splice(i, 1); + } + } + }, + + isCancelDisabled: function() { + return angular.equals(this.master, this.form); + }, + + isSaveDisabled: function() { + return this.myForm.$invalid || angular.equals(this.master, this.form); } + };
@@ -53,7 +74,7 @@ detection, and preventing invalid form submission. ng:pattern="zip" required/>

- [ add ] + [ add ]
- [ X ] + [ X ]
- - + +
diff --git a/docs/content/cookbook/deeplinking.ngdoc b/docs/content/cookbook/deeplinking.ngdoc index 27087726d7aa..2ef3da4a65e0 100644 --- a/docs/content/cookbook/deeplinking.ngdoc +++ b/docs/content/cookbook/deeplinking.ngdoc @@ -105,9 +105,9 @@ The two partials are defined in the following URLs: # Things to notice * Routes are defined in the `AppCntl` class. The initialization of the controller causes the - initialization of the {@link api/angular.service.$route $route} service with the proper URL + initialization of the {@link api/angular.module.ng.$route $route} service with the proper URL routes. -* The {@link api/angular.service.$route $route} service then watches the URL and instantiates the +* The {@link api/angular.module.ng.$route $route} service then watches the URL and instantiates the appropriate controller when the URL changes. * The {@link api/angular.widget.ng:view ng:view} widget loads the view when the URL changes. It also diff --git a/docs/content/cookbook/form.ngdoc b/docs/content/cookbook/form.ngdoc index 6cd1d83aae05..80c23e942cff 100644 --- a/docs/content/cookbook/form.ngdoc +++ b/docs/content/cookbook/form.ngdoc @@ -18,6 +18,18 @@ allow a user to enter data. }; this.state = /^\w\w$/; this.zip = /^\d\d\d\d\d$/; + + this.addContact = function() { + this.user.contacts.push({type:'', value:''}); + }; + + this.removeContact = function(contact) { + for ( var i = 0, ii = this.user.contacts.length; i < ii; i++) { + if (contact === this.user.contacts[i]) { + this.user.contacts.splice(i, 1); + } + } + }; }
@@ -34,7 +46,7 @@ allow a user to enter data. ng:pattern="zip" required>

- [ add ] + [ add ]
- [ X ] + [ X ]

Debug View: @@ -92,7 +104,7 @@ allow a user to enter data. * The user data model is initialized {@link api/angular.directive.ng:controller controller} and is available in - the {@link api/angular.scope scope} with the initial data. + the {@link api/angular.module.ng.$rootScope.Scope scope} with the initial data. * For debugging purposes we have included a debug view of the model to better understand what is going on. * The {@link api/angular.widget.input input widgets} simply refer to the model and are data-bound. diff --git a/docs/content/cookbook/helloworld.ngdoc b/docs/content/cookbook/helloworld.ngdoc index c93cdbea0ed0..e3d76d836f7e 100644 --- a/docs/content/cookbook/helloworld.ngdoc +++ b/docs/content/cookbook/helloworld.ngdoc @@ -31,7 +31,7 @@ Take a look through the source and note: * The script tag that {@link guide/dev_guide.bootstrap bootstraps} the angular environment. * The text {@link api/angular.widget.input input widget} which is bound to the greeting name text. * No need for listener registration and event firing on change events. -* The implicit presence of the `name` variable which is in the root {@link api/angular.scope scope}. +* The implicit presence of the `name` variable which is in the root {@link api/angular.module.ng.$rootScope.Scope scope}. * The double curly brace `{{markup}}`, which binds the name variable to the greeting text. * The concept of {@link guide/dev_guide.templates.databinding data binding}, which reflects any changes to the diff --git a/docs/content/cookbook/index.ngdoc b/docs/content/cookbook/index.ngdoc index 06b898acf887..43ac9bb20fa7 100644 --- a/docs/content/cookbook/index.ngdoc +++ b/docs/content/cookbook/index.ngdoc @@ -44,7 +44,7 @@ allowing you to send links to specific screens in your app. # Services -{@link api/angular.service Services}: Services are long lived objects in your applications that are +{@link api/angular.module.ng Services}: Services are long lived objects in your applications that are available across controllers. A collection of useful services are pre-bundled with angular but you will likely add your own. Services are initialized using dependency injection, which resolves the order of initialization. This safeguards you from the perils of global state (a common way to diff --git a/docs/content/cookbook/mvc.ngdoc b/docs/content/cookbook/mvc.ngdoc index 28b8836f0c85..f566a541b13a 100644 --- a/docs/content/cookbook/mvc.ngdoc +++ b/docs/content/cookbook/mvc.ngdoc @@ -121,4 +121,4 @@ board variable. * The view can call any controller function. * In this example, the `setUrl()` and `readUrl()` functions copy the game state to/from the URL's hash so the browser's back button will undo game steps. See deep-linking. This example calls {@link -api/angular.scope.$watch $watch()} to set up a listener that invokes `readUrl()` when needed. +api/angular.module.ng.$rootScope.Scope#$watch $watch()} to set up a listener that invokes `readUrl()` when needed. diff --git a/docs/content/guide/dev_guide.bootstrap.auto_bootstrap.ngdoc b/docs/content/guide/dev_guide.bootstrap.auto_bootstrap.ngdoc index 438b3d3889ad..d461bfb41635 100644 --- a/docs/content/guide/dev_guide.bootstrap.auto_bootstrap.ngdoc +++ b/docs/content/guide/dev_guide.bootstrap.auto_bootstrap.ngdoc @@ -98,4 +98,4 @@ APIs are bound to fields of this global object. ## Related API -{@link api/angular.compile Compiler API} +{@link api/angular.module.ng.$compile Compiler API} diff --git a/docs/content/guide/dev_guide.bootstrap.manual_bootstrap.ngdoc b/docs/content/guide/dev_guide.bootstrap.manual_bootstrap.ngdoc index 1adbb0d23cc5..c042b2e31529 100644 --- a/docs/content/guide/dev_guide.bootstrap.manual_bootstrap.ngdoc +++ b/docs/content/guide/dev_guide.bootstrap.manual_bootstrap.ngdoc @@ -17,7 +17,7 @@ explicitly. @@ -31,7 +31,7 @@ This is the sequence that your code should follow if you bootstrap angular on yo 1. After the page is loaded, find the root of the HTML template, which is typically the root of the document. -2. Run angular's {@link dev_guide.compiler Angular HTML compiler}, which converts a template into +2. Call {@link api/angular.bootstrap} to {@link dev_guide.compiler compile} the template into an executable, bi-directionally bound application. @@ -43,4 +43,4 @@ an executable, bi-directionally bound application. ## Related API -{@link api/angular.compile Compiler API} +{@link api/angular.module.ng.$compile Compiler API} diff --git a/docs/content/guide/dev_guide.compiler.directives.creating_directives.ngdoc b/docs/content/guide/dev_guide.compiler.directives.creating_directives.ngdoc index c9384835205a..2d6723cf11d4 100644 --- a/docs/content/guide/dev_guide.compiler.directives.creating_directives.ngdoc +++ b/docs/content/guide/dev_guide.compiler.directives.creating_directives.ngdoc @@ -23,7 +23,7 @@ angular.directive('ng:bind', function(expression, compiledElement) { The angular compiler exposes methods that you may need to use when writing your own widgets and directives. For example, the `descend()` method lets you control whether the compiler ignores or processes child elements of the element it is compiling. For information on this and other -compiler methods, see the {@link api/angular.compile Compiler API doc}. +compiler methods, see the {@link api/angular.module.ng.$compile Compiler API doc}. ## Related Docs diff --git a/docs/content/guide/dev_guide.compiler.extending_compiler.ngdoc b/docs/content/guide/dev_guide.compiler.extending_compiler.ngdoc index 831b288028be..90c7f5e2d812 100644 --- a/docs/content/guide/dev_guide.compiler.extending_compiler.ngdoc +++ b/docs/content/guide/dev_guide.compiler.extending_compiler.ngdoc @@ -93,4 +93,4 @@ corresponding spans. ## Related API -* {@link api/angular.compile angular.compile()} +* {@link api/angular.module.ng.$compile $compile()} diff --git a/docs/content/guide/dev_guide.compiler.markup.ngdoc b/docs/content/guide/dev_guide.compiler.markup.ngdoc index ba28f27522b3..0a01da57c0d8 100644 --- a/docs/content/guide/dev_guide.compiler.markup.ngdoc +++ b/docs/content/guide/dev_guide.compiler.markup.ngdoc @@ -89,4 +89,4 @@ angular.attrMarkup('extraClass', function(attrValue, attrName, element){ ## Related API -* {@link api/angular.compile Compiler API Reference} +* {@link api/angular.module.ng.$compile Compiler API Reference} diff --git a/docs/content/guide/dev_guide.compiler.ngdoc b/docs/content/guide/dev_guide.compiler.ngdoc index 8f616c1af43a..2789c84369b7 100644 --- a/docs/content/guide/dev_guide.compiler.ngdoc +++ b/docs/content/guide/dev_guide.compiler.ngdoc @@ -23,4 +23,4 @@ All compilation takes place in the web browser; no server is involved. ## Related API -* {@link api/angular.compile Angular Compiler API} +* {@link api/angular.module.ng.$compile Angular Compiler API} diff --git a/docs/content/guide/dev_guide.compiler.testing_dom_element.ngdoc b/docs/content/guide/dev_guide.compiler.testing_dom_element.ngdoc index ac6421f31bf6..e077bf4db534 100644 --- a/docs/content/guide/dev_guide.compiler.testing_dom_element.ngdoc +++ b/docs/content/guide/dev_guide.compiler.testing_dom_element.ngdoc @@ -14,4 +14,4 @@ ## Related API -* {@link api/angular.compile angular.compile()} +* {@link api/angular.module.ng.$compile $compile()} diff --git a/docs/content/guide/dev_guide.compiler.understanding_compiler.ngdoc b/docs/content/guide/dev_guide.compiler.understanding_compiler.ngdoc index b76e53799f82..94bab26da6e3 100644 --- a/docs/content/guide/dev_guide.compiler.understanding_compiler.ngdoc +++ b/docs/content/guide/dev_guide.compiler.understanding_compiler.ngdoc @@ -20,7 +20,7 @@ dataset]"`), the link function gets called to set up a listener on each element Note that angular's built-in widgets, directives, and markup have predefined compile and link functions that you don't need to modify. When you create your own widgets, directives, or markup, -you must write compile and link functions for them. Refer to the {@link api/angular.compile +you must write compile and link functions for them. Refer to the {@link api/angular.module.ng.$compile Compiler API} for details. When the angular compiler compiles a page, it proceeds through 3 phases: Compile, Create Root @@ -53,7 +53,7 @@ Note that while the compile function is executed exactly once, the link function multiple times, for example, once for each iteration in a repeater. The angular compiler exposes methods that you will need to make use of when writing your own -widgets and directives. For information on these methods, see the {@link api/angular.compile +widgets and directives. For information on these methods, see the {@link api/angular.module.ng.$compile Compiler API doc}. @@ -65,4 +65,4 @@ Compiler API doc}. ## Related API -* {@link api/angular.compile angular.compile()} +* {@link api/angular.module.ng.$compile $compile()} diff --git a/docs/content/guide/dev_guide.compiler.widgets.creating_widgets.ngdoc b/docs/content/guide/dev_guide.compiler.widgets.creating_widgets.ngdoc index 838bead452ef..312f40000b24 100644 --- a/docs/content/guide/dev_guide.compiler.widgets.creating_widgets.ngdoc +++ b/docs/content/guide/dev_guide.compiler.widgets.creating_widgets.ngdoc @@ -80,7 +80,7 @@ angular.widget('my:time', function(compileElement){ The angular compiler exposes methods that you may need to use of when writing your own widgets and directives. For example, the `descend()` method lets you control whether the compiler ignores or processes child elements of the element it is compiling. For information on this and other -compiler methods, see the {@link api/angular.compile Compiler API doc}. +compiler methods, see the {@link api/angular.module.ng.$compile Compiler API doc}. ## Related Topics @@ -92,4 +92,4 @@ compiler methods, see the {@link api/angular.compile Compiler API doc}. ## Related API -* {@link api/angular.compile Compiler API} +* {@link api/angular.module.ng.$compile Compiler API} diff --git a/docs/content/guide/dev_guide.compiler.widgets.ngdoc b/docs/content/guide/dev_guide.compiler.widgets.ngdoc index 542dec8de47d..003cba537ab9 100644 --- a/docs/content/guide/dev_guide.compiler.widgets.ngdoc +++ b/docs/content/guide/dev_guide.compiler.widgets.ngdoc @@ -32,4 +32,4 @@ dev_guide.compiler.widgets.creating_widgets Creating Custom Widgets}. ## Related API -* {@link api/angular.compile Compiler API} +* {@link api/angular.module.ng.$compile Compiler API} diff --git a/docs/content/guide/dev_guide.di.ngdoc b/docs/content/guide/dev_guide.di.ngdoc index fc303e58354f..b21b05a75e32 100644 --- a/docs/content/guide/dev_guide.di.ngdoc +++ b/docs/content/guide/dev_guide.di.ngdoc @@ -28,5 +28,5 @@ book. ## Related API -* {@link api/angular.service Service API} +* {@link api/angular.module.ng Service API} * {@link api/angular.injector Angular Injector API} diff --git a/docs/content/guide/dev_guide.di.understanding_di.ngdoc b/docs/content/guide/dev_guide.di.understanding_di.ngdoc index 202fa3c6e934..4c40ff203da3 100644 --- a/docs/content/guide/dev_guide.di.understanding_di.ngdoc +++ b/docs/content/guide/dev_guide.di.understanding_di.ngdoc @@ -7,15 +7,15 @@ While DI is widely used in statically typed languages such as Java or C++, it ha used in JavaScript. Angular brings the benefits of DI into JavaScript apps. In angular, DI is implemented as a subsystem that manages dependencies between services, -controllers, widgets, and filters. The most important of these are {@link api/angular.service +controllers, widgets, and filters. The most important of these are {@link api/angular.module.ng services}. Services are objects that handle common tasks in web applications. Angular provides several{@link -api/angular.service built-in services}, and you can create your own custom services. +api/angular.module.ng built-in services}, and you can create your own custom services. The main job of angular's DI subsystem is to provide services to angular components that depend on them. The way the DI subsystem provides services is as follows: all services are registered with -angular's {@link api/angular.service service API}, and all components that depend on services +angular's {@link api/angular.module.ng service API}, and all components that depend on services define those dependencies as a property (`$inject`). With this information, the DI subsystem manages the creation of service objects and the provision of those objects to the components that need them, at the time they need them. The following illustration steps through the sequence of @@ -49,7 +49,7 @@ achieve the necessary isolation by having each test create its own separate root
 // create a root scope
-var rootScope = angular.scope();
+var rootScope = angular.module.ng.$rootScope.Scope();
 // access the service locator
 var myService = rootScope.$service('myService');
 
@@ -74,7 +74,7 @@ equivalent:
 // given a user defined service
-angular.service('serviceA', ...);
+angular.module.ng('serviceA', ...);
 
 // inject '$window', 'serviceA', curry 'name';
 function fnA($window, serviceA, name){};
@@ -102,4 +102,4 @@ code and insert the `$inject` into the source code so that it can be minified/ob
 
 ## Related API
 
-* {@link api/angular.service Services API}
+* {@link api/angular.module.ng Services API}
diff --git a/docs/content/guide/dev_guide.di.using_di_controllers.ngdoc b/docs/content/guide/dev_guide.di.using_di_controllers.ngdoc
index 035d166384b7..fc27a5fda73c 100644
--- a/docs/content/guide/dev_guide.di.using_di_controllers.ngdoc
+++ b/docs/content/guide/dev_guide.di.using_di_controllers.ngdoc
@@ -14,7 +14,7 @@ MyController.$inject = ['$route'];
 
In this example, the `MyController` constructor function takes one argument, the {@link -api/angular.service.$route $route} service. Angular is then responsible for supplying the instance +api/angular.module.ng.$route $route} service. Angular is then responsible for supplying the instance of `$route` to the controller when the constructor is instantiated. There are two ways to cause controller instantiation – by configuring routes with the `$route` service, or by referencing the controller from the HTML template, as follows: diff --git a/docs/content/guide/dev_guide.e2e-testing.ngdoc b/docs/content/guide/dev_guide.e2e-testing.ngdoc index d725e07a5d93..2cb82416fe51 100644 --- a/docs/content/guide/dev_guide.e2e-testing.ngdoc +++ b/docs/content/guide/dev_guide.e2e-testing.ngdoc @@ -78,19 +78,19 @@ Returns the window.location.search of the currently loaded page in the test fram Returns the window.location.hash (without `#`) of the currently loaded page in the test frame. ## browser().location().url() -Returns the {@link api/angular.service.$location $location.url()} of the currently loaded page in +Returns the {@link api/angular.module.ng.$location $location.url()} of the currently loaded page in the test frame. ## browser().location().path() -Returns the {@link api/angular.service.$location $location.path()} of the currently loaded page in +Returns the {@link api/angular.module.ng.$location $location.path()} of the currently loaded page in the test frame. ## browser().location().search() -Returns the {@link api/angular.service.$location $location.search()} of the currently loaded page +Returns the {@link api/angular.module.ng.$location $location.search()} of the currently loaded page in the test frame. ## browser().location().hash() -Returns the {@link api/angular.service.$location $location.hash()} of the currently loaded page in +Returns the {@link api/angular.module.ng.$location $location.hash()} of the currently loaded page in the test frame. ## expect(future).{matcher} diff --git a/docs/content/guide/dev_guide.expressions.ngdoc b/docs/content/guide/dev_guide.expressions.ngdoc index 420a6f988ba4..4df69d28a4b4 100644 --- a/docs/content/guide/dev_guide.expressions.ngdoc +++ b/docs/content/guide/dev_guide.expressions.ngdoc @@ -54,15 +54,26 @@ You can try evaluating different expressions here: function Cntl2() { this.exprs = []; this.expr = '3*10|currency'; + this.addExp = function(expr) { + this.exprs.push(expr); + }; + + this.removeExp = function(contact) { + for ( var i = 0, ii = this.exprs.length; i < ii; i++) { + if (contact === this.exprs[i]) { + this.exprs.splice(i, 1); + } + } + }; }
Expression: - +
  • - [ X ] + [ X ] {{expr}} =>
@@ -154,15 +165,15 @@ JavaScript method instead. Built-in types have methods like `[].push()`, but the richness of these methods is limited. Consider the example below, which allows you to do a simple search over a canned set of contacts. The example would be much more complicated if we did not have the `Array:$filter()`. There is no -built-in method on `Array` called {@link api/angular.Array.filter $filter} and angular doesn't add +built-in method on `Array` called {@link api/angular.module.ng.$filter.filter $filter} and angular doesn't add it to `Array.prototype` because that could collide with other JavaScript frameworks. For this reason the scope expression evaluator augments the built-in types to make them act like -they have extra methods. The actual method for `$filter()` is `angular.Array.filter()`. You can +they have extra methods. The actual method for `$filter()` is `angular.module.ng.$filter.filter()`. You can call it from JavaScript. Extensions: You can further extend the expression vocabulary by adding new methods to -`angular.Array` or `angular.String`, etc. +`angular.module.ng.$filter` or `angular.String`, etc. @@ -175,7 +186,7 @@ Extensions: You can further extend the expression vocabulary by adding new metho Search: - + @@ -201,7 +212,7 @@ of filters like this: name | uppercase -The expression evaluator simply passes the value of name to angular.filter.uppercase. +The expression evaluator simply passes the value of name to angular.module.ng.$filter.uppercase. Chain filters using this syntax: @@ -232,4 +243,4 @@ so that angular developers and developers who use angular can develop in harmony ## Related API -* {@link api/angular.compile Angular Compiler API} +* {@link api/angular.module.ng.$compile Angular Compiler API} diff --git a/docs/content/guide/dev_guide.forms.ngdoc b/docs/content/guide/dev_guide.forms.ngdoc index 980b6c17b757..d2b81dccf8ed 100644 --- a/docs/content/guide/dev_guide.forms.ngdoc +++ b/docs/content/guide/dev_guide.forms.ngdoc @@ -18,14 +18,14 @@ Forms consist of all of the following: A form groups a set of widgets together into a single logical data-set. A form is created using the {@link api/angular.widget.form <form>} element that calls the -{@link api/angular.service.$formFactory $formFactory} service. The form is responsible for managing +{@link api/angular.module.ng.$formFactory $formFactory} service. The form is responsible for managing the widgets and for tracking validation information. A form is: - The collection which contains widgets or other forms. - Responsible for marshaling data from the model into a widget. This is - triggered by {@link api/angular.scope.$watch $watch} of the model expression. + triggered by {@link api/angular.module.ng.$rootScope.Scope#$watch $watch} of the model expression. - Responsible for marshaling data from the widget into the model. This is triggered by the widget emitting the `$viewChange` event. - Responsible for updating the validation state of the widget, when the widget emits @@ -57,7 +57,7 @@ In Angular, a widget is the term used for the UI with which the user input. Exam bult-in Angular widgets are {@link api/angular.widget.input input} and {@link api/angular.widget.select select}. Widgets provide the rendering and the user interaction logic. Widgets should be declared inside a form, if no form is provided an implicit -form {@link api/angular.service.$formFactory $formFactory.rootForm} form is used. +form {@link api/angular.module.ng.$formFactory $formFactory.rootForm} form is used. Widgets are implemented as Angular controllers. A widget controller: @@ -134,7 +134,16 @@ The following example demonstrates: save: function() { this.master = this.form; this.cancel(); + }, + + isCancelDisabled: function() { + return angular.equals(this.master, this.form); + }, + + isSaveDisabled: function() { + return this.userForm.$invalid || angular.equals(this.master, this.form); } + };
@@ -172,10 +181,9 @@ The following example demonstrates: + ng:disabled="{{isCancelDisabled()}}">Cancel + ng:disabled="{{isSaveDisabled()}}">Save
@@ -210,7 +218,7 @@ The following example demonstrates: # Life-cycle - The `
` element triggers creation of a new form {@link dev_guide.scopes scope} using the - {@link api/angular.service.$formFactory $formfactory}. The new form scope is added to the + {@link api/angular.module.ng.$formFactory $formfactory}. The new form scope is added to the `` element using the jQuery `.data()` method for later retrieval under the key `$form`. The form also sets up these listeners: @@ -219,8 +227,8 @@ The following example demonstrates: - `$valid` / `$invalid` - This event is emitted by the widget on validation state change. - `` element triggers the creation of the widget using the - {@link api/angular.service.$formFactory $formfactory.$createWidget()} method. The `$createWidget()` - creates new widget instance by calling the current scope {@link api/angular.scope.$new .$new()} and + {@link api/angular.module.ng.$formFactory $formfactory.$createWidget()} method. The `$createWidget()` + creates new widget instance by calling the current scope {@link api/angular.module.ng.$rootScope.Scope#$new .$new()} and registers these listeners: - `$watch` on the model scope. @@ -236,7 +244,7 @@ The following example demonstrates: 1. The DOM element fires the `change` event which the widget intercepts. Widget then emits a `$viewChange` event which includes the new user-entered value. (Remember that the DOM events are outside of the Angular environment so the widget must emit its event within the - {@link api/angular.scope.$apply $apply} method). + {@link api/angular.module.ng.$rootScope.Scope#$apply $apply} method). 2. The form's `$viewChange` listener copies the user-entered value to the widget's `$viewValue` property. Since the `$viewValue` is the raw value as entered by user, it may need to be translated to a different format/type (for example, translating a string to a number). @@ -278,9 +286,9 @@ This example shows how to implement a custom HTML editor widget in Angular. this.htmlContent = 'Hello World!'; } - function HTMLEditorWidget(element) { + HTMLEditorWidget.$inject = ['$element', 'html$Filter']; + function HTMLEditorWidget(element, htmlFilter) { var self = this; - var htmlFilter = angular.filter('html'); this.$parseModel = function() { // need to protect for script injection @@ -309,7 +317,7 @@ This example shows how to implement a custom HTML editor widget in Angular. } angular.directive('ng:html-editor-model', function() { - function linkFn($formFactory, element) { + return ['$formFactory', '$element', function ($formFactory, element) { var exp = element.attr('ng:html-editor-model'), form = $formFactory.forElement(element), widget; @@ -318,15 +326,13 @@ This example shows how to implement a custom HTML editor widget in Angular. scope: this, model: exp, controller: HTMLEditorWidget, - controllerArgs: [element]}); + controllerArgs: {$element: element}}); // if the element is destroyed, then we need to // notify the form. element.bind('$destroy', function() { widget.$destroy(); }); - } - linkFn.$inject = ['$formFactory']; - return linkFn; + }]; }); @@ -511,7 +517,7 @@ function LoginController() { describe('LoginController', function() { it('should disable login button when form is invalid', function() { - var scope = angular.scope(); + var scope = angular.module.ng.$rootScope.Scope(); var loginController = scope.$new(LoginController); // In production the 'loginForm' form instance gets set from the view, @@ -564,7 +570,7 @@ function LoginController(){ describe('LoginController', function() { it('should disable login button when form is invalid', function() { - var scope = angular.scope(); + var scope = angular.module.ng.$rootScope.Scope(); var loginController = scope.$new(LoginController); var input = angular.element(''); diff --git a/docs/content/guide/dev_guide.i18n.ngdoc b/docs/content/guide/dev_guide.i18n.ngdoc index 7a6bbdee7d38..d88715cd5124 100644 --- a/docs/content/guide/dev_guide.i18n.ngdoc +++ b/docs/content/guide/dev_guide.i18n.ngdoc @@ -17,15 +17,15 @@ abstracted bits. **What level of support for i18n/l10n is currently in Angular?** Currently, Angular supports i18n/l10n for {@link -http://docs.angularjs.org/#!/api/angular.filter.date datetime}, {@link -http://docs.angularjs.org/#!/api/angular.filter.number number} and {@link -http://docs.angularjs.org/#!/api/angular.filter.currency currency} filters. +http://docs.angularjs.org/#!/api/angular.module.ng.$filter.date datetime}, {@link +http://docs.angularjs.org/#!/api/angular.module.ng.$filter.number number} and {@link +http://docs.angularjs.org/#!/api/angular.module.ng.$filter.currency currency} filters. Additionally, Angular supports localizable pluralization support provided by the {@link api/angular.widget.ng:pluralize ng:pluralize widget}. All localizable Angular components depend on locale-specific rule sets managed by the {@link -api/angular.service.$locale $locale service}. +api/angular.module.ng.$locale $locale service}. For readers who want to jump straight into examples, we have a few web pages that showcase how to use Angular filters with various locale rule sets. You can find these examples either on {@link @@ -90,8 +90,8 @@ because an extra script needs to be loaded. **Currency symbol "gotcha"** -Angular's {@link http://docs.angularjs.org/#!/api/angular.filter.currency currency filter} allows -you to use the default currency symbol from the {@link api/angular.service.$locale locale service}, +Angular's {@link http://docs.angularjs.org/#!/api/angular.module.ng.$filter.currency currency filter} allows +you to use the default currency symbol from the {@link api/angular.module.ng.$locale locale service}, or you can provide the filter with a custom currency symbol. If your app will be used only in one locale, it is fine to rely on the default currency symbol. However, if you anticipate that viewers in other locales might use your app, you should provide your own currency symbol to make sure the @@ -104,7 +104,7 @@ browser will specify the locale as ja, and the balance of '¥1000.00' will be sh will really upset your client. In this case, you need to override the default currency symbol by providing the {@link -http://docs.angularjs.org/#!/api/angular.filter.currency currency filter} with a currency symbol as +http://docs.angularjs.org/#!/api/angular.module.ng.$filter.currency currency filter} with a currency symbol as a parameter when you configure the filter, for example, {{ 1000 | currency:"USD$"}}. This way, Angular will always show a balance of 'USD$1000' and disregard any locale changes. diff --git a/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc b/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc index 833dc0052742..5f571680cbaa 100644 --- a/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc +++ b/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc @@ -4,7 +4,7 @@ In angular, a controller is a JavaScript function(type/class) that is used to augment instances of angular {@link dev_guide.scopes Scope}, excluding the root scope. When you or angular create a new -child scope object via the {@link api/angular.scope.$new scope.$new} API , there is an +child scope object via the {@link api/angular.module.ng.$rootScope.Scope#$new scope.$new} API , there is an option to pass in a controller as a method argument. This will tell angular to associate the controller with the new scope and to augment its behavior. @@ -77,9 +77,9 @@ instances). # Associating Controllers with Angular Scope Objects -You can associate controllers with scope objects explicitly via the {@link api/angular.scope.$new +You can associate controllers with scope objects explicitly via the {@link api/angular.module.ng.$rootScope.Scope#$new scope.$new} api or implicitly via the {@link api/angular.directive.ng:controller ng:controller -directive} or {@link api/angular.service.$route $route service}. +directive} or {@link api/angular.module.ng.$route $route service}. ## Controller Constructor and Methods Example @@ -160,7 +160,7 @@ input box) in the second button. ## Controller Inheritance Example -Controller inheritance in angular is based on {@link api/angular.scope Scope} inheritance. Let's +Controller inheritance in angular is based on {@link api/angular.module.ng.$rootScope.Scope Scope} inheritance. Let's have a look at an example:
diff --git a/docs/content/guide/dev_guide.scopes.internals.ngdoc b/docs/content/guide/dev_guide.scopes.internals.ngdoc
index 47e90c183e25..b63f566cf18b 100644
--- a/docs/content/guide/dev_guide.scopes.internals.ngdoc
+++ b/docs/content/guide/dev_guide.scopes.internals.ngdoc
@@ -11,8 +11,8 @@ pattern, a scope's properties comprise both the model and the controller methods
 
 
 ### Scope characteristics
-- Scopes provide APIs ({@link api/angular.scope.$watch $watch}) to observe model mutations.
-- Scopes provide APIs ({@link api/angular.scope.$apply $apply}) to propagate any model changes
+- Scopes provide APIs ({@link api/angular.module.ng.$rootScope.Scope#$watch $watch}) to observe model mutations.
+- Scopes provide APIs ({@link api/angular.module.ng.$rootScope.Scope#$apply $apply}) to propagate any model changes
 through the system into the view from outside of the "Angular realm" (controllers, services,
 Angular event handlers).
 - Scopes can be nested to isolate application components while providing access to shared model
@@ -23,20 +23,18 @@ available as `this` within the given context. (Note: This api will change before
 
 ### Root scope
 
-Every application has a root scope, which is the ancestor of all other scopes. The root scope is
-responsible for creating the injector which is assigned to the {@link api/angular.scope.$service
-$service} property, and initializing the services.
+Every application has a root scope, which is the ancestor of all other scopes.
 
 ### What is scope used for?
 
-{@link dev_guide.expressions Expressions} in the view are {@link api/angular.scope.$eval evaluated}
+{@link dev_guide.expressions Expressions} in the view are {@link api/angular.module.ng.$rootScope.Scope#$eval evaluated}
 against the current scope. When HTML DOM elements are attached to a scope, expressions in those
 elements are evaluated against the attached scope.
 
 There are two kinds of expressions:
 
 - Binding expressions, which are observations of property changes. Property changes are reflected
-in the view during the {@link api/angular.scope.$digest digest cycle}.
+in the view during the {@link api/angular.module.ng.$rootScope.Scope#$digest digest cycle}.
 - Action expressions, which are expressions with side effects. Typically, the side effects cause
 execution of a method in a controller in response to a user action, such as clicking on a button.
 
@@ -59,7 +57,7 @@ A property write will always write to the current scope. This means that a write
 property within the scope it writes to, as shown in the following example.
 
 
-var root = angular.scope();
+var root = angular.module.ng.$rootScope.Scope();
 var child = root.$new();
 
 root.name = 'angular';
@@ -75,25 +73,25 @@ expect(root.name).toEqual('angular');
 ### Scope life cycle
 1. **Creation**
 
-   * You can create the root scope via {@link api/angular.scope angular.scope()}.
-   * To create a child scopes, you should call {@link api/angular.scope.$new parentScope.$new()}.
+   * The root scope is created by the  {@link api/angular.module.ng.$rootScope $rootScope} service.
+   * To create a child scopes, you should call {@link api/angular.module.ng.$rootScope.Scope#$new parentScope.$new()}.
 
 2. **Watcher registration**
 
    Watcher registration can happen at any time and on any scope (root or child) via {@link
-api/angular.scope.$watch scope.$watch()} API.
+api/angular.module.ng.$rootScope.Scope#$watch scope.$watch()} API.
 
 3. **Model mutation**
 
    For mutations to be properly observed, you should make them only within the execution of the
-function passed into {@link api/angular.scope.$apply scope.$apply()} call. (Angular apis do this
+function passed into {@link api/angular.module.ng.$rootScope.Scope#$apply scope.$apply()} call. (Angular apis do this
 implicitly, so no extra `$apply` call is needed when doing synchronous work in controllers, or
-asynchronous work with {@link api/angular.service.$xhr $xhr} or {@link api/angular.service.$defer
+asynchronous work with {@link api/angular.module.ng.$xhr $xhr} or {@link api/angular.module.ng.$defer
 $defer} services.
 
 4. **Mutation observation**
 
-   At the end of each `$apply` call {@link api/angular.scope.$digest $digest} cycle is started on
+   At the end of each `$apply` call {@link api/angular.module.ng.$rootScope.Scope#$digest $digest} cycle is started on
 the root scope, which then propagates throughout all child scopes.
 
    During the `$digest` cycle, all `$watch-ers` expressions or functions are checked for model
@@ -102,7 +100,7 @@ mutation and if a mutation is detected, the `$watch-er` listener is called.
 5. **Scope destruction**
 
    When child scopes are no longer needed, it is the responsibility of the child scope creator to
-destroy them via {@link api/angular.scope.$destroy scope.$destroy()} API. This will stop
+destroy them via {@link api/angular.module.ng.$rootScope.Scope#$destroy scope.$destroy()} API. This will stop
 propagation of `$digest` calls into the child scope and allow for memory used by the child scope
 models to be reclaimed by the garbage collector.
 
@@ -116,29 +114,26 @@ scopes come into play throughout and get a sense of their interactions.
 
 1. At application compile time, a root scope is created and is attached to the root `` DOM
 element.
-   1. The root scope creates an {@link api/angular.injector injector} which is assigned to the
-{@link api/angular.scope.$service $service} property of the root scope.
-   2. Any eager {@link api/angular.scope.$service services} are initialized at this point.
 2. During the compilation phase, the {@link dev_guide.compiler compiler} matches {@link
 api/angular.directive directives} against the DOM template. The directives usually fall into one of
 two categories:
    - Observing {@link api/angular.directive directives}, such as double-curly expressions
-`{{expression}}`, register listeners using the {@link api/angular.scope.$watch $watch()} method.
+`{{expression}}`, register listeners using the {@link api/angular.module.ng.$rootScope.Scope#$watch $watch()} method.
 This type of directive needs to be notified whenever the expression changes so that it can update
 the view.
    -  Listener directives, such as {@link api/angular.directive.ng:click ng:click}, register a
 listener with the DOM. When the DOM listener fires, the directive executes the associated
-expression and updates the view using  the {@link api/angular.scope.$apply $apply()} method.
+expression and updates the view using  the {@link api/angular.module.ng.$rootScope.Scope#$apply $apply()} method.
 3. When an external event (such as a user action, timer or XHR) is received, the associated {@link
 dev_guide.expressions expression} must be applied to the scope through the {@link
-api/angular.scope.$apply $apply()} method so that all listeners are updated correctly.
+api/angular.module.ng.$rootScope.Scope#$apply $apply()} method so that all listeners are updated correctly.
 
 
 ### Directives that create scopes
 In most cases, {@link api/angular.directive directives} and scopes interact but do not create new
 instances of scope. However, some directives, such as {@link api/angular.directive.ng:controller
 ng:controller} and {@link api/angular.widget.@ng:repeat ng:repeat}, create new child scopes using
-the {@link api/angular.scope.$new $new()} method and then attach the child scope to the
+the {@link api/angular.module.ng.$rootScope.Scope#$new $new()} method and then attach the child scope to the
 corresponding DOM element. You can retrieve a scope for any DOM element by using an
 `angular.element(aDomElement).scope()` method call.)
 
@@ -148,13 +143,13 @@ Scopes and controllers interact with each other in the following situations:
    - Controllers use scopes to expose controller methods to templates (see {@link
 api/angular.directive.ng:controller ng:controller}).
    - Controllers define methods (behavior) that can mutate the model (properties on the scope).
-   - Controllers may register {@link api/angular.scope.$watch watches} on the model. These watches
+   - Controllers may register {@link api/angular.module.ng.$rootScope.Scope#$watch watches} on the model. These watches
 execute immediately after the controller behavior executes, but before the DOM gets updated.
 
 See the {@link dev_guide.mvc.understanding_controller controller docs} for more information.
 
 ### Updating scope properties
-You can update a scope by calling its {@link api/angular.scope.$apply $apply()} method with an
+You can update a scope by calling its {@link api/angular.module.ng.$rootScope.Scope#$apply $apply()} method with an
 expression or a function as the function argument. However it is typically not necessary to do this
 explicitly. In most cases, angular intercepts all external events (such as user interactions, XHRs,
 and timers) and wraps their callbacks into the `$apply()` method call on the scope object for you
@@ -177,8 +172,8 @@ doesn't need to worry about propagating the `$digest` call from the parent scope
 This happens automatically.
 
 ## Scopes in unit-testing
-You can create scopes, including the root scope, in tests using the {@link api/angular.scope
-angular.scope()} API. This allows you to mimic the run-time environment and have full control over
+You can create scopes, including the root scope, in tests using the {@link api/angular.module.ng.$rootScope.Scope
+angular.module.ng.$rootScope.Scope()} API. This allows you to mimic the run-time environment and have full control over
 the life cycle of the scope so that you can assert correct model transitions. Since these scopes
 are created outside the normal compilation process, their life cycles must be managed by the test.
 
@@ -188,7 +183,7 @@ within the unit-tests.
 
 
   // example of a test
-  var scope = angular.scope();
+  var scope = angular.module.ng.$rootScope.Scope();
   scope.$watch('name', function(scope, name){
    scope.greeting = 'Hello ' + name + '!';
   });
@@ -209,9 +204,14 @@ When you find it necessary to inject your own mocks in your tests, use a scope t
 service instances, as shown in the following example.
 
 
-var myLocation = {};
-var scope = angular.scope(angular.service, {$location: myLocation});
-expect(scope.$service('$location')).toEqual(myLocation);
+it('should allow override of providers', inject(
+  function($provide) {
+    $provide.value('$location', {mode:'I am a mock'});
+  },
+  function($location){
+    expect($location.mode).toBe('I am a mock');
+  }
+)};
 
## Related Topics @@ -221,5 +221,5 @@ expect(scope.$service('$location')).toEqual(myLocation); ## Related API -* {@link api/angular.scope Angular Scope API} +* {@link api/angular.module.ng.$rootScope.Scope Angular Scope API} diff --git a/docs/content/guide/dev_guide.scopes.ngdoc b/docs/content/guide/dev_guide.scopes.ngdoc index b59bd87ba1c5..7b9b77ec9bd6 100644 --- a/docs/content/guide/dev_guide.scopes.ngdoc +++ b/docs/content/guide/dev_guide.scopes.ngdoc @@ -13,15 +13,15 @@ the contexts in which Angular creates data-bindings between the model and the vi In addition to providing the context in which data is evaluated, Angular scope objects watch for model changes. The scope objects also notify all components interested in any model changes (for -example, functions registered through {@link api/angular.scope.$watch $watch}, bindings created by +example, functions registered through {@link api/angular.module.ng.$rootScope.Scope#$watch $watch}, bindings created by {@link api/angular.directive.ng:bind ng:bind}, or HTML input elements). Angular scope objects: * Link the model, controller and view template together. -* Provide the mechanism to watch for model changes ({@link api/angular.scope.$watch $watch}). -* Apply model changes to the system ({@link api/angular.scope.$apply $apply}). -* Provide the context in which expressions are evaluated ({@link api/angular.scope.$eval $eval}). +* Provide the mechanism to watch for model changes ({@link api/angular.module.ng.$rootScope.Scope#$watch $watch}). +* Apply model changes to the system ({@link api/angular.module.ng.$rootScope.Scope#$apply $apply}). +* Provide the context in which expressions are evaluated ({@link api/angular.module.ng.$rootScope.Scope#$eval $eval}). ## Related Topics @@ -31,5 +31,5 @@ Angular scope objects: ## Related API -* {@link api/angular.scope Angular Scope API} +* {@link api/angular.module.ng.$rootScope.Scope Angular Scope API} diff --git a/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc b/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc index 03b20517216d..77f589dcae2a 100644 --- a/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc +++ b/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc @@ -63,4 +63,4 @@ The following illustration shows the DOM and angular scopes for the example abov ## Related API -* {@link api/angular.scope Angular Scope API} +* {@link api/angular.module.ng.$rootScope.Scope Angular Scope API} diff --git a/docs/content/guide/dev_guide.services.$location.ngdoc b/docs/content/guide/dev_guide.services.$location.ngdoc index 5174751669e7..2296a1075cdc 100644 --- a/docs/content/guide/dev_guide.services.$location.ngdoc +++ b/docs/content/guide/dev_guide.services.$location.ngdoc @@ -88,26 +88,22 @@ setter methods that allow you to get or change the current URL in the browser. ## $location service configuration -To configure the `$location` service, you define the `$locationConfig` service which is an object -with configuration properties: +To configure the `$location` service, retrieve the +{@link api/angular.module.ng.$locationProvider $locationProvider} and set the parameters as follows: -- **html5Mode**: {boolean}
+ +- **html5Mode(mode)**: {boolean}
`true` - see HTML5 mode
`false` - see Hashbang mode
default: `false` -- **hashPrefix**: {string}
+- **hashPrefix(prefix)**: {string}
prefix used for Hashbang URLs (used in Hashbang mode or in legacy browser in Html5 mode)
default: `'!'` ### Example configuration
-angular.service('$locationConfig', function() {
-  return {
-    html5mode: true,
-    hashPrefix: '!'
-  };
-});
+$locationProvider.html5Mode(true).hashPrefix('!');
 
## Getter and setter methods @@ -138,7 +134,7 @@ current URL without creating a new browser history record you can call:
Note that the setters don't update `window.location` immediately. Instead, `$location` service is -aware of the {@link api/angular.scope scope} life-cycle and coalesces multiple `$location` +aware of the {@link api/angular.module.ng.$rootScope.Scope scope} life-cycle and coalesces multiple `$location` mutations into one "commit" to the `window.location` object during the scope `$digest` phase. Since multiple changes to the $location's state will be pushed to the browser as a single change, it's enough to call the `replace()` method just once to make the entire "commit" a replace operation @@ -214,26 +210,27 @@ In this mode, `$location` uses Hashbang URLs in all browsers. ### Example
-angular.service('$locationConfig', function() {
-  return {
-    html5Mode: false,
-    hashPrefix: '!'
-  };
-});
-
-// open http://host.com/base/index.html#!/a
-$location.absUrl() == 'http://host.com/base/index.html#!/a'
-$location.path() == '/a'
-
-$location.path('/foo')
-$location.absUrl() == 'http://host.com/base/index.html#!/foo'
-
-$location.search() == {}
-$location.search({a: 'b', c: true});
-$location.absUrl() == 'http://host.com/base/index.html#!/foo?a=b&c'
-
-$location.path('/new').search('x=y');
-$location.absUrl() == 'http://host.com/base/index.html#!/new?x=y'
+it('should show example', inject(
+  function($locationProvider) {
+    $locationProvider.html5mode = false;
+    $locationProvider.hashPrefix = '!';
+  },
+  function($location) {
+    // open http://host.com/base/index.html#!/a
+    $location.absUrl() == 'http://host.com/base/index.html#!/a'
+    $location.path() == '/a'
+
+    $location.path('/foo')
+    $location.absUrl() == 'http://host.com/base/index.html#!/foo'
+
+    $location.search() == {}
+    $location.search({a: 'b', c: true});
+    $location.absUrl() == 'http://host.com/base/index.html#!/foo?a=b&c'
+
+    $location.path('/new').search('x=y');
+    $location.absUrl() == 'http://host.com/base/index.html#!/new?x=y'
+  }
+));
 
### Crawling your app @@ -262,39 +259,40 @@ having to worry about whether the browser displaying your app supports the histo ### Example
-angular.service('$locationConfig', function() {
-  return {
-    html5Mode: true,
-    hashPrefix: '!'
-  };
-});
-
-// in browser with HTML5 history support:
-// open http://host.com/#!/a -> rewrite to http://host.com/a
-// (replacing the http://host.com/#!/a history record)
-$location.path() == '/a'
-
-$location.path('/foo');
-$location.absUrl() == 'http://host.com/foo'
-
-$location.search() == {}
-$location.search({a: 'b', c: true});
-$location.absUrl() == 'http://host.com/foo?a=b&c'
-
-$location.path('/new').search('x=y');
-$location.url() == 'new?x=y'
-$location.absUrl() == 'http://host.com/new?x=y'
-
-// in browser without html5 history support:
-// open http://host.com/new?x=y -> redirect to http://host.com/#!/new?x=y
-// (again replacing the http://host.com/new?x=y history item)
-$location.path() == '/new'
-$location.search() == {x: 'y'}
-
-$location.path('/foo/bar');
-$location.path() == '/foo/bar'
-$location.url() == '/foo/bar?x=y'
-$location.absUrl() == 'http://host.com/#!/foo/bar?x=y'
+it('should show example', inject(
+  function($locationProvider) {
+    $locationProvider.html5mode = true;
+    $locationProvider.hashPrefix = '!';
+  },
+  function($location) {
+    // in browser with HTML5 history support:
+    // open http://host.com/#!/a -> rewrite to http://host.com/a
+    // (replacing the http://host.com/#!/a history record)
+    $location.path() == '/a'
+
+    $location.path('/foo');
+    $location.absUrl() == 'http://host.com/foo'
+
+    $location.search() == {}
+    $location.search({a: 'b', c: true});
+    $location.absUrl() == 'http://host.com/foo?a=b&c'
+
+    $location.path('/new').search('x=y');
+    $location.url() == 'new?x=y'
+    $location.absUrl() == 'http://host.com/new?x=y'
+
+    // in browser without html5 history support:
+    // open http://host.com/new?x=y -> redirect to http://host.com/#!/new?x=y
+    // (again replacing the http://host.com/new?x=y history item)
+    $location.path() == '/new'
+    $location.search() == {x: 'y'}
+
+    $location.path('/foo/bar');
+    $location.path() == '/foo/bar'
+    $location.url() == '/foo/bar?x=y'
+    $location.absUrl() == 'http://host.com/#!/foo/bar?x=y'
+  }
+));
 
### Fallback for legacy browsers @@ -368,7 +366,6 @@ redirect to regular / hashbang url, as this conversion happens only during parsi = on page reload. In this examples we use `` - @@ -426,8 +423,7 @@ In this examples we use `` var browsers = { html5: new FakeBrowser('http://www.host.com/base/path?a=b#h', '/base/index.html'), - hashbang: new FakeBrowser('http://www.host.com/base/index.html#!/path?a=b#h', -'/base/index.html') + hashbang: new FakeBrowser('http://www.host.com/base/index.html#!/path?a=b#h', '/base/index.html') }; function Html5Cntl($location) { @@ -465,14 +461,14 @@ In this examples we use `` function initEnv(name) { var root = angular.element(document.getElementById(name + '-mode')); - var scope = angular.scope(null, { - $locationConfig: {html5Mode: true, hashPrefix: '!'}, - $browser: browsers[name], - $document: root, - $sniffer: {history: name == 'html5'} - }); - - angular.compile(root)(scope).$apply(); + angular.bootstrap(root, [function($locationProvider, $provide){ + $locationProvider.html5Mode = true; + $locationProvider.hashPrefix = '!'; + + $provide.value('$browser', browsers[name]); + $provide.value('$document', root); + $provide.value('$sniffer', {history: name == 'html5'}); + }]); root.bind('click', function(e) { e.stopPropagation(); }); @@ -492,11 +488,11 @@ In this examples we use `` The `$location` service allows you to change only the URL; it does not allow you to reload the page. When you need to change the URL and reload the page or navigate to a different page, please -use a lower level API, {@link api/angular.service.$window $window.location.href}. +use a lower level API, {@link api/angular.module.ng.$window $window.location.href}. ## Using $location outside of the scope life-cycle -`$location` knows about Angular's {@link api/angular.scope scope} life-cycle. When a URL changes in +`$location` knows about Angular's {@link api/angular.module.ng.$rootScope.Scope scope} life-cycle. When a URL changes in the browser it updates the `$location` and calls `$apply` so that all $watchers / $observers are notified. When you change the `$location` inside the `$digest` phase everything is ok; `$location` will @@ -516,29 +512,23 @@ hashPrefix. # Testing with the $location service When using `$location` service during testing, you are outside of the angular's {@link -api/angular.scope scope} life-cycle. This means it's your responsibility to call `scope.$apply()`. +api/angular.module.ng.$rootScope.Scope scope} life-cycle. This means it's your responsibility to call `scope.$apply()`.
-angular.service('$serviceUnderTest', function($location) {
-  // whatever it does...
-};
-
-describe('$serviceUnderTest', function() {
-  var scope, $location, $sut;
-
-  beforeEach(function() {
-    scope = angular.scope();
-    $location = scope.$service('$location');
-    $sut = scope.$service('$serviceUnderTest');
+describe('serviceUnderTest', function() {
+  beforeEach(inject(function($provide) {
+    $provide.factory('serviceUnderTest', function($location){
+      // whatever it does...
+    });
   });
 
-  it('should...', function() {
+  it('should...', inject(function($location, $rootScope, serviceUnderTest) {
     $location.path('/new/path');
-    scope.$apply();
+    $rootScope.$apply();
 
     // test whatever the service should do...
 
-  });
+  }));
 });
 
@@ -640,7 +630,7 @@ this.$watch('$location.path()', function(scope, path) { # Related API -* {@link api/angular.service.$location $location API} +* {@link api/angular.module.ng.$location $location API} diff --git a/docs/content/guide/dev_guide.services.creating_services.ngdoc b/docs/content/guide/dev_guide.services.creating_services.ngdoc index 74ade37679ad..06d57d77714b 100644 --- a/docs/content/guide/dev_guide.services.creating_services.ngdoc +++ b/docs/content/guide/dev_guide.services.creating_services.ngdoc @@ -6,7 +6,7 @@ While angular offers several useful services, for any nontrivial application you to write your own custom services. To do this you begin by registering a service factory function that angular's DI will use to create the service object when it is needed. -The `angular.service` method accepts three parameters: +The `angular.module.ng` method accepts three parameters: - `{string} name` - Name of the service. - `{function()} factory` - Factory function(called just once by DI). @@ -14,9 +14,6 @@ The `angular.service` method accepts three parameters: - `$inject` - {Array.} - Array of service ids this service depends on. These services will be passed as arguments into the factory function in the same order specified in the `$inject` array. Defaults to `[]`. - - `$eager` - {boolean} - If true, the service factory will be called and the service will be -instantiated when angular boots. If false, the service will be lazily instantiated when it is first -requested during instantiation of a dependant. Defaults to `false`. The `this` of the factory function is bound to the root scope of the angular application. @@ -32,7 +29,7 @@ stores all notifications; after the third one, the service displays all of the n window alert.
-    angular.service('notify', function(win) {
+    angular.module.ng('notify', function(win) {
       var msgs = [];
       return function(msg) {
         msgs.push(msg);
@@ -55,4 +52,4 @@ window alert.
 
 ## Related API
 
-* {@link api/angular.service Angular Service API}
+* {@link api/angular.module.ng Angular Service API}
diff --git a/docs/content/guide/dev_guide.services.injecting_controllers.ngdoc b/docs/content/guide/dev_guide.services.injecting_controllers.ngdoc
index d58f2c3cfd0b..c01b04b1f381 100644
--- a/docs/content/guide/dev_guide.services.injecting_controllers.ngdoc
+++ b/docs/content/guide/dev_guide.services.injecting_controllers.ngdoc
@@ -28,19 +28,21 @@ this.secondMethod = function() {
 myController.$inject = ['$location', '$log'];
 
- +
@@ -45,7 +45,6 @@ text upper-case and assigns color. No filter: {{greeting}}
Reverse: {{greeting|reverse}}
Reverse + uppercase: {{greeting|reverse:true}}
- Reverse + uppercase + blue: {{greeting|reverse:true:"blue"}}
@@ -65,4 +64,4 @@ text upper-case and assigns color. ## Related API -* {@link api/angular.filter Angular Filter API} +* {@link api/angular.module.ng.$filter Angular Filter API} diff --git a/docs/content/guide/dev_guide.templates.filters.ngdoc b/docs/content/guide/dev_guide.templates.filters.ngdoc index 933ddfd323fa..52780ec0c96b 100644 --- a/docs/content/guide/dev_guide.templates.filters.ngdoc +++ b/docs/content/guide/dev_guide.templates.filters.ngdoc @@ -11,7 +11,7 @@ displaying it to the user. You can pass expressions through a chain of filters l name | uppercase -The expression evaluator simply passes the value of name to `angular.filter.uppercase()`. +The expression evaluator simply passes the value of name to `angular.module.ng.$filter.uppercase()`. In addition to formatting data, filters can also modify the DOM. This allows filters to handle tasks such as conditionally applying CSS styles to filtered output. @@ -24,4 +24,4 @@ tasks such as conditionally applying CSS styles to filtered output. ## Related API -* {@link api/angular.filter Angular Filter API} +* {@link api/angular.module.ng.$filter Angular Filter API} diff --git a/docs/content/guide/dev_guide.templates.filters.using_filters.ngdoc b/docs/content/guide/dev_guide.templates.filters.using_filters.ngdoc index f7dd5766719c..a159e1f5a6f2 100644 --- a/docs/content/guide/dev_guide.templates.filters.using_filters.ngdoc +++ b/docs/content/guide/dev_guide.templates.filters.using_filters.ngdoc @@ -2,7 +2,7 @@ @name Developer Guide: Templates: Filters: Using Angular Filters @description -Filters can be part of any {@link api/angular.scope} evaluation but are typically used to format +Filters can be part of any {@link api/angular.module.ng.$rootScope.Scope} evaluation but are typically used to format expressions in bindings in your templates: {{ expression | filter }} @@ -37,4 +37,4 @@ argument that specifies how many digits to display to the right of the decimal p ## Related API -* {@link api/angular.filter Angular Filter API} +* {@link api/angular.module.ng.$filter Angular Filter API} diff --git a/docs/content/guide/dev_guide.templates.ngdoc b/docs/content/guide/dev_guide.templates.ngdoc index a90f4c38e92b..584fdcfe9b13 100644 --- a/docs/content/guide/dev_guide.templates.ngdoc +++ b/docs/content/guide/dev_guide.templates.ngdoc @@ -43,7 +43,7 @@ and {@link dev_guide.expressions expressions}: In a simple single-page app, the template consists of HTML, CSS, and angular directives contained in just one HTML file (usually `index.html`). In a more complex app, you can display multiple views within one main page using "partials", which are segments of template located in separate HTML -files. You "include" the partials in the main page using the {@link api/angular.service.$route +files. You "include" the partials in the main page using the {@link api/angular.module.ng.$route $route} service in conjunction with the {@link api/angular.widget.ng:view ng:view} directive. An example of this technique is shown in the {@link tutorial/ angular tutorial}, in steps seven and eight. diff --git a/docs/content/guide/dev_guide.unit-testing.ngdoc b/docs/content/guide/dev_guide.unit-testing.ngdoc index 4ca5473c95dd..8b4d4687f34a 100644 --- a/docs/content/guide/dev_guide.unit-testing.ngdoc +++ b/docs/content/guide/dev_guide.unit-testing.ngdoc @@ -247,16 +247,16 @@ that such a test tells a story, rather then asserting random bits which don't se ## Filters -{@link api/angular.filter Filters} are functions which transform the data into user readable +{@link api/angular.module.ng.$filter Filters} are functions which transform the data into user readable format. They are important because they remove the formatting responsibility from the application logic, further simplifying the application logic.
-angular.filter('length', function(text){
+angular.module.ng.$filter('length', function(text){
   return (''+(text||'')).length;
 });
 
-var length = angular.filter('length');
+var length = angular.module.ng.$filter('length');
 expect(length(null)).toEqual(0);
 expect(length('abc')).toEqual(3);
 
diff --git a/docs/content/misc/faq.ngdoc b/docs/content/misc/faq.ngdoc index f2168b48b438..1d2deac25916 100644 --- a/docs/content/misc/faq.ngdoc +++ b/docs/content/misc/faq.ngdoc @@ -68,7 +68,7 @@ manipulate the DOM. ### What is testability like in angular? Very testable. It has an integrated dependency injection framework. See -{@link api/angular.service service} for details. +{@link api/angular.module.ng service} for details. ### How can I learn more about angular? diff --git a/docs/content/tutorial/step_02.ngdoc b/docs/content/tutorial/step_02.ngdoc index 09065979411a..792228dfa1c8 100644 --- a/docs/content/tutorial/step_02.ngdoc +++ b/docs/content/tutorial/step_02.ngdoc @@ -102,7 +102,7 @@ contained in the template, data model, and controller, to keep models and views sync. Any changes made to the model are reflected in the view; any changes that occur in the view are reflected in the model. - To learn more about Angular scopes, see the {@link api/angular.scope angular scope documentation}. + To learn more about Angular scopes, see the {@link api/angular.module.ng.$rootScope.Scope angular scope documentation}. ## Tests diff --git a/docs/content/tutorial/step_03.ngdoc b/docs/content/tutorial/step_03.ngdoc index 9be7380a69a2..fef4743f5a2a 100644 --- a/docs/content/tutorial/step_03.ngdoc +++ b/docs/content/tutorial/step_03.ngdoc @@ -43,7 +43,7 @@ __`app/index.html`:__ ...
-We added a standard HTML `` tag and used angular's {@link api/angular.Array.filter $filter} +We added a standard HTML `` tag and used angular's {@link api/angular.module.ng.$filter.filter $filter} function to process the input for the `ng:repeater`. This lets a user enter search criteria and immediately see the effects of their search on the phone @@ -59,7 +59,7 @@ the DOM to reflect the current state of the model. -* Use of `$filter`. The {@link api/angular.Array.filter $filter} method uses the `query` value to +* Use of `$filter`. The {@link api/angular.module.ng.$filter.filter $filter} method uses the `query` value to create a new array that contains only those records that match the `query`. `ng:repeat` automatically updates the view in response to the changing number of phones returned diff --git a/docs/content/tutorial/step_04.ngdoc b/docs/content/tutorial/step_04.ngdoc index 6426674a6e97..a5fefd748d6d 100644 --- a/docs/content/tutorial/step_04.ngdoc +++ b/docs/content/tutorial/step_04.ngdoc @@ -54,9 +54,9 @@ two provided sorting options. -* We then chained the `$filter` method with {@link api/angular.Array.orderBy `$orderBy`} method to +* We then chained the `$filter` method with {@link api/angular.module.ng.$filter.orderBy `$orderBy`} method to further process the input into the repeater. `$orderBy` is a utility method similar to {@link -api/angular.Array.filter `$filter`}, but instead of filtering an array, it reorders it. +api/angular.module.ng.$filter.filter `$filter`}, but instead of filtering an array, it reorders it. Angular creates a two way data-binding between the select element and the `orderProp` model. `orderProp` is then used as the input for the `$orderBy` method. diff --git a/docs/content/tutorial/step_05.ngdoc b/docs/content/tutorial/step_05.ngdoc index fd8f19b89e81..7bf6f70877f8 100644 --- a/docs/content/tutorial/step_05.ngdoc +++ b/docs/content/tutorial/step_05.ngdoc @@ -6,8 +6,8 @@ Enough of building an app with three phones in a hard-coded dataset! Let's fetch a larger dataset -from our server using one of angular's built-in {@link api/angular.service services} called {@link -api/angular.service.$xhr $xhr}. We will use angular's {@link guide/dev_guide.di dependency +from our server using one of angular's built-in {@link api/angular.module.ng services} called {@link +api/angular.module.ng.$xhr $xhr}. We will use angular's {@link guide/dev_guide.di dependency injection (DI)} to provide the service to the `PhoneListCtrl` controller. @@ -42,9 +42,9 @@ Following is a sample of the file: ## Controller -We'll use angular's {@link api/angular.service.$xhr $xhr} service in our controller to make an HTTP +We'll use angular's {@link api/angular.module.ng.$xhr $xhr} service in our controller to make an HTTP request to your web server to fetch the data in the `app/phones/phones.json` file. `$xhr` is just -one of several built-in {@link api/angular.service angular services} that handle common operations +one of several built-in {@link api/angular.module.ng angular services} that handle common operations in web apps. Angular injects these services for you where you need them. Services are managed by angular's {@link guide/dev_guide.di DI subsystem}. Dependency injection @@ -127,7 +127,7 @@ describe('PhoneCat controllers', function() { var scope, $browser, ctrl; beforeEach(function() { - scope = angular.scope(); + scope = angular.module.ng.$rootScope.Scope(); $browser = scope.$service('$browser'); $browser.xhr.expectGET('phones/phones.json') @@ -140,7 +140,7 @@ describe('PhoneCat controllers', function() { We created the controller in the test environment, as follows: -* We created a root scope object by calling `angular.scope()` +* We created a root scope object by calling `angular.module.ng.$rootScope.Scope()` * We called `scope.$new(PhoneListCtrl)` to get angular to create the child scope associated with the `PhoneListCtrl` controller @@ -149,7 +149,7 @@ Because our code now uses the `$xhr` service to fetch the phone list data in our we create the `PhoneListCtrl` child scope, we need to tell the testing harness to expect an incoming request from the controller. To do this we: -* Use the {@link api/angular.scope.$service `$service`} method to retrieve the `$browser` service, +* Use the {@link api/angular.module.ng.$rootScope.Scope#$service `$service`} method to retrieve the `$browser` service, a service that angular uses to represent various browser APIs. In tests, angular automatically uses a mock version of this service that allows you to write tests without having to deal with these native APIs and the global state associated with them. diff --git a/docs/content/tutorial/step_07.ngdoc b/docs/content/tutorial/step_07.ngdoc index eaf7f4ab8c9c..1467a8a7d1c6 100644 --- a/docs/content/tutorial/step_07.ngdoc +++ b/docs/content/tutorial/step_07.ngdoc @@ -34,7 +34,7 @@ template into what we call a "layout template". This is a template that is commo our application. Other "partial templates" are then included into this layout template depending on the current "route" — the view that is currently displayed to the user. -Application routes in angular are declared via the {@link api/angular.service.$route $route} +Application routes in angular are declared via the {@link api/angular.module.ng.$route $route} service. This service makes it easy to wire together controllers, view templates, and the current URL location in the browser. Using this feature we can implement {@link http://en.wikipedia.org/wiki/Deep_linking deep linking}, which lets us utilize the browser's @@ -91,7 +91,7 @@ Note the use of the `:phoneId` parameter in the second route declaration. The `$ the route declaration — `'/phones/:phoneId'` — as a template that is matched against the current URL. All variables defined with the `:` notation are extracted into the `$route.current.params` map. -The `params` alias created in the {@link api/angular.service.$route `$route.onChange`} callback +The `params` alias created in the {@link api/angular.module.ng.$route `$route.onChange`} callback allows us to use the `phoneId` property of this map in the `phone-details.html` template. diff --git a/docs/content/tutorial/step_08.ngdoc b/docs/content/tutorial/step_08.ngdoc index 7d9c82d7d4fe..a81c689bcc80 100644 --- a/docs/content/tutorial/step_08.ngdoc +++ b/docs/content/tutorial/step_08.ngdoc @@ -15,7 +15,7 @@ phone in the phone list. Now when you click on a phone on the list, the phone details page with phone-specific information is displayed. -To implement the phone details view we will use {@link api/angular.service.$xhr $xhr} to fetch our +To implement the phone details view we will use {@link api/angular.module.ng.$xhr $xhr} to fetch our data, and we'll flesh out the `phone-details.html` view template. The most important changes are listed below. You can see the full diff on {@link diff --git a/docs/content/tutorial/step_09.ngdoc b/docs/content/tutorial/step_09.ngdoc index 7d8e34303a97..c0df9e1f096c 100644 --- a/docs/content/tutorial/step_09.ngdoc +++ b/docs/content/tutorial/step_09.ngdoc @@ -25,11 +25,11 @@ GitHub}: ## Custom Filter In order to create a new filter, simply register your custom filter function with the {@link -api/angular.filter `angular.filter`} API. +api/angular.module.ng.$filter `angular.module.ng.$filter`} API. __`app/js/filters.js`:__
-angular.filter('checkmark', function(input) {
+angular.module.ng.$filter('checkmark', function(input) {
   return input ? '\u2713' : '\u2718';
 });
 
@@ -82,8 +82,8 @@ __`test/unit/filtersSpec.js`:__ describe('checkmark filter', function() { it('should convert boolean values to unicode checkmark or cross', function() { - expect(angular.filter.checkmark(true)).toBe('\u2713'); - expect(angular.filter.checkmark(false)).toBe('\u2718'); + expect(angular.module.ng.$filter.checkmark(true)).toBe('\u2713'); + expect(angular.module.ng.$filter.checkmark(false)).toBe('\u2718'); }); })
@@ -99,7 +99,7 @@ output. # Experiments -* Let's experiment with some of the {@link api/angular.filter built-in angular filters} and add the +* Let's experiment with some of the {@link api/angular.module.ng.$filter built-in angular filters} and add the following bindings to `index.html`: * `{{ "lower cap string" | uppercase }}` * `{{ {foo: "bar", baz: 23} | json }}` diff --git a/docs/content/tutorial/step_11.ngdoc b/docs/content/tutorial/step_11.ngdoc index 450bf6799397..c6b700651aaf 100644 --- a/docs/content/tutorial/step_11.ngdoc +++ b/docs/content/tutorial/step_11.ngdoc @@ -14,7 +14,7 @@ In this step, you will improve the way our app fetches data. The last improvement we will make to our app is to define a custom service that represents a {@link http://en.wikipedia.org/wiki/Representational_State_Transfer RESTful} client. Using this client we can make xhr requests for data in an easier way, without having to deal with the lower-level {@link -api/angular.service.$xhr $xhr} API, HTTP methods and URLs. +api/angular.module.ng.$xhr $xhr} API, HTTP methods and URLs. The most important changes are listed below. You can see the full diff on {@link https://github.com/angular/angular-phonecat/compare/step-10...step-11 @@ -37,30 +37,30 @@ __`app/index.html`.__ __`app/js/services.js`.__
- angular.service('Phone', function($resource) {
+ angular.module.ng('Phone', function($resource) {
   return $resource('phones/:phoneId.json', {}, {
     query: {method: 'GET', params: {phoneId: 'phones'}, isArray: true}
   });
  });
 
-We used the {@link api/angular.service} API to register a custom service. We passed in the name of +We used the {@link api/angular.module.ng} API to register a custom service. We passed in the name of the service - 'Phone' - and a factory function. The factory function is similar to a controller's constructor in that both can declare dependencies via function arguments. The Phone service declared a dependency on the `$resource` service. -The {@link api/angular.service.$resource `$resource`} service makes it easy to create a {@link +The {@link api/angular.module.ng.$resource `$resource`} service makes it easy to create a {@link http://en.wikipedia.org/wiki/Representational_State_Transfer RESTful} client with just a few lines of code. This client can then be used in our application, instead of the lower-level {@link -api/angular.service.$xhr $xhr} service. +api/angular.module.ng.$xhr $xhr} service. ## Controller We simplified our sub-controllers (`PhoneListCtrl` and `PhoneDetailCtrl`) by factoring out the -lower-level {@link api/angular.service.$xhr $xhr} service, replacing it with a new service called -`Phone`. Angular's {@link api/angular.service.$resource `$resource`} service is easier to use than -{@link api/angular.service.$xhr $xhr} for interacting with data sources exposed as RESTful +lower-level {@link api/angular.module.ng.$xhr $xhr} service, replacing it with a new service called +`Phone`. Angular's {@link api/angular.module.ng.$resource `$resource`} service is easier to use than +{@link api/angular.module.ng.$xhr $xhr} for interacting with data sources exposed as RESTful resources. It is also easier now to understand what the code in our controllers is doing. __`app/js/controllers.js`.__ @@ -116,7 +116,7 @@ We have modified our unit tests to verify that our new service is issuing HTTP r processing them as expected. The tests also check that our controllers are interacting with the service correctly. -The {@link api/angular.service.$resource $resource} service augments the response object with +The {@link api/angular.module.ng.$resource $resource} service augments the response object with methods for updating and deleting the resource. If we were to use the standard `toEqual` matcher, our tests would fail because the test values would not match the responses exactly. To solve the problem, we use a newly-defined `toEqualData` {@link @@ -141,7 +141,7 @@ describe('PhoneCat controllers', function() { var scope, $browser, ctrl; beforeEach(function() { - scope = angular.scope(); + scope = angular.module.ng.$rootScope.Scope(); $browser = scope.$service('$browser'); $browser.xhr.expectGET('phones/phones.json') @@ -167,12 +167,12 @@ describe('PhoneCat controllers', function() { var scope, $browser, ctrl; beforeEach(function() { - scope = angular.scope(); + scope = angular.module.ng.$rootScope.Scope(); $browser = scope.$service('$browser'); }); beforeEach(function() { - scope = angular.scope(); + scope = angular.module.ng.$rootScope.Scope(); $browser = scope.$service('$browser'); }); diff --git a/docs/spec/domSpec.js b/docs/spec/domSpec.js index a967645e430c..5175b91a0e41 100644 --- a/docs/spec/domSpec.js +++ b/docs/spec/domSpec.js @@ -24,7 +24,7 @@ describe('dom', function() { dom.h('heading', function() { this.html('

sub-heading

'); }); - expect(dom.toString()).toContain('

heading

'); + expect(dom.toString()).toContain('

heading

'); expect(dom.toString()).toContain('

sub-heading

'); }); diff --git a/docs/spec/ngdocSpec.js b/docs/spec/ngdocSpec.js index 367f91b4fbbb..8f109e922817 100644 --- a/docs/spec/ngdocSpec.js +++ b/docs/spec/ngdocSpec.js @@ -54,6 +54,7 @@ describe('ngdoc', function() { it('should parse parameters', function() { var doc = new Doc( + '@name a\n' + '@param {*} a short\n' + '@param {Type} b med\n' + '@param {Class=} [c=2] long\nline'); @@ -66,7 +67,7 @@ describe('ngdoc', function() { }); it('should parse return', function() { - var doc = new Doc('@returns {Type} text *bold*.'); + var doc = new Doc('@name a\n@returns {Type} text *bold*.'); doc.parse(); expect(doc.returns).toEqual({ type: 'Type', @@ -82,7 +83,7 @@ describe('ngdoc', function() { }); it('should escape element', function() { - var doc = new Doc('@description before ' + + var doc = new Doc('@name a\n@description before ' + '\n<>\n after'); doc.parse(); expect(doc.description).toContain('

before

' + @@ -90,7 +91,7 @@ describe('ngdoc', function() { }); it('should preserve the source attribute', function() { - var doc = new Doc('@description before ' + + var doc = new Doc('@name a\n@description before ' + 'lala after'); doc.parse(); expect(doc.description).toContain('

before

' + @@ -98,7 +99,7 @@ describe('ngdoc', function() { }); it('should preserve the jsfiddle attribute', function() { - var doc = new Doc('@description before ' + + var doc = new Doc('@name a\n@description before ' + 'lala after'); doc.parse(); expect(doc.description).toContain('

before

' + @@ -106,7 +107,7 @@ describe('ngdoc', function() { }); it('should escape element', function() { - var doc = new Doc('@description before ' + + var doc = new Doc('@name a\n@description before ' + '\n<>\n after'); doc.parse(); expect(doc.description).toContain('

before

' + @@ -114,7 +115,7 @@ describe('ngdoc', function() { }); it('should store all links', function() { - var doc = new Doc('@description {@link api/angular.link}'); + var doc = new Doc('@name a\n@description {@link api/angular.link}'); doc.parse(); expect(doc.links).toContain('api/angular.link'); @@ -255,17 +256,17 @@ describe('ngdoc', function() { describe('merge', function() { it('should merge child with parent', function() { - var parent = new Doc({id: 'angular.service.abc', name: 'angular.service.abc', section: 'api'}); - var methodA = new Doc({name: 'methodA', methodOf: 'angular.service.abc'}); - var methodB = new Doc({name: 'methodB', methodOf: 'angular.service.abc'}); - var propA = new Doc({name: 'propA', propertyOf: 'angular.service.abc'}); - var propB = new Doc({name: 'propB', propertyOf: 'angular.service.abc'}); - var eventA = new Doc({name: 'eventA', eventOf: 'angular.service.abc'}); - var eventB = new Doc({name: 'eventB', eventOf: 'angular.service.abc'}); + var parent = new Doc({id: 'angular.module.ng.abc', name: 'angular.module.ng.abc', section: 'api'}); + var methodA = new Doc({name: 'methodA', methodOf: 'angular.module.ng.abc'}); + var methodB = new Doc({name: 'methodB', methodOf: 'angular.module.ng.abc'}); + var propA = new Doc({name: 'propA', propertyOf: 'angular.module.ng.abc'}); + var propB = new Doc({name: 'propB', propertyOf: 'angular.module.ng.abc'}); + var eventA = new Doc({name: 'eventA', eventOf: 'angular.module.ng.abc'}); + var eventB = new Doc({name: 'eventB', eventOf: 'angular.module.ng.abc'}); var docs = [methodB, methodA, eventB, eventA, propA, propB, parent]; // keep wrong order; ngdoc.merge(docs); expect(docs.length).toEqual(1); - expect(docs[0].id).toEqual('angular.service.abc'); + expect(docs[0].id).toEqual('angular.module.ng.abc'); expect(docs[0].methods).toEqual([methodA, methodB]); expect(docs[0].events).toEqual([eventA, eventB]); expect(docs[0].properties).toEqual([propA, propB]); @@ -305,7 +306,7 @@ describe('ngdoc', function() { describe('TAG', function() { describe('@param', function() { it('should parse with no default', function() { - var doc = new Doc('@param {(number|string)} number Number \n to format.'); + var doc = new Doc('@name a\n@param {(number|string)} number Number \n to format.'); doc.parse(); expect(doc.param).toEqual([{ type : '(number|string)', @@ -316,7 +317,7 @@ describe('ngdoc', function() { }); it('should parse with default and optional', function() { - var doc = new Doc('@param {(number|string)=} [fractionSize=2] desc'); + var doc = new Doc('@name a\n@param {(number|string)=} [fractionSize=2] desc'); doc.parse(); expect(doc.param).toEqual([{ type : '(number|string)', @@ -329,14 +330,14 @@ describe('ngdoc', function() { describe('@requires', function() { it('should parse more @requires tag into array', function() { - var doc = new Doc('@requires $service for \n`A`\n@requires $another for `B`'); + var doc = new Doc('@name a\n@requires $service for \n`A`\n@requires $another for `B`'); doc.ngdoc = 'service'; doc.parse(); expect(doc.requires).toEqual([ {name:'$service', text:'

for \nA

'}, {name:'$another', text:'

for B

'}]); - expect(doc.html()).toContain('$service'); - expect(doc.html()).toContain('$another'); + expect(doc.html()).toContain('$service'); + expect(doc.html()).toContain('$another'); expect(doc.html()).toContain('

for \nA

'); expect(doc.html()).toContain('

for B

'); }); @@ -344,7 +345,7 @@ describe('ngdoc', function() { describe('@property', function() { it('should parse @property tags into array', function() { - var doc = new Doc("@property {type} name1 desc\n@property {type} name2 desc"); + var doc = new Doc("@name a\n@property {type} name1 desc\n@property {type} name2 desc"); doc.parse(); expect(doc.properties.length).toEqual(2); }); @@ -356,21 +357,21 @@ describe('ngdoc', function() { }); it('should parse @property with type', function() { - var doc = new Doc("@property {string} name"); + var doc = new Doc("@name a\n@property {string} name"); doc.parse(); expect(doc.properties[0].name).toEqual('name'); expect(doc.properties[0].type).toEqual('string'); }); it('should parse @property with optional description', function() { - var doc = new Doc("@property {string} name desc rip tion"); + var doc = new Doc("@name a\n@property {string} name desc rip tion"); doc.parse(); expect(doc.properties[0].name).toEqual('name'); expect(doc.properties[0].description).toEqual('

desc rip tion

'); }); it('should parse @property with type and description both', function() { - var doc = new Doc("@property {bool} name desc rip tion"); + var doc = new Doc("@name a\n@property {bool} name desc rip tion"); doc.parse(); expect(doc.properties[0].name).toEqual('name'); expect(doc.properties[0].type).toEqual('bool'); @@ -386,19 +387,19 @@ describe('ngdoc', function() { }); it('should parse @returns with type and description', function() { - var doc = new Doc("@returns {string} descrip tion"); + var doc = new Doc("@name a\n@returns {string} descrip tion"); doc.parse(); expect(doc.returns).toEqual({type: 'string', description: '

descrip tion

'}); }); it('should transform description of @returns with markdown', function() { - var doc = new Doc("@returns {string} descrip *tion*"); + var doc = new Doc("@name a\n@returns {string} descrip *tion*"); doc.parse(); expect(doc.returns).toEqual({type: 'string', description: '

descrip tion

'}); }); it('should support multiline content', function() { - var doc = new Doc("@returns {string} description\n new line\n another line"); + var doc = new Doc("@name a\n@returns {string} description\n new line\n another line"); doc.parse(); expect(doc.returns). toEqual({type: 'string', description: '

description\nnew line\nanother line

'}); @@ -407,14 +408,14 @@ describe('ngdoc', function() { describe('@description', function() { it('should support pre blocks', function() { - var doc = new Doc("@description
abc
"); + var doc = new Doc("@name a\n@description
abc
"); doc.parse(); expect(doc.description). toBe('
<b>abc</b>
'); }); it('should support multiple pre blocks', function() { - var doc = new Doc("@description foo \n
abc
\n#bah\nfoo \n
cba
"); + var doc = new Doc("@name a\n@description foo \n
abc
\n#bah\nfoo \n
cba
"); doc.parse(); expect(doc.description). toBe('

foo

' + @@ -426,7 +427,7 @@ describe('ngdoc', function() { }); it('should support nested @link annotations with or without description', function() { - var doc = new Doc("@description " + + var doc = new Doc("@name a\n@description " + 'foo {@link angular.foo}\n\n da {@link angular.foo bar foo bar } \n\n' + 'dad{@link angular.foo}\n\n' + 'external{@link http://angularjs.org}\n\n' + @@ -451,7 +452,7 @@ describe('ngdoc', function() { }); it('should support line breaks in @link', function() { - var doc = new Doc("@description " + + var doc = new Doc("@name a\n@description " + '{@link\napi/angular.foo\na\nb}'); doc.parse(); expect(doc.description). @@ -462,13 +463,13 @@ describe('ngdoc', function() { describe('@example', function() { it('should not remove {{}}', function() { - var doc = new Doc('@example text {{ abc }}'); + var doc = new Doc('@name a\n@example text {{ abc }}'); doc.parse(); expect(doc.example).toEqual('

text {{ abc }}

'); }); it('should support doc:example', function() { - var doc = new Doc('@ngdoc overview\n@example \n' + + var doc = new Doc('@name a\n@ngdoc overview\n@example \n' + '\n' + ' \n' + ' \n' + @@ -482,7 +483,7 @@ describe('ngdoc', function() { describe('@deprecated', function() { it('should parse @deprecated', function() { - var doc = new Doc('@deprecated Replaced with foo.'); + var doc = new Doc('@name a\n@deprecated Replaced with foo.'); doc.parse(); expect(doc.deprecated).toBe('Replaced with foo.'); }); @@ -490,7 +491,7 @@ describe('ngdoc', function() { describe('@this', function() { it('should render @this', function() { - var doc = new Doc('@this I am self.'); + var doc = new Doc('@name a\n@this I am self.'); doc.ngdoc = 'filter'; doc.parse(); expect(doc.html()).toContain('

Method\'s this

\n' + @@ -528,7 +529,7 @@ describe('ngdoc', function() { returns: {type: 'number', description: 'return desc'} }); doc.html_usage_function(dom); - expect(dom).toContain('some.name([a][, b], c)'); //TODO(i) the comma position here is lame + expect(dom).toContain('name([a][, b], c)'); //TODO(i) the comma position here is lame expect(dom).toContain('param desc'); expect(dom).toContain('(optional="xxx")'); expect(dom).toContain('return desc'); @@ -547,7 +548,7 @@ describe('ngdoc', function() { }); doc.html_usage_filter(dom); expect(dom).toContain('myFilter_expression | myFilter:b'); - expect(dom).toContain('angular.filter.myFilter(a, b)'); + expect(dom).toContain('$filter(\'myFilter\')(a, b)'); }); }); diff --git a/docs/src/dom.js b/docs/src/dom.js index ccfee7ac0219..7363d06bdac9 100644 --- a/docs/src/dom.js +++ b/docs/src/dom.js @@ -74,13 +74,25 @@ DOM.prototype = { }); }, + div: function(attr, text) { + this.tag('div', attr, text); + }, + h: function(heading, content, fn){ if (content==undefined || (content instanceof Array && content.length == 0)) return; this.headingDepth++; - this.tag('h' + this.headingDepth, heading); - var className = typeof heading == 'string' - ? {'class': heading.toLowerCase().replace(/[^\d\w_]/mg, '-').replace(/-+/gm, '-')} - : null; + var className = null, + anchor = null; + if (typeof heading == 'string') { + var id = heading. + replace(/\(.*\)/mg, ''). + replace(/[^\d\w]/mg, '.'). + replace(/-+/gm, '-'). + replace(/-*$/gm, ''); + anchor = {'id': id}; + className = {'class': id.toLowerCase().replace(/[._]/mg, '-')}; + } + this.tag('h' + this.headingDepth, anchor, heading); if (content instanceof Array) { this.ul(content, className, fn); } else if (fn) { diff --git a/docs/src/ngdoc.js b/docs/src/ngdoc.js index 562144b517c2..a0536266d695 100644 --- a/docs/src/ngdoc.js +++ b/docs/src/ngdoc.js @@ -89,6 +89,7 @@ Doc.prototype = { var self = this, IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:|\.|\/)/, IS_ANGULAR = /^(api\/)?angular\./, + IS_HASH = /^#/, parts = trim(text).split(/(
[\s\S]*?<\/pre>|[\s\S]*?<\/doc:\2>)/);
 
     parts.forEach(function(text, i) {
@@ -134,13 +135,16 @@ Doc.prototype = {
           function(_all, url, title){
             var isFullUrl = url.match(IS_URL),
                 isAngular = url.match(IS_ANGULAR),
-                absUrl = isFullUrl ? url : self.convertUrlToAbsolute(url);
+                isHash = url.match(IS_HASH),
+                absUrl = isHash
+                  ? url
+                  : (isFullUrl ? url : self.convertUrlToAbsolute(url));
 
             if (!isFullUrl) self.links.push(absUrl);
 
             return '' +
               (isAngular ? '' : '') +
-              (title || url).replace(/\n/g, ' ') +
+              (title || url).replace(/^#/g, '').replace(/\n/g, ' ') +
               (isAngular ? '' : '') +
               '';
           });
@@ -171,7 +175,7 @@ Doc.prototype = {
       }
     });
     flush();
-    this.shortName = (this.name || '').split(/[\.#]/).pop();
+    this.shortName = this.name.split(this.name.match(/#/) ? /#/ : /\./ ).pop();
     this.id = this.id || // if we have an id just use it
       (((this.file||'').match(/.*\/([^\/]*)\.ngdoc/)||{})[1]) || // try to extract it from file name
       this.name; // default to name
@@ -217,11 +221,12 @@ Doc.prototype = {
           if (!match) {
             throw new Error("Not a valid 'property' format: " + text);
           }
-          var property = {
+          var property = new Doc({
               type: match[1],
               name: match[2],
+              shortName: match[2],
               description: self.markdown(text.replace(match[0], match[4]))
-            };
+            });
           self.properties.push(property);
         } else if(atName == 'eventType') {
           match = text.match(/^([^\s]*)\s+on\s+([\S\s]*)/);
@@ -246,7 +251,7 @@ Doc.prototype = {
       }
       dom.h('Dependencies', self.requires, function(require){
         dom.tag('code', function() {
-          dom.tag('a', {href: 'api/angular.service.' + require.name}, require.name);
+          dom.tag('a', {href: 'api/angular.module.ng.' + require.name}, require.name);
         });
         dom.html(require.text);
       });
@@ -319,7 +324,7 @@ Doc.prototype = {
     var self = this;
     dom.h('Usage', function() {
       dom.code(function() {
-        dom.text(self.name.split('service.').pop());
+        dom.text(self.name.split(/\./).pop());
         dom.text('(');
         self.parameters(dom, ', ');
         dom.text(');');
@@ -329,6 +334,7 @@ Doc.prototype = {
       self.html_usage_this(dom);
       self.html_usage_returns(dom);
     });
+    this.method_properties_events(dom);
   },
 
   html_usage_property: function(dom){
@@ -374,9 +380,9 @@ Doc.prototype = {
 
       dom.h('In JavaScript', function() {
         dom.tag('code', function() {
-          dom.text('angular.filter.');
+          dom.text('$filter(\'');
           dom.text(self.shortName);
-          dom.text('(');
+          dom.text('\')(');
           self.parameters(dom, ', ');
           dom.text(')');
         });
@@ -450,7 +456,7 @@ Doc.prototype = {
     dom.html(this.description);
   },
 
-  html_usage_service: function(dom){
+  html_usage_object: function(dom){
     var self = this;
 
     if (this.param.length) {
@@ -467,45 +473,69 @@ Doc.prototype = {
         self.html_usage_returns(dom);
       });
     }
+    this.method_properties_events(dom);
+  },
 
-    dom.h('Methods', this.methods, function(method){
-      var signature = (method.param || []).map(property('name'));
-      dom.h(method.shortName + '(' + signature.join(', ') + ')', method, function() {
-        dom.html(method.description);
-        method.html_usage_parameters(dom);
-        self.html_usage_this(dom);
-        method.html_usage_returns(dom);
+  html_usage_service: function(dom) {
+    this.html_usage_object(dom)
+  },
 
-        dom.h('Example', method.example, dom.html);
-      });
-    });
-    dom.h('Properties', this.properties, function(property){
-      dom.h(property.name, function() {
-       dom.html(property.description);
-       dom.h('Example', property.example, dom.html);
-      });
-    });
-    dom.h('Events', this.events, function(event){
-    dom.h(event.shortName, event, function() {
-        dom.html(event.description);
-        if (event.type == 'listen') {
-          dom.tag('div', {class:'inline'}, function() {
-            dom.h('Listen on:', event.target);
-          });
-        } else {
-          dom.tag('div', {class:'inline'}, function() {
-            dom.h('Type:', event.type);
+  method_properties_events: function(dom) {
+    var self = this;
+    if (self.methods.length) {
+      dom.div({class:'member method'}, function(){
+        dom.h('Methods', self.methods, function(method){
+          var signature = (method.param || []).map(property('name'));
+          dom.h(method.shortName + '(' + signature.join(', ') + ')', method, function() {
+            dom.html(method.description);
+            method.html_usage_parameters(dom);
+            self.html_usage_this(dom);
+            method.html_usage_returns(dom);
+
+            dom.h('Example', method.example, dom.html);
           });
-          dom.tag('div', {class:'inline'}, function() {
-            dom.h('Target:', event.target);
+        });
+      });
+    }
+    if (self.properties.length) {
+      dom.div({class:'member property'}, function(){
+        dom.h('Properties', self.properties, function(property){
+          dom.h(property.shortName, function() {
+           dom.html(property.description);
+           if (!property.html_usage_returns) {
+             console.log(property);
+           }
+           property.html_usage_returns(dom);
+           dom.h('Example', property.example, dom.html);
           });
-        }
-        event.html_usage_parameters(dom);
-        self.html_usage_this(dom);
+        });
+      });
+    }
+    if (self.events.length) {
+      dom.div({class:'member event'}, function(){
+        dom.h('Events', self.events, function(event){
+          dom.h(event.shortName, event, function() {
+            dom.html(event.description);
+            if (event.type == 'listen') {
+              dom.tag('div', {class:'inline'}, function() {
+                dom.h('Listen on:', event.target);
+              });
+            } else {
+              dom.tag('div', {class:'inline'}, function() {
+                dom.h('Type:', event.type);
+              });
+              dom.tag('div', {class:'inline'}, function() {
+                dom.h('Target:', event.target);
+              });
+            }
+            event.html_usage_parameters(dom);
+            self.html_usage_this(dom);
 
-        dom.h('Example', event.example, dom.html);
+            dom.h('Example', event.example, dom.html);
+          });
+        });
       });
-    });
+    }
   },
 
   parameters: function(dom, separator, skipFirst, prefix) {
@@ -589,12 +619,12 @@ var KEYWORD_PRIORITY = {
   '.index': 1,
   '.guide': 2,
   '.angular': 7,
-  '.angular.Array': 7,
+  '.angular.module.ng.$filter': 7,
   '.angular.Object': 7,
   '.angular.directive': 7,
-  '.angular.filter': 7,
-  '.angular.scope': 7,
-  '.angular.service': 7,
+  '.angular.module.ng.$filter': 7,
+  '.angular.module.ng.$rootScope.Scope': 7,
+  '.angular.module.ng': 7,
   '.angular.inputType': 7,
   '.angular.widget': 7,
   '.angular.mock': 8,
@@ -693,7 +723,13 @@ function merge(docs){
 
     // check links - do they exist ?
     doc.links.forEach(function(link) {
-      if (!byFullId[link]) console.log('WARNING: In ' + doc.section + '/' + doc.id + ', non existing link: "' + link + '"');
+      // convert #id to path#id
+      if (link[0] == '#') {
+        link = doc.section + '/' + doc.id.split('#').shift() + link;
+      }
+      if (!byFullId[link]) {
+        console.log('WARNING: In ' + doc.section + '/' + doc.id + ', non existing link: "' + link + '"');
+      }
     });
 
     // merge into parents
diff --git a/docs/src/reader.js b/docs/src/reader.js
index 576ae2e41b5a..ded573c16ad2 100644
--- a/docs/src/reader.js
+++ b/docs/src/reader.js
@@ -22,7 +22,6 @@ function collect() {
     files.forEach(function(file) {
       var work;
       if(/\.js$/.test(file)) {
-        console.log("reading " + file + ".......");
         work = Q.when(qfs.read(file, 'b'), function(content) {
           processJsFile(content, file).forEach (function(doc) {
             allDocs.push(doc);
@@ -36,14 +35,13 @@ function collect() {
     return done;
   });
 
-   //collect all NG Docs in Content Folder
+   //collect all ng Docs in Content Folder
    var path2 = 'docs/content';
    var promiseB = Q.when(qfs.listTree(path2), function(files){
      var done2;
      files.forEach(function(file) {
        var work2;
        if (file.match(/\.ngdoc$/)) {
-         console.log("reading " + file + ".......");
          work2 = Q.when(qfs.read(file, 'b'), function(content){
             var section = '@section ' + file.split('/')[2] + '\n';
             allDocs.push(new ngdoc.Doc(section + content.toString(),file, 1).parse());
@@ -95,4 +93,4 @@ function processJsFile(content, file) {
     }
   });
   return docs;
-}
\ No newline at end of file
+}
diff --git a/docs/src/templates/doc_widgets.js b/docs/src/templates/doc_widgets.js
index 56ef5bcf4ffb..eb8f36f66e89 100644
--- a/docs/src/templates/doc_widgets.js
+++ b/docs/src/templates/doc_widgets.js
@@ -15,14 +15,15 @@
   var HTML_TEMPLATE =
   '\n' +
   '\n' +
-  ' \n' +
+  ' \n' +
   ' \n' +
   '_HTML_SOURCE_\n' +
   ' \n' +
   '';
 
-  angular.widget('doc:example', function(element){
+  angular.widget('doc:example', ['$injector', '$element', function($injector, element){
     this.descend(true); //compile the example code
+    var module = element.attr('module');
 
     //jQuery find() methods in this widget contain primitive selectors on purpose so that we can use
     //jqlite instead. jqlite's find() method currently supports onlt getElementsByTagName!
@@ -59,7 +60,10 @@
       '';
     var tabs = angular.element(tabHtml);
 
-    tabs.find('li').eq(1).find('pre').text(HTML_TEMPLATE.replace('_HTML_SOURCE_', code.html));
+    tabs.find('li').eq(1).find('pre').text(
+      HTML_TEMPLATE.
+        replace('_HTML_SOURCE_', code.html).
+        replace('_MODULE_', (module ? (' ng:module="' + module + '"') : '')));
 
     element.html('');
     element.append(tabs);
@@ -76,6 +80,11 @@
       alert(e);
     }
 
+    if (module) {
+      $injector.invoke(null, angular.module[module]);
+    }
+
+
     function jsFiddleButton(jsfiddle) {
       if (jsfiddle !== 'false') {
         if(jsfiddle === true) {
@@ -100,7 +109,7 @@
                     '' +
                     '' +
                     '' +
@@ -116,7 +125,7 @@
       }
       return '';
     }
-  });
+  }]);
 
   function indent(text) {
     if (!text) return text;
diff --git a/docs/src/templates/docs.css b/docs/src/templates/docs.css
index d42ec093ebaa..b3f9aad926ea 100644
--- a/docs/src/templates/docs.css
+++ b/docs/src/templates/docs.css
@@ -53,6 +53,42 @@ li {
   border: 1px solid red;
 }
 
+.member {
+  border: 1px solid gray;
+  margin: 2em 0;
+}
+
+.member p {
+  padding: 0;
+}
+
+.member>h2 {
+  background-color: lightgray;
+  padding: .2em .4em;
+  margin: 0;
+  border-bottom: 1px solid gray;
+}
+
+.member>ul {
+  list-style: none;
+  padding: 0;
+}
+
+.member>ul>li {
+  border: 1px solid lightgray;
+  margin: 1em;
+
+}
+.member>ul>li>h3 {
+  background-color: #EEE;
+  padding: .2em .4em;
+  margin: 0;
+  font-family: monospace;
+  border-bottom: 1px solid lightgray;
+}
+.member>ul>li>div {
+  padding: 1em;
+}
 
 /*----- Upgrade IE Prompt -----*/
 
@@ -240,23 +276,25 @@ li {
 }
 
 #content-list .level-1 {
-  font-size: 1.1em;
-  font-weight: bold;
+  margin-left: 0em;
 }
 
-#content-list .level-2,
-#content-list .level-3 {
+#content-list .level-2 {
   margin-left: 1em;
 }
 
-#content-list .level-4 {
+#content-list .level-3 {
   margin-left: 2em;
 }
 
-#content-list .level-5 {
+#content-list .level-4 {
   margin-left: 3em;
 }
 
+#content-list .level-5 {
+  margin-left: 4em;
+}
+
 
 #content-list a.current {
   font-weight: bold;
@@ -474,3 +512,11 @@ td.empty-corner-lt {
 .error {
    color: red;
 }
+
+.odd {
+  background-color: #808080;
+}
+
+.even {
+  background-color: #d3d3d3;
+}
diff --git a/docs/src/templates/docs.js b/docs/src/templates/docs.js
index b50333a55600..5b6379a69604 100644
--- a/docs/src/templates/docs.js
+++ b/docs/src/templates/docs.js
@@ -1,11 +1,12 @@
-DocsController.$inject = ['$location', '$window', '$cookies'];
-function DocsController($location, $window, $cookies) {
+DocsController.$inject = ['$location', '$window', '$cookies', '$filter'];
+function DocsController($location, $window, $cookies, $filter) {
   window.$root = this.$root;
 
   var scope = this,
       OFFLINE_COOKIE_NAME = 'ng-offline',
       DOCS_PATH = /^\/(api)|(guide)|(cookbook)|(misc)|(tutorial)/,
-      INDEX_PATH = /^(\/|\/index[^\.]*.html)$/;
+      INDEX_PATH = /^(\/|\/index[^\.]*.html)$/,
+      filter = $filter('filter');
 
   scope.$location = $location;
   scope.versionNumber = angular.version.full;
@@ -25,7 +26,7 @@ function DocsController($location, $window, $cookies) {
       var parts = path.split('/');
       scope.sectionId = parts[1];
       scope.partialId = parts[2] || 'index';
-      scope.pages = angular.Array.filter(NG_PAGES, {section: scope.sectionId});
+      scope.pages = filter(NG_PAGES, {section: scope.sectionId});
 
       var i = scope.pages.length;
       while (i--) {
@@ -148,9 +149,17 @@ function TutorialInstructionsCtrl($cookieStore) {
   };
 }
 
-angular.service('$locationConfig', function() {
-  return {
-    html5Mode: true,
-    hashPrefix: '!'
-  };
-});
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+
+angular.module.ngdocs = function($locationProvider, $filterProvider) {
+  $locationProvider.html5Mode(true).hashPrefix('!');
+
+  $filterProvider.register('title', function(){
+    return function(text) {
+      return text && text.replace(/^angular\.module\.([^\.]+)(\.(.*))?$/, function(_, module, _0, name){
+        return 'Module ' + module + (name ? ' - ' + name : '');
+      });
+    }
+  });
+};
diff --git a/docs/src/templates/index.html b/docs/src/templates/index.html
index 490363098ac0..8a6dc7a73931 100644
--- a/docs/src/templates/index.html
+++ b/docs/src/templates/index.html
@@ -6,7 +6,7 @@
 
   
   
-  AngularJS
+  AngularJS
   
     
   
   
diff --git a/i18n/locale/angular-locale_am-et.js b/i18n/locale/angular-locale_am-et.js
index 4e5560208bd0..3afec4ac2592 100644
--- a/i18n/locale/angular-locale_am-et.js
+++ b/i18n/locale/angular-locale_am-et.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Br"},"pluralCat":function(n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ጃንዩወሪ","ፌብሩወሪ","ማርች","ኤፕረል","ሜይ","ጁን","ጁላይ","ኦገስት","ሴፕቴምበር","ኦክተውበር","ኖቬምበር","ዲሴምበር"],"SHORTMONTH":["ጃንዩ","ፌብሩ","ማርች","ኤፕረ","ሜይ","ጁን","ጁላይ","ኦገስ","ሴፕቴ","ኦክተ","ኖቬም","ዲሴም"],"DAY":["እሑድ","ሰኞ","ማክሰኞ","ረቡዕ","ሐሙስ","ዓርብ","ቅዳሜ"],"SHORTDAY":["እሑድ","ሰኞ","ማክሰ","ረቡዕ","ሐሙስ","ዓርብ","ቅዳሜ"],"AMPMS":["ጡዋት","ከሳዓት"],"medium":"d MMM y h:mm:ss a","short":"dd/MM/yyyy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yyyy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"am-et"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Br"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ጃንዩወሪ","ፌብሩወሪ","ማርች","ኤፕረል","ሜይ","ጁን","ጁላይ","ኦገስት","ሴፕቴምበር","ኦክተውበር","ኖቬምበር","ዲሴምበር"],"SHORTMONTH":["ጃንዩ","ፌብሩ","ማርች","ኤፕረ","ሜይ","ጁን","ጁላይ","ኦገስ","ሴፕቴ","ኦክተ","ኖቬም","ዲሴም"],"DAY":["እሑድ","ሰኞ","ማክሰኞ","ረቡዕ","ሐሙስ","ዓርብ","ቅዳሜ"],"SHORTDAY":["እሑድ","ሰኞ","ማክሰ","ረቡዕ","ሐሙስ","ዓርብ","ቅዳሜ"],"AMPMS":["ጡዋት","ከሳዓት"],"medium":"d MMM y h:mm:ss a","short":"dd/MM/yyyy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yyyy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"am-et"});
+}];
diff --git a/i18n/locale/angular-locale_am.js b/i18n/locale/angular-locale_am.js
index a9c8e146eb56..748df957f851 100644
--- a/i18n/locale/angular-locale_am.js
+++ b/i18n/locale/angular-locale_am.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["ጃንዩወሪ","ፌብሩወሪ","ማርች","ኤፕረል","ሜይ","ጁን","ጁላይ","ኦገስት","ሴፕቴምበር","ኦክተውበር","ኖቬምበር","ዲሴምበር"],"SHORTMONTH":["ጃንዩ","ፌብሩ","ማርች","ኤፕረ","ሜይ","ጁን","ጁላይ","ኦገስ","ሴፕቴ","ኦክተ","ኖቬም","ዲሴም"],"DAY":["እሑድ","ሰኞ","ማክሰኞ","ረቡዕ","ሐሙስ","ዓርብ","ቅዳሜ"],"SHORTDAY":["እሑድ","ሰኞ","ማክሰ","ረቡዕ","ሐሙስ","ዓርብ","ቅዳሜ"],"AMPMS":["ጡዋት","ከሳዓት"],"medium":"d MMM y h:mm:ss a","short":"dd/MM/yyyy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yyyy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Br"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"am"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["ጃንዩወሪ","ፌብሩወሪ","ማርች","ኤፕረል","ሜይ","ጁን","ጁላይ","ኦገስት","ሴፕቴምበር","ኦክተውበር","ኖቬምበር","ዲሴምበር"],"SHORTMONTH":["ጃንዩ","ፌብሩ","ማርች","ኤፕረ","ሜይ","ጁን","ጁላይ","ኦገስ","ሴፕቴ","ኦክተ","ኖቬም","ዲሴም"],"DAY":["እሑድ","ሰኞ","ማክሰኞ","ረቡዕ","ሐሙስ","ዓርብ","ቅዳሜ"],"SHORTDAY":["እሑድ","ሰኞ","ማክሰ","ረቡዕ","ሐሙስ","ዓርብ","ቅዳሜ"],"AMPMS":["ጡዋት","ከሳዓት"],"medium":"d MMM y h:mm:ss a","short":"dd/MM/yyyy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yyyy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Br"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"am"});
+}];
diff --git a/i18n/locale/angular-locale_ar-eg.js b/i18n/locale/angular-locale_ar-eg.js
index e4ed06a5b8d7..afd97b49ad59 100644
--- a/i18n/locale/angular-locale_ar-eg.js
+++ b/i18n/locale/angular-locale_ar-eg.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"","negSuf":"-","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 ","negSuf":"-","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"£"},"pluralCat":function (n) {  if (n == 0) {    return PLURAL_CATEGORY.ZERO;  }  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 2) {    return PLURAL_CATEGORY.TWO;  }  if ((n % 100) >= 3 && (n % 100) <= 10 && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 100) >= 11 && (n % 100) <= 99 && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],"SHORTMONTH":["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],"DAY":["الأحد","الإثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],"SHORTDAY":["أحد","إثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],"AMPMS":["ص","م"],"medium":"dd‏/MM‏/yyyy h:mm:ss a","short":"d‏/M‏/yyyy h:mm a","fullDate":"EEEE، d MMMM، y","longDate":"d MMMM، y","mediumDate":"dd‏/MM‏/yyyy","shortDate":"d‏/M‏/yyyy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"ar-eg"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"","negSuf":"-","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 ","negSuf":"-","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"£"},"pluralCat":function (n) {  if (n == 0) {    return PLURAL_CATEGORY.ZERO;  }  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 2) {    return PLURAL_CATEGORY.TWO;  }  if ((n % 100) >= 3 && (n % 100) <= 10 && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 100) >= 11 && (n % 100) <= 99 && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],"SHORTMONTH":["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],"DAY":["الأحد","الإثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],"SHORTDAY":["أحد","إثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],"AMPMS":["ص","م"],"medium":"dd‏/MM‏/yyyy h:mm:ss a","short":"d‏/M‏/yyyy h:mm a","fullDate":"EEEE، d MMMM، y","longDate":"d MMMM، y","mediumDate":"dd‏/MM‏/yyyy","shortDate":"d‏/M‏/yyyy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"ar-eg"});
+}];
diff --git a/i18n/locale/angular-locale_ar.js b/i18n/locale/angular-locale_ar.js
index a03fb9da26af..15db1de5dd92 100644
--- a/i18n/locale/angular-locale_ar.js
+++ b/i18n/locale/angular-locale_ar.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],"SHORTMONTH":["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],"DAY":["الأحد","الإثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],"SHORTDAY":["أحد","إثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],"AMPMS":["ص","م"],"medium":"dd‏/MM‏/yyyy h:mm:ss a","short":"d‏/M‏/yyyy h:mm a","fullDate":"EEEE، d MMMM، y","longDate":"d MMMM، y","mediumDate":"dd‏/MM‏/yyyy","shortDate":"d‏/M‏/yyyy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"","negSuf":"-","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 ","negSuf":"-","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"£"},"pluralCat":function (n) {  if (n == 0) {    return PLURAL_CATEGORY.ZERO;  }  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 2) {    return PLURAL_CATEGORY.TWO;  }  if ((n % 100) >= 3 && (n % 100) <= 10 && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 100) >= 11 && (n % 100) <= 99 && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"id":"ar"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],"SHORTMONTH":["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],"DAY":["الأحد","الإثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],"SHORTDAY":["أحد","إثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],"AMPMS":["ص","م"],"medium":"dd‏/MM‏/yyyy h:mm:ss a","short":"d‏/M‏/yyyy h:mm a","fullDate":"EEEE، d MMMM، y","longDate":"d MMMM، y","mediumDate":"dd‏/MM‏/yyyy","shortDate":"d‏/M‏/yyyy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"","negSuf":"-","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 ","negSuf":"-","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"£"},"pluralCat":function (n) {  if (n == 0) {    return PLURAL_CATEGORY.ZERO;  }  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 2) {    return PLURAL_CATEGORY.TWO;  }  if ((n % 100) >= 3 && (n % 100) <= 10 && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 100) >= 11 && (n % 100) <= 99 && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"id":"ar"});
+}];
diff --git a/i18n/locale/angular-locale_bg-bg.js b/i18n/locale/angular-locale_bg-bg.js
index 7dfc3056e40a..e19ed7679a55 100644
--- a/i18n/locale/angular-locale_bg-bg.js
+++ b/i18n/locale/angular-locale_bg-bg.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"лв"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["януари","февруари","март","април","май","юни","юли","август","септември","октомври","ноември","декември"],"SHORTMONTH":["ян.","февр.","март","апр.","май","юни","юли","авг.","септ.","окт.","ноем.","дек."],"DAY":["неделя","понеделник","вторник","сряда","четвъртък","петък","събота"],"SHORTDAY":["нд","пн","вт","ср","чт","пт","сб"],"AMPMS":["пр. об.","сл. об."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"dd MMMM y, EEEE","longDate":"dd MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"bg-bg"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"лв"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["януари","февруари","март","април","май","юни","юли","август","септември","октомври","ноември","декември"],"SHORTMONTH":["ян.","февр.","март","апр.","май","юни","юли","авг.","септ.","окт.","ноем.","дек."],"DAY":["неделя","понеделник","вторник","сряда","четвъртък","петък","събота"],"SHORTDAY":["нд","пн","вт","ср","чт","пт","сб"],"AMPMS":["пр. об.","сл. об."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"dd MMMM y, EEEE","longDate":"dd MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"bg-bg"});
+}];
diff --git a/i18n/locale/angular-locale_bg.js b/i18n/locale/angular-locale_bg.js
index 2e2480b70150..00f04b107b43 100644
--- a/i18n/locale/angular-locale_bg.js
+++ b/i18n/locale/angular-locale_bg.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["януари","февруари","март","април","май","юни","юли","август","септември","октомври","ноември","декември"],"SHORTMONTH":["ян.","февр.","март","апр.","май","юни","юли","авг.","септ.","окт.","ноем.","дек."],"DAY":["неделя","понеделник","вторник","сряда","четвъртък","петък","събота"],"SHORTDAY":["нд","пн","вт","ср","чт","пт","сб"],"AMPMS":["пр. об.","сл. об."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"dd MMMM y, EEEE","longDate":"dd MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"лв"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"bg"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["януари","февруари","март","април","май","юни","юли","август","септември","октомври","ноември","декември"],"SHORTMONTH":["ян.","февр.","март","апр.","май","юни","юли","авг.","септ.","окт.","ноем.","дек."],"DAY":["неделя","понеделник","вторник","сряда","четвъртък","петък","събота"],"SHORTDAY":["нд","пн","вт","ср","чт","пт","сб"],"AMPMS":["пр. об.","сл. об."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"dd MMMM y, EEEE","longDate":"dd MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"лв"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"bg"});
+}];
diff --git a/i18n/locale/angular-locale_bn-bd.js b/i18n/locale/angular-locale_bn-bd.js
index 2d206bfdf4ce..ba597126b580 100644
--- a/i18n/locale/angular-locale_bn-bd.js
+++ b/i18n/locale/angular-locale_bn-bd.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":"\u00A4","negPre":"(","negSuf":"\u00A4)","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"৳"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["জানুয়ারী","ফেব্রুয়ারী","মার্চ","এপ্রিল","মে","জুন","জুলাই","আগস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],"SHORTMONTH":["জানুয়ারী","ফেব্রুয়ারী","মার্চ","এপ্রিল","মে","জুন","জুলাই","আগস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],"DAY":["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহষ্পতিবার","শুক্রবার","শনিবার"],"SHORTDAY":["রবি","সোম","মঙ্গল","বুধ","বৃহস্পতি","শুক্র","শনি"],"AMPMS":["am","pm"],"medium":"d MMM, y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, d MMMM, y","longDate":"d MMMM, y","mediumDate":"d MMM, y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"bn-bd"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":"\u00A4","negPre":"(","negSuf":"\u00A4)","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"৳"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["জানুয়ারী","ফেব্রুয়ারী","মার্চ","এপ্রিল","মে","জুন","জুলাই","আগস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],"SHORTMONTH":["জানুয়ারী","ফেব্রুয়ারী","মার্চ","এপ্রিল","মে","জুন","জুলাই","আগস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],"DAY":["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহষ্পতিবার","শুক্রবার","শনিবার"],"SHORTDAY":["রবি","সোম","মঙ্গল","বুধ","বৃহস্পতি","শুক্র","শনি"],"AMPMS":["am","pm"],"medium":"d MMM, y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, d MMMM, y","longDate":"d MMMM, y","mediumDate":"d MMM, y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"bn-bd"});
+}];
diff --git a/i18n/locale/angular-locale_bn.js b/i18n/locale/angular-locale_bn.js
index 55c77ca38549..3b1011852ef8 100644
--- a/i18n/locale/angular-locale_bn.js
+++ b/i18n/locale/angular-locale_bn.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["জানুয়ারী","ফেব্রুয়ারী","মার্চ","এপ্রিল","মে","জুন","জুলাই","আগস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],"SHORTMONTH":["জানুয়ারী","ফেব্রুয়ারী","মার্চ","এপ্রিল","মে","জুন","জুলাই","আগস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],"DAY":["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহষ্পতিবার","শুক্রবার","শনিবার"],"SHORTDAY":["রবি","সোম","মঙ্গল","বুধ","বৃহস্পতি","শুক্র","শনি"],"AMPMS":["am","pm"],"medium":"d MMM, y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, d MMMM, y","longDate":"d MMMM, y","mediumDate":"d MMM, y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":"\u00A4","negPre":"(","negSuf":"\u00A4)","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"৳"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"bn"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["জানুয়ারী","ফেব্রুয়ারী","মার্চ","এপ্রিল","মে","জুন","জুলাই","আগস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],"SHORTMONTH":["জানুয়ারী","ফেব্রুয়ারী","মার্চ","এপ্রিল","মে","জুন","জুলাই","আগস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],"DAY":["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহষ্পতিবার","শুক্রবার","শনিবার"],"SHORTDAY":["রবি","সোম","মঙ্গল","বুধ","বৃহস্পতি","শুক্র","শনি"],"AMPMS":["am","pm"],"medium":"d MMM, y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, d MMMM, y","longDate":"d MMMM, y","mediumDate":"d MMM, y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":"\u00A4","negPre":"(","negSuf":"\u00A4)","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"৳"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"bn"});
+}];
diff --git a/i18n/locale/angular-locale_ca-es.js b/i18n/locale/angular-locale_ca-es.js
index 6a163d12ca79..f7f6ea14ab73 100644
--- a/i18n/locale/angular-locale_ca-es.js
+++ b/i18n/locale/angular-locale_ca-es.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["de gener","de febrer","de març","d’abril","de maig","de juny","de juliol","d’agost","de setembre","d’octubre","de novembre","de desembre"],"SHORTMONTH":["de gen.","de febr.","de març","d’abr.","de maig","de juny","de jul.","d’ag.","de set.","d’oct.","de nov.","de des."],"DAY":["diumenge","dilluns","dimarts","dimecres","dijous","divendres","dissabte"],"SHORTDAY":["dg.","dl.","dt.","dc.","dj.","dv.","ds."],"AMPMS":["a.m.","p.m."],"medium":"dd/MM/yyyy H:mm:ss","short":"dd/MM/yy H:mm","fullDate":"EEEE d MMMM 'de' y","longDate":"d MMMM 'de' y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"ca-es"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["de gener","de febrer","de març","d’abril","de maig","de juny","de juliol","d’agost","de setembre","d’octubre","de novembre","de desembre"],"SHORTMONTH":["de gen.","de febr.","de març","d’abr.","de maig","de juny","de jul.","d’ag.","de set.","d’oct.","de nov.","de des."],"DAY":["diumenge","dilluns","dimarts","dimecres","dijous","divendres","dissabte"],"SHORTDAY":["dg.","dl.","dt.","dc.","dj.","dv.","ds."],"AMPMS":["a.m.","p.m."],"medium":"dd/MM/yyyy H:mm:ss","short":"dd/MM/yy H:mm","fullDate":"EEEE d MMMM 'de' y","longDate":"d MMMM 'de' y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"ca-es"});
+}];
diff --git a/i18n/locale/angular-locale_ca.js b/i18n/locale/angular-locale_ca.js
index 04e6ec452803..8bcd2b625620 100644
--- a/i18n/locale/angular-locale_ca.js
+++ b/i18n/locale/angular-locale_ca.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["de gener","de febrer","de març","d’abril","de maig","de juny","de juliol","d’agost","de setembre","d’octubre","de novembre","de desembre"],"SHORTMONTH":["de gen.","de febr.","de març","d’abr.","de maig","de juny","de jul.","d’ag.","de set.","d’oct.","de nov.","de des."],"DAY":["diumenge","dilluns","dimarts","dimecres","dijous","divendres","dissabte"],"SHORTDAY":["dg.","dl.","dt.","dc.","dj.","dv.","ds."],"AMPMS":["a.m.","p.m."],"medium":"dd/MM/yyyy H:mm:ss","short":"dd/MM/yy H:mm","fullDate":"EEEE d MMMM 'de' y","longDate":"d MMMM 'de' y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"ca"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["de gener","de febrer","de març","d’abril","de maig","de juny","de juliol","d’agost","de setembre","d’octubre","de novembre","de desembre"],"SHORTMONTH":["de gen.","de febr.","de març","d’abr.","de maig","de juny","de jul.","d’ag.","de set.","d’oct.","de nov.","de des."],"DAY":["diumenge","dilluns","dimarts","dimecres","dijous","divendres","dissabte"],"SHORTDAY":["dg.","dl.","dt.","dc.","dj.","dv.","ds."],"AMPMS":["a.m.","p.m."],"medium":"dd/MM/yyyy H:mm:ss","short":"dd/MM/yy H:mm","fullDate":"EEEE d MMMM 'de' y","longDate":"d MMMM 'de' y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"ca"});
+}];
diff --git a/i18n/locale/angular-locale_cs-cz.js b/i18n/locale/angular-locale_cs-cz.js
index f0def70cd2d1..08e7f06b3f9a 100644
--- a/i18n/locale/angular-locale_cs-cz.js
+++ b/i18n/locale/angular-locale_cs-cz.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Kč"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 2 || n == 3 || n == 4) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ledna","února","března","dubna","května","června","července","srpna","září","října","listopadu","prosince"],"SHORTMONTH":["1","2","3","4","5","6","7","8","9","10","11","12"],"DAY":["neděle","pondělí","úterý","středa","čtvrtek","pátek","sobota"],"SHORTDAY":["ne","po","út","st","čt","pá","so"],"AMPMS":["dop.","odp."],"medium":"d.M.yyyy H:mm:ss","short":"d.M.yy H:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"cs-cz"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Kč"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 2 || n == 3 || n == 4) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ledna","února","března","dubna","května","června","července","srpna","září","října","listopadu","prosince"],"SHORTMONTH":["1","2","3","4","5","6","7","8","9","10","11","12"],"DAY":["neděle","pondělí","úterý","středa","čtvrtek","pátek","sobota"],"SHORTDAY":["ne","po","út","st","čt","pá","so"],"AMPMS":["dop.","odp."],"medium":"d.M.yyyy H:mm:ss","short":"d.M.yy H:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"cs-cz"});
+}];
diff --git a/i18n/locale/angular-locale_cs.js b/i18n/locale/angular-locale_cs.js
index 87b6139bbebc..b43ca70dd944 100644
--- a/i18n/locale/angular-locale_cs.js
+++ b/i18n/locale/angular-locale_cs.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["ledna","února","března","dubna","května","června","července","srpna","září","října","listopadu","prosince"],"SHORTMONTH":["1","2","3","4","5","6","7","8","9","10","11","12"],"DAY":["neděle","pondělí","úterý","středa","čtvrtek","pátek","sobota"],"SHORTDAY":["ne","po","út","st","čt","pá","so"],"AMPMS":["dop.","odp."],"medium":"d.M.yyyy H:mm:ss","short":"d.M.yy H:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Kč"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 2 || n == 3 || n == 4) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"id":"cs"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["ledna","února","března","dubna","května","června","července","srpna","září","října","listopadu","prosince"],"SHORTMONTH":["1","2","3","4","5","6","7","8","9","10","11","12"],"DAY":["neděle","pondělí","úterý","středa","čtvrtek","pátek","sobota"],"SHORTDAY":["ne","po","út","st","čt","pá","so"],"AMPMS":["dop.","odp."],"medium":"d.M.yyyy H:mm:ss","short":"d.M.yy H:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Kč"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 2 || n == 3 || n == 4) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"id":"cs"});
+}];
diff --git a/i18n/locale/angular-locale_da-dk.js b/i18n/locale/angular-locale_da-dk.js
index d03409923d5c..32af847006ca 100644
--- a/i18n/locale/angular-locale_da-dk.js
+++ b/i18n/locale/angular-locale_da-dk.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kr"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["januar","februar","marts","april","maj","juni","juli","august","september","oktober","november","december"],"SHORTMONTH":["jan.","feb.","mar.","apr.","maj","jun.","jul.","aug.","sep.","okt.","nov.","dec."],"DAY":["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],"SHORTDAY":["søn","man","tir","ons","tor","fre","lør"],"AMPMS":["f.m.","e.m."],"medium":"dd/MM/yyyy HH.mm.ss","short":"dd/MM/yy HH.mm","fullDate":"EEEE 'den' d. MMMM y","longDate":"d. MMM y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"HH.mm.ss","shortTime":"HH.mm"},"id":"da-dk"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kr"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["januar","februar","marts","april","maj","juni","juli","august","september","oktober","november","december"],"SHORTMONTH":["jan.","feb.","mar.","apr.","maj","jun.","jul.","aug.","sep.","okt.","nov.","dec."],"DAY":["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],"SHORTDAY":["søn","man","tir","ons","tor","fre","lør"],"AMPMS":["f.m.","e.m."],"medium":"dd/MM/yyyy HH.mm.ss","short":"dd/MM/yy HH.mm","fullDate":"EEEE 'den' d. MMMM y","longDate":"d. MMM y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"HH.mm.ss","shortTime":"HH.mm"},"id":"da-dk"});
+}];
diff --git a/i18n/locale/angular-locale_da.js b/i18n/locale/angular-locale_da.js
index 67bbfecbc628..71322558c1d5 100644
--- a/i18n/locale/angular-locale_da.js
+++ b/i18n/locale/angular-locale_da.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["januar","februar","marts","april","maj","juni","juli","august","september","oktober","november","december"],"SHORTMONTH":["jan.","feb.","mar.","apr.","maj","jun.","jul.","aug.","sep.","okt.","nov.","dec."],"DAY":["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],"SHORTDAY":["søn","man","tir","ons","tor","fre","lør"],"AMPMS":["f.m.","e.m."],"medium":"dd/MM/yyyy HH.mm.ss","short":"dd/MM/yy HH.mm","fullDate":"EEEE 'den' d. MMMM y","longDate":"d. MMM y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"HH.mm.ss","shortTime":"HH.mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kr"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"da"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["januar","februar","marts","april","maj","juni","juli","august","september","oktober","november","december"],"SHORTMONTH":["jan.","feb.","mar.","apr.","maj","jun.","jul.","aug.","sep.","okt.","nov.","dec."],"DAY":["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],"SHORTDAY":["søn","man","tir","ons","tor","fre","lør"],"AMPMS":["f.m.","e.m."],"medium":"dd/MM/yyyy HH.mm.ss","short":"dd/MM/yy HH.mm","fullDate":"EEEE 'den' d. MMMM y","longDate":"d. MMM y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"HH.mm.ss","shortTime":"HH.mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kr"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"da"});
+}];
diff --git a/i18n/locale/angular-locale_de-at.js b/i18n/locale/angular-locale_de-at.js
index 56361dbd2706..65af64ed9329 100644
--- a/i18n/locale/angular-locale_de-at.js
+++ b/i18n/locale/angular-locale_de-at.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Jänner","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"SHORTMONTH":["Jän","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"SHORTDAY":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"AMPMS":["vorm.","nachm."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, dd. MMMM y","longDate":"dd. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"de-at"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Jänner","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"SHORTMONTH":["Jän","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"SHORTDAY":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"AMPMS":["vorm.","nachm."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, dd. MMMM y","longDate":"dd. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"de-at"});
+}];
diff --git a/i18n/locale/angular-locale_de-be.js b/i18n/locale/angular-locale_de-be.js
index 284c9ee904c3..be6ec5e8e56e 100644
--- a/i18n/locale/angular-locale_de-be.js
+++ b/i18n/locale/angular-locale_de-be.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"SHORTMONTH":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"SHORTDAY":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"AMPMS":["vorm.","nachm."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"de-be"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"SHORTMONTH":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"SHORTDAY":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"AMPMS":["vorm.","nachm."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"de-be"});
+}];
diff --git a/i18n/locale/angular-locale_de-ch.js b/i18n/locale/angular-locale_de-ch.js
index 14497cc6830e..a06320ed29d0 100644
--- a/i18n/locale/angular-locale_de-ch.js
+++ b/i18n/locale/angular-locale_de-ch.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"SHORTMONTH":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"SHORTDAY":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"AMPMS":["vorm.","nachm."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":"'","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Fr."},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"de-ch"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"SHORTMONTH":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"SHORTDAY":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"AMPMS":["vorm.","nachm."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":"'","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Fr."},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"de-ch"});
+}];
diff --git a/i18n/locale/angular-locale_de-de.js b/i18n/locale/angular-locale_de-de.js
index 620a36980067..5a19c52c7a5e 100644
--- a/i18n/locale/angular-locale_de-de.js
+++ b/i18n/locale/angular-locale_de-de.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"SHORTMONTH":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"SHORTDAY":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"AMPMS":["vorm.","nachm."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"de-de"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"SHORTMONTH":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"SHORTDAY":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"AMPMS":["vorm.","nachm."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"de-de"});
+}];
diff --git a/i18n/locale/angular-locale_de-lu.js b/i18n/locale/angular-locale_de-lu.js
index 440c14173a46..235a266fdf44 100644
--- a/i18n/locale/angular-locale_de-lu.js
+++ b/i18n/locale/angular-locale_de-lu.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"SHORTMONTH":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"SHORTDAY":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"AMPMS":["vorm.","nachm."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"de-lu"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"SHORTMONTH":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"SHORTDAY":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"AMPMS":["vorm.","nachm."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"de-lu"});
+}];
diff --git a/i18n/locale/angular-locale_de.js b/i18n/locale/angular-locale_de.js
index 20f966efb45e..6a023e5d982f 100644
--- a/i18n/locale/angular-locale_de.js
+++ b/i18n/locale/angular-locale_de.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"SHORTMONTH":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"SHORTDAY":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"AMPMS":["vorm.","nachm."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"de"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"SHORTMONTH":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"SHORTDAY":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"AMPMS":["vorm.","nachm."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"de"});
+}];
diff --git a/i18n/locale/angular-locale_el-gr.js b/i18n/locale/angular-locale_el-gr.js
index 61eed5803355..767bf5e51f63 100644
--- a/i18n/locale/angular-locale_el-gr.js
+++ b/i18n/locale/angular-locale_el-gr.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Ιανουαρίου","Φεβρουαρίου","Μαρτίου","Απριλίου","Μαΐου","Ιουνίου","Ιουλίου","Αυγούστου","Σεπτεμβρίου","Οκτωβρίου","Νοεμβρίου","Δεκεμβρίου"],"SHORTMONTH":["Ιαν","Φεβ","Μαρ","Απρ","Μαϊ","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],"DAY":["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],"SHORTDAY":["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],"AMPMS":["π.μ.","μ.μ."],"medium":"d MMM y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"el-gr"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Ιανουαρίου","Φεβρουαρίου","Μαρτίου","Απριλίου","Μαΐου","Ιουνίου","Ιουλίου","Αυγούστου","Σεπτεμβρίου","Οκτωβρίου","Νοεμβρίου","Δεκεμβρίου"],"SHORTMONTH":["Ιαν","Φεβ","Μαρ","Απρ","Μαϊ","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],"DAY":["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],"SHORTDAY":["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],"AMPMS":["π.μ.","μ.μ."],"medium":"d MMM y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"el-gr"});
+}];
diff --git a/i18n/locale/angular-locale_el-polyton.js b/i18n/locale/angular-locale_el-polyton.js
index 55dbef0f77c7..a4d1d13f5370 100644
--- a/i18n/locale/angular-locale_el-polyton.js
+++ b/i18n/locale/angular-locale_el-polyton.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Ιανουαρίου","Φεβρουαρίου","Μαρτίου","Απριλίου","Μαΐου","Ιουνίου","Ιουλίου","Αυγούστου","Σεπτεμβρίου","Οκτωβρίου","Νοεμβρίου","Δεκεμβρίου"],"SHORTMONTH":["Ιαν","Φεβ","Μαρ","Απρ","Μαϊ","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],"DAY":["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],"SHORTDAY":["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],"AMPMS":["π.μ.","μ.μ."],"medium":"d MMM y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"el-polyton"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Ιανουαρίου","Φεβρουαρίου","Μαρτίου","Απριλίου","Μαΐου","Ιουνίου","Ιουλίου","Αυγούστου","Σεπτεμβρίου","Οκτωβρίου","Νοεμβρίου","Δεκεμβρίου"],"SHORTMONTH":["Ιαν","Φεβ","Μαρ","Απρ","Μαϊ","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],"DAY":["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],"SHORTDAY":["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],"AMPMS":["π.μ.","μ.μ."],"medium":"d MMM y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"el-polyton"});
+}];
diff --git a/i18n/locale/angular-locale_el.js b/i18n/locale/angular-locale_el.js
index 53fe0fdd862d..967ee77978cc 100644
--- a/i18n/locale/angular-locale_el.js
+++ b/i18n/locale/angular-locale_el.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Ιανουαρίου","Φεβρουαρίου","Μαρτίου","Απριλίου","Μαΐου","Ιουνίου","Ιουλίου","Αυγούστου","Σεπτεμβρίου","Οκτωβρίου","Νοεμβρίου","Δεκεμβρίου"],"SHORTMONTH":["Ιαν","Φεβ","Μαρ","Απρ","Μαϊ","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],"DAY":["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],"SHORTDAY":["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],"AMPMS":["π.μ.","μ.μ."],"medium":"d MMM y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"el"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Ιανουαρίου","Φεβρουαρίου","Μαρτίου","Απριλίου","Μαΐου","Ιουνίου","Ιουλίου","Αυγούστου","Σεπτεμβρίου","Οκτωβρίου","Νοεμβρίου","Δεκεμβρίου"],"SHORTMONTH":["Ιαν","Φεβ","Μαρ","Απρ","Μαϊ","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],"DAY":["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],"SHORTDAY":["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],"AMPMS":["π.μ.","μ.μ."],"medium":"d MMM y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"el"});
+}];
diff --git a/i18n/locale/angular-locale_en-as.js b/i18n/locale/angular-locale_en-as.js
index fb5056aa10af..7c7ab2785fc6 100644
--- a/i18n/locale/angular-locale_en-as.js
+++ b/i18n/locale/angular-locale_en-as.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-as"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-as"});
+}];
diff --git a/i18n/locale/angular-locale_en-au.js b/i18n/locale/angular-locale_en-au.js
index fb055cfbd832..f4090c97b159 100644
--- a/i18n/locale/angular-locale_en-au.js
+++ b/i18n/locale/angular-locale_en-au.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"dd/MM/yyyy h:mm:ss a","short":"d/MM/yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd/MM/yyyy","shortDate":"d/MM/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en-au"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"dd/MM/yyyy h:mm:ss a","short":"d/MM/yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd/MM/yyyy","shortDate":"d/MM/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en-au"});
+}];
diff --git a/i18n/locale/angular-locale_en-dsrt-us.js b/i18n/locale/angular-locale_en-dsrt-us.js
index edec3fc3b678..df51914f542a 100644
--- a/i18n/locale/angular-locale_en-dsrt-us.js
+++ b/i18n/locale/angular-locale_en-dsrt-us.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-dsrt-us"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-dsrt-us"});
+}];
diff --git a/i18n/locale/angular-locale_en-dsrt.js b/i18n/locale/angular-locale_en-dsrt.js
index 66b49e545cb7..45b604d233a9 100644
--- a/i18n/locale/angular-locale_en-dsrt.js
+++ b/i18n/locale/angular-locale_en-dsrt.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-dsrt"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-dsrt"});
+}];
diff --git a/i18n/locale/angular-locale_en-gb.js b/i18n/locale/angular-locale_en-gb.js
index cdef219d89f5..0e1176d6e6b1 100644
--- a/i18n/locale/angular-locale_en-gb.js
+++ b/i18n/locale/angular-locale_en-gb.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yyyy HH:mm","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"£"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en-gb"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yyyy HH:mm","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"£"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en-gb"});
+}];
diff --git a/i18n/locale/angular-locale_en-gu.js b/i18n/locale/angular-locale_en-gu.js
index 569ee050766e..50474e48f3fb 100644
--- a/i18n/locale/angular-locale_en-gu.js
+++ b/i18n/locale/angular-locale_en-gu.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-gu"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-gu"});
+}];
diff --git a/i18n/locale/angular-locale_en-ie.js b/i18n/locale/angular-locale_en-ie.js
index b2b339759bf2..76c2859b21fc 100644
--- a/i18n/locale/angular-locale_en-ie.js
+++ b/i18n/locale/angular-locale_en-ie.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["a.m.","p.m."],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yyyy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en-ie"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["a.m.","p.m."],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yyyy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en-ie"});
+}];
diff --git a/i18n/locale/angular-locale_en-in.js b/i18n/locale/angular-locale_en-in.js
index 51f8ff088944..2da223a5ab54 100644
--- a/i18n/locale/angular-locale_en-in.js
+++ b/i18n/locale/angular-locale_en-in.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"dd-MMM-y h:mm:ss a","short":"dd/MM/yy h:mm a","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"dd-MMM-y","shortDate":"dd/MM/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en-in"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"dd-MMM-y h:mm:ss a","short":"dd/MM/yy h:mm a","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"dd-MMM-y","shortDate":"dd/MM/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en-in"});
+}];
diff --git a/i18n/locale/angular-locale_en-iso.js b/i18n/locale/angular-locale_en-iso.js
index 884a14fc7120..8416abc48787 100644
--- a/i18n/locale/angular-locale_en-iso.js
+++ b/i18n/locale/angular-locale_en-iso.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"y MMM d HH:mm:ss","short":"yyyy-MM-dd HH:mm","fullDate":"EEEE, y MMMM dd","longDate":"y MMMM d","mediumDate":"y MMM d","shortDate":"yyyy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"id":"en-iso"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"y MMM d HH:mm:ss","short":"yyyy-MM-dd HH:mm","fullDate":"EEEE, y MMMM dd","longDate":"y MMMM d","mediumDate":"y MMM d","shortDate":"yyyy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"id":"en-iso"});
+}];
diff --git a/i18n/locale/angular-locale_en-mh.js b/i18n/locale/angular-locale_en-mh.js
index bc44ceede420..dd826fa8b263 100644
--- a/i18n/locale/angular-locale_en-mh.js
+++ b/i18n/locale/angular-locale_en-mh.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-mh"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-mh"});
+}];
diff --git a/i18n/locale/angular-locale_en-mp.js b/i18n/locale/angular-locale_en-mp.js
index c0f091ac1f57..86d478bc47cf 100644
--- a/i18n/locale/angular-locale_en-mp.js
+++ b/i18n/locale/angular-locale_en-mp.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-mp"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-mp"});
+}];
diff --git a/i18n/locale/angular-locale_en-sg.js b/i18n/locale/angular-locale_en-sg.js
index dc40b024108f..28f376c65404 100644
--- a/i18n/locale/angular-locale_en-sg.js
+++ b/i18n/locale/angular-locale_en-sg.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en-sg"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en-sg"});
+}];
diff --git a/i18n/locale/angular-locale_en-um.js b/i18n/locale/angular-locale_en-um.js
index 7ac1a8753634..ad8aa13d5429 100644
--- a/i18n/locale/angular-locale_en-um.js
+++ b/i18n/locale/angular-locale_en-um.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-um"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-um"});
+}];
diff --git a/i18n/locale/angular-locale_en-us.js b/i18n/locale/angular-locale_en-us.js
index c7dd6d79685b..5dacd4464cd7 100644
--- a/i18n/locale/angular-locale_en-us.js
+++ b/i18n/locale/angular-locale_en-us.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en-us"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en-us"});
+}];
diff --git a/i18n/locale/angular-locale_en-vi.js b/i18n/locale/angular-locale_en-vi.js
index 5b4b87a389e5..d51c16cd521e 100644
--- a/i18n/locale/angular-locale_en-vi.js
+++ b/i18n/locale/angular-locale_en-vi.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-vi"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-vi"});
+}];
diff --git a/i18n/locale/angular-locale_en-za.js b/i18n/locale/angular-locale_en-za.js
index 5ee4f325e7bb..f3ff66ba2c16 100644
--- a/i18n/locale/angular-locale_en-za.js
+++ b/i18n/locale/angular-locale_en-za.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"dd MMM y h:mm:ss a","short":"yyyy/MM/dd h:mm a","fullDate":"EEEE dd MMMM y","longDate":"dd MMMM y","mediumDate":"dd MMM y","shortDate":"yyyy/MM/dd","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"R"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en-za"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"dd MMM y h:mm:ss a","short":"yyyy/MM/dd h:mm a","fullDate":"EEEE dd MMMM y","longDate":"dd MMMM y","mediumDate":"dd MMM y","shortDate":"yyyy/MM/dd","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"R"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en-za"});
+}];
diff --git a/i18n/locale/angular-locale_en-zz.js b/i18n/locale/angular-locale_en-zz.js
index 496262b3160a..d174fe4c4b2e 100644
--- a/i18n/locale/angular-locale_en-zz.js
+++ b/i18n/locale/angular-locale_en-zz.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-zz"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"en-zz"});
+}];
diff --git a/i18n/locale/angular-locale_en.js b/i18n/locale/angular-locale_en.js
index d614c93650b1..11cc9879e750 100644
--- a/i18n/locale/angular-locale_en.js
+++ b/i18n/locale/angular-locale_en.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["January","February","March","April","May","June","July","August","September","October","November","December"],"SHORTMONTH":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"DAY":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"SHORTDAY":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"AMPMS":["AM","PM"],"medium":"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"en"});
+}];
diff --git a/i18n/locale/angular-locale_es-es.js b/i18n/locale/angular-locale_es-es.js
index 90ca686d3657..9f5fe41540aa 100644
--- a/i18n/locale/angular-locale_es-es.js
+++ b/i18n/locale/angular-locale_es-es.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],"SHORTMONTH":["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],"DAY":["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],"SHORTDAY":["dom","lun","mar","mié","jue","vie","sáb"],"AMPMS":["a.m.","p.m."],"medium":"dd/MM/yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d 'de' MMMM 'de' y","longDate":"d 'de' MMMM 'de' y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"es-es"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],"SHORTMONTH":["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],"DAY":["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],"SHORTDAY":["dom","lun","mar","mié","jue","vie","sáb"],"AMPMS":["a.m.","p.m."],"medium":"dd/MM/yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d 'de' MMMM 'de' y","longDate":"d 'de' MMMM 'de' y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"es-es"});
+}];
diff --git a/i18n/locale/angular-locale_es.js b/i18n/locale/angular-locale_es.js
index 65f81518ada2..6d8a084348fb 100644
--- a/i18n/locale/angular-locale_es.js
+++ b/i18n/locale/angular-locale_es.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],"SHORTMONTH":["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],"DAY":["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],"SHORTDAY":["dom","lun","mar","mié","jue","vie","sáb"],"AMPMS":["a.m.","p.m."],"medium":"dd/MM/yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d 'de' MMMM 'de' y","longDate":"d 'de' MMMM 'de' y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"es"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],"SHORTMONTH":["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],"DAY":["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],"SHORTDAY":["dom","lun","mar","mié","jue","vie","sáb"],"AMPMS":["a.m.","p.m."],"medium":"dd/MM/yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d 'de' MMMM 'de' y","longDate":"d 'de' MMMM 'de' y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"es"});
+}];
diff --git a/i18n/locale/angular-locale_et-ee.js b/i18n/locale/angular-locale_et-ee.js
index 3242a27a556c..65cfc1bfbea1 100644
--- a/i18n/locale/angular-locale_et-ee.js
+++ b/i18n/locale/angular-locale_et-ee.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["jaanuar","veebruar","märts","aprill","mai","juuni","juuli","august","september","oktoober","november","detsember"],"SHORTMONTH":["jaan","veebr","märts","apr","mai","juuni","juuli","aug","sept","okt","nov","dets"],"DAY":["pühapäev","esmaspäev","teisipäev","kolmapäev","neljapäev","reede","laupäev"],"SHORTDAY":["P","E","T","K","N","R","L"],"AMPMS":["enne keskpäeva","pärast keskpäeva"],"medium":"dd.MM.yyyy H:mm.ss","short":"dd.MM.yy H:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"H:mm.ss","shortTime":"H:mm"},"id":"et-ee"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["jaanuar","veebruar","märts","aprill","mai","juuni","juuli","august","september","oktoober","november","detsember"],"SHORTMONTH":["jaan","veebr","märts","apr","mai","juuni","juuli","aug","sept","okt","nov","dets"],"DAY":["pühapäev","esmaspäev","teisipäev","kolmapäev","neljapäev","reede","laupäev"],"SHORTDAY":["P","E","T","K","N","R","L"],"AMPMS":["enne keskpäeva","pärast keskpäeva"],"medium":"dd.MM.yyyy H:mm.ss","short":"dd.MM.yy H:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"H:mm.ss","shortTime":"H:mm"},"id":"et-ee"});
+}];
diff --git a/i18n/locale/angular-locale_et.js b/i18n/locale/angular-locale_et.js
index 58bd93ff672c..0e206aca7d35 100644
--- a/i18n/locale/angular-locale_et.js
+++ b/i18n/locale/angular-locale_et.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["jaanuar","veebruar","märts","aprill","mai","juuni","juuli","august","september","oktoober","november","detsember"],"SHORTMONTH":["jaan","veebr","märts","apr","mai","juuni","juuli","aug","sept","okt","nov","dets"],"DAY":["pühapäev","esmaspäev","teisipäev","kolmapäev","neljapäev","reede","laupäev"],"SHORTDAY":["P","E","T","K","N","R","L"],"AMPMS":["enne keskpäeva","pärast keskpäeva"],"medium":"dd.MM.yyyy H:mm.ss","short":"dd.MM.yy H:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"H:mm.ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"et"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["jaanuar","veebruar","märts","aprill","mai","juuni","juuli","august","september","oktoober","november","detsember"],"SHORTMONTH":["jaan","veebr","märts","apr","mai","juuni","juuli","aug","sept","okt","nov","dets"],"DAY":["pühapäev","esmaspäev","teisipäev","kolmapäev","neljapäev","reede","laupäev"],"SHORTDAY":["P","E","T","K","N","R","L"],"AMPMS":["enne keskpäeva","pärast keskpäeva"],"medium":"dd.MM.yyyy H:mm.ss","short":"dd.MM.yy H:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"H:mm.ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"et"});
+}];
diff --git a/i18n/locale/angular-locale_eu-es.js b/i18n/locale/angular-locale_eu-es.js
index 7c5221d35312..c8ebd197297a 100644
--- a/i18n/locale/angular-locale_eu-es.js
+++ b/i18n/locale/angular-locale_eu-es.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["urtarrila","otsaila","martxoa","apirila","maiatza","ekaina","uztaila","abuztua","iraila","urria","azaroa","abendua"],"SHORTMONTH":["urt","ots","mar","api","mai","eka","uzt","abu","ira","urr","aza","abe"],"DAY":["igandea","astelehena","asteartea","asteazkena","osteguna","ostirala","larunbata"],"SHORTDAY":["ig","al","as","az","og","or","lr"],"AMPMS":["AM","PM"],"medium":"y MMM d HH:mm:ss","short":"yyyy-MM-dd HH:mm","fullDate":"EEEE, y'eko' MMMM'ren' dd'a'","longDate":"y'eko' MMM'ren' dd'a'","mediumDate":"y MMM d","shortDate":"yyyy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"eu-es"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["urtarrila","otsaila","martxoa","apirila","maiatza","ekaina","uztaila","abuztua","iraila","urria","azaroa","abendua"],"SHORTMONTH":["urt","ots","mar","api","mai","eka","uzt","abu","ira","urr","aza","abe"],"DAY":["igandea","astelehena","asteartea","asteazkena","osteguna","ostirala","larunbata"],"SHORTDAY":["ig","al","as","az","og","or","lr"],"AMPMS":["AM","PM"],"medium":"y MMM d HH:mm:ss","short":"yyyy-MM-dd HH:mm","fullDate":"EEEE, y'eko' MMMM'ren' dd'a'","longDate":"y'eko' MMM'ren' dd'a'","mediumDate":"y MMM d","shortDate":"yyyy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"eu-es"});
+}];
diff --git a/i18n/locale/angular-locale_eu.js b/i18n/locale/angular-locale_eu.js
index 5c6d0972dee4..4ae428f2d6f3 100644
--- a/i18n/locale/angular-locale_eu.js
+++ b/i18n/locale/angular-locale_eu.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["urtarrila","otsaila","martxoa","apirila","maiatza","ekaina","uztaila","abuztua","iraila","urria","azaroa","abendua"],"SHORTMONTH":["urt","ots","mar","api","mai","eka","uzt","abu","ira","urr","aza","abe"],"DAY":["igandea","astelehena","asteartea","asteazkena","osteguna","ostirala","larunbata"],"SHORTDAY":["ig","al","as","az","og","or","lr"],"AMPMS":["AM","PM"],"medium":"y MMM d HH:mm:ss","short":"yyyy-MM-dd HH:mm","fullDate":"EEEE, y'eko' MMMM'ren' dd'a'","longDate":"y'eko' MMM'ren' dd'a'","mediumDate":"y MMM d","shortDate":"yyyy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"eu"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["urtarrila","otsaila","martxoa","apirila","maiatza","ekaina","uztaila","abuztua","iraila","urria","azaroa","abendua"],"SHORTMONTH":["urt","ots","mar","api","mai","eka","uzt","abu","ira","urr","aza","abe"],"DAY":["igandea","astelehena","asteartea","asteazkena","osteguna","ostirala","larunbata"],"SHORTDAY":["ig","al","as","az","og","or","lr"],"AMPMS":["AM","PM"],"medium":"y MMM d HH:mm:ss","short":"yyyy-MM-dd HH:mm","fullDate":"EEEE, y'eko' MMMM'ren' dd'a'","longDate":"y'eko' MMM'ren' dd'a'","mediumDate":"y MMM d","shortDate":"yyyy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"eu"});
+}];
diff --git a/i18n/locale/angular-locale_fa-ir.js b/i18n/locale/angular-locale_fa-ir.js
index 0604c7e3daba..1152601f84c8 100644
--- a/i18n/locale/angular-locale_fa-ir.js
+++ b/i18n/locale/angular-locale_fa-ir.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":"/","GROUP_SEP":"،","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"‪-","negSuf":"‬","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"‪-","negSuf":"‬ \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"﷼"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ژانویهٔ","فوریهٔ","مارس","آوریل","می","جون","جولای","آگوست","سپتامبر","اکتبر","نوامبر","دسامبر"],"SHORTMONTH":["ژانویهٔ","فوریهٔ","مارس","آوریل","می","جون","جولای","اوت","سپتامبر","اکتبر","نوامبر","دسامبر"],"DAY":["یکشنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنجشنبه","جمعه","شنبه"],"SHORTDAY":["یکشنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنجشنبه","جمعه","شنبه"],"AMPMS":["قبل از ظهر","بعد از ظهر"],"medium":"MMM d, y H:mm:ss","short":"M/d/yy H:mm","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"fa-ir"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":"/","GROUP_SEP":"،","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"‪-","negSuf":"‬","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"‪-","negSuf":"‬ \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"﷼"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ژانویهٔ","فوریهٔ","مارس","آوریل","می","جون","جولای","آگوست","سپتامبر","اکتبر","نوامبر","دسامبر"],"SHORTMONTH":["ژانویهٔ","فوریهٔ","مارس","آوریل","می","جون","جولای","اوت","سپتامبر","اکتبر","نوامبر","دسامبر"],"DAY":["یکشنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنجشنبه","جمعه","شنبه"],"SHORTDAY":["یکشنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنجشنبه","جمعه","شنبه"],"AMPMS":["قبل از ظهر","بعد از ظهر"],"medium":"MMM d, y H:mm:ss","short":"M/d/yy H:mm","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"fa-ir"});
+}];
diff --git a/i18n/locale/angular-locale_fa.js b/i18n/locale/angular-locale_fa.js
index fbe9c6bde6e1..1c0e9e439de3 100644
--- a/i18n/locale/angular-locale_fa.js
+++ b/i18n/locale/angular-locale_fa.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["ژانویهٔ","فوریهٔ","مارس","آوریل","می","جون","جولای","آگوست","سپتامبر","اکتبر","نوامبر","دسامبر"],"SHORTMONTH":["ژانویهٔ","فوریهٔ","مارس","آوریل","می","جون","جولای","اوت","سپتامبر","اکتبر","نوامبر","دسامبر"],"DAY":["یکشنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنجشنبه","جمعه","شنبه"],"SHORTDAY":["یکشنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنجشنبه","جمعه","شنبه"],"AMPMS":["قبل از ظهر","بعد از ظهر"],"medium":"MMM d, y H:mm:ss","short":"M/d/yy H:mm","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":"/","GROUP_SEP":"،","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"‪-","negSuf":"‬","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"‪-","negSuf":"‬ \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"﷼"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"fa"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["ژانویهٔ","فوریهٔ","مارس","آوریل","می","جون","جولای","آگوست","سپتامبر","اکتبر","نوامبر","دسامبر"],"SHORTMONTH":["ژانویهٔ","فوریهٔ","مارس","آوریل","می","جون","جولای","اوت","سپتامبر","اکتبر","نوامبر","دسامبر"],"DAY":["یکشنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنجشنبه","جمعه","شنبه"],"SHORTDAY":["یکشنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنجشنبه","جمعه","شنبه"],"AMPMS":["قبل از ظهر","بعد از ظهر"],"medium":"MMM d, y H:mm:ss","short":"M/d/yy H:mm","fullDate":"EEEE, MMMM d, y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":"/","GROUP_SEP":"،","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"‪-","negSuf":"‬","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"‪-","negSuf":"‬ \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"﷼"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"fa"});
+}];
diff --git a/i18n/locale/angular-locale_fi-fi.js b/i18n/locale/angular-locale_fi-fi.js
index bdb6374ef9eb..2cb5086180f4 100644
--- a/i18n/locale/angular-locale_fi-fi.js
+++ b/i18n/locale/angular-locale_fi-fi.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kesäkuuta","heinäkuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],"SHORTMONTH":["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kesäkuuta","heinäkuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],"DAY":["sunnuntaina","maanantaina","tiistaina","keskiviikkona","torstaina","perjantaina","lauantaina"],"SHORTDAY":["su","ma","ti","ke","to","pe","la"],"AMPMS":["ap.","ip."],"medium":"d.M.yyyy H.mm.ss","short":"d.M.yyyy H.mm","fullDate":"cccc d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yyyy","mediumTime":"H.mm.ss","shortTime":"H.mm"},"id":"fi-fi"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kesäkuuta","heinäkuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],"SHORTMONTH":["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kesäkuuta","heinäkuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],"DAY":["sunnuntaina","maanantaina","tiistaina","keskiviikkona","torstaina","perjantaina","lauantaina"],"SHORTDAY":["su","ma","ti","ke","to","pe","la"],"AMPMS":["ap.","ip."],"medium":"d.M.yyyy H.mm.ss","short":"d.M.yyyy H.mm","fullDate":"cccc d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yyyy","mediumTime":"H.mm.ss","shortTime":"H.mm"},"id":"fi-fi"});
+}];
diff --git a/i18n/locale/angular-locale_fi.js b/i18n/locale/angular-locale_fi.js
index b74742c88616..50cc54278a84 100644
--- a/i18n/locale/angular-locale_fi.js
+++ b/i18n/locale/angular-locale_fi.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kesäkuuta","heinäkuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],"SHORTMONTH":["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kesäkuuta","heinäkuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],"DAY":["sunnuntaina","maanantaina","tiistaina","keskiviikkona","torstaina","perjantaina","lauantaina"],"SHORTDAY":["su","ma","ti","ke","to","pe","la"],"AMPMS":["ap.","ip."],"medium":"d.M.yyyy H.mm.ss","short":"d.M.yyyy H.mm","fullDate":"cccc d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yyyy","mediumTime":"H.mm.ss","shortTime":"H.mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"fi"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kesäkuuta","heinäkuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],"SHORTMONTH":["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kesäkuuta","heinäkuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],"DAY":["sunnuntaina","maanantaina","tiistaina","keskiviikkona","torstaina","perjantaina","lauantaina"],"SHORTDAY":["su","ma","ti","ke","to","pe","la"],"AMPMS":["ap.","ip."],"medium":"d.M.yyyy H.mm.ss","short":"d.M.yyyy H.mm","fullDate":"cccc d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yyyy","mediumTime":"H.mm.ss","shortTime":"H.mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"fi"});
+}];
diff --git a/i18n/locale/angular-locale_fil-ph.js b/i18n/locale/angular-locale_fil-ph.js
index 090defbca3cf..a94d8bc4427d 100644
--- a/i18n/locale/angular-locale_fil-ph.js
+++ b/i18n/locale/angular-locale_fil-ph.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"P"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Enero","Pebrero","Marso","Abril","Mayo","Hunyo","Hulyo","Agosto","Setyembre","Oktubre","Nobyembre","Disyembre"],"SHORTMONTH":["Ene","Peb","Mar","Abr","May","Hun","Hul","Ago","Set","Okt","Nob","Dis"],"DAY":["Linggo","Lunes","Martes","Miyerkules","Huwebes","Biyernes","Sabado"],"SHORTDAY":["Lin","Lun","Mar","Mye","Huw","Bye","Sab"],"AMPMS":["AM","PM"],"medium":"MMM d, y HH:mm:ss","short":"M/d/yy HH:mm","fullDate":"EEEE, MMMM dd y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fil-ph"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"P"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Enero","Pebrero","Marso","Abril","Mayo","Hunyo","Hulyo","Agosto","Setyembre","Oktubre","Nobyembre","Disyembre"],"SHORTMONTH":["Ene","Peb","Mar","Abr","May","Hun","Hul","Ago","Set","Okt","Nob","Dis"],"DAY":["Linggo","Lunes","Martes","Miyerkules","Huwebes","Biyernes","Sabado"],"SHORTDAY":["Lin","Lun","Mar","Mye","Huw","Bye","Sab"],"AMPMS":["AM","PM"],"medium":"MMM d, y HH:mm:ss","short":"M/d/yy HH:mm","fullDate":"EEEE, MMMM dd y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fil-ph"});
+}];
diff --git a/i18n/locale/angular-locale_fil.js b/i18n/locale/angular-locale_fil.js
index 680b3cb15c69..a0a0477e7e07 100644
--- a/i18n/locale/angular-locale_fil.js
+++ b/i18n/locale/angular-locale_fil.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Enero","Pebrero","Marso","Abril","Mayo","Hunyo","Hulyo","Agosto","Setyembre","Oktubre","Nobyembre","Disyembre"],"SHORTMONTH":["Ene","Peb","Mar","Abr","May","Hun","Hul","Ago","Set","Okt","Nob","Dis"],"DAY":["Linggo","Lunes","Martes","Miyerkules","Huwebes","Biyernes","Sabado"],"SHORTDAY":["Lin","Lun","Mar","Mye","Huw","Bye","Sab"],"AMPMS":["AM","PM"],"medium":"MMM d, y HH:mm:ss","short":"M/d/yy HH:mm","fullDate":"EEEE, MMMM dd y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"P"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"fil"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Enero","Pebrero","Marso","Abril","Mayo","Hunyo","Hulyo","Agosto","Setyembre","Oktubre","Nobyembre","Disyembre"],"SHORTMONTH":["Ene","Peb","Mar","Abr","May","Hun","Hul","Ago","Set","Okt","Nob","Dis"],"DAY":["Linggo","Lunes","Martes","Miyerkules","Huwebes","Biyernes","Sabado"],"SHORTDAY":["Lin","Lun","Mar","Mye","Huw","Bye","Sab"],"AMPMS":["AM","PM"],"medium":"MMM d, y HH:mm:ss","short":"M/d/yy HH:mm","fullDate":"EEEE, MMMM dd y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"P"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"fil"});
+}];
diff --git a/i18n/locale/angular-locale_fr-bl.js b/i18n/locale/angular-locale_fr-bl.js
index f841143c7b04..5e758d307c05 100644
--- a/i18n/locale/angular-locale_fr-bl.js
+++ b/i18n/locale/angular-locale_fr-bl.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fr-bl"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fr-bl"});
+}];
diff --git a/i18n/locale/angular-locale_fr-ca.js b/i18n/locale/angular-locale_fr-ca.js
index edf62eeac7eb..cc0493efa435 100644
--- a/i18n/locale/angular-locale_fr-ca.js
+++ b/i18n/locale/angular-locale_fr-ca.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"yyyy-MM-dd HH:mm:ss","short":"yy-MM-dd HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"yyyy-MM-dd","shortDate":"yy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"(","negSuf":" \u00A4)","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"fr-ca"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"yyyy-MM-dd HH:mm:ss","short":"yy-MM-dd HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"yyyy-MM-dd","shortDate":"yy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"(","negSuf":" \u00A4)","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"fr-ca"});
+}];
diff --git a/i18n/locale/angular-locale_fr-fr.js b/i18n/locale/angular-locale_fr-fr.js
index c92b4e2fa90b..f0b904654c67 100644
--- a/i18n/locale/angular-locale_fr-fr.js
+++ b/i18n/locale/angular-locale_fr-fr.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fr-fr"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fr-fr"});
+}];
diff --git a/i18n/locale/angular-locale_fr-gp.js b/i18n/locale/angular-locale_fr-gp.js
index 108e439785f9..3d5e4d988bbe 100644
--- a/i18n/locale/angular-locale_fr-gp.js
+++ b/i18n/locale/angular-locale_fr-gp.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fr-gp"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fr-gp"});
+}];
diff --git a/i18n/locale/angular-locale_fr-mc.js b/i18n/locale/angular-locale_fr-mc.js
index bcd900465596..2aa13514f93c 100644
--- a/i18n/locale/angular-locale_fr-mc.js
+++ b/i18n/locale/angular-locale_fr-mc.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fr-mc"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fr-mc"});
+}];
diff --git a/i18n/locale/angular-locale_fr-mf.js b/i18n/locale/angular-locale_fr-mf.js
index 9b29b9e1d036..3c76b70d719f 100644
--- a/i18n/locale/angular-locale_fr-mf.js
+++ b/i18n/locale/angular-locale_fr-mf.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fr-mf"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fr-mf"});
+}];
diff --git a/i18n/locale/angular-locale_fr-mq.js b/i18n/locale/angular-locale_fr-mq.js
index 351c82d39c7d..22f40c8a3d90 100644
--- a/i18n/locale/angular-locale_fr-mq.js
+++ b/i18n/locale/angular-locale_fr-mq.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fr-mq"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fr-mq"});
+}];
diff --git a/i18n/locale/angular-locale_fr-re.js b/i18n/locale/angular-locale_fr-re.js
index 3af5f9f5dd28..f06acb3bc741 100644
--- a/i18n/locale/angular-locale_fr-re.js
+++ b/i18n/locale/angular-locale_fr-re.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fr-re"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"fr-re"});
+}];
diff --git a/i18n/locale/angular-locale_fr.js b/i18n/locale/angular-locale_fr.js
index 343fadf7c169..ed80ab974396 100644
--- a/i18n/locale/angular-locale_fr.js
+++ b/i18n/locale/angular-locale_fr.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"fr"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"SHORTMONTH":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"DAY":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"SHORTDAY":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n >= 0 && n < 2) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"fr"});
+}];
diff --git a/i18n/locale/angular-locale_gl-es.js b/i18n/locale/angular-locale_gl-es.js
index f61ac022d04b..288e0ad20d8b 100644
--- a/i18n/locale/angular-locale_gl-es.js
+++ b/i18n/locale/angular-locale_gl-es.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Xaneiro","Febreiro","Marzo","Abril","Maio","Xuño","Xullo","Agosto","Setembro","Outubro","Novembro","Decembro"],"SHORTMONTH":["Xan","Feb","Mar","Abr","Mai","Xuñ","Xul","Ago","Set","Out","Nov","Dec"],"DAY":["Domingo","Luns","Martes","Mércores","Xoves","Venres","Sábado"],"SHORTDAY":["Dom","Lun","Mar","Mér","Xov","Ven","Sáb"],"AMPMS":["AM","PM"],"medium":"d MMM, y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE dd MMMM y","longDate":"dd MMMM y","mediumDate":"d MMM, y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"gl-es"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Xaneiro","Febreiro","Marzo","Abril","Maio","Xuño","Xullo","Agosto","Setembro","Outubro","Novembro","Decembro"],"SHORTMONTH":["Xan","Feb","Mar","Abr","Mai","Xuñ","Xul","Ago","Set","Out","Nov","Dec"],"DAY":["Domingo","Luns","Martes","Mércores","Xoves","Venres","Sábado"],"SHORTDAY":["Dom","Lun","Mar","Mér","Xov","Ven","Sáb"],"AMPMS":["AM","PM"],"medium":"d MMM, y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE dd MMMM y","longDate":"dd MMMM y","mediumDate":"d MMM, y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"gl-es"});
+}];
diff --git a/i18n/locale/angular-locale_gl.js b/i18n/locale/angular-locale_gl.js
index f45521ebb17b..6eb1000af9c3 100644
--- a/i18n/locale/angular-locale_gl.js
+++ b/i18n/locale/angular-locale_gl.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Xaneiro","Febreiro","Marzo","Abril","Maio","Xuño","Xullo","Agosto","Setembro","Outubro","Novembro","Decembro"],"SHORTMONTH":["Xan","Feb","Mar","Abr","Mai","Xuñ","Xul","Ago","Set","Out","Nov","Dec"],"DAY":["Domingo","Luns","Martes","Mércores","Xoves","Venres","Sábado"],"SHORTDAY":["Dom","Lun","Mar","Mér","Xov","Ven","Sáb"],"AMPMS":["AM","PM"],"medium":"d MMM, y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE dd MMMM y","longDate":"dd MMMM y","mediumDate":"d MMM, y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"gl"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Xaneiro","Febreiro","Marzo","Abril","Maio","Xuño","Xullo","Agosto","Setembro","Outubro","Novembro","Decembro"],"SHORTMONTH":["Xan","Feb","Mar","Abr","Mai","Xuñ","Xul","Ago","Set","Out","Nov","Dec"],"DAY":["Domingo","Luns","Martes","Mércores","Xoves","Venres","Sábado"],"SHORTDAY":["Dom","Lun","Mar","Mér","Xov","Ven","Sáb"],"AMPMS":["AM","PM"],"medium":"d MMM, y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE dd MMMM y","longDate":"dd MMMM y","mediumDate":"d MMM, y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"gl"});
+}];
diff --git a/i18n/locale/angular-locale_gsw-ch.js b/i18n/locale/angular-locale_gsw-ch.js
index 01c1b3878464..eda0a1bdc748 100644
--- a/i18n/locale/angular-locale_gsw-ch.js
+++ b/i18n/locale/angular-locale_gsw-ch.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":"’","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Fr."},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Januar","Februar","März","April","Mai","Juni","Juli","Auguscht","Septämber","Oktoober","Novämber","Dezämber"],"SHORTMONTH":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sunntig","Määntig","Ziischtig","Mittwuch","Dunschtig","Friitig","Samschtig"],"SHORTDAY":["Su.","Mä.","Zi.","Mi.","Du.","Fr.","Sa."],"AMPMS":["vorm.","nam."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"gsw-ch"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":"’","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Fr."},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Januar","Februar","März","April","Mai","Juni","Juli","Auguscht","Septämber","Oktoober","Novämber","Dezämber"],"SHORTMONTH":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sunntig","Määntig","Ziischtig","Mittwuch","Dunschtig","Friitig","Samschtig"],"SHORTDAY":["Su.","Mä.","Zi.","Mi.","Du.","Fr.","Sa."],"AMPMS":["vorm.","nam."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"gsw-ch"});
+}];
diff --git a/i18n/locale/angular-locale_gsw.js b/i18n/locale/angular-locale_gsw.js
index b2ce74d67bdd..19bd388f5b56 100644
--- a/i18n/locale/angular-locale_gsw.js
+++ b/i18n/locale/angular-locale_gsw.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Januar","Februar","März","April","Mai","Juni","Juli","Auguscht","Septämber","Oktoober","Novämber","Dezämber"],"SHORTMONTH":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sunntig","Määntig","Ziischtig","Mittwuch","Dunschtig","Friitig","Samschtig"],"SHORTDAY":["Su.","Mä.","Zi.","Mi.","Du.","Fr.","Sa."],"AMPMS":["vorm.","nam."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":"’","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Fr."},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"gsw"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Januar","Februar","März","April","Mai","Juni","Juli","Auguscht","Septämber","Oktoober","Novämber","Dezämber"],"SHORTMONTH":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"DAY":["Sunntig","Määntig","Ziischtig","Mittwuch","Dunschtig","Friitig","Samschtig"],"SHORTDAY":["Su.","Mä.","Zi.","Mi.","Du.","Fr.","Sa."],"AMPMS":["vorm.","nam."],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":"’","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Fr."},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"gsw"});
+}];
diff --git a/i18n/locale/angular-locale_gu-in.js b/i18n/locale/angular-locale_gu-in.js
index 2776837f0db0..14079acddd04 100644
--- a/i18n/locale/angular-locale_gu-in.js
+++ b/i18n/locale/angular-locale_gu-in.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["જાન્યુઆરી","ફેબ્રુઆરી","માર્ચ","એપ્રિલ","મે","જૂન","જુલાઈ","ઑગસ્ટ","સપ્ટેમ્બર","ઑક્ટ્બર","નવેમ્બર","ડિસેમ્બર"],"SHORTMONTH":["જાન્યુ","ફેબ્રુ","માર્ચ","એપ્રિલ","મે","જૂન","જુલાઈ","ઑગસ્ટ","સપ્ટે","ઑક્ટો","નવે","ડિસે"],"DAY":["રવિવાર","સોમવાર","મંગળવાર","બુધવાર","ગુરુવાર","શુક્રવાર","શનિવાર"],"SHORTDAY":["રવિ","સોમ","મંગળ","બુધ","ગુરુ","શુક્ર","શનિ"],"AMPMS":["પૂર્વ મધ્યાહ્ન","ઉત્તર મધ્યાહ્ન"],"medium":"d MMM, y hh:mm:ss a","short":"d-MM-yy hh:mm a","fullDate":"EEEE, d MMMM, y","longDate":"d MMMM, y","mediumDate":"d MMM, y","shortDate":"d-MM-yy","mediumTime":"hh:mm:ss a","shortTime":"hh:mm a"},"id":"gu-in"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["જાન્યુઆરી","ફેબ્રુઆરી","માર્ચ","એપ્રિલ","મે","જૂન","જુલાઈ","ઑગસ્ટ","સપ્ટેમ્બર","ઑક્ટ્બર","નવેમ્બર","ડિસેમ્બર"],"SHORTMONTH":["જાન્યુ","ફેબ્રુ","માર્ચ","એપ્રિલ","મે","જૂન","જુલાઈ","ઑગસ્ટ","સપ્ટે","ઑક્ટો","નવે","ડિસે"],"DAY":["રવિવાર","સોમવાર","મંગળવાર","બુધવાર","ગુરુવાર","શુક્રવાર","શનિવાર"],"SHORTDAY":["રવિ","સોમ","મંગળ","બુધ","ગુરુ","શુક્ર","શનિ"],"AMPMS":["પૂર્વ મધ્યાહ્ન","ઉત્તર મધ્યાહ્ન"],"medium":"d MMM, y hh:mm:ss a","short":"d-MM-yy hh:mm a","fullDate":"EEEE, d MMMM, y","longDate":"d MMMM, y","mediumDate":"d MMM, y","shortDate":"d-MM-yy","mediumTime":"hh:mm:ss a","shortTime":"hh:mm a"},"id":"gu-in"});
+}];
diff --git a/i18n/locale/angular-locale_gu.js b/i18n/locale/angular-locale_gu.js
index c68b6191321d..6e928fc08509 100644
--- a/i18n/locale/angular-locale_gu.js
+++ b/i18n/locale/angular-locale_gu.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["જાન્યુઆરી","ફેબ્રુઆરી","માર્ચ","એપ્રિલ","મે","જૂન","જુલાઈ","ઑગસ્ટ","સપ્ટેમ્બર","ઑક્ટ્બર","નવેમ્બર","ડિસેમ્બર"],"SHORTMONTH":["જાન્યુ","ફેબ્રુ","માર્ચ","એપ્રિલ","મે","જૂન","જુલાઈ","ઑગસ્ટ","સપ્ટે","ઑક્ટો","નવે","ડિસે"],"DAY":["રવિવાર","સોમવાર","મંગળવાર","બુધવાર","ગુરુવાર","શુક્રવાર","શનિવાર"],"SHORTDAY":["રવિ","સોમ","મંગળ","બુધ","ગુરુ","શુક્ર","શનિ"],"AMPMS":["પૂર્વ મધ્યાહ્ન","ઉત્તર મધ્યાહ્ન"],"medium":"d MMM, y hh:mm:ss a","short":"d-MM-yy hh:mm a","fullDate":"EEEE, d MMMM, y","longDate":"d MMMM, y","mediumDate":"d MMM, y","shortDate":"d-MM-yy","mediumTime":"hh:mm:ss a","shortTime":"hh:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"gu"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["જાન્યુઆરી","ફેબ્રુઆરી","માર્ચ","એપ્રિલ","મે","જૂન","જુલાઈ","ઑગસ્ટ","સપ્ટેમ્બર","ઑક્ટ્બર","નવેમ્બર","ડિસેમ્બર"],"SHORTMONTH":["જાન્યુ","ફેબ્રુ","માર્ચ","એપ્રિલ","મે","જૂન","જુલાઈ","ઑગસ્ટ","સપ્ટે","ઑક્ટો","નવે","ડિસે"],"DAY":["રવિવાર","સોમવાર","મંગળવાર","બુધવાર","ગુરુવાર","શુક્રવાર","શનિવાર"],"SHORTDAY":["રવિ","સોમ","મંગળ","બુધ","ગુરુ","શુક્ર","શનિ"],"AMPMS":["પૂર્વ મધ્યાહ્ન","ઉત્તર મધ્યાહ્ન"],"medium":"d MMM, y hh:mm:ss a","short":"d-MM-yy hh:mm a","fullDate":"EEEE, d MMMM, y","longDate":"d MMMM, y","mediumDate":"d MMM, y","shortDate":"d-MM-yy","mediumTime":"hh:mm:ss a","shortTime":"hh:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"gu"});
+}];
diff --git a/i18n/locale/angular-locale_he-il.js b/i18n/locale/angular-locale_he-il.js
index b6b465e5b888..ddc8f33b0115 100644
--- a/i18n/locale/angular-locale_he-il.js
+++ b/i18n/locale/angular-locale_he-il.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₪"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ינואר","פברואר","מרס","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],"SHORTMONTH":["ינו","פבר","מרס","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],"DAY":["יום ראשון","יום שני","יום שלישי","יום רביעי","יום חמישי","יום שישי","יום שבת"],"SHORTDAY":["יום א׳","יום ב׳","יום ג׳","יום ד׳","יום ה׳","יום ו׳","שבת"],"AMPMS":["לפנה״צ","אחה״צ"],"medium":"d בMMM yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, d בMMMM y","longDate":"d בMMMM y","mediumDate":"d בMMM yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"he-il"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₪"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ינואר","פברואר","מרס","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],"SHORTMONTH":["ינו","פבר","מרס","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],"DAY":["יום ראשון","יום שני","יום שלישי","יום רביעי","יום חמישי","יום שישי","יום שבת"],"SHORTDAY":["יום א׳","יום ב׳","יום ג׳","יום ד׳","יום ה׳","יום ו׳","שבת"],"AMPMS":["לפנה״צ","אחה״צ"],"medium":"d בMMM yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, d בMMMM y","longDate":"d בMMMM y","mediumDate":"d בMMM yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"he-il"});
+}];
diff --git a/i18n/locale/angular-locale_he.js b/i18n/locale/angular-locale_he.js
index 6bd5ceb25bb9..62d6b1a70aa6 100644
--- a/i18n/locale/angular-locale_he.js
+++ b/i18n/locale/angular-locale_he.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["ינואר","פברואר","מרס","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],"SHORTMONTH":["ינו","פבר","מרס","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],"DAY":["יום ראשון","יום שני","יום שלישי","יום רביעי","יום חמישי","יום שישי","יום שבת"],"SHORTDAY":["יום א׳","יום ב׳","יום ג׳","יום ד׳","יום ה׳","יום ו׳","שבת"],"AMPMS":["לפנה״צ","אחה״צ"],"medium":"d בMMM yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, d בMMMM y","longDate":"d בMMMM y","mediumDate":"d בMMM yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₪"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"he"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["ינואר","פברואר","מרס","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],"SHORTMONTH":["ינו","פבר","מרס","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],"DAY":["יום ראשון","יום שני","יום שלישי","יום רביעי","יום חמישי","יום שישי","יום שבת"],"SHORTDAY":["יום א׳","יום ב׳","יום ג׳","יום ד׳","יום ה׳","יום ו׳","שבת"],"AMPMS":["לפנה״צ","אחה״צ"],"medium":"d בMMM yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, d בMMMM y","longDate":"d בMMMM y","mediumDate":"d בMMM yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₪"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"he"});
+}];
diff --git a/i18n/locale/angular-locale_hi-in.js b/i18n/locale/angular-locale_hi-in.js
index c1a66824dfeb..cd553ad628d8 100644
--- a/i18n/locale/angular-locale_hi-in.js
+++ b/i18n/locale/angular-locale_hi-in.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["जनवरी","फरवरी","मार्च","अप्रैल","मई","जून","जुलाई","अगस्त","सितम्बर","अक्तूबर","नवम्बर","दिसम्बर"],"SHORTMONTH":["जनवरी","फरवरी","मार्च","अप्रैल","मई","जून","जुलाई","अगस्त","सितम्बर","अक्तूबर","नवम्बर","दिसम्बर"],"DAY":["रविवार","सोमवार","मंगलवार","बुधवार","बृहस्पतिवार","शुक्रवार","शनिवार"],"SHORTDAY":["रवि.","सोम.","मंगल.","बुध.","बृह.","शुक्र.","शनि."],"AMPMS":["पूर्वाह्न","अपराह्न"],"medium":"dd-MM-yyyy h:mm:ss a","short":"d-M-yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd-MM-yyyy","shortDate":"d-M-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"hi-in"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["जनवरी","फरवरी","मार्च","अप्रैल","मई","जून","जुलाई","अगस्त","सितम्बर","अक्तूबर","नवम्बर","दिसम्बर"],"SHORTMONTH":["जनवरी","फरवरी","मार्च","अप्रैल","मई","जून","जुलाई","अगस्त","सितम्बर","अक्तूबर","नवम्बर","दिसम्बर"],"DAY":["रविवार","सोमवार","मंगलवार","बुधवार","बृहस्पतिवार","शुक्रवार","शनिवार"],"SHORTDAY":["रवि.","सोम.","मंगल.","बुध.","बृह.","शुक्र.","शनि."],"AMPMS":["पूर्वाह्न","अपराह्न"],"medium":"dd-MM-yyyy h:mm:ss a","short":"d-M-yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd-MM-yyyy","shortDate":"d-M-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"hi-in"});
+}];
diff --git a/i18n/locale/angular-locale_hi.js b/i18n/locale/angular-locale_hi.js
index 5641e2e82ec3..c74392c63078 100644
--- a/i18n/locale/angular-locale_hi.js
+++ b/i18n/locale/angular-locale_hi.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["जनवरी","फरवरी","मार्च","अप्रैल","मई","जून","जुलाई","अगस्त","सितम्बर","अक्तूबर","नवम्बर","दिसम्बर"],"SHORTMONTH":["जनवरी","फरवरी","मार्च","अप्रैल","मई","जून","जुलाई","अगस्त","सितम्बर","अक्तूबर","नवम्बर","दिसम्बर"],"DAY":["रविवार","सोमवार","मंगलवार","बुधवार","बृहस्पतिवार","शुक्रवार","शनिवार"],"SHORTDAY":["रवि.","सोम.","मंगल.","बुध.","बृह.","शुक्र.","शनि."],"AMPMS":["पूर्वाह्न","अपराह्न"],"medium":"dd-MM-yyyy h:mm:ss a","short":"d-M-yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd-MM-yyyy","shortDate":"d-M-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"hi"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["जनवरी","फरवरी","मार्च","अप्रैल","मई","जून","जुलाई","अगस्त","सितम्बर","अक्तूबर","नवम्बर","दिसम्बर"],"SHORTMONTH":["जनवरी","फरवरी","मार्च","अप्रैल","मई","जून","जुलाई","अगस्त","सितम्बर","अक्तूबर","नवम्बर","दिसम्बर"],"DAY":["रविवार","सोमवार","मंगलवार","बुधवार","बृहस्पतिवार","शुक्रवार","शनिवार"],"SHORTDAY":["रवि.","सोम.","मंगल.","बुध.","बृह.","शुक्र.","शनि."],"AMPMS":["पूर्वाह्न","अपराह्न"],"medium":"dd-MM-yyyy h:mm:ss a","short":"d-M-yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd-MM-yyyy","shortDate":"d-M-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"hi"});
+}];
diff --git a/i18n/locale/angular-locale_hr-hr.js b/i18n/locale/angular-locale_hr-hr.js
index 3bc262ac8978..b2e43e0337af 100644
--- a/i18n/locale/angular-locale_hr-hr.js
+++ b/i18n/locale/angular-locale_hr-hr.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kn"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["siječnja","veljače","ožujka","travnja","svibnja","lipnja","srpnja","kolovoza","rujna","listopada","studenoga","prosinca"],"SHORTMONTH":["sij","velj","ožu","tra","svi","lip","srp","kol","ruj","lis","stu","pro"],"DAY":["nedjelja","ponedjeljak","utorak","srijeda","četvrtak","petak","subota"],"SHORTDAY":["ned","pon","uto","sri","čet","pet","sub"],"AMPMS":["AM","PM"],"medium":"d. M. yyyy. HH:mm:ss","short":"dd. MM. yyyy. HH:mm","fullDate":"EEEE, d. MMMM y.","longDate":"d. MMMM y.","mediumDate":"d. M. yyyy.","shortDate":"dd. MM. yyyy.","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"hr-hr"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kn"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["siječnja","veljače","ožujka","travnja","svibnja","lipnja","srpnja","kolovoza","rujna","listopada","studenoga","prosinca"],"SHORTMONTH":["sij","velj","ožu","tra","svi","lip","srp","kol","ruj","lis","stu","pro"],"DAY":["nedjelja","ponedjeljak","utorak","srijeda","četvrtak","petak","subota"],"SHORTDAY":["ned","pon","uto","sri","čet","pet","sub"],"AMPMS":["AM","PM"],"medium":"d. M. yyyy. HH:mm:ss","short":"dd. MM. yyyy. HH:mm","fullDate":"EEEE, d. MMMM y.","longDate":"d. MMMM y.","mediumDate":"d. M. yyyy.","shortDate":"dd. MM. yyyy.","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"hr-hr"});
+}];
diff --git a/i18n/locale/angular-locale_hr.js b/i18n/locale/angular-locale_hr.js
index 814d9a027fb4..ac3bf8b8e3de 100644
--- a/i18n/locale/angular-locale_hr.js
+++ b/i18n/locale/angular-locale_hr.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["siječnja","veljače","ožujka","travnja","svibnja","lipnja","srpnja","kolovoza","rujna","listopada","studenoga","prosinca"],"SHORTMONTH":["sij","velj","ožu","tra","svi","lip","srp","kol","ruj","lis","stu","pro"],"DAY":["nedjelja","ponedjeljak","utorak","srijeda","četvrtak","petak","subota"],"SHORTDAY":["ned","pon","uto","sri","čet","pet","sub"],"AMPMS":["AM","PM"],"medium":"d. M. yyyy. HH:mm:ss","short":"dd. MM. yyyy. HH:mm","fullDate":"EEEE, d. MMMM y.","longDate":"d. MMMM y.","mediumDate":"d. M. yyyy.","shortDate":"dd. MM. yyyy.","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kn"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"id":"hr"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["siječnja","veljače","ožujka","travnja","svibnja","lipnja","srpnja","kolovoza","rujna","listopada","studenoga","prosinca"],"SHORTMONTH":["sij","velj","ožu","tra","svi","lip","srp","kol","ruj","lis","stu","pro"],"DAY":["nedjelja","ponedjeljak","utorak","srijeda","četvrtak","petak","subota"],"SHORTDAY":["ned","pon","uto","sri","čet","pet","sub"],"AMPMS":["AM","PM"],"medium":"d. M. yyyy. HH:mm:ss","short":"dd. MM. yyyy. HH:mm","fullDate":"EEEE, d. MMMM y.","longDate":"d. MMMM y.","mediumDate":"d. M. yyyy.","shortDate":"dd. MM. yyyy.","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kn"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"id":"hr"});
+}];
diff --git a/i18n/locale/angular-locale_hu-hu.js b/i18n/locale/angular-locale_hu-hu.js
index 3aa3393a17b8..318a88e5c20f 100644
--- a/i18n/locale/angular-locale_hu-hu.js
+++ b/i18n/locale/angular-locale_hu-hu.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Ft"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["január","február","március","április","május","június","július","augusztus","szeptember","október","november","december"],"SHORTMONTH":["jan.","febr.","márc.","ápr.","máj.","jún.","júl.","aug.","szept.","okt.","nov.","dec."],"DAY":["vasárnap","hétfő","kedd","szerda","csütörtök","péntek","szombat"],"SHORTDAY":["V","H","K","Sze","Cs","P","Szo"],"AMPMS":["de.","du."],"medium":"yyyy.MM.dd. H:mm:ss","short":"yyyy.MM.dd. H:mm","fullDate":"y. MMMM d., EEEE","longDate":"y. MMMM d.","mediumDate":"yyyy.MM.dd.","shortDate":"yyyy.MM.dd.","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"hu-hu"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Ft"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["január","február","március","április","május","június","július","augusztus","szeptember","október","november","december"],"SHORTMONTH":["jan.","febr.","márc.","ápr.","máj.","jún.","júl.","aug.","szept.","okt.","nov.","dec."],"DAY":["vasárnap","hétfő","kedd","szerda","csütörtök","péntek","szombat"],"SHORTDAY":["V","H","K","Sze","Cs","P","Szo"],"AMPMS":["de.","du."],"medium":"yyyy.MM.dd. H:mm:ss","short":"yyyy.MM.dd. H:mm","fullDate":"y. MMMM d., EEEE","longDate":"y. MMMM d.","mediumDate":"yyyy.MM.dd.","shortDate":"yyyy.MM.dd.","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"hu-hu"});
+}];
diff --git a/i18n/locale/angular-locale_hu.js b/i18n/locale/angular-locale_hu.js
index 6a60d6efe211..b497438405ec 100644
--- a/i18n/locale/angular-locale_hu.js
+++ b/i18n/locale/angular-locale_hu.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["január","február","március","április","május","június","július","augusztus","szeptember","október","november","december"],"SHORTMONTH":["jan.","febr.","márc.","ápr.","máj.","jún.","júl.","aug.","szept.","okt.","nov.","dec."],"DAY":["vasárnap","hétfő","kedd","szerda","csütörtök","péntek","szombat"],"SHORTDAY":["V","H","K","Sze","Cs","P","Szo"],"AMPMS":["de.","du."],"medium":"yyyy.MM.dd. H:mm:ss","short":"yyyy.MM.dd. H:mm","fullDate":"y. MMMM d., EEEE","longDate":"y. MMMM d.","mediumDate":"yyyy.MM.dd.","shortDate":"yyyy.MM.dd.","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Ft"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"hu"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["január","február","március","április","május","június","július","augusztus","szeptember","október","november","december"],"SHORTMONTH":["jan.","febr.","márc.","ápr.","máj.","jún.","júl.","aug.","szept.","okt.","nov.","dec."],"DAY":["vasárnap","hétfő","kedd","szerda","csütörtök","péntek","szombat"],"SHORTDAY":["V","H","K","Sze","Cs","P","Szo"],"AMPMS":["de.","du."],"medium":"yyyy.MM.dd. H:mm:ss","short":"yyyy.MM.dd. H:mm","fullDate":"y. MMMM d., EEEE","longDate":"y. MMMM d.","mediumDate":"yyyy.MM.dd.","shortDate":"yyyy.MM.dd.","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Ft"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"hu"});
+}];
diff --git a/i18n/locale/angular-locale_id-id.js b/i18n/locale/angular-locale_id-id.js
index 8511a9073e80..683e1fc9be63 100644
--- a/i18n/locale/angular-locale_id-id.js
+++ b/i18n/locale/angular-locale_id-id.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rp"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],"SHORTMONTH":["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agt","Sep","Okt","Nov","Des"],"DAY":["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],"SHORTDAY":["Min","Sen","Sel","Rab","Kam","Jum","Sab"],"AMPMS":["pagi","malam"],"medium":"d MMM yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, dd MMMM yyyy","longDate":"d MMMM yyyy","mediumDate":"d MMM yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"id-id"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rp"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],"SHORTMONTH":["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agt","Sep","Okt","Nov","Des"],"DAY":["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],"SHORTDAY":["Min","Sen","Sel","Rab","Kam","Jum","Sab"],"AMPMS":["pagi","malam"],"medium":"d MMM yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, dd MMMM yyyy","longDate":"d MMMM yyyy","mediumDate":"d MMM yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"id-id"});
+}];
diff --git a/i18n/locale/angular-locale_id.js b/i18n/locale/angular-locale_id.js
index 01c325b24073..e6376f617210 100644
--- a/i18n/locale/angular-locale_id.js
+++ b/i18n/locale/angular-locale_id.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],"SHORTMONTH":["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agt","Sep","Okt","Nov","Des"],"DAY":["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],"SHORTDAY":["Min","Sen","Sel","Rab","Kam","Jum","Sab"],"AMPMS":["pagi","malam"],"medium":"d MMM yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, dd MMMM yyyy","longDate":"d MMMM yyyy","mediumDate":"d MMM yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rp"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"id"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],"SHORTMONTH":["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agt","Sep","Okt","Nov","Des"],"DAY":["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],"SHORTDAY":["Min","Sen","Sel","Rab","Kam","Jum","Sab"],"AMPMS":["pagi","malam"],"medium":"d MMM yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, dd MMMM yyyy","longDate":"d MMMM yyyy","mediumDate":"d MMM yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rp"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"id"});
+}];
diff --git a/i18n/locale/angular-locale_in.js b/i18n/locale/angular-locale_in.js
index c6089f89ddae..cc226e40bff6 100644
--- a/i18n/locale/angular-locale_in.js
+++ b/i18n/locale/angular-locale_in.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],"SHORTMONTH":["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agt","Sep","Okt","Nov","Des"],"DAY":["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],"SHORTDAY":["Min","Sen","Sel","Rab","Kam","Jum","Sab"],"AMPMS":["pagi","malam"],"medium":"d MMM yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, dd MMMM yyyy","longDate":"d MMMM yyyy","mediumDate":"d MMM yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rp"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"in"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],"SHORTMONTH":["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agt","Sep","Okt","Nov","Des"],"DAY":["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],"SHORTDAY":["Min","Sen","Sel","Rab","Kam","Jum","Sab"],"AMPMS":["pagi","malam"],"medium":"d MMM yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, dd MMMM yyyy","longDate":"d MMMM yyyy","mediumDate":"d MMM yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rp"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"in"});
+}];
diff --git a/i18n/locale/angular-locale_is-is.js b/i18n/locale/angular-locale_is-is.js
index 97998154a181..30a86f509397 100644
--- a/i18n/locale/angular-locale_is-is.js
+++ b/i18n/locale/angular-locale_is-is.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kr"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janúar","febrúar","mars","apríl","maí","júní","júlí","ágúst","september","október","nóvember","desember"],"SHORTMONTH":["jan","feb","mar","apr","maí","jún","júl","ágú","sep","okt","nóv","des"],"DAY":["sunnudagur","mánudagur","þriðjudagur","miðvikudagur","fimmtudagur","föstudagur","laugardagur"],"SHORTDAY":["sun","mán","þri","mið","fim","fös","lau"],"AMPMS":["f.h.","e.h."],"medium":"d.M.yyyy HH:mm:ss","short":"d.M.yyyy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"is-is"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kr"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janúar","febrúar","mars","apríl","maí","júní","júlí","ágúst","september","október","nóvember","desember"],"SHORTMONTH":["jan","feb","mar","apr","maí","jún","júl","ágú","sep","okt","nóv","des"],"DAY":["sunnudagur","mánudagur","þriðjudagur","miðvikudagur","fimmtudagur","föstudagur","laugardagur"],"SHORTDAY":["sun","mán","þri","mið","fim","fös","lau"],"AMPMS":["f.h.","e.h."],"medium":"d.M.yyyy HH:mm:ss","short":"d.M.yyyy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"is-is"});
+}];
diff --git a/i18n/locale/angular-locale_is.js b/i18n/locale/angular-locale_is.js
index 9df2659aeb92..6f42680c610e 100644
--- a/i18n/locale/angular-locale_is.js
+++ b/i18n/locale/angular-locale_is.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["janúar","febrúar","mars","apríl","maí","júní","júlí","ágúst","september","október","nóvember","desember"],"SHORTMONTH":["jan","feb","mar","apr","maí","jún","júl","ágú","sep","okt","nóv","des"],"DAY":["sunnudagur","mánudagur","þriðjudagur","miðvikudagur","fimmtudagur","föstudagur","laugardagur"],"SHORTDAY":["sun","mán","þri","mið","fim","fös","lau"],"AMPMS":["f.h.","e.h."],"medium":"d.M.yyyy HH:mm:ss","short":"d.M.yyyy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kr"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"is"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["janúar","febrúar","mars","apríl","maí","júní","júlí","ágúst","september","október","nóvember","desember"],"SHORTMONTH":["jan","feb","mar","apr","maí","jún","júl","ágú","sep","okt","nóv","des"],"DAY":["sunnudagur","mánudagur","þriðjudagur","miðvikudagur","fimmtudagur","föstudagur","laugardagur"],"SHORTDAY":["sun","mán","þri","mið","fim","fös","lau"],"AMPMS":["f.h.","e.h."],"medium":"d.M.yyyy HH:mm:ss","short":"d.M.yyyy HH:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kr"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"is"});
+}];
diff --git a/i18n/locale/angular-locale_it-it.js b/i18n/locale/angular-locale_it-it.js
index 2fda5d164e5e..4ff6dac4ff33 100644
--- a/i18n/locale/angular-locale_it-it.js
+++ b/i18n/locale/angular-locale_it-it.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["gennaio","febbraio","marzo","aprile","maggio","giugno","luglio","agosto","settembre","ottobre","novembre","dicembre"],"SHORTMONTH":["gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"],"DAY":["domenica","lunedì","martedì","mercoledì","giovedì","venerdì","sabato"],"SHORTDAY":["dom","lun","mar","mer","gio","ven","sab"],"AMPMS":["m.","p."],"medium":"dd/MMM/y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"dd MMMM y","mediumDate":"dd/MMM/y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"it-it"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["gennaio","febbraio","marzo","aprile","maggio","giugno","luglio","agosto","settembre","ottobre","novembre","dicembre"],"SHORTMONTH":["gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"],"DAY":["domenica","lunedì","martedì","mercoledì","giovedì","venerdì","sabato"],"SHORTDAY":["dom","lun","mar","mer","gio","ven","sab"],"AMPMS":["m.","p."],"medium":"dd/MMM/y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"dd MMMM y","mediumDate":"dd/MMM/y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"it-it"});
+}];
diff --git a/i18n/locale/angular-locale_it.js b/i18n/locale/angular-locale_it.js
index 9e909fb6cc5b..149f60c4f65c 100644
--- a/i18n/locale/angular-locale_it.js
+++ b/i18n/locale/angular-locale_it.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["gennaio","febbraio","marzo","aprile","maggio","giugno","luglio","agosto","settembre","ottobre","novembre","dicembre"],"SHORTMONTH":["gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"],"DAY":["domenica","lunedì","martedì","mercoledì","giovedì","venerdì","sabato"],"SHORTDAY":["dom","lun","mar","mer","gio","ven","sab"],"AMPMS":["m.","p."],"medium":"dd/MMM/y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"dd MMMM y","mediumDate":"dd/MMM/y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"it"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["gennaio","febbraio","marzo","aprile","maggio","giugno","luglio","agosto","settembre","ottobre","novembre","dicembre"],"SHORTMONTH":["gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"],"DAY":["domenica","lunedì","martedì","mercoledì","giovedì","venerdì","sabato"],"SHORTDAY":["dom","lun","mar","mer","gio","ven","sab"],"AMPMS":["m.","p."],"medium":"dd/MMM/y HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"dd MMMM y","mediumDate":"dd/MMM/y","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"it"});
+}];
diff --git a/i18n/locale/angular-locale_iw.js b/i18n/locale/angular-locale_iw.js
index 697131dd95b7..80a0443b178d 100644
--- a/i18n/locale/angular-locale_iw.js
+++ b/i18n/locale/angular-locale_iw.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["ינואר","פברואר","מרס","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],"SHORTMONTH":["ינו","פבר","מרס","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],"DAY":["יום ראשון","יום שני","יום שלישי","יום רביעי","יום חמישי","יום שישי","יום שבת"],"SHORTDAY":["יום א׳","יום ב׳","יום ג׳","יום ד׳","יום ה׳","יום ו׳","שבת"],"AMPMS":["לפנה״צ","אחה״צ"],"medium":"d בMMM yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, d בMMMM y","longDate":"d בMMMM y","mediumDate":"d בMMM yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₪"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"iw"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["ינואר","פברואר","מרס","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],"SHORTMONTH":["ינו","פבר","מרס","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],"DAY":["יום ראשון","יום שני","יום שלישי","יום רביעי","יום חמישי","יום שישי","יום שבת"],"SHORTDAY":["יום א׳","יום ב׳","יום ג׳","יום ד׳","יום ה׳","יום ו׳","שבת"],"AMPMS":["לפנה״צ","אחה״צ"],"medium":"d בMMM yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, d בMMMM y","longDate":"d בMMMM y","mediumDate":"d בMMM yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₪"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"iw"});
+}];
diff --git a/i18n/locale/angular-locale_ja-jp.js b/i18n/locale/angular-locale_ja-jp.js
index 8fe8a333634e..4e47a03e3e1d 100644
--- a/i18n/locale/angular-locale_ja-jp.js
+++ b/i18n/locale/angular-locale_ja-jp.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"¥"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],"SHORTDAY":["日","月","火","水","木","金","土"],"AMPMS":["午前","午後"],"medium":"yyyy/MM/dd H:mm:ss","short":"yy/MM/dd H:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"yyyy/MM/dd","shortDate":"yy/MM/dd","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"ja-jp"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"¥"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],"SHORTDAY":["日","月","火","水","木","金","土"],"AMPMS":["午前","午後"],"medium":"yyyy/MM/dd H:mm:ss","short":"yy/MM/dd H:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"yyyy/MM/dd","shortDate":"yy/MM/dd","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"ja-jp"});
+}];
diff --git a/i18n/locale/angular-locale_ja.js b/i18n/locale/angular-locale_ja.js
index 6091e81d8bd8..b80ec8bc4198 100644
--- a/i18n/locale/angular-locale_ja.js
+++ b/i18n/locale/angular-locale_ja.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],"SHORTDAY":["日","月","火","水","木","金","土"],"AMPMS":["午前","午後"],"medium":"yyyy/MM/dd H:mm:ss","short":"yy/MM/dd H:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"yyyy/MM/dd","shortDate":"yy/MM/dd","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"¥"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"ja"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],"SHORTDAY":["日","月","火","水","木","金","土"],"AMPMS":["午前","午後"],"medium":"yyyy/MM/dd H:mm:ss","short":"yy/MM/dd H:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"yyyy/MM/dd","shortDate":"yy/MM/dd","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"¥"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"ja"});
+}];
diff --git a/i18n/locale/angular-locale_kn-in.js b/i18n/locale/angular-locale_kn-in.js
index 0ad7355c6e07..ab4194b3d840 100644
--- a/i18n/locale/angular-locale_kn-in.js
+++ b/i18n/locale/angular-locale_kn-in.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ಜನವರೀ","ಫೆಬ್ರವರೀ","ಮಾರ್ಚ್","ಎಪ್ರಿಲ್","ಮೆ","ಜೂನ್","ಜುಲೈ","ಆಗಸ್ಟ್","ಸಪ್ಟೆಂಬರ್","ಅಕ್ಟೋಬರ್","ನವೆಂಬರ್","ಡಿಸೆಂಬರ್"],"SHORTMONTH":["ಜನವರೀ","ಫೆಬ್ರವರೀ","ಮಾರ್ಚ್","ಎಪ್ರಿಲ್","ಮೆ","ಜೂನ್","ಜುಲೈ","ಆಗಸ್ಟ್","ಸಪ್ಟೆಂಬರ್","ಅಕ್ಟೋಬರ್","ನವೆಂಬರ್","ಡಿಸೆಂಬರ್"],"DAY":["ರವಿವಾರ","ಸೋಮವಾರ","ಮಂಗಳವಾರ","ಬುಧವಾರ","ಗುರುವಾರ","ಶುಕ್ರವಾರ","ಶನಿವಾರ"],"SHORTDAY":["ರ.","ಸೋ.","ಮಂ.","ಬು.","ಗು.","ಶು.","ಶನಿ."],"AMPMS":["am","pm"],"medium":"d MMM y hh:mm:ss a","short":"d-M-yy hh:mm a","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d-M-yy","mediumTime":"hh:mm:ss a","shortTime":"hh:mm a"},"id":"kn-in"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ಜನವರೀ","ಫೆಬ್ರವರೀ","ಮಾರ್ಚ್","ಎಪ್ರಿಲ್","ಮೆ","ಜೂನ್","ಜುಲೈ","ಆಗಸ್ಟ್","ಸಪ್ಟೆಂಬರ್","ಅಕ್ಟೋಬರ್","ನವೆಂಬರ್","ಡಿಸೆಂಬರ್"],"SHORTMONTH":["ಜನವರೀ","ಫೆಬ್ರವರೀ","ಮಾರ್ಚ್","ಎಪ್ರಿಲ್","ಮೆ","ಜೂನ್","ಜುಲೈ","ಆಗಸ್ಟ್","ಸಪ್ಟೆಂಬರ್","ಅಕ್ಟೋಬರ್","ನವೆಂಬರ್","ಡಿಸೆಂಬರ್"],"DAY":["ರವಿವಾರ","ಸೋಮವಾರ","ಮಂಗಳವಾರ","ಬುಧವಾರ","ಗುರುವಾರ","ಶುಕ್ರವಾರ","ಶನಿವಾರ"],"SHORTDAY":["ರ.","ಸೋ.","ಮಂ.","ಬು.","ಗು.","ಶು.","ಶನಿ."],"AMPMS":["am","pm"],"medium":"d MMM y hh:mm:ss a","short":"d-M-yy hh:mm a","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d-M-yy","mediumTime":"hh:mm:ss a","shortTime":"hh:mm a"},"id":"kn-in"});
+}];
diff --git a/i18n/locale/angular-locale_kn.js b/i18n/locale/angular-locale_kn.js
index 01f53ae24943..2574ab41a889 100644
--- a/i18n/locale/angular-locale_kn.js
+++ b/i18n/locale/angular-locale_kn.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["ಜನವರೀ","ಫೆಬ್ರವರೀ","ಮಾರ್ಚ್","ಎಪ್ರಿಲ್","ಮೆ","ಜೂನ್","ಜುಲೈ","ಆಗಸ್ಟ್","ಸಪ್ಟೆಂಬರ್","ಅಕ್ಟೋಬರ್","ನವೆಂಬರ್","ಡಿಸೆಂಬರ್"],"SHORTMONTH":["ಜನವರೀ","ಫೆಬ್ರವರೀ","ಮಾರ್ಚ್","ಎಪ್ರಿಲ್","ಮೆ","ಜೂನ್","ಜುಲೈ","ಆಗಸ್ಟ್","ಸಪ್ಟೆಂಬರ್","ಅಕ್ಟೋಬರ್","ನವೆಂಬರ್","ಡಿಸೆಂಬರ್"],"DAY":["ರವಿವಾರ","ಸೋಮವಾರ","ಮಂಗಳವಾರ","ಬುಧವಾರ","ಗುರುವಾರ","ಶುಕ್ರವಾರ","ಶನಿವಾರ"],"SHORTDAY":["ರ.","ಸೋ.","ಮಂ.","ಬು.","ಗು.","ಶು.","ಶನಿ."],"AMPMS":["am","pm"],"medium":"d MMM y hh:mm:ss a","short":"d-M-yy hh:mm a","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d-M-yy","mediumTime":"hh:mm:ss a","shortTime":"hh:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"kn"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["ಜನವರೀ","ಫೆಬ್ರವರೀ","ಮಾರ್ಚ್","ಎಪ್ರಿಲ್","ಮೆ","ಜೂನ್","ಜುಲೈ","ಆಗಸ್ಟ್","ಸಪ್ಟೆಂಬರ್","ಅಕ್ಟೋಬರ್","ನವೆಂಬರ್","ಡಿಸೆಂಬರ್"],"SHORTMONTH":["ಜನವರೀ","ಫೆಬ್ರವರೀ","ಮಾರ್ಚ್","ಎಪ್ರಿಲ್","ಮೆ","ಜೂನ್","ಜುಲೈ","ಆಗಸ್ಟ್","ಸಪ್ಟೆಂಬರ್","ಅಕ್ಟೋಬರ್","ನವೆಂಬರ್","ಡಿಸೆಂಬರ್"],"DAY":["ರವಿವಾರ","ಸೋಮವಾರ","ಮಂಗಳವಾರ","ಬುಧವಾರ","ಗುರುವಾರ","ಶುಕ್ರವಾರ","ಶನಿವಾರ"],"SHORTDAY":["ರ.","ಸೋ.","ಮಂ.","ಬು.","ಗು.","ಶು.","ಶನಿ."],"AMPMS":["am","pm"],"medium":"d MMM y hh:mm:ss a","short":"d-M-yy hh:mm a","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d-M-yy","mediumTime":"hh:mm:ss a","shortTime":"hh:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"kn"});
+}];
diff --git a/i18n/locale/angular-locale_ko-kr.js b/i18n/locale/angular-locale_ko-kr.js
index 6e0bf9b29ba0..3f7d90792de4 100644
--- a/i18n/locale/angular-locale_ko-kr.js
+++ b/i18n/locale/angular-locale_ko-kr.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₩"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"SHORTMONTH":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"DAY":["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],"SHORTDAY":["일","월","화","수","목","금","토"],"AMPMS":["오전","오후"],"medium":"yyyy. M. d. a h:mm:ss","short":"yy. M. d. a h:mm","fullDate":"y년 M월 d일 EEEE","longDate":"y년 M월 d일","mediumDate":"yyyy. M. d.","shortDate":"yy. M. d.","mediumTime":"a h:mm:ss","shortTime":"a h:mm"},"id":"ko-kr"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₩"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"SHORTMONTH":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"DAY":["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],"SHORTDAY":["일","월","화","수","목","금","토"],"AMPMS":["오전","오후"],"medium":"yyyy. M. d. a h:mm:ss","short":"yy. M. d. a h:mm","fullDate":"y년 M월 d일 EEEE","longDate":"y년 M월 d일","mediumDate":"yyyy. M. d.","shortDate":"yy. M. d.","mediumTime":"a h:mm:ss","shortTime":"a h:mm"},"id":"ko-kr"});
+}];
diff --git a/i18n/locale/angular-locale_ko.js b/i18n/locale/angular-locale_ko.js
index 8b14b4e7e152..bdf7f7d897c9 100644
--- a/i18n/locale/angular-locale_ko.js
+++ b/i18n/locale/angular-locale_ko.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"SHORTMONTH":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"DAY":["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],"SHORTDAY":["일","월","화","수","목","금","토"],"AMPMS":["오전","오후"],"medium":"yyyy. M. d. a h:mm:ss","short":"yy. M. d. a h:mm","fullDate":"y년 M월 d일 EEEE","longDate":"y년 M월 d일","mediumDate":"yyyy. M. d.","shortDate":"yy. M. d.","mediumTime":"a h:mm:ss","shortTime":"a h:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₩"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"ko"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"SHORTMONTH":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"DAY":["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],"SHORTDAY":["일","월","화","수","목","금","토"],"AMPMS":["오전","오후"],"medium":"yyyy. M. d. a h:mm:ss","short":"yy. M. d. a h:mm","fullDate":"y년 M월 d일 EEEE","longDate":"y년 M월 d일","mediumDate":"yyyy. M. d.","shortDate":"yy. M. d.","mediumTime":"a h:mm:ss","shortTime":"a h:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₩"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"ko"});
+}];
diff --git a/i18n/locale/angular-locale_ln-cd.js b/i18n/locale/angular-locale_ln-cd.js
index 8d3cbdc6f6e1..d77bf96f4d36 100644
--- a/i18n/locale/angular-locale_ln-cd.js
+++ b/i18n/locale/angular-locale_ln-cd.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"F"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["sánzá ya yambo","sánzá ya míbalé","sánzá ya mísáto","sánzá ya mínei","sánzá ya mítáno","sánzá ya motóbá","sánzá ya nsambo","sánzá ya mwambe","sánzá ya libwa","sánzá ya zómi","sánzá ya zómi na mɔ̌kɔ́","sánzá ya zómi na míbalé"],"SHORTMONTH":["s1","s2","s3","s4","s5","s6","s7","s8","s9","s10","s11","s12"],"DAY":["eyenga","mokɔlɔ ya libosó","mokɔlɔ ya míbalé","mokɔlɔ ya mísáto","mokɔlɔ ya mínéi","mokɔlɔ ya mítáno","mpɔ́sɔ"],"SHORTDAY":["eye","m1","m2","m3","m4","m5","mps"],"AMPMS":["AM","PM"],"medium":"y MMM d HH:mm:ss","short":"yy/MM/dd HH:mm","fullDate":"EEEE, y MMMM dd","longDate":"y MMMM d","mediumDate":"y MMM d","shortDate":"yy/MM/dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"ln-cd"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"F"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["sánzá ya yambo","sánzá ya míbalé","sánzá ya mísáto","sánzá ya mínei","sánzá ya mítáno","sánzá ya motóbá","sánzá ya nsambo","sánzá ya mwambe","sánzá ya libwa","sánzá ya zómi","sánzá ya zómi na mɔ̌kɔ́","sánzá ya zómi na míbalé"],"SHORTMONTH":["s1","s2","s3","s4","s5","s6","s7","s8","s9","s10","s11","s12"],"DAY":["eyenga","mokɔlɔ ya libosó","mokɔlɔ ya míbalé","mokɔlɔ ya mísáto","mokɔlɔ ya mínéi","mokɔlɔ ya mítáno","mpɔ́sɔ"],"SHORTDAY":["eye","m1","m2","m3","m4","m5","mps"],"AMPMS":["AM","PM"],"medium":"y MMM d HH:mm:ss","short":"yy/MM/dd HH:mm","fullDate":"EEEE, y MMMM dd","longDate":"y MMMM d","mediumDate":"y MMM d","shortDate":"yy/MM/dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"ln-cd"});
+}];
diff --git a/i18n/locale/angular-locale_ln.js b/i18n/locale/angular-locale_ln.js
index 93ca889f9de1..8f28dbd58489 100644
--- a/i18n/locale/angular-locale_ln.js
+++ b/i18n/locale/angular-locale_ln.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["sánzá ya yambo","sánzá ya míbalé","sánzá ya mísáto","sánzá ya mínei","sánzá ya mítáno","sánzá ya motóbá","sánzá ya nsambo","sánzá ya mwambe","sánzá ya libwa","sánzá ya zómi","sánzá ya zómi na mɔ̌kɔ́","sánzá ya zómi na míbalé"],"SHORTMONTH":["s1","s2","s3","s4","s5","s6","s7","s8","s9","s10","s11","s12"],"DAY":["eyenga","mokɔlɔ ya libosó","mokɔlɔ ya míbalé","mokɔlɔ ya mísáto","mokɔlɔ ya mínéi","mokɔlɔ ya mítáno","mpɔ́sɔ"],"SHORTDAY":["eye","m1","m2","m3","m4","m5","mps"],"AMPMS":["AM","PM"],"medium":"y MMM d HH:mm:ss","short":"yy/MM/dd HH:mm","fullDate":"EEEE, y MMMM dd","longDate":"y MMMM d","mediumDate":"y MMM d","shortDate":"yy/MM/dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"F"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"ln"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["sánzá ya yambo","sánzá ya míbalé","sánzá ya mísáto","sánzá ya mínei","sánzá ya mítáno","sánzá ya motóbá","sánzá ya nsambo","sánzá ya mwambe","sánzá ya libwa","sánzá ya zómi","sánzá ya zómi na mɔ̌kɔ́","sánzá ya zómi na míbalé"],"SHORTMONTH":["s1","s2","s3","s4","s5","s6","s7","s8","s9","s10","s11","s12"],"DAY":["eyenga","mokɔlɔ ya libosó","mokɔlɔ ya míbalé","mokɔlɔ ya mísáto","mokɔlɔ ya mínéi","mokɔlɔ ya mítáno","mpɔ́sɔ"],"SHORTDAY":["eye","m1","m2","m3","m4","m5","mps"],"AMPMS":["AM","PM"],"medium":"y MMM d HH:mm:ss","short":"yy/MM/dd HH:mm","fullDate":"EEEE, y MMMM dd","longDate":"y MMMM d","mediumDate":"y MMM d","shortDate":"yy/MM/dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"F"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"ln"});
+}];
diff --git a/i18n/locale/angular-locale_lt-lt.js b/i18n/locale/angular-locale_lt-lt.js
index e26c614f92fc..329d50086c0c 100644
--- a/i18n/locale/angular-locale_lt-lt.js
+++ b/i18n/locale/angular-locale_lt-lt.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Lt"},"pluralCat":function (n) {  if ((n % 10) == 1 && ((n % 100) < 11 || (n % 100) > 19)) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 9 &&      ((n % 100) < 11 || (n % 100) > 19) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["sausis","vasaris","kovas","balandis","gegužė","birželis","liepa","rugpjūtis","rugsėjis","spalis","lapkritis","gruodis"],"SHORTMONTH":["Sau","Vas","Kov","Bal","Geg","Bir","Lie","Rgp","Rgs","Spl","Lap","Grd"],"DAY":["sekmadienis","pirmadienis","antradienis","trečiadienis","ketvirtadienis","penktadienis","šeštadienis"],"SHORTDAY":["Sk","Pr","An","Tr","Kt","Pn","Št"],"AMPMS":["priešpiet","popiet"],"medium":"yyyy.MM.dd HH:mm:ss","short":"yyyy-MM-dd HH:mm","fullDate":"y 'm'. MMMM d 'd'.,EEEE","longDate":"y 'm'. MMMM d 'd'.","mediumDate":"yyyy.MM.dd","shortDate":"yyyy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"lt-lt"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Lt"},"pluralCat":function (n) {  if ((n % 10) == 1 && ((n % 100) < 11 || (n % 100) > 19)) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 9 &&      ((n % 100) < 11 || (n % 100) > 19) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["sausis","vasaris","kovas","balandis","gegužė","birželis","liepa","rugpjūtis","rugsėjis","spalis","lapkritis","gruodis"],"SHORTMONTH":["Sau","Vas","Kov","Bal","Geg","Bir","Lie","Rgp","Rgs","Spl","Lap","Grd"],"DAY":["sekmadienis","pirmadienis","antradienis","trečiadienis","ketvirtadienis","penktadienis","šeštadienis"],"SHORTDAY":["Sk","Pr","An","Tr","Kt","Pn","Št"],"AMPMS":["priešpiet","popiet"],"medium":"yyyy.MM.dd HH:mm:ss","short":"yyyy-MM-dd HH:mm","fullDate":"y 'm'. MMMM d 'd'.,EEEE","longDate":"y 'm'. MMMM d 'd'.","mediumDate":"yyyy.MM.dd","shortDate":"yyyy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"lt-lt"});
+}];
diff --git a/i18n/locale/angular-locale_lt.js b/i18n/locale/angular-locale_lt.js
index 8cfd28cefd9e..ac8158e0983f 100644
--- a/i18n/locale/angular-locale_lt.js
+++ b/i18n/locale/angular-locale_lt.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["sausis","vasaris","kovas","balandis","gegužė","birželis","liepa","rugpjūtis","rugsėjis","spalis","lapkritis","gruodis"],"SHORTMONTH":["Sau","Vas","Kov","Bal","Geg","Bir","Lie","Rgp","Rgs","Spl","Lap","Grd"],"DAY":["sekmadienis","pirmadienis","antradienis","trečiadienis","ketvirtadienis","penktadienis","šeštadienis"],"SHORTDAY":["Sk","Pr","An","Tr","Kt","Pn","Št"],"AMPMS":["priešpiet","popiet"],"medium":"yyyy.MM.dd HH:mm:ss","short":"yyyy-MM-dd HH:mm","fullDate":"y 'm'. MMMM d 'd'.,EEEE","longDate":"y 'm'. MMMM d 'd'.","mediumDate":"yyyy.MM.dd","shortDate":"yyyy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Lt"},"pluralCat":function (n) {  if ((n % 10) == 1 && ((n % 100) < 11 || (n % 100) > 19)) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 9 &&      ((n % 100) < 11 || (n % 100) > 19) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"id":"lt"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["sausis","vasaris","kovas","balandis","gegužė","birželis","liepa","rugpjūtis","rugsėjis","spalis","lapkritis","gruodis"],"SHORTMONTH":["Sau","Vas","Kov","Bal","Geg","Bir","Lie","Rgp","Rgs","Spl","Lap","Grd"],"DAY":["sekmadienis","pirmadienis","antradienis","trečiadienis","ketvirtadienis","penktadienis","šeštadienis"],"SHORTDAY":["Sk","Pr","An","Tr","Kt","Pn","Št"],"AMPMS":["priešpiet","popiet"],"medium":"yyyy.MM.dd HH:mm:ss","short":"yyyy-MM-dd HH:mm","fullDate":"y 'm'. MMMM d 'd'.,EEEE","longDate":"y 'm'. MMMM d 'd'.","mediumDate":"yyyy.MM.dd","shortDate":"yyyy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Lt"},"pluralCat":function (n) {  if ((n % 10) == 1 && ((n % 100) < 11 || (n % 100) > 19)) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 9 &&      ((n % 100) < 11 || (n % 100) > 19) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"id":"lt"});
+}];
diff --git a/i18n/locale/angular-locale_lv-lv.js b/i18n/locale/angular-locale_lv-lv.js
index f960350f8fbf..166794e567d9 100644
--- a/i18n/locale/angular-locale_lv-lv.js
+++ b/i18n/locale/angular-locale_lv-lv.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Ls"},"pluralCat":function (n) {  if (n == 0) {    return PLURAL_CATEGORY.ZERO;  }  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvāris","februāris","marts","aprīlis","maijs","jūnijs","jūlijs","augusts","septembris","oktobris","novembris","decembris"],"SHORTMONTH":["janv.","febr.","marts","apr.","maijs","jūn.","jūl.","aug.","sept.","okt.","nov.","dec."],"DAY":["svētdiena","pirmdiena","otrdiena","trešdiena","ceturtdiena","piektdiena","sestdiena"],"SHORTDAY":["Sv","Pr","Ot","Tr","Ce","Pk","Se"],"AMPMS":["priekšpusdienā","pēcpusdienā"],"medium":"y. 'gada' d. MMM HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, y. 'gada' d. MMMM","longDate":"y. 'gada' d. MMMM","mediumDate":"y. 'gada' d. MMM","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"lv-lv"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Ls"},"pluralCat":function (n) {  if (n == 0) {    return PLURAL_CATEGORY.ZERO;  }  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janvāris","februāris","marts","aprīlis","maijs","jūnijs","jūlijs","augusts","septembris","oktobris","novembris","decembris"],"SHORTMONTH":["janv.","febr.","marts","apr.","maijs","jūn.","jūl.","aug.","sept.","okt.","nov.","dec."],"DAY":["svētdiena","pirmdiena","otrdiena","trešdiena","ceturtdiena","piektdiena","sestdiena"],"SHORTDAY":["Sv","Pr","Ot","Tr","Ce","Pk","Se"],"AMPMS":["priekšpusdienā","pēcpusdienā"],"medium":"y. 'gada' d. MMM HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, y. 'gada' d. MMMM","longDate":"y. 'gada' d. MMMM","mediumDate":"y. 'gada' d. MMM","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"lv-lv"});
+}];
diff --git a/i18n/locale/angular-locale_lv.js b/i18n/locale/angular-locale_lv.js
index a01c403cb521..73a4beb39a58 100644
--- a/i18n/locale/angular-locale_lv.js
+++ b/i18n/locale/angular-locale_lv.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["janvāris","februāris","marts","aprīlis","maijs","jūnijs","jūlijs","augusts","septembris","oktobris","novembris","decembris"],"SHORTMONTH":["janv.","febr.","marts","apr.","maijs","jūn.","jūl.","aug.","sept.","okt.","nov.","dec."],"DAY":["svētdiena","pirmdiena","otrdiena","trešdiena","ceturtdiena","piektdiena","sestdiena"],"SHORTDAY":["Sv","Pr","Ot","Tr","Ce","Pk","Se"],"AMPMS":["priekšpusdienā","pēcpusdienā"],"medium":"y. 'gada' d. MMM HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, y. 'gada' d. MMMM","longDate":"y. 'gada' d. MMMM","mediumDate":"y. 'gada' d. MMM","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Ls"},"pluralCat":function (n) {  if (n == 0) {    return PLURAL_CATEGORY.ZERO;  }  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"lv"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["janvāris","februāris","marts","aprīlis","maijs","jūnijs","jūlijs","augusts","septembris","oktobris","novembris","decembris"],"SHORTMONTH":["janv.","febr.","marts","apr.","maijs","jūn.","jūl.","aug.","sept.","okt.","nov.","dec."],"DAY":["svētdiena","pirmdiena","otrdiena","trešdiena","ceturtdiena","piektdiena","sestdiena"],"SHORTDAY":["Sv","Pr","Ot","Tr","Ce","Pk","Se"],"AMPMS":["priekšpusdienā","pēcpusdienā"],"medium":"y. 'gada' d. MMM HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, y. 'gada' d. MMMM","longDate":"y. 'gada' d. MMMM","mediumDate":"y. 'gada' d. MMM","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Ls"},"pluralCat":function (n) {  if (n == 0) {    return PLURAL_CATEGORY.ZERO;  }  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"lv"});
+}];
diff --git a/i18n/locale/angular-locale_ml-in.js b/i18n/locale/angular-locale_ml-in.js
index 663eeb33eec1..077a944f2627 100644
--- a/i18n/locale/angular-locale_ml-in.js
+++ b/i18n/locale/angular-locale_ml-in.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":"\u00A4","negPre":"-","negSuf":"\u00A4","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ജനുവരി","ഫെബ്രുവരി","മാര്‍ച്ച്","ഏപ്രില്‍","മേയ്","ജൂണ്‍","ജൂലൈ","ആഗസ്റ്റ്","സെപ്റ്റംബര്‍","ഒക്ടോബര്‍","നവംബര്‍","ഡിസംബര്‍"],"SHORTMONTH":["ജനു","ഫെബ്രു","മാര്‍","ഏപ്രി","മേയ്","ജൂണ്‍","ജൂലൈ","ഓഗ","സെപ്റ്റം","ഒക്ടോ","നവം","ഡിസം"],"DAY":["ഞായറാഴ്ച","തിങ്കളാഴ്ച","ചൊവ്വാഴ്ച","ബുധനാഴ്ച","വ്യാഴാഴ്ച","വെള്ളിയാഴ്ച","ശനിയാഴ്ച"],"SHORTDAY":["ഞായര്‍","തിങ്കള്‍","ചൊവ്വ","ബുധന്‍","വ്യാഴം","വെള്ളി","ശനി"],"AMPMS":["രാവിലെ","വൈകുന്നേരം"],"medium":"y, MMM d h:mm:ss a","short":"dd/MM/yy h:mm a","fullDate":"y, MMMM d, EEEE","longDate":"y, MMMM d","mediumDate":"y, MMM d","shortDate":"dd/MM/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"ml-in"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":"\u00A4","negPre":"-","negSuf":"\u00A4","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ജനുവരി","ഫെബ്രുവരി","മാര്‍ച്ച്","ഏപ്രില്‍","മേയ്","ജൂണ്‍","ജൂലൈ","ആഗസ്റ്റ്","സെപ്റ്റംബര്‍","ഒക്ടോബര്‍","നവംബര്‍","ഡിസംബര്‍"],"SHORTMONTH":["ജനു","ഫെബ്രു","മാര്‍","ഏപ്രി","മേയ്","ജൂണ്‍","ജൂലൈ","ഓഗ","സെപ്റ്റം","ഒക്ടോ","നവം","ഡിസം"],"DAY":["ഞായറാഴ്ച","തിങ്കളാഴ്ച","ചൊവ്വാഴ്ച","ബുധനാഴ്ച","വ്യാഴാഴ്ച","വെള്ളിയാഴ്ച","ശനിയാഴ്ച"],"SHORTDAY":["ഞായര്‍","തിങ്കള്‍","ചൊവ്വ","ബുധന്‍","വ്യാഴം","വെള്ളി","ശനി"],"AMPMS":["രാവിലെ","വൈകുന്നേരം"],"medium":"y, MMM d h:mm:ss a","short":"dd/MM/yy h:mm a","fullDate":"y, MMMM d, EEEE","longDate":"y, MMMM d","mediumDate":"y, MMM d","shortDate":"dd/MM/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"ml-in"});
+}];
diff --git a/i18n/locale/angular-locale_ml.js b/i18n/locale/angular-locale_ml.js
index 810fdfc4ce1c..bd3ff33a5671 100644
--- a/i18n/locale/angular-locale_ml.js
+++ b/i18n/locale/angular-locale_ml.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["ജനുവരി","ഫെബ്രുവരി","മാര്‍ച്ച്","ഏപ്രില്‍","മേയ്","ജൂണ്‍","ജൂലൈ","ആഗസ്റ്റ്","സെപ്റ്റംബര്‍","ഒക്ടോബര്‍","നവംബര്‍","ഡിസംബര്‍"],"SHORTMONTH":["ജനു","ഫെബ്രു","മാര്‍","ഏപ്രി","മേയ്","ജൂണ്‍","ജൂലൈ","ഓഗ","സെപ്റ്റം","ഒക്ടോ","നവം","ഡിസം"],"DAY":["ഞായറാഴ്ച","തിങ്കളാഴ്ച","ചൊവ്വാഴ്ച","ബുധനാഴ്ച","വ്യാഴാഴ്ച","വെള്ളിയാഴ്ച","ശനിയാഴ്ച"],"SHORTDAY":["ഞായര്‍","തിങ്കള്‍","ചൊവ്വ","ബുധന്‍","വ്യാഴം","വെള്ളി","ശനി"],"AMPMS":["രാവിലെ","വൈകുന്നേരം"],"medium":"y, MMM d h:mm:ss a","short":"dd/MM/yy h:mm a","fullDate":"y, MMMM d, EEEE","longDate":"y, MMMM d","mediumDate":"y, MMM d","shortDate":"dd/MM/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":"\u00A4","negPre":"-","negSuf":"\u00A4","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"ml"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["ജനുവരി","ഫെബ്രുവരി","മാര്‍ച്ച്","ഏപ്രില്‍","മേയ്","ജൂണ്‍","ജൂലൈ","ആഗസ്റ്റ്","സെപ്റ്റംബര്‍","ഒക്ടോബര്‍","നവംബര്‍","ഡിസംബര്‍"],"SHORTMONTH":["ജനു","ഫെബ്രു","മാര്‍","ഏപ്രി","മേയ്","ജൂണ്‍","ജൂലൈ","ഓഗ","സെപ്റ്റം","ഒക്ടോ","നവം","ഡിസം"],"DAY":["ഞായറാഴ്ച","തിങ്കളാഴ്ച","ചൊവ്വാഴ്ച","ബുധനാഴ്ച","വ്യാഴാഴ്ച","വെള്ളിയാഴ്ച","ശനിയാഴ്ച"],"SHORTDAY":["ഞായര്‍","തിങ്കള്‍","ചൊവ്വ","ബുധന്‍","വ്യാഴം","വെള്ളി","ശനി"],"AMPMS":["രാവിലെ","വൈകുന്നേരം"],"medium":"y, MMM d h:mm:ss a","short":"dd/MM/yy h:mm a","fullDate":"y, MMMM d, EEEE","longDate":"y, MMMM d","mediumDate":"y, MMM d","shortDate":"dd/MM/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":"\u00A4","negPre":"-","negSuf":"\u00A4","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"ml"});
+}];
diff --git a/i18n/locale/angular-locale_mo.js b/i18n/locale/angular-locale_mo.js
index 3a2f64ca56be..e84a8fcd4c30 100644
--- a/i18n/locale/angular-locale_mo.js
+++ b/i18n/locale/angular-locale_mo.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["ianuarie","februarie","martie","aprilie","mai","iunie","iulie","august","septembrie","octombrie","noiembrie","decembrie"],"SHORTMONTH":["ian.","feb.","mar.","apr.","mai","iun.","iul.","aug.","sept.","oct.","nov.","dec."],"DAY":["duminică","luni","marți","miercuri","joi","vineri","sâmbătă"],"SHORTDAY":["Du","Lu","Ma","Mi","Jo","Vi","Sâ"],"AMPMS":["AM","PM"],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yyyy HH:mm","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"MDL"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 0 || n != 1 && (n % 100) >= 1 &&      (n % 100) <= 19 && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"id":"mo"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["ianuarie","februarie","martie","aprilie","mai","iunie","iulie","august","septembrie","octombrie","noiembrie","decembrie"],"SHORTMONTH":["ian.","feb.","mar.","apr.","mai","iun.","iul.","aug.","sept.","oct.","nov.","dec."],"DAY":["duminică","luni","marți","miercuri","joi","vineri","sâmbătă"],"SHORTDAY":["Du","Lu","Ma","Mi","Jo","Vi","Sâ"],"AMPMS":["AM","PM"],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yyyy HH:mm","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"MDL"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 0 || n != 1 && (n % 100) >= 1 &&      (n % 100) <= 19 && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"id":"mo"});
+}];
diff --git a/i18n/locale/angular-locale_mr-in.js b/i18n/locale/angular-locale_mr-in.js
index 96960a2b5f47..49433e97eed9 100644
--- a/i18n/locale/angular-locale_mr-in.js
+++ b/i18n/locale/angular-locale_mr-in.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["जानेवारी","फेब्रुवारी","मार्च","एप्रिल","मे","जून","जुलै","ऑगस्ट","सप्टेंबर","ऑक्टोबर","नोव्हेंबर","डिसेंबर"],"SHORTMONTH":["जानेवारी","फेब्रुवारी","मार्च","एप्रिल","मे","जून","जुलै","ऑगस्ट","सप्टेंबर","ऑक्टोबर","नोव्हेंबर","डिसेंबर"],"DAY":["रविवार","सोमवार","मंगळवार","बुधवार","गुरुवार","शुक्रवार","शनिवार"],"SHORTDAY":["रवि","सोम","मंगळ","बुध","गुरु","शुक्र","शनि"],"AMPMS":["am","pm"],"medium":"d MMM y h-mm-ss a","short":"d-M-yy h-mm a","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d-M-yy","mediumTime":"h-mm-ss a","shortTime":"h-mm a"},"id":"mr-in"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["जानेवारी","फेब्रुवारी","मार्च","एप्रिल","मे","जून","जुलै","ऑगस्ट","सप्टेंबर","ऑक्टोबर","नोव्हेंबर","डिसेंबर"],"SHORTMONTH":["जानेवारी","फेब्रुवारी","मार्च","एप्रिल","मे","जून","जुलै","ऑगस्ट","सप्टेंबर","ऑक्टोबर","नोव्हेंबर","डिसेंबर"],"DAY":["रविवार","सोमवार","मंगळवार","बुधवार","गुरुवार","शुक्रवार","शनिवार"],"SHORTDAY":["रवि","सोम","मंगळ","बुध","गुरु","शुक्र","शनि"],"AMPMS":["am","pm"],"medium":"d MMM y h-mm-ss a","short":"d-M-yy h-mm a","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d-M-yy","mediumTime":"h-mm-ss a","shortTime":"h-mm a"},"id":"mr-in"});
+}];
diff --git a/i18n/locale/angular-locale_mr.js b/i18n/locale/angular-locale_mr.js
index 2471cc1b63ef..b8421747f2fc 100644
--- a/i18n/locale/angular-locale_mr.js
+++ b/i18n/locale/angular-locale_mr.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["जानेवारी","फेब्रुवारी","मार्च","एप्रिल","मे","जून","जुलै","ऑगस्ट","सप्टेंबर","ऑक्टोबर","नोव्हेंबर","डिसेंबर"],"SHORTMONTH":["जानेवारी","फेब्रुवारी","मार्च","एप्रिल","मे","जून","जुलै","ऑगस्ट","सप्टेंबर","ऑक्टोबर","नोव्हेंबर","डिसेंबर"],"DAY":["रविवार","सोमवार","मंगळवार","बुधवार","गुरुवार","शुक्रवार","शनिवार"],"SHORTDAY":["रवि","सोम","मंगळ","बुध","गुरु","शुक्र","शनि"],"AMPMS":["am","pm"],"medium":"d MMM y h-mm-ss a","short":"d-M-yy h-mm a","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d-M-yy","mediumTime":"h-mm-ss a","shortTime":"h-mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"mr"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["जानेवारी","फेब्रुवारी","मार्च","एप्रिल","मे","जून","जुलै","ऑगस्ट","सप्टेंबर","ऑक्टोबर","नोव्हेंबर","डिसेंबर"],"SHORTMONTH":["जानेवारी","फेब्रुवारी","मार्च","एप्रिल","मे","जून","जुलै","ऑगस्ट","सप्टेंबर","ऑक्टोबर","नोव्हेंबर","डिसेंबर"],"DAY":["रविवार","सोमवार","मंगळवार","बुधवार","गुरुवार","शुक्रवार","शनिवार"],"SHORTDAY":["रवि","सोम","मंगळ","बुध","गुरु","शुक्र","शनि"],"AMPMS":["am","pm"],"medium":"d MMM y h-mm-ss a","short":"d-M-yy h-mm a","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d-M-yy","mediumTime":"h-mm-ss a","shortTime":"h-mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"mr"});
+}];
diff --git a/i18n/locale/angular-locale_ms-my.js b/i18n/locale/angular-locale_ms-my.js
index ecea8b4162f8..2ceaa236bddd 100644
--- a/i18n/locale/angular-locale_ms-my.js
+++ b/i18n/locale/angular-locale_ms-my.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"RM"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember"],"SHORTMONTH":["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ogos","Sep","Okt","Nov","Dis"],"DAY":["Ahad","Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu"],"SHORTDAY":["Ahd","Isn","Sel","Rab","Kha","Jum","Sab"],"AMPMS":["AM","PM"],"medium":"dd/MM/yyyy h:mm:ss a","short":"d/MM/yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd/MM/yyyy","shortDate":"d/MM/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"ms-my"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"RM"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember"],"SHORTMONTH":["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ogos","Sep","Okt","Nov","Dis"],"DAY":["Ahad","Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu"],"SHORTDAY":["Ahd","Isn","Sel","Rab","Kha","Jum","Sab"],"AMPMS":["AM","PM"],"medium":"dd/MM/yyyy h:mm:ss a","short":"d/MM/yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd/MM/yyyy","shortDate":"d/MM/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"ms-my"});
+}];
diff --git a/i18n/locale/angular-locale_ms.js b/i18n/locale/angular-locale_ms.js
index 46adba95d942..a94f1b485b61 100644
--- a/i18n/locale/angular-locale_ms.js
+++ b/i18n/locale/angular-locale_ms.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember"],"SHORTMONTH":["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ogos","Sep","Okt","Nov","Dis"],"DAY":["Ahad","Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu"],"SHORTDAY":["Ahd","Isn","Sel","Rab","Kha","Jum","Sab"],"AMPMS":["AM","PM"],"medium":"dd/MM/yyyy h:mm:ss a","short":"d/MM/yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd/MM/yyyy","shortDate":"d/MM/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"RM"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"ms"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember"],"SHORTMONTH":["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ogos","Sep","Okt","Nov","Dis"],"DAY":["Ahad","Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu"],"SHORTDAY":["Ahd","Isn","Sel","Rab","Kha","Jum","Sab"],"AMPMS":["AM","PM"],"medium":"dd/MM/yyyy h:mm:ss a","short":"d/MM/yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd/MM/yyyy","shortDate":"d/MM/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"RM"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"ms"});
+}];
diff --git a/i18n/locale/angular-locale_mt-mt.js b/i18n/locale/angular-locale_mt-mt.js
index 54de6f1dcd76..6ac46271f05e 100644
--- a/i18n/locale/angular-locale_mt-mt.js
+++ b/i18n/locale/angular-locale_mt-mt.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₤"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 0 || ((n % 100) >= 2 && (n % 100) <= 4 && n == Math.floor(n))) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 100) >= 11 && (n % 100) <= 19 && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Jannar","Frar","Marzu","April","Mejju","Ġunju","Lulju","Awwissu","Settembru","Ottubru","Novembru","Diċembru"],"SHORTMONTH":["Jan","Fra","Mar","Apr","Mej","Ġun","Lul","Aww","Set","Ott","Nov","Diċ"],"DAY":["Il-Ħadd","It-Tnejn","It-Tlieta","L-Erbgħa","Il-Ħamis","Il-Ġimgħa","Is-Sibt"],"SHORTDAY":["Ħad","Tne","Tli","Erb","Ħam","Ġim","Sib"],"AMPMS":["QN","WN"],"medium":"dd MMM y HH:mm:ss","short":"dd/MM/yyyy HH:mm","fullDate":"EEEE, d 'ta'’ MMMM y","longDate":"d 'ta'’ MMMM y","mediumDate":"dd MMM y","shortDate":"dd/MM/yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"mt-mt"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₤"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 0 || ((n % 100) >= 2 && (n % 100) <= 4 && n == Math.floor(n))) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 100) >= 11 && (n % 100) <= 19 && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Jannar","Frar","Marzu","April","Mejju","Ġunju","Lulju","Awwissu","Settembru","Ottubru","Novembru","Diċembru"],"SHORTMONTH":["Jan","Fra","Mar","Apr","Mej","Ġun","Lul","Aww","Set","Ott","Nov","Diċ"],"DAY":["Il-Ħadd","It-Tnejn","It-Tlieta","L-Erbgħa","Il-Ħamis","Il-Ġimgħa","Is-Sibt"],"SHORTDAY":["Ħad","Tne","Tli","Erb","Ħam","Ġim","Sib"],"AMPMS":["QN","WN"],"medium":"dd MMM y HH:mm:ss","short":"dd/MM/yyyy HH:mm","fullDate":"EEEE, d 'ta'’ MMMM y","longDate":"d 'ta'’ MMMM y","mediumDate":"dd MMM y","shortDate":"dd/MM/yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"mt-mt"});
+}];
diff --git a/i18n/locale/angular-locale_mt.js b/i18n/locale/angular-locale_mt.js
index 9471c8454dec..3cc32d6c5fd4 100644
--- a/i18n/locale/angular-locale_mt.js
+++ b/i18n/locale/angular-locale_mt.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Jannar","Frar","Marzu","April","Mejju","Ġunju","Lulju","Awwissu","Settembru","Ottubru","Novembru","Diċembru"],"SHORTMONTH":["Jan","Fra","Mar","Apr","Mej","Ġun","Lul","Aww","Set","Ott","Nov","Diċ"],"DAY":["Il-Ħadd","It-Tnejn","It-Tlieta","L-Erbgħa","Il-Ħamis","Il-Ġimgħa","Is-Sibt"],"SHORTDAY":["Ħad","Tne","Tli","Erb","Ħam","Ġim","Sib"],"AMPMS":["QN","WN"],"medium":"dd MMM y HH:mm:ss","short":"dd/MM/yyyy HH:mm","fullDate":"EEEE, d 'ta'’ MMMM y","longDate":"d 'ta'’ MMMM y","mediumDate":"dd MMM y","shortDate":"dd/MM/yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₤"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 0 || ((n % 100) >= 2 && (n % 100) <= 4 && n == Math.floor(n))) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 100) >= 11 && (n % 100) <= 19 && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"id":"mt"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Jannar","Frar","Marzu","April","Mejju","Ġunju","Lulju","Awwissu","Settembru","Ottubru","Novembru","Diċembru"],"SHORTMONTH":["Jan","Fra","Mar","Apr","Mej","Ġun","Lul","Aww","Set","Ott","Nov","Diċ"],"DAY":["Il-Ħadd","It-Tnejn","It-Tlieta","L-Erbgħa","Il-Ħamis","Il-Ġimgħa","Is-Sibt"],"SHORTDAY":["Ħad","Tne","Tli","Erb","Ħam","Ġim","Sib"],"AMPMS":["QN","WN"],"medium":"dd MMM y HH:mm:ss","short":"dd/MM/yyyy HH:mm","fullDate":"EEEE, d 'ta'’ MMMM y","longDate":"d 'ta'’ MMMM y","mediumDate":"dd MMM y","shortDate":"dd/MM/yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₤"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 0 || ((n % 100) >= 2 && (n % 100) <= 4 && n == Math.floor(n))) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 100) >= 11 && (n % 100) <= 19 && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"id":"mt"});
+}];
diff --git a/i18n/locale/angular-locale_nl-nl.js b/i18n/locale/angular-locale_nl-nl.js
index 7f1a38d26881..e4951a31a864 100644
--- a/i18n/locale/angular-locale_nl-nl.js
+++ b/i18n/locale/angular-locale_nl-nl.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 ","negSuf":"-","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],"SHORTMONTH":["jan.","feb.","mrt.","apr.","mei","jun.","jul.","aug.","sep.","okt.","nov.","dec."],"DAY":["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],"SHORTDAY":["zo","ma","di","wo","do","vr","za"],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd-MM-yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd-MM-yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"nl-nl"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 ","negSuf":"-","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],"SHORTMONTH":["jan.","feb.","mrt.","apr.","mei","jun.","jul.","aug.","sep.","okt.","nov.","dec."],"DAY":["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],"SHORTDAY":["zo","ma","di","wo","do","vr","za"],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd-MM-yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd-MM-yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"nl-nl"});
+}];
diff --git a/i18n/locale/angular-locale_nl.js b/i18n/locale/angular-locale_nl.js
index 74cd2fbf45e0..0123aac79813 100644
--- a/i18n/locale/angular-locale_nl.js
+++ b/i18n/locale/angular-locale_nl.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],"SHORTMONTH":["jan.","feb.","mrt.","apr.","mei","jun.","jul.","aug.","sep.","okt.","nov.","dec."],"DAY":["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],"SHORTDAY":["zo","ma","di","wo","do","vr","za"],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd-MM-yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd-MM-yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 ","negSuf":"-","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"nl"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],"SHORTMONTH":["jan.","feb.","mrt.","apr.","mei","jun.","jul.","aug.","sep.","okt.","nov.","dec."],"DAY":["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],"SHORTDAY":["zo","ma","di","wo","do","vr","za"],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd-MM-yy HH:mm","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd-MM-yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 ","negSuf":"-","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"nl"});
+}];
diff --git a/i18n/locale/angular-locale_no.js b/i18n/locale/angular-locale_no.js
index fca70380e782..185bba5c298b 100644
--- a/i18n/locale/angular-locale_no.js
+++ b/i18n/locale/angular-locale_no.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["januar","februar","mars","april","mai","juni","juli","august","september","oktober","november","desember"],"SHORTMONTH":["jan.","feb.","mars","apr.","mai","juni","juli","aug.","sep.","okt.","nov.","des."],"DAY":["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],"SHORTDAY":["søn.","man.","tir.","ons.","tor.","fre.","lør."],"AMPMS":["AM","PM"],"medium":"d. MMM y HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE d. MMMM y","longDate":"d. MMMM y","mediumDate":"d. MMM y","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kr"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"no"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["januar","februar","mars","april","mai","juni","juli","august","september","oktober","november","desember"],"SHORTMONTH":["jan.","feb.","mars","apr.","mai","juni","juli","aug.","sep.","okt.","nov.","des."],"DAY":["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],"SHORTDAY":["søn.","man.","tir.","ons.","tor.","fre.","lør."],"AMPMS":["AM","PM"],"medium":"d. MMM y HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE d. MMMM y","longDate":"d. MMMM y","mediumDate":"d. MMM y","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kr"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"no"});
+}];
diff --git a/i18n/locale/angular-locale_or-in.js b/i18n/locale/angular-locale_or-in.js
index 7ad8e8902dc1..17a9b6e61870 100644
--- a/i18n/locale/angular-locale_or-in.js
+++ b/i18n/locale/angular-locale_or-in.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ଜାନୁଆରୀ","ଫେବ୍ରୁୟାରୀ","ମାର୍ଚ୍ଚ","ଅପ୍ରେଲ","ମେ","ଜୁନ","ଜୁଲାଇ","ଅଗଷ୍ଟ","ସେପ୍ଟେମ୍ବର","ଅକ୍ଟୋବର","ନଭେମ୍ବର","ଡିସେମ୍ବର"],"SHORTMONTH":["ଜାନୁଆରୀ","ଫେବ୍ରୁୟାରୀ","ମାର୍ଚ୍ଚ","ଅପ୍ରେଲ","ମେ","ଜୁନ","ଜୁଲାଇ","ଅଗଷ୍ଟ","ସେପ୍ଟେମ୍ବର","ଅକ୍ଟୋବର","ନଭେମ୍ବର","ଡିସେମ୍ବର"],"DAY":["ରବିବାର","ସୋମବାର","ମଙ୍ଗଳବାର","ବୁଧବାର","ଗୁରୁବାର","ଶୁକ୍ରବାର","ଶନିବାର"],"SHORTDAY":["ରବି","ସୋମ","ମଙ୍ଗଳ","ବୁଧ","ଗୁରୁ","ଶୁକ୍ର","ଶନି"],"AMPMS":["am","pm"],"medium":"d MMM y h:mm:ss a","short":"d-M-yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d-M-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"or-in"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ଜାନୁଆରୀ","ଫେବ୍ରୁୟାରୀ","ମାର୍ଚ୍ଚ","ଅପ୍ରେଲ","ମେ","ଜୁନ","ଜୁଲାଇ","ଅଗଷ୍ଟ","ସେପ୍ଟେମ୍ବର","ଅକ୍ଟୋବର","ନଭେମ୍ବର","ଡିସେମ୍ବର"],"SHORTMONTH":["ଜାନୁଆରୀ","ଫେବ୍ରୁୟାରୀ","ମାର୍ଚ୍ଚ","ଅପ୍ରେଲ","ମେ","ଜୁନ","ଜୁଲାଇ","ଅଗଷ୍ଟ","ସେପ୍ଟେମ୍ବର","ଅକ୍ଟୋବର","ନଭେମ୍ବର","ଡିସେମ୍ବର"],"DAY":["ରବିବାର","ସୋମବାର","ମଙ୍ଗଳବାର","ବୁଧବାର","ଗୁରୁବାର","ଶୁକ୍ରବାର","ଶନିବାର"],"SHORTDAY":["ରବି","ସୋମ","ମଙ୍ଗଳ","ବୁଧ","ଗୁରୁ","ଶୁକ୍ର","ଶନି"],"AMPMS":["am","pm"],"medium":"d MMM y h:mm:ss a","short":"d-M-yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d-M-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"or-in"});
+}];
diff --git a/i18n/locale/angular-locale_or.js b/i18n/locale/angular-locale_or.js
index 5cf6b3d97de9..f7601d063c9a 100644
--- a/i18n/locale/angular-locale_or.js
+++ b/i18n/locale/angular-locale_or.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["ଜାନୁଆରୀ","ଫେବ୍ରୁୟାରୀ","ମାର୍ଚ୍ଚ","ଅପ୍ରେଲ","ମେ","ଜୁନ","ଜୁଲାଇ","ଅଗଷ୍ଟ","ସେପ୍ଟେମ୍ବର","ଅକ୍ଟୋବର","ନଭେମ୍ବର","ଡିସେମ୍ବର"],"SHORTMONTH":["ଜାନୁଆରୀ","ଫେବ୍ରୁୟାରୀ","ମାର୍ଚ୍ଚ","ଅପ୍ରେଲ","ମେ","ଜୁନ","ଜୁଲାଇ","ଅଗଷ୍ଟ","ସେପ୍ଟେମ୍ବର","ଅକ୍ଟୋବର","ନଭେମ୍ବର","ଡିସେମ୍ବର"],"DAY":["ରବିବାର","ସୋମବାର","ମଙ୍ଗଳବାର","ବୁଧବାର","ଗୁରୁବାର","ଶୁକ୍ରବାର","ଶନିବାର"],"SHORTDAY":["ରବି","ସୋମ","ମଙ୍ଗଳ","ବୁଧ","ଗୁରୁ","ଶୁକ୍ର","ଶନି"],"AMPMS":["am","pm"],"medium":"d MMM y h:mm:ss a","short":"d-M-yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d-M-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"or"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["ଜାନୁଆରୀ","ଫେବ୍ରୁୟାରୀ","ମାର୍ଚ୍ଚ","ଅପ୍ରେଲ","ମେ","ଜୁନ","ଜୁଲାଇ","ଅଗଷ୍ଟ","ସେପ୍ଟେମ୍ବର","ଅକ୍ଟୋବର","ନଭେମ୍ବର","ଡିସେମ୍ବର"],"SHORTMONTH":["ଜାନୁଆରୀ","ଫେବ୍ରୁୟାରୀ","ମାର୍ଚ୍ଚ","ଅପ୍ରେଲ","ମେ","ଜୁନ","ଜୁଲାଇ","ଅଗଷ୍ଟ","ସେପ୍ଟେମ୍ବର","ଅକ୍ଟୋବର","ନଭେମ୍ବର","ଡିସେମ୍ବର"],"DAY":["ରବିବାର","ସୋମବାର","ମଙ୍ଗଳବାର","ବୁଧବାର","ଗୁରୁବାର","ଶୁକ୍ରବାର","ଶନିବାର"],"SHORTDAY":["ରବି","ସୋମ","ମଙ୍ଗଳ","ବୁଧ","ଗୁରୁ","ଶୁକ୍ର","ଶନି"],"AMPMS":["am","pm"],"medium":"d MMM y h:mm:ss a","short":"d-M-yy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d-M-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"or"});
+}];
diff --git a/i18n/locale/angular-locale_pl-pl.js b/i18n/locale/angular-locale_pl-pl.js
index 0f501610e886..1bd69d370116 100644
--- a/i18n/locale/angular-locale_pl-pl.js
+++ b/i18n/locale/angular-locale_pl-pl.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"zł"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || n != 1 && (n % 10) == 1 ||      ((n % 10) >= 5 && (n % 10) <= 9 || (n % 100) >= 12 && (n % 100) <= 14) &&      n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["stycznia","lutego","marca","kwietnia","maja","czerwca","lipca","sierpnia","września","października","listopada","grudnia"],"SHORTMONTH":["sty","lut","mar","kwi","maj","cze","lip","sie","wrz","paź","lis","gru"],"DAY":["niedziela","poniedziałek","wtorek","środa","czwartek","piątek","sobota"],"SHORTDAY":["niedz.","pon.","wt.","śr.","czw.","pt.","sob."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd.MM.yyyy HH:mm","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd.MM.yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"pl-pl"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"zł"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || n != 1 && (n % 10) == 1 ||      ((n % 10) >= 5 && (n % 10) <= 9 || (n % 100) >= 12 && (n % 100) <= 14) &&      n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["stycznia","lutego","marca","kwietnia","maja","czerwca","lipca","sierpnia","września","października","listopada","grudnia"],"SHORTMONTH":["sty","lut","mar","kwi","maj","cze","lip","sie","wrz","paź","lis","gru"],"DAY":["niedziela","poniedziałek","wtorek","środa","czwartek","piątek","sobota"],"SHORTDAY":["niedz.","pon.","wt.","śr.","czw.","pt.","sob."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd.MM.yyyy HH:mm","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd.MM.yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"pl-pl"});
+}];
diff --git a/i18n/locale/angular-locale_pl.js b/i18n/locale/angular-locale_pl.js
index 8b6886b0658a..e98836d3f5ae 100644
--- a/i18n/locale/angular-locale_pl.js
+++ b/i18n/locale/angular-locale_pl.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["stycznia","lutego","marca","kwietnia","maja","czerwca","lipca","sierpnia","września","października","listopada","grudnia"],"SHORTMONTH":["sty","lut","mar","kwi","maj","cze","lip","sie","wrz","paź","lis","gru"],"DAY":["niedziela","poniedziałek","wtorek","środa","czwartek","piątek","sobota"],"SHORTDAY":["niedz.","pon.","wt.","śr.","czw.","pt.","sob."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd.MM.yyyy HH:mm","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd.MM.yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"zł"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || n != 1 && (n % 10) == 1 ||      ((n % 10) >= 5 && (n % 10) <= 9 || (n % 100) >= 12 && (n % 100) <= 14) &&      n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"id":"pl"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["stycznia","lutego","marca","kwietnia","maja","czerwca","lipca","sierpnia","września","października","listopada","grudnia"],"SHORTMONTH":["sty","lut","mar","kwi","maj","cze","lip","sie","wrz","paź","lis","gru"],"DAY":["niedziela","poniedziałek","wtorek","środa","czwartek","piątek","sobota"],"SHORTDAY":["niedz.","pon.","wt.","śr.","czw.","pt.","sob."],"AMPMS":["AM","PM"],"medium":"d MMM y HH:mm:ss","short":"dd.MM.yyyy HH:mm","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd.MM.yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"zł"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || n != 1 && (n % 10) == 1 ||      ((n % 10) >= 5 && (n % 10) <= 9 || (n % 100) >= 12 && (n % 100) <= 14) &&      n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"id":"pl"});
+}];
diff --git a/i18n/locale/angular-locale_pt-br.js b/i18n/locale/angular-locale_pt-br.js
index 95251277c4b6..8cdb2a32120a 100644
--- a/i18n/locale/angular-locale_pt-br.js
+++ b/i18n/locale/angular-locale_pt-br.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["janeiro","fevereiro","março","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro"],"SHORTMONTH":["jan","fev","mar","abr","mai","jun","jul","ago","set","out","nov","dez"],"DAY":["domingo","segunda-feira","terça-feira","quarta-feira","quinta-feira","sexta-feira","sábado"],"SHORTDAY":["dom","seg","ter","qua","qui","sex","sáb"],"AMPMS":["AM","PM"],"medium":"dd/MM/yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, d 'de' MMMM 'de' y","longDate":"d 'de' MMMM 'de' y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"R$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"pt-br"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["janeiro","fevereiro","março","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro"],"SHORTMONTH":["jan","fev","mar","abr","mai","jun","jul","ago","set","out","nov","dez"],"DAY":["domingo","segunda-feira","terça-feira","quarta-feira","quinta-feira","sexta-feira","sábado"],"SHORTDAY":["dom","seg","ter","qua","qui","sex","sáb"],"AMPMS":["AM","PM"],"medium":"dd/MM/yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, d 'de' MMMM 'de' y","longDate":"d 'de' MMMM 'de' y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"R$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"pt-br"});
+}];
diff --git a/i18n/locale/angular-locale_pt-pt.js b/i18n/locale/angular-locale_pt-pt.js
index c25b157637fe..da7998dee6dd 100644
--- a/i18n/locale/angular-locale_pt-pt.js
+++ b/i18n/locale/angular-locale_pt-pt.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],"SHORTMONTH":["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],"DAY":["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],"SHORTDAY":["dom","seg","ter","qua","qui","sex","sáb"],"AMPMS":["Antes do meio-dia","Depois do meio-dia"],"medium":"d 'de' MMM 'de' yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, d 'de' MMMM 'de' y","longDate":"d 'de' MMMM 'de' y","mediumDate":"d 'de' MMM 'de' yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"pt-pt"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],"SHORTMONTH":["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],"DAY":["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],"SHORTDAY":["dom","seg","ter","qua","qui","sex","sáb"],"AMPMS":["Antes do meio-dia","Depois do meio-dia"],"medium":"d 'de' MMM 'de' yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, d 'de' MMMM 'de' y","longDate":"d 'de' MMMM 'de' y","mediumDate":"d 'de' MMM 'de' yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"pt-pt"});
+}];
diff --git a/i18n/locale/angular-locale_pt.js b/i18n/locale/angular-locale_pt.js
index 91f8b72bd207..694f2fd56f61 100644
--- a/i18n/locale/angular-locale_pt.js
+++ b/i18n/locale/angular-locale_pt.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["janeiro","fevereiro","março","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro"],"SHORTMONTH":["jan","fev","mar","abr","mai","jun","jul","ago","set","out","nov","dez"],"DAY":["domingo","segunda-feira","terça-feira","quarta-feira","quinta-feira","sexta-feira","sábado"],"SHORTDAY":["dom","seg","ter","qua","qui","sex","sáb"],"AMPMS":["AM","PM"],"medium":"dd/MM/yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, d 'de' MMMM 'de' y","longDate":"d 'de' MMMM 'de' y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"R$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"pt"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["janeiro","fevereiro","março","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro"],"SHORTMONTH":["jan","fev","mar","abr","mai","jun","jul","ago","set","out","nov","dez"],"DAY":["domingo","segunda-feira","terça-feira","quarta-feira","quinta-feira","sexta-feira","sábado"],"SHORTDAY":["dom","seg","ter","qua","qui","sex","sáb"],"AMPMS":["AM","PM"],"medium":"dd/MM/yyyy HH:mm:ss","short":"dd/MM/yy HH:mm","fullDate":"EEEE, d 'de' MMMM 'de' y","longDate":"d 'de' MMMM 'de' y","mediumDate":"dd/MM/yyyy","shortDate":"dd/MM/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"R$"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"pt"});
+}];
diff --git a/i18n/locale/angular-locale_ro-ro.js b/i18n/locale/angular-locale_ro-ro.js
index a0efd994a668..8791966f9d66 100644
--- a/i18n/locale/angular-locale_ro-ro.js
+++ b/i18n/locale/angular-locale_ro-ro.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"L"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 0 || n != 1 && (n % 100) >= 1 &&      (n % 100) <= 19 && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ianuarie","februarie","martie","aprilie","mai","iunie","iulie","august","septembrie","octombrie","noiembrie","decembrie"],"SHORTMONTH":["ian.","feb.","mar.","apr.","mai","iun.","iul.","aug.","sept.","oct.","nov.","dec."],"DAY":["duminică","luni","marți","miercuri","joi","vineri","sâmbătă"],"SHORTDAY":["Du","Lu","Ma","Mi","Jo","Vi","Sâ"],"AMPMS":["AM","PM"],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yyyy HH:mm","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"ro-ro"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"L"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 0 || n != 1 && (n % 100) >= 1 &&      (n % 100) <= 19 && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ianuarie","februarie","martie","aprilie","mai","iunie","iulie","august","septembrie","octombrie","noiembrie","decembrie"],"SHORTMONTH":["ian.","feb.","mar.","apr.","mai","iun.","iul.","aug.","sept.","oct.","nov.","dec."],"DAY":["duminică","luni","marți","miercuri","joi","vineri","sâmbătă"],"SHORTDAY":["Du","Lu","Ma","Mi","Jo","Vi","Sâ"],"AMPMS":["AM","PM"],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yyyy HH:mm","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"ro-ro"});
+}];
diff --git a/i18n/locale/angular-locale_ro.js b/i18n/locale/angular-locale_ro.js
index 77a5b308c2b1..fb1f407df255 100644
--- a/i18n/locale/angular-locale_ro.js
+++ b/i18n/locale/angular-locale_ro.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["ianuarie","februarie","martie","aprilie","mai","iunie","iulie","august","septembrie","octombrie","noiembrie","decembrie"],"SHORTMONTH":["ian.","feb.","mar.","apr.","mai","iun.","iul.","aug.","sept.","oct.","nov.","dec."],"DAY":["duminică","luni","marți","miercuri","joi","vineri","sâmbătă"],"SHORTDAY":["Du","Lu","Ma","Mi","Jo","Vi","Sâ"],"AMPMS":["AM","PM"],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yyyy HH:mm","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"L"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 0 || n != 1 && (n % 100) >= 1 &&      (n % 100) <= 19 && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"id":"ro"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["ianuarie","februarie","martie","aprilie","mai","iunie","iulie","august","septembrie","octombrie","noiembrie","decembrie"],"SHORTMONTH":["ian.","feb.","mar.","apr.","mai","iun.","iul.","aug.","sept.","oct.","nov.","dec."],"DAY":["duminică","luni","marți","miercuri","joi","vineri","sâmbătă"],"SHORTDAY":["Du","Lu","Ma","Mi","Jo","Vi","Sâ"],"AMPMS":["AM","PM"],"medium":"dd.MM.yyyy HH:mm:ss","short":"dd.MM.yyyy HH:mm","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"L"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 0 || n != 1 && (n % 100) >= 1 &&      (n % 100) <= 19 && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"id":"ro"});
+}];
diff --git a/i18n/locale/angular-locale_ru-ru.js b/i18n/locale/angular-locale_ru-ru.js
index 6bc87cddabb8..2f393a08bb30 100644
--- a/i18n/locale/angular-locale_ru-ru.js
+++ b/i18n/locale/angular-locale_ru-ru.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"руб"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря"],"SHORTMONTH":["янв.","февр.","марта","апр.","мая","июня","июля","авг.","сент.","окт.","нояб.","дек."],"DAY":["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"],"SHORTDAY":["вс","пн","вт","ср","чт","пт","сб"],"AMPMS":["AM","PM"],"medium":"dd.MM.yyyy H:mm:ss","short":"dd.MM.yy H:mm","fullDate":"EEEE, d MMMM y 'г'.","longDate":"d MMMM y 'г'.","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"ru-ru"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"руб"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря"],"SHORTMONTH":["янв.","февр.","марта","апр.","мая","июня","июля","авг.","сент.","окт.","нояб.","дек."],"DAY":["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"],"SHORTDAY":["вс","пн","вт","ср","чт","пт","сб"],"AMPMS":["AM","PM"],"medium":"dd.MM.yyyy H:mm:ss","short":"dd.MM.yy H:mm","fullDate":"EEEE, d MMMM y 'г'.","longDate":"d MMMM y 'г'.","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"ru-ru"});
+}];
diff --git a/i18n/locale/angular-locale_ru.js b/i18n/locale/angular-locale_ru.js
index 48004687a9ad..b86434b1b1fc 100644
--- a/i18n/locale/angular-locale_ru.js
+++ b/i18n/locale/angular-locale_ru.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря"],"SHORTMONTH":["янв.","февр.","марта","апр.","мая","июня","июля","авг.","сент.","окт.","нояб.","дек."],"DAY":["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"],"SHORTDAY":["вс","пн","вт","ср","чт","пт","сб"],"AMPMS":["AM","PM"],"medium":"dd.MM.yyyy H:mm:ss","short":"dd.MM.yy H:mm","fullDate":"EEEE, d MMMM y 'г'.","longDate":"d MMMM y 'г'.","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"руб"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"id":"ru"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря"],"SHORTMONTH":["янв.","февр.","марта","апр.","мая","июня","июля","авг.","сент.","окт.","нояб.","дек."],"DAY":["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"],"SHORTDAY":["вс","пн","вт","ср","чт","пт","сб"],"AMPMS":["AM","PM"],"medium":"dd.MM.yyyy H:mm:ss","short":"dd.MM.yy H:mm","fullDate":"EEEE, d MMMM y 'г'.","longDate":"d MMMM y 'г'.","mediumDate":"dd.MM.yyyy","shortDate":"dd.MM.yy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"руб"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"id":"ru"});
+}];
diff --git a/i18n/locale/angular-locale_sk-sk.js b/i18n/locale/angular-locale_sk-sk.js
index 8fc5a6380f26..c55b576e24c5 100644
--- a/i18n/locale/angular-locale_sk-sk.js
+++ b/i18n/locale/angular-locale_sk-sk.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Sk"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 2 || n == 3 || n == 4) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["januára","februára","marca","apríla","mája","júna","júla","augusta","septembra","októbra","novembra","decembra"],"SHORTMONTH":["jan","feb","mar","apr","máj","jún","júl","aug","sep","okt","nov","dec"],"DAY":["nedeľa","pondelok","utorok","streda","štvrtok","piatok","sobota"],"SHORTDAY":["ne","po","ut","st","št","pi","so"],"AMPMS":["dopoludnia","popoludní"],"medium":"d.M.yyyy H:mm:ss","short":"d.M.yyyy H:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yyyy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"sk-sk"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Sk"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 2 || n == 3 || n == 4) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["januára","februára","marca","apríla","mája","júna","júla","augusta","septembra","októbra","novembra","decembra"],"SHORTMONTH":["jan","feb","mar","apr","máj","jún","júl","aug","sep","okt","nov","dec"],"DAY":["nedeľa","pondelok","utorok","streda","štvrtok","piatok","sobota"],"SHORTDAY":["ne","po","ut","st","št","pi","so"],"AMPMS":["dopoludnia","popoludní"],"medium":"d.M.yyyy H:mm:ss","short":"d.M.yyyy H:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yyyy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"sk-sk"});
+}];
diff --git a/i18n/locale/angular-locale_sk.js b/i18n/locale/angular-locale_sk.js
index 4ba8e06df60f..ef94ef92efe3 100644
--- a/i18n/locale/angular-locale_sk.js
+++ b/i18n/locale/angular-locale_sk.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["januára","februára","marca","apríla","mája","júna","júla","augusta","septembra","októbra","novembra","decembra"],"SHORTMONTH":["jan","feb","mar","apr","máj","jún","júl","aug","sep","okt","nov","dec"],"DAY":["nedeľa","pondelok","utorok","streda","štvrtok","piatok","sobota"],"SHORTDAY":["ne","po","ut","st","št","pi","so"],"AMPMS":["dopoludnia","popoludní"],"medium":"d.M.yyyy H:mm:ss","short":"d.M.yyyy H:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yyyy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Sk"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 2 || n == 3 || n == 4) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"id":"sk"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["januára","februára","marca","apríla","mája","júna","júla","augusta","septembra","októbra","novembra","decembra"],"SHORTMONTH":["jan","feb","mar","apr","máj","jún","júl","aug","sep","okt","nov","dec"],"DAY":["nedeľa","pondelok","utorok","streda","štvrtok","piatok","sobota"],"SHORTDAY":["ne","po","ut","st","št","pi","so"],"AMPMS":["dopoludnia","popoludní"],"medium":"d.M.yyyy H:mm:ss","short":"d.M.yyyy H:mm","fullDate":"EEEE, d. MMMM y","longDate":"d. MMMM y","mediumDate":"d.M.yyyy","shortDate":"d.M.yyyy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Sk"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  if (n == 2 || n == 3 || n == 4) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"id":"sk"});
+}];
diff --git a/i18n/locale/angular-locale_sl-si.js b/i18n/locale/angular-locale_sl-si.js
index a785cfc8fc6d..b18e90a5d825 100644
--- a/i18n/locale/angular-locale_sl-si.js
+++ b/i18n/locale/angular-locale_sl-si.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if ((n % 100) == 1) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 100) == 2) {    return PLURAL_CATEGORY.TWO;  }  if ((n % 100) == 3 || (n % 100) == 4) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["januar","februar","marec","april","maj","junij","julij","avgust","september","oktober","november","december"],"SHORTMONTH":["jan.","feb.","mar.","apr.","maj","jun.","jul.","avg.","sep.","okt.","nov.","dec."],"DAY":["nedelja","ponedeljek","torek","sreda","četrtek","petek","sobota"],"SHORTDAY":["ned","pon","tor","sre","čet","pet","sob"],"AMPMS":["dop.","pop."],"medium":"d. MMM yyyy HH:mm:ss","short":"d. MM. yy HH:mm","fullDate":"EEEE, dd. MMMM y","longDate":"dd. MMMM y","mediumDate":"d. MMM yyyy","shortDate":"d. MM. yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"sl-si"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if ((n % 100) == 1) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 100) == 2) {    return PLURAL_CATEGORY.TWO;  }  if ((n % 100) == 3 || (n % 100) == 4) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["januar","februar","marec","april","maj","junij","julij","avgust","september","oktober","november","december"],"SHORTMONTH":["jan.","feb.","mar.","apr.","maj","jun.","jul.","avg.","sep.","okt.","nov.","dec."],"DAY":["nedelja","ponedeljek","torek","sreda","četrtek","petek","sobota"],"SHORTDAY":["ned","pon","tor","sre","čet","pet","sob"],"AMPMS":["dop.","pop."],"medium":"d. MMM yyyy HH:mm:ss","short":"d. MM. yy HH:mm","fullDate":"EEEE, dd. MMMM y","longDate":"dd. MMMM y","mediumDate":"d. MMM yyyy","shortDate":"d. MM. yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"sl-si"});
+}];
diff --git a/i18n/locale/angular-locale_sl.js b/i18n/locale/angular-locale_sl.js
index 5c1718eebcdd..b1406c1b2b88 100644
--- a/i18n/locale/angular-locale_sl.js
+++ b/i18n/locale/angular-locale_sl.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["januar","februar","marec","april","maj","junij","julij","avgust","september","oktober","november","december"],"SHORTMONTH":["jan.","feb.","mar.","apr.","maj","jun.","jul.","avg.","sep.","okt.","nov.","dec."],"DAY":["nedelja","ponedeljek","torek","sreda","četrtek","petek","sobota"],"SHORTDAY":["ned","pon","tor","sre","čet","pet","sob"],"AMPMS":["dop.","pop."],"medium":"d. MMM yyyy HH:mm:ss","short":"d. MM. yy HH:mm","fullDate":"EEEE, dd. MMMM y","longDate":"dd. MMMM y","mediumDate":"d. MMM yyyy","shortDate":"d. MM. yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if ((n % 100) == 1) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 100) == 2) {    return PLURAL_CATEGORY.TWO;  }  if ((n % 100) == 3 || (n % 100) == 4) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"id":"sl"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["januar","februar","marec","april","maj","junij","julij","avgust","september","oktober","november","december"],"SHORTMONTH":["jan.","feb.","mar.","apr.","maj","jun.","jul.","avg.","sep.","okt.","nov.","dec."],"DAY":["nedelja","ponedeljek","torek","sreda","četrtek","petek","sobota"],"SHORTDAY":["ned","pon","tor","sre","čet","pet","sob"],"AMPMS":["dop.","pop."],"medium":"d. MMM yyyy HH:mm:ss","short":"d. MM. yy HH:mm","fullDate":"EEEE, dd. MMMM y","longDate":"dd. MMMM y","mediumDate":"d. MMM yyyy","shortDate":"d. MM. yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"€"},"pluralCat":function (n) {  if ((n % 100) == 1) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 100) == 2) {    return PLURAL_CATEGORY.TWO;  }  if ((n % 100) == 3 || (n % 100) == 4) {    return PLURAL_CATEGORY.FEW;  }  return PLURAL_CATEGORY.OTHER;},"id":"sl"});
+}];
diff --git a/i18n/locale/angular-locale_sq-al.js b/i18n/locale/angular-locale_sq-al.js
index 1403556eba25..0f767e56d963 100644
--- a/i18n/locale/angular-locale_sq-al.js
+++ b/i18n/locale/angular-locale_sq-al.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Lek"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janar","shkurt","mars","prill","maj","qershor","korrik","gusht","shtator","tetor","nëntor","dhjetor"],"SHORTMONTH":["Jan","Shk","Mar","Pri","Maj","Qer","Kor","Gsh","Sht","Tet","Nën","Dhj"],"DAY":["e diel","e hënë","e martë","e mërkurë","e enjte","e premte","e shtunë"],"SHORTDAY":["Die","Hën","Mar","Mër","Enj","Pre","Sht"],"AMPMS":["PD","MD"],"medium":"yyyy-MM-dd h.mm.ss.a","short":"yy-MM-dd h.mm.a","fullDate":"EEEE, dd MMMM y","longDate":"dd MMMM y","mediumDate":"yyyy-MM-dd","shortDate":"yy-MM-dd","mediumTime":"h.mm.ss.a","shortTime":"h.mm.a"},"id":"sq-al"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Lek"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["janar","shkurt","mars","prill","maj","qershor","korrik","gusht","shtator","tetor","nëntor","dhjetor"],"SHORTMONTH":["Jan","Shk","Mar","Pri","Maj","Qer","Kor","Gsh","Sht","Tet","Nën","Dhj"],"DAY":["e diel","e hënë","e martë","e mërkurë","e enjte","e premte","e shtunë"],"SHORTDAY":["Die","Hën","Mar","Mër","Enj","Pre","Sht"],"AMPMS":["PD","MD"],"medium":"yyyy-MM-dd h.mm.ss.a","short":"yy-MM-dd h.mm.a","fullDate":"EEEE, dd MMMM y","longDate":"dd MMMM y","mediumDate":"yyyy-MM-dd","shortDate":"yy-MM-dd","mediumTime":"h.mm.ss.a","shortTime":"h.mm.a"},"id":"sq-al"});
+}];
diff --git a/i18n/locale/angular-locale_sq.js b/i18n/locale/angular-locale_sq.js
index 572e375ee5a1..ba948c29815a 100644
--- a/i18n/locale/angular-locale_sq.js
+++ b/i18n/locale/angular-locale_sq.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["janar","shkurt","mars","prill","maj","qershor","korrik","gusht","shtator","tetor","nëntor","dhjetor"],"SHORTMONTH":["Jan","Shk","Mar","Pri","Maj","Qer","Kor","Gsh","Sht","Tet","Nën","Dhj"],"DAY":["e diel","e hënë","e martë","e mërkurë","e enjte","e premte","e shtunë"],"SHORTDAY":["Die","Hën","Mar","Mër","Enj","Pre","Sht"],"AMPMS":["PD","MD"],"medium":"yyyy-MM-dd h.mm.ss.a","short":"yy-MM-dd h.mm.a","fullDate":"EEEE, dd MMMM y","longDate":"dd MMMM y","mediumDate":"yyyy-MM-dd","shortDate":"yy-MM-dd","mediumTime":"h.mm.ss.a","shortTime":"h.mm.a"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Lek"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"sq"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["janar","shkurt","mars","prill","maj","qershor","korrik","gusht","shtator","tetor","nëntor","dhjetor"],"SHORTMONTH":["Jan","Shk","Mar","Pri","Maj","Qer","Kor","Gsh","Sht","Tet","Nën","Dhj"],"DAY":["e diel","e hënë","e martë","e mërkurë","e enjte","e premte","e shtunë"],"SHORTDAY":["Die","Hën","Mar","Mër","Enj","Pre","Sht"],"AMPMS":["PD","MD"],"medium":"yyyy-MM-dd h.mm.ss.a","short":"yy-MM-dd h.mm.a","fullDate":"EEEE, dd MMMM y","longDate":"dd MMMM y","mediumDate":"yyyy-MM-dd","shortDate":"yy-MM-dd","mediumTime":"h.mm.ss.a","shortTime":"h.mm.a"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Lek"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"sq"});
+}];
diff --git a/i18n/locale/angular-locale_sr-cyrl-rs.js b/i18n/locale/angular-locale_sr-cyrl-rs.js
index b5af27d3b76a..e76a6e5da80f 100644
--- a/i18n/locale/angular-locale_sr-cyrl-rs.js
+++ b/i18n/locale/angular-locale_sr-cyrl-rs.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"РСД"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["јануар","фебруар","март","април","мај","јун","јул","август","септембар","октобар","новембар","децембар"],"SHORTMONTH":["јан","феб","мар","апр","мај","јун","јул","авг","сеп","окт","нов","дец"],"DAY":["недеља","понедељак","уторак","среда","четвртак","петак","субота"],"SHORTDAY":["нед","пон","уто","сре","чет","пет","суб"],"AMPMS":["пре подне","поподне"],"medium":"dd.MM.y. HH.mm.ss","short":"d.M.yy. HH.mm","fullDate":"EEEE, dd. MMMM y.","longDate":"dd. MMMM y.","mediumDate":"dd.MM.y.","shortDate":"d.M.yy.","mediumTime":"HH.mm.ss","shortTime":"HH.mm"},"id":"sr-cyrl-rs"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"РСД"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["јануар","фебруар","март","април","мај","јун","јул","август","септембар","октобар","новембар","децембар"],"SHORTMONTH":["јан","феб","мар","апр","мај","јун","јул","авг","сеп","окт","нов","дец"],"DAY":["недеља","понедељак","уторак","среда","четвртак","петак","субота"],"SHORTDAY":["нед","пон","уто","сре","чет","пет","суб"],"AMPMS":["пре подне","поподне"],"medium":"dd.MM.y. HH.mm.ss","short":"d.M.yy. HH.mm","fullDate":"EEEE, dd. MMMM y.","longDate":"dd. MMMM y.","mediumDate":"dd.MM.y.","shortDate":"d.M.yy.","mediumTime":"HH.mm.ss","shortTime":"HH.mm"},"id":"sr-cyrl-rs"});
+}];
diff --git a/i18n/locale/angular-locale_sr-latn-rs.js b/i18n/locale/angular-locale_sr-latn-rs.js
index 150addd6f656..3a0dc9e7cc5f 100644
--- a/i18n/locale/angular-locale_sr-latn-rs.js
+++ b/i18n/locale/angular-locale_sr-latn-rs.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"РСД"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["јануар","фебруар","март","април","мај","јун","јул","август","септембар","октобар","новембар","децембар"],"SHORTMONTH":["јан","феб","мар","апр","мај","јун","јул","авг","сеп","окт","нов","дец"],"DAY":["недеља","понедељак","уторак","среда","четвртак","петак","субота"],"SHORTDAY":["нед","пон","уто","сре","чет","пет","суб"],"AMPMS":["пре подне","поподне"],"medium":"dd.MM.y. HH.mm.ss","short":"d.M.yy. HH.mm","fullDate":"EEEE, dd. MMMM y.","longDate":"dd. MMMM y.","mediumDate":"dd.MM.y.","shortDate":"d.M.yy.","mediumTime":"HH.mm.ss","shortTime":"HH.mm"},"id":"sr-latn-rs"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"РСД"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["јануар","фебруар","март","април","мај","јун","јул","август","септембар","октобар","новембар","децембар"],"SHORTMONTH":["јан","феб","мар","апр","мај","јун","јул","авг","сеп","окт","нов","дец"],"DAY":["недеља","понедељак","уторак","среда","четвртак","петак","субота"],"SHORTDAY":["нед","пон","уто","сре","чет","пет","суб"],"AMPMS":["пре подне","поподне"],"medium":"dd.MM.y. HH.mm.ss","short":"d.M.yy. HH.mm","fullDate":"EEEE, dd. MMMM y.","longDate":"dd. MMMM y.","mediumDate":"dd.MM.y.","shortDate":"d.M.yy.","mediumTime":"HH.mm.ss","shortTime":"HH.mm"},"id":"sr-latn-rs"});
+}];
diff --git a/i18n/locale/angular-locale_sr-rs.js b/i18n/locale/angular-locale_sr-rs.js
index 5d971a63245d..c9b973f2540e 100644
--- a/i18n/locale/angular-locale_sr-rs.js
+++ b/i18n/locale/angular-locale_sr-rs.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"РСД"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["јануар","фебруар","март","април","мај","јун","јул","август","септембар","октобар","новембар","децембар"],"SHORTMONTH":["јан","феб","мар","апр","мај","јун","јул","авг","сеп","окт","нов","дец"],"DAY":["недеља","понедељак","уторак","среда","четвртак","петак","субота"],"SHORTDAY":["нед","пон","уто","сре","чет","пет","суб"],"AMPMS":["пре подне","поподне"],"medium":"dd.MM.y. HH.mm.ss","short":"d.M.yy. HH.mm","fullDate":"EEEE, dd. MMMM y.","longDate":"dd. MMMM y.","mediumDate":"dd.MM.y.","shortDate":"d.M.yy.","mediumTime":"HH.mm.ss","shortTime":"HH.mm"},"id":"sr-rs"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"РСД"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["јануар","фебруар","март","април","мај","јун","јул","август","септембар","октобар","новембар","децембар"],"SHORTMONTH":["јан","феб","мар","апр","мај","јун","јул","авг","сеп","окт","нов","дец"],"DAY":["недеља","понедељак","уторак","среда","четвртак","петак","субота"],"SHORTDAY":["нед","пон","уто","сре","чет","пет","суб"],"AMPMS":["пре подне","поподне"],"medium":"dd.MM.y. HH.mm.ss","short":"d.M.yy. HH.mm","fullDate":"EEEE, dd. MMMM y.","longDate":"dd. MMMM y.","mediumDate":"dd.MM.y.","shortDate":"d.M.yy.","mediumTime":"HH.mm.ss","shortTime":"HH.mm"},"id":"sr-rs"});
+}];
diff --git a/i18n/locale/angular-locale_sr.js b/i18n/locale/angular-locale_sr.js
index 61af901d5d71..61045a4488c5 100644
--- a/i18n/locale/angular-locale_sr.js
+++ b/i18n/locale/angular-locale_sr.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["јануар","фебруар","март","април","мај","јун","јул","август","септембар","октобар","новембар","децембар"],"SHORTMONTH":["јан","феб","мар","апр","мај","јун","јул","авг","сеп","окт","нов","дец"],"DAY":["недеља","понедељак","уторак","среда","четвртак","петак","субота"],"SHORTDAY":["нед","пон","уто","сре","чет","пет","суб"],"AMPMS":["пре подне","поподне"],"medium":"dd.MM.y. HH.mm.ss","short":"d.M.yy. HH.mm","fullDate":"EEEE, dd. MMMM y.","longDate":"dd. MMMM y.","mediumDate":"dd.MM.y.","shortDate":"d.M.yy.","mediumTime":"HH.mm.ss","shortTime":"HH.mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"РСД"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"id":"sr"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["јануар","фебруар","март","април","мај","јун","јул","август","септембар","октобар","новембар","децембар"],"SHORTMONTH":["јан","феб","мар","апр","мај","јун","јул","авг","сеп","окт","нов","дец"],"DAY":["недеља","понедељак","уторак","среда","четвртак","петак","субота"],"SHORTDAY":["нед","пон","уто","сре","чет","пет","суб"],"AMPMS":["пре подне","поподне"],"medium":"dd.MM.y. HH.mm.ss","short":"d.M.yy. HH.mm","fullDate":"EEEE, dd. MMMM y.","longDate":"dd. MMMM y.","mediumDate":"dd.MM.y.","shortDate":"d.M.yy.","mediumTime":"HH.mm.ss","shortTime":"HH.mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"РСД"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"id":"sr"});
+}];
diff --git a/i18n/locale/angular-locale_sv-se.js b/i18n/locale/angular-locale_sv-se.js
index 4ce275197045..9c0976d6853c 100644
--- a/i18n/locale/angular-locale_sv-se.js
+++ b/i18n/locale/angular-locale_sv-se.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kr"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],"SHORTMONTH":["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],"DAY":["söndag","måndag","tisdag","onsdag","torsdag","fredag","lördag"],"SHORTDAY":["sön","mån","tis","ons","tors","fre","lör"],"AMPMS":["fm","em"],"medium":"d MMM y HH:mm:ss","short":"yyyy-MM-dd HH:mm","fullDate":"EEEE'en' 'den' d:'e' MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"yyyy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"sv-se"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kr"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],"SHORTMONTH":["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],"DAY":["söndag","måndag","tisdag","onsdag","torsdag","fredag","lördag"],"SHORTDAY":["sön","mån","tis","ons","tors","fre","lör"],"AMPMS":["fm","em"],"medium":"d MMM y HH:mm:ss","short":"yyyy-MM-dd HH:mm","fullDate":"EEEE'en' 'den' d:'e' MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"yyyy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"sv-se"});
+}];
diff --git a/i18n/locale/angular-locale_sv.js b/i18n/locale/angular-locale_sv.js
index 0dfa534c6180..4f83a7697981 100644
--- a/i18n/locale/angular-locale_sv.js
+++ b/i18n/locale/angular-locale_sv.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],"SHORTMONTH":["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],"DAY":["söndag","måndag","tisdag","onsdag","torsdag","fredag","lördag"],"SHORTDAY":["sön","mån","tis","ons","tors","fre","lör"],"AMPMS":["fm","em"],"medium":"d MMM y HH:mm:ss","short":"yyyy-MM-dd HH:mm","fullDate":"EEEE'en' 'den' d:'e' MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"yyyy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kr"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"sv"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],"SHORTMONTH":["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],"DAY":["söndag","måndag","tisdag","onsdag","torsdag","fredag","lördag"],"SHORTDAY":["sön","mån","tis","ons","tors","fre","lör"],"AMPMS":["fm","em"],"medium":"d MMM y HH:mm:ss","short":"yyyy-MM-dd HH:mm","fullDate":"EEEE'en' 'den' d:'e' MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"yyyy-MM-dd","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"kr"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"sv"});
+}];
diff --git a/i18n/locale/angular-locale_sw-tz.js b/i18n/locale/angular-locale_sw-tz.js
index 87d9ac5514e5..e18620cec973 100644
--- a/i18n/locale/angular-locale_sw-tz.js
+++ b/i18n/locale/angular-locale_sw-tz.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"TZS"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Januari","Februari","Machi","Aprili","Mei","Juni","Julai","Agosti","Septemba","Oktoba","Novemba","Desemba"],"SHORTMONTH":["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ago","Sep","Okt","Nov","Des"],"DAY":["Jumapili","Jumatatu","Jumanne","Jumatano","Alhamisi","Ijumaa","Jumamosi"],"SHORTDAY":["J2","J3","J4","J5","Alh","Ij","J1"],"AMPMS":["asubuhi","alasiri"],"medium":"d MMM y h:mm:ss a","short":"dd/MM/yyyy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yyyy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"sw-tz"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"TZS"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Januari","Februari","Machi","Aprili","Mei","Juni","Julai","Agosti","Septemba","Oktoba","Novemba","Desemba"],"SHORTMONTH":["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ago","Sep","Okt","Nov","Des"],"DAY":["Jumapili","Jumatatu","Jumanne","Jumatano","Alhamisi","Ijumaa","Jumamosi"],"SHORTDAY":["J2","J3","J4","J5","Alh","Ij","J1"],"AMPMS":["asubuhi","alasiri"],"medium":"d MMM y h:mm:ss a","short":"dd/MM/yyyy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yyyy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"sw-tz"});
+}];
diff --git a/i18n/locale/angular-locale_sw.js b/i18n/locale/angular-locale_sw.js
index 832f06bfdd42..356b131ae9c4 100644
--- a/i18n/locale/angular-locale_sw.js
+++ b/i18n/locale/angular-locale_sw.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Januari","Februari","Machi","Aprili","Mei","Juni","Julai","Agosti","Septemba","Oktoba","Novemba","Desemba"],"SHORTMONTH":["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ago","Sep","Okt","Nov","Des"],"DAY":["Jumapili","Jumatatu","Jumanne","Jumatano","Alhamisi","Ijumaa","Jumamosi"],"SHORTDAY":["J2","J3","J4","J5","Alh","Ij","J1"],"AMPMS":["asubuhi","alasiri"],"medium":"d MMM y h:mm:ss a","short":"dd/MM/yyyy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yyyy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"TZS"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"sw"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Januari","Februari","Machi","Aprili","Mei","Juni","Julai","Agosti","Septemba","Oktoba","Novemba","Desemba"],"SHORTMONTH":["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ago","Sep","Okt","Nov","Des"],"DAY":["Jumapili","Jumatatu","Jumanne","Jumatano","Alhamisi","Ijumaa","Jumamosi"],"SHORTDAY":["J2","J3","J4","J5","Alh","Ij","J1"],"AMPMS":["asubuhi","alasiri"],"medium":"d MMM y h:mm:ss a","short":"dd/MM/yyyy h:mm a","fullDate":"EEEE, d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd/MM/yyyy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"TZS"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"sw"});
+}];
diff --git a/i18n/locale/angular-locale_ta-in.js b/i18n/locale/angular-locale_ta-in.js
index 0055058a9dfe..300e8601b623 100644
--- a/i18n/locale/angular-locale_ta-in.js
+++ b/i18n/locale/angular-locale_ta-in.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ஜனவரி","பிப்ரவரி","மார்ச்","ஏப்ரல்","மே","ஜூன்","ஜூலை","ஆகஸ்ட்","செப்டெம்ப்ர்","அக்டோபர்","நவம்பர்","டிசம்பர்"],"SHORTMONTH":["ஜன.","பிப்.","மார்.","ஏப்.","மே","ஜூன்","ஜூலை","ஆக.","செப்.","அக்.","நவ.","டிச."],"DAY":["ஞாயிறு","திங்கள்","செவ்வாய்","புதன்","வியாழன்","வெள்ளி","சனி"],"SHORTDAY":["ஞா","தி","செ","பு","வி","வெ","ச"],"AMPMS":["am","pm"],"medium":"d MMM, y h:mm:ss a","short":"d-M-yy h:mm a","fullDate":"EEEE, d MMMM, y","longDate":"d MMMM, y","mediumDate":"d MMM, y","shortDate":"d-M-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"ta-in"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["ஜனவரி","பிப்ரவரி","மார்ச்","ஏப்ரல்","மே","ஜூன்","ஜூலை","ஆகஸ்ட்","செப்டெம்ப்ர்","அக்டோபர்","நவம்பர்","டிசம்பர்"],"SHORTMONTH":["ஜன.","பிப்.","மார்.","ஏப்.","மே","ஜூன்","ஜூலை","ஆக.","செப்.","அக்.","நவ.","டிச."],"DAY":["ஞாயிறு","திங்கள்","செவ்வாய்","புதன்","வியாழன்","வெள்ளி","சனி"],"SHORTDAY":["ஞா","தி","செ","பு","வி","வெ","ச"],"AMPMS":["am","pm"],"medium":"d MMM, y h:mm:ss a","short":"d-M-yy h:mm a","fullDate":"EEEE, d MMMM, y","longDate":"d MMMM, y","mediumDate":"d MMM, y","shortDate":"d-M-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"ta-in"});
+}];
diff --git a/i18n/locale/angular-locale_ta.js b/i18n/locale/angular-locale_ta.js
index 0d83fb8c35ff..3c9b16862528 100644
--- a/i18n/locale/angular-locale_ta.js
+++ b/i18n/locale/angular-locale_ta.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["ஜனவரி","பிப்ரவரி","மார்ச்","ஏப்ரல்","மே","ஜூன்","ஜூலை","ஆகஸ்ட்","செப்டெம்ப்ர்","அக்டோபர்","நவம்பர்","டிசம்பர்"],"SHORTMONTH":["ஜன.","பிப்.","மார்.","ஏப்.","மே","ஜூன்","ஜூலை","ஆக.","செப்.","அக்.","நவ.","டிச."],"DAY":["ஞாயிறு","திங்கள்","செவ்வாய்","புதன்","வியாழன்","வெள்ளி","சனி"],"SHORTDAY":["ஞா","தி","செ","பு","வி","வெ","ச"],"AMPMS":["am","pm"],"medium":"d MMM, y h:mm:ss a","short":"d-M-yy h:mm a","fullDate":"EEEE, d MMMM, y","longDate":"d MMMM, y","mediumDate":"d MMM, y","shortDate":"d-M-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"ta"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["ஜனவரி","பிப்ரவரி","மார்ச்","ஏப்ரல்","மே","ஜூன்","ஜூலை","ஆகஸ்ட்","செப்டெம்ப்ர்","அக்டோபர்","நவம்பர்","டிசம்பர்"],"SHORTMONTH":["ஜன.","பிப்.","மார்.","ஏப்.","மே","ஜூன்","ஜூலை","ஆக.","செப்.","அக்.","நவ.","டிச."],"DAY":["ஞாயிறு","திங்கள்","செவ்வாய்","புதன்","வியாழன்","வெள்ளி","சனி"],"SHORTDAY":["ஞா","தி","செ","பு","வி","வெ","ச"],"AMPMS":["am","pm"],"medium":"d MMM, y h:mm:ss a","short":"d-M-yy h:mm a","fullDate":"EEEE, d MMMM, y","longDate":"d MMMM, y","mediumDate":"d MMM, y","shortDate":"d-M-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"ta"});
+}];
diff --git a/i18n/locale/angular-locale_te-in.js b/i18n/locale/angular-locale_te-in.js
index d851dd89b0ef..78383bed72c4 100644
--- a/i18n/locale/angular-locale_te-in.js
+++ b/i18n/locale/angular-locale_te-in.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["జనవరి","ఫిబ్రవరి","మార్చి","ఏప్రిల్","మే","జూన్","జూలై","ఆగస్టు","సెప్టెంబర్","అక్టోబర్","నవంబర్","డిసెంబర్"],"SHORTMONTH":["జనవరి","ఫిబ్రవరి","మార్చి","ఏప్రిల్","మే","జూన్","జూలై","ఆగస్టు","సెప్టెంబర్","అక్టోబర్","నవంబర్","డిసెంబర్"],"DAY":["ఆదివారం","సోమవారం","మంగళవారం","బుధవారం","గురువారం","శుక్రవారం","శనివారం"],"SHORTDAY":["ఆది","సోమ","మంగళ","బుధ","గురు","శుక్ర","శని"],"AMPMS":["ఉ","సా"],"medium":"d MMM y h:mm:ss a","short":"dd-MM-yy h:mm a","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd-MM-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"te-in"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["జనవరి","ఫిబ్రవరి","మార్చి","ఏప్రిల్","మే","జూన్","జూలై","ఆగస్టు","సెప్టెంబర్","అక్టోబర్","నవంబర్","డిసెంబర్"],"SHORTMONTH":["జనవరి","ఫిబ్రవరి","మార్చి","ఏప్రిల్","మే","జూన్","జూలై","ఆగస్టు","సెప్టెంబర్","అక్టోబర్","నవంబర్","డిసెంబర్"],"DAY":["ఆదివారం","సోమవారం","మంగళవారం","బుధవారం","గురువారం","శుక్రవారం","శనివారం"],"SHORTDAY":["ఆది","సోమ","మంగళ","బుధ","గురు","శుక్ర","శని"],"AMPMS":["ఉ","సా"],"medium":"d MMM y h:mm:ss a","short":"dd-MM-yy h:mm a","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd-MM-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"te-in"});
+}];
diff --git a/i18n/locale/angular-locale_te.js b/i18n/locale/angular-locale_te.js
index 3c4ded554249..a64b5bd17133 100644
--- a/i18n/locale/angular-locale_te.js
+++ b/i18n/locale/angular-locale_te.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["జనవరి","ఫిబ్రవరి","మార్చి","ఏప్రిల్","మే","జూన్","జూలై","ఆగస్టు","సెప్టెంబర్","అక్టోబర్","నవంబర్","డిసెంబర్"],"SHORTMONTH":["జనవరి","ఫిబ్రవరి","మార్చి","ఏప్రిల్","మే","జూన్","జూలై","ఆగస్టు","సెప్టెంబర్","అక్టోబర్","నవంబర్","డిసెంబర్"],"DAY":["ఆదివారం","సోమవారం","మంగళవారం","బుధవారం","గురువారం","శుక్రవారం","శనివారం"],"SHORTDAY":["ఆది","సోమ","మంగళ","బుధ","గురు","శుక్ర","శని"],"AMPMS":["ఉ","సా"],"medium":"d MMM y h:mm:ss a","short":"dd-MM-yy h:mm a","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd-MM-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"te"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["జనవరి","ఫిబ్రవరి","మార్చి","ఏప్రిల్","మే","జూన్","జూలై","ఆగస్టు","సెప్టెంబర్","అక్టోబర్","నవంబర్","డిసెంబర్"],"SHORTMONTH":["జనవరి","ఫిబ్రవరి","మార్చి","ఏప్రిల్","మే","జూన్","జూలై","ఆగస్టు","సెప్టెంబర్","అక్టోబర్","నవంబర్","డిసెంబర్"],"DAY":["ఆదివారం","సోమవారం","మంగళవారం","బుధవారం","గురువారం","శుక్రవారం","శనివారం"],"SHORTDAY":["ఆది","సోమ","మంగళ","బుధ","గురు","శుక్ర","శని"],"AMPMS":["ఉ","సా"],"medium":"d MMM y h:mm:ss a","short":"dd-MM-yy h:mm a","fullDate":"EEEE d MMMM y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"dd-MM-yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":2,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":2,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs"},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"te"});
+}];
diff --git a/i18n/locale/angular-locale_th-th.js b/i18n/locale/angular-locale_th-th.js
index 9d5284f7eba0..858aa1195a32 100644
--- a/i18n/locale/angular-locale_th-th.js
+++ b/i18n/locale/angular-locale_th-th.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"฿"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],"SHORTMONTH":["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],"DAY":["วันอาทิตย์","วันจันทร์","วันอังคาร","วันพุธ","วันพฤหัสบดี","วันศุกร์","วันเสาร์"],"SHORTDAY":["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],"AMPMS":["ก่อนเที่ยง","หลังเที่ยง"],"medium":"d MMM y H:mm:ss","short":"d/M/yyyy H:mm","fullDate":"EEEEที่ d MMMM G y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d/M/yyyy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"th-th"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"฿"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],"SHORTMONTH":["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],"DAY":["วันอาทิตย์","วันจันทร์","วันอังคาร","วันพุธ","วันพฤหัสบดี","วันศุกร์","วันเสาร์"],"SHORTDAY":["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],"AMPMS":["ก่อนเที่ยง","หลังเที่ยง"],"medium":"d MMM y H:mm:ss","short":"d/M/yyyy H:mm","fullDate":"EEEEที่ d MMMM G y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d/M/yyyy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"id":"th-th"});
+}];
diff --git a/i18n/locale/angular-locale_th.js b/i18n/locale/angular-locale_th.js
index e675cdfa41d1..7ab6dc53c861 100644
--- a/i18n/locale/angular-locale_th.js
+++ b/i18n/locale/angular-locale_th.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],"SHORTMONTH":["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],"DAY":["วันอาทิตย์","วันจันทร์","วันอังคาร","วันพุธ","วันพฤหัสบดี","วันศุกร์","วันเสาร์"],"SHORTDAY":["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],"AMPMS":["ก่อนเที่ยง","หลังเที่ยง"],"medium":"d MMM y H:mm:ss","short":"d/M/yyyy H:mm","fullDate":"EEEEที่ d MMMM G y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d/M/yyyy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"฿"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"th"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],"SHORTMONTH":["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],"DAY":["วันอาทิตย์","วันจันทร์","วันอังคาร","วันพุธ","วันพฤหัสบดี","วันศุกร์","วันเสาร์"],"SHORTDAY":["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],"AMPMS":["ก่อนเที่ยง","หลังเที่ยง"],"medium":"d MMM y H:mm:ss","short":"d/M/yyyy H:mm","fullDate":"EEEEที่ d MMMM G y","longDate":"d MMMM y","mediumDate":"d MMM y","shortDate":"d/M/yyyy","mediumTime":"H:mm:ss","shortTime":"H:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"฿"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"th"});
+}];
diff --git a/i18n/locale/angular-locale_tl-ph.js b/i18n/locale/angular-locale_tl-ph.js
index b1720af8e7f6..73d3c9c90f61 100644
--- a/i18n/locale/angular-locale_tl-ph.js
+++ b/i18n/locale/angular-locale_tl-ph.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"P"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Enero","Pebrero","Marso","Abril","Mayo","Hunyo","Hulyo","Agosto","Setyembre","Oktubre","Nobyembre","Disyembre"],"SHORTMONTH":["Ene","Peb","Mar","Abr","May","Hun","Hul","Ago","Set","Okt","Nob","Dis"],"DAY":["Linggo","Lunes","Martes","Miyerkules","Huwebes","Biyernes","Sabado"],"SHORTDAY":["Lin","Lun","Mar","Mye","Huw","Bye","Sab"],"AMPMS":["AM","PM"],"medium":"MMM d, y HH:mm:ss","short":"M/d/yy HH:mm","fullDate":"EEEE, MMMM dd y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"tl-ph"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"P"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Enero","Pebrero","Marso","Abril","Mayo","Hunyo","Hulyo","Agosto","Setyembre","Oktubre","Nobyembre","Disyembre"],"SHORTMONTH":["Ene","Peb","Mar","Abr","May","Hun","Hul","Ago","Set","Okt","Nob","Dis"],"DAY":["Linggo","Lunes","Martes","Miyerkules","Huwebes","Biyernes","Sabado"],"SHORTDAY":["Lin","Lun","Mar","Mye","Huw","Bye","Sab"],"AMPMS":["AM","PM"],"medium":"MMM d, y HH:mm:ss","short":"M/d/yy HH:mm","fullDate":"EEEE, MMMM dd y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"tl-ph"});
+}];
diff --git a/i18n/locale/angular-locale_tl.js b/i18n/locale/angular-locale_tl.js
index 49b5fb19efe2..7aa9141b0ed2 100644
--- a/i18n/locale/angular-locale_tl.js
+++ b/i18n/locale/angular-locale_tl.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Enero","Pebrero","Marso","Abril","Mayo","Hunyo","Hulyo","Agosto","Setyembre","Oktubre","Nobyembre","Disyembre"],"SHORTMONTH":["Ene","Peb","Mar","Abr","May","Hun","Hul","Ago","Set","Okt","Nob","Dis"],"DAY":["Linggo","Lunes","Martes","Miyerkules","Huwebes","Biyernes","Sabado"],"SHORTDAY":["Lin","Lun","Mar","Mye","Huw","Bye","Sab"],"AMPMS":["AM","PM"],"medium":"MMM d, y HH:mm:ss","short":"M/d/yy HH:mm","fullDate":"EEEE, MMMM dd y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"P"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"tl"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Enero","Pebrero","Marso","Abril","Mayo","Hunyo","Hulyo","Agosto","Setyembre","Oktubre","Nobyembre","Disyembre"],"SHORTMONTH":["Ene","Peb","Mar","Abr","May","Hun","Hul","Ago","Set","Okt","Nob","Dis"],"DAY":["Linggo","Lunes","Martes","Miyerkules","Huwebes","Biyernes","Sabado"],"SHORTDAY":["Lin","Lun","Mar","Mye","Huw","Bye","Sab"],"AMPMS":["AM","PM"],"medium":"MMM d, y HH:mm:ss","short":"M/d/yy HH:mm","fullDate":"EEEE, MMMM dd y","longDate":"MMMM d, y","mediumDate":"MMM d, y","shortDate":"M/d/yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4 ","posSuf":"","negPre":"\u00A4 -","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"P"},"pluralCat":function (n) {  if (n == 0 || n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"tl"});
+}];
diff --git a/i18n/locale/angular-locale_tr-tr.js b/i18n/locale/angular-locale_tr-tr.js
index 9587c77b9e67..979da8802b87 100644
--- a/i18n/locale/angular-locale_tr-tr.js
+++ b/i18n/locale/angular-locale_tr-tr.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"YTL"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],"SHORTMONTH":["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],"DAY":["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"],"SHORTDAY":["Paz","Pzt","Sal","Çar","Per","Cum","Cmt"],"AMPMS":["AM","PM"],"medium":"dd MMM y HH:mm:ss","short":"dd MM yyyy HH:mm","fullDate":"dd MMMM y EEEE","longDate":"dd MMMM y","mediumDate":"dd MMM y","shortDate":"dd MM yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"tr-tr"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"YTL"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],"SHORTMONTH":["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],"DAY":["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"],"SHORTDAY":["Paz","Pzt","Sal","Çar","Per","Cum","Cmt"],"AMPMS":["AM","PM"],"medium":"dd MMM y HH:mm:ss","short":"dd MM yyyy HH:mm","fullDate":"dd MMMM y EEEE","longDate":"dd MMMM y","mediumDate":"dd MMM y","shortDate":"dd MM yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"tr-tr"});
+}];
diff --git a/i18n/locale/angular-locale_tr.js b/i18n/locale/angular-locale_tr.js
index 4dd55522e475..f96849399324 100644
--- a/i18n/locale/angular-locale_tr.js
+++ b/i18n/locale/angular-locale_tr.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],"SHORTMONTH":["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],"DAY":["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"],"SHORTDAY":["Paz","Pzt","Sal","Çar","Per","Cum","Cmt"],"AMPMS":["AM","PM"],"medium":"dd MMM y HH:mm:ss","short":"dd MM yyyy HH:mm","fullDate":"dd MMMM y EEEE","longDate":"dd MMMM y","mediumDate":"dd MMM y","shortDate":"dd MM yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"YTL"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"tr"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],"SHORTMONTH":["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],"DAY":["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"],"SHORTDAY":["Paz","Pzt","Sal","Çar","Per","Cum","Cmt"],"AMPMS":["AM","PM"],"medium":"dd MMM y HH:mm:ss","short":"dd MM yyyy HH:mm","fullDate":"dd MMMM y EEEE","longDate":"dd MMMM y","mediumDate":"dd MMM y","shortDate":"dd MM yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"YTL"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"tr"});
+}];
diff --git a/i18n/locale/angular-locale_uk-ua.js b/i18n/locale/angular-locale_uk-ua.js
index 97ed947b4376..abb4390aa095 100644
--- a/i18n/locale/angular-locale_uk-ua.js
+++ b/i18n/locale/angular-locale_uk-ua.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₴"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["січня","лютого","березня","квітня","травня","червня","липня","серпня","вересня","жовтня","листопада","грудня"],"SHORTMONTH":["січ.","лют.","бер.","квіт.","трав.","черв.","лип.","серп.","вер.","жовт.","лист.","груд."],"DAY":["Неділя","Понеділок","Вівторок","Середа","Четвер","Пʼятниця","Субота"],"SHORTDAY":["Нд","Пн","Вт","Ср","Чт","Пт","Сб"],"AMPMS":["дп","пп"],"medium":"d MMM y HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d MMMM y 'р'.","longDate":"d MMMM y 'р'.","mediumDate":"d MMM y","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"uk-ua"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₴"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["січня","лютого","березня","квітня","травня","червня","липня","серпня","вересня","жовтня","листопада","грудня"],"SHORTMONTH":["січ.","лют.","бер.","квіт.","трав.","черв.","лип.","серп.","вер.","жовт.","лист.","груд."],"DAY":["Неділя","Понеділок","Вівторок","Середа","Четвер","Пʼятниця","Субота"],"SHORTDAY":["Нд","Пн","Вт","Ср","Чт","Пт","Сб"],"AMPMS":["дп","пп"],"medium":"d MMM y HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d MMMM y 'р'.","longDate":"d MMMM y 'р'.","mediumDate":"d MMM y","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"uk-ua"});
+}];
diff --git a/i18n/locale/angular-locale_uk.js b/i18n/locale/angular-locale_uk.js
index 643fedc82872..f8f80fdec9be 100644
--- a/i18n/locale/angular-locale_uk.js
+++ b/i18n/locale/angular-locale_uk.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["січня","лютого","березня","квітня","травня","червня","липня","серпня","вересня","жовтня","листопада","грудня"],"SHORTMONTH":["січ.","лют.","бер.","квіт.","трав.","черв.","лип.","серп.","вер.","жовт.","лист.","груд."],"DAY":["Неділя","Понеділок","Вівторок","Середа","Четвер","Пʼятниця","Субота"],"SHORTDAY":["Нд","Пн","Вт","Ср","Чт","Пт","Сб"],"AMPMS":["дп","пп"],"medium":"d MMM y HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d MMMM y 'р'.","longDate":"d MMMM y 'р'.","mediumDate":"d MMM y","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₴"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"id":"uk"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["січня","лютого","березня","квітня","травня","червня","липня","серпня","вересня","жовтня","листопада","грудня"],"SHORTMONTH":["січ.","лют.","бер.","квіт.","трав.","черв.","лип.","серп.","вер.","жовт.","лист.","груд."],"DAY":["Неділя","Понеділок","Вівторок","Середа","Четвер","Пʼятниця","Субота"],"SHORTDAY":["Нд","Пн","Вт","Ср","Чт","Пт","Сб"],"AMPMS":["дп","пп"],"medium":"d MMM y HH:mm:ss","short":"dd.MM.yy HH:mm","fullDate":"EEEE, d MMMM y 'р'.","longDate":"d MMMM y 'р'.","mediumDate":"d MMM y","shortDate":"dd.MM.yy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":" ","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₴"},"pluralCat":function (n) {  if ((n % 10) == 1 && (n % 100) != 11) {    return PLURAL_CATEGORY.ONE;  }  if ((n % 10) >= 2 && (n % 10) <= 4 &&      ((n % 100) < 12 || (n % 100) > 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.FEW;  }  if ((n % 10) == 0 || ((n % 10) >= 5 && (n % 10) <= 9) ||      ((n % 100) >= 11 && (n % 100) <= 14) && n == Math.floor(n)) {    return PLURAL_CATEGORY.MANY;  }  return PLURAL_CATEGORY.OTHER;},"id":"uk"});
+}];
diff --git a/i18n/locale/angular-locale_ur-pk.js b/i18n/locale/angular-locale_ur-pk.js
index 8492626b5844..6cbc8832daed 100644
--- a/i18n/locale/angular-locale_ur-pk.js
+++ b/i18n/locale/angular-locale_ur-pk.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs."},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["جنوری","فروری","مار چ","اپريل","مئ","جون","جولائ","اگست","ستمبر","اکتوبر","نومبر","دسمبر"],"SHORTMONTH":["جنوری","فروری","مار چ","اپريل","مئ","جون","جولائ","اگست","ستمبر","اکتوبر","نومبر","دسمبر"],"DAY":["اتوار","پير","منگل","بده","جمعرات","جمعہ","ہفتہ"],"SHORTDAY":["اتوار","پير","منگل","بده","جمعرات","جمعہ","ہفتہ"],"AMPMS":["قبل دوپہر","بعد دوپہر"],"medium":"d, MMM y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, d, MMMM y","longDate":"d, MMMM y","mediumDate":"d, MMM y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"ur-pk"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs."},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["جنوری","فروری","مار چ","اپريل","مئ","جون","جولائ","اگست","ستمبر","اکتوبر","نومبر","دسمبر"],"SHORTMONTH":["جنوری","فروری","مار چ","اپريل","مئ","جون","جولائ","اگست","ستمبر","اکتوبر","نومبر","دسمبر"],"DAY":["اتوار","پير","منگل","بده","جمعرات","جمعہ","ہفتہ"],"SHORTDAY":["اتوار","پير","منگل","بده","جمعرات","جمعہ","ہفتہ"],"AMPMS":["قبل دوپہر","بعد دوپہر"],"medium":"d, MMM y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, d, MMMM y","longDate":"d, MMMM y","mediumDate":"d, MMM y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"id":"ur-pk"});
+}];
diff --git a/i18n/locale/angular-locale_ur.js b/i18n/locale/angular-locale_ur.js
index f1b5f634126e..2ba65c3cad21 100644
--- a/i18n/locale/angular-locale_ur.js
+++ b/i18n/locale/angular-locale_ur.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["جنوری","فروری","مار چ","اپريل","مئ","جون","جولائ","اگست","ستمبر","اکتوبر","نومبر","دسمبر"],"SHORTMONTH":["جنوری","فروری","مار چ","اپريل","مئ","جون","جولائ","اگست","ستمبر","اکتوبر","نومبر","دسمبر"],"DAY":["اتوار","پير","منگل","بده","جمعرات","جمعہ","ہفتہ"],"SHORTDAY":["اتوار","پير","منگل","بده","جمعرات","جمعہ","ہفتہ"],"AMPMS":["قبل دوپہر","بعد دوپہر"],"medium":"d, MMM y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, d, MMMM y","longDate":"d, MMMM y","mediumDate":"d, MMM y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs."},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"ur"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["جنوری","فروری","مار چ","اپريل","مئ","جون","جولائ","اگست","ستمبر","اکتوبر","نومبر","دسمبر"],"SHORTMONTH":["جنوری","فروری","مار چ","اپريل","مئ","جون","جولائ","اگست","ستمبر","اکتوبر","نومبر","دسمبر"],"DAY":["اتوار","پير","منگل","بده","جمعرات","جمعہ","ہفتہ"],"SHORTDAY":["اتوار","پير","منگل","بده","جمعرات","جمعہ","ہفتہ"],"AMPMS":["قبل دوپہر","بعد دوپہر"],"medium":"d, MMM y h:mm:ss a","short":"d/M/yy h:mm a","fullDate":"EEEE, d, MMMM y","longDate":"d, MMMM y","mediumDate":"d, MMM y","shortDate":"d/M/yy","mediumTime":"h:mm:ss a","shortTime":"h:mm a"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"Rs."},"pluralCat":function (n) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;},"id":"ur"});
+}];
diff --git a/i18n/locale/angular-locale_vi-vn.js b/i18n/locale/angular-locale_vi-vn.js
index a2d8d7623794..5438f5040408 100644
--- a/i18n/locale/angular-locale_vi-vn.js
+++ b/i18n/locale/angular-locale_vi-vn.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₫"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["tháng một","tháng hai","tháng ba","tháng tư","tháng năm","tháng sáu","tháng bảy","tháng tám","tháng chín","tháng mười","tháng mười một","tháng mười hai"],"SHORTMONTH":["thg 1","thg 2","thg 3","thg 4","thg 5","thg 6","thg 7","thg 8","thg 9","thg 10","thg 11","thg 12"],"DAY":["Chủ nhật","Thứ hai","Thứ ba","Thứ tư","Thứ năm","Thứ sáu","Thứ bảy"],"SHORTDAY":["CN","Th 2","Th 3","Th 4","Th 5","Th 6","Th 7"],"AMPMS":["SA","CH"],"medium":"dd-MM-yyyy HH:mm:ss","short":"dd/MM/yyyy HH:mm","fullDate":"EEEE, 'ngày' dd MMMM 'năm' y","longDate":"'Ngày' dd 'tháng' M 'năm' y","mediumDate":"dd-MM-yyyy","shortDate":"dd/MM/yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"vi-vn"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₫"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["tháng một","tháng hai","tháng ba","tháng tư","tháng năm","tháng sáu","tháng bảy","tháng tám","tháng chín","tháng mười","tháng mười một","tháng mười hai"],"SHORTMONTH":["thg 1","thg 2","thg 3","thg 4","thg 5","thg 6","thg 7","thg 8","thg 9","thg 10","thg 11","thg 12"],"DAY":["Chủ nhật","Thứ hai","Thứ ba","Thứ tư","Thứ năm","Thứ sáu","Thứ bảy"],"SHORTDAY":["CN","Th 2","Th 3","Th 4","Th 5","Th 6","Th 7"],"AMPMS":["SA","CH"],"medium":"dd-MM-yyyy HH:mm:ss","short":"dd/MM/yyyy HH:mm","fullDate":"EEEE, 'ngày' dd MMMM 'năm' y","longDate":"'Ngày' dd 'tháng' M 'năm' y","mediumDate":"dd-MM-yyyy","shortDate":"dd/MM/yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"id":"vi-vn"});
+}];
diff --git a/i18n/locale/angular-locale_vi.js b/i18n/locale/angular-locale_vi.js
index 42fe05d91430..b6f2cb21cea5 100644
--- a/i18n/locale/angular-locale_vi.js
+++ b/i18n/locale/angular-locale_vi.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["tháng một","tháng hai","tháng ba","tháng tư","tháng năm","tháng sáu","tháng bảy","tháng tám","tháng chín","tháng mười","tháng mười một","tháng mười hai"],"SHORTMONTH":["thg 1","thg 2","thg 3","thg 4","thg 5","thg 6","thg 7","thg 8","thg 9","thg 10","thg 11","thg 12"],"DAY":["Chủ nhật","Thứ hai","Thứ ba","Thứ tư","Thứ năm","Thứ sáu","Thứ bảy"],"SHORTDAY":["CN","Th 2","Th 3","Th 4","Th 5","Th 6","Th 7"],"AMPMS":["SA","CH"],"medium":"dd-MM-yyyy HH:mm:ss","short":"dd/MM/yyyy HH:mm","fullDate":"EEEE, 'ngày' dd MMMM 'năm' y","longDate":"'Ngày' dd 'tháng' M 'năm' y","mediumDate":"dd-MM-yyyy","shortDate":"dd/MM/yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₫"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"vi"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["tháng một","tháng hai","tháng ba","tháng tư","tháng năm","tháng sáu","tháng bảy","tháng tám","tháng chín","tháng mười","tháng mười một","tháng mười hai"],"SHORTMONTH":["thg 1","thg 2","thg 3","thg 4","thg 5","thg 6","thg 7","thg 8","thg 9","thg 10","thg 11","thg 12"],"DAY":["Chủ nhật","Thứ hai","Thứ ba","Thứ tư","Thứ năm","Thứ sáu","Thứ bảy"],"SHORTDAY":["CN","Th 2","Th 3","Th 4","Th 5","Th 6","Th 7"],"AMPMS":["SA","CH"],"medium":"dd-MM-yyyy HH:mm:ss","short":"dd/MM/yyyy HH:mm","fullDate":"EEEE, 'ngày' dd MMMM 'năm' y","longDate":"'Ngày' dd 'tháng' M 'năm' y","mediumDate":"dd-MM-yyyy","shortDate":"dd/MM/yyyy","mediumTime":"HH:mm:ss","shortTime":"HH:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":",","GROUP_SEP":".","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"","posSuf":" \u00A4","negPre":"-","negSuf":" \u00A4","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"₫"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"vi"});
+}];
diff --git a/i18n/locale/angular-locale_zh-cn.js b/i18n/locale/angular-locale_zh-cn.js
index 4e5ec635c186..b4d68038295c 100644
--- a/i18n/locale/angular-locale_zh-cn.js
+++ b/i18n/locale/angular-locale_zh-cn.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"SHORTDAY":["周日","周一","周二","周三","周四","周五","周六"],"AMPMS":["上午","下午"],"medium":"yyyy-M-d ah:mm:ss","short":"yy-M-d ah:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"yyyy-M-d","shortDate":"yy-M-d","mediumTime":"ah:mm:ss","shortTime":"ah:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"¥"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"zh-cn"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"SHORTDAY":["周日","周一","周二","周三","周四","周五","周六"],"AMPMS":["上午","下午"],"medium":"yyyy-M-d ah:mm:ss","short":"yy-M-d ah:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"yyyy-M-d","shortDate":"yy-M-d","mediumTime":"ah:mm:ss","shortTime":"ah:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"¥"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"zh-cn"});
+}];
diff --git a/i18n/locale/angular-locale_zh-hans-cn.js b/i18n/locale/angular-locale_zh-hans-cn.js
index a4f2bfd345a5..3d3f11f47bf9 100644
--- a/i18n/locale/angular-locale_zh-hans-cn.js
+++ b/i18n/locale/angular-locale_zh-hans-cn.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"¥"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"SHORTDAY":["周日","周一","周二","周三","周四","周五","周六"],"AMPMS":["上午","下午"],"medium":"yyyy-M-d ah:mm:ss","short":"yy-M-d ah:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"yyyy-M-d","shortDate":"yy-M-d","mediumTime":"ah:mm:ss","shortTime":"ah:mm"},"id":"zh-hans-cn"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"¥"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"SHORTDAY":["周日","周一","周二","周三","周四","周五","周六"],"AMPMS":["上午","下午"],"medium":"yyyy-M-d ah:mm:ss","short":"yy-M-d ah:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"yyyy-M-d","shortDate":"yy-M-d","mediumTime":"ah:mm:ss","shortTime":"ah:mm"},"id":"zh-hans-cn"});
+}];
diff --git a/i18n/locale/angular-locale_zh-hans.js b/i18n/locale/angular-locale_zh-hans.js
index 44ea178ac52e..55fa28b45e91 100644
--- a/i18n/locale/angular-locale_zh-hans.js
+++ b/i18n/locale/angular-locale_zh-hans.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"¥"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"SHORTDAY":["周日","周一","周二","周三","周四","周五","周六"],"AMPMS":["上午","下午"],"medium":"yyyy-M-d ah:mm:ss","short":"yy-M-d ah:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"yyyy-M-d","shortDate":"yy-M-d","mediumTime":"ah:mm:ss","shortTime":"ah:mm"},"id":"zh-hans"};
-});
\ No newline at end of file
+$provide.value("$locale", {"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"¥"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"SHORTDAY":["周日","周一","周二","周三","周四","周五","周六"],"AMPMS":["上午","下午"],"medium":"yyyy-M-d ah:mm:ss","short":"yy-M-d ah:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"yyyy-M-d","shortDate":"yy-M-d","mediumTime":"ah:mm:ss","shortTime":"ah:mm"},"id":"zh-hans"});
+}];
diff --git a/i18n/locale/angular-locale_zh-hk.js b/i18n/locale/angular-locale_zh-hk.js
index 99502cce9d92..03756b81b841 100644
--- a/i18n/locale/angular-locale_zh-hk.js
+++ b/i18n/locale/angular-locale_zh-hk.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"SHORTDAY":["週日","週一","週二","週三","週四","週五","週六"],"AMPMS":["上午","下午"],"medium":"y年M月d日 ahh:mm:ss","short":"yy年M月d日 ah:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"y年M月d日","shortDate":"yy年M月d日","mediumTime":"ahh:mm:ss","shortTime":"ah:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"zh-hk"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"SHORTDAY":["週日","週一","週二","週三","週四","週五","週六"],"AMPMS":["上午","下午"],"medium":"y年M月d日 ahh:mm:ss","short":"yy年M月d日 ah:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"y年M月d日","shortDate":"yy年M月d日","mediumTime":"ahh:mm:ss","shortTime":"ah:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"(\u00A4","negSuf":")","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"$"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"zh-hk"});
+}];
diff --git a/i18n/locale/angular-locale_zh-tw.js b/i18n/locale/angular-locale_zh-tw.js
index 9bea7839857d..cc62c3ccfe93 100644
--- a/i18n/locale/angular-locale_zh-tw.js
+++ b/i18n/locale/angular-locale_zh-tw.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"SHORTDAY":["週日","週一","週二","週三","週四","週五","週六"],"AMPMS":["上午","下午"],"medium":"yyyy/M/d ah:mm:ss","short":"yy/M/d ah:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"yyyy/M/d","shortDate":"yy/M/d","mediumTime":"ah:mm:ss","shortTime":"ah:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"NT$"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"zh-tw"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"SHORTDAY":["週日","週一","週二","週三","週四","週五","週六"],"AMPMS":["上午","下午"],"medium":"yyyy/M/d ah:mm:ss","short":"yy/M/d ah:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"yyyy/M/d","shortDate":"yy/M/d","mediumTime":"ah:mm:ss","shortTime":"ah:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"NT$"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"zh-tw"});
+}];
diff --git a/i18n/locale/angular-locale_zh.js b/i18n/locale/angular-locale_zh.js
index 723cca89ccd5..85b01205657f 100644
--- a/i18n/locale/angular-locale_zh.js
+++ b/i18n/locale/angular-locale_zh.js
@@ -1,4 +1,6 @@
-angular.service("$locale", function() {
+window.angular = window.angular || {};
+angular.module = angular.module || {};
+angular.module.ngLocale = ["$provide", function($provide) {
 var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-return {"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"SHORTDAY":["周日","周一","周二","周三","周四","周五","周六"],"AMPMS":["上午","下午"],"medium":"yyyy-M-d ah:mm:ss","short":"yy-M-d ah:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"yyyy-M-d","shortDate":"yy-M-d","mediumTime":"ah:mm:ss","shortTime":"ah:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"¥"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"zh"};
-});
\ No newline at end of file
+$provide.value("$locale", {"DATETIME_FORMATS":{"MONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"SHORTMONTH":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"DAY":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"SHORTDAY":["周日","周一","周二","周三","周四","周五","周六"],"AMPMS":["上午","下午"],"medium":"yyyy-M-d ah:mm:ss","short":"yy-M-d ah:mm","fullDate":"y年M月d日EEEE","longDate":"y年M月d日","mediumDate":"yyyy-M-d","shortDate":"yy-M-d","mediumTime":"ah:mm:ss","shortTime":"ah:mm"},"NUMBER_FORMATS":{"DECIMAL_SEP":".","GROUP_SEP":",","PATTERNS":[{"minInt":1,"minFrac":0,"macFrac":0,"posPre":"","posSuf":"","negPre":"-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":3},{"minInt":1,"minFrac":2,"macFrac":0,"posPre":"\u00A4","posSuf":"","negPre":"\u00A4-","negSuf":"","gSize":3,"lgSize":3,"maxFrac":2}],"CURRENCY_SYM":"¥"},"pluralCat":function (n) {  return PLURAL_CATEGORY.OTHER;},"id":"zh"});
+}];
diff --git a/i18n/src/closureSlurper.js b/i18n/src/closureSlurper.js
index 69c94e10f02a..9630c5e149ab 100644
--- a/i18n/src/closureSlurper.js
+++ b/i18n/src/closureSlurper.js
@@ -100,13 +100,16 @@ createFolder('../locale/').then(function() {
     var correctedLocaleId = localeID.replace(/_/g, '-').toLowerCase();
     localeObj.id = correctedLocaleId;
 
-    var prefix = 'angular.service("$locale", function() {\n' +
-                 'var PLURAL_CATEGORY = {' +
-                   'ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"' +
-                 '};\n' +
-                 'return ';
-
-    var suffix = ';\n});';
+    var prefix =
+      'window.angular = window.angular || {};\n' +
+      'angular.module = angular.module || {};\n' +
+      'angular.module.ngLocale = ["$provide", function($provide) {\n' +
+         'var PLURAL_CATEGORY = {' +
+           'ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"' +
+         '};\n' +
+         '$provide.value("$locale", ';
+
+    var suffix = ');\n}];';
 
     var content = JSON.stringify(localeInfo[localeID]).replace(/\¤/g,'\\u00A4').
                       replace(/"@@|@@"/g, '');
diff --git a/regression/resource_json_date.html b/regression/resource_json_date.html
index 59300863ab9e..4b85a9f1ea56 100644
--- a/regression/resource_json_date.html
+++ b/regression/resource_json_date.html
@@ -4,7 +4,7 @@
   
   
   
- *   
- * Number of items in array: {{ [1,2].$size() }}
- * Number of items in object: {{ {a:1, b:2, c:3}.$size() }}
- * String length: {{fooStringLength}} - *
- * - * - * it('should print correct sizes for an array and an object', function() { - * expect(binding('[1,2].$size()')).toBe('2'); - * expect(binding('{a:1, b:2, c:3}.$size()')).toBe('3'); - * expect(binding('fooStringLength')).toBe('3'); - * }); - * - * */ function size(obj, ownPropsOnly) { var size = 0, key; @@ -572,6 +538,13 @@ function indexOf(array, obj) { return -1; } +function arrayRemove(array, value) { + var index = indexOf(array, value); + if (index >=0) + array.splice(index, 1); + return value; +} + function isLeafNode (node) { if (node) { switch (node.nodeName) { @@ -590,15 +563,6 @@ function isLeafNode (node) { * @function * * @description - * Alias for {@link angular.Object.copy} - */ - -/** - * @ngdoc function - * @name angular.Object.copy - * @function - * - * @description * Creates a deep copy of `source`, which should be an object or an array. * * * If no destination is supplied, a copy of the object or array is created. @@ -607,53 +571,13 @@ function isLeafNode (node) { * * If `source` is not an object or array, `source` is returned. * * Note: this function is used to augment the Object type in Angular expressions. See - * {@link angular.Array} for more information about Angular arrays. + * {@link angular.module.ng.$filter} for more information about Angular arrays. * * @param {*} source The source that will be used to make a copy. * Can be any type, including primitives, `null`, and `undefined`. * @param {(Object|Array)=} destination Destination into which the source is copied. If * provided, must be of the same type as `source`. * @returns {*} The copy or updated `destination`, if `destination` was specified. - * - * @example - * - * - -
- Salutation:
- Name:
- -
- - The master object is NOT equal to the form object. - -
master={{master}}
-
form={{form}}
-
- *
- * - it('should print that initialy the form object is NOT equal to master', function() { - expect(element('.doc-example-live input[ng\\:model="master.salutation"]').val()).toBe('Hello'); - expect(element('.doc-example-live input[ng\\:model="master.name"]').val()).toBe('world'); - expect(element('.doc-example-live span').css('display')).toBe('inline'); - }); - - it('should make form and master equal when the copy button is clicked', function() { - element('.doc-example-live button').click(); - expect(element('.doc-example-live span').css('display')).toBe('none'); - }); - * - *
*/ function copy(source, destination){ if (!destination) { @@ -693,15 +617,6 @@ function copy(source, destination){ * @function * * @description - * Alias for {@link angular.Object.equals} - */ - -/** - * @ngdoc function - * @name angular.Object.equals - * @function - * - * @description * Determines if two objects or two values are equivalent. Supports value types, arrays and * objects. * @@ -714,56 +629,19 @@ function copy(source, destination){ * that begin with `$` are ignored. * * Note: This function is used to augment the Object type in Angular expressions. See - * {@link angular.Array} for more information about Angular arrays. + * {@link angular.module.ng.$filter} for more information about Angular arrays. * * @param {*} o1 Object or value to compare. * @param {*} o2 Object or value to compare. * @returns {boolean} True if arguments are equal. * - * @example - * - * - -
- Salutation:
- Name:
-
- - The greeting object is - NOT equal to - {salutation:'Hello', name:'world'}. - -
greeting={{greeting}}
-
- *
- * - it('should print that initialy greeting is equal to the hardcoded value object', function() { - expect(element('.doc-example-live input[ng\\:model="greeting.salutation"]').val()).toBe('Hello'); - expect(element('.doc-example-live input[ng\\:model="greeting.name"]').val()).toBe('world'); - expect(element('.doc-example-live span').css('display')).toBe('none'); - }); - - it('should say that the objects are not equal when the form is modified', function() { - input('greeting.name').enter('kitty'); - expect(element('.doc-example-live span').css('display')).toBe('inline'); - }); - * - *
*/ function equals(o1, o2) { if (o1 === o2) return true; if (o1 === null || o2 === null) return false; var t1 = typeof o1, t2 = typeof o2, length, key, keySet; if (t1 == t2 && t1 == 'object') { - if (o1 instanceof Array) { + if (isArray(o1)) { if ((length = o1.length) == o2.length) { for(key=0; key=} modules an array of module declarations. See: {@link angular.module modules} + */ +function bootstrap(element, modules) { + modules = modules || []; + modules.unshift(ngModule); + createInjector(modules, angularModule).invoke(null, + ['$rootScope', '$compile', '$injector', function(scope, compile, injector){ + scope.$apply(function() { + element.data('$injector', injector); + compile(element)(scope); + }); + }] + ); +} + function angularJsConfig(document) { bindJQuery(); var scripts = document.getElementsByTagName('script'), @@ -1012,28 +914,6 @@ function assertArg(arg, name, reason) { function assertArgFn(arg, name) { assertArg(isFunction(arg), name, 'not a function, got ' + - (typeof arg == 'object' ? arg.constructor.name : typeof arg)); + (typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg)); return arg; } - - -/** - * @ngdoc property - * @name angular.version - * @description - * An object that contains information about the current AngularJS version. This object has the - * following properties: - * - * - `full` – `{string}` – Full version string, such as "0.9.18". - * - `major` – `{number}` – Major version number, such as "0". - * - `minor` – `{number}` – Minor version number, such as "9". - * - `dot` – `{number}` – Dot version number, such as "18". - * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". - */ -var version = { - full: '"NG_VERSION_FULL"', // all of these placeholder strings will be replaced by rake's - major: "NG_VERSION_MAJOR", // compile task - minor: "NG_VERSION_MINOR", - dot: "NG_VERSION_DOT", - codeName: '"NG_VERSION_CODENAME"' -}; diff --git a/src/AngularPublic.js b/src/AngularPublic.js index fc8a90fdf978..663011045786 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -1,46 +1,92 @@ 'use strict'; -var browserSingleton; - -angularService('$browser', function($log, $sniffer) { - if (!browserSingleton) { - browserSingleton = new Browser(window, jqLite(window.document), jqLite(window.document.body), - XHR, $log, $sniffer); - } - return browserSingleton; -}, {$inject: ['$log', '$sniffer']}); - - -extend(angular, { - // disabled for now until we agree on public name - //'annotate': annotate, - 'compile': compile, - 'scope': createScope, - 'copy': copy, - 'extend': extend, - 'equals': equals, - 'forEach': forEach, - 'injector': createInjector, - 'noop':noop, - 'bind':bind, - 'toJson': toJson, - 'fromJson': fromJson, - 'identity':identity, - 'isUndefined': isUndefined, - 'isDefined': isDefined, - 'isString': isString, - 'isFunction': isFunction, - 'isObject': isObject, - 'isNumber': isNumber, - 'isArray': isArray, - 'version': version, - 'isDate': isDate, - 'lowercase': lowercase, - 'uppercase': uppercase -}); - -//try to bind to jquery now so that one can write angular.element().read() -//but we will rebind on bootstrap again. -bindJQuery(); +/** + * @ngdoc property + * @name angular.version + * @description + * An object that contains information about the current AngularJS version. This object has the + * following properties: + * + * - `full` – `{string}` – Full version string, such as "0.9.18". + * - `major` – `{number}` – Major version number, such as "0". + * - `minor` – `{number}` – Minor version number, such as "9". + * - `dot` – `{number}` – Dot version number, such as "18". + * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". + */ +var version = { + full: '"NG_VERSION_FULL"', // all of these placeholder strings will be replaced by rake's + major: "NG_VERSION_MAJOR", // compile task + minor: "NG_VERSION_MINOR", + dot: "NG_VERSION_DOT", + codeName: '"NG_VERSION_CODENAME"' +}; +function publishExternalAPI(angular){ + extend(angular, { + 'bootstrap': bootstrap, + 'copy': copy, + 'extend': extend, + 'equals': equals, + 'element': jqLite, + 'forEach': forEach, + 'injector': function(){ return createInjector(arguments, angularModule); }, + 'noop':noop, + 'bind':bind, + 'toJson': toJson, + 'fromJson': fromJson, + 'identity':identity, + 'isUndefined': isUndefined, + 'isDefined': isDefined, + 'isString': isString, + 'isFunction': isFunction, + 'isObject': isObject, + 'isNumber': isNumber, + 'isElement': isElement, + 'isArray': isArray, + 'version': version, + 'isDate': isDate, + 'lowercase': lowercase, + 'uppercase': uppercase + }); + + angularModule.ng = ngModule; +} + +ngModule.$inject = ['$provide', '$injector']; +function ngModule($provide, $injector) { +// TODO(misko): temporary services to get the compiler working; + $provide.value('$textMarkup', angularTextMarkup); + $provide.value('$attrMarkup', angularAttrMarkup); + $provide.value('$directive', angularDirective); + $provide.value('$widget', angularWidget); + + // load the LOCALE if present + $injector.invoke(null, angularModule.ngLocale || function(){ + $provide.service('$locale', $LocaleProvider); + }); + + $provide.service('$browser', $BrowserProvider); + $provide.service('$compile', $CompileProvider); + $provide.service('$cookies', $CookiesProvider); + $provide.service('$cookieStore', $CookieStoreProvider); + $provide.service('$defer', $DeferProvider); + $provide.service('$document', $DocumentProvider); + $provide.service('$exceptionHandler', $ExceptionHandlerProvider); + $provide.service('$filter', $FilterProvider); + $provide.service('$formFactory', $FormFactoryProvider); + $provide.service('$location', $LocationProvider); + $provide.service('$log', $LogProvider); + $provide.service('$parse', $ParseProvider); + $provide.service('$resource', $ResourceProvider); + $provide.service('$route', $RouteProvider); + $provide.service('$routeParams', $RouteParamsProvider); + $provide.service('$rootScope', $RootScopeProvider); + $provide.service('$sniffer', $SnifferProvider); + $provide.service('$window', $WindowProvider); + $provide.service('$xhr.bulk', $XhrBulkProvider); + $provide.service('$xhr.cache', $XhrCacheProvider); + $provide.service('$xhr.error', $XhrErrorProvider); + $provide.service('$xhr', $XhrProvider); +} + diff --git a/src/Compiler.js b/src/Compiler.js deleted file mode 100644 index 0411c70de60a..000000000000 --- a/src/Compiler.js +++ /dev/null @@ -1,330 +0,0 @@ -'use strict'; - -/** - * Template provides directions an how to bind to a given element. - * It contains a list of init functions which need to be called to - * bind to a new instance of elements. It also provides a list - * of child paths which contain child templates - */ -function Template() { - this.paths = []; - this.children = []; - this.linkFns = []; - this.newScope = false; -} - -Template.prototype = { - link: function(element, scope) { - var childScope = scope; - if (this.newScope) { - childScope = isFunction(this.newScope) ? scope.$new(this.newScope(scope)) : scope.$new(); - element.data($$scope, childScope); - } - forEach(this.linkFns, function(fn) { - try { - childScope.$service.invoke(childScope, fn, [element]); - } catch (e) { - childScope.$service('$exceptionHandler')(e); - } - }); - var i, - childNodes = element[0].childNodes, - children = this.children, - paths = this.paths, - length = paths.length; - for (i = 0; i < length; i++) { - // sometimes `element` can be modified by one of the linker functions in `this.linkFns` - // and childNodes may be added or removed - // TODO: element structure needs to be re-evaluated if new children added - // if the childNode still exists - if (childNodes[paths[i]]) - children[i].link(jqLite(childNodes[paths[i]]), childScope); - else - delete paths[i]; // if child no longer available, delete path - } - }, - - - addLinkFn:function(linkingFn) { - if (linkingFn) { - this.linkFns.push(linkingFn); - } - }, - - - addChild: function(index, template) { - if (template) { - this.paths.push(index); - this.children.push(template); - } - }, - - empty: function() { - return this.linkFns.length === 0 && this.paths.length === 0; - } -}; - -/////////////////////////////////// -//Compiler -////////////////////////////////// - -/** - * @ngdoc function - * @name angular.compile - * @function - * - * @description - * Compiles a piece of HTML string or DOM into a template and produces a template function, which - * can then be used to link {@link angular.scope scope} and the template together. - * - * The compilation is a process of walking the DOM tree and trying to match DOM elements to - * {@link angular.markup markup}, {@link angular.attrMarkup attrMarkup}, - * {@link angular.widget widgets}, and {@link angular.directive directives}. For each match it - * executes corresponding markup, attrMarkup, widget or directive template function and collects the - * instance functions into a single template function which is then returned. - * - * The template function can then be used once to produce the view or as it is the case with - * {@link angular.widget.@ng:repeat repeater} many-times, in which case each call results in a view - * that is a DOM clone of the original template. - * -
-    // compile the entire window.document and give me the scope bound to this template.
-    var rootScope = angular.compile(window.document)();
-
-    // compile a piece of html
-    var rootScope2 = angular.compile('
click me
')(); - - // compile a piece of html and retain reference to both the dom and scope - var template = angular.element('
click me
'), - scope = angular.compile(template)(); - // at this point template was transformed into a view -
- * - * - * @param {string|DOMElement} element Element or HTML to compile into a template function. - * @returns {function([scope][, cloneAttachFn])} a template function which is used to bind template - * (a DOM element/tree) to a scope. Where: - * - * * `scope` - A {@link angular.scope Scope} to bind to. If none specified, then a new - * root scope is created. - * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the - * `template` and call the `cloneAttachFn` function allowing the caller to attach the - * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is - * called as:
`cloneAttachFn(clonedElement, scope)` where: - * - * * `clonedElement` - is a clone of the original `element` passed into the compiler. - * * `scope` - is the current scope with which the linking function is working with. - * - * Calling the template function returns the scope to which the element is bound to. It is either - * the same scope as the one passed into the template function, or if none were provided it's the - * newly create scope. - * - * It is important to understand that the returned scope is "linked" to the view DOM, but no linking - * (instance) functions registered by {@link angular.directive directives} or - * {@link angular.widget widgets} found in the template have been executed yet. This means that the - * view is likely empty and doesn't contain any values that result from evaluation on the scope. To - * bring the view to life, the scope needs to run through a $digest phase which typically is done by - * Angular automatically, except for the case when an application is being - * {@link guide/dev_guide.bootstrap.manual_bootstrap} manually bootstrapped, in which case the - * $digest phase must be invoked by calling {@link angular.scope.$apply}. - * - * If you need access to the bound view, there are two ways to do it: - * - * - If you are not asking the linking function to clone the template, create the DOM element(s) - * before you send them to the compiler and keep this reference around. - *
- *     var view = angular.element('

{{total}}

'), - * scope = angular.compile(view)(); - *
- * - * - if on the other hand, you need the element to be cloned, the view reference from the original - * example would not point to the clone, but rather to the original template that was cloned. In - * this case, you can access the clone via the cloneAttachFn: - *
- *     var original = angular.element('

{{total}}

'), - * scope = someParentScope.$new(), - * clone; - * - * angular.compile(original)(scope, function(clonedElement, scope) { - * clone = clonedElement; - * //attach the clone to DOM document at the right place - * }); - * - * //now we have reference to the cloned DOM via `clone` - *
- * - * - * Compiler Methods For Widgets and Directives: - * - * The following methods are available for use when you write your own widgets, directives, - * and markup. (Recall that the compile function's this is a reference to the compiler.) - * - * `compile(element)` - returns linker - - * Invoke a new instance of the compiler to compile a DOM element and return a linker function. - * You can apply the linker function to the original element or a clone of the original element. - * The linker function returns a scope. - * - * * `comment(commentText)` - returns element - Create a comment element. - * - * * `element(elementName)` - returns element - Create an element by name. - * - * * `text(text)` - returns element - Create a text element. - * - * * `descend([set])` - returns descend state (true or false). Get or set the current descend - * state. If true the compiler will descend to children elements. - * - * * `directives([set])` - returns directive state (true or false). Get or set the current - * directives processing state. The compiler will process directives only when directives set to - * true. - * - * For information on how the compiler works, see the - * {@link guide/dev_guide.compiler Angular HTML Compiler} section of the Developer Guide. - */ -function Compiler(markup, attrMarkup, directives, widgets){ - this.markup = markup; - this.attrMarkup = attrMarkup; - this.directives = directives; - this.widgets = widgets; -} - -Compiler.prototype = { - compile: function(templateElement) { - templateElement = jqLite(templateElement); - var index = 0, - template, - parent = templateElement.parent(); - if (templateElement.length > 1) { - // https://github.com/angular/angular.js/issues/338 - throw Error("Cannot compile multiple element roots: " + - jqLite('
').append(templateElement.clone()).html()); - } - if (parent && parent[0]) { - parent = parent[0]; - for(var i = 0; i < parent.childNodes.length; i++) { - if (parent.childNodes[i] == templateElement[0]) { - index = i; - } - } - } - template = this.templatize(templateElement, index) || new Template(); - return function(scope, cloneConnectFn){ - // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart - // and sometimes changes the structure of the DOM. - var element = cloneConnectFn - ? JQLitePrototype.clone.call(templateElement) // IMPORTANT!!! - : templateElement; - scope = scope || createScope(); - element.data($$scope, scope); - scope.$element = element; - (cloneConnectFn||noop)(element, scope); - template.link(element, scope); - return scope; - }; - }, - - templatize: function(element, elementIndex){ - var self = this, - widget, - fn, - directiveFns = self.directives, - descend = true, - directives = true, - elementName = nodeName_(element), - elementNamespace = elementName.indexOf(':') > 0 ? lowercase(elementName).replace(':', '-') : '', - template, - selfApi = { - compile: bind(self, self.compile), - descend: function(value){ if(isDefined(value)) descend = value; return descend;}, - directives: function(value){ if(isDefined(value)) directives = value; return directives;}, - scope: function(value){ if(isDefined(value)) template.newScope = template.newScope || value; return template.newScope;} - }; - element.addClass(elementNamespace); - template = new Template(); - eachAttribute(element, function(value, name){ - if (!widget) { - if ((widget = self.widgets('@' + name))) { - element.addClass('ng-attr-widget'); - widget = bind(selfApi, widget, value, element); - } - } - }); - if (!widget) { - if ((widget = self.widgets(elementName))) { - if (elementNamespace) - element.addClass('ng-widget'); - widget = bind(selfApi, widget, element); - } - } - if (widget) { - descend = false; - directives = false; - var parent = element.parent(); - template.addLinkFn(widget.call(selfApi, element)); - if (parent && parent[0]) { - element = jqLite(parent[0].childNodes[elementIndex]); - } - } - if (descend){ - // process markup for text nodes only - for(var i=0, child=element[0].childNodes; - i=} [factories=angular.service] Map of the service factory - * functions. - * @param {Object.=} [instanceCache={}] Place where instances of services are - * saved for reuse. Can also be used to override services specified by `serviceFactory` - * (useful in tests). - * @returns {function()} Injector function: - * - * * `injector(serviceName)`: - * * `serviceName` - `{string=}` - Name of the service to retrieve. - * - * The injector function also has these properties: - * - * * An `invoke` property which can be used to invoke methods with dependency-injected arguments. - * `injector.invoke(self, fn, curryArgs)` - * * `self` - The "`this`" to be used when invoking the function. - * * `fn` - The function to be invoked. The function may have the `$inject` property that - * lists the set of arguments which should be auto-injected. - * (see {@link guide/dev_guide.di dependency injection}). - * * `curryArgs(array)` - Optional array of arguments to pass to the function - * invocation after the injection arguments (also known as curry arguments or currying). - * * An `eager` property which is used to initialize the eager services. - * `injector.eager()` - */ -function createInjector(factoryScope, factories, instanceCache) { - factories = factories || angularService; - instanceCache = instanceCache || {}; - factoryScope = factoryScope || {}; - injector.invoke = invoke; - - injector.eager = function() { - forEach(factories, function(factory, name){ - if (factory.$eager) - injector(name); - - if (factory.$creation) - throw new Error("Failed to register service '" + name + - "': $creation property is unsupported. Use $eager:true or see release notes."); - }); - }; - return injector; - - function injector(value){ - if (!(value in instanceCache)) { - var factory = factories[value]; - if (!factory) throw Error("Unknown provider for '"+value+"'."); - inferInjectionArgs(factory); - instanceCache[value] = invoke(factoryScope, factory); - } - return instanceCache[value]; - } - - function invoke(self, fn, args){ - args = args || []; - var injectNames = fn.$inject || []; - var i = injectNames.length; - while(i--) { - args.unshift(injector(injectNames[i])); - } - return fn.apply(self, args); - } -} -/** - * THIS IS NOT PUBLIC DOC YET! - * - * @name angular.annotate - * @function - * - * @description - * Annotate the function with injection arguments. This is equivalent to setting the `$inject` - * property as described in {@link guide.di dependency injection}. + * @param {} modules... A list of module functions or their aliases. See + * {@link angular.module}. The `ng` module must be explicitly added. + * @returns {function()} Injector function. See {@link angular.module.AUTO.$injector $injector}. * + * @example + * Typical usage *
- * var MyController = angular.annotate('$location', function($location){ ... });
- * 
+ * // create an injector + * var $injector = angular.injector('ng'); * - * is the same as - * - *
- * var MyController = function($location){ ... };
- * MyController.$inject = ['$location'];
+ *   // use the injector to kick of your application
+ *   // use the type inference to auto inject arguments, or use implicit injection
+ *   $injector.invoke(null, function($rootScope, $compile, $document){
+ *     $compile($document)($rootScope);
+ *     $rootScope.$digest();
+ *   });
  * 
- * - * @param {String|Array} serviceName... zero or more service names to inject into the - * `annotatedFunction`. - * @param {function} annotatedFunction function to annotate with `$inject` - * functions. - * @returns {function} `annotatedFunction` */ -function annotate(services, fn) { - if (services instanceof Array) { - fn.$inject = services; - return fn; - } else { - var i = 0, - length = arguments.length - 1, // last one is the destination function - $inject = arguments[length].$inject = []; - for (; i < length; i++) { - $inject.push(arguments[i]); - } - return arguments[length]; // return the last one - } -} - -function angularServiceInject(name, fn, inject, eager) { - angularService(name, fn, {$inject:inject, $eager:eager}); -} /** - * @returns the $inject property of function. If not found the - * the $inject is computed by looking at the toString of function and - * extracting all arguments which and assuming that they are the - * injection names. + * @ngdoc overview + * @name angular.module.AUTO + * @description + * + * Implicit module which gets automatically added to each {@link angular.module.AUTO.$injector $injector}. */ + var FN_ARGS = /^function\s*[^\(]*\(([^\)]*)\)/m; var FN_ARG_SPLIT = /,/; var FN_ARG = /^\s*(.+?)\s*$/; @@ -148,3 +56,313 @@ function inferInjectionArgs(fn) { } return fn.$inject; } + +/////////////////////////////////////// + +/** + * @ngdoc object + * @name angular.module.AUTO.$injector + * @function + * + * @description + * + * `$injector` is used to retrieve object instances as defined by + * {@link angular.module.AUTO.$provide provider}, instantiate types, invoke methods, + * and load modules. + * + * The following always holds true: + * + *
+ *   var $injector = angular.injector();
+ *   expect($injector.get('$injector')).toBe($injector);
+ *   expect($injector.invoke(null, function($injector){
+ *     return $injector;
+ *   }).toBe($injector);
+ * 
+ * + * # Injection Function Annotation + * + * JavaScript does not have annotations, and annotations are needed for dependency injection. The + * following ways are all valid way of annotating function with injection arguments and are equivalent. + * + *
+ *   // inferred (only works if code not minified/obfuscated)
+ *   $inject.invoke(function(serviceA){});
+ *
+ *   // annotated
+ *   function explicit(serviceA) {};
+ *   explicit.$inject = ['serviceA'];
+ *   $inject.invoke(explicit);
+ *
+ *   // inline
+ *   $inject.invoke(['serviceA', function(serviceA){}]);
+ * 
+ * + * ## Inference + * + * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be + * parsed and the function arguments can be extracted. *NOTE:* This does not work with minfication, and obfuscation + * tools since these tools change the argument names. + * + * ## `$inject` Annotation + * By adding a `$inject` property onto a function the injection parameters can be specified. + * + * ## Inline + * As an array of injection names, where the last item in the array is the function to call. + */ + +/** + * @ngdoc method + * @name angular.module.AUTO.$injector#invoke + * @methodOf angular.module.AUTO.$injector + * + * @description + * Invoke the method and supply the method arguments from the `$injector`. + * + * @param {Object} self The `this` for the invoked method. + * @param {function} fn The function to invoke. The function arguments come form the function annotation. + * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before + * the `$injector` is consulted. + * @return the value returned by the invoked `fn` function. + */ + +/** + * @ngdoc method + * @name angular.module.AUTO.$injector#instantiate + * @methodOf angular.module.AUTO.$injector + * @description + * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies + * all of the arguments to the constructor function as specified by the constructor annotation. + * + * @param {function} Type Annotated constructor function. + * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before + * the `$injector` is consulted. + * @return new instance of `Type`. + */ + + +/** + * @ngdoc object + * @name angular.module.AUTO.$provide + * + * @description + * + * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance. + * The providers share the same name as the instance they create with the `Provide` suffixed to them. + * + * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of + * a service. The Provider can have additional methods which would allow for configuration of the provider. + * + *
+ *   function GreetProvider() {
+ *     var salutation = 'Hello';
+ *
+ *     this.salutation = function(text) {
+ *       salutation = text;
+ *     };
+ *
+ *     this.$get = function() {
+ *       return function (name) {
+ *         return salutation + ' ' + name + '!';
+ *       };
+ *     };
+ *   }
+ *
+ *   describe('Greeter', function(){
+ *
+ *     beforeEach(inject(function($provide) {
+ *       $provide.service('greet', GreetProvider);
+ *     });
+ *
+ *     it('should greet', inject(function(greet) {
+ *       expect(greet('angular')).toEqual('Hello angular!');
+ *     }));
+ *
+ *     it('should allow configuration of salutation', inject(
+ *       function(greetProvider) {
+ *         greetProvider.salutation('Ahoj');
+ *       },
+ *       function(greet) {
+ *         expect(greet('angular')).toEqual('Ahoj angular!');
+ *       }
+ *     )};
+ *
+ *   });
+ * 
+ */ + +/** + * @ngdoc method + * @name angular.module.AUTO.$provide#service + * @methodOf angular.module.AUTO.$provide + * @description + * + * Register a provider for a service. The providers can be retrieved and can have additional configuration methods. + * + * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provide'` key. + * @param {(Object|function())} provider If the provider is: + * + * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using + * {@link angular.module.AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created. + * - `Constructor`: a new instance of the provider will be created using + * {@link angular.module.AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`. + * + */ + +/** + * @ngdoc method + * @name angular.module.AUTO.$provide#factory + * @methodOf angular.module.AUTO.$provide + * @description + * + * A short hand for configuring services if only `$get` method is required. + * + * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provide'` key. + * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for + * `$provide.service(name, {$get:$getFn})`. + */ + + +/** + * @ngdoc method + * @name angular.module.AUTO.$provide#value + * @methodOf angular.module.AUTO.$provide + * @description + * + * A short hand for configuring services if the `$get` method is a constant. + * + * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provide'` key. + * @param {function()} value The $getFn for the instance creation. Internally this is a short hand for + * `$provide.service(name, {$get:function(){ return value; }})`. + */ + + +function createInjector(modulesToLoad, moduleRegistry) { + var cache = {}, + providerSuffix = 'Provider', + path = [], + $injector; + + value('$injector', $injector = { + get: getService, + invoke: invoke, + instantiate: instantiate + }); + value('$provide', { + service: service, + factory: factory, + value: value + }); + + loadModule(modulesToLoad); + + return $injector; + + //////////////////////////////////// + + function service(name, provider) { + if (isFunction(provider)){ + provider = instantiate(provider); + } + if (!provider.$get) { + throw Error('Providers must define $get factory method.'); + } + cache['#' + name + providerSuffix] = provider; + } + + function factory(name, factoryFn) { service(name, { $get:factoryFn }); } + + function value(name, value) { factory(name, valueFn(value)); } + + function getService(value) { + if (typeof value !== 'string') { + throw Error('Service name expected'); + } + var instanceKey = '#' + value, + instance = cache[instanceKey]; + if (instance !== undefined || cache.hasOwnProperty(instanceKey)) { + return instance; + } + try { + path.unshift(value); + var providerKey = instanceKey + providerSuffix, + provider = cache[providerKey]; + if (provider) { + return cache[instanceKey] = invoke(provider, provider.$get); + } else { + throw Error("Unknown provider for '" + path.join("' <- '") + "'."); + } + } finally { + path.shift(); + } + } + + function invoke(self, fn, locals){ + var args = [], + $inject, + length, + key; + + if (typeof fn == 'function') { + $inject = inferInjectionArgs(fn); + length = $inject.length; + } else { + if (isArray(fn)) { + $inject = fn; + length = $inject.length; + fn = $inject[--length]; + } + assertArgFn(fn, 'fn'); + } + + while(length--) { + key = $inject[length]; + args.unshift( + locals && locals.hasOwnProperty(key) + ? locals[key] + : getService($inject[length], path) + ); + } + + // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke + switch (self ? -1 : args.length) { + case 0: return fn(); + case 1: return fn(args[0]); + case 2: return fn(args[0], args[1]); + case 3: return fn(args[0], args[1], args[2]); + case 4: return fn(args[0], args[1], args[2], args[3]); + case 5: return fn(args[0], args[1], args[2], args[3], args[4]); + case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + case 8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); + case 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); + case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); + default: return fn.apply(self, args); + } + } + + function instantiate(Type, locals){ + var Constructor = function(){}, + instance; + Constructor.prototype = Type.prototype; + instance = new Constructor(); + return invoke(instance, Type, locals) || instance; + } + + function loadModule(modulesToLoad){ + forEach(isString(modulesToLoad) ? modulesToLoad.split(',') : modulesToLoad, function(module) { + if (isString(module)) { + if (moduleRegistry[module = trim(module)]) { + module = moduleRegistry[module]; + } else { + throw Error("Module '" + module + "' is not defined!"); + } + } + if (isFunction(module) || isArray(module)) { + invoke(null, module); + } else { + assertArgFn(module, 'module'); + } + }); + } +} diff --git a/src/JSON.js b/src/JSON.js index 7fdbf1a1647e..db1458792885 100644 --- a/src/JSON.js +++ b/src/JSON.js @@ -40,18 +40,20 @@ function fromJson(json, useNative) { try { if (useNative && window.JSON && window.JSON.parse) { obj = JSON.parse(json); - return transformDates(obj); + } else { + obj = parseJson(json, true)(); } - return parser(json, true).primary()(); + return transformDates(obj); } catch (e) { error("fromJson error: ", json, e); throw e; } // TODO make forEach optionally recursive and remove this function + // TODO(misko): remove this once the $http service is checked in. function transformDates(obj) { if (isString(obj) && obj.length === DATE_ISOSTRING_LN) { - return angularString.toDate(obj); + return jsonStringToDate(obj); } else if (isArray(obj) || isObject(obj)) { forEach(obj, function(val, name) { obj[name] = transformDates(val); @@ -61,8 +63,57 @@ function fromJson(json, useNative) { } } -angular.toJson = toJson; -angular.fromJson = fromJson; +var R_ISO8061_STR = /^(\d{4})-(\d\d)-(\d\d)(?:T(\d\d)(?:\:(\d\d)(?:\:(\d\d)(?:\.(\d{3}))?)?)?Z)?$/; +function jsonStringToDate(string){ + var match; + if (isString(string) && (match = string.match(R_ISO8061_STR))){ + var date = new Date(0); + date.setUTCFullYear(match[1], match[2] - 1, match[3]); + date.setUTCHours(match[4]||0, match[5]||0, match[6]||0, match[7]||0); + return date; + } + return string; +} + +function jsonDateToString(date){ + if (!date) return date; + var isoString = date.toISOString ? date.toISOString() : ''; + return (isoString.length==24) + ? isoString + : padNumber(date.getUTCFullYear(), 4) + '-' + + padNumber(date.getUTCMonth() + 1, 2) + '-' + + padNumber(date.getUTCDate(), 2) + 'T' + + padNumber(date.getUTCHours(), 2) + ':' + + padNumber(date.getUTCMinutes(), 2) + ':' + + padNumber(date.getUTCSeconds(), 2) + '.' + + padNumber(date.getUTCMilliseconds(), 3) + 'Z'; +} + +function quoteUnicode(string) { + var chars = ['"']; + for ( var i = 0; i < string.length; i++) { + var code = string.charCodeAt(i); + var ch = string.charAt(i); + switch(ch) { + case '"': chars.push('\\"'); break; + case '\\': chars.push('\\\\'); break; + case '\n': chars.push('\\n'); break; + case '\f': chars.push('\\f'); break; + case '\r': chars.push(ch = '\\r'); break; + case '\t': chars.push(ch = '\\t'); break; + default: + if (32 <= code && code <= 126) { + chars.push(ch); + } else { + var encode = "000" + code.toString(16); + chars.push("\\u" + encode.substring(encode.length - 4)); + } + } + } + chars.push('"'); + return chars.join(''); + } + function toJsonArray(buf, obj, pretty, stack) { if (isObject(obj)) { @@ -83,21 +134,21 @@ function toJsonArray(buf, obj, pretty, stack) { stack.push(obj); } if (obj === null) { - buf.push($null); + buf.push('null'); } else if (obj instanceof RegExp) { - buf.push(angularString.quoteUnicode(obj.toString())); + buf.push(quoteUnicode(obj.toString())); } else if (isFunction(obj)) { return; } else if (isBoolean(obj)) { buf.push('' + obj); } else if (isNumber(obj)) { if (isNaN(obj)) { - buf.push($null); + buf.push('null'); } else { buf.push('' + obj); } } else if (isString(obj)) { - return buf.push(angularString.quoteUnicode(obj)); + return buf.push(quoteUnicode(obj)); } else if (isObject(obj)) { if (isArray(obj)) { buf.push("["); @@ -107,7 +158,7 @@ function toJsonArray(buf, obj, pretty, stack) { var item = obj[i]; if (sep) buf.push(","); if (!(item instanceof RegExp) && (isFunction(item) || isUndefined(item))) { - buf.push($null); + buf.push('null'); } else { toJsonArray(buf, item, pretty, stack); } @@ -118,7 +169,7 @@ function toJsonArray(buf, obj, pretty, stack) { // TODO(misko): maybe in dev mode have a better error reporting? buf.push('DOM_ELEMENT'); } else if (isDate(obj)) { - buf.push(angularString.quoteUnicode(angular.Date.toString(obj))); + buf.push(quoteUnicode(jsonDateToString(obj))); } else { buf.push("{"); if (pretty) buf.push(pretty); @@ -139,7 +190,7 @@ function toJsonArray(buf, obj, pretty, stack) { buf.push(","); if (pretty) buf.push(pretty); } - buf.push(angularString.quote(key)); + buf.push(quoteUnicode(key)); buf.push(":"); toJsonArray(buf, value, childPretty, stack); comma = true; diff --git a/src/Scope.js b/src/Scope.js deleted file mode 100644 index c4b9513b30c3..000000000000 --- a/src/Scope.js +++ /dev/null @@ -1,679 +0,0 @@ -'use strict'; - -/** - * DESIGN NOTES - * - * The design decisions behind the scope ware heavily favored for speed and memory consumption. - * - * The typical use of scope is to watch the expressions, which most of the time return the same - * value as last time so we optimize the operation. - * - * Closures construction is expensive from speed as well as memory: - * - no closures, instead ups prototypical inheritance for API - * - Internal state needs to be stored on scope directly, which means that private state is - * exposed as $$____ properties - * - * Loop operations are optimized by using while(count--) { ... } - * - this means that in order to keep the same order of execution as addition we have to add - * items to the array at the begging (shift) instead of at the end (push) - * - * Child scopes are created and removed often - * - Using array would be slow since inserts in meddle are expensive so we use linked list - * - * There are few watches then a lot of observers. This is why you don't want the observer to be - * implemented in the same way as watch. Watch requires return of initialization function which - * are expensive to construct. - */ - - -function createScope(providers, instanceCache) { - var scope = new Scope(); - (scope.$service = createInjector(scope, providers, instanceCache)).eager(); - return scope; -} - - -/** - * @ngdoc function - * @name angular.scope - * - * @description - * A root scope can be created by calling {@link angular.scope angular.scope()}. Child scopes - * are created using the {@link angular.scope.$new $new()} method. - * (Most scopes are created automatically when compiled HTML template is executed.) - * - * Here is a simple scope snippet to show how you can interact with the scope. - *
-       var scope = angular.scope();
-       scope.salutation = 'Hello';
-       scope.name = 'World';
-
-       expect(scope.greeting).toEqual(undefined);
-
-       scope.$watch('name', function() {
-         this.greeting = this.salutation + ' ' + this.name + '!';
-       }); // initialize the watch
-
-       expect(scope.greeting).toEqual(undefined);
-       scope.name = 'Misko';
-       // still old value, since watches have not been called yet
-       expect(scope.greeting).toEqual(undefined);
-
-       scope.$digest(); // fire all  the watches
-       expect(scope.greeting).toEqual('Hello Misko!');
- * 
- * - * # Inheritance - * A scope can inherit from a parent scope, as in this example: - *
-     var parent = angular.scope();
-     var child = parent.$new();
-
-     parent.salutation = "Hello";
-     child.name = "World";
-     expect(child.salutation).toEqual('Hello');
-
-     child.salutation = "Welcome";
-     expect(child.salutation).toEqual('Welcome');
-     expect(parent.salutation).toEqual('Hello');
- * 
- * - * # Dependency Injection - * See {@link guide/dev_guide.di dependency injection}. - * - * - * @param {Object.=} providers Map of service factory which need to be provided - * for the current scope. Defaults to {@link angular.service}. - * @param {Object.=} instanceCache Provides pre-instantiated services which should - * append/override services provided by `providers`. This is handy when unit-testing and having - * the need to override a default service. - * @returns {Object} Newly created scope. - * - */ -function Scope() { - this.$id = nextUid(); - this.$$phase = this.$parent = this.$$watchers = - this.$$nextSibling = this.$$prevSibling = - this.$$childHead = this.$$childTail = null; - this.$destructor = noop; - this['this'] = this.$root = this; - this.$$asyncQueue = []; - this.$$listeners = {}; -} - -/** - * @ngdoc property - * @name angular.scope.$id - * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for - * debugging. - */ - -/** - * @ngdoc property - * @name angular.scope.$service - * @function - * - * @description - * Provides reference to an instance of {@link angular.injector injector} which can be used to - * retrieve {@link angular.service services}. In general the use of this api is discouraged, - * in favor of proper {@link guide/dev_guide.di dependency injection}. - * - * @returns {function} {@link angular.injector injector} - */ - -/** - * @ngdoc property - * @name angular.scope.$root - * @returns {Scope} The root scope of the current scope hierarchy. - */ - -/** - * @ngdoc property - * @name angular.scope.$parent - * @returns {Scope} The parent scope of the current scope. - */ - - -Scope.prototype = { - /** - * @ngdoc function - * @name angular.scope.$new - * @function - * - * @description - * Creates a new child {@link angular.scope scope}. The new scope can optionally behave as a - * controller. The parent scope will propagate the {@link angular.scope.$digest $digest()} and - * {@link angular.scope.$digest $digest()} events. The scope can be removed from the scope - * hierarchy using {@link angular.scope.$destroy $destroy()}. - * - * {@link angular.scope.$destroy $destroy()} must be called on a scope when it is desired for - * the scope and its child scopes to be permanently detached from the parent and thus stop - * participating in model change detection and listener notification by invoking. - * - * @param {function()=} Class Constructor function which the scope should be applied to the scope. - * @param {...*} curryArguments Any additional arguments which are curried into the constructor. - * See {@link guide/dev_guide.di dependency injection}. - * @returns {Object} The newly created child scope. - * - */ - $new: function(Class, curryArguments) { - var Child = function() {}; // should be anonymous; This is so that when the minifier munges - // the name it does not become random set of chars. These will then show up as class - // name in the debugger. - var child; - Child.prototype = this; - child = new Child(); - child['this'] = child; - child.$$listeners = {}; - child.$parent = this; - child.$id = nextUid(); - child.$$asyncQueue = []; - child.$$phase = child.$$watchers = - child.$$nextSibling = child.$$childHead = child.$$childTail = null; - child.$$prevSibling = this.$$childTail; - if (this.$$childHead) { - this.$$childTail.$$nextSibling = child; - this.$$childTail = child; - } else { - this.$$childHead = this.$$childTail = child; - } - // short circuit if we have no class - if (Class) { - // can't use forEach, we need speed! - var ClassPrototype = Class.prototype; - for(var key in ClassPrototype) { - child[key] = bind(child, ClassPrototype[key]); - } - this.$service.invoke(child, Class, curryArguments); - } - return child; - }, - - /** - * @ngdoc function - * @name angular.scope.$watch - * @function - * - * @description - * Registers a `listener` callback to be executed whenever the `watchExpression` changes. - * - * - The `watchExpression` is called on every call to {@link angular.scope.$digest $digest()} and - * should return the value which will be watched. (Since {@link angular.scope.$digest $digest()} - * reruns when it detects changes the `watchExpression` can execute multiple times per - * {@link angular.scope.$digest $digest()} and should be idempotent.) - * - The `listener` is called only when the value from the current `watchExpression` and the - * previous call to `watchExpression' are not equal. The inequality is determined according to - * {@link angular.equals} function. To save the value of the object for later comparison - * {@link angular.copy} function is used. It also means that watching complex options will - * have adverse memory and performance implications. - * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This - * is achieved by rerunning the watchers until no changes are detected. The rerun iteration - * limit is 100 to prevent infinity loop deadlock. - * - * - * If you want to be notified whenever {@link angular.scope.$digest $digest} is called, - * you can register an `watchExpression` function with no `listener`. (Since `watchExpression`, - * can execute multiple times per {@link angular.scope.$digest $digest} cycle when a change is - * detected, be prepared for multiple calls to your listener.) - * - * - * # Example -
-       var scope = angular.scope();
-       scope.name = 'misko';
-       scope.counter = 0;
-
-       expect(scope.counter).toEqual(0);
-       scope.$watch('name', function(scope, newValue, oldValue) { counter = counter + 1; });
-       expect(scope.counter).toEqual(0);
-
-       scope.$digest();
-       // no variable change
-       expect(scope.counter).toEqual(0);
-
-       scope.name = 'adam';
-       scope.$digest();
-       expect(scope.counter).toEqual(1);
-     
- * - * - * - * @param {(function()|string)} watchExpression Expression that is evaluated on each - * {@link angular.scope.$digest $digest} cycle. A change in the return value triggers a - * call to the `listener`. - * - * - `string`: Evaluated as {@link guide/dev_guide.expressions expression} - * - `function(scope)`: called with current `scope` as a parameter. - * @param {(function()|string)=} listener Callback called whenever the return value of - * the `watchExpression` changes. - * - * - `string`: Evaluated as {@link guide/dev_guide.expressions expression} - * - `function(scope, newValue, oldValue)`: called with current `scope` an previous and - * current values as parameters. - * @returns {function()} Returns a deregistration function for this listener. - */ - $watch: function(watchExp, listener) { - var scope = this, - get = compileToFn(watchExp, 'watch'), - listenFn = compileToFn(listener || noop, 'listener'), - array = scope.$$watchers, - watcher = { - fn: listenFn, - last: Number.NaN, // NaN !== NaN. We used this to force $watch to fire on first run. - get: get, - exp: watchExp - }; - - if (!array) { - array = scope.$$watchers = []; - } - // we use unshift since we use a while loop in $digest for speed. - // the while loop reads in reverse order. - array.unshift(watcher); - - return function() { - angularArray.remove(array, watcher); - }; - }, - - /** - * @ngdoc function - * @name angular.scope.$digest - * @function - * - * @description - * Process all of the {@link angular.scope.$watch watchers} of the current scope and its children. - * Because a {@link angular.scope.$watch watcher}'s listener can change the model, the - * `$digest()` keeps calling the {@link angular.scope.$watch watchers} until no more listeners are - * firing. This means that it is possible to get into an infinite loop. This function will throw - * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 100. - * - * Usually you don't call `$digest()` directly in - * {@link angular.directive.ng:controller controllers} or in {@link angular.directive directives}. - * Instead a call to {@link angular.scope.$apply $apply()} (typically from within a - * {@link angular.directive directive}) will force a `$digest()`. - * - * If you want to be notified whenever `$digest()` is called, - * you can register a `watchExpression` function with {@link angular.scope.$watch $watch()} - * with no `listener`. - * - * You may have a need to call `$digest()` from within unit-tests, to simulate the scope - * life-cycle. - * - * # Example -
-       var scope = angular.scope();
-       scope.name = 'misko';
-       scope.counter = 0;
-
-       expect(scope.counter).toEqual(0);
-       scope.$digest('name', function(scope, newValue, oldValue) { counter = counter + 1; });
-       expect(scope.counter).toEqual(0);
-
-       scope.$digest();
-       // no variable change
-       expect(scope.counter).toEqual(0);
-
-       scope.name = 'adam';
-       scope.$digest();
-       expect(scope.counter).toEqual(1);
-     
- * - */ - $digest: function() { - var watch, value, last, - watchers, - asyncQueue, - length, - dirty, ttl = 100, - next, current, target = this, - watchLog = []; - - if (target.$$phase) { - throw Error(target.$$phase + ' already in progress'); - } - do { - - dirty = false; - current = target; - do { - current.$$phase = '$digest'; - asyncQueue = current.$$asyncQueue; - while(asyncQueue.length) { - try { - current.$eval(asyncQueue.shift()); - } catch (e) { - current.$service('$exceptionHandler')(e); - } - } - if ((watchers = current.$$watchers)) { - // process our watches - length = watchers.length; - while (length--) { - try { - watch = watchers[length]; - // Most common watches are on primitives, in which case we can short - // circuit it with === operator, only when === fails do we use .equals - if ((value = watch.get(current)) !== (last = watch.last) && !equals(value, last)) { - dirty = true; - watch.last = copy(value); - watch.fn(current, value, last); - if (ttl < 5) { - if (!watchLog[4-ttl]) watchLog[4-ttl] = []; - if (isFunction(watch.exp)) { - watchLog[4-ttl].push('fn: ' + (watch.exp.name || watch.exp.toString())); - } else { - watchLog[4-ttl].push(watch.exp); - } - } - } - } catch (e) { - current.$service('$exceptionHandler')(e); - } - } - } - - current.$$phase = null; - - // Insanity Warning: scope depth-first traversal - // yes, this code is a bit crazy, but it works and we have tests to prove it! - // this piece should be kept in sync with the traversal in $broadcast - if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) { - while(current !== target && !(next = current.$$nextSibling)) { - current = current.$parent; - } - } - } while ((current = next)); - - if(!(ttl--)) { - throw Error('100 $digest() iterations reached. Aborting!\n' + - 'Watchers fired in the last 5 iterations: ' + toJson(watchLog)); - } - } while (dirty); - }, - - /** - * @ngdoc function - * @name angular.scope.$destroy - * @function - * - * @description - * Remove the current scope (and all of its children) from the parent scope. Removal implies - * that calls to {@link angular.scope.$digest $digest()} will no longer propagate to the current - * scope and its children. Removal also implies that the current scope is eligible for garbage - * collection. - * - * The destructing scope emits an `$destroy` {@link angular.scope.$emit event}. - * - * The `$destroy()` is usually used by directives such as - * {@link angular.widget.@ng:repeat ng:repeat} for managing the unrolling of the loop. - * - */ - $destroy: function() { - if (this.$root == this) return; // we can't remove the root node; - this.$emit('$destroy'); - var parent = this.$parent; - - if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; - if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; - if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; - if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; - }, - - /** - * @ngdoc function - * @name angular.scope.$eval - * @function - * - * @description - * Executes the `expression` on the current scope returning the result. Any exceptions in the - * expression are propagated (uncaught). This is useful when evaluating engular expressions. - * - * # Example -
-       var scope = angular.scope();
-       scope.a = 1;
-       scope.b = 2;
-
-       expect(scope.$eval('a+b')).toEqual(3);
-       expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
-     
- * - * @param {(string|function())=} expression An angular expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/dev_guide.expressions expression}. - * - `function(scope)`: execute the function with the current `scope` parameter. - * - * @returns {*} The result of evaluating the expression. - */ - $eval: function(expr) { - var fn = isString(expr) - ? expressionCompile(expr) - : expr || noop; - return fn(this); - }, - - /** - * @ngdoc function - * @name angular.scope.$evalAsync - * @function - * - * @description - * Executes the expression on the current scope at a later point in time. - * - * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that: - * - * - it will execute in the current script execution context (before any DOM rendering). - * - at least one {@link angular.scope.$digest $digest cycle} will be performed after - * `expression` execution. - * - * Any exceptions from the execution of the expression are forwarded to the - * {@link angular.service.$exceptionHandler $exceptionHandler} service. - * - * @param {(string|function())=} expression An angular expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/dev_guide.expressions expression}. - * - `function(scope)`: execute the function with the current `scope` parameter. - * - */ - $evalAsync: function(expr) { - this.$$asyncQueue.push(expr); - }, - - /** - * @ngdoc function - * @name angular.scope.$apply - * @function - * - * @description - * `$apply()` is used to execute an expression in angular from outside of the angular framework. - * (For example from browser DOM events, setTimeout, XHR or third party libraries). - * Because we are calling into the angular framework we need to perform proper scope life-cycle - * of {@link angular.service.$exceptionHandler exception handling}, - * {@link angular.scope.$digest executing watches}. - * - * ## Life cycle - * - * # Pseudo-Code of `$apply()` - function $apply(expr) { - try { - return $eval(expr); - } catch (e) { - $exceptionHandler(e); - } finally { - $root.$digest(); - } - } - * - * - * Scope's `$apply()` method transitions through the following stages: - * - * 1. The {@link guide/dev_guide.expressions expression} is executed using the - * {@link angular.scope.$eval $eval()} method. - * 2. Any exceptions from the execution of the expression are forwarded to the - * {@link angular.service.$exceptionHandler $exceptionHandler} service. - * 3. The {@link angular.scope.$watch watch} listeners are fired immediately after the expression - * was executed using the {@link angular.scope.$digest $digest()} method. - * - * - * @param {(string|function())=} exp An angular expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/dev_guide.expressions expression}. - * - `function(scope)`: execute the function with current `scope` parameter. - * - * @returns {*} The result of evaluating the expression. - */ - $apply: function(expr) { - try { - return this.$eval(expr); - } catch (e) { - this.$service('$exceptionHandler')(e); - } finally { - this.$root.$digest(); - } - }, - - /** - * @ngdoc function - * @name angular.scope.$on - * @function - * - * @description - * Listen on events of a given type. See {@link angular.scope.$emit $emit} for discussion of - * event life cycle. - * - * @param {string} name Event name to listen on. - * @param {function(event)} listener Function to call when the event is emitted. - * @returns {function()} Returns a deregistration function for this listener. - * - * The event listener function format is: `function(event)`. The `event` object passed into the - * listener has the following attributes - * - `targetScope` - {Scope}: the scope on which the event was `$emit`-ed or `$broadcast`-ed. - * - `currentScope` - {Scope}: the current scope which is handling the event. - * - `name` - {string}: Name of the event. - * - `cancel` - {function=}: calling `cancel` function will cancel further event propagation - * (available only for events that were `$emit`-ed). - */ - $on: function(name, listener) { - var namedListeners = this.$$listeners[name]; - if (!namedListeners) { - this.$$listeners[name] = namedListeners = []; - } - namedListeners.push(listener); - - return function() { - angularArray.remove(namedListeners, listener); - }; - }, - - - /** - * @ngdoc function - * @name angular.scope.$emit - * @function - * - * @description - * Dispatches an event `name` upwards through the scope hierarchy notifying the - * registered {@link angular.scope.$on} listeners. - * - * The event life cycle starts at the scope on which `$emit` was called. All - * {@link angular.scope.$on listeners} listening for `name` event on this scope get notified. - * Afterwards, the event traverses upwards toward the root scope and calls all registered - * listeners along the way. The event will stop propagating if one of the listeners cancels it. - * - * Any exception emmited from the {@link angular.scope.$on listeners} will be passed - * onto the {@link angular.service.$exceptionHandler $exceptionHandler} service. - * - * @param {string} name Event name to emit. - * @param {...*} args Optional set of arguments which will be passed onto the event listeners. - */ - $emit: function(name, args) { - var empty = [], - namedListeners, - canceled = false, - scope = this, - event = { - name: name, - targetScope: scope, - cancel: function() {canceled = true;} - }, - listenerArgs = concat([event], arguments, 1), - i, length; - - do { - namedListeners = scope.$$listeners[name] || empty; - event.currentScope = scope; - for (i=0, length=namedListeners.length; i * */ -function TzDate(offset, timestamp) { +angular.module.ngMock.TzDate = function (offset, timestamp) { + var self = new Date(0); if (angular.isString(timestamp)) { var tsStr = timestamp; - this.origDate = angular.String.toDate(timestamp); + self.origDate = angular.fromJson(angular.toJson({date:timestamp})).date; - timestamp = this.origDate.getTime(); + timestamp = self.origDate.getTime(); if (isNaN(timestamp)) throw { name: "Illegal Argument", message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string" }; } else { - this.origDate = new Date(timestamp); + self.origDate = new Date(timestamp); } var localOffset = new Date(timestamp).getTimezoneOffset(); - this.offsetDiff = localOffset*60*1000 - offset*1000*60*60; - this.date = new Date(timestamp + this.offsetDiff); + self.offsetDiff = localOffset*60*1000 - offset*1000*60*60; + self.date = new Date(timestamp + self.offsetDiff); - this.getTime = function() { - return this.date.getTime() - this.offsetDiff; + self.getTime = function() { + return self.date.getTime() - self.offsetDiff; }; - this.toLocaleDateString = function() { - return this.date.toLocaleDateString(); + self.toLocaleDateString = function() { + return self.date.toLocaleDateString(); }; - this.getFullYear = function() { - return this.date.getFullYear(); + self.getFullYear = function() { + return self.date.getFullYear(); }; - this.getMonth = function() { - return this.date.getMonth(); + self.getMonth = function() { + return self.date.getMonth(); }; - this.getDate = function() { - return this.date.getDate(); + self.getDate = function() { + return self.date.getDate(); }; - this.getHours = function() { - return this.date.getHours(); + self.getHours = function() { + return self.date.getHours(); }; - this.getMinutes = function() { - return this.date.getMinutes(); + self.getMinutes = function() { + return self.date.getMinutes(); }; - this.getSeconds = function() { - return this.date.getSeconds(); + self.getSeconds = function() { + return self.date.getSeconds(); }; - this.getTimezoneOffset = function() { + self.getTimezoneOffset = function() { return offset * 60; }; - this.getUTCFullYear = function() { - return this.origDate.getUTCFullYear(); + self.getUTCFullYear = function() { + return self.origDate.getUTCFullYear(); }; - this.getUTCMonth = function() { - return this.origDate.getUTCMonth(); + self.getUTCMonth = function() { + return self.origDate.getUTCMonth(); }; - this.getUTCDate = function() { - return this.origDate.getUTCDate(); + self.getUTCDate = function() { + return self.origDate.getUTCDate(); }; - this.getUTCHours = function() { - return this.origDate.getUTCHours(); + self.getUTCHours = function() { + return self.origDate.getUTCHours(); }; - this.getUTCMinutes = function() { - return this.origDate.getUTCMinutes(); + self.getUTCMinutes = function() { + return self.origDate.getUTCMinutes(); }; - this.getUTCSeconds = function() { - return this.origDate.getUTCSeconds(); + self.getUTCSeconds = function() { + return self.origDate.getUTCSeconds(); }; - this.getDay = function() { - return this.origDate.getDay(); + self.getDay = function() { + return self.origDate.getDay(); }; //hide all methods not implemented in this mock that the Date prototype exposes - var self = this, - unimplementedMethods = ['getMilliseconds', 'getUTCDay', + var unimplementedMethods = ['getMilliseconds', 'getUTCDay', 'getUTCMilliseconds', 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', @@ -536,13 +656,138 @@ function TzDate(offset, timestamp) { angular.forEach(unimplementedMethods, function(methodName) { self[methodName] = function() { - throw { - name: "MethodNotImplemented", - message: "Method '" + methodName + "' is not implemented in the TzDate mock" - }; + throw Error("Method '" + methodName + "' is not implemented in the TzDate mock"); }; }); + + return self; } //make "tzDateInstance instanceof Date" return true -TzDate.prototype = Date.prototype; +angular.module.ngMock.TzDate.prototype = Date.prototype; + + +/** + * @ngdoc function + * @name angular.module.ngMock.debug + * @description + * + * *NOTE*: this is not an injectable instance, just a globally available function. + * + * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging. + * + * This method is also available on window, where it can be used to display objects on debug console. + * + * @param {*} object - any object to turn into string. + * @return a serialized string of the argument + */ +angular.module.ngMock.dump = function(object){ + var out; + if (angular.isElement(object)) { + object = angular.element(object); + out = angular.element('
') + angular.forEach(object, function(element){ + out.append(angular.element(element).clone()); + }); + out = out.html(); + } else if (angular.isObject(object)) { + if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) { + out = serializeScope(object); + } else { + out = angular.toJson(object, true); + } + } else { + out = String(object); + } + return out; + + function serializeScope(scope, offset) { + offset = offset || ' '; + var log = [offset + 'Scope(' + scope.$id + '): {']; + for ( var key in scope ) { + if (scope.hasOwnProperty(key) && !key.match(/^(\$|this)/)) { + log.push(' ' + key + ': ' + angular.toJson(scope[key])); + } + } + var child = scope.$$childHead; + while(child) { + log.push(serializeScope(child, offset + ' ')); + child = child.$$nextSibling; + } + log.push('}'); + return log.join('\n' + offset); + } +}; + +window.jstestdriver && (function(window){ + /** + * Global method to output any number of objects into JSTD console. Useful for debugging. + */ + window.dump = function() { + var args = []; + angular.forEach(arguments, function(arg){ + args.push(angular.module.ngMock.dump(arg)); + }); + jstestdriver.console.log.apply(jstestdriver.console, args); + }; +})(window); + + +/** + * @ngdoc function + * @name angular.module.ngMock.inject + * @description + * + * *NOTE*: this is not an injectable instance, just a globally available function on window. + * + * This function wraps a test method into an injectable method. It create one + * {@link angular.module.AUTO.$injector $injector} per test, which is then used for testing. + * + * Here is an example of what a typical jasmine tests looks like with the inject method. + *
+ *   describe('MyApp', function() {
+ *
+ *     // Argument inference is used to inject the $provide service
+ *     beforeEach(inject(function($provide, $rootScope) {
+ *       // $provide service is configured as needed
+ *       $provide.value('version', 'v1.0.1');
+ *       $rootScope.value = 123;
+ *     });
+ *
+ *     // Argument inference is used to inject the $rootScope as well as the version
+ *     it('should provide a version', inject(function($rootScope, version){
+ *       expect(version).toEqual('v1.0.1');
+ *       expect($rootScope.value).toEqual(123);
+ *     });
+ *
+ *     // The inject can also chain the methods
+ *     it('should override a version and test the new version is injected', inject(
+ *       function($provide) {
+ *         $provide.value('version', 'overridden'); // override version here
+ *       },
+ *       function(version) {
+ *         expect(version).toEqual('overridden');
+ *       }
+ *     ));
+ *
+ *   });
+ *
+ * 
+ * + * @param {*} fns... any number of functions which will be injected using the injector. + * @return a method + */ +window.jasmine && (function(window){ + window.inject = function (){ + var blockFns = Array.prototype.slice.call(arguments, 0); + return function(){ + var injector = this.$injector; + if (!injector) { + injector = this.$injector = angular.injector('ng', 'ngMock'); + } + for(var i = 0, ii = blockFns.length; i < ii; i++) { + injector.invoke(this, blockFns[i]); + } + }; + } +})(window); diff --git a/src/angular.suffix b/src/angular.suffix index d38d3130dc35..99726fbd394b 100644 --- a/src/angular.suffix +++ b/src/angular.suffix @@ -1,3 +1,8 @@ + //try to bind to jquery now so that one can write angular.element().read() + //but we will rebind on bootstrap again. + bindJQuery(); + + publishExternalAPI(angular); var config = angularJsConfig(document); diff --git a/src/apis.js b/src/apis.js index c23f9a614f51..6f9b1d0a6a9d 100644 --- a/src/apis.js +++ b/src/apis.js @@ -1,878 +1,5 @@ 'use strict'; -var angularGlobal = { - 'typeOf':function(obj){ - if (obj === null) return $null; - var type = typeof obj; - if (type == $object) { - if (obj instanceof Array) return $array; - if (isDate(obj)) return $date; - if (obj.nodeType == 1) return 'element'; - } - return type; - } -}; - - -/** - * @ngdoc overview - * @name angular.Object - * @function - * - * @description - * A namespace for utility functions used to work with JavaScript objects. These functions are - * exposed in two ways: - * - * * __Angular expressions:__ Functions are bound to all objects and augment the Object type. - * The names of these methods are prefixed with the '$' character in order to minimize naming - * collisions. To call a method, invoke the function without the first argument, for example, - * `myObject.$foo(param2)`. - * - * * __JavaScript code:__ Functions don't augment the Object type and must be invoked as functions - * of `angular.Object` as `angular.Object.foo(myObject, param2)`. - * - * * {@link angular.Object.copy angular.Object.copy()} - Creates a deep copy of the source - * parameter. - * * {@link angular.Object.equals angular.Object.equals()} - Determines if two objects or values - * are equivalent. - * * {@link angular.Object.size angular.Object.size()} - Determines the number of elements in - * strings, arrays, and objects. - */ -var angularCollection = { - 'copy': copy, - 'size': size, - 'equals': equals -}; -var angularObject = { - 'extend': extend -}; - -/** - * @ngdoc overview - * @name angular.Array - * - * @description - * A namespace for utility functions for the manipulation of JavaScript Array objects. - * - * These functions are exposed in two ways: - * - * * __Angular expressions:__ Functions are bound to the Array objects and augment the Array type - * as array methods. The names of these methods are prefixed with the `$` character to minimize - * naming collisions. To call a method, invoke myArrayObject.$foo(params). - * - * Because Array type is a subtype of the Object type, all angular.Object functions augment - * the Array type in Angular expressions as well. - * - * * __JavaScript code:__ Functions do nor augment the Array type and must be invoked as functions - * of `angular.Array` as `angular.Array.foo(myArrayObject, params)`. - * - * The following APIs are built in to the Angular Array object: - * - * * {@link angular.Array.add angular.Array.add()} - Optionally adds a new element to an array. - * * {@link angular.Array.count angular.Array.count()} - Determines the number of elements in an - * array. - * * {@link angular.Array.filter angular.Array.filter()} - Returns the subset of elements specified - * in the filter as a new array. - * * {@link angular.Array.indexOf angular.Array.indexOf()} - Determines the index of an array - * value. - * * {@link angular.Array.limitTo angular.Array.limitTo()} - Creates a sub-array of an existing - * array. - * * {@link angular.Array.orderBy angular.Array.orderBy()} - Orders array elements. - * * {@link angular.Array.remove angular.Array.remove()} - Removes array elements. - * * {@link angular.Array.sum angular.Array.sum()} - Sums the numbers in an array. - */ -var angularArray = { - - - /** - * @ngdoc function - * @name angular.Array.indexOf - * @function - * - * @description - * Determines the index of a `value` in an `array`. - * - * Note: This function is used to augment the `Array` type in Angular expressions. See - * {@link angular.Array} for more information about Angular arrays. - * - * @param {Array} array Array to search. - * @param {*} value Value to search for. - * @returns {number} The position of the element in `array`. The position is 0-based. - * If the value cannot be found, `-1` is returned. - * - * @example - - - -
-
- Index of '{{bookName}}' in the list {{books}} is {{books.$indexOf(bookName)}}. -
-
- - it('should correctly calculate the initial index', function() { - expect(binding('books.$indexOf(bookName)')).toBe('2'); - }); - - it('should recalculate', function() { - input('bookName').enter('foo'); - expect(binding('books.$indexOf(bookName)')).toBe('-1'); - - input('bookName').enter('Moby Dick'); - expect(binding('books.$indexOf(bookName)')).toBe('0'); - }); - -
- */ - 'indexOf': indexOf, - - - /** - * @ngdoc function - * @name angular.Array.sum - * @function - * - * @description - * The `sum` function calculates the sum of all numbers in an `array`. If an `expression` is - * supplied, `sum` evaluates each element in the `array` with the expression and then returns - * the sum of the calculated values. - * - * Note: This function is used to augment the `Array` type in Angular expressions. See - * {@link angular.Array} for more info about Angular arrays. - * - * @param {Array} array The source array. - * @param {(string|function())=} expression Angular expression or a function to be evaluated for - * each element in `array`. The array element becomes the `this` during the evaluation. - * @returns {number} Sum of items in the array. - * - * @example - - - -
NamePhone
{{friend.name}} {{friend.phone}}
- - - - - - - - - - - - - - -
QtyDescriptionCostTotal
{{item.qty * item.cost | currency}}[X]
add itemTotal:{{invoice.items.$sum('qty*cost') | currency}}
-
- - //TODO: these specs are lame because I had to work around issues #164 and #167 - it('should initialize and calculate the totals', function() { - expect(repeater('table.invoice tr', 'item in invoice.items').count()).toBe(3); - expect(repeater('table.invoice tr', 'item in invoice.items').row(1)). - toEqual(['$99.50']); - expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50'); - expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50'); - }); - - it('should add an entry and recalculate', function() { - element('.doc-example-live a:contains("add item")').click(); - using('.doc-example-live tr:nth-child(3)').input('item.qty').enter('20'); - using('.doc-example-live tr:nth-child(3)').input('item.cost').enter('100'); - - expect(repeater('table.invoice tr', 'item in invoice.items').row(2)). - toEqual(['$2,000.00']); - expect(binding("invoice.items.$sum('qty*cost')")).toBe('$2,099.50'); - }); - -
- */ - 'sum':function(array, expression) { - var fn = angularFunction.compile(expression); - var sum = 0; - for (var i = 0; i < array.length; i++) { - var value = 1 * fn(array[i]); - if (!isNaN(value)){ - sum += value; - } - } - return sum; - }, - - - /** - * @ngdoc function - * @name angular.Array.remove - * @function - * - * @description - * Modifies `array` by removing an element from it. The element will be looked up using the - * {@link angular.Array.indexOf indexOf} function on the `array` and only the first instance of - * the element will be removed. - * - * Note: This function is used to augment the `Array` type in Angular expressions. See - * {@link angular.Array} for more information about Angular arrays. - * - * @param {Array} array Array from which an element should be removed. - * @param {*} value Element to be removed. - * @returns {*} The removed element. - * - * @example - - -
    -
  • - {{task}} [X] -
  • -
-
- tasks = {{tasks}} -
- - it('should initialize the task list with for tasks', function() { - expect(repeater('.doc-example-live ul li', 'task in tasks').count()).toBe(4); - expect(repeater('.doc-example-live ul li', 'task in tasks').column('task')). - toEqual(['Learn Angular', 'Read Documentation', 'Check out demos', - 'Build cool applications']); - }); - - it('should initialize the task list with for tasks', function() { - element('.doc-example-live ul li a:contains("X"):first').click(); - expect(repeater('.doc-example-live ul li', 'task in tasks').count()).toBe(3); - - element('.doc-example-live ul li a:contains("X"):last').click(); - expect(repeater('.doc-example-live ul li', 'task in tasks').count()).toBe(2); - - expect(repeater('.doc-example-live ul li', 'task in tasks').column('task')). - toEqual(['Read Documentation', 'Check out demos']); - }); - -
- */ - 'remove':function(array, value) { - var index = indexOf(array, value); - if (index >=0) - array.splice(index, 1); - return value; - }, - - - /** - * @ngdoc function - * @name angular.Array.filter - * @function - * - * @description - * Selects a subset of items from `array` and returns it as a new array. - * - * Note: This function is used to augment the `Array` type in Angular expressions. See - * {@link angular.Array} for more information about Angular arrays. - * - * @param {Array} array The source array. - * @param {string|Object|function()} expression The predicate to be used for selecting items from - * `array`. - * - * Can be one of: - * - * - `string`: Predicate that results in a substring match using the value of `expression` - * string. All strings or objects with string properties in `array` that contain this string - * will be returned. The predicate can be negated by prefixing the string with `!`. - * - * - `Object`: A pattern object can be used to filter specific properties on objects contained - * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items - * which have property `name` containing "M" and property `phone` containing "1". A special - * property name `$` can be used (as in `{$:"text"}`) to accept a match against any - * property of the object. That's equivalent to the simple substring match with a `string` - * as described above. - * - * - `function`: A predicate function can be used to write arbitrary filters. The function is - * called for each element of `array`. The final result is an array of those elements that - * the predicate returned true for. - * - * @example - - -
- - Search: - - - - - - -
NamePhone
{{friend.name}}{{friend.phone}}
-
- Any:
- Name only
- Phone only
- - - - - - -
NamePhone
{{friend.name}}{{friend.phone}}
-
- - it('should search across all fields when filtering with a string', function() { - input('searchText').enter('m'); - expect(repeater('#searchTextResults tr', 'friend in friends').column('name')). - toEqual(['Mary', 'Mike', 'Adam']); - - input('searchText').enter('76'); - expect(repeater('#searchTextResults tr', 'friend in friends').column('name')). - toEqual(['John', 'Julie']); - }); - - it('should search in specific fields when filtering with a predicate object', function() { - input('search.$').enter('i'); - expect(repeater('#searchObjResults tr', 'friend in friends').column('name')). - toEqual(['Mary', 'Mike', 'Julie']); - }); - -
- */ - 'filter':function(array, expression) { - var predicates = []; - predicates.check = function(value) { - for (var j = 0; j < predicates.length; j++) { - if(!predicates[j](value)) { - return false; - } - } - return true; - }; - var search = function(obj, text){ - if (text.charAt(0) === '!') { - return !search(obj, text.substr(1)); - } - switch (typeof obj) { - case "boolean": - case "number": - case "string": - return ('' + obj).toLowerCase().indexOf(text) > -1; - case "object": - for ( var objKey in obj) { - if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) { - return true; - } - } - return false; - case "array": - for ( var i = 0; i < obj.length; i++) { - if (search(obj[i], text)) { - return true; - } - } - return false; - default: - return false; - } - }; - switch (typeof expression) { - case "boolean": - case "number": - case "string": - expression = {$:expression}; - case "object": - for (var key in expression) { - if (key == '$') { - (function() { - var text = (''+expression[key]).toLowerCase(); - if (!text) return; - predicates.push(function(value) { - return search(value, text); - }); - })(); - } else { - (function() { - var path = key; - var text = (''+expression[key]).toLowerCase(); - if (!text) return; - predicates.push(function(value) { - return search(getter(value, path), text); - }); - })(); - } - } - break; - case 'function': - predicates.push(expression); - break; - default: - return array; - } - var filtered = []; - for ( var j = 0; j < array.length; j++) { - var value = array[j]; - if (predicates.check(value)) { - filtered.push(value); - } - } - return filtered; - }, - - - /** - * @ngdoc function - * @name angular.Array.add - * @function - * - * @description - * The `add` function in Angualar is similar to JavaScript's `Array#push` method in that it - * appends a new element to an array. Angular's function differs from the JavaScript method in - * that specifying a value for the function is optional and the default for the function is an - * empty object. - * - * Note: This function is used to augment the `Array` type in Angular expressions. See - * {@link angular.Array} for more information about Angular arrays. - * - * @param {Array} array The array to be expanded. - * @param {*=} [value={}] The value to be appended. - * @returns {Array} The expanded array. - * - * @TODO simplify the example. - * - * @example - * This example shows how you can use the `$add` method to populate an initially empty array - * with objects created from user input. - - - -
- [add empty] - [add 'John'] - [add 'Mary'] - -
    -
  • - - - [X] -
  • -
-
people = {{people}}
-
-
- - beforeEach(function() { - expect(binding('people')).toBe('people = []'); - }); - - it('should create an empty record when "add empty" is clicked', function() { - element('.doc-example-live a:contains("add empty")').click(); - expect(binding('people')).toBe('people = [{\n }]'); - }); - - it('should create a "John" record when "add \'John\'" is clicked', function() { - element('.doc-example-live a:contains("add \'John\'")').click(); - expect(binding('people')).toBe('people = [{\n "name":"John",\n "sex":"male"}]'); - }); - - it('should create a "Mary" record when "add \'Mary\'" is clicked', function() { - element('.doc-example-live a:contains("add \'Mary\'")').click(); - expect(binding('people')).toBe('people = [{\n "name":"Mary",\n "sex":"female"}]'); - }); - - it('should delete a record when "X" is clicked', function() { - element('.doc-example-live a:contains("add empty")').click(); - element('.doc-example-live li a:contains("X"):first').click(); - expect(binding('people')).toBe('people = []'); - }); - -
- */ - 'add':function(array, value) { - array.push(isUndefined(value)? {} : value); - return array; - }, - - - /** - * @ngdoc function - * @name angular.Array.count - * @function - * - * @description - * Determines the number of elements in an array. Provides an option for counting only those - * elements for which a specified `condition` evaluates to `true`. - * - * Note: This function is used to augment the `Array` type in Angular expressions. See - * {@link angular.Array} for more information about Angular arrays. - * - * @param {Array} array The array containing the elements to be counted. - * @param {(function()|string)=} condition A function to be evaluated or - * an Angular expression to be compiled and evaluated. The element being - * iterated over is exposed to the `condition` as `this`. - * @returns {number} Number of elements in the array. If a `condition` is specified, returns - * the number of elements whose `condition` evaluates to `true`. - * - * @example - - -

-         
    -
  • - {{item.name}}: points= - -
  • -
-

Number of items which have one point: {{ items.$count('points==1') }}

-

Number of items which have more than one point: - {{items.$count('points>1')}}

-
- - it('should calculate counts', function() { - expect(binding('items.$count(\'points==1\')')).toEqual('2'); - expect(binding('items.$count(\'points>1\')')).toEqual('1'); - }); - - it('should recalculate when updated', function() { - using('.doc-example-live li:first-child').input('item.points').enter('23'); - expect(binding('items.$count(\'points==1\')')).toEqual('1'); - expect(binding('items.$count(\'points>1\')')).toEqual('2'); - }); - -
- */ - 'count':function(array, condition) { - if (!condition) return array.length; - var fn = angularFunction.compile(condition), count = 0; - forEach(array, function(value){ - if (fn(value)) { - count ++; - } - }); - return count; - }, - - - /** - * @ngdoc function - * @name angular.Array.orderBy - * @function - * - * @description - * Orders a specified `array` by the `expression` predicate. - * - * Note: this function is used to augment the `Array` type in Angular expressions. See - * {@link angular.Array} for more informaton about Angular arrays. - * - * @param {Array} array The array to sort. - * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be - * used by the comparator to determine the order of elements. - * - * Can be one of: - * - * - `function`: Getter function. The result of this function will be sorted using the - * `<`, `=`, `>` operator. - * - `string`: An Angular expression which evaluates to an object to order by, such as 'name' - * to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control - * ascending or descending sort order (for example, +name or -name). - * - `Array`: An array of function or string predicates. The first predicate in the array - * is used for sorting, but when two items are equivalent, the next predicate is used. - * - * @param {boolean=} reverse Reverse the order the array. - * @returns {Array} Sorted copy of the source array. - * - * @example - - - -
-
Sorting predicate = {{predicate}}; reverse = {{reverse}}
-
- [ unsorted ] - - - - - - - - - - - -
Name - (^)Phone NumberAge
{{friend.name}}{{friend.phone}}{{friend.age}}
-
-
- - it('should be reverse ordered by aged', function() { - expect(binding('predicate')).toBe('Sorting predicate = -age; reverse = '); - expect(repeater('table.friend', 'friend in friends').column('friend.age')). - toEqual(['35', '29', '21', '19', '10']); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']); - }); - - it('should reorder the table when user selects different predicate', function() { - element('.doc-example-live a:contains("Name")').click(); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']); - expect(repeater('table.friend', 'friend in friends').column('friend.age')). - toEqual(['35', '10', '29', '19', '21']); - - element('.doc-example-live a:contains("Phone")').click(); - expect(repeater('table.friend', 'friend in friends').column('friend.phone')). - toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']); - }); - -
- */ - 'orderBy':function(array, sortPredicate, reverseOrder) { - if (!sortPredicate) return array; - sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate]; - sortPredicate = map(sortPredicate, function(predicate){ - var descending = false, get = predicate || identity; - if (isString(predicate)) { - if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) { - descending = predicate.charAt(0) == '-'; - predicate = predicate.substring(1); - } - get = expressionCompile(predicate); - } - return reverseComparator(function(a,b){ - return compare(get(a),get(b)); - }, descending); - }); - var arrayCopy = []; - for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); } - return arrayCopy.sort(reverseComparator(comparator, reverseOrder)); - - function comparator(o1, o2){ - for ( var i = 0; i < sortPredicate.length; i++) { - var comp = sortPredicate[i](o1, o2); - if (comp !== 0) return comp; - } - return 0; - } - function reverseComparator(comp, descending) { - return toBoolean(descending) - ? function(a,b){return comp(b,a);} - : comp; - } - function compare(v1, v2){ - var t1 = typeof v1; - var t2 = typeof v2; - if (t1 == t2) { - if (t1 == "string") v1 = v1.toLowerCase(); - if (t1 == "string") v2 = v2.toLowerCase(); - if (v1 === v2) return 0; - return v1 < v2 ? -1 : 1; - } else { - return t1 < t2 ? -1 : 1; - } - } - }, - - - /** - * @ngdoc function - * @name angular.Array.limitTo - * @function - * - * @description - * Creates a new array containing only a specified number of elements in an array. The elements - * are taken from either the beginning or the end of the source array, as specified by the - * value and sign (positive or negative) of `limit`. - * - * Note: This function is used to augment the `Array` type in Angular expressions. See - * {@link angular.Array} for more information about Angular arrays. - * - * @param {Array} array Source array to be limited. - * @param {string|Number} limit The length of the returned array. If the `limit` number is - * positive, `limit` number of items from the beginning of the source array are copied. - * If the number is negative, `limit` number of items from the end of the source array are - * copied. The `limit` will be trimmed if it exceeds `array.length` - * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit` - * elements. - * - * @example - - - -
- Limit {{numbers}} to: -

Output: {{ numbers.$limitTo(limit) | json }}

-
-
- - it('should limit the numer array to first three items', function() { - expect(element('.doc-example-live input[ng\\:model=limit]').val()).toBe('3'); - expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3]'); - }); - - it('should update the output when -3 is entered', function() { - input('limit').enter(-3); - expect(binding('numbers.$limitTo(limit) | json')).toEqual('[7,8,9]'); - }); - - it('should not exceed the maximum size of input array', function() { - input('limit').enter(100); - expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3,4,5,6,7,8,9]'); - }); - -
- */ - limitTo: function(array, limit) { - limit = parseInt(limit, 10); - var out = [], - i, n; - - // check that array is iterable - if (!array || !(array instanceof Array)) - return out; - - // if abs(limit) exceeds maximum length, trim it - if (limit > array.length) - limit = array.length; - else if (limit < -array.length) - limit = -array.length; - - if (limit > 0) { - i = 0; - n = limit; - } else { - i = array.length + limit; - n = array.length; - } - - for (; i
  1. - + {{name}}      
  2. @@ -699,9 +699,9 @@ angularDirective("ng:class-odd", ngClass(function(i){return i % 2 === 0;})); it('should check ng:class-odd and ng:class-even', function() { expect(element('.doc-example-live li:first span').prop('className')). - toMatch(/ng-format-negative/); + toMatch(/odd/); expect(element('.doc-example-live li:last span').prop('className')). - toMatch(/ng-input-indicator-wait/); + toMatch(/even/); }); diff --git a/src/jqLite.js b/src/jqLite.js index 3ed0888aebbf..ec0d327ed37f 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -523,7 +523,7 @@ forEach({ removeEventListenerFn(element, type, bind[type]); delete bind[type]; } else { - angularArray.remove(bind[type].fns, fn); + arrayRemove(bind[type].fns, fn); } } }, diff --git a/src/scenario/Application.js b/src/scenario/Application.js index 1a87141fba66..5e7b8370cede 100644 --- a/src/scenario/Application.js +++ b/src/scenario/Application.js @@ -44,8 +44,8 @@ angular.scenario.Application.prototype.getWindow_ = function() { * * @param {string} url The URL. If it begins with a # then only the * hash of the page is changed. - * @param {Function} loadFn function($window, $document) Called when frame loads. - * @param {Function} errorFn function(error) Called if any error when loading. + * @param {function()} loadFn function($window, $document) Called when frame loads. + * @param {function()} errorFn function(error) Called if any error when loading. */ angular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorFn) { var self = this; @@ -78,7 +78,7 @@ angular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorF * Executes a function in the context of the tested application. Will wait * for all pending angular xhr requests before executing. * - * @param {Function} action The callback to execute. function($window, $document) + * @param {function()} action The callback to execute. function($window, $document) * $document is a jQuery wrapped document. */ angular.scenario.Application.prototype.executeAction = function(action) { @@ -90,8 +90,11 @@ angular.scenario.Application.prototype.executeAction = function(action) { if (!$window.angular) { return action.call(this, $window, _jQuery($window.document)); } - var $browser = $window.angular.service.$browser(); - $browser.notifyWhenNoOutstandingRequests(function() { - action.call(self, $window, _jQuery($window.document)); + var element = $window.angular.element($window.document); + var $injector = element.inheritedData('$injector'); + $injector.invoke(null, function($browser){ + $browser.notifyWhenNoOutstandingRequests(function() { + action.call(self, $window, _jQuery($window.document)); + }); }); }; diff --git a/src/scenario/Describe.js b/src/scenario/Describe.js index 45a5aa630f29..4d52e9d58486 100644 --- a/src/scenario/Describe.js +++ b/src/scenario/Describe.js @@ -45,7 +45,7 @@ angular.scenario.Describe.specId = 0; /** * Defines a block to execute before each it or nested describe. * - * @param {Function} body Body of the block. + * @param {function()} body Body of the block. */ angular.scenario.Describe.prototype.beforeEach = function(body) { this.beforeEachFns.push(body); @@ -54,7 +54,7 @@ angular.scenario.Describe.prototype.beforeEach = function(body) { /** * Defines a block to execute after each it or nested describe. * - * @param {Function} body Body of the block. + * @param {function()} body Body of the block. */ angular.scenario.Describe.prototype.afterEach = function(body) { this.afterEachFns.push(body); @@ -64,7 +64,7 @@ angular.scenario.Describe.prototype.afterEach = function(body) { * Creates a new describe block that's a child of this one. * * @param {string} name Name of the block. Appended to the parent block's name. - * @param {Function} body Body of the block. + * @param {function()} body Body of the block. */ angular.scenario.Describe.prototype.describe = function(name, body) { var child = new angular.scenario.Describe(name, this); @@ -76,7 +76,7 @@ angular.scenario.Describe.prototype.describe = function(name, body) { * Same as describe() but makes ddescribe blocks the only to run. * * @param {string} name Name of the test. - * @param {Function} body Body of the block. + * @param {function()} body Body of the block. */ angular.scenario.Describe.prototype.ddescribe = function(name, body) { var child = new angular.scenario.Describe(name, this); @@ -94,7 +94,7 @@ angular.scenario.Describe.prototype.xdescribe = angular.noop; * Defines a test. * * @param {string} name Name of the test. - * @param {Function} vody Body of the block. + * @param {function()} vody Body of the block. */ angular.scenario.Describe.prototype.it = function(name, body) { this.its.push({ @@ -112,7 +112,7 @@ angular.scenario.Describe.prototype.it = function(name, body) { * Same as it() but makes iit tests the only test to run. * * @param {string} name Name of the test. - * @param {Function} body Body of the block. + * @param {function()} body Body of the block. */ angular.scenario.Describe.prototype.iit = function(name, body) { this.it.apply(this, arguments); diff --git a/src/scenario/Future.js b/src/scenario/Future.js index 598731faf8ee..335dd2bbbb03 100644 --- a/src/scenario/Future.js +++ b/src/scenario/Future.js @@ -4,8 +4,8 @@ * A future action in a spec. * * @param {string} name of the future action - * @param {Function} future callback(error, result) - * @param {Function} Optional. function that returns the file/line number. + * @param {function()} future callback(error, result) + * @param {function()} Optional. function that returns the file/line number. */ angular.scenario.Future = function(name, behavior, line) { this.name = name; @@ -19,7 +19,7 @@ angular.scenario.Future = function(name, behavior, line) { /** * Executes the behavior of the closure. * - * @param {Function} doneFn Callback function(error, result) + * @param {function()} doneFn Callback function(error, result) */ angular.scenario.Future.prototype.execute = function(doneFn) { var self = this; @@ -40,7 +40,7 @@ angular.scenario.Future.prototype.execute = function(doneFn) { /** * Configures the future to convert it's final with a function fn(value) * - * @param {Function} fn function(value) that returns the parsed value + * @param {function()} fn function(value) that returns the parsed value */ angular.scenario.Future.prototype.parsedWith = function(fn) { this.parser = fn; diff --git a/src/scenario/ObjectModel.js b/src/scenario/ObjectModel.js index 76e0201a4d1e..b4dad1a5ef7c 100644 --- a/src/scenario/ObjectModel.js +++ b/src/scenario/ObjectModel.js @@ -121,7 +121,7 @@ angular.scenario.ObjectModel = function(runner) { * Adds a listener for an event. * * @param {string} eventName Name of the event to add a handler for - * @param {Function} listener Function that will be called when event is fired + * @param {function()} listener Function that will be called when event is fired */ angular.scenario.ObjectModel.prototype.on = function(eventName, listener) { eventName = eventName.toLowerCase(); diff --git a/src/scenario/Runner.js b/src/scenario/Runner.js index f3211fd2b958..aeb5196acf59 100644 --- a/src/scenario/Runner.js +++ b/src/scenario/Runner.js @@ -61,7 +61,7 @@ angular.scenario.Runner.prototype.on = function(eventName, listener) { * @see Describe.js * * @param {string} name Name of the block - * @param {Function} body Body of the block + * @param {function()} body Body of the block */ angular.scenario.Runner.prototype.describe = function(name, body) { var self = this; @@ -82,7 +82,7 @@ angular.scenario.Runner.prototype.describe = function(name, body) { * @see Describe.js * * @param {string} name Name of the block - * @param {Function} body Body of the block + * @param {function()} body Body of the block */ angular.scenario.Runner.prototype.ddescribe = function(name, body) { var self = this; @@ -103,7 +103,7 @@ angular.scenario.Runner.prototype.ddescribe = function(name, body) { * @see Describe.js * * @param {string} name Name of the block - * @param {Function} body Body of the block + * @param {function()} body Body of the block */ angular.scenario.Runner.prototype.it = function(name, body) { this.currentDescribe.it(name, body); @@ -115,7 +115,7 @@ angular.scenario.Runner.prototype.it = function(name, body) { * @see Describe.js * * @param {string} name Name of the block - * @param {Function} body Body of the block + * @param {function()} body Body of the block */ angular.scenario.Runner.prototype.iit = function(name, body) { this.currentDescribe.iit(name, body); @@ -127,7 +127,7 @@ angular.scenario.Runner.prototype.iit = function(name, body) { * * @see Describe.js * - * @param {Function} Callback to execute + * @param {function()} Callback to execute */ angular.scenario.Runner.prototype.beforeEach = function(body) { this.currentDescribe.beforeEach(body); @@ -139,7 +139,7 @@ angular.scenario.Runner.prototype.beforeEach = function(body) { * * @see Describe.js * - * @param {Function} Callback to execute + * @param {function()} Callback to execute */ angular.scenario.Runner.prototype.afterEach = function(body) { this.currentDescribe.afterEach(body); @@ -163,7 +163,7 @@ angular.scenario.Runner.prototype.createSpecRunner_ = function(scope) { */ angular.scenario.Runner.prototype.run = function(application) { var self = this; - var $root = angular.scope(); + var $root = angular.injector('ng').get('$rootScope'); angular.extend($root, this); angular.forEach(angular.scenario.Runner.prototype, function(fn, name) { $root[name] = angular.bind(self, fn); diff --git a/src/scenario/Scenario.js b/src/scenario/Scenario.js index 0df74dae229b..a7979342d101 100644 --- a/src/scenario/Scenario.js +++ b/src/scenario/Scenario.js @@ -13,7 +13,7 @@ angular.scenario = angular.scenario || {}; * Defines a new output format. * * @param {string} name the name of the new output format - * @param {Function} fn function(context, runner) that generates the output + * @param {function()} fn function(context, runner) that generates the output */ angular.scenario.output = angular.scenario.output || function(name, fn) { angular.scenario.output[name] = fn; @@ -29,7 +29,7 @@ angular.scenario.output = angular.scenario.output || function(name, fn) { * functions. * * @param {string} name The name of the statement - * @param {Function} fn Factory function(), return a function for + * @param {function()} fn Factory function(), return a function for * the statement. */ angular.scenario.dsl = angular.scenario.dsl || function(name, fn) { @@ -65,7 +65,7 @@ angular.scenario.dsl = angular.scenario.dsl || function(name, fn) { * created for you. * * @param {string} name The name of the matcher - * @param {Function} fn The matching function(expected). + * @param {function()} fn The matching function(expected). */ angular.scenario.matcher = angular.scenario.matcher || function(name, fn) { angular.scenario.matcher[name] = function(expected) { @@ -148,8 +148,8 @@ angular.scenario.setUpAndRun = function(config) { * continueFunction to continute iterating. * * @param {Array} list list to iterate over - * @param {Function} iterator Callback function(value, continueFunction) - * @param {Function} done Callback function(error, result) called when + * @param {function()} iterator Callback function(value, continueFunction) + * @param {function()} done Callback function(error, result) called when * iteration finishes or an error occurs. */ function asyncForEach(list, iterator, done) { diff --git a/src/scenario/SpecRunner.js b/src/scenario/SpecRunner.js index 0d6274a424c2..eacf13a86209 100644 --- a/src/scenario/SpecRunner.js +++ b/src/scenario/SpecRunner.js @@ -18,7 +18,7 @@ angular.scenario.SpecRunner = function() { * based on the describe nesting. * * @param {Object} spec A spec object - * @param {Function} specDone function that is called when the spec finshes. Function(error, index) + * @param {function()} specDone function that is called when the spec finshes. Function(error, index) */ angular.scenario.SpecRunner.prototype.run = function(spec, specDone) { var self = this; @@ -85,8 +85,8 @@ angular.scenario.SpecRunner.prototype.run = function(spec, specDone) { * Note: Do not pass line manually. It happens automatically. * * @param {string} name Name of the future - * @param {Function} behavior Behavior of the future - * @param {Function} line fn() that returns file/line number + * @param {function()} behavior Behavior of the future + * @param {function()} line fn() that returns file/line number */ angular.scenario.SpecRunner.prototype.addFuture = function(name, behavior, line) { var future = new angular.scenario.Future(name, angular.bind(this, behavior), line); @@ -100,8 +100,8 @@ angular.scenario.SpecRunner.prototype.addFuture = function(name, behavior, line) * Note: Do not pass line manually. It happens automatically. * * @param {string} name Name of the future - * @param {Function} behavior Behavior of the future - * @param {Function} line fn() that returns file/line number + * @param {function()} behavior Behavior of the future + * @param {function()} line fn() that returns file/line number */ angular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior, line) { var self = this; diff --git a/src/scenario/angular.suffix b/src/scenario/angular.suffix index 014c2cc9281d..a79fd270c57b 100644 --- a/src/scenario/angular.suffix +++ b/src/scenario/angular.suffix @@ -1,3 +1,5 @@ +publishExternalAPI(angular); + var $runner = new angular.scenario.Runner(window), config = angularJsConfig(document); diff --git a/src/scenario/dsl.js b/src/scenario/dsl.js index db81dd3550d0..12cbdb216f1f 100644 --- a/src/scenario/dsl.js +++ b/src/scenario/dsl.js @@ -38,10 +38,10 @@ angular.scenario.dsl('sleep', function() { * browser().window.path() window.location.pathname * browser().window.search() window.location.search * browser().window.hash() window.location.hash without # prefix - * browser().location().url() see angular.service.$location#url - * browser().location().path() see angular.service.$location#path - * browser().location().search() see angular.service.$location#search - * browser().location().hash() see angular.service.$location#hash + * browser().location().url() see angular.module.ng.$location#url + * browser().location().path() see angular.module.ng.$location#path + * browser().location().search() see angular.module.ng.$location#search + * browser().location().hash() see angular.module.ng.$location#hash */ angular.scenario.dsl('browser', function() { var chain = {}; @@ -103,25 +103,25 @@ angular.scenario.dsl('browser', function() { api.url = function() { return this.addFutureAction('$location.url()', function($window, $document, done) { - done(null, $window.angular.scope().$service('$location').url()); + done(null, $window.angular.injector('ng').get('$location').url()); }); }; api.path = function() { return this.addFutureAction('$location.path()', function($window, $document, done) { - done(null, $window.angular.scope().$service('$location').path()); + done(null, $window.angular.injector('ng').get('$location').path()); }); }; api.search = function() { return this.addFutureAction('$location.search()', function($window, $document, done) { - done(null, $window.angular.scope().$service('$location').search()); + done(null, $window.angular.injector('ng').get('$location').search()); }); }; api.hash = function() { return this.addFutureAction('$location.hash()', function($window, $document, done) { - done(null, $window.angular.scope().$service('$location').hash()); + done(null, $window.angular.injector('ng').get('$location').hash()); }); }; diff --git a/src/scenario/output/Html.js b/src/scenario/output/Html.js index 1c2216b56b09..326928d89136 100644 --- a/src/scenario/output/Html.js +++ b/src/scenario/output/Html.js @@ -160,7 +160,7 @@ angular.scenario.output('html', function(context, runner, model) { * Add an error to a step. * * @param {Object} The JQuery wrapped context - * @param {Function} fn() that should return the file/line number of the error + * @param {function()} fn() that should return the file/line number of the error * @param {Object} the error. */ function addError(context, line, error) { diff --git a/src/Browser.js b/src/service/Browser.js similarity index 91% rename from src/Browser.js rename to src/service/Browser.js index 71252050e68b..2e2c07e8ad95 100644 --- a/src/Browser.js +++ b/src/service/Browser.js @@ -12,19 +12,16 @@ var XHR = window.XMLHttpRequest || function() { /** - * @ngdoc service - * @name angular.service.$browser + * @ngdoc object + * @name angular.module.ng.$browser * @requires $log - * * @description - * Constructor for the object exposed as $browser service. - * * This object has two goals: * * - hide all the global state in the browser caused by the window object * - abstract away all the browser specific features and inconsistencies * - * For tests we provide {@link angular.mock.service.$browser mock implementation} of the `$browser` + * For tests we provide {@link angular.module.ngMock.$browser mock implementation} of the `$browser` * service, which can be used for convenient testing of the application without the interaction with * the real browser apis. */ @@ -78,8 +75,8 @@ function Browser(window, document, body, XHR, $log, $sniffer) { /** * @ngdoc method - * @name angular.service.$browser#xhr - * @methodOf angular.service.$browser + * @name angular.module.ng.$browser#xhr + * @methodOf angular.module.ng.$browser * * @param {string} method Requested method (get|post|put|delete|head|json) * @param {string} url Requested url @@ -157,8 +154,8 @@ function Browser(window, document, body, XHR, $log, $sniffer) { /** * @ngdoc method - * @name angular.service.$browser#addPollFn - * @methodOf angular.service.$browser + * @name angular.module.ng.$browser#addPollFn + * @methodOf angular.module.ng.$browser * * @param {function()} fn Poll function to add * @@ -197,8 +194,8 @@ function Browser(window, document, body, XHR, $log, $sniffer) { /** * @ngdoc method - * @name angular.service.$browser#url - * @methodOf angular.service.$browser + * @name angular.module.ng.$browser#url + * @methodOf angular.module.ng.$browser * * @description * GETTER: @@ -211,7 +208,7 @@ function Browser(window, document, body, XHR, $log, $sniffer) { * Returns its own instance to allow chaining * * NOTE: this api is intended for use only by the $location service. Please use the - * {@link angular.service.$location $location service} to change url. + * {@link angular.module.ng.$location $location service} to change url. * * @param {string} url New url (when used as setter) * @param {boolean=} replace Should new url replace current history record ? @@ -248,8 +245,8 @@ function Browser(window, document, body, XHR, $log, $sniffer) { /** * @ngdoc method - * @name angular.service.$browser#onUrlChange - * @methodOf angular.service.$browser + * @name angular.module.ng.$browser#onUrlChange + * @methodOf angular.module.ng.$browser * @TODO(vojta): refactor to use node's syntax for events * * @description @@ -265,7 +262,7 @@ function Browser(window, document, body, XHR, $log, $sniffer) { * The listener gets called with new url as parameter. * * NOTE: this api is intended for use only by the $location service. Please use the - * {@link angular.service.$location $location service} to monitor url changes in angular apps. + * {@link angular.module.ng.$location $location service} to monitor url changes in angular apps. * * @param {function(string)} listener Listener function to be called when url changes. * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous. @@ -298,8 +295,8 @@ function Browser(window, document, body, XHR, $log, $sniffer) { /** * @ngdoc method - * @name angular.service.$browser#cookies - * @methodOf angular.service.$browser + * @name angular.module.ng.$browser#cookies + * @methodOf angular.module.ng.$browser * * @param {string=} name Cookie name * @param {string=} value Cokkie value @@ -359,8 +356,8 @@ function Browser(window, document, body, XHR, $log, $sniffer) { /** * @ngdoc method - * @name angular.service.$browser#defer - * @methodOf angular.service.$browser + * @name angular.module.ng.$browser#defer + * @methodOf angular.module.ng.$browser * @param {function()} fn A function, who's execution should be defered. * @param {number=} [delay=0] of milliseconds to defer the function execution. * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`. @@ -388,8 +385,8 @@ function Browser(window, document, body, XHR, $log, $sniffer) { /** * THIS DOC IS NOT VISIBLE because ngdocs can't process docs for foo#method.method * - * @name angular.service.$browser#defer.cancel - * @methodOf angular.service.$browser.defer + * @name angular.module.ng.$browser#defer.cancel + * @methodOf angular.module.ng.$browser.defer * * @description * Cancels a defered task identified with `deferId`. @@ -414,8 +411,8 @@ function Browser(window, document, body, XHR, $log, $sniffer) { /** * @ngdoc method - * @name angular.service.$browser#addCss - * @methodOf angular.service.$browser + * @name angular.module.ng.$browser#addCss + * @methodOf angular.module.ng.$browser * * @param {string} url Url to css file * @description @@ -432,8 +429,8 @@ function Browser(window, document, body, XHR, $log, $sniffer) { /** * @ngdoc method - * @name angular.service.$browser#addJs - * @methodOf angular.service.$browser + * @name angular.module.ng.$browser#addJs + * @methodOf angular.module.ng.$browser * * @param {string} url Url to js file * @@ -473,3 +470,10 @@ function Browser(window, document, body, XHR, $log, $sniffer) { return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : href; }; } + +function $BrowserProvider(){ + this.$get = ['$window', '$log', '$sniffer', '$document', + function( $window, $log, $sniffer, $document){ + return new Browser($window, $document, $document.find('body'), XHR, $log, $sniffer); + }]; +} diff --git a/src/service/compiler.js b/src/service/compiler.js new file mode 100644 index 000000000000..8a0dca7d1076 --- /dev/null +++ b/src/service/compiler.js @@ -0,0 +1,356 @@ +'use strict'; + + +function $CompileProvider(){ + this.$get = ['$injector', '$exceptionHandler', '$textMarkup', '$attrMarkup', '$directive', '$widget', + function( $injector, $exceptionHandler, $textMarkup, $attrMarkup, $directive, $widget){ + /** + * Template provides directions an how to bind to a given element. + * It contains a list of init functions which need to be called to + * bind to a new instance of elements. It also provides a list + * of child paths which contain child templates + */ + function Template() { + this.paths = []; + this.children = []; + this.linkFns = []; + this.newScope = false; + } + + Template.prototype = { + link: function(element, scope) { + var childScope = scope, + locals = {$element: element}; + if (this.newScope) { + childScope = isFunction(this.newScope) ? scope.$new(this.newScope(scope)) : scope.$new(); + element.data($$scope, childScope); + } + forEach(this.linkFns, function(fn) { + try { + if (isArray(fn) || fn.$inject) { + $injector.invoke(childScope, fn, locals); + } else { + fn.call(childScope, element); + } + } catch (e) { + $exceptionHandler(e); + } + }); + var i, + childNodes = element[0].childNodes, + children = this.children, + paths = this.paths, + length = paths.length; + for (i = 0; i < length; i++) { + // sometimes `element` can be modified by one of the linker functions in `this.linkFns` + // and childNodes may be added or removed + // TODO: element structure needs to be re-evaluated if new children added + // if the childNode still exists + if (childNodes[paths[i]]) + children[i].link(jqLite(childNodes[paths[i]]), childScope); + else + delete paths[i]; // if child no longer available, delete path + } + }, + + + addLinkFn:function(linkingFn) { + if (linkingFn) { + this.linkFns.push(linkingFn); + } + }, + + + addChild: function(index, template) { + if (template) { + this.paths.push(index); + this.children.push(template); + } + }, + + empty: function() { + return this.linkFns.length === 0 && this.paths.length === 0; + } + }; + + /////////////////////////////////// + //Compiler + ////////////////////////////////// + + /** + * @ngdoc function + * @name angular.module.ng.$compile + * @function + * + * @description + * Compiles a piece of HTML string or DOM into a template and produces a template function, which + * can then be used to link {@link angular.module.ng.$rootScope.Scope scope} and the template together. + * + * The compilation is a process of walking the DOM tree and trying to match DOM elements to + * {@link angular.markup markup}, {@link angular.attrMarkup attrMarkup}, + * {@link angular.widget widgets}, and {@link angular.directive directives}. For each match it + * executes corresponding markup, attrMarkup, widget or directive template function and collects the + * instance functions into a single template function which is then returned. + * + * The template function can then be used once to produce the view or as it is the case with + * {@link angular.widget.@ng:repeat repeater} many-times, in which case each call results in a view + * that is a DOM clone of the original template. + * +
    +          angular.injector('ng').invoke(null, function($rootScope, $compile) {
    +            // Chose one:
    +
    +            // A: compile the entire window.document.
    +            var element = $compile(window.document)($rootScope);
    +
    +            // B: compile a piece of html
    +            var element = $compile('
    click me
    ')($rootScope); + + // C: compile a piece of html and retain reference to both the dom and scope + var element = $compile('
    click me
    ')(scope); + // at this point template was transformed into a view + }); +
    + * + * + * @param {string|DOMElement} element Element or HTML to compile into a template function. + * @returns {function(scope[, cloneAttachFn])} a template function which is used to bind template + * (a DOM element/tree) to a scope. Where: + * + * * `scope` - A {@link angular.module.ng.$rootScope.Scope Scope} to bind to. + * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the + * `template` and call the `cloneAttachFn` function allowing the caller to attach the + * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is + * called as:
    `cloneAttachFn(clonedElement, scope)` where: + * + * * `clonedElement` - is a clone of the original `element` passed into the compiler. + * * `scope` - is the current scope with which the linking function is working with. + * + * Calling the template function returns the element of the template. It is either the original element + * passed in, or the clone of the element if the `cloneAttachFn` is provided. + * + * It is important to understand that the returned scope is "linked" to the view DOM, but no linking + * (instance) functions registered by {@link angular.directive directives} or + * {@link angular.widget widgets} found in the template have been executed yet. This means that the + * view is likely empty and doesn't contain any values that result from evaluation on the scope. To + * bring the view to life, the scope needs to run through a $digest phase which typically is done by + * Angular automatically, except for the case when an application is being + * {@link guide/dev_guide.bootstrap.manual_bootstrap} manually bootstrapped, in which case the + * $digest phase must be invoked by calling {@link angular.module.ng.$rootScope.Scope#$apply}. + * + * If you need access to the bound view, there are two ways to do it: + * + * - If you are not asking the linking function to clone the template, create the DOM element(s) + * before you send them to the compiler and keep this reference around. + *
    +       *     var $injector = angular.injector('ng');
    +       *     var scope = $injector.invoke(null, function($rootScope, $compile){
    +       *       var element = $compile('

    {{total}}

    ')($rootScope); + * }); + *
    + * + * - if on the other hand, you need the element to be cloned, the view reference from the original + * example would not point to the clone, but rather to the original template that was cloned. In + * this case, you can access the clone via the cloneAttachFn: + *
    +       *     var original = angular.element('

    {{total}}

    '), + * scope = someParentScope.$new(), + * clone; + * + * $compile(original)(scope, function(clonedElement, scope) { + * clone = clonedElement; + * //attach the clone to DOM document at the right place + * }); + * + * //now we have reference to the cloned DOM via `clone` + *
    + * + * + * Compiler Methods For Widgets and Directives: + * + * The following methods are available for use when you write your own widgets, directives, + * and markup. (Recall that the compile function's this is a reference to the compiler.) + * + * `compile(element)` - returns linker - + * Invoke a new instance of the compiler to compile a DOM element and return a linker function. + * You can apply the linker function to the original element or a clone of the original element. + * The linker function returns a scope. + * + * * `comment(commentText)` - returns element - Create a comment element. + * + * * `element(elementName)` - returns element - Create an element by name. + * + * * `text(text)` - returns element - Create a text element. + * + * * `descend([set])` - returns descend state (true or false). Get or set the current descend + * state. If true the compiler will descend to children elements. + * + * * `directives([set])` - returns directive state (true or false). Get or set the current + * directives processing state. The compiler will process directives only when directives set to + * true. + * + * For information on how the compiler works, see the + * {@link guide/dev_guide.compiler Angular HTML Compiler} section of the Developer Guide. + */ + function Compiler(markup, attrMarkup, directives, widgets){ + this.markup = markup; + this.attrMarkup = attrMarkup; + this.directives = directives; + this.widgets = widgets; + } + + Compiler.prototype = { + compile: function(templateElement) { + templateElement = jqLite(templateElement); + var index = 0, + template, + parent = templateElement.parent(); + if (templateElement.length > 1) { + // https://github.com/angular/angular.js/issues/338 + throw Error("Cannot compile multiple element roots: " + + jqLite('
    ').append(templateElement.clone()).html()); + } + if (parent && parent[0]) { + parent = parent[0]; + for(var i = 0; i < parent.childNodes.length; i++) { + if (parent.childNodes[i] == templateElement[0]) { + index = i; + } + } + } + template = this.templatize(templateElement, index) || new Template(); + return function(scope, cloneConnectFn){ + assertArg(scope, 'scope'); + // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart + // and sometimes changes the structure of the DOM. + var element = cloneConnectFn + ? JQLitePrototype.clone.call(templateElement) // IMPORTANT!!! + : templateElement; + element.data($$scope, scope); + scope.$element = element; + (cloneConnectFn||noop)(element, scope); + template.link(element, scope); + return element; + }; + }, + + templatize: function(element, elementIndex){ + var self = this, + widget, + fn, + directiveFns = self.directives, + descend = true, + directives = true, + elementName = nodeName_(element), + elementNamespace = elementName.indexOf(':') > 0 ? lowercase(elementName).replace(':', '-') : '', + template, + locals = {$element: element}, + selfApi = { + compile: bind(self, self.compile), + descend: function(value){ if(isDefined(value)) descend = value; return descend;}, + directives: function(value){ if(isDefined(value)) directives = value; return directives;}, + scope: function(value){ if(isDefined(value)) template.newScope = template.newScope || value; return template.newScope;} + }; + element.addClass(elementNamespace); + template = new Template(); + eachAttribute(element, function(value, name){ + if (!widget) { + if ((widget = self.widgets('@' + name))) { + element.addClass('ng-attr-widget'); + if (isFunction(widget) && !widget.$inject) { + widget.$inject = ['$value', '$element']; + } + locals.$value = value; + } + } + }); + if (!widget) { + if ((widget = self.widgets(elementName))) { + if (elementNamespace) + element.addClass('ng-widget'); + if (isFunction(widget) && !widget.$inject) { + widget.$inject = ['$element']; + } + } + } + if (widget) { + descend = false; + directives = false; + var parent = element.parent(); + template.addLinkFn($injector.invoke(selfApi, widget, locals)); + if (parent && parent[0]) { + element = jqLite(parent[0].childNodes[elementIndex]); + } + } + if (descend){ + // process markup for text nodes only + for(var i=0, child=element[0].childNodes; + i + * // Filter registration + * function MyModule($provide, $filterProvider) { + * // create a service to demonstrate injection (not always needed) + * $provide.value('greet', function(name){ + * return 'Hello ' + name + '!': + * }); + * + * // register a filter factory which uses the + * // greet service to demonstrate DI. + * $filterProvider.register('greet', function(greet){ + * // return the filter function which uses the greet service + * // to generate salutation + * return function(text) { + * // filters need to be forgiving so check input validity + * return text && greet(text) || text; + * }; + * }; + * } + * + * + * The filter function is registered with the `$injector` under the filter name suffixe with `$Filter`. + *
    + *   it('should be the same instance', inject(
    + *     function($filterProvider) {
    + *       $filterProvider.register('reverse', function(){
    + *         return ...;
    + *       });
    + *     },
    + *     function($filter, revers$Filter) {
    + *       expect($filter('reverse')).toBe(reverse$Filter);
    + *     });
    + * 
    + * + * + * For more information about how angular filters work, and how to create your own filters, see + * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer + * Guide. + */ +/** + * @ngdoc method + * @name angular.module.ng.$filterProvider#register + * @methodOf angular.module.ng.$filterProvider + * @description + * Register filter factory function. + * + * @param {String} name Name of the filter. + * @param {function} fn The filter factory function which is injectable. + */ + + +/** + * @ngdoc function + * @name angular.module.ng.$filter + * @function + * @description + * Filters are used for formatting data displayed to the user. + * + * The general syntax in templates is as follows: + * + * {{ expression | [ filter_name ] }} + * + * @param {String} name Name of the filter function to retrieve + * @return {Function} the filter function + */ +$FilterProvider.$inject = ['$provide']; +function $FilterProvider($provide) { + var suffix = '$Filter'; + + function register(name, factory) { + return $provide.factory(name + suffix, factory); + }; + this.register = register; + + this.$get = ['$injector', function($injector) { + return function(name) { + return $injector.get(name + suffix); + } + }]; + + //////////////////////////////////////// + + register('currency', currencyFilter); + register('date', dateFilter); + register('filter', filterFilter); + register('html', htmlFilter); + register('json', jsonFilter); + register('limitTo', limitToFilter); + register('linky', linkyFilter); + register('lowercase', lowercaseFilter); + register('number', numberFilter); + register('orderBy', orderByFilter); + register('uppercase', uppercaseFilter); +} diff --git a/src/service/filter/filter.js b/src/service/filter/filter.js new file mode 100644 index 000000000000..61cfc80fd928 --- /dev/null +++ b/src/service/filter/filter.js @@ -0,0 +1,164 @@ +'use strict'; + +/** + * @ngdoc filter + * @name angular.module.ng.$filter.filter + * @function + * + * @description + * Selects a subset of items from `array` and returns it as a new array. + * + * Note: This function is used to augment the `Array` type in Angular expressions. See + * {@link angular.module.ng.$filter} for more information about Angular arrays. + * + * @param {Array} array The source array. + * @param {string|Object|function()} expression The predicate to be used for selecting items from + * `array`. + * + * Can be one of: + * + * - `string`: Predicate that results in a substring match using the value of `expression` + * string. All strings or objects with string properties in `array` that contain this string + * will be returned. The predicate can be negated by prefixing the string with `!`. + * + * - `Object`: A pattern object can be used to filter specific properties on objects contained + * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items + * which have property `name` containing "M" and property `phone` containing "1". A special + * property name `$` can be used (as in `{$:"text"}`) to accept a match against any + * property of the object. That's equivalent to the simple substring match with a `string` + * as described above. + * + * - `function`: A predicate function can be used to write arbitrary filters. The function is + * called for each element of `array`. The final result is an array of those elements that + * the predicate returned true for. + * + * @example + + +
    + + Search: + + + + + + +
    NamePhone
    {{friend.name}}{{friend.phone}}
    +
    + Any:
    + Name only
    + Phone only
    + + + + + + +
    NamePhone
    {{friend.name}}{{friend.phone}}
    +
    + + it('should search across all fields when filtering with a string', function() { + input('searchText').enter('m'); + expect(repeater('#searchTextResults tr', 'friend in friends').column('name')). + toEqual(['Mary', 'Mike', 'Adam']); + + input('searchText').enter('76'); + expect(repeater('#searchTextResults tr', 'friend in friends').column('name')). + toEqual(['John', 'Julie']); + }); + + it('should search in specific fields when filtering with a predicate object', function() { + input('search.$').enter('i'); + expect(repeater('#searchObjResults tr', 'friend in friends').column('name')). + toEqual(['Mary', 'Mike', 'Julie']); + }); + +
    + */ +function filterFilter() { + return function(array, expression) { + if (!(array instanceof Array)) return array; + var predicates = []; + predicates.check = function(value) { + for (var j = 0; j < predicates.length; j++) { + if(!predicates[j](value)) { + return false; + } + } + return true; + }; + var search = function(obj, text){ + if (text.charAt(0) === '!') { + return !search(obj, text.substr(1)); + } + switch (typeof obj) { + case "boolean": + case "number": + case "string": + return ('' + obj).toLowerCase().indexOf(text) > -1; + case "object": + for ( var objKey in obj) { + if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) { + return true; + } + } + return false; + case "array": + for ( var i = 0; i < obj.length; i++) { + if (search(obj[i], text)) { + return true; + } + } + return false; + default: + return false; + } + }; + switch (typeof expression) { + case "boolean": + case "number": + case "string": + expression = {$:expression}; + case "object": + for (var key in expression) { + if (key == '$') { + (function() { + var text = (''+expression[key]).toLowerCase(); + if (!text) return; + predicates.push(function(value) { + return search(value, text); + }); + })(); + } else { + (function() { + var path = key; + var text = (''+expression[key]).toLowerCase(); + if (!text) return; + predicates.push(function(value) { + return search(getter(value, path), text); + }); + })(); + } + } + break; + case 'function': + predicates.push(expression); + break; + default: + return array; + } + var filtered = []; + for ( var j = 0; j < array.length; j++) { + var value = array[j]; + if (predicates.check(value)) { + filtered.push(value); + } + } + return filtered; + } +} diff --git a/src/filters.js b/src/service/filter/filters.js similarity index 80% rename from src/filters.js rename to src/service/filter/filters.js index b9c3d2efd98a..3e7f8e375a17 100644 --- a/src/filters.js +++ b/src/service/filter/filters.js @@ -1,35 +1,8 @@ 'use strict'; -/** - * @ngdoc overview - * @name angular.filter - * @description - * - * Filters are used for formatting data displayed to the user. - * - * The general syntax in templates is as follows: - * - * {{ expression | [ filter_name ] }} - * - * Following is the list of built-in angular filters: - * - * * {@link angular.filter.currency currency} - * * {@link angular.filter.date date} - * * {@link angular.filter.html html} - * * {@link angular.filter.json json} - * * {@link angular.filter.linky linky} - * * {@link angular.filter.lowercase lowercase} - * * {@link angular.filter.number number} - * * {@link angular.filter.uppercase uppercase} - * - * For more information about how angular filters work, and how to create your own filters, see - * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer - * Guide. - */ - /** * @ngdoc filter - * @name angular.filter.currency + * @name angular.module.ng.$filter.currency * @function * * @description @@ -40,8 +13,6 @@ * @param {string=} symbol Currency symbol or identifier to be displayed. * @returns {string} Formatted number. * - * @css ng-format-negative - * When the value is negative, this css class is applied to the binding making it (by default) red. * * @example @@ -66,23 +37,23 @@ input('amount').enter('-1234'); expect(binding('amount | currency')).toBe('($1,234.00)'); expect(binding('amount | currency:"USD$"')).toBe('(USD$1,234.00)'); - expect(element('.doc-example-live .ng-binding').prop('className')). - toMatch(/ng-format-negative/); }); */ -angularFilter.currency = function(amount, currencySymbol){ - var formats = this.$service('$locale').NUMBER_FORMATS; - this.$element.toggleClass('ng-format-negative', amount < 0); - if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM; - return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2). - replace(/\u00A4/g, currencySymbol); -}; +currencyFilter.$inject = ['$locale']; +function currencyFilter($locale) { + var formats = $locale.NUMBER_FORMATS; + return function(amount, currencySymbol){ + if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM; + return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2). + replace(/\u00A4/g, currencySymbol); + }; +} /** * @ngdoc filter - * @name angular.filter.number + * @name angular.module.ng.$filter.number * @function * * @description @@ -126,14 +97,17 @@ angularFilter.currency = function(amount, currencySymbol){ */ -var DECIMAL_SEP = '.'; -angularFilter.number = function(number, fractionSize) { - var formats = this.$service('$locale').NUMBER_FORMATS; - return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, - formats.DECIMAL_SEP, fractionSize); -}; +numberFilter.$inject = ['$locale']; +function numberFilter($locale) { + var formats = $locale.NUMBER_FORMATS; + return function(number, fractionSize) { + return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP, + fractionSize); + }; +} +var DECIMAL_SEP = '.'; function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { if (isNaN(number) || !isFinite(number)) return ''; @@ -260,14 +234,12 @@ var DATE_FORMATS = { Z: timeZoneGetter }; -var GET_TIME_ZONE = /[A-Z]{3}(?![+\-])/, - DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/, - OPERA_TOSTRING_PATTERN = /^[\d].*Z$/, +var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/, NUMBER_STRING = /^\d+$/; /** * @ngdoc filter - * @name angular.filter.date + * @name angular.module.ng.$filter.date * @function * * @description @@ -343,54 +315,56 @@ var GET_TIME_ZONE = /[A-Z]{3}(?![+\-])/, */ -angularFilter.date = function(date, format) { - var $locale = this.$service('$locale'), - text = '', - parts = [], - fn, match; - - format = format || 'mediumDate' - format = $locale.DATETIME_FORMATS[format] || format; - if (isString(date)) { - if (NUMBER_STRING.test(date)) { - date = parseInt(date, 10); - } else { - date = angularString.toDate(date); +dateFilter.$inject = ['$locale']; +function dateFilter($locale) { + return function(date, format) { + var text = '', + parts = [], + fn, match; + + format = format || 'mediumDate' + format = $locale.DATETIME_FORMATS[format] || format; + if (isString(date)) { + if (NUMBER_STRING.test(date)) { + date = parseInt(date, 10); + } else { + date = jsonStringToDate(date); + } } - } - if (isNumber(date)) { - date = new Date(date); - } + if (isNumber(date)) { + date = new Date(date); + } - if (!isDate(date)) { - return date; - } + if (!isDate(date)) { + return date; + } - while(format) { - match = DATE_FORMATS_SPLIT.exec(format); - if (match) { - parts = concat(parts, match, 1); - format = parts.pop(); - } else { - parts.push(format); - format = null; + while(format) { + match = DATE_FORMATS_SPLIT.exec(format); + if (match) { + parts = concat(parts, match, 1); + format = parts.pop(); + } else { + parts.push(format); + format = null; + } } - } - forEach(parts, function(value){ - fn = DATE_FORMATS[value]; - text += fn ? fn(date, $locale.DATETIME_FORMATS) - : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); - }); + forEach(parts, function(value){ + fn = DATE_FORMATS[value]; + text += fn ? fn(date, $locale.DATETIME_FORMATS) + : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); + }); - return text; -}; + return text; + }; +} /** * @ngdoc filter - * @name angular.filter.json + * @name angular.module.ng.$filter.json * @function * * @description @@ -417,35 +391,38 @@ angularFilter.date = function(date, format) { * */ -angularFilter.json = function(object) { - this.$element.addClass("ng-monospace"); - return toJson(object, true, /^(\$|this$)/); -}; +function jsonFilter() { + return function(object) { + return toJson(object, true); + }; +} /** * @ngdoc filter - * @name angular.filter.lowercase + * @name angular.module.ng.$filter.lowercase * @function - * + * @description + * Converts string to lowercase. * @see angular.lowercase */ -angularFilter.lowercase = lowercase; +var lowercaseFilter = valueFn(lowercase); /** * @ngdoc filter - * @name angular.filter.uppercase + * @name angular.module.ng.$filter.uppercase * @function - * + * @description + * Converts string to uppercase. * @see angular.uppercase */ -angularFilter.uppercase = uppercase; +var uppercaseFilter = valueFn(uppercase); /** * @ngdoc filter - * @name angular.filter.html + * @name angular.module.ng.$filter.html * @function * * @description @@ -537,14 +514,17 @@ angularFilter.uppercase = uppercase; */ -angularFilter.html = function(html, option){ - return new HTML(html, option); -}; +//TODO(misko): turn sensitization into injectable service +function htmlFilter() { + return function(html, option){ + return new HTML(html, option); + }; +} /** * @ngdoc filter - * @name angular.filter.linky + * @name angular.module.ng.$filter.linky * @function * * @description @@ -619,29 +599,31 @@ angularFilter.html = function(html, option){ */ -var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/, - MAILTO_REGEXP = /^mailto:/; - -angularFilter.linky = function(text) { - if (!text) return text; - var match; - var raw = text; - var html = []; - var writer = htmlSanitizeWriter(html); - var url; - var i; - while ((match = raw.match(LINKY_URL_REGEXP))) { - // We can not end in these as they are sometimes found at the end of the sentence - url = match[0]; - // if we did not match ftp/http/mailto then assume mailto - if (match[2] == match[3]) url = 'mailto:' + url; - i = match.index; - writer.chars(raw.substr(0, i)); - writer.start('a', {href:url}); - writer.chars(match[0].replace(MAILTO_REGEXP, '')); - writer.end('a'); - raw = raw.substring(i + match[0].length); - } - writer.chars(raw); - return new HTML(html.join('')); +function linkyFilter() { + var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/, + MAILTO_REGEXP = /^mailto:/; + + return function(text) { + if (!text) return text; + var match; + var raw = text; + var html = []; + var writer = htmlSanitizeWriter(html); + var url; + var i; + while ((match = raw.match(LINKY_URL_REGEXP))) { + // We can not end in these as they are sometimes found at the end of the sentence + url = match[0]; + // if we did not match ftp/http/mailto then assume mailto + if (match[2] == match[3]) url = 'mailto:' + url; + i = match.index; + writer.chars(raw.substr(0, i)); + writer.start('a', {href:url}); + writer.chars(match[0].replace(MAILTO_REGEXP, '')); + writer.end('a'); + raw = raw.substring(i + match[0].length); + } + writer.chars(raw); + return new HTML(html.join('')); + }; }; diff --git a/src/service/filter/limitTo.js b/src/service/filter/limitTo.js new file mode 100644 index 000000000000..a250bd3bd606 --- /dev/null +++ b/src/service/filter/limitTo.js @@ -0,0 +1,87 @@ +'use strict'; + +/** + * @ngdoc function + * @name angular.module.ng.$filter.limitTo + * @function + * + * @description + * Creates a new array containing only a specified number of elements in an array. The elements + * are taken from either the beginning or the end of the source array, as specified by the + * value and sign (positive or negative) of `limit`. + * + * Note: This function is used to augment the `Array` type in Angular expressions. See + * {@link angular.module.ng.$filter} for more information about Angular arrays. + * + * @param {Array} array Source array to be limited. + * @param {string|Number} limit The length of the returned array. If the `limit` number is + * positive, `limit` number of items from the beginning of the source array are copied. + * If the number is negative, `limit` number of items from the end of the source array are + * copied. The `limit` will be trimmed if it exceeds `array.length` + * @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit` + * elements. + * + * @example + + + +
    + Limit {{numbers}} to: +

    Output: {{ numbers | limitTo:limit | json }}

    +
    +
    + + it('should limit the numer array to first three items', function() { + expect(element('.doc-example-live input[ng\\:model=limit]').val()).toBe('3'); + expect(binding('numbers | limitTo:limit | json')).toEqual('[1,2,3]'); + }); + + it('should update the output when -3 is entered', function() { + input('limit').enter(-3); + expect(binding('numbers | limitTo:limit | json')).toEqual('[7,8,9]'); + }); + + it('should not exceed the maximum size of input array', function() { + input('limit').enter(100); + expect(binding('numbers | limitTo:limit | json')).toEqual('[1,2,3,4,5,6,7,8,9]'); + }); + +
    + */ +function limitToFilter(){ + return function(array, limit) { + if (!(array instanceof Array)) return array; + limit = parseInt(limit, 10); + var out = [], + i, n; + + // check that array is iterable + if (!array || !(array instanceof Array)) + return out; + + // if abs(limit) exceeds maximum length, trim it + if (limit > array.length) + limit = array.length; + else if (limit < -array.length) + limit = -array.length; + + if (limit > 0) { + i = 0; + n = limit; + } else { + i = array.length + limit; + n = array.length; + } + + for (; i} expression A predicate to be + * used by the comparator to determine the order of elements. + * + * Can be one of: + * + * - `function`: Getter function. The result of this function will be sorted using the + * `<`, `=`, `>` operator. + * - `string`: An Angular expression which evaluates to an object to order by, such as 'name' + * to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control + * ascending or descending sort order (for example, +name or -name). + * - `Array`: An array of function or string predicates. The first predicate in the array + * is used for sorting, but when two items are equivalent, the next predicate is used. + * + * @param {boolean=} reverse Reverse the order the array. + * @returns {Array} Sorted copy of the source array. + * + * @example + + + +
    +
    Sorting predicate = {{predicate}}; reverse = {{reverse}}
    +
    + [ unsorted ] + + + + + + + + + + + +
    Name + (^)Phone NumberAge
    {{friend.name}}{{friend.phone}}{{friend.age}}
    +
    +
    + + it('should be reverse ordered by aged', function() { + expect(binding('predicate')).toBe('Sorting predicate = -age; reverse = '); + expect(repeater('table.friend', 'friend in friends').column('friend.age')). + toEqual(['35', '29', '21', '19', '10']); + expect(repeater('table.friend', 'friend in friends').column('friend.name')). + toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']); + }); + + it('should reorder the table when user selects different predicate', function() { + element('.doc-example-live a:contains("Name")').click(); + expect(repeater('table.friend', 'friend in friends').column('friend.name')). + toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']); + expect(repeater('table.friend', 'friend in friends').column('friend.age')). + toEqual(['35', '10', '29', '19', '21']); + + element('.doc-example-live a:contains("Phone")').click(); + expect(repeater('table.friend', 'friend in friends').column('friend.phone')). + toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']); + expect(repeater('table.friend', 'friend in friends').column('friend.name')). + toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']); + }); + +
    + */ +orderByFilter.$inject = ['$parse']; +function orderByFilter($parse){ + return function(array, sortPredicate, reverseOrder) { + if (!(array instanceof Array)) return array; + if (!sortPredicate) return array; + sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate]; + sortPredicate = map(sortPredicate, function(predicate){ + var descending = false, get = predicate || identity; + if (isString(predicate)) { + if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) { + descending = predicate.charAt(0) == '-'; + predicate = predicate.substring(1); + } + get = $parse(predicate); + } + return reverseComparator(function(a,b){ + return compare(get(a),get(b)); + }, descending); + }); + var arrayCopy = []; + for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); } + return arrayCopy.sort(reverseComparator(comparator, reverseOrder)); + + function comparator(o1, o2){ + for ( var i = 0; i < sortPredicate.length; i++) { + var comp = sortPredicate[i](o1, o2); + if (comp !== 0) return comp; + } + return 0; + } + function reverseComparator(comp, descending) { + return toBoolean(descending) + ? function(a,b){return comp(b,a);} + : comp; + } + function compare(v1, v2){ + var t1 = typeof v1; + var t2 = typeof v2; + if (t1 == t2) { + if (t1 == "string") v1 = v1.toLowerCase(); + if (t1 == "string") v2 = v2.toLowerCase(); + if (v1 === v2) return 0; + return v1 < v2 ? -1 : 1; + } else { + return t1 < t2 ? -1 : 1; + } + } + } +} diff --git a/src/service/formFactory.js b/src/service/formFactory.js index e7ff42ff804a..eb33eb4ac799 100644 --- a/src/service/formFactory.js +++ b/src/service/formFactory.js @@ -1,21 +1,21 @@ 'use strict'; /** - * @ngdoc service - * @name angular.service.$formFactory + * @ngdoc object + * @name angular.module.ng.$formFactory * * @description - * Use `$formFactory` to create a new instance of a {@link guide/dev_guide.forms form} + * Use `$formFactory` to create a new instance of a {@link angular.module.ng.$formFactory.Form Form} * controller or to find the nearest form instance for a given DOM element. * * The form instance is a collection of widgets, and is responsible for life cycle and validation * of widget. * - * Keep in mind that both form and widget instances are {@link api/angular.scope scopes}. + * Keep in mind that both form and widget instances are {@link api/angular.module.ng.$rootScope.Scope scopes}. * * @param {Form=} parentForm The form which should be the parent form of the new form controller. * If none specified default to the `rootForm`. - * @returns {Form} A new form instance. + * @returns {Form} A new {@link angular.module.ng.$formFactory.Form Form} instance. * * @example * @@ -29,9 +29,9 @@ this.html = 'Hello World!'; } - function HTMLEditorWidget(element) { + HTMLEditorWidget.$inject = ['$element', 'html$Filter']; + function HTMLEditorWidget(element, htmlFilter) { var self = this; - var htmlFilter = angular.filter('html'); this.$parseModel = function() { // need to protect for script injection @@ -59,7 +59,7 @@ } angular.directive('ng:contenteditable', function() { - function linkFn($formFactory, element) { + return ['$formFactory', '$element', function ($formFactory, element) { var exp = element.attr('ng:contenteditable'), form = $formFactory.forElement(element), widget; @@ -68,14 +68,12 @@ scope: this, model: exp, controller: HTMLEditorWidget, - controllerArgs: [element]}); + controllerArgs: {$element: element}}); // if the element is destroyed, then we need to notify the form. element.bind('$destroy', function() { widget.$destroy(); }); - } - linkFn.$inject = ['$formFactory']; - return linkFn; + }]; }); @@ -96,297 +94,311 @@ */ -angularServiceInject('$formFactory', function() { +/** + * @ngdoc object + * @name angular.module.ng.$formFactory.Form + * @description + * The `Form` is a controller which keeps track of the validity of the widgets contained within it. + */ + +function $FormFactoryProvider() { + var $parse; + this.$get = ['$rootScope', '$parse', function($rootScope, $parse_) { + $parse = $parse_; + /** + * @ngdoc proprety + * @name rootForm + * @propertyOf angular.module.ng.$formFactory + * @description + * Static property on `$formFactory` + * + * Each application ({@link guide/dev_guide.scopes.internals root scope}) gets a root form which + * is the top-level parent of all forms. + */ + formFactory.rootForm = formFactory($rootScope); + + + /** + * @ngdoc method + * @name forElement + * @methodOf angular.module.ng.$formFactory + * @description + * Static method on `$formFactory` service. + * + * Retrieve the closest form for a given element or defaults to the `root` form. Used by the + * {@link angular.widget.form form} element. + * @param {Element} element The element where the search for form should initiate. + */ + formFactory.forElement = function(element) { + return element.inheritedData('$form') || formFactory.rootForm; + }; + return formFactory; + + function formFactory(parent) { + return (parent || formFactory.rootForm).$new(FormController); + } + + }]; + + function propertiesUpdate(widget) { + widget.$valid = !(widget.$invalid = + !(widget.$readonly || widget.$disabled || equals(widget.$error, {}))); + } /** - * @ngdoc proprety - * @name rootForm - * @propertyOf angular.service.$formFactory + * @ngdoc property + * @name $error + * @propertyOf angular.module.ng.$formFactory.Form * @description - * Static property on `$formFactory` + * Property of the form and widget instance. * - * Each application ({@link guide/dev_guide.scopes.internals root scope}) gets a root form which - * is the top-level parent of all forms. + * Summary of all of the errors on the page. If a widget emits `$invalid` with `REQUIRED` key, + * then the `$error` object will have a `REQUIRED` key with an array of widgets which have + * emitted this key. `form.$error.REQUIRED == [ widget ]`. */ - formFactory.rootForm = formFactory(this); - /** - * @ngdoc method - * @name forElement - * @methodOf angular.service.$formFactory + * @ngdoc property + * @name $invalid + * @propertyOf angular.module.ng.$formFactory.Form * @description - * Static method on `$formFactory` service. + * Property of the form and widget instance. * - * Retrieve the closest form for a given element or defaults to the `root` form. Used by the - * {@link angular.widget.form form} element. - * @param {Element} element The element where the search for form should initiate. + * True if any of the widgets of the form are invalid. */ - formFactory.forElement = function(element) { - return element.inheritedData('$form') || formFactory.rootForm; - }; - return formFactory; - - function formFactory(parent) { - return (parent || formFactory.rootForm).$new(FormController); - } - -}); -function propertiesUpdate(widget) { - widget.$valid = !(widget.$invalid = - !(widget.$readonly || widget.$disabled || equals(widget.$error, {}))); -} - -/** - * @ngdoc property - * @name $error - * @propertyOf angular.service.$formFactory - * @description - * Property of the form and widget instance. - * - * Summary of all of the errors on the page. If a widget emits `$invalid` with `REQUIRED` key, - * then the `$error` object will have a `REQUIRED` key with an array of widgets which have - * emitted this key. `form.$error.REQUIRED == [ widget ]`. - */ - -/** - * @ngdoc property - * @name $invalid - * @propertyOf angular.service.$formFactory - * @description - * Property of the form and widget instance. - * - * True if any of the widgets of the form are invalid. - */ - -/** - * @ngdoc property - * @name $valid - * @propertyOf angular.service.$formFactory - * @description - * Property of the form and widget instance. - * - * True if all of the widgets of the form are valid. - */ + /** + * @ngdoc property + * @name $valid + * @propertyOf angular.module.ng.$formFactory.Form + * @description + * Property of the form and widget instance. + * + * True if all of the widgets of the form are valid. + */ -/** - * @ngdoc event - * @name angular.service.$formFactory#$valid - * @eventOf angular.service.$formFactory - * @eventType listen on form - * @description - * Upon receiving the `$valid` event from the widget update the `$error`, `$valid` and `$invalid` - * properties of both the widget as well as the from. - * - * @param {String} validationKey The validation key to be used when updating the `$error` object. - * The validation key is what will allow the template to bind to a specific validation error - * such as `
    error for key
    `. - */ + /** + * @ngdoc event + * @name angular.module.ng.$formFactory.Form#$valid + * @eventOf angular.module.ng.$formFactory.Form + * @eventType listen on form + * @description + * Upon receiving the `$valid` event from the widget update the `$error`, `$valid` and `$invalid` + * properties of both the widget as well as the from. + * + * @param {string} validationKey The validation key to be used when updating the `$error` object. + * The validation key is what will allow the template to bind to a specific validation error + * such as `
    error for key
    `. + */ -/** - * @ngdoc event - * @name angular.service.$formFactory#$invalid - * @eventOf angular.service.$formFactory - * @eventType listen on form - * @description - * Upon receiving the `$invalid` event from the widget update the `$error`, `$valid` and `$invalid` - * properties of both the widget as well as the from. - * - * @param {String} validationKey The validation key to be used when updating the `$error` object. - * The validation key is what will allow the template to bind to a specific validation error - * such as `
    error for key
    `. - */ + /** + * @ngdoc event + * @name angular.module.ng.$formFactory.Form#$invalid + * @eventOf angular.module.ng.$formFactory.Form + * @eventType listen on form + * @description + * Upon receiving the `$invalid` event from the widget update the `$error`, `$valid` and `$invalid` + * properties of both the widget as well as the from. + * + * @param {string} validationKey The validation key to be used when updating the `$error` object. + * The validation key is what will allow the template to bind to a specific validation error + * such as `
    error for key
    `. + */ -/** - * @ngdoc event - * @name angular.service.$formFactory#$validate - * @eventOf angular.service.$formFactory - * @eventType emit on widget - * @description - * Emit the `$validate` event on the widget, giving a widget a chance to emit a - * `$valid` / `$invalid` event base on its state. The `$validate` event is triggered when the - * model or the view changes. - */ + /** + * @ngdoc event + * @name angular.module.ng.$formFactory.Form#$validate + * @eventOf angular.module.ng.$formFactory.Form + * @eventType emit on widget + * @description + * Emit the `$validate` event on the widget, giving a widget a chance to emit a + * `$valid` / `$invalid` event base on its state. The `$validate` event is triggered when the + * model or the view changes. + */ -/** - * @ngdoc event - * @name angular.service.$formFactory#$viewChange - * @eventOf angular.service.$formFactory - * @eventType listen on widget - * @description - * A widget is responsible for emitting this event whenever the view changes do to user interaction. - * The event takes a `$viewValue` parameter, which is the new value of the view. This - * event triggers a call to `$parseView()` as well as `$validate` event on widget. - * - * @param {*} viewValue The new value for the view which will be assigned to `widget.$viewValue`. - */ + /** + * @ngdoc event + * @name angular.module.ng.$formFactory.Form#$viewChange + * @eventOf angular.module.ng.$formFactory.Form + * @eventType listen on widget + * @description + * A widget is responsible for emitting this event whenever the view changes do to user interaction. + * The event takes a `$viewValue` parameter, which is the new value of the view. This + * event triggers a call to `$parseView()` as well as `$validate` event on widget. + * + * @param {*} viewValue The new value for the view which will be assigned to `widget.$viewValue`. + */ -function FormController() { - var form = this, - $error = form.$error = {}; + function FormController() { + var form = this, + $error = form.$error = {}; - form.$on('$destroy', function(event){ - var widget = event.targetScope; - if (widget.$widgetId) { - delete form[widget.$widgetId]; - } - forEach($error, removeWidget, widget); - }); + form.$on('$destroy', function(event){ + var widget = event.targetScope; + if (widget.$widgetId) { + delete form[widget.$widgetId]; + } + forEach($error, removeWidget, widget); + }); + + form.$on('$valid', function(event, error){ + var widget = event.targetScope; + delete widget.$error[error]; + propertiesUpdate(widget); + removeWidget($error[error], error, widget); + }); + + form.$on('$invalid', function(event, error){ + var widget = event.targetScope; + addWidget(error, widget); + widget.$error[error] = true; + propertiesUpdate(widget); + }); - form.$on('$valid', function(event, error){ - var widget = event.targetScope; - delete widget.$error[error]; - propertiesUpdate(widget); - removeWidget($error[error], error, widget); - }); + propertiesUpdate(form); - form.$on('$invalid', function(event, error){ - var widget = event.targetScope; - addWidget(error, widget); - widget.$error[error] = true; - propertiesUpdate(widget); - }); - - propertiesUpdate(form); - - function removeWidget(queue, errorKey, widget) { - if (queue) { - widget = widget || this; // so that we can be used in forEach; - for (var i = 0, length = queue.length; i < length; i++) { - if (queue[i] === widget) { - queue.splice(i, 1); - if (!queue.length) { - delete $error[errorKey]; + function removeWidget(queue, errorKey, widget) { + if (queue) { + widget = widget || this; // so that we can be used in forEach; + for (var i = 0, length = queue.length; i < length; i++) { + if (queue[i] === widget) { + queue.splice(i, 1); + if (!queue.length) { + delete $error[errorKey]; + } } } + propertiesUpdate(form); } - propertiesUpdate(form); } - } - function addWidget(errorKey, widget) { - var queue = $error[errorKey]; - if (queue) { - for (var i = 0, length = queue.length; i < length; i++) { - if (queue[i] === widget) { - return; + function addWidget(errorKey, widget) { + var queue = $error[errorKey]; + if (queue) { + for (var i = 0, length = queue.length; i < length; i++) { + if (queue[i] === widget) { + return; + } } + } else { + $error[errorKey] = queue = []; } - } else { - $error[errorKey] = queue = []; + queue.push(widget); + propertiesUpdate(form); } - queue.push(widget); - propertiesUpdate(form); } -} -/** - * @ngdoc method - * @name $createWidget - * @methodOf angular.service.$formFactory - * @description - * - * Use form's `$createWidget` instance method to create new widgets. The widgets can be created - * using an alias which makes the accessible from the form and available for data-binding, - * useful for displaying validation error messages. - * - * The creation of a widget sets up: - * - * - `$watch` of `expression` on `model` scope. This code path syncs the model to the view. - * The `$watch` listener will: - * - * - assign the new model value of `expression` to `widget.$modelValue`. - * - call `widget.$parseModel` method if present. The `$parseModel` is responsible for copying - * the `widget.$modelValue` to `widget.$viewValue` and optionally converting the data. - * (For example to convert a number into string) - * - emits `$validate` event on widget giving a widget a chance to emit `$valid` / `$invalid` - * event. - * - call `widget.$render()` method on widget. The `$render` method is responsible for - * reading the `widget.$viewValue` and updating the DOM. - * - * - Listen on `$viewChange` event from the `widget`. This code path syncs the view to the model. - * The `$viewChange` listener will: - * - * - assign the value to `widget.$viewValue`. - * - call `widget.$parseView` method if present. The `$parseView` is responsible for copying - * the `widget.$viewValue` to `widget.$modelValue` and optionally converting the data. - * (For example to convert a string into number) - * - emits `$validate` event on widget giving a widget a chance to emit `$valid` / `$invalid` - * event. - * - Assign the `widget.$modelValue` to the `expression` on the `model` scope. - * - * - Creates these set of properties on the `widget` which are updated as a response to the - * `$valid` / `$invalid` events: - * - * - `$error` - object - validation errors will be published as keys on this object. - * Data-binding to this property is useful for displaying the validation errors. - * - `$valid` - boolean - true if there are no validation errors - * - `$invalid` - boolean - opposite of `$valid`. - * @param {Object} params Named parameters: - * - * - `scope` - `{Scope}` - The scope to which the model for this widget is attached. - * - `model` - `{string}` - The name of the model property on model scope. - * - `controller` - {WidgetController} - The controller constructor function. - * The controller constructor should create these instance methods. - * - `$parseView()`: optional method responsible for copying `$viewVale` to `$modelValue`. - * The method may fire `$valid`/`$invalid` events. - * - `$parseModel()`: optional method responsible for copying `$modelVale` to `$viewValue`. - * The method may fire `$valid`/`$invalid` events. - * - `$render()`: required method which needs to update the DOM of the widget to match the - * `$viewValue`. - * - * - `controllerArgs` - `{Array}` (Optional) - Any extra arguments will be curried to the - * WidgetController constructor. - * - `onChange` - `{(string|function())}` (Optional) - Expression to execute when user changes the - * value. - * - `alias` - `{string}` (Optional) - The name of the form property under which the widget - * instance should be published. The name should be unique for each form. - * @returns {Widget} Instance of a widget scope. - */ -FormController.prototype.$createWidget = function(params) { - var form = this, - modelScope = params.scope, - onChange = params.onChange, - alias = params.alias, - scopeGet = parser(params.model).assignable(), - scopeSet = scopeGet.assign, - widget = this.$new(params.controller, params.controllerArgs); - - widget.$error = {}; - // Set the state to something we know will change to get the process going. - widget.$modelValue = Number.NaN; - // watch for scope changes and update the view appropriately - modelScope.$watch(scopeGet, function(scope, value) { - if (!equals(widget.$modelValue, value)) { - widget.$modelValue = value; - widget.$parseModel ? widget.$parseModel() : (widget.$viewValue = value); - widget.$emit('$validate'); - widget.$render && widget.$render(); - } - }); - - widget.$on('$viewChange', function(event, viewValue){ - if (!equals(widget.$viewValue, viewValue)) { - widget.$viewValue = viewValue; - widget.$parseView ? widget.$parseView() : (widget.$modelValue = widget.$viewValue); - scopeSet(modelScope, widget.$modelValue); - if (onChange) modelScope.$eval(onChange); - widget.$emit('$validate'); - } - }); + /** + * @ngdoc method + * @name $createWidget + * @methodOf angular.module.ng.$formFactory.Form + * @description + * + * Use form's `$createWidget` instance method to create new widgets. The widgets can be created + * using an alias which makes the accessible from the form and available for data-binding, + * useful for displaying validation error messages. + * + * The creation of a widget sets up: + * + * - `$watch` of `expression` on `model` scope. This code path syncs the model to the view. + * The `$watch` listener will: + * + * - assign the new model value of `expression` to `widget.$modelValue`. + * - call `widget.$parseModel` method if present. The `$parseModel` is responsible for copying + * the `widget.$modelValue` to `widget.$viewValue` and optionally converting the data. + * (For example to convert a number into string) + * - emits `$validate` event on widget giving a widget a chance to emit `$valid` / `$invalid` + * event. + * - call `widget.$render()` method on widget. The `$render` method is responsible for + * reading the `widget.$viewValue` and updating the DOM. + * + * - Listen on `$viewChange` event from the `widget`. This code path syncs the view to the model. + * The `$viewChange` listener will: + * + * - assign the value to `widget.$viewValue`. + * - call `widget.$parseView` method if present. The `$parseView` is responsible for copying + * the `widget.$viewValue` to `widget.$modelValue` and optionally converting the data. + * (For example to convert a string into number) + * - emits `$validate` event on widget giving a widget a chance to emit `$valid` / `$invalid` + * event. + * - Assign the `widget.$modelValue` to the `expression` on the `model` scope. + * + * - Creates these set of properties on the `widget` which are updated as a response to the + * `$valid` / `$invalid` events: + * + * - `$error` - object - validation errors will be published as keys on this object. + * Data-binding to this property is useful for displaying the validation errors. + * - `$valid` - boolean - true if there are no validation errors + * - `$invalid` - boolean - opposite of `$valid`. + * @param {Object} params Named parameters: + * + * - `scope` - `{Scope}` - The scope to which the model for this widget is attached. + * - `model` - `{string}` - The name of the model property on model scope. + * - `controller` - {WidgetController} - The controller constructor function. + * The controller constructor should create these instance methods. + * - `$parseView()`: optional method responsible for copying `$viewVale` to `$modelValue`. + * The method may fire `$valid`/`$invalid` events. + * - `$parseModel()`: optional method responsible for copying `$modelVale` to `$viewValue`. + * The method may fire `$valid`/`$invalid` events. + * - `$render()`: required method which needs to update the DOM of the widget to match the + * `$viewValue`. + * + * - `controllerArgs` - `{Array}` (Optional) - Any extra arguments will be curried to the + * WidgetController constructor. + * - `onChange` - `{(string|function())}` (Optional) - Expression to execute when user changes the + * value. + * - `alias` - `{string}` (Optional) - The name of the form property under which the widget + * instance should be published. The name should be unique for each form. + * @returns {Widget} Instance of a widget scope. + */ + FormController.prototype.$createWidget = function(params) { + var form = this, + modelScope = params.scope, + onChange = params.onChange, + alias = params.alias, + scopeGet = $parse(params.model), + scopeSet = scopeGet.assign, + widget = this.$new(params.controller, params.controllerArgs); + + if (!scopeSet) { + throw Error("Expression '" + params.model + "' is not assignable!"); + }; + + widget.$error = {}; + // Set the state to something we know will change to get the process going. + widget.$modelValue = Number.NaN; + // watch for scope changes and update the view appropriately + modelScope.$watch(scopeGet, function(scope, value) { + if (!equals(widget.$modelValue, value)) { + widget.$modelValue = value; + widget.$parseModel ? widget.$parseModel() : (widget.$viewValue = value); + widget.$emit('$validate'); + widget.$render && widget.$render(); + } + }); + + widget.$on('$viewChange', function(event, viewValue){ + if (!equals(widget.$viewValue, viewValue)) { + widget.$viewValue = viewValue; + widget.$parseView ? widget.$parseView() : (widget.$modelValue = widget.$viewValue); + scopeSet(modelScope, widget.$modelValue); + if (onChange) modelScope.$eval(onChange); + widget.$emit('$validate'); + } + }); - propertiesUpdate(widget); + propertiesUpdate(widget); - // assign the widgetModel to the form - if (alias && !form.hasOwnProperty(alias)) { - form[alias] = widget; - widget.$widgetId = alias; - } else { - alias = null; - } + // assign the widgetModel to the form + if (alias && !form.hasOwnProperty(alias)) { + form[alias] = widget; + widget.$widgetId = alias; + } else { + alias = null; + } - return widget; -}; + return widget; + }; +} diff --git a/src/service/locale.js b/src/service/locale.js index 069a691ed268..4c9a989d5e07 100644 --- a/src/service/locale.js +++ b/src/service/locale.js @@ -1,8 +1,8 @@ 'use strict'; /** - * @ngdoc service - * @name angular.service.$locale + * @ngdoc object + * @name angular.module.ng.$locale * * @description * $locale service provides localization rules for various Angular components. As of right now the @@ -10,61 +10,63 @@ * * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`) */ -angularServiceInject('$locale', function() { - return { - id: 'en-us', +function $LocaleProvider(){ + this.$get = function() { + return { + id: 'en-us', - NUMBER_FORMATS: { - DECIMAL_SEP: '.', - GROUP_SEP: ',', - PATTERNS: [ - { // Decimal Pattern - minInt: 1, - minFrac: 0, - maxFrac: 3, - posPre: '', - posSuf: '', - negPre: '-', - negSuf: '', - gSize: 3, - lgSize: 3 - },{ //Currency Pattern - minInt: 1, - minFrac: 2, - maxFrac: 2, - posPre: '\u00A4', - posSuf: '', - negPre: '(\u00A4', - negSuf: ')', - gSize: 3, - lgSize: 3 - } - ], - CURRENCY_SYM: '$' - }, + NUMBER_FORMATS: { + DECIMAL_SEP: '.', + GROUP_SEP: ',', + PATTERNS: [ + { // Decimal Pattern + minInt: 1, + minFrac: 0, + maxFrac: 3, + posPre: '', + posSuf: '', + negPre: '-', + negSuf: '', + gSize: 3, + lgSize: 3 + },{ //Currency Pattern + minInt: 1, + minFrac: 2, + maxFrac: 2, + posPre: '\u00A4', + posSuf: '', + negPre: '(\u00A4', + negSuf: ')', + gSize: 3, + lgSize: 3 + } + ], + CURRENCY_SYM: '$' + }, - DATETIME_FORMATS: { - MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December' - .split(','), - SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','), - DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','), - SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','), - AMPMS: ['AM','PM'], - medium: 'MMM d, y h:mm:ss a', - short: 'M/d/yy h:mm a', - fullDate: 'EEEE, MMMM d, y', - longDate: 'MMMM d, y', - mediumDate: 'MMM d, y', - shortDate: 'M/d/yy', - mediumTime: 'h:mm:ss a', - shortTime: 'h:mm a' - }, + DATETIME_FORMATS: { + MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December' + .split(','), + SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','), + DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','), + SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','), + AMPMS: ['AM','PM'], + medium: 'MMM d, y h:mm:ss a', + short: 'M/d/yy h:mm a', + fullDate: 'EEEE, MMMM d, y', + longDate: 'MMMM d, y', + mediumDate: 'MMM d, y', + shortDate: 'M/d/yy', + mediumTime: 'h:mm:ss a', + shortTime: 'h:mm a' + }, - pluralCat: function(num) { - if (num === 1) { - return 'one'; + pluralCat: function(num) { + if (num === 1) { + return 'one'; + } + return 'other'; } - return 'other'; - } + }; }; -}); +} diff --git a/src/service/location.js b/src/service/location.js index d1d34e6762be..a29a1a157579 100644 --- a/src/service/location.js +++ b/src/service/location.js @@ -205,8 +205,8 @@ LocationUrl.prototype = LocationHashbangUrl.prototype = { /** * @ngdoc method - * @name angular.service.$location#absUrl - * @methodOf angular.service.$location + * @name angular.module.ng.$location#absUrl + * @methodOf angular.module.ng.$location * * @description * This method is getter only. @@ -220,8 +220,8 @@ LocationUrl.prototype = LocationHashbangUrl.prototype = { /** * @ngdoc method - * @name angular.service.$location#url - * @methodOf angular.service.$location + * @name angular.module.ng.$location#url + * @methodOf angular.module.ng.$location * * @description * This method is getter / setter. @@ -238,16 +238,17 @@ LocationUrl.prototype = LocationHashbangUrl.prototype = { return this.$$url; var match = PATH_MATCH.exec(url); - this.path(decodeURIComponent(match[1] || '')).search(match[3] || '') - .hash(match[5] || '', replace); + if (match[1]) this.path(decodeURIComponent(match[1])); + if (match[2] || match[1]) this.search(match[3] || ''); + this.hash(match[5] || '', replace); return this; }, /** * @ngdoc method - * @name angular.service.$location#protocol - * @methodOf angular.service.$location + * @name angular.module.ng.$location#protocol + * @methodOf angular.module.ng.$location * * @description * This method is getter only. @@ -260,8 +261,8 @@ LocationUrl.prototype = LocationHashbangUrl.prototype = { /** * @ngdoc method - * @name angular.service.$location#host - * @methodOf angular.service.$location + * @name angular.module.ng.$location#host + * @methodOf angular.module.ng.$location * * @description * This method is getter only. @@ -274,8 +275,8 @@ LocationUrl.prototype = LocationHashbangUrl.prototype = { /** * @ngdoc method - * @name angular.service.$location#port - * @methodOf angular.service.$location + * @name angular.module.ng.$location#port + * @methodOf angular.module.ng.$location * * @description * This method is getter only. @@ -288,8 +289,8 @@ LocationUrl.prototype = LocationHashbangUrl.prototype = { /** * @ngdoc method - * @name angular.service.$location#path - * @methodOf angular.service.$location + * @name angular.module.ng.$location#path + * @methodOf angular.module.ng.$location * * @description * This method is getter / setter. @@ -310,8 +311,8 @@ LocationUrl.prototype = LocationHashbangUrl.prototype = { /** * @ngdoc method - * @name angular.service.$location#search - * @methodOf angular.service.$location + * @name angular.module.ng.$location#search + * @methodOf angular.module.ng.$location * * @description * This method is getter / setter. @@ -343,8 +344,8 @@ LocationUrl.prototype = LocationHashbangUrl.prototype = { /** * @ngdoc method - * @name angular.service.$location#hash - * @methodOf angular.service.$location + * @name angular.module.ng.$location#hash + * @methodOf angular.module.ng.$location * * @description * This method is getter / setter. @@ -360,8 +361,8 @@ LocationUrl.prototype = LocationHashbangUrl.prototype = { /** * @ngdoc method - * @name angular.service.$location#replace - * @methodOf angular.service.$location + * @name angular.module.ng.$location#replace + * @methodOf angular.module.ng.$location * * @description * If called, all changes to $location during current `$digest` will be replacing current history @@ -395,12 +396,11 @@ function locationGetterSetter(property, preprocess) { /** - * @ngdoc service - * @name angular.service.$location + * @ngdoc object + * @name angular.module.ng.$location * * @requires $browser * @requires $sniffer - * @requires $locationConfig * @requires $document * * @description @@ -419,94 +419,132 @@ function locationGetterSetter(property, preprocess) { * * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular Services: Using $location} */ -angularServiceInject('$location', function($browser, $sniffer, $locationConfig, $document) { - var scope = this, currentUrl, - basePath = $browser.baseHref() || '/', - pathPrefix = pathPrefixFromBase(basePath), - hashPrefix = $locationConfig.hashPrefix || '', - initUrl = $browser.url(); - - if ($locationConfig.html5Mode) { - if ($sniffer.history) { - currentUrl = new LocationUrl(convertToHtml5Url(initUrl, basePath, hashPrefix), pathPrefix); + +/** + * @ngdoc object + * @name angular.module.ng.$locationProvider + * @description + * Use the `$locationProvider` to configure how the application deep linking paths are stored. + */ +function $LocationProvider(){ + var hashPrefix = '', + html5Mode = false; + + /** + * @ngdoc property + * @name angular.module.ng.$locationProvider#hashPrefix + * @methodOf angular.module.ng.$locationProvider + * @description + * @param {string=} prefix Prefix for hash part (containing path and search) + * @returns {*} current value if used as getter or itself (chaining) if used as setter + */ + this.hashPrefix = function(prefix) { + if (isDefined(prefix)) { + hashPrefix = prefix; + return this; } else { - currentUrl = new LocationHashbangUrl(convertToHashbangUrl(initUrl, basePath, hashPrefix), - hashPrefix); + return html5Mode; } + } - // link rewriting - var u = currentUrl, - absUrlPrefix = composeProtocolHostPort(u.protocol(), u.host(), u.port()) + pathPrefix; + /** + * @ngdoc property + * @name angular.module.ng.$locationProvider#hashPrefix + * @methodOf angular.module.ng.$locationProvider + * @description + * @param {string=} mode Use HTML5 strategy if available. + * @returns {*} current value if used as getter or itself (chaining) if used as setter + */ + this.html5Mode = function(mode) { + if (isDefined(mode)) { + html5Mode = mode; + return this; + } else { + return html5Mode; + } + }; + + this.$get = ['$rootScope', '$browser', '$sniffer', '$document', + function( $rootScope, $browser, $sniffer, $document) { + var currentUrl, + basePath = $browser.baseHref() || '/', + pathPrefix = pathPrefixFromBase(basePath), + initUrl = $browser.url(); - $document.bind('click', function(event) { - // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser) - // currently we open nice url link and redirect then + if (html5Mode) { + if ($sniffer.history) { + currentUrl = new LocationUrl(convertToHtml5Url(initUrl, basePath, hashPrefix), pathPrefix); + } else { + currentUrl = new LocationHashbangUrl(convertToHashbangUrl(initUrl, basePath, hashPrefix), + hashPrefix); + } - if (event.ctrlKey || event.metaKey || event.which == 2) return; + // link rewriting + var u = currentUrl, + absUrlPrefix = composeProtocolHostPort(u.protocol(), u.host(), u.port()) + pathPrefix; - var elm = jqLite(event.target); + $document.bind('click', function(event) { + // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser) + // currently we open nice url link and redirect then - // traverse the DOM up to find first A tag - while (elm.length && lowercase(elm[0].nodeName) !== 'a') { - elm = elm.parent(); - } + if (event.ctrlKey || event.metaKey || event.which == 2) return; - var href = elm.attr('href'); - if (!href || isDefined(elm.attr('ng:ext-link')) || elm.attr('target')) return; + var elm = jqLite(event.target); - // remove same domain from full url links (IE7 always returns full hrefs) - href = href.replace(absUrlPrefix, ''); + // traverse the DOM up to find first A tag + while (elm.length && lowercase(elm[0].nodeName) !== 'a') { + elm = elm.parent(); + } - // link to different domain (or base path) - if (href.substr(0, 4) == 'http') return; + var href = elm.attr('href'); + if (!href || isDefined(elm.attr('ng:ext-link')) || elm.attr('target')) return; - // remove pathPrefix from absolute links - href = href.indexOf(pathPrefix) === 0 ? href.substr(pathPrefix.length) : href; + // remove same domain from full url links (IE7 always returns full hrefs) + href = href.replace(absUrlPrefix, ''); - currentUrl.url(https://github.com/href); - scope.$apply(); - event.preventDefault(); - // hack to work around FF6 bug 684208 when scenario runner clicks on links - window.angular['ff-684208-preventDefault'] = true; - }); - } else { - currentUrl = new LocationHashbangUrl(initUrl, hashPrefix); - } + // link to different domain (or base path) + if (href.substr(0, 4) == 'http') return; - // rewrite hashbang url <> html5 url - if (currentUrl.absUrl() != initUrl) { - $browser.url(https://github.com/currentUrl.absUrl(), true); - } + // remove pathPrefix from absolute links + href = href.indexOf(pathPrefix) === 0 ? href.substr(pathPrefix.length) : href; - // update $location when $browser url changes - $browser.onUrlChange(function(newUrl) { - if (currentUrl.absUrl() != newUrl) { - currentUrl.$$parse(newUrl); - scope.$apply(); - } - }); - - // update browser - var changeCounter = 0; - scope.$watch(function() { - if ($browser.url() != currentUrl.absUrl()) { - changeCounter++; - scope.$evalAsync(function() { - $browser.url(https://github.com/currentUrl.absUrl(), currentUrl.$$replace); - currentUrl.$$replace = false; + currentUrl.url(https://github.com/href); + $rootScope.$apply(); + event.preventDefault(); + // hack to work around FF6 bug 684208 when scenario runner clicks on links + window.angular['ff-684208-preventDefault'] = true; }); + } else { + currentUrl = new LocationHashbangUrl(initUrl, hashPrefix); } - return changeCounter; - }); + // rewrite hashbang url <> html5 url + if (currentUrl.absUrl() != initUrl) { + $browser.url(https://github.com/currentUrl.absUrl(), true); + } + + // update $location when $browser url changes + $browser.onUrlChange(function(newUrl) { + if (currentUrl.absUrl() != newUrl) { + currentUrl.$$parse(newUrl); + $rootScope.$apply(); + } + }); - return currentUrl; -}, ['$browser', '$sniffer', '$locationConfig', '$document']); + // update browser + var changeCounter = 0; + $rootScope.$watch(function() { + if ($browser.url() != currentUrl.absUrl()) { + changeCounter++; + $rootScope.$evalAsync(function() { + $browser.url(https://github.com/currentUrl.absUrl(), currentUrl.$$replace); + currentUrl.$$replace = false; + }); + } + return changeCounter; + }); -angular.service('$locationConfig', function() { - return { - html5Mode: false, - hashPrefix: '' - }; -}); + return currentUrl; +}]; +} diff --git a/src/service/log.js b/src/service/log.js index 29577166d968..d6566140eedd 100644 --- a/src/service/log.js +++ b/src/service/log.js @@ -1,8 +1,8 @@ 'use strict'; /** - * @ngdoc service - * @name angular.service.$log + * @ngdoc object + * @name angular.module.ng.$log * @requires $window * * @description @@ -34,64 +34,78 @@ */ -var $logFactory; //reference to be used only in tests -angularServiceInject("$log", $logFactory = function($window){ - return { - /** - * @ngdoc method - * @name angular.service.$log#log - * @methodOf angular.service.$log - * - * @description - * Write a log message - */ - log: consoleLog('log'), - /** - * @ngdoc method - * @name angular.service.$log#warn - * @methodOf angular.service.$log - * - * @description - * Write a warning message - */ - warn: consoleLog('warn'), +function $LogProvider(){ + this.$get = ['$window', function($window){ + return { + /** + * @ngdoc method + * @name angular.module.ng.$log#log + * @methodOf angular.module.ng.$log + * + * @description + * Write a log message + */ + log: consoleLog('log'), - /** - * @ngdoc method - * @name angular.service.$log#info - * @methodOf angular.service.$log - * - * @description - * Write an information message - */ - info: consoleLog('info'), + /** + * @ngdoc method + * @name angular.module.ng.$log#warn + * @methodOf angular.module.ng.$log + * + * @description + * Write a warning message + */ + warn: consoleLog('warn'), - /** - * @ngdoc method - * @name angular.service.$log#error - * @methodOf angular.service.$log - * - * @description - * Write an error message - */ - error: consoleLog('error') - }; + /** + * @ngdoc method + * @name angular.module.ng.$log#info + * @methodOf angular.module.ng.$log + * + * @description + * Write an information message + */ + info: consoleLog('info'), - function consoleLog(type) { - var console = $window.console || {}; - var logFn = console[type] || console.log || noop; - if (logFn.apply) { - return function() { - var args = []; - forEach(arguments, function(arg){ - args.push(formatError(arg)); - }); - return logFn.apply(console, args); - }; - } else { - // we are IE, in which case there is nothing we can do - return logFn; + /** + * @ngdoc method + * @name angular.module.ng.$log#error + * @methodOf angular.module.ng.$log + * + * @description + * Write an error message + */ + error: consoleLog('error') + }; + + function formatError(arg) { + if (arg instanceof Error) { + if (arg.stack) { + arg = (arg.message && arg.stack.indexOf(arg.message) === -1) ? + 'Error: ' + arg.message + '\n' + arg.stack : arg.stack; + } else if (arg.sourceURL) { + arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line; + } + } + return arg; + } + + function consoleLog(type) { + var console = $window.console || {}; + var logFn = console[type] || console.log || noop; + if (logFn.apply) { + return function() { + var args = []; + forEach(arguments, function(arg){ + args.push(formatError(arg)); + }); + return logFn.apply(console, args); + }; + } else { + // we are IE, in which case there is nothing we can do + return logFn; + } } - } -}, ['$window']); + }]; +} diff --git a/src/parser.js b/src/service/parse.js similarity index 88% rename from src/parser.js rename to src/service/parse.js index 0265973643fd..432929b5499b 100644 --- a/src/parser.js +++ b/src/service/parse.js @@ -27,9 +27,8 @@ var OPERATORS = { }; var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'}; -function lex(text, parseStringsForObjects){ - var dateParseLength = parseStringsForObjects ? DATE_ISOSTRING_LN : -1, - tokens = [], +function lex(text){ + var tokens = [], token, index = 0, json = [], @@ -199,12 +198,13 @@ function lex(text, parseStringsForObjects){ escape = true; } else if (ch == quote) { index++; - tokens.push({index:start, text:rawString, string:string, json:true, - fn:function() { - return (string.length == dateParseLength) - ? angular['String']['toDate'](string) - : string; - }}); + tokens.push({ + index:start, + text:rawString, + string:string, + json:true, + fn:function() { return string; } + }); return; } else { string += ch; @@ -217,17 +217,17 @@ function lex(text, parseStringsForObjects){ ///////////////////////////////////////// -function parser(text, json){ +function parser(text, json, $filter){ var ZERO = valueFn(0), - tokens = lex(text, json), + value, + tokens = lex(text), assignment = _assignment, assignable = logicalOR, functionCall = _functionCall, fieldAccess = _fieldAccess, objectIndex = _objectIndex, filterChain = _filterChain, - functionIdent = _functionIdent, - pipeFunction = _pipeFunction; + functionIdent = _functionIdent; if(json){ // The extra level of aliasing is here, just in case the lexer misses something, so that // we prevent any accidental execution in JSON. @@ -238,26 +238,15 @@ function parser(text, json){ assignable = filterChain = functionIdent = - pipeFunction = function() { throwError("is not valid json", {text:text, index:0}); }; + value = primary(); + } else { + value = statements(); } - //TODO: Shouldn't all of the public methods have assertAllConsumed? - //TODO: I think these should be public as part of the parser api instead of scope.$eval(). - return { - assignable: assertConsumed(assignable), - primary: assertConsumed(primary), - statements: assertConsumed(statements) - }; - - function assertConsumed(fn) { - return function() { - var value = fn(); - if (tokens.length !== 0) { - throwError("is an unexpected token", tokens[0]); - } - return value; - }; + if (tokens.length !== 0) { + throwError("is an unexpected token", tokens[0]); } + return value; /////////////////////////////////// function throwError(msg, token) { @@ -355,13 +344,9 @@ function parser(text, json){ } function filter() { - return pipeFunction(angularFilter); - } - - function _pipeFunction(fnScope){ - var fn = functionIdent(fnScope); + var token = expect(); + var fn = $filter(token.text); var argsFn = []; - var token; while(true) { if ((token = expect(':'))) { argsFn.push(expression()); @@ -652,6 +637,7 @@ function setter(obj, path, setValue) { * @param {boolean=true} bindFnToScope * @returns value as accesbile by path */ +//TODO(misko): this function needs to be removed function getter(obj, path, bindFnToScope) { if (!path) return obj; var keys = path.split('.'); @@ -664,14 +650,6 @@ function getter(obj, path, bindFnToScope) { if (obj) { obj = (lastInstance = obj)[key]; } - if (isUndefined(obj) && key.charAt(0) == '$') { - var type = angularGlobal.typeOf(lastInstance); - type = angular[type.charAt(0).toUpperCase()+type.substring(1)]; - var fn = type ? type[[key.substring(1)]] : _undefined; - if (fn) { - return obj = bind(lastInstance, fn, lastInstance); - } - } } if (!bindFnToScope && isFunction(obj)) { return bind(lastInstance, obj); @@ -680,7 +658,6 @@ function getter(obj, path, bindFnToScope) { } var getterFnCache = {}, - compileCache = {}, JS_KEYWORDS = {}; forEach( @@ -707,16 +684,6 @@ function getterFn(path) { ' fn.$unboundFn=s;\n' + ' s=fn;\n' + '}\n'; - if (key.charAt(1) == '$') { - // special code for super-imposed functions - var name = key.substr(2); - code += 'if(!s) {\n' + - ' t = angular.Global.typeOf(l);\n' + - ' fn = (angular[t.charAt(0).toUpperCase() + t.substring(1)]||{})["' + name + '"];\n' + - ' if (fn) ' + - 's = function(){ return fn.apply(l, [l].concat(Array.prototype.slice.call(arguments, 0))); };\n' + - '}\n'; - } }); code += 'return s;'; fn = Function('s', code); @@ -727,18 +694,26 @@ function getterFn(path) { /////////////////////////////////// -// TODO(misko): Should this function be public? -function compileExpr(expr) { - return parser(expr).statements(); +function $ParseProvider() { + var cache = {}; + this.$get = ['$filter', function($filter) { + return function(exp) { + switch(typeof exp) { + case 'string': + return cache.hasOwnProperty(exp) + ? cache[exp] + : cache[exp] = parser(exp, false, $filter); + case 'function': + return exp; + default: + return noop; + } + }; + }]; } -// TODO(misko): Deprecate? Remove! -// I think that compilation should be a service. -function expressionCompile(exp) { - if (isFunction(exp)) return exp; - var fn = compileCache[exp]; - if (!fn) { - fn = compileCache[exp] = parser(exp).statements(); - } - return fn; -} + +// This is a special access for JSON parser which bypasses the injector +var parseJson = function(json) { + return parser(json, true); +}; diff --git a/src/service/resource.js b/src/service/resource.js index 8d77a9e4e0f5..969e4be1cd85 100644 --- a/src/service/resource.js +++ b/src/service/resource.js @@ -1,8 +1,8 @@ 'use strict'; /** - * @ngdoc service - * @name angular.service.$resource + * @ngdoc object + * @name angular.module.ng.$resource * @requires $xhr.cache * * @description @@ -10,7 +10,7 @@ * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources. * * The returned resource object has action methods which provide high-level behaviors without - * the need to interact with the low level {@link angular.service.$xhr $xhr} service or + * the need to interact with the low level {@link angular.module.ng.$xhr $xhr} service or * raw XMLHttpRequest. * * @param {string} url A parameterized URL template with parameters prefixed by `:` as in @@ -57,7 +57,7 @@ * 'remove': {method:'DELETE'}, * 'delete': {method:'DELETE'} }; * - * Calling these methods invoke an {@link angular.service.$xhr} with the specified http method, + * Calling these methods invoke an {@link angular.module.ng.$xhr} with the specified http method, * destination and parameters. When the data is returned from the server then the object is an * instance of the resource class `save`, `remove` and `delete` actions are available on it as * methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read, @@ -200,7 +200,9 @@ */ -angularServiceInject('$resource', function($xhr){ - var resource = new ResourceFactory($xhr); - return bind(resource, resource.route); -}, ['$xhr.cache']); +function $ResourceProvider() { + this.$get = ['$xhr.cache', function($xhr){ + var resource = new ResourceFactory($xhr); + return bind(resource, resource.route); + }]; +} diff --git a/src/service/route.js b/src/service/route.js index ddc3df493729..97c9cee00ea5 100644 --- a/src/service/route.js +++ b/src/service/route.js @@ -1,8 +1,8 @@ 'use strict'; /** - * @ngdoc service - * @name angular.service.$route + * @ngdoc object + * @name angular.module.ng.$route * @requires $location * @requires $routeParams * @@ -14,7 +14,7 @@ * definition. It is used for deep-linking URLs to controllers and views (HTML partials). * * The `$route` service is typically used in conjunction with {@link angular.widget.ng:view ng:view} - * widget and the {@link angular.service.$routeParams $routeParams} service. + * widget and the {@link angular.module.ng.$routeParams $routeParams} service. * * @example This example shows how changing the URL hash causes the $route @@ -62,265 +62,267 @@ */ -angularServiceInject('$route', function($location, $routeParams) { - /** - * @ngdoc event - * @name angular.service.$route#$beforeRouteChange - * @eventOf angular.service.$route - * @eventType broadcast on root scope - * @description - * Broadcasted before a route change. - * - * @param {Route} next Future route information. - * @param {Route} current Current route information. - * - * The `Route` object extends the route definition with the following properties. - * - * * `scope` - The instance of the route controller. - * * `params` - The current {@link angular.service.$routeParams params}. - * - */ +function $RouteProvider(){ + this.$get = ['$rootScope', '$location', '$routeParams', + function( $rootScope, $location, $routeParams) { + /** + * @ngdoc event + * @name angular.module.ng.$route#$beforeRouteChange + * @eventOf angular.module.ng.$route + * @eventType broadcast on root scope + * @description + * Broadcasted before a route change. + * + * @param {Route} next Future route information. + * @param {Route} current Current route information. + * + * The `Route` object extends the route definition with the following properties. + * + * * `scope` - The instance of the route controller. + * * `params` - The current {@link angular.module.ng.$routeParams params}. + * + */ - /** - * @ngdoc event - * @name angular.service.$route#$afterRouteChange - * @eventOf angular.service.$route - * @eventType broadcast on root scope - * @description - * Broadcasted after a route change. - * - * @param {Route} current Current route information. - * @param {Route} previous Previous route information. - * - * The `Route` object extends the route definition with the following properties. - * - * * `scope` - The instance of the route controller. - * * `params` - The current {@link angular.service.$routeParams params}. - * - */ + /** + * @ngdoc event + * @name angular.module.ng.$route#$afterRouteChange + * @eventOf angular.module.ng.$route + * @eventType broadcast on root scope + * @description + * Broadcasted after a route change. + * + * @param {Route} current Current route information. + * @param {Route} previous Previous route information. + * + * The `Route` object extends the route definition with the following properties. + * + * * `scope` - The instance of the route controller. + * * `params` - The current {@link angular.module.ng.$routeParams params}. + * + */ - /** - * @ngdoc event - * @name angular.service.$route#$routeUpdate - * @eventOf angular.service.$route - * @eventType emit on the current route scope - * @description - * - * The `reloadOnSearch` property has been set to false, and we are reusing the same - * instance of the Controller. - */ + /** + * @ngdoc event + * @name angular.module.ng.$route#$routeUpdate + * @eventOf angular.module.ng.$route + * @eventType emit on the current route scope + * @description + * + * The `reloadOnSearch` property has been set to false, and we are reusing the same + * instance of the Controller. + */ - var routes = {}, - matcher = switchRouteMatcher, - parentScope = this, - rootScope = this, - dirty = 0, - forceReload = false, - $route = { - routes: routes, + var routes = {}, + matcher = switchRouteMatcher, + parentScope = $rootScope, + dirty = 0, + forceReload = false, + $route = { + routes: routes, - /** - * @ngdoc method - * @name angular.service.$route#parent - * @methodOf angular.service.$route - * - * @param {Scope} [scope=rootScope] Scope to be used as parent for newly created - * `$route.current.scope` scopes. - * - * @description - * Sets a scope to be used as the parent scope for scopes created on route change. If not - * set, defaults to the root scope. - */ - parent: function(scope) { - if (scope) parentScope = scope; - }, + /** + * @ngdoc method + * @name angular.module.ng.$route#parent + * @methodOf angular.module.ng.$route + * + * @param {Scope} [scope=rootScope] Scope to be used as parent for newly created + * `$route.current.scope` scopes. + * + * @description + * Sets a scope to be used as the parent scope for scopes created on route change. If not + * set, defaults to the root scope. + */ + parent: function(scope) { + if (scope) parentScope = scope; + }, - /** - * @ngdoc method - * @name angular.service.$route#when - * @methodOf angular.service.$route - * - * @param {string} path Route path (matched against `$location.hash`) - * @param {Object} route Mapping information to be assigned to `$route.current` on route - * match. - * - * Object properties: - * - * - `controller` – `{function()=}` – Controller fn that should be associated with newly - * created scope. - * - `template` – `{string=}` – path to an html template that should be used by - * {@link angular.widget.ng:view ng:view} or - * {@link angular.widget.ng:include ng:include} widgets. - * - `redirectTo` – {(string|function())=} – value to update - * {@link angular.service.$location $location} path with and trigger route redirection. - * - * If `redirectTo` is a function, it will be called with the following parameters: - * - * - `{Object.}` - route parameters extracted from the current - * `$location.path()` by applying the current route template. - * - `{string}` - current `$location.path()` - * - `{Object}` - current `$location.search()` - * - * The custom `redirectTo` function is expected to return a string which will be used - * to update `$location.path()` and `$location.search()`. - * - * - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search() - * changes. - * - * If the option is set to false and url in the browser changes, then - * $routeUpdate event is emited on the current route scope. You can use this event to - * react to {@link angular.service.$routeParams} changes: - * - * function MyCtrl($route, $routeParams) { - * this.$on('$routeUpdate', function() { - * // do stuff with $routeParams - * }); - * } - * - * @returns {Object} route object - * - * @description - * Adds a new route definition to the `$route` service. - */ - when: function(path, route) { - var routeDef = routes[path]; - if (!routeDef) routeDef = routes[path] = {reloadOnSearch: true}; - if (route) extend(routeDef, route); // TODO(im): what the heck? merge two route definitions? - dirty++; - return routeDef; - }, + /** + * @ngdoc method + * @name angular.module.ng.$route#when + * @methodOf angular.module.ng.$route + * + * @param {string} path Route path (matched against `$location.hash`) + * @param {Object} route Mapping information to be assigned to `$route.current` on route + * match. + * + * Object properties: + * + * - `controller` – `{function()=}` – Controller fn that should be associated with newly + * created scope. + * - `template` – `{string=}` – path to an html template that should be used by + * {@link angular.widget.ng:view ng:view} or + * {@link angular.widget.ng:include ng:include} widgets. + * - `redirectTo` – {(string|function())=} – value to update + * {@link angular.module.ng.$location $location} path with and trigger route redirection. + * + * If `redirectTo` is a function, it will be called with the following parameters: + * + * - `{Object.}` - route parameters extracted from the current + * `$location.path()` by applying the current route template. + * - `{string}` - current `$location.path()` + * - `{Object}` - current `$location.search()` + * + * The custom `redirectTo` function is expected to return a string which will be used + * to update `$location.path()` and `$location.search()`. + * + * - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search() + * changes. + * + * If the option is set to false and url in the browser changes, then + * $routeUpdate event is emited on the current route scope. You can use this event to + * react to {@link angular.module.ng.$routeParams} changes: + * + * function MyCtrl($route, $routeParams) { + * this.$on('$routeUpdate', function() { + * // do stuff with $routeParams + * }); + * } + * + * @returns {Object} route object + * + * @description + * Adds a new route definition to the `$route` service. + */ + when: function(path, route) { + var routeDef = routes[path]; + if (!routeDef) routeDef = routes[path] = {reloadOnSearch: true}; + if (route) extend(routeDef, route); // TODO(im): what the heck? merge two route definitions? + dirty++; + return routeDef; + }, - /** - * @ngdoc method - * @name angular.service.$route#otherwise - * @methodOf angular.service.$route - * - * @description - * Sets route definition that will be used on route change when no other route definition - * is matched. - * - * @param {Object} params Mapping information to be assigned to `$route.current`. - */ - otherwise: function(params) { - $route.when(null, params); - }, + /** + * @ngdoc method + * @name angular.module.ng.$route#otherwise + * @methodOf angular.module.ng.$route + * + * @description + * Sets route definition that will be used on route change when no other route definition + * is matched. + * + * @param {Object} params Mapping information to be assigned to `$route.current`. + */ + otherwise: function(params) { + $route.when(null, params); + }, - /** - * @ngdoc method - * @name angular.service.$route#reload - * @methodOf angular.service.$route - * - * @description - * Causes `$route` service to reload (and recreate the `$route.current` scope) upon the next - * eval even if {@link angular.service.$location $location} hasn't changed. - */ - reload: function() { - dirty++; - forceReload = true; - } - }; + /** + * @ngdoc method + * @name angular.module.ng.$route#reload + * @methodOf angular.module.ng.$route + * + * @description + * Causes `$route` service to reload (and recreate the `$route.current` scope) upon the next + * eval even if {@link angular.module.ng.$location $location} hasn't changed. + */ + reload: function() { + dirty++; + forceReload = true; + } + }; - this.$watch(function() { return dirty + $location.url(); }, updateRoute); + $rootScope.$watch(function() { return dirty + $location.url(); }, updateRoute); - return $route; + return $route; - ///////////////////////////////////////////////////// + ///////////////////////////////////////////////////// - function switchRouteMatcher(on, when) { - // TODO(i): this code is convoluted and inefficient, we should construct the route matching - // regex only once and then reuse it - var regex = '^' + when.replace(/([\.\\\(\)\^\$])/g, "\\$1") + '$', - params = [], - dst = {}; - forEach(when.split(/\W/), function(param) { - if (param) { - var paramRegExp = new RegExp(":" + param + "([\\W])"); - if (regex.match(paramRegExp)) { - regex = regex.replace(paramRegExp, "([^\\/]*)$1"); - params.push(param); + function switchRouteMatcher(on, when) { + // TODO(i): this code is convoluted and inefficient, we should construct the route matching + // regex only once and then reuse it + var regex = '^' + when.replace(/([\.\\\(\)\^\$])/g, "\\$1") + '$', + params = [], + dst = {}; + forEach(when.split(/\W/), function(param) { + if (param) { + var paramRegExp = new RegExp(":" + param + "([\\W])"); + if (regex.match(paramRegExp)) { + regex = regex.replace(paramRegExp, "([^\\/]*)$1"); + params.push(param); + } } - } - }); - var match = on.match(new RegExp(regex)); - if (match) { - forEach(params, function(name, index) { - dst[name] = match[index + 1]; }); + var match = on.match(new RegExp(regex)); + if (match) { + forEach(params, function(name, index) { + dst[name] = match[index + 1]; + }); + } + return match ? dst : null; } - return match ? dst : null; - } - function updateRoute() { - var next = parseRoute(), - last = $route.current, - Controller; + function updateRoute() { + var next = parseRoute(), + last = $route.current, + Controller; - if (next && last && next.$route === last.$route - && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) { - $route.current = next; - copy(next.params, $routeParams); - last.scope && last.scope.$emit('$routeUpdate'); - } else { - forceReload = false; - rootScope.$broadcast('$beforeRouteChange', next, last); - last && last.scope && last.scope.$destroy(); - $route.current = next; - if (next) { - if (next.redirectTo) { - if (isString(next.redirectTo)) { - $location.path(interpolate(next.redirectTo, next.params)).search(next.params) - .replace(); + if (next && last && next.$route === last.$route + && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) { + $route.current = next; + copy(next.params, $routeParams); + last.scope && last.scope.$emit('$routeUpdate'); + } else { + forceReload = false; + $rootScope.$broadcast('$beforeRouteChange', next, last); + last && last.scope && last.scope.$destroy(); + $route.current = next; + if (next) { + if (next.redirectTo) { + if (isString(next.redirectTo)) { + $location.path(interpolate(next.redirectTo, next.params)).search(next.params) + .replace(); + } else { + $location.url(https://github.com/next.redirectTo(next.pathParams,%20$location.path(), $location.search())) + .replace(); + } } else { - $location.url(https://github.com/next.redirectTo(next.pathParams,%20$location.path(), $location.search())) - .replace(); + copy(next.params, $routeParams); + (Controller = next.controller) && inferInjectionArgs(Controller); + next.scope = parentScope.$new(Controller); } - } else { - copy(next.params, $routeParams); - (Controller = next.controller) && inferInjectionArgs(Controller); - next.scope = parentScope.$new(Controller); } + $rootScope.$broadcast('$afterRouteChange', next, last); } - rootScope.$broadcast('$afterRouteChange', next, last); } - } - /** - * @returns the current active route, by matching it against the URL - */ - function parseRoute() { - // Match a route - var params, match; - forEach(routes, function(route, path) { - if (!match && (params = matcher($location.path(), path))) { - match = inherit(route, { - params: extend({}, $location.search(), params), - pathParams: params}); - match.$route = route; - } - }); - // No route matched; fallback to "otherwise" route - return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}}); - } + /** + * @returns the current active route, by matching it against the URL + */ + function parseRoute() { + // Match a route + var params, match; + forEach(routes, function(route, path) { + if (!match && (params = matcher($location.path(), path))) { + match = inherit(route, { + params: extend({}, $location.search(), params), + pathParams: params}); + match.$route = route; + } + }); + // No route matched; fallback to "otherwise" route + return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}}); + } - /** - * @returns interpolation of the redirect path with the parametrs - */ - function interpolate(string, params) { - var result = []; - forEach((string||'').split(':'), function(segment, i) { - if (i == 0) { - result.push(segment); - } else { - var segmentMatch = segment.match(/(\w+)(.*)/); - var key = segmentMatch[1]; - result.push(params[key]); - result.push(segmentMatch[2] || ''); - delete params[key]; - } - }); - return result.join(''); - } + /** + * @returns interpolation of the redirect path with the parametrs + */ + function interpolate(string, params) { + var result = []; + forEach((string||'').split(':'), function(segment, i) { + if (i == 0) { + result.push(segment); + } else { + var segmentMatch = segment.match(/(\w+)(.*)/); + var key = segmentMatch[1]; + result.push(params[key]); + result.push(segmentMatch[2] || ''); + delete params[key]; + } + }); + return result.join(''); + } -}, ['$location', '$routeParams']); + }]; +} diff --git a/src/service/routeParams.js b/src/service/routeParams.js index a9e201a3aa23..949bc22d1e5d 100644 --- a/src/service/routeParams.js +++ b/src/service/routeParams.js @@ -1,14 +1,14 @@ 'use strict'; /** - * @ngdoc service - * @name angular.service.$routeParams + * @ngdoc object + * @name angular.module.ng.$routeParams * @requires $route * * @description * Current set of route parameters. The route parameters are a combination of the - * {@link angular.service.$location $location} `search()`, and `path()`. The `path` parameters - * are extracted when the {@link angular.service.$route $route} path is matched. + * {@link angular.module.ng.$location $location} `search()`, and `path()`. The `path` parameters + * are extracted when the {@link angular.module.ng.$route $route} path is matched. * * In case of parameter name collision, `path` params take precedence over `search` params. * @@ -25,6 +25,6 @@ * $routeParams ==> {chapterId:1, sectionId:2, search:'moby'} * */ -angularService('$routeParams', function() { - return {}; -}); +function $RouteParamsProvider() { + this.$get = valueFn({}); +} diff --git a/src/service/scope.js b/src/service/scope.js new file mode 100644 index 000000000000..df969cfca3f9 --- /dev/null +++ b/src/service/scope.js @@ -0,0 +1,674 @@ +'use strict'; + +/** + * DESIGN NOTES + * + * The design decisions behind the scope ware heavily favored for speed and memory consumption. + * + * The typical use of scope is to watch the expressions, which most of the time return the same + * value as last time so we optimize the operation. + * + * Closures construction is expensive from speed as well as memory: + * - no closures, instead ups prototypical inheritance for API + * - Internal state needs to be stored on scope directly, which means that private state is + * exposed as $$____ properties + * + * Loop operations are optimized by using while(count--) { ... } + * - this means that in order to keep the same order of execution as addition we have to add + * items to the array at the begging (shift) instead of at the end (push) + * + * Child scopes are created and removed often + * - Using array would be slow since inserts in meddle are expensive so we use linked list + * + * There are few watches then a lot of observers. This is why you don't want the observer to be + * implemented in the same way as watch. Watch requires return of initialization function which + * are expensive to construct. + */ + +/** + * @ngdoc object + * @name angular.module.ng.$rootScope + * @description + * + * Every application has a single root {@link angular.module.ng.$rootScope.Scope scope}. + * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide + * event processing life-cycle. See {@link guide/dev_guide.scopes developer guide on scopes}. + */ +function $RootScopeProvider(){ + this.$get = ['$injector', '$exceptionHandler', '$parse', + function( $injector, $exceptionHandler, $parse){ + /** + * @ngdoc function + * @name angular.module.ng.$rootScope.Scope + * + * @description + * A root scope can be retrieved using the {@link angular.module.ng.$rootScope $rootScope} key from the + * {@link angular.module.AUTO.$injector $injector}. Child scopes are created using the + * {@link angular.module.ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when + * compiled HTML template is executed.) + * + * Here is a simple scope snippet to show how you can interact with the scope. + *
    +        angular.injector(function($rootScope) {
    +           var scope = $rootScope.$new();
    +           scope.salutation = 'Hello';
    +           scope.name = 'World';
    +
    +           expect(scope.greeting).toEqual(undefined);
    +
    +           scope.$watch('name', function() {
    +             this.greeting = this.salutation + ' ' + this.name + '!';
    +           }); // initialize the watch
    +
    +           expect(scope.greeting).toEqual(undefined);
    +           scope.name = 'Misko';
    +           // still old value, since watches have not been called yet
    +           expect(scope.greeting).toEqual(undefined);
    +
    +           scope.$digest(); // fire all  the watches
    +           expect(scope.greeting).toEqual('Hello Misko!');
    +        });
    +     * 
    + * + * # Inheritance + * A scope can inherit from a parent scope, as in this example: + *
    +         var parent = $rootScope;
    +         var child = parent.$new();
    +
    +         parent.salutation = "Hello";
    +         child.name = "World";
    +         expect(child.salutation).toEqual('Hello');
    +
    +         child.salutation = "Welcome";
    +         expect(child.salutation).toEqual('Welcome');
    +         expect(parent.salutation).toEqual('Hello');
    +     * 
    + * + * # Dependency Injection + * See {@link guide/dev_guide.di dependency injection}. + * + * + * @param {Object.=} providers Map of service factory which need to be provided + * for the current scope. Defaults to {@link angular.module.ng}. + * @param {Object.=} instanceCache Provides pre-instantiated services which should + * append/override services provided by `providers`. This is handy when unit-testing and having + * the need to override a default service. + * @returns {Object} Newly created scope. + * + */ + function Scope() { + this.$id = nextUid(); + this.$$phase = this.$parent = this.$$watchers = + this.$$nextSibling = this.$$prevSibling = + this.$$childHead = this.$$childTail = null; + this.$destructor = noop; + this['this'] = this.$root = this; + this.$$asyncQueue = []; + this.$$listeners = {}; + } + + /** + * @ngdoc property + * @name angular.module.ng.$rootScope.Scope#$id + * @propertyOf angular.module.ng.$rootScope.Scope + * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for + * debugging. + */ + + + Scope.prototype = { + /** + * @ngdoc function + * @name angular.module.ng.$rootScope.Scope#$new + * @methodOf angular.module.ng.$rootScope.Scope + * @function + * + * @description + * Creates a new child {@link angular.module.ng.$rootScope.Scope scope}. The new scope can optionally behave as a + * controller. The parent scope will propagate the {@link angular.module.ng.$rootScope.Scope#$digest $digest()} and + * {@link angular.module.ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope + * hierarchy using {@link angular.module.ng.$rootScope.Scope#$destroy $destroy()}. + * + * {@link angular.module.ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for + * the scope and its child scopes to be permanently detached from the parent and thus stop + * participating in model change detection and listener notification by invoking. + * + * @param {function()=} Class Constructor function which the scope should be applied to the scope. + * @param {...*} curryArguments Any additional arguments which are curried into the constructor. + * See {@link guide/dev_guide.di dependency injection}. + * @returns {Object} The newly created child scope. + * + */ + $new: function(Class, curryArguments) { + var Child = function() {}; // should be anonymous; This is so that when the minifier munges + // the name it does not become random set of chars. These will then show up as class + // name in the debugger. + var child; + Child.prototype = this; + child = new Child(); + child['this'] = child; + child.$$listeners = {}; + child.$parent = this; + child.$id = nextUid(); + child.$$asyncQueue = []; + child.$$phase = child.$$watchers = + child.$$nextSibling = child.$$childHead = child.$$childTail = null; + child.$$prevSibling = this.$$childTail; + if (this.$$childHead) { + this.$$childTail.$$nextSibling = child; + this.$$childTail = child; + } else { + this.$$childHead = this.$$childTail = child; + } + // short circuit if we have no class + if (Class) { + // can't use forEach, we need speed! + var ClassPrototype = Class.prototype; + for(var key in ClassPrototype) { + child[key] = bind(child, ClassPrototype[key]); + } + $injector.invoke(child, Class, curryArguments); + } + return child; + }, + + /** + * @ngdoc function + * @name angular.module.ng.$rootScope.Scope#$watch + * @methodOf angular.module.ng.$rootScope.Scope + * @function + * + * @description + * Registers a `listener` callback to be executed whenever the `watchExpression` changes. + * + * - The `watchExpression` is called on every call to {@link angular.module.ng.$rootScope.Scope#$digest $digest()} and + * should return the value which will be watched. (Since {@link angular.module.ng.$rootScope.Scope#$digest $digest()} + * reruns when it detects changes the `watchExpression` can execute multiple times per + * {@link angular.module.ng.$rootScope.Scope#$digest $digest()} and should be idempotent.) + * - The `listener` is called only when the value from the current `watchExpression` and the + * previous call to `watchExpression' are not equal. The inequality is determined according to + * {@link angular.equals} function. To save the value of the object for later comparison + * {@link angular.copy} function is used. It also means that watching complex options will + * have adverse memory and performance implications. + * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This + * is achieved by rerunning the watchers until no changes are detected. The rerun iteration + * limit is 100 to prevent infinity loop deadlock. + * + * + * If you want to be notified whenever {@link angular.module.ng.$rootScope.Scope#$digest $digest} is called, + * you can register an `watchExpression` function with no `listener`. (Since `watchExpression`, + * can execute multiple times per {@link angular.module.ng.$rootScope.Scope#$digest $digest} cycle when a change is + * detected, be prepared for multiple calls to your listener.) + * + * + * # Example +
    +           var scope = angular.module.ng.$rootScope.Scope();
    +           scope.name = 'misko';
    +           scope.counter = 0;
    +
    +           expect(scope.counter).toEqual(0);
    +           scope.$watch('name', function(scope, newValue, oldValue) { counter = counter + 1; });
    +           expect(scope.counter).toEqual(0);
    +
    +           scope.$digest();
    +           // no variable change
    +           expect(scope.counter).toEqual(0);
    +
    +           scope.name = 'adam';
    +           scope.$digest();
    +           expect(scope.counter).toEqual(1);
    +         
    + * + * + * + * @param {(function()|string)} watchExpression Expression that is evaluated on each + * {@link angular.module.ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a + * call to the `listener`. + * + * - `string`: Evaluated as {@link guide/dev_guide.expressions expression} + * - `function(scope)`: called with current `scope` as a parameter. + * @param {(function()|string)=} listener Callback called whenever the return value of + * the `watchExpression` changes. + * + * - `string`: Evaluated as {@link guide/dev_guide.expressions expression} + * - `function(scope, newValue, oldValue)`: called with current `scope` an previous and + * current values as parameters. + * @returns {function()} Returns a deregistration function for this listener. + */ + $watch: function(watchExp, listener) { + var scope = this, + get = compileToFn(watchExp, 'watch'), + listenFn = compileToFn(listener || noop, 'listener'), + array = scope.$$watchers, + watcher = { + fn: listenFn, + last: Number.NaN, // NaN !== NaN. We used this to force $watch to fire on first run. + get: get, + exp: watchExp + }; + + if (!array) { + array = scope.$$watchers = []; + } + // we use unshift since we use a while loop in $digest for speed. + // the while loop reads in reverse order. + array.unshift(watcher); + + return function() { + arrayRemove(array, watcher); + }; + }, + + /** + * @ngdoc function + * @name angular.module.ng.$rootScope.Scope#$digest + * @methodOf angular.module.ng.$rootScope.Scope + * @function + * + * @description + * Process all of the {@link angular.module.ng.$rootScope.Scope#$watch watchers} of the current scope and its children. + * Because a {@link angular.module.ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the + * `$digest()` keeps calling the {@link angular.module.ng.$rootScope.Scope#$watch watchers} until no more listeners are + * firing. This means that it is possible to get into an infinite loop. This function will throw + * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 100. + * + * Usually you don't call `$digest()` directly in + * {@link angular.directive.ng:controller controllers} or in {@link angular.directive directives}. + * Instead a call to {@link angular.module.ng.$rootScope.Scope#$apply $apply()} (typically from within a + * {@link angular.directive directive}) will force a `$digest()`. + * + * If you want to be notified whenever `$digest()` is called, + * you can register a `watchExpression` function with {@link angular.module.ng.$rootScope.Scope#$watch $watch()} + * with no `listener`. + * + * You may have a need to call `$digest()` from within unit-tests, to simulate the scope + * life-cycle. + * + * # Example +
    +           var scope = ...;
    +           scope.name = 'misko';
    +           scope.counter = 0;
    +
    +           expect(scope.counter).toEqual(0);
    +           scope.$digest('name', function(scope, newValue, oldValue) {
    +             counter = counter + 1;
    +           });
    +           expect(scope.counter).toEqual(0);
    +
    +           scope.$digest();
    +           // no variable change
    +           expect(scope.counter).toEqual(0);
    +
    +           scope.name = 'adam';
    +           scope.$digest();
    +           expect(scope.counter).toEqual(1);
    +         
    + * + */ + $digest: function() { + var watch, value, last, + watchers, + asyncQueue, + length, + dirty, ttl = 100, + next, current, target = this, + watchLog = []; + + if (target.$$phase) { + throw Error(target.$$phase + ' already in progress'); + } + do { + + dirty = false; + current = target; + do { + current.$$phase = '$digest'; + asyncQueue = current.$$asyncQueue; + while(asyncQueue.length) { + try { + current.$eval(asyncQueue.shift()); + } catch (e) { + $exceptionHandler(e); + } + } + if ((watchers = current.$$watchers)) { + // process our watches + length = watchers.length; + while (length--) { + try { + watch = watchers[length]; + // Most common watches are on primitives, in which case we can short + // circuit it with === operator, only when === fails do we use .equals + if ((value = watch.get(current)) !== (last = watch.last) && !equals(value, last)) { + dirty = true; + watch.last = copy(value); + watch.fn(current, value, last); + if (ttl < 5) { + if (!watchLog[4-ttl]) watchLog[4-ttl] = []; + if (isFunction(watch.exp)) { + watchLog[4-ttl].push('fn: ' + (watch.exp.name || watch.exp.toString())); + } else { + watchLog[4-ttl].push(watch.exp); + } + } + } + } catch (e) { + $exceptionHandler(e); + } + } + } + + current.$$phase = null; + + // Insanity Warning: scope depth-first traversal + // yes, this code is a bit crazy, but it works and we have tests to prove it! + // this piece should be kept in sync with the traversal in $broadcast + if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) { + while(current !== target && !(next = current.$$nextSibling)) { + current = current.$parent; + } + } + } while ((current = next)); + + if(!(ttl--)) { + throw Error('100 $digest() iterations reached. Aborting!\n' + + 'Watchers fired in the last 5 iterations: ' + toJson(watchLog)); + } + } while (dirty); + }, + + /** + * @ngdoc function + * @name angular.module.ng.$rootScope.Scope#$destroy + * @methodOf angular.module.ng.$rootScope.Scope + * @function + * + * @description + * Remove the current scope (and all of its children) from the parent scope. Removal implies + * that calls to {@link angular.module.ng.$rootScope.Scope#$digest $digest()} will no longer propagate to the current + * scope and its children. Removal also implies that the current scope is eligible for garbage + * collection. + * + * The destructing scope emits an `$destroy` {@link angular.module.ng.$rootScope.Scope#$emit event}. + * + * The `$destroy()` is usually used by directives such as + * {@link angular.widget.@ng:repeat ng:repeat} for managing the unrolling of the loop. + * + */ + $destroy: function() { + if (this.$root == this) return; // we can't remove the root node; + this.$emit('$destroy'); + var parent = this.$parent; + + if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; + if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; + if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; + if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; + }, + + /** + * @ngdoc function + * @name angular.module.ng.$rootScope.Scope#$eval + * @methodOf angular.module.ng.$rootScope.Scope + * @function + * + * @description + * Executes the `expression` on the current scope returning the result. Any exceptions in the + * expression are propagated (uncaught). This is useful when evaluating engular expressions. + * + * # Example +
    +           var scope = angular.module.ng.$rootScope.Scope();
    +           scope.a = 1;
    +           scope.b = 2;
    +
    +           expect(scope.$eval('a+b')).toEqual(3);
    +           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
    +         
    + * + * @param {(string|function())=} expression An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/dev_guide.expressions expression}. + * - `function(scope)`: execute the function with the current `scope` parameter. + * + * @returns {*} The result of evaluating the expression. + */ + $eval: function(expr) { + return $parse(expr)(this); + }, + + /** + * @ngdoc function + * @name angular.module.ng.$rootScope.Scope#$evalAsync + * @methodOf angular.module.ng.$rootScope.Scope + * @function + * + * @description + * Executes the expression on the current scope at a later point in time. + * + * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that: + * + * - it will execute in the current script execution context (before any DOM rendering). + * - at least one {@link angular.module.ng.$rootScope.Scope#$digest $digest cycle} will be performed after + * `expression` execution. + * + * Any exceptions from the execution of the expression are forwarded to the + * {@link angular.module.ng.$exceptionHandler $exceptionHandler} service. + * + * @param {(string|function())=} expression An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/dev_guide.expressions expression}. + * - `function(scope)`: execute the function with the current `scope` parameter. + * + */ + $evalAsync: function(expr) { + this.$$asyncQueue.push(expr); + }, + + /** + * @ngdoc function + * @name angular.module.ng.$rootScope.Scope#$apply + * @methodOf angular.module.ng.$rootScope.Scope + * @function + * + * @description + * `$apply()` is used to execute an expression in angular from outside of the angular framework. + * (For example from browser DOM events, setTimeout, XHR or third party libraries). + * Because we are calling into the angular framework we need to perform proper scope life-cycle + * of {@link angular.module.ng.$exceptionHandler exception handling}, + * {@link angular.module.ng.$rootScope.Scope#$digest executing watches}. + * + * ## Life cycle + * + * # Pseudo-Code of `$apply()` + function $apply(expr) { + try { + return $eval(expr); + } catch (e) { + $exceptionHandler(e); + } finally { + $root.$digest(); + } + } + * + * + * Scope's `$apply()` method transitions through the following stages: + * + * 1. The {@link guide/dev_guide.expressions expression} is executed using the + * {@link angular.module.ng.$rootScope.Scope#$eval $eval()} method. + * 2. Any exceptions from the execution of the expression are forwarded to the + * {@link angular.module.ng.$exceptionHandler $exceptionHandler} service. + * 3. The {@link angular.module.ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression + * was executed using the {@link angular.module.ng.$rootScope.Scope#$digest $digest()} method. + * + * + * @param {(string|function())=} exp An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/dev_guide.expressions expression}. + * - `function(scope)`: execute the function with current `scope` parameter. + * + * @returns {*} The result of evaluating the expression. + */ + $apply: function(expr) { + try { + return this.$eval(expr); + } catch (e) { + $exceptionHandler(e); + } finally { + this.$root.$digest(); + } + }, + + /** + * @ngdoc function + * @name angular.module.ng.$rootScope.Scope#$on + * @methodOf angular.module.ng.$rootScope.Scope + * @function + * + * @description + * Listen on events of a given type. See {@link angular.module.ng.$rootScope.Scope#$emit $emit} for discussion of + * event life cycle. + * + * @param {string} name Event name to listen on. + * @param {function(event)} listener Function to call when the event is emitted. + * @returns {function()} Returns a deregistration function for this listener. + * + * The event listener function format is: `function(event)`. The `event` object passed into the + * listener has the following attributes + * - `targetScope` - {Scope}: the scope on which the event was `$emit`-ed or `$broadcast`-ed. + * - `currentScope` - {Scope}: the current scope which is handling the event. + * - `name` - {string}: Name of the event. + * - `cancel` - {function=}: calling `cancel` function will cancel further event propagation + * (available only for events that were `$emit`-ed). + */ + $on: function(name, listener) { + var namedListeners = this.$$listeners[name]; + if (!namedListeners) { + this.$$listeners[name] = namedListeners = []; + } + namedListeners.push(listener); + + return function() { + arrayRemove(namedListeners, listener); + }; + }, + + + /** + * @ngdoc function + * @name angular.module.ng.$rootScope.Scope#$emit + * @methodOf angular.module.ng.$rootScope.Scope + * @function + * + * @description + * Dispatches an event `name` upwards through the scope hierarchy notifying the + * registered {@link angular.module.ng.$rootScope.Scope#$on} listeners. + * + * The event life cycle starts at the scope on which `$emit` was called. All + * {@link angular.module.ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified. + * Afterwards, the event traverses upwards toward the root scope and calls all registered + * listeners along the way. The event will stop propagating if one of the listeners cancels it. + * + * Any exception emmited from the {@link angular.module.ng.$rootScope.Scope#$on listeners} will be passed + * onto the {@link angular.module.ng.$exceptionHandler $exceptionHandler} service. + * + * @param {string} name Event name to emit. + * @param {...*} args Optional set of arguments which will be passed onto the event listeners. + */ + $emit: function(name, args) { + var empty = [], + namedListeners, + canceled = false, + scope = this, + event = { + name: name, + targetScope: scope, + cancel: function() {canceled = true;} + }, + listenerArgs = concat([event], arguments, 1), + i, length; + + do { + namedListeners = scope.$$listeners[name] || empty; + event.currentScope = scope; + for (i=0, length=namedListeners.length; i 7) - }; -}, ['$window']); + return { + history: !!($window.history && $window.history.pushState), + hashchange: 'onhashchange' in $window && + // IE8 compatible mode lies + (!$window.document.documentMode || $window.document.documentMode > 7) + }; + }]; +} diff --git a/src/service/window.js b/src/service/window.js index bc264e302a5f..7bb3dfcab269 100644 --- a/src/service/window.js +++ b/src/service/window.js @@ -1,8 +1,8 @@ 'use strict'; /** - * @ngdoc service - * @name angular.service.$window + * @ngdoc object + * @name angular.module.ng.$window * * @description * A reference to the browser's `window` object. While `window` @@ -23,4 +23,6 @@ */ -angularServiceInject("$window", bind(window, identity, window)); +function $WindowProvider(){ + this.$get = valueFn(window); +} diff --git a/src/service/xhr.bulk.js b/src/service/xhr.bulk.js index 33c9384b8a48..fca96dde33c2 100644 --- a/src/service/xhr.bulk.js +++ b/src/service/xhr.bulk.js @@ -1,8 +1,8 @@ 'use strict'; /** - * @ngdoc service - * @name angular.service.$xhr.bulk + * @ngdoc object + * @name angular.module.ng.$xhr.bulk * @requires $xhr * @requires $xhr.error * @requires $log @@ -11,77 +11,79 @@ * * @example */ -angularServiceInject('$xhr.bulk', function($xhr, $error, $log){ - var requests = [], - scope = this; - function bulkXHR(method, url, post, success, error) { - if (isFunction(post)) { - error = success; - success = post; - post = null; - } - var currentQueue; - forEach(bulkXHR.urls, function(queue){ - if (isFunction(queue.match) ? queue.match(url) : queue.match.exec(url)) { - currentQueue = queue; +function $XhrBulkProvider() { + this.$get = ['$rootScope', '$xhr', '$xhr.error', '$log', + function( $rootScope, $xhr, $error, $log) { + var requests = []; + function bulkXHR(method, url, post, success, error) { + if (isFunction(post)) { + error = success; + success = post; + post = null; + } + var currentQueue; + forEach(bulkXHR.urls, function(queue){ + if (isFunction(queue.match) ? queue.match(url) : queue.match.exec(url)) { + currentQueue = queue; + } + }); + if (currentQueue) { + if (!currentQueue.requests) currentQueue.requests = []; + var request = { + method: method, + url: url, + data: post, + success: success}; + if (error) request.error = error; + currentQueue.requests.push(request); + } else { + $xhr(method, url, post, success, error); } - }); - if (currentQueue) { - if (!currentQueue.requests) currentQueue.requests = []; - var request = { - method: method, - url: url, - data: post, - success: success}; - if (error) request.error = error; - currentQueue.requests.push(request); - } else { - $xhr(method, url, post, success, error); } - } - bulkXHR.urls = {}; - bulkXHR.flush = function(success, errorback) { - assertArgFn(success = success || noop, 0); - assertArgFn(errorback = errorback || noop, 1); - forEach(bulkXHR.urls, function(queue, url) { - var currentRequests = queue.requests; - if (currentRequests && currentRequests.length) { - queue.requests = []; - queue.callbacks = []; - $xhr('POST', url, {requests: currentRequests}, - function(code, response) { - forEach(response, function(response, i) { - try { - if (response.status == 200) { - (currentRequests[i].success || noop)(response.status, response.response); - } else if (isFunction(currentRequests[i].error)) { - currentRequests[i].error(response.status, response.response); - } else { - $error(currentRequests[i], response); + bulkXHR.urls = {}; + bulkXHR.flush = function(success, errorback) { + assertArgFn(success = success || noop, 0); + assertArgFn(errorback = errorback || noop, 1); + forEach(bulkXHR.urls, function(queue, url) { + var currentRequests = queue.requests; + if (currentRequests && currentRequests.length) { + queue.requests = []; + queue.callbacks = []; + $xhr('POST', url, {requests: currentRequests}, + function(code, response) { + forEach(response, function(response, i) { + try { + if (response.status == 200) { + (currentRequests[i].success || noop)(response.status, response.response); + } else if (isFunction(currentRequests[i].error)) { + currentRequests[i].error(response.status, response.response); + } else { + $error(currentRequests[i], response); + } + } catch(e) { + $log.error(e); } - } catch(e) { - $log.error(e); - } - }); - success(); - }, - function(code, response) { - forEach(currentRequests, function(request, i) { - try { - if (isFunction(request.error)) { - request.error(code, response); - } else { - $error(request, response); + }); + success(); + }, + function(code, response) { + forEach(currentRequests, function(request, i) { + try { + if (isFunction(request.error)) { + request.error(code, response); + } else { + $error(request, response); + } + } catch(e) { + $log.error(e); } - } catch(e) { - $log.error(e); - } + }); + noop(); }); - noop(); - }); - } - }); - }; - this.$watch(function() { bulkXHR.flush(); }); - return bulkXHR; -}, ['$xhr', '$xhr.error', '$log']); + } + }); + }; + $rootScope.$watch(function() { bulkXHR.flush(); }); + return bulkXHR; + }]; +} diff --git a/src/service/xhr.cache.js b/src/service/xhr.cache.js index 630caa5b8f4e..8a14ad99590f 100644 --- a/src/service/xhr.cache.js +++ b/src/service/xhr.cache.js @@ -1,8 +1,8 @@ 'use strict'; /** - * @ngdoc service - * @name angular.service.$xhr.cache + * @ngdoc object + * @name angular.module.ng.$xhr.cache * @function * * @requires $xhr.bulk @@ -11,11 +11,11 @@ * @requires $log * * @description - * Acts just like the {@link angular.service.$xhr $xhr} service but caches responses for `GET` + * Acts just like the {@link angular.module.ng.$xhr $xhr} service but caches responses for `GET` * requests. All cache misses are delegated to the $xhr service. * * @property {function()} delegate Function to delegate all the cache misses to. Defaults to - * the {@link angular.service.$xhr $xhr} service. + * the {@link angular.module.ng.$xhr $xhr} service. * @property {object} data The hashmap where all cached entries are stored. * * @param {string} method HTTP method. @@ -28,87 +28,91 @@ * cached entry. The `success` function will be called when the response is received. * @param {boolean=} [sync=false] in case of cache hit execute `success` synchronously. */ -angularServiceInject('$xhr.cache', function($xhr, $defer, $error, $log) { - var inflight = {}, self = this; - function cache(method, url, post, success, error, verifyCache, sync) { - if (isFunction(post)) { - if (!isFunction(success)) { - verifyCache = success; - sync = error; - error = null; - } else { +function $XhrCacheProvider() { + this.$get = ['$xhr.bulk', '$defer', '$xhr.error', '$log', + function($xhr, $defer, $error, $log) { + var inflight = {}; + function cache(method, url, post, success, error, verifyCache, sync) { + if (isFunction(post)) { + if (!isFunction(success)) { + verifyCache = success; + sync = error; + error = null; + } else { + sync = verifyCache; + verifyCache = error; + error = success; + } + success = post; + post = null; + } else if (!isFunction(error)) { sync = verifyCache; verifyCache = error; - error = success; + error = null; } - success = post; - post = null; - } else if (!isFunction(error)) { - sync = verifyCache; - verifyCache = error; - error = null; - } - if (method == 'GET') { - var data, dataCached; - if ((dataCached = cache.data[url])) { + if (method == 'GET') { + var data, dataCached; + if ((dataCached = cache.data[url])) { - if (sync) { - success(200, copy(dataCached.value)); - } else { - $defer(function() { success(200, copy(dataCached.value)); }); - } + if (sync) { + success(200, copy(dataCached.value)); + } else { + $defer(function() { success(200, copy(dataCached.value)); }); + } - if (!verifyCache) - return; - } + if (!verifyCache) + return; + } - if ((data = inflight[url])) { - data.successes.push(success); - data.errors.push(error); - } else { - inflight[url] = {successes: [success], errors: [error]}; - cache.delegate(method, url, post, - function(status, response) { - if (status == 200) - cache.data[url] = {value: response}; - var successes = inflight[url].successes; - delete inflight[url]; - forEach(successes, function(success) { - try { - (success||noop)(status, copy(response)); - } catch(e) { - $log.error(e); - } - }); - }, - function(status, response) { - var errors = inflight[url].errors, - successes = inflight[url].successes; - delete inflight[url]; + if ((data = inflight[url])) { + data.successes.push(success); + data.errors.push(error); + } else { + inflight[url] = {successes: [success], errors: [error]}; + cache.delegate(method, url, post, + function(status, response) { + if (status == 200) + cache.data[url] = {value: response}; + var successes = inflight[url].successes; + delete inflight[url]; + forEach(successes, function(success) { + try { + (success||noop)(status, copy(response)); + } catch(e) { + $log.error(e); + } + }); + }, + function(status, response) { + var errors = inflight[url].errors, + successes = inflight[url].successes; + delete inflight[url]; - forEach(errors, function(error, i) { - try { - if (isFunction(error)) { - error(status, copy(response)); - } else { - $error( - {method: method, url: url, data: post, success: successes[i]}, - {status: status, body: response}); + forEach(errors, function(error, i) { + try { + if (isFunction(error)) { + error(status, copy(response)); + } else { + $error( + {method: method, url: url, data: post, success: successes[i]}, + {status: status, body: response}); + } + } catch(e) { + $log.error(e); } - } catch(e) { - $log.error(e); - } + }); }); - }); - } + } - } else { - cache.data = {}; - cache.delegate(method, url, post, success, error); + } else { + cache.data = {}; + cache.delegate(method, url, post, success, error); + } } - } - cache.data = {}; - cache.delegate = $xhr; - return cache; -}, ['$xhr.bulk', '$defer', '$xhr.error', '$log']); + cache.data = {}; + cache.delegate = $xhr; + return cache; + }]; + +} diff --git a/src/service/xhr.error.js b/src/service/xhr.error.js index 01fb8fff9841..372f97f46888 100644 --- a/src/service/xhr.error.js +++ b/src/service/xhr.error.js @@ -1,15 +1,15 @@ 'use strict'; /** - * @ngdoc service - * @name angular.service.$xhr.error + * @ngdoc object + * @name angular.module.ng.$xhr.error * @function * @requires $log * * @description - * Error handler for {@link angular.service.$xhr $xhr service}. An application can replaces this + * Error handler for {@link angular.module.ng.$xhr $xhr service}. An application can replaces this * service with one specific for the application. The default implementation logs the error to - * {@link angular.service.$log $log.error}. + * {@link angular.module.ng.$log $log.error}. * * @param {Object} request Request object. * @@ -35,8 +35,10 @@ */ -angularServiceInject('$xhr.error', function($log){ - return function(request, response){ - $log.error('ERROR: XHR: ' + request.url, request, response); - }; -}, ['$log']); +function $XhrErrorProvider() { + this.$get = ['$log', function($log) { + return function(request, response){ + $log.error('ERROR: XHR: ' + request.url, request, response); + }; + }]; +} diff --git a/src/service/xhr.js b/src/service/xhr.js index fe7d42d9c8cc..d9c78fd65729 100644 --- a/src/service/xhr.js +++ b/src/service/xhr.js @@ -1,8 +1,8 @@ 'use strict'; /** - * @ngdoc service - * @name angular.service.$xhr + * @ngdoc object + * @name angular.module.ng.$xhr * @function * @requires $browser $xhr delegates all XHR requests to the `$browser.xhr()`. A mock version * of the $browser exists which allows setting expectations on XHR requests @@ -12,14 +12,14 @@ * * @description * Generates an XHR request. The $xhr service delegates all requests to - * {@link angular.service.$browser $browser.xhr()} and adds error handling and security features. + * {@link angular.module.ng.$browser $browser.xhr()} and adds error handling and security features. * While $xhr service provides nicer api than raw XmlHttpRequest, it is still considered a lower * level api in angular. For a higher level abstraction that utilizes `$xhr`, please check out the - * {@link angular.service.$resource $resource} service. + * {@link angular.module.ng.$resource $resource} service. * * # Error handling * If no `error callback` is specified, XHR response with response code other then `2xx` will be - * delegated to {@link angular.service.$xhr.error $xhr.error}. The `$xhr.error` can intercept the + * delegated to {@link angular.module.ng.$xhr.error $xhr.error}. The `$xhr.error` can intercept the * request and process it in application specific way, or resume normal execution by calling the * request `success` method. * @@ -98,7 +98,7 @@ * * - {number} code [HTTP status code](http://en.wikipedia.org/wiki/List_of_HTTP_status_codes) of * the response. This will currently always be 200, since all non-200 responses are routed to - * {@link angular.service.$xhr.error} service (or custom error callback). + * {@link angular.module.ng.$xhr.error} service (or custom error callback). * - {string|Object} response Response object as string or an Object if the response was in JSON * format. * @param {function(number, (string|Object))} error A function to be called if the response code is @@ -171,59 +171,61 @@ */ -angularServiceInject('$xhr', function($browser, $error, $log){ - var rootScope = this; - var xhrHeaderDefaults = { - common: { - "Accept": "application/json, text/plain, */*", - "X-Requested-With": "XMLHttpRequest" - }, - post: {'Content-Type': 'application/x-www-form-urlencoded'}, - get: {}, // all these empty properties are needed so that client apps can just do: - head: {}, // $xhr.defaults.headers.head.foo="bar" without having to create head object - put: {}, // it also means that if we add a header for these methods in the future, it - 'delete': {}, // won't be easily silently lost due to an object assignment. - patch: {} - }; +function $XhrProvider() { + this.$get = ['$rootScope', '$browser', '$xhr.error', '$log', + function( $rootScope, $browser, $error, $log){ + var xhrHeaderDefaults = { + common: { + "Accept": "application/json, text/plain, */*", + "X-Requested-With": "XMLHttpRequest" + }, + post: {'Content-Type': 'application/x-www-form-urlencoded'}, + get: {}, // all these empty properties are needed so that client apps can just do: + head: {}, // $xhr.defaults.headers.head.foo="bar" without having to create head object + put: {}, // it also means that if we add a header for these methods in the future, it + 'delete': {}, // won't be easily silently lost due to an object assignment. + patch: {} + }; - function xhr(method, url, post, success, error) { - if (isFunction(post)) { - error = success; - success = post; - post = null; - } - if (post && isObject(post)) { - post = toJson(post); - } + function xhr(method, url, post, success, error) { + if (isFunction(post)) { + error = success; + success = post; + post = null; + } + if (post && isObject(post)) { + post = toJson(post); + } - $browser.xhr(method, url, post, function(code, response){ - try { - if (isString(response)) { - if (response.match(/^\)\]\}',\n/)) response=response.substr(6); - if (/^\s*[\[\{]/.exec(response) && /[\}\]]\s*$/.exec(response)) { - response = fromJson(response, true); + $browser.xhr(method, url, post, function(code, response){ + try { + if (isString(response)) { + if (response.match(/^\)\]\}',\n/)) response=response.substr(6); + if (/^\s*[\[\{]/.exec(response) && /[\}\]]\s*$/.exec(response)) { + response = fromJson(response, true); + } } + $rootScope.$apply(function() { + if (200 <= code && code < 300) { + success(code, response); + } else if (isFunction(error)) { + error(code, response); + } else { + $error( + {method: method, url: url, data: post, success: success}, + {status: code, body: response}); + } + }); + } catch (e) { + $log.error(e); } - rootScope.$apply(function() { - if (200 <= code && code < 300) { - success(code, response); - } else if (isFunction(error)) { - error(code, response); - } else { - $error( - {method: method, url: url, data: post, success: success}, - {status: code, body: response}); - } - }); - } catch (e) { - $log.error(e); - } - }, extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']}, - xhrHeaderDefaults.common, - xhrHeaderDefaults[lowercase(method)])); - } + }, extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']}, + xhrHeaderDefaults.common, + xhrHeaderDefaults[lowercase(method)])); + } - xhr.defaults = {headers: xhrHeaderDefaults}; + xhr.defaults = {headers: xhrHeaderDefaults}; - return xhr; -}, ['$browser', '$xhr.error', '$log']); + return xhr; + }]; +} diff --git a/src/widget/form.js b/src/widget/form.js index 065ee74dc0a6..51864cf0037a 100644 --- a/src/widget/form.js +++ b/src/widget/form.js @@ -6,7 +6,7 @@ * * @description * Angular widget that creates a form scope using the - * {@link angular.service.$formFactory $formFactory} API. The resulting form scope instance is + * {@link angular.module.ng.$formFactory $formFactory} API. The resulting form scope instance is * attached to the DOM element using the jQuery `.data()` method under the `$form` key. * See {@link guide/dev_guide.forms forms} on detailed discussion of forms and widgets. * @@ -56,7 +56,7 @@ angularWidget('form', function(form){ this.descend(true); this.directives(true); - return annotate('$formFactory', function($formFactory, formElement) { + return ['$formFactory', '$element', function($formFactory, formElement) { var name = formElement.attr('name'), parentForm = $formFactory.forElement(formElement), form = $formFactory(parentForm); @@ -74,7 +74,7 @@ angularWidget('form', function(form){ formElement[value ? 'addClass' : 'removeClass']('ng-' + name); }); } - }); + }]; }); angularWidget('ng:form', angularWidget('form')); diff --git a/src/widget/input.js b/src/widget/input.js index cf29d0f1ac54..016e23537d5c 100644 --- a/src/widget/input.js +++ b/src/widget/input.js @@ -569,7 +569,7 @@ angularInputType('radio', function(inputElement) { function numericRegexpInputType(regexp, error) { - return function(inputElement) { + return ['$element', function(inputElement) { var widget = this, min = 1 * (inputElement.attr('min') || Number.MIN_VALUE), max = 1 * (inputElement.attr('max') || Number.MAX_VALUE); @@ -598,7 +598,7 @@ function numericRegexpInputType(regexp, error) { widget.$viewValue = '' + widget.$modelValue; } }; - }; + }]; } @@ -617,7 +617,7 @@ var HTML5_INPUTS_TYPES = makeMap( * * The {@link angular.inputType custom angular.inputType}s provide a shorthand for declaring new * inputs. This is a sharthand for text-box based inputs, and there is no need to go through the - * full {@link angular.service.$formFactory $formFactory} widget lifecycle. + * full {@link angular.module.ng.$formFactory $formFactory} widget lifecycle. * * * @param {string} type Widget types as defined by {@link angular.inputType}. If the @@ -713,7 +713,7 @@ angularWidget('input', function(inputElement){ this.descend(true); var modelExp = inputElement.attr('ng:model'); return modelExp && - annotate('$defer', '$formFactory', function($defer, $formFactory, inputElement){ + ['$defer', '$formFactory', '$element', function($defer, $formFactory, inputElement){ var form = $formFactory.forElement(inputElement), // We have to use .getAttribute, since jQuery tries to be smart and use the // type property. Trouble is some browser change unknown to text. @@ -761,14 +761,16 @@ angularWidget('input', function(inputElement){ } } - !TypeController.$inject && (TypeController.$inject = []); + //TODO(misko): setting $inject is a hack + !TypeController.$inject && (TypeController.$inject = ['$element']); widget = form.$createWidget({ scope: modelScope, model: modelExp, onChange: inputElement.attr('ng:change'), alias: inputElement.attr('name'), controller: TypeController, - controllerArgs: [inputElement]}); + controllerArgs: {$element: inputElement} + }); watchElementProperty(this, widget, 'value', inputElement); watchElementProperty(this, widget, 'required', inputElement); @@ -830,7 +832,7 @@ angularWidget('input', function(inputElement){ } }); } - }); + }]; }); diff --git a/src/widget/select.js b/src/widget/select.js index 9b9ed1727bc8..e66d4cba487a 100644 --- a/src/widget/select.js +++ b/src/widget/select.js @@ -130,7 +130,9 @@ var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+ angularWidget('select', function(element){ this.directives(true); this.descend(true); - return element.attr('ng:model') && annotate('$formFactory', function($formFactory, selectElement){ + return element.attr('ng:model') && + ['$formFactory', '$compile', '$parse', '$element', + function($formFactory, $compile, $parse, selectElement){ var modelScope = this, match, form = $formFactory.forElement(selectElement), @@ -223,12 +225,12 @@ angularWidget('select', function(element){ } var widgetScope = this, - displayFn = expressionCompile(match[2] || match[1]), + displayFn = $parse(match[2] || match[1]), valueName = match[4] || match[6], keyName = match[5], - groupByFn = expressionCompile(match[3] || ''), - valueFn = expressionCompile(match[2] ? match[1] : valueName), - valuesFn = expressionCompile(match[7]), + groupByFn = $parse(match[3] || ''), + valueFn = $parse(match[2] ? match[1] : valueName), + valuesFn = $parse(match[7]), // we can't just jqLite('
    ', sortedHtml(scope.$element)); - }); + '
', sortedHtml(element)); + })); - it('HideBindingExpression', function() { - var scope = this.compile('
'); + it('HideBindingExpression', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); - scope.hidden = 3; - scope.$apply(); + $rootScope.hidden = 3; + $rootScope.$apply(); - assertHidden(scope.$element); + assertHidden(element); - scope.hidden = 2; - scope.$apply(); + $rootScope.hidden = 2; + $rootScope.$apply(); - assertVisible(scope.$element); - }); + assertVisible(element); + })); - it('HideBinding', function() { - var scope = this.compile('
'); + it('HideBinding', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); - scope.hidden = 'true'; - scope.$apply(); + $rootScope.hidden = 'true'; + $rootScope.$apply(); - assertHidden(scope.$element); + assertHidden(element); - scope.hidden = 'false'; - scope.$apply(); + $rootScope.hidden = 'false'; + $rootScope.$apply(); - assertVisible(scope.$element); + assertVisible(element); - scope.hidden = ''; - scope.$apply(); + $rootScope.hidden = ''; + $rootScope.$apply(); - assertVisible(scope.$element); - }); + assertVisible(element); + })); - it('ShowBinding', function() { - var scope = this.compile('
'); + it('ShowBinding', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); - scope.show = 'true'; - scope.$apply(); + $rootScope.show = 'true'; + $rootScope.$apply(); - assertVisible(scope.$element); + assertVisible(element); - scope.show = 'false'; - scope.$apply(); + $rootScope.show = 'false'; + $rootScope.$apply(); - assertHidden(scope.$element); + assertHidden(element); - scope.show = ''; - scope.$apply(); + $rootScope.show = ''; + $rootScope.$apply(); - assertHidden(scope.$element); - }); + assertHidden(element); + })); - it('BindClass', function() { - var scope = this.compile('
'); + it('BindClass', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); - scope.clazz = 'testClass'; - scope.$apply(); + $rootScope.clazz = 'testClass'; + $rootScope.$apply(); - assertEquals('
', sortedHtml(scope.$element)); + assertEquals('
', sortedHtml(element)); - scope.clazz = ['a', 'b']; - scope.$apply(); + $rootScope.clazz = ['a', 'b']; + $rootScope.$apply(); - assertEquals('
', sortedHtml(scope.$element)); - }); + assertEquals('
', sortedHtml(element)); + })); - it('BindClassEvenOdd', function() { - var scope = this.compile('
'); - scope.$apply(); - var d1 = jqLite(scope.$element[0].childNodes[1]); - var d2 = jqLite(scope.$element[0].childNodes[2]); + it('BindClassEvenOdd', inject(function($rootScope, $compile) { + var element = $compile( + '
' + + '
' + + '
')($rootScope); + $rootScope.$apply(); + var d1 = jqLite(element[0].childNodes[1]); + var d2 = jqLite(element[0].childNodes[2]); expect(d1.hasClass('o')).toBeTruthy(); expect(d2.hasClass('e')).toBeTruthy(); assertEquals( '
<#comment>' + '
' + '
', - sortedHtml(scope.$element)); - }); - - it('BindStyle', function() { - var scope = this.compile('
'); - - scope.$eval('style={height: "10px"}'); - scope.$apply(); - - assertEquals("10px", scope.$element.css('height')); - - scope.$eval('style={}'); - scope.$apply(); - }); - - it('ActionOnAHrefThrowsError', function() { - var scope = this.compile('Add Phone', null, true); - scope.action = function() { - throw new Error('MyError'); - }; - var input = scope.$element; - browserTrigger(input, 'click'); - expect(scope.$service('$exceptionHandler').errors[0]).toMatch(/MyError/); - }); - - it('ShoulIgnoreVbNonBindable', function() { - var scope = this.compile("
{{a}}" + + sortedHtml(element)); + })); + + it('BindStyle', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + + $rootScope.$eval('style={height: "10px"}'); + $rootScope.$apply(); + + assertEquals("10px", element.css('height')); + + $rootScope.$eval('style={}'); + $rootScope.$apply(); + })); + + it('ActionOnAHrefThrowsError', inject( + function($exceptionHandlerProvider){ + $exceptionHandlerProvider.mode('log'); + }, + function($rootScope, $exceptionHandler, $compile) { + var input = $compile('Add Phone')($rootScope); + $rootScope.action = function() { + throw new Error('MyError'); + }; + browserTrigger(input, 'click'); + expect($exceptionHandler.errors[0]).toMatch(/MyError/); + }) + ); + + it('ShoulIgnoreVbNonBindable', inject(function($rootScope, $compile) { + var element = $compile( + "
{{a}}" + "
{{a}}
" + "
{{b}}
" + - "
{{c}}
"); - scope.a = 123; - scope.$apply(); - assertEquals('123{{a}}{{b}}{{c}}', scope.$element.text()); - }); + "
{{c}}
" + + "
")($rootScope); + $rootScope.a = 123; + $rootScope.$apply(); + assertEquals('123{{a}}{{b}}{{c}}', element.text()); + })); + + it('ShouldTemplateBindPreElements', inject(function ($rootScope, $compile) { + var element = $compile('
Hello {{name}}!
')($rootScope); + $rootScope.name = "World"; + $rootScope.$apply(); - it('ShouldTemplateBindPreElements', function () { - var scope = this.compile('
Hello {{name}}!
'); - scope.name = "World"; - scope.$apply(); - - assertEquals('
Hello World!
', sortedHtml(scope.$element)); - }); + assertEquals( + '
Hello World!
', + sortedHtml(element)); + })); - it('FillInOptionValueWhenMissing', function() { - var scope = this.compile( + it('FillInOptionValueWhenMissing', inject(function($rootScope, $compile) { + var element = $compile( ''); - scope.a = 'A'; - scope.b = 'B'; - scope.$apply(); - var optionA = childNode(scope.$element, 0); - var optionB = childNode(scope.$element, 1); - var optionC = childNode(scope.$element, 2); + '')($rootScope); + $rootScope.a = 'A'; + $rootScope.b = 'B'; + $rootScope.$apply(); + var optionA = childNode(element, 0); + var optionB = childNode(element, 1); + var optionC = childNode(element, 2); expect(optionA.attr('value')).toEqual('A'); expect(optionA.text()).toEqual('A'); @@ -425,19 +449,21 @@ describe('Binder', function() { expect(optionC.attr('value')).toEqual('C'); expect(optionC.text()).toEqual('C'); - }); + })); - it('DeleteAttributeIfEvaluatesFalse', function() { - var scope = this.compile('
' + + it('DeleteAttributeIfEvaluatesFalse', inject(function($rootScope, $compile) { + var element = $compile( + '
' + '' + '' + '' + '' + '' + - '
'); - scope.$apply(); + '' + + '
')($rootScope); + $rootScope.$apply(); function assertChild(index, disabled) { - var child = childNode(scope.$element, index); + var child = childNode(element, index); assertEquals(sortedHtml(child), disabled, !!child.attr('disabled')); } @@ -447,72 +473,84 @@ describe('Binder', function() { assertChild(3, false); assertChild(4, true); assertChild(5, false); - }); - - it('ItShouldDisplayErrorWhenActionIsSyntacticlyIncorrect', function() { - var scope = this.compile('
' + - '' + - '
', null, true); - var first = jqLite(scope.$element[0].childNodes[0]); - var second = jqLite(scope.$element[0].childNodes[1]); - var errorLogs = scope.$service('$log').error.logs; - - browserTrigger(first, 'click'); - assertEquals("ABC", scope.greeting); - expect(errorLogs).toEqual([]); - - browserTrigger(second, 'click'); - expect(scope.$service('$exceptionHandler').errors[0]). - toMatchError(/Syntax Error: Token ':' not a primary expression/); - }); - - it('ItShouldSelectTheCorrectRadioBox', function() { - var scope = this.compile('
' + + })); + + it('ItShouldDisplayErrorWhenActionIsSyntacticlyIncorrect', inject( + function($exceptionHandlerProvider){ + $exceptionHandlerProvider.mode('log'); + }, + function($rootScope, $exceptionHandler, $log, $compile) { + var element = $compile( + '
' + + '' + + '' + + '
')($rootScope); + var first = jqLite(element.find('input')[0]); + var second = jqLite(element.find('input')[1]); + var errorLogs = $log.error.logs; + + browserTrigger(first, 'click'); + assertEquals("ABC", $rootScope.greeting); + expect(errorLogs).toEqual([]); + + browserTrigger(second, 'click'); + expect($exceptionHandler.errors[0]). + toMatchError(/Syntax Error: Token ':' not a primary expression/); + }) + ); + + it('ItShouldSelectTheCorrectRadioBox', inject(function($rootScope, $compile) { + var element = $compile( + '
' + '' + - '
'); - var female = jqLite(scope.$element[0].childNodes[0]); - var male = jqLite(scope.$element[0].childNodes[1]); + '' + + '
')($rootScope); + var female = jqLite(element[0].childNodes[0]); + var male = jqLite(element[0].childNodes[1]); browserTrigger(female); - assertEquals("female", scope.sex); + assertEquals("female", $rootScope.sex); assertEquals(true, female[0].checked); assertEquals(false, male[0].checked); assertEquals("female", female.val()); browserTrigger(male); - assertEquals("male", scope.sex); + assertEquals("male", $rootScope.sex); assertEquals(false, female[0].checked); assertEquals(true, male[0].checked); assertEquals("male", male.val()); - }); - - it('ItShouldRepeatOnHashes', function() { - var scope = this.compile('
'); - scope.$apply(); + })); + + it('ItShouldRepeatOnHashes', inject(function($rootScope, $compile) { + var element = $compile( + '
    ' + + '
  • ' + + '
')($rootScope); + $rootScope.$apply(); assertEquals('
    ' + '<#comment>' + '
  • a0
  • ' + '
  • b1
  • ' + '
', - sortedHtml(scope.$element)); - }); - - it('ItShouldFireChangeListenersBeforeUpdate', function() { - var scope = this.compile('
'); - scope.name = ""; - scope.$watch("watched", "name=123"); - scope.watched = "change"; - scope.$apply(); - assertEquals(123, scope.name); + sortedHtml(element)); + })); + + it('ItShouldFireChangeListenersBeforeUpdate', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.name = ""; + $rootScope.$watch("watched", "name=123"); + $rootScope.watched = "change"; + $rootScope.$apply(); + assertEquals(123, $rootScope.name); assertEquals( '
123
', - sortedHtml(scope.$element)); - }); - - it('ItShouldHandleMultilineBindings', function() { - var scope = this.compile('
{{\n 1 \n + \n 2 \n}}
'); - scope.$apply(); - assertEquals("3", scope.$element.text()); - }); + sortedHtml(element)); + })); + + it('ItShouldHandleMultilineBindings', inject(function($rootScope, $compile) { + var element = $compile('
{{\n 1 \n + \n 2 \n}}
')($rootScope); + $rootScope.$apply(); + assertEquals("3", element.text()); + })); }); diff --git a/test/InjectorSpec.js b/test/InjectorSpec.js index 2c6c102a2c85..d39fee1321ae 100644 --- a/test/InjectorSpec.js +++ b/test/InjectorSpec.js @@ -2,53 +2,39 @@ describe('injector', function() { var providers; - var cache; var injector; - var scope; - beforeEach(function() { - providers = extensionMap({}, 'providers'); - cache = {}; - scope = {}; - injector = createInjector(scope, providers, cache); - }); + beforeEach(inject(function($injector, $provide) { + providers = function(name, factory, decoration){ + $provide.factory(name, extend(factory, decoration||{})); + }; + injector = $injector; + })); it("should return same instance from calling provider", function() { - providers('text', function() { return scope.name; }); - scope.name = 'abc'; - expect(injector('text')).toEqual('abc'); - expect(cache.text).toEqual('abc'); - scope.name = 'deleted'; - expect(injector('text')).toEqual('abc'); + var instance = {}, + original = instance; + providers('instance', function() { return instance; }); + expect(injector.get('instance')).toEqual(instance); + instance = 'deleted'; + expect(injector.get('instance')).toEqual(original); }); - it("should call function", function() { - providers('a', function() {return 1;}); - providers('b', function() {return 2;}); - var args; - function fn(a, b, c, d) { - args = [this, a, b, c, d]; - } - fn.$inject = ['a', 'b']; - injector.invoke({name:"this"}, fn, [3, 4]); - expect(args).toEqual([{name:'this'}, 1, 2, 3, 4]); - }); it('should inject providers', function() { - providers('a', function() {return this.mi = 'Mi';}); - providers('b', function(mi){return this.name = mi+'sko';}, {$inject:['a']}); - expect(injector('b')).toEqual('Misko'); - expect(scope).toEqual({mi:'Mi', name:'Misko'}); + providers('a', function() {return 'Mi';}); + providers('b', function(mi) {return mi+'sko';}, {$inject:['a']}); + expect(injector.get('b')).toEqual('Misko'); }); it('should resolve dependency graph and instantiate all services just once', function() { var log = []; -// s1 -// / |\ -// / s2\ -// / / | \\ +// s1 +// / | \ +// / s2 \ +// / / | \ \ // /s3 < s4 > s5 // // // s6 @@ -61,24 +47,71 @@ describe('injector', function() { providers('s5', function() { log.push('s5'); }); providers('s6', function() { log.push('s6'); }); - injector('s1'); + injector.get('s1'); expect(log).toEqual(['s6', 's5', 's3', 's4', 's2', 's1']); }); - it('should provide usefull message if no provider', function() { + it('should provide useful message if no provider', function() { expect(function() { - injector('idontexist'); + injector.get('idontexist'); }).toThrow("Unknown provider for 'idontexist'."); }); - it('should autostart eager services', function() { - var log = ''; - providers('eager', function() {log += 'eager;'; return 'foo';}, {$eager: true}); - injector.eager(); - expect(log).toEqual('eager;'); - expect(injector('eager')).toBe('foo'); + it('should proved path to the missing provider', function() { + providers('a', function(idontexist) {return 1;}); + providers('b', function(a) {return 2;}); + expect(function() { + injector.get('b'); + }).toThrow("Unknown provider for 'idontexist' <- 'a' <- 'b'."); + }); + + + describe('invoke', function() { + var args; + + beforeEach(function() { + args = null; + providers('a', function() {return 1;}); + providers('b', function() {return 2;}); + }); + + + function fn(a, b, c, d) { + args = [this, a, b, c, d]; + return a + b + c + d; + } + + + it('should call function', function() { + fn.$inject = ['a', 'b', 'c', 'd']; + injector.invoke({name:"this"}, fn, {c:3, d:4}); + expect(args).toEqual([{name:'this'}, 1, 2, 3, 4]); + }); + + + it('should treat array as annotations', function() { + injector.invoke({name:"this"}, ['a', 'b', 'c', 'd', fn], {c:3, d:4}); + expect(args).toEqual([{name:'this'}, 1, 2, 3, 4]); + }); + + + it('should invoke the passed in function with all of the dependencies as arguments', function(){ + providers('c', function() {return 3;}); + providers('d', function() {return 4;}); + expect(injector.invoke(null, ['a', 'b', 'c', 'd', fn])).toEqual(10); + }); + + + it('should fail with errors if not function or array', function() { + expect(function() { + injector.invoke({}, {}); + }).toThrow("Argument 'fn' is not a function, got Object"); + expect(function() { + injector.invoke({}, ['a', 123]); + }).toThrow("Argument 'fn' is not a function, got number"); + }); }); describe('annotation', function() { @@ -99,10 +132,10 @@ describe('injector', function() { $a, // x, <-- looks like an arg but it is a comment b_, /* z, <-- looks like an arg but it is a multi-line comment - function (a, b){} + function (a, b) {} */ _c, - /* {some type} */ d){ extraParans();} + /* {some type} */ d) { extraParans();} expect(inferInjectionArgs($f_n0)).toEqual(['$a', 'b_', '_c', 'd']); expect($f_n0.$inject).toEqual(['$a', 'b_', '_c', 'd']); }); @@ -114,7 +147,7 @@ describe('injector', function() { }); it('should handle args with both $ and _', function() { - function $f_n0($a_){} + function $f_n0($a_) {} expect(inferInjectionArgs($f_n0)).toEqual(['$a_']); expect($f_n0.$inject).toEqual(['$a_']); }); @@ -125,24 +158,279 @@ describe('injector', function() { }).toThrow(); }); - it('should infer injection on services', function() { - var scope = angular.scope({ - a: function() { return 'a';}, - b: function(a){ return a + 'b';} + }); + + + it('should have $injector', function() { + var $injector = createInjector(); + expect($injector.get('$injector')).toBe($injector); + }); + + it('should define module', function() { + var log = ''; + var injector = createInjector([function($provide) { + $provide.value('value', 'value;'); + $provide.factory('fn', valueFn('function;')); + $provide.service('service', function() { + this.$get = valueFn('service;'); }); - expect(scope.$service('b')).toEqual('ab'); + }, function(valueProvider, fnProvider, serviceProvider) { + log += valueProvider.$get() + fnProvider.$get() + serviceProvider.$get(); + }]).invoke(null, function(value, fn, service) { + log += '->' + value + fn + service; }); + expect(log).toEqual('value;function;service;->value;function;service;'); }); - describe('inject', function() { - it('should inject names', function() { - expect(annotate('a', {}).$inject).toEqual(['a']); - expect(annotate('a', 'b', {}).$inject).toEqual(['a', 'b']); + + describe('module', function() { + it('should provide $injector and $provide even when no module is requested', function() { + var $provide, + $injector = createInjector([ + angular.extend(function(p) { $provide = p; }, {$inject: ['$provide']}) + ]); + expect($injector.get('$injector')).toBe($injector); + expect($injector.get('$provide')).toBe($provide); + }); + + + it('should load multiple function modules and infer inject them', function() { + var a = 'junk'; + var $injector = createInjector([ + function() { + a = 'A'; // reset to prove we ran + }, + function($provide) { + $provide.value('a', a); + }, + angular.extend(function(p, serviceA) { + p.value('b', serviceA.$get() + 'B' ); + }, {$inject:['$provide', 'aProvider']}), + ['$provide', 'bProvider', function(p, serviceB) { + p.value('c', serviceB.$get() + 'C'); + }] + ]); + expect($injector.get('a')).toEqual('A'); + expect($injector.get('b')).toEqual('AB'); + expect($injector.get('c')).toEqual('ABC'); }); - it('should inject array', function() { - expect(annotate(['a'], {}).$inject).toEqual(['a']); - expect(annotate(['a', 'b'], {}).$inject).toEqual(['a', 'b']); + + it('should run symbolic modules', function() { + var $injector = createInjector(['myModule'], { + myModule: ['$provide', function(provide) { + provide.value('a', 'abc'); + }] + }); + expect($injector.get('a')).toEqual('abc'); + }); + + it('should error on invalid madule name', function(){ + expect(function(){ + createInjector(['IDontExist'], {}); + }).toThrow("Module 'IDontExist' is not defined!"); + }); + + + describe('$provide', function() { + describe('value', function(){ + it('should configure $provide values', function() { + expect(createInjector([function($provide) { + $provide.value('value', 'abc'); + }]).get('value')).toEqual('abc'); + }); + }); + + + describe('factory', function(){ + it('should configure $provide factory function', function() { + expect(createInjector([function($provide) { + $provide.factory('value', valueFn('abc')); + }]).get('value')).toEqual('abc'); + }); + }); + + + describe('service', function(){ + it('should configure $provide service object', function() { + expect(createInjector([function($provide) { + $provide.service('value', { + $get: valueFn('abc') + }); + }]).get('value')).toEqual('abc'); + }); + + + it('should configure $provide service type', function() { + function Type() {}; + Type.prototype.$get = function() { + expect(this instanceof Type).toBe(true); + return 'abc'; + }; + expect(createInjector([function($provide) { + $provide.service('value', Type); + }]).get('value')).toEqual('abc'); + }); + }); + }); + + + describe('error handling', function() { + it('should handle wrong argument type', function() { + expect(function() { + createInjector([ + {} + ], {}); + }).toThrow("Argument 'module' is not a function, got Object"); + }); + + + it('should handle exceptions', function() { + expect(function() { + createInjector([function() { + throw 'MyError'; + }], {}); + }).toThrow('MyError'); + }); + + + it('should handle no module alias', function() { + expect(function() { + createInjector([function(dontExist) { + }], {}); + }).toThrow("Unknown provider for 'dontExist'."); + }); + }); + }); + + + describe('retrieval', function() { + var instance, + $injector, + $provide; + + beforeEach(function() { + $injector = createInjector([ ['$provide', function(provide) { + ($provide = provide).value('instance', instance = {name:'angular'}); + }]]); + }); + + + it('should retrieve by name and cache instance', function() { + expect(instance).toEqual({name: 'angular'}); + expect($injector.get('instance')).toBe(instance); + expect($injector.get('instance')).toBe(instance); + }); + + + it('should call functions and infer arguments', function() { + expect($injector.invoke(null, function(instance) { return instance; })).toBe(instance); + expect($injector.invoke(null, function(instance) { return instance; })).toBe(instance); + }); + }); + + + describe('method invoking', function() { + var $injector; + + beforeEach(function() { + $injector = createInjector([ function($provide) { + $provide.value('book', 'moby'); + $provide.value('author', 'melville'); + }]); + }); + + + it('should invoke method', function() { + expect($injector.invoke(null, function(book, author) { + return author + ':' + book; + })).toEqual('melville:moby'); + expect($injector.invoke($injector, function(book, author) { + expect(this).toEqual($injector); + return author + ':' + book;})).toEqual('melville:moby'); + }); + + + it('should invoke method with locals', function() { + expect($injector.invoke(null, function(book, author) { + return author + ':' + book; + })).toEqual('melville:moby'); + expect($injector.invoke($injector, + function(book, author, chapter) { + expect(this).toEqual($injector); + return author + ':' + book + '-' + chapter; + }, {author:'m', chapter:'ch1'})).toEqual('m:moby-ch1'); + }); + + + it('should invoke method which is annotated', function() { + expect($injector.invoke(null, extend(function(b, a) { + return a + ':' + b + }, {$inject:['book', 'author']}))).toEqual('melville:moby'); + expect($injector.invoke($injector, extend(function(b, a) { + expect(this).toEqual($injector); + return a + ':' + b; + }, {$inject:['book', 'author']}))).toEqual('melville:moby'); + }); + + + it('should invoke method which is an array of annotation', function() { + expect($injector.invoke(null, function(book, author) { + return author + ':' + book; + })).toEqual('melville:moby'); + expect($injector.invoke($injector, function(book, author) { + expect(this).toEqual($injector); + return author + ':' + book; + })).toEqual('melville:moby'); + }); + + + it('should throw usefull error on wrong argument type]', function() { + expect(function(){ + $injector.invoke(null, {}); + }).toThrow("Argument 'fn' is not a function, got Object"); + }); + }); + + describe('service instantiation', function() { + var $injector; + + beforeEach(function() { + $injector = createInjector([ function($provide) { + $provide.value('book', 'moby'); + $provide.value('author', 'melville'); + }]); + }); + + + function Type(book, author) { + this.book = book; + this.author = author; + } + Type.prototype.title = function() { + return this.author + ': ' + this.book; + }; + + + it('should instantiate object and preserve constructor property and be instanceof', function() { + var t = $injector.instantiate(Type); + expect(t.book).toEqual('moby'); + expect(t.author).toEqual('melville'); + expect(t.title()).toEqual('melville: moby'); + expect(t instanceof Type).toBe(true); + }); + + + it('should allow constructor to return different object', function() { + var t = $injector.instantiate(function() { return 'ABC'; }); + expect(t).toBe('ABC'); + }); + + + it('should handle constructor exception', function() { + expect(function() { + $injector.instantiate(function() { throw 'MyError'; }); + }).toThrow('MyError'); }); }); }); diff --git a/test/JsonSpec.js b/test/JsonSpec.js index d3f6de0f0443..736e6032fc1e 100644 --- a/test/JsonSpec.js +++ b/test/JsonSpec.js @@ -72,7 +72,7 @@ describe('json', function() { }); it('should serialize UTC dates', function() { - var date = angular.String.toDate("2009-10-09T01:02:03.027Z"); + var date = jsonStringToDate("2009-10-09T01:02:03.027Z"); expect(toJson(date)).toEqual('"2009-10-09T01:02:03.027Z"'); expect(fromJson('"2009-10-09T01:02:03.027Z"').getTime()).toEqual(date.getTime()); }); @@ -219,4 +219,61 @@ describe('json', function() { }); + + it('should read/write to date', function() { + var date = new Date("Sep 10 2003 13:02:03 GMT"); + assertEquals("2003-09-10T13:02:03.000Z", jsonDateToString(date)); + assertEquals(date.getTime(), jsonStringToDate(jsonDateToString(date)).getTime()); + }); + + + it('should convert to date', function() { + //full ISO8061 + expect(jsonStringToDate("2003-09-10T13:02:03.000Z")). + toEqual(new Date("Sep 10 2003 13:02:03 GMT")); + + //no millis + expect(jsonStringToDate("2003-09-10T13:02:03Z")). + toEqual(new Date("Sep 10 2003 13:02:03 GMT")); + + //no seconds + expect(jsonStringToDate("2003-09-10T13:02Z")). + toEqual(new Date("Sep 10 2003 13:02:00 GMT")); + + //no minutes + expect(jsonStringToDate("2003-09-10T13Z")). + toEqual(new Date("Sep 10 2003 13:00:00 GMT")); + + //no time + expect(jsonStringToDate("2003-09-10")). + toEqual(new Date("Sep 10 2003 00:00:00 GMT")); + }); + + + it('should parse date', function() { + var date = jsonStringToDate("2003-09-10T13:02:03.000Z"); + assertEquals("2003-09-10T13:02:03.000Z", jsonDateToString(date)); + assertEquals("str", jsonStringToDate("str")); + }); + + + describe('string', function() { + it('should quote', function() { + assertEquals(quoteUnicode('a'), '"a"'); + assertEquals(quoteUnicode('\\'), '"\\\\"'); + assertEquals(quoteUnicode("'a'"), '"\'a\'"'); + assertEquals(quoteUnicode('"a"'), '"\\"a\\""'); + assertEquals(quoteUnicode('\n\f\r\t'), '"\\n\\f\\r\\t"'); + }); + + it('should quote slashes', function() { + assertEquals('"7\\\\\\\"7"', quoteUnicode("7\\\"7")); + }); + + it('should quote unicode', function() { + assertEquals('"abc\\u00a0def"', quoteUnicode('abc\u00A0def')); + }); + + }); + }); diff --git a/test/ResourceSpec.js b/test/ResourceSpec.js index 15bbbdae166a..57aaffe0b265 100644 --- a/test/ResourceSpec.js +++ b/test/ResourceSpec.js @@ -1,20 +1,28 @@ 'use strict'; describe("resource", function() { - var xhr, resource, CreditCard, callback, $xhrErr; - - beforeEach(function() { - var scope = angular.scope(angularService, {'$xhr.error': $xhrErr = jasmine.createSpy('xhr.error')}); - xhr = scope.$service('$browser').xhr; - resource = new ResourceFactory(scope.$service('$xhr')); - CreditCard = resource.route('/CreditCard/:id:verb', {id:'@id.key'}, { - charge:{ - method:'POST', - params:{verb:'!charge'} - } - }); - callback = jasmine.createSpy(); - }); + var resource, CreditCard, callback; + + function nakedExpect(obj) { + return expect(angular.fromJson(angular.toJson(obj))); + } + + beforeEach(inject( + function($provide) { + $provide.value('$xhr.error', jasmine.createSpy('xhr.error')); + $provide.factory('$xhrError', ['$xhr.error', identity]); + }, + function($xhr) { + resource = new ResourceFactory($xhr); + CreditCard = resource.route('/CreditCard/:id:verb', {id:'@id.key'}, { + charge:{ + method:'POST', + params:{verb:'!charge'} + } + }); + callback = jasmine.createSpy(); + }) + ); it("should build resource", function() { expect(typeof CreditCard).toBe('function'); @@ -25,162 +33,162 @@ describe("resource", function() { expect(typeof CreditCard.query).toBe('function'); }); - it('should default to empty parameters', function() { - xhr.expectGET('URL').respond({}); + it('should default to empty parameters', inject(function($browser) { + $browser.xhr.expectGET('URL').respond({}); resource.route('URL').query(); - }); + })); - it('should ignore slashes of undefinend parameters', function() { + it('should ignore slashes of undefinend parameters', inject(function($browser) { var R = resource.route('/Path/:a/:b/:c'); - xhr.expectGET('/Path').respond({}); - xhr.expectGET('/Path/1').respond({}); - xhr.expectGET('/Path/2/3').respond({}); - xhr.expectGET('/Path/4/5/6').respond({}); + $browser.xhr.expectGET('/Path').respond({}); + $browser.xhr.expectGET('/Path/1').respond({}); + $browser.xhr.expectGET('/Path/2/3').respond({}); + $browser.xhr.expectGET('/Path/4/5/6').respond({}); R.get({}); R.get({a:1}); R.get({a:2, b:3}); R.get({a:4, b:5, c:6}); - }); + })); - it('should correctly encode url params', function() { + it('should correctly encode url params', inject(function($browser) { var R = resource.route('/Path/:a'); - xhr.expectGET('/Path/foo%231').respond({}); - xhr.expectGET('/Path/doh!@foo?bar=baz%231').respond({}); + $browser.xhr.expectGET('/Path/foo%231').respond({}); + $browser.xhr.expectGET('/Path/doh!@foo?bar=baz%231').respond({}); R.get({a: 'foo#1'}); R.get({a: 'doh!@foo', bar: 'baz#1'}); - }); + })); - it('should not encode @ in url params', function() { + it('should not encode @ in url params', inject(function($browser) { //encodeURIComponent is too agressive and doesn't follow http://www.ietf.org/rfc/rfc3986.txt //with regards to the character set (pchar) allowed in path segments //so we need this test to make sure that we don't over-encode the params and break stuff like //buzz api which uses @self var R = resource.route('/Path/:a'); - xhr.expectGET('/Path/doh@fo%20o?!do%26h=g%3Da+h&:bar=$baz@1').respond({}); + $browser.xhr.expectGET('/Path/doh@fo%20o?!do%26h=g%3Da+h&:bar=$baz@1').respond({}); R.get({a: 'doh@fo o', ':bar': '$baz@1', '!do&h': 'g=a h'}); - }); + })); - it('should encode & in url params', function() { + it('should encode & in url params', inject(function($browser) { var R = resource.route('/Path/:a'); - xhr.expectGET('/Path/doh&foo?bar=baz%261').respond({}); + $browser.xhr.expectGET('/Path/doh&foo?bar=baz%261').respond({}); R.get({a: 'doh&foo', bar: 'baz&1'}); - }); + })); - it("should build resource with default param", function() { - xhr.expectGET('/Order/123/Line/456.visa?minimum=0.05').respond({id:'abc'}); + it("should build resource with default param", inject(function($browser) { + $browser.xhr.expectGET('/Order/123/Line/456.visa?minimum=0.05').respond({id:'abc'}); var LineItem = resource.route('/Order/:orderId/Line/:id:verb', {orderId: '123', id: '@id.key', verb:'.visa', minimum:0.05}); var item = LineItem.get({id:456}); - xhr.flush(); + $browser.xhr.flush(); nakedExpect(item).toEqual({id:'abc'}); - }); + })); - it("should build resource with action default param overriding default param", function() { - xhr.expectGET('/Customer/123').respond({id:'abc'}); + it("should build resource with action default param overriding default param", inject(function($browser) { + $browser.xhr.expectGET('/Customer/123').respond({id:'abc'}); var TypeItem = resource.route('/:type/:typeId', {type: 'Order'}, {get: {method: 'GET', params: {type: 'Customer'}}}); var item = TypeItem.get({typeId:123}); - xhr.flush(); + $browser.xhr.flush(); nakedExpect(item).toEqual({id:'abc'}); - }); + })); - it("should create resource", function() { - xhr.expectPOST('/CreditCard', {name:'misko'}).respond({id:123, name:'misko'}); + it("should create resource", inject(function($browser) { + $browser.xhr.expectPOST('/CreditCard', {name:'misko'}).respond({id:123, name:'misko'}); var cc = CreditCard.save({name:'misko'}, callback); nakedExpect(cc).toEqual({name:'misko'}); expect(callback).not.toHaveBeenCalled(); - xhr.flush(); + $browser.xhr.flush(); nakedExpect(cc).toEqual({id:123, name:'misko'}); expect(callback).toHaveBeenCalledWith(cc); - }); + })); - it("should read resource", function() { - xhr.expectGET("/CreditCard/123").respond({id:123, number:'9876'}); + it("should read resource", inject(function($browser) { + $browser.xhr.expectGET("/CreditCard/123").respond({id:123, number:'9876'}); var cc = CreditCard.get({id:123}, callback); expect(cc instanceof CreditCard).toBeTruthy(); nakedExpect(cc).toEqual({}); expect(callback).not.toHaveBeenCalled(); - xhr.flush(); + $browser.xhr.flush(); nakedExpect(cc).toEqual({id:123, number:'9876'}); expect(callback).toHaveBeenCalledWith(cc); - }); + })); - it("should read partial resource", function() { - xhr.expectGET("/CreditCard").respond([{id:{key:123}}]); - xhr.expectGET("/CreditCard/123").respond({id:{key:123}, number:'9876'}); + it("should read partial resource", inject(function($browser) { + $browser.xhr.expectGET("/CreditCard").respond([{id:{key:123}}]); + $browser.xhr.expectGET("/CreditCard/123").respond({id:{key:123}, number:'9876'}); var ccs = CreditCard.query(); - xhr.flush(); + $browser.xhr.flush(); expect(ccs.length).toEqual(1); var cc = ccs[0]; expect(cc instanceof CreditCard).toBeTruthy(); expect(cc.number).not.toBeDefined(); cc.$get(callback); - xhr.flush(); + $browser.xhr.flush(); expect(callback).toHaveBeenCalledWith(cc); expect(cc.number).toEqual('9876'); - }); + })); - it("should update resource", function() { - xhr.expectPOST('/CreditCard/123', {id:{key:123}, name:'misko'}).respond({id:{key:123}, name:'rama'}); + it("should update resource", inject(function($browser) { + $browser.xhr.expectPOST('/CreditCard/123', {id:{key:123}, name:'misko'}).respond({id:{key:123}, name:'rama'}); var cc = CreditCard.save({id:{key:123}, name:'misko'}, callback); nakedExpect(cc).toEqual({id:{key:123}, name:'misko'}); expect(callback).not.toHaveBeenCalled(); - xhr.flush(); - }); + $browser.xhr.flush(); + })); - it("should query resource", function() { - xhr.expectGET("/CreditCard?key=value").respond([{id:1}, {id:2}]); + it("should query resource", inject(function($browser) { + $browser.xhr.expectGET("/CreditCard?key=value").respond([{id:1}, {id:2}]); var ccs = CreditCard.query({key:'value'}, callback); expect(ccs).toEqual([]); expect(callback).not.toHaveBeenCalled(); - xhr.flush(); + $browser.xhr.flush(); nakedExpect(ccs).toEqual([{id:1}, {id:2}]); expect(callback).toHaveBeenCalledWith(ccs); - }); + })); - it("should have all arguments optional", function() { - xhr.expectGET('/CreditCard').respond([{id:1}]); + it("should have all arguments optional", inject(function($browser) { + $browser.xhr.expectGET('/CreditCard').respond([{id:1}]); var log = ''; var ccs = CreditCard.query(function() { log += 'cb;'; }); - xhr.flush(); + $browser.xhr.flush(); nakedExpect(ccs).toEqual([{id:1}]); expect(log).toEqual('cb;'); - }); + })); - it('should delete resource and call callback', function() { - xhr.expectDELETE("/CreditCard/123").respond(200, {}); + it('should delete resource and call callback', inject(function($browser) { + $browser.xhr.expectDELETE("/CreditCard/123").respond(200, {}); CreditCard.remove({id:123}, callback); expect(callback).not.toHaveBeenCalled(); - xhr.flush(); + $browser.xhr.flush(); nakedExpect(callback.mostRecentCall.args).toEqual([{}]); callback.reset(); - xhr.expectDELETE("/CreditCard/333").respond(204, null); + $browser.xhr.expectDELETE("/CreditCard/333").respond(204, null); CreditCard.remove({id:333}, callback); expect(callback).not.toHaveBeenCalled(); - xhr.flush(); + $browser.xhr.flush(); nakedExpect(callback.mostRecentCall.args).toEqual([{}]); - }); + })); - it('should post charge verb', function() { - xhr.expectPOST('/CreditCard/123!charge?amount=10', {auth:'abc'}).respond({success:'ok'}); + it('should post charge verb', inject(function($browser) { + $browser.xhr.expectPOST('/CreditCard/123!charge?amount=10', {auth:'abc'}).respond({success:'ok'}); CreditCard.charge({id:123, amount:10},{auth:'abc'}, callback); - }); + })); - it('should post charge verb on instance', function() { - xhr.expectPOST('/CreditCard/123!charge?amount=10', {id:{key:123}, name:'misko'}).respond({success:'ok'}); + it('should post charge verb on instance', inject(function($browser) { + $browser.xhr.expectPOST('/CreditCard/123!charge?amount=10', {id:{key:123}, name:'misko'}).respond({success:'ok'}); var card = new CreditCard({id:{key:123}, name:'misko'}); card.$charge({amount:10}, callback); - }); + })); - it('should create on save', function() { - xhr.expectPOST('/CreditCard', {name:'misko'}).respond({id:123}); + it('should create on save', inject(function($browser) { + $browser.xhr.expectPOST('/CreditCard', {name:'misko'}).respond({id:123}); var cc = new CreditCard(); expect(cc.$get).toBeDefined(); expect(cc.$query).toBeDefined(); @@ -190,49 +198,45 @@ describe("resource", function() { cc.name = 'misko'; cc.$save(callback); nakedExpect(cc).toEqual({name:'misko'}); - xhr.flush(); + $browser.xhr.flush(); nakedExpect(cc).toEqual({id:123}); expect(callback).toHaveBeenCalledWith(cc); - }); + })); - it('should not mutate the resource object if response contains no body', function() { + it('should not mutate the resource object if response contains no body', inject(function($browser) { var data = {id:{key:123}, number:'9876'}; - xhr.expectGET("/CreditCard/123").respond(data); + $browser.xhr.expectGET("/CreditCard/123").respond(data); var cc = CreditCard.get({id:123}); - xhr.flush(); + $browser.xhr.flush(); expect(cc instanceof CreditCard).toBeTruthy(); var idBefore = cc.id; - xhr.expectPOST("/CreditCard/123", data).respond(''); + $browser.xhr.expectPOST("/CreditCard/123", data).respond(''); cc.$save(); - xhr.flush(); + $browser.xhr.flush(); expect(idBefore).toEqual(cc.id); - }); + })); - it('should bind default parameters', function() { - xhr.expectGET('/CreditCard/123.visa?minimum=0.05').respond({id:123}); + it('should bind default parameters', inject(function($browser) { + $browser.xhr.expectGET('/CreditCard/123.visa?minimum=0.05').respond({id:123}); var Visa = CreditCard.bind({verb:'.visa', minimum:0.05}); var visa = Visa.get({id:123}); - xhr.flush(); + $browser.xhr.flush(); nakedExpect(visa).toEqual({id:123}); - }); + })); - it('should excersize full stack', function() { - var scope = angular.compile('
')(); - var $browser = scope.$service('$browser'); - var $resource = scope.$service('$resource'); + it('should excersize full stack', inject(function($rootScope, $browser, $resource, $compile) { + $compile('
')($rootScope); var Person = $resource('/Person/:id'); $browser.xhr.expectGET('/Person/123').respond('\n{\n"name":\n"misko"\n}\n'); var person = Person.get({id:123}); $browser.xhr.flush(); expect(person.name).toEqual('misko'); - dealoc(scope); - }); + })); - it('should return the same object when verifying the cache', function() { - var scope = angular.compile('
')(); - var $browser = scope.$service('$browser'); - var $resource = scope.$service('$resource'); + it('should return the same object when verifying the cache', + inject(function($rootScope, $compile, $browser, $resource) { + $compile('
')($rootScope); var Person = $resource('/Person/:id', null, {query: {method:'GET', isArray: true, verifyCache: true}}); $browser.xhr.expectGET('/Person/123').respond('[\n{\n"name":\n"misko"\n}\n]'); var person = Person.query({id:123}); @@ -248,8 +252,7 @@ describe("resource", function() { $browser.xhr.flush(); expect(person2Cache).toEqual(person2); expect(person2[0].name).toEqual('rob'); - dealoc(scope); - }); + })); describe('failure mode', function() { var ERROR_CODE = 500, @@ -260,29 +263,32 @@ describe("resource", function() { errorCB = jasmine.createSpy(); }); - it('should report error when non 2xx if error callback is not provided', function() { - xhr.expectGET('/CreditCard/123').respond(ERROR_CODE, ERROR_RESPONSE); + it('should report error when non 2xx if error callback is not provided', + inject(function($browser, $xhrError) { + $browser.xhr.expectGET('/CreditCard/123').respond(ERROR_CODE, ERROR_RESPONSE); CreditCard.get({id:123}); - xhr.flush(); - expect($xhrErr).toHaveBeenCalled(); - }); + $browser.xhr.flush(); + expect($xhrError).toHaveBeenCalled(); + })); - it('should call the error callback if provided on non 2xx response', function() { - xhr.expectGET('/CreditCard/123').respond(ERROR_CODE, ERROR_RESPONSE); + it('should call the error callback if provided on non 2xx response', + inject(function($browser, $xhrError) { + $browser.xhr.expectGET('/CreditCard/123').respond(ERROR_CODE, ERROR_RESPONSE); CreditCard.get({id:123}, callback, errorCB); - xhr.flush(); + $browser.xhr.flush(); expect(errorCB).toHaveBeenCalledWith(500, ERROR_RESPONSE); expect(callback).not.toHaveBeenCalled(); - expect($xhrErr).not.toHaveBeenCalled(); - }); + expect($xhrError).not.toHaveBeenCalled(); + })); - it('should call the error callback if provided on non 2xx response', function() { - xhr.expectGET('/CreditCard').respond(ERROR_CODE, ERROR_RESPONSE); + it('should call the error callback if provided on non 2xx response', + inject(function($browser, $xhrError) { + $browser.xhr.expectGET('/CreditCard').respond(ERROR_CODE, ERROR_RESPONSE); CreditCard.get(callback, errorCB); - xhr.flush(); + $browser.xhr.flush(); expect(errorCB).toHaveBeenCalledWith(500, ERROR_RESPONSE); expect(callback).not.toHaveBeenCalled(); - expect($xhrErr).not.toHaveBeenCalled(); - }); + expect($xhrError).not.toHaveBeenCalled(); + })); }); }); diff --git a/test/ScenarioSpec.js b/test/ScenarioSpec.js index 5f83ab930539..986e21217969 100644 --- a/test/ScenarioSpec.js +++ b/test/ScenarioSpec.js @@ -1,35 +1,25 @@ 'use strict'; describe("ScenarioSpec: Compilation", function() { - var scope; - - beforeEach(function() { - scope = null; - }); - - afterEach(function() { - dealoc(scope); - }); - describe('compilation', function() { - it("should compile dom node and return scope", function() { + it("should compile dom node and return scope", inject(function($rootScope, $compile) { var node = jqLite('
{{b=a+1}}
')[0]; - scope = angular.compile(node)(); - scope.$digest(); - expect(scope.a).toEqual(1); - expect(scope.b).toEqual(2); - }); + $compile(node)($rootScope); + $rootScope.$digest(); + expect($rootScope.a).toEqual(1); + expect($rootScope.b).toEqual(2); + })); - it("should compile jQuery node and return scope", function() { - scope = compile(jqLite('
{{a=123}}
'))(); - scope.$digest(); - expect(jqLite(scope.$element).text()).toEqual('123'); - }); + it("should compile jQuery node and return scope", inject(function($rootScope, $compile) { + var element = $compile(jqLite('
{{a=123}}
'))($rootScope); + $rootScope.$digest(); + expect(jqLite(element).text()).toEqual('123'); + })); - it("should compile text node and return scope", function() { - scope = angular.compile('
{{a=123}}
')(); - scope.$digest(); - expect(jqLite(scope.$element).text()).toEqual('123'); - }); + it("should compile text node and return scope", inject(function($rootScope, $compile) { + var element = $compile('
{{a=123}}
')($rootScope); + $rootScope.$digest(); + expect(jqLite(element).text()).toEqual('123'); + })); }); }); diff --git a/test/angular-mocksSpec.js b/test/angular-mocksSpec.js index c2cffca6d8cc..acb019c7b764 100644 --- a/test/angular-mocksSpec.js +++ b/test/angular-mocksSpec.js @@ -7,91 +7,96 @@ describe('mocks', function() { return min*60*1000; } + it('should look like a Date', function() { + var date = new angular.module.ngMock.TzDate(0,0); + expect(angular.isDate(date)).toBe(true); + }); + it('should take millis as constructor argument', function() { - expect(new TzDate(0, 0).getTime()).toBe(0); - expect(new TzDate(0, 1283555108000).getTime()).toBe(1283555108000); + expect(new angular.module.ngMock.TzDate(0, 0).getTime()).toBe(0); + expect(new angular.module.ngMock.TzDate(0, 1283555108000).getTime()).toBe(1283555108000); }); it('should take dateString as constructor argument', function() { - expect(new TzDate(0, '1970-01-01T00:00:00.000Z').getTime()).toBe(0); - expect(new TzDate(0, '2010-09-03T23:05:08.023Z').getTime()).toBe(1283555108023); + expect(new angular.module.ngMock.TzDate(0, '1970-01-01T00:00:00.000Z').getTime()).toBe(0); + expect(new angular.module.ngMock.TzDate(0, '2010-09-03T23:05:08.023Z').getTime()).toBe(1283555108023); }); it('should fake getLocalDateString method', function() { //0 in -3h - var t0 = new TzDate(-3, 0); + var t0 = new angular.module.ngMock.TzDate(-3, 0); expect(t0.toLocaleDateString()).toMatch('1970'); //0 in +0h - var t1 = new TzDate(0, 0); + var t1 = new angular.module.ngMock.TzDate(0, 0); expect(t1.toLocaleDateString()).toMatch('1970'); //0 in +3h - var t2 = new TzDate(3, 0); + var t2 = new angular.module.ngMock.TzDate(3, 0); expect(t2.toLocaleDateString()).toMatch('1969'); }); it('should fake getHours method', function() { //0 in -3h - var t0 = new TzDate(-3, 0); + var t0 = new angular.module.ngMock.TzDate(-3, 0); expect(t0.getHours()).toBe(3); //0 in +0h - var t1 = new TzDate(0, 0); + var t1 = new angular.module.ngMock.TzDate(0, 0); expect(t1.getHours()).toBe(0); //0 in +3h - var t2 = new TzDate(3, 0); + var t2 = new angular.module.ngMock.TzDate(3, 0); expect(t2.getHours()).toMatch(21); }); it('should fake getMinutes method', function() { //0:15 in -3h - var t0 = new TzDate(-3, minutes(15)); + var t0 = new angular.module.ngMock.TzDate(-3, minutes(15)); expect(t0.getMinutes()).toBe(15); //0:15 in -3.25h - var t0a = new TzDate(-3.25, minutes(15)); + var t0a = new angular.module.ngMock.TzDate(-3.25, minutes(15)); expect(t0a.getMinutes()).toBe(30); //0 in +0h - var t1 = new TzDate(0, minutes(0)); + var t1 = new angular.module.ngMock.TzDate(0, minutes(0)); expect(t1.getMinutes()).toBe(0); //0:15 in +0h - var t1a = new TzDate(0, minutes(15)); + var t1a = new angular.module.ngMock.TzDate(0, minutes(15)); expect(t1a.getMinutes()).toBe(15); //0:15 in +3h - var t2 = new TzDate(3, minutes(15)); + var t2 = new angular.module.ngMock.TzDate(3, minutes(15)); expect(t2.getMinutes()).toMatch(15); //0:15 in +3.25h - var t2a = new TzDate(3.25, minutes(15)); + var t2a = new angular.module.ngMock.TzDate(3.25, minutes(15)); expect(t2a.getMinutes()).toMatch(0); }); it('should fake getSeconds method', function() { //0 in -3h - var t0 = new TzDate(-3, 0); + var t0 = new angular.module.ngMock.TzDate(-3, 0); expect(t0.getSeconds()).toBe(0); //0 in +0h - var t1 = new TzDate(0, 0); + var t1 = new angular.module.ngMock.TzDate(0, 0); expect(t1.getSeconds()).toBe(0); //0 in +3h - var t2 = new TzDate(3, 0); + var t2 = new angular.module.ngMock.TzDate(3, 0); expect(t2.getSeconds()).toMatch(0); }); it('should create a date representing new year in Bratislava', function() { - var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00.000Z'); + var newYearInBratislava = new angular.module.ngMock.TzDate(-1, '2009-12-31T23:00:00.000Z'); expect(newYearInBratislava.getTimezoneOffset()).toBe(-60); expect(newYearInBratislava.getFullYear()).toBe(2010); expect(newYearInBratislava.getMonth()).toBe(0); @@ -103,7 +108,7 @@ describe('mocks', function() { it('should delegate all the UTC methods to the original UTC Date object', function() { //from when created from string - var date1 = new TzDate(-1, '2009-12-31T23:00:00.000Z'); + var date1 = new angular.module.ngMock.TzDate(-1, '2009-12-31T23:00:00.000Z'); expect(date1.getUTCFullYear()).toBe(2009); expect(date1.getUTCMonth()).toBe(11); expect(date1.getUTCDate()).toBe(31); @@ -113,7 +118,7 @@ describe('mocks', function() { //from when created from millis - var date2 = new TzDate(-1, angular.String.toDate('2009-12-31T23:00:00.000Z').getTime()); + var date2 = new angular.module.ngMock.TzDate(-1, date1.getTime()); expect(date2.getUTCFullYear()).toBe(2009); expect(date2.getUTCMonth()).toBe(11); expect(date2.getUTCDate()).toBe(31); @@ -124,16 +129,20 @@ describe('mocks', function() { it('should throw error when no third param but toString called', function() { - expect(function() { new TzDate(0,0).toString(); }). + expect(function() { new angular.module.ngMock.TzDate(0,0).toString(); }). toThrow('Method \'toString\' is not implemented in the TzDate mock'); }); }); - describe('$log mock', function() { + describe('$log', function() { var $log; - beforeEach(function() { - $log = MockLogFactory(); - }); + beforeEach(inject(['$log', function(log) { + $log = log; + }])); + + afterEach(inject(function($log){ + $log.reset(); + })); it('should provide log method', function() { expect(function() { $log.log(''); }).not.toThrow(); @@ -170,14 +179,48 @@ describe('mocks', function() { $log.error('fake log'); expect($log.error.logs).toContain(['fake log']); }); + + it('should assertEmpty', function(){ + try { + $log.error(Error('MyError')); + $log.warn(Error('MyWarn')); + $log.info(Error('MyInfo')); + $log.log(Error('MyLog')); + $log.assertEmpty(); + } catch (error) { + error = error.message || error; + expect(error).toMatch(/Error: MyError/m); + expect(error).toMatch(/Error: MyWarn/m); + expect(error).toMatch(/Error: MyInfo/m); + expect(error).toMatch(/Error: MyLog/m); + } finally { + $log.reset(); + } + }); + + it('should reset state', function(){ + $log.error(Error('MyError')); + $log.warn(Error('MyWarn')); + $log.info(Error('MyInfo')); + $log.log(Error('MyLog')); + $log.reset(); + var passed = false; + try { + $log.assertEmpty(); // should not throw error! + passed = true; + } catch (e) { + passed = e; + } + expect(passed).toBe(true); + }); }); describe('defer', function() { var browser, log; - beforeEach(function() { - browser = new MockBrowser(); + beforeEach(inject(function($browser) { + browser = $browser; log = ''; - }); + })); function logFn(text){ return function() { log += text +';'; @@ -226,11 +269,77 @@ describe('mocks', function() { describe('$exceptionHandler', function() { - it('should rethrow exceptions', function() { - var rootScope = angular.scope(), - exHandler = rootScope.$service('$exceptionHandler'); + it('should rethrow exceptions', inject(function($exceptionHandler) { + expect(function() { $exceptionHandler('myException'); }).toThrow('myException'); + })); + + + it('should log exceptions', inject(function($exceptionHandlerProvider){ + $exceptionHandlerProvider.mode('log'); + var $exceptionHandler = $exceptionHandlerProvider.$get(); + $exceptionHandler('MyError'); + expect($exceptionHandler.errors).toEqual(['MyError']); + })); + + + it('should thorw on wrong argument', inject(function($exceptionHandlerProvider) { + expect(function() { + $exceptionHandlerProvider.mode('XXX'); + }).toThrow("Unknown mode 'XXX', only 'log'/'rethrow' modes are allowed!"); + })); + }); + + + describe('angular.module.ngMock.dump', function(){ + var d = angular.module.ngMock.dump; + + + it('should serialize primitive types', function(){ + expect(d(undefined)).toEqual('undefined'); + expect(d(1)).toEqual('1'); + expect(d(null)).toEqual('null'); + expect(d('abc')).toEqual('abc'); + }); + + + it('should serialize element', function(){ + var e = angular.element('
abc
xyz'); + expect(d(e).toLowerCase()).toEqual('
abc
xyz'); + expect(d(e[0]).toLowerCase()).toEqual('
abc
'); + }); + + it('should serialize scope', inject(function($rootScope){ + $rootScope.obj = {abc:'123'}; + expect(d($rootScope)).toMatch(/Scope\(.*\): \{/); + expect(d($rootScope)).toMatch(/{"abc":"123"}/); + })); + + + it('should be published on window', function(){ + expect(window.dump instanceof Function).toBe(true); + }); + }); + + describe('jasmine inject', function(){ + it('should call invoke', function(){ + var count = 0; + function fn1(){ + expect(this).toBe(self); + count++; + } + function fn2(){ + expect(this).toBe(self); + count++; + } + var fn = inject(fn1, fn2); + var self = { + $injector: { + invoke: function(self, fn) { fn.call(self); } + } + }; - expect(function() { exHandler('myException'); }).toThrow('myException'); + fn.call(self); + expect(count).toBe(2); }); }); }); diff --git a/test/directivesSpec.js b/test/directivesSpec.js index e92cb719a488..5f9fa0a86015 100644 --- a/test/directivesSpec.js +++ b/test/directivesSpec.js @@ -2,329 +2,306 @@ describe("directive", function() { - var compile, model, element; - - beforeEach(function() { - compile = function(html) { - element = jqLite(html); - return model = angular.compile(element)(); - }; - }); - - afterEach(function() { - dealoc(model); - }); - - it("should ng:init", function() { - var scope = compile('
'); - expect(scope.a).toEqual(123); - }); + it("should ng:init", inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + expect($rootScope.a).toEqual(123); + })); describe('ng:bind', function() { - it('should set text', function() { - var scope = compile('
'); + it('should set text', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); expect(element.text()).toEqual(''); - scope.a = 'misko'; - scope.$digest(); + $rootScope.a = 'misko'; + $rootScope.$digest(); expect(element.hasClass('ng-binding')).toEqual(true); expect(element.text()).toEqual('misko'); - }); + })); - it('should set text to blank if undefined', function() { - var scope = compile('
'); - scope.a = 'misko'; - scope.$digest(); + it('should set text to blank if undefined', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.a = 'misko'; + $rootScope.$digest(); expect(element.text()).toEqual('misko'); - scope.a = undefined; - scope.$digest(); + $rootScope.a = undefined; + $rootScope.$digest(); expect(element.text()).toEqual(''); - }); + })); - it('should set html', function() { - var scope = compile('
'); - scope.html = '
hello
'; - scope.$digest(); + it('should set html', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.html = '
hello
'; + $rootScope.$digest(); expect(lowercase(element.html())).toEqual('
hello
'); - }); + })); - it('should set unsafe html', function() { - var scope = compile('
'); - scope.html = '
hello
'; - scope.$digest(); + it('should set unsafe html', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.html = '
hello
'; + $rootScope.$digest(); expect(lowercase(element.html())).toEqual('
hello
'); - }); + })); - it('should set element element', function() { - angularFilter.myElement = function() { + it('should set element element', inject(function($rootScope, $compile, $filterProvider) { + $filterProvider.register('myElement', valueFn(function() { return jqLite('hello'); - }; - var scope = compile('
'); - scope.$digest(); + })); + var element = $compile('
')($rootScope); + $rootScope.$digest(); expect(lowercase(element.html())).toEqual('hello'); - }); - - it('should have $element set to current bind element', function() { - angularFilter.myFilter = function() { - this.$element.addClass("filter"); - return 'HELLO'; - }; - var scope = compile('
before
after
'); - scope.$digest(); - expect(sortedHtml(scope.$element)).toEqual('
before
HELLO
after
'); - }); + })); - it('should suppress rendering of falsy values', function() { - var scope = compile('
{{ null }}{{ undefined }}{{ "" }}-{{ 0 }}{{ false }}
'); - scope.$digest(); - expect(scope.$element.text()).toEqual('-0false'); - }); + it('should suppress rendering of falsy values', inject(function($rootScope, $compile) { + var element = $compile('
{{ null }}{{ undefined }}{{ "" }}-{{ 0 }}{{ false }}
')($rootScope); + $rootScope.$digest(); + expect(element.text()).toEqual('-0false'); + })); - it('should render object as JSON ignore $$', function() { - var scope = compile('
{{ {key:"value", $$key:"hide"} }}
'); - scope.$digest(); - expect(fromJson(scope.$element.text())).toEqual({key:'value'}); - }); + it('should render object as JSON ignore $$', inject(function($rootScope, $compile) { + var element = $compile('
{{ {key:"value", $$key:"hide"} }}
')($rootScope); + $rootScope.$digest(); + expect(fromJson(element.text())).toEqual({key:'value'}); + })); }); describe('ng:bind-template', function() { - it('should ng:bind-template', function() { - var scope = compile('
'); - scope.name = 'Misko'; - scope.$digest(); + it('should ng:bind-template', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.name = 'Misko'; + $rootScope.$digest(); expect(element.hasClass('ng-binding')).toEqual(true); expect(element.text()).toEqual('Hello Misko!'); - }); + })); - it('should have $element set to current bind element', function() { + it('should have $element set to current bind element', inject(function($rootScope, $compile, $filterProvider) { var innerText; - angularFilter.myFilter = function(text) { + $filterProvider.register('myFilter', valueFn(function(text) { innerText = innerText || this.$element.text(); return text; - }; - var scope = compile('
beforeINNERafter
'); - scope.$digest(); - expect(scope.$element.text()).toEqual("beforeHELLOafter"); + })); + var element = $compile('
beforeINNERafter
')($rootScope); + $rootScope.$digest(); + expect(element.text()).toEqual("beforeHELLOafter"); expect(innerText).toEqual('INNER'); - }); + })); - it('should render object as JSON ignore $$', function() { - var scope = compile('
{{ {key:"value", $$key:"hide"}  }}
'); - scope.$digest(); - expect(fromJson(scope.$element.text())).toEqual({key:'value'}); - }); + it('should render object as JSON ignore $$', inject(function($rootScope, $compile) { + var element = $compile('
{{ {key:"value", $$key:"hide"}  }}
')($rootScope); + $rootScope.$digest(); + expect(fromJson(element.text())).toEqual({key:'value'}); + })); }); describe('ng:bind-attr', function() { - it('should bind attributes', function() { - var scope = compile('
'); - scope.$digest(); + it('should bind attributes', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.$digest(); expect(element.attr('src')).toEqual('http://localhost/mysrc'); expect(element.attr('alt')).toEqual('myalt'); - }); + })); - it('should not pretty print JSON in attributes', function() { - var scope = compile('{{ {a:1} }}'); - scope.$digest(); + it('should not pretty print JSON in attributes', inject(function($rootScope, $compile) { + var element = $compile('{{ {a:1} }}')($rootScope); + $rootScope.$digest(); expect(element.attr('alt')).toEqual('{"a":1}'); - }); + })); }); - it('should remove special attributes on false', function() { - var scope = compile(''); - var input = scope.$element[0]; + it('should remove special attributes on false', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope); + var input = element[0]; expect(input.disabled).toEqual(false); expect(input.readOnly).toEqual(false); expect(input.checked).toEqual(false); - scope.disabled = true; - scope.readonly = true; - scope.checked = true; - scope.$digest(); + $rootScope.disabled = true; + $rootScope.readonly = true; + $rootScope.checked = true; + $rootScope.$digest(); expect(input.disabled).toEqual(true); expect(input.readOnly).toEqual(true); expect(input.checked).toEqual(true); - }); + })); describe('ng:click', function() { - it('should get called on a click', function() { - var scope = compile('
'); - scope.$digest(); - expect(scope.clicked).toBeFalsy(); + it('should get called on a click', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.$digest(); + expect($rootScope.clicked).toBeFalsy(); browserTrigger(element, 'click'); - expect(scope.clicked).toEqual(true); - }); + expect($rootScope.clicked).toEqual(true); + })); - it('should stop event propagation', function() { - var scope = compile('
'); - scope.$digest(); - expect(scope.outer).not.toBeDefined(); - expect(scope.inner).not.toBeDefined(); + it('should stop event propagation', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.$digest(); + expect($rootScope.outer).not.toBeDefined(); + expect($rootScope.inner).not.toBeDefined(); var innerDiv = element.children()[0]; browserTrigger(innerDiv, 'click'); - expect(scope.outer).not.toBeDefined(); - expect(scope.inner).toEqual(true); - }); + expect($rootScope.outer).not.toBeDefined(); + expect($rootScope.inner).toEqual(true); + })); }); describe('ng:submit', function() { - it('should get called on form submit', function() { - var scope = compile('' + - '' + - ''); - scope.$digest(); - expect(scope.submitted).not.toBeDefined(); + it('should get called on form submit', inject(function($rootScope, $compile) { + var element = $compile('
' + + '' + + '
')($rootScope); + $rootScope.$digest(); + expect($rootScope.submitted).not.toBeDefined(); browserTrigger(element.children()[0]); - expect(scope.submitted).toEqual(true); - }); + expect($rootScope.submitted).toEqual(true); + })); }); describe('ng:class', function() { - it('should add new and remove old classes dynamically', function() { - var scope = compile('
'); - scope.dynClass = 'A'; - scope.$digest(); + it('should add new and remove old classes dynamically', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.dynClass = 'A'; + $rootScope.$digest(); expect(element.hasClass('existing')).toBe(true); expect(element.hasClass('A')).toBe(true); - scope.dynClass = 'B'; - scope.$digest(); + $rootScope.dynClass = 'B'; + $rootScope.$digest(); expect(element.hasClass('existing')).toBe(true); expect(element.hasClass('A')).toBe(false); expect(element.hasClass('B')).toBe(true); - delete scope.dynClass; - scope.$digest(); + delete $rootScope.dynClass; + $rootScope.$digest(); expect(element.hasClass('existing')).toBe(true); expect(element.hasClass('A')).toBe(false); expect(element.hasClass('B')).toBe(false); - }); + })); - it('should support adding multiple classes via an array', function() { - var scope = compile('
'); - scope.$digest(); + it('should support adding multiple classes via an array', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.$digest(); expect(element.hasClass('existing')).toBeTruthy(); expect(element.hasClass('A')).toBeTruthy(); expect(element.hasClass('B')).toBeTruthy(); - }); + })); - it('should support adding multiple classes via a space delimited string', function() { - var scope = compile('
'); - scope.$digest(); + it('should support adding multiple classes via a space delimited string', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.$digest(); expect(element.hasClass('existing')).toBeTruthy(); expect(element.hasClass('A')).toBeTruthy(); expect(element.hasClass('B')).toBeTruthy(); - }); + })); - it('should preserve class added post compilation with pre-existing classes', function() { - var scope = compile('
'); - scope.dynClass = 'A'; - scope.$digest(); + it('should preserve class added post compilation with pre-existing classes', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.dynClass = 'A'; + $rootScope.$digest(); expect(element.hasClass('existing')).toBe(true); // add extra class, change model and eval element.addClass('newClass'); - scope.dynClass = 'B'; - scope.$digest(); + $rootScope.dynClass = 'B'; + $rootScope.$digest(); expect(element.hasClass('existing')).toBe(true); expect(element.hasClass('B')).toBe(true); expect(element.hasClass('newClass')).toBe(true); - }); + })); - it('should preserve class added post compilation without pre-existing classes"', function() { - var scope = compile('
'); - scope.dynClass = 'A'; - scope.$digest(); + it('should preserve class added post compilation without pre-existing classes"', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.dynClass = 'A'; + $rootScope.$digest(); expect(element.hasClass('A')).toBe(true); // add extra class, change model and eval element.addClass('newClass'); - scope.dynClass = 'B'; - scope.$digest(); + $rootScope.dynClass = 'B'; + $rootScope.$digest(); expect(element.hasClass('B')).toBe(true); expect(element.hasClass('newClass')).toBe(true); - }); + })); - it('should preserve other classes with similar name"', function() { - var scope = compile('
'); - scope.dynCls = 'panel'; - scope.$digest(); - scope.dynCls = 'foo'; - scope.$digest(); + it('should preserve other classes with similar name"', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.dynCls = 'panel'; + $rootScope.$digest(); + $rootScope.dynCls = 'foo'; + $rootScope.$digest(); expect(element[0].className).toBe('ui-panel ui-selected ng-directive foo'); - }); + })); - it('should not add duplicate classes', function() { - var scope = compile('
'); - scope.dynCls = 'panel'; - scope.$digest(); + it('should not add duplicate classes', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.dynCls = 'panel'; + $rootScope.$digest(); expect(element[0].className).toBe('panel bar ng-directive'); - }); + })); - it('should remove classes even if it was specified via class attribute', function() { - var scope = compile('
'); - scope.dynCls = 'panel'; - scope.$digest(); - scope.dynCls = 'window'; - scope.$digest(); + it('should remove classes even if it was specified via class attribute', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.dynCls = 'panel'; + $rootScope.$digest(); + $rootScope.dynCls = 'window'; + $rootScope.$digest(); expect(element[0].className).toBe('bar ng-directive window'); - }); + })); - it('should remove classes even if they were added by another code', function() { - var scope = compile('
'); - scope.dynCls = 'foo'; - scope.$digest(); + it('should remove classes even if they were added by another code', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.dynCls = 'foo'; + $rootScope.$digest(); element.addClass('foo'); - scope.dynCls = ''; - scope.$digest(); + $rootScope.dynCls = ''; + $rootScope.$digest(); expect(element[0].className).toBe('ng-directive'); - }); + })); - it('should convert undefined and null values to an empty string', function() { - var scope = compile('
'); - scope.dynCls = [undefined, null]; - scope.$digest(); + it('should convert undefined and null values to an empty string', inject(function($rootScope, $compile) { + var element = $compile('
')($rootScope); + $rootScope.dynCls = [undefined, null]; + $rootScope.$digest(); expect(element[0].className).toBe('ng-directive'); - }); + })); }); - it('should ng:class odd/even', function() { - var scope = compile('
    • '); - scope.$digest(); + it('should ng:class odd/even', inject(function($rootScope, $compile) { + var element = $compile('
        • ')($rootScope); + $rootScope.$digest(); var e1 = jqLite(element[0].childNodes[1]); var e2 = jqLite(element[0].childNodes[2]); expect(e1.hasClass('existing')).toBeTruthy(); expect(e1.hasClass('odd')).toBeTruthy(); expect(e2.hasClass('existing')).toBeTruthy(); expect(e2.hasClass('even')).toBeTruthy(); - }); + })); - it('should allow both ng:class and ng:class-odd/even on the same element', function() { - var scope = compile('
            ' + - '
          • ' + - '
              '); - scope.$apply(); + it('should allow both ng:class and ng:class-odd/even on the same element', inject(function($rootScope, $compile) { + var element = $compile('
                ' + + '
              • ' + + '
                  ')($rootScope); + $rootScope.$apply(); var e1 = jqLite(element[0].childNodes[1]); var e2 = jqLite(element[0].childNodes[2]); @@ -334,15 +311,15 @@ describe("directive", function() { expect(e2.hasClass('plainClass')).toBeTruthy(); expect(e2.hasClass('even')).toBeTruthy(); expect(e2.hasClass('odd')).toBeFalsy(); - }); + })); - it('should allow both ng:class and ng:class-odd/even with multiple classes', function() { - var scope = compile('
                    ' + - '
                  • ' + - '
                      '); - scope.$apply(); + it('should allow both ng:class and ng:class-odd/even with multiple classes', inject(function($rootScope, $compile) { + var element = $compile('
                        ' + + '
                      • ' + + '
                          ')($rootScope); + $rootScope.$apply(); var e1 = jqLite(element[0].childNodes[1]); var e2 = jqLite(element[0].childNodes[2]); @@ -359,29 +336,29 @@ describe("directive", function() { expect(e2.hasClass('F')).toBeTruthy(); expect(e2.hasClass('C')).toBeFalsy(); expect(e2.hasClass('D')).toBeFalsy(); - }); + })); describe('ng:style', function() { - it('should set', function() { - var scope = compile('
                          '); - scope.$digest(); + it('should set', inject(function($rootScope, $compile) { + var element = $compile('
                          ')($rootScope); + $rootScope.$digest(); expect(element.css('height')).toEqual('40px'); - }); + })); - it('should silently ignore undefined style', function() { - var scope = compile('
                          '); - scope.$digest(); + it('should silently ignore undefined style', inject(function($rootScope, $compile) { + var element = $compile('
                          ')($rootScope); + $rootScope.$digest(); expect(element.hasClass('ng-exception')).toBeFalsy(); - }); + })); describe('preserving styles set before and after compilation', function() { - var scope, preCompStyle, preCompVal, postCompStyle, postCompVal; + var scope, preCompStyle, preCompVal, postCompStyle, postCompVal, element; - beforeEach(function() { + beforeEach(inject(function($rootScope, $compile) { preCompStyle = 'width'; preCompVal = '300px'; postCompStyle = 'height'; @@ -389,11 +366,12 @@ describe("directive", function() { element = jqLite('
                          '); element.css(preCompStyle, preCompVal); jqLite(document.body).append(element); - scope = compile(element); + $compile(element)($rootScope); + scope = $rootScope; scope.styleObj = {'margin-top': '44px'}; scope.$apply(); element.css(postCompStyle, postCompVal); - }); + })); afterEach(function() { element.remove(); @@ -443,39 +421,36 @@ describe("directive", function() { describe('ng:show', function() { - it('should show and hide an element', function() { - var element = jqLite('
                          '), - scope = compile(element); - - scope.$digest(); + it('should show and hide an element', inject(function($rootScope, $compile) { + var element = jqLite('
                          '); + var element = $compile(element)($rootScope); + $rootScope.$digest(); expect(isCssVisible(element)).toEqual(false); - scope.exp = true; - scope.$digest(); + $rootScope.exp = true; + $rootScope.$digest(); expect(isCssVisible(element)).toEqual(true); - }); - + })); - it('should make hidden element visible', function() { - var element = jqLite('
                          '), - scope = compile(element); + it('should make hidden element visible', inject(function($rootScope, $compile) { + var element = jqLite('
                          '); + var element = $compile(element)($rootScope); expect(isCssVisible(element)).toBe(false); - scope.exp = true; - scope.$digest(); + $rootScope.exp = true; + $rootScope.$digest(); expect(isCssVisible(element)).toBe(true); - }); + })); }); describe('ng:hide', function() { - it('should hide an element', function() { - var element = jqLite('
                          '), - scope = compile(element); - + it('should hide an element', inject(function($rootScope, $compile) { + var element = jqLite('
                          '); + var element = $compile(element)($rootScope); expect(isCssVisible(element)).toBe(true); - scope.exp = true; - scope.$digest(); + $rootScope.exp = true; + $rootScope.$digest(); expect(isCssVisible(element)).toBe(false); - }); + })); }); describe('ng:controller', function() { @@ -500,13 +475,13 @@ describe("directive", function() { window.temp = undefined; }); - it('should bind', function() { - var scope = compile('
                          '); - expect(scope.greeter.greeting).toEqual('hello'); - expect(scope.greeter.greet('misko')).toEqual('hello misko!'); - }); + it('should bind', inject(function($rootScope, $compile) { + var element = $compile('
                          ')($rootScope); + expect($rootScope.greeter.greeting).toEqual('hello'); + expect($rootScope.greeter.greet('misko')).toEqual('hello misko!'); + })); - it('should support nested controllers', function() { + it('should support nested controllers', inject(function($rootScope, $compile) { temp.ChildGreeter = function() { this.greeting = 'hey'; this.$root.childGreeter = this; @@ -516,48 +491,48 @@ describe("directive", function() { return this.greeting + ' dude' + this.suffix; } }; - var scope = compile('
                          {{greet("misko")}}
                          '); - expect(scope.greeting).not.toBeDefined(); - expect(scope.greeter.greeting).toEqual('hello'); - expect(scope.greeter.greet('misko')).toEqual('hello misko!'); - expect(scope.greeter.greeting).toEqual('hello'); - expect(scope.childGreeter.greeting).toEqual('hey'); - expect(scope.childGreeter.$parent.greeting).toEqual('hello'); - scope.$digest(); - expect(scope.$element.text()).toEqual('hey dude!'); - }); - - it('should infer injection arguments', function() { + var element = $compile('
                          {{greet("misko")}}
                          ')($rootScope); + expect($rootScope.greeting).not.toBeDefined(); + expect($rootScope.greeter.greeting).toEqual('hello'); + expect($rootScope.greeter.greet('misko')).toEqual('hello misko!'); + expect($rootScope.greeter.greeting).toEqual('hello'); + expect($rootScope.childGreeter.greeting).toEqual('hey'); + expect($rootScope.childGreeter.$parent.greeting).toEqual('hello'); + $rootScope.$digest(); + expect(element.text()).toEqual('hey dude!'); + })); + + it('should infer injection arguments', inject(function($rootScope, $compile, $xhr) { temp.MyController = function($xhr){ this.$root.someService = $xhr; }; - var scope = compile('
                          '); - expect(scope.someService).toBe(scope.$service('$xhr')); - }); + var element = $compile('
                          ')($rootScope); + expect($rootScope.someService).toBe($xhr); + })); }); describe('ng:cloak', function() { - it('should get removed when an element is compiled', function() { + it('should get removed when an element is compiled', inject(function($rootScope, $compile) { var element = jqLite('
                          '); expect(element.attr('ng:cloak')).toBe(''); - angular.compile(element); + $compile(element); expect(element.attr('ng:cloak')).toBeUndefined(); - }); + })); - it('should remove ng-cloak class from a compiled element', function() { + it('should remove ng-cloak class from a compiled element', inject(function($rootScope, $compile) { var element = jqLite('
                          '); expect(element.hasClass('foo')).toBe(true); expect(element.hasClass('ng-cloak')).toBe(true); expect(element.hasClass('bar')).toBe(true); - angular.compile(element); + $compile(element); expect(element.hasClass('foo')).toBe(true); expect(element.hasClass('ng-cloak')).toBe(false); expect(element.hasClass('bar')).toBe(true); - }); + })); }); }); diff --git a/test/jqLiteSpec.js b/test/jqLiteSpec.js index 2f9a5fb9ab48..5c54e786cba0 100644 --- a/test/jqLiteSpec.js +++ b/test/jqLiteSpec.js @@ -10,8 +10,8 @@ describe('jqLite', function() { }); - beforeEach(function() { - scope = angular.scope(); + beforeEach(inject(function($rootScope) { + scope = $rootScope; this.addMatchers({ toJqEqual: function(expected) { var msg = "Unequal length"; @@ -29,7 +29,7 @@ describe('jqLite', function() { return value; } }); - }); + })); afterEach(function() { diff --git a/test/markupSpec.js b/test/markupSpec.js index 41255b4a1f75..6b6ba66471b8 100644 --- a/test/markupSpec.js +++ b/test/markupSpec.js @@ -2,51 +2,36 @@ describe("markups", function() { - var compile, element, scope; - - beforeEach(function() { - scope = null; - element = null; - compile = function(html) { - element = jqLite(html); - scope = angular.compile(element)(); - }; - }); - - afterEach(function() { - dealoc(element); - }); - - it('should translate {{}} in text', function() { - compile('
                          hello {{name}}!
                          '); + it('should translate {{}} in text', inject(function($rootScope, $compile) { + var element = $compile('
                          hello {{name}}!
                          ')($rootScope) expect(sortedHtml(element)).toEqual('
                          hello !
                          '); - scope.name = 'Misko'; - scope.$digest(); + $rootScope.name = 'Misko'; + $rootScope.$digest(); expect(sortedHtml(element)).toEqual('
                          hello Misko!
                          '); - }); + })); - it('should translate {{}} in terminal nodes', function() { - compile(''); - scope.$digest(); + it('should translate {{}} in terminal nodes', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope) + $rootScope.$digest(); expect(sortedHtml(element).replace(' selected="true"', '')). toEqual(''); - scope.name = 'Misko'; - scope.$digest(); + $rootScope.name = 'Misko'; + $rootScope.$digest(); expect(sortedHtml(element).replace(' selected="true"', '')). toEqual(''); - }); + })); - it('should translate {{}} in attributes', function() { - compile('
                          '); + it('should translate {{}} in attributes', inject(function($rootScope, $compile) { + var element = $compile('
                          ')($rootScope) expect(element.attr('ng:bind-attr')).toEqual('{"src":"http://server/%7B%7Bpath%7D%7D.png"}'); - scope.path = 'a/b'; - scope.$digest(); + $rootScope.path = 'a/b'; + $rootScope.$digest(); expect(element.attr('src')).toEqual("http://server/a/b.png"); - }); + })); describe('OPTION value', function() { beforeEach(function() { @@ -69,127 +54,138 @@ describe("markups", function() { }); }); - afterEach(function() { - if (element) element.remove(); - }); - - it('should populate value attribute on OPTION', function() { - compile(''); + it('should populate value attribute on OPTION', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope) expect(element).toHaveValue('abc'); - }); + })); - it('should ignore value if already exists', function() { - compile(''); + it('should ignore value if already exists', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope) expect(element).toHaveValue('abc'); - }); + })); - it('should set value even if newlines present', function() { - compile(''); + it('should set value even if newlines present', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope) expect(element).toHaveValue('\nabc\n'); - }); + })); - it('should set value even if self closing HTML', function() { + it('should set value even if self closing HTML', inject(function($rootScope, $compile) { // IE removes the \n from option, which makes this test pointless if (msie) return; - compile(''); + var element = $compile('')($rootScope) expect(element).toHaveValue('\n'); - }); + })); }); - it('should bind href', function() { - compile(''); + it('should bind href', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope) expect(sortedHtml(element)).toEqual(''); - }); + })); - it('should bind disabled', function() { - compile(''); - scope.isDisabled = false; - scope.$digest(); + it('should bind disabled', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope) + $rootScope.isDisabled = false; + $rootScope.$digest(); expect(element.attr('disabled')).toBeFalsy(); - scope.isDisabled = true; - scope.$digest(); + $rootScope.isDisabled = true; + $rootScope.$digest(); expect(element.attr('disabled')).toBeTruthy(); - }); + })); - it('should bind checked', function() { - compile(''); - scope.isChecked = false; - scope.$digest(); + it('should bind checked', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope) + $rootScope.isChecked = false; + $rootScope.$digest(); expect(element.attr('checked')).toBeFalsy(); - scope.isChecked=true; - scope.$digest(); + $rootScope.isChecked=true; + $rootScope.$digest(); expect(element.attr('checked')).toBeTruthy(); - }); + })); - it('should bind selected', function() { - compile(''); + it('should bind selected', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope) jqLite(document.body).append(element) - scope.isSelected=false; - scope.$digest(); + $rootScope.isSelected=false; + $rootScope.$digest(); expect(element.children()[1].selected).toBeFalsy(); - scope.isSelected=true; - scope.$digest(); + $rootScope.isSelected=true; + $rootScope.$digest(); expect(element.children()[1].selected).toBeTruthy(); - }); + })); - it('should bind readonly', function() { - compile(''); - scope.isReadonly=false; - scope.$digest(); + it('should bind readonly', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope) + $rootScope.isReadonly=false; + $rootScope.$digest(); expect(element.attr('readOnly')).toBeFalsy(); - scope.isReadonly=true; - scope.$digest(); + $rootScope.isReadonly=true; + $rootScope.$digest(); expect(element.attr('readOnly')).toBeTruthy(); - }); + })); - it('should bind multiple', function() { - compile(''); - scope.isMultiple=false; - scope.$digest(); + it('should bind multiple', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope) + $rootScope.isMultiple=false; + $rootScope.$digest(); expect(element.attr('multiple')).toBeFalsy(); - scope.isMultiple='multiple'; - scope.$digest(); + $rootScope.isMultiple='multiple'; + $rootScope.$digest(); expect(element.attr('multiple')).toBeTruthy(); - }); + })); - it('should bind src', function() { - compile('
                          '); - scope.url = 'http://localhost/'; - scope.$digest(); + it('should bind src', inject(function($rootScope, $compile) { + var element = $compile('
                          ')($rootScope) + $rootScope.url = 'http://localhost/'; + $rootScope.$digest(); expect(element.attr('src')).toEqual('http://localhost/'); - }); + })); - it('should bind href and merge with other attrs', function() { - compile(''); + it('should bind href and merge with other attrs', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope) expect(sortedHtml(element)).toEqual(''); - }); - - it('should bind Text with no Bindings', function() { - forEach(['checked', 'disabled', 'multiple', 'readonly', 'selected', 'src', 'href'], - function(name) { - compile('
                          '); - expect(sortedHtml(element)).toEqual('
                          '); + })); + + it('should bind Text with no Bindings', inject(function($compile) { + var $rootScope; + function newScope (){ + return $rootScope = angular.injector('ng').get('$rootScope'); + } + forEach(['checked', 'disabled', 'multiple', 'readonly', 'selected'], function(name) { + var element = $compile('
                          ')(newScope()) + expect(element.attr('ng:bind-attr')).toBe('{"' + name +'":"some"}'); + $rootScope.$digest(); + expect(element.attr(name)).toBe(name); dealoc(element); }); - }); - it('should Parse Text With No Bindings', function() { + var element = $compile('
                          ')(newScope()) + $rootScope.$digest(); + expect(sortedHtml(element)).toEqual('
                          '); + dealoc(element); + + var element = $compile('
                          ')(newScope()) + $rootScope.$digest(); + expect(sortedHtml(element)).toEqual('
                          '); + dealoc(element); + })); + + it('should Parse Text With No Bindings', inject(function($rootScope, $compile) { var parts = parseBindings("a"); assertEquals(parts.length, 1); assertEquals(parts[0], "a"); assertTrue(!binding(parts[0])); - }); + })); - it('should Parse Empty Text', function() { + it('should Parse Empty Text', inject(function($rootScope, $compile) { var parts = parseBindings(""); assertEquals(parts.length, 1); assertEquals(parts[0], ""); assertTrue(!binding(parts[0])); - }); + })); - it('should Parse Inner Binding', function() { + it('should Parse Inner Binding', inject(function($rootScope, $compile) { var parts = parseBindings("a{{b}}C"); assertEquals(parts.length, 3); assertEquals(parts[0], "a"); @@ -198,43 +194,43 @@ describe("markups", function() { assertEquals(binding(parts[1]), "b"); assertEquals(parts[2], "C"); assertTrue(!binding(parts[2])); - }); + })); - it('should Parse Ending Binding', function() { + it('should Parse Ending Binding', inject(function($rootScope, $compile) { var parts = parseBindings("a{{b}}"); assertEquals(parts.length, 2); assertEquals(parts[0], "a"); assertTrue(!binding(parts[0])); assertEquals(parts[1], "{{b}}"); assertEquals(binding(parts[1]), "b"); - }); + })); - it('should Parse Begging Binding', function() { + it('should Parse Begging Binding', inject(function($rootScope, $compile) { var parts = parseBindings("{{b}}c"); assertEquals(parts.length, 2); assertEquals(parts[0], "{{b}}"); assertEquals(binding(parts[0]), "b"); assertEquals(parts[1], "c"); assertTrue(!binding(parts[1])); - }); + })); - it('should Parse Loan Binding', function() { + it('should Parse Loan Binding', inject(function($rootScope, $compile) { var parts = parseBindings("{{b}}"); assertEquals(parts.length, 1); assertEquals(parts[0], "{{b}}"); assertEquals(binding(parts[0]), "b"); - }); + })); - it('should Parse Two Bindings', function() { + it('should Parse Two Bindings', inject(function($rootScope, $compile) { var parts = parseBindings("{{b}}{{c}}"); assertEquals(parts.length, 2); assertEquals(parts[0], "{{b}}"); assertEquals(binding(parts[0]), "b"); assertEquals(parts[1], "{{c}}"); assertEquals(binding(parts[1]), "c"); - }); + })); - it('should Parse Two Bindings With Text In Middle', function() { + it('should Parse Two Bindings With Text In Middle', inject(function($rootScope, $compile) { var parts = parseBindings("{{b}}x{{c}}"); assertEquals(parts.length, 3); assertEquals(parts[0], "{{b}}"); @@ -243,22 +239,22 @@ describe("markups", function() { assertTrue(!binding(parts[1])); assertEquals(parts[2], "{{c}}"); assertEquals(binding(parts[2]), "c"); - }); + })); - it('should Parse Multiline', function() { + it('should Parse Multiline', inject(function($rootScope, $compile) { var parts = parseBindings('"X\nY{{A\nB}}C\nD"'); assertTrue(!!binding('{{A\nB}}')); assertEquals(parts.length, 3); assertEquals(parts[0], '"X\nY'); assertEquals(parts[1], '{{A\nB}}'); assertEquals(parts[2], 'C\nD"'); - }); + })); - it('should Has Binding', function() { + it('should Has Binding', inject(function($rootScope, $compile) { assertTrue(hasBindings(parseBindings("{{a}}"))); assertTrue(!hasBindings(parseBindings("a"))); assertTrue(hasBindings(parseBindings("{{b}}x{{c}}"))); - }); + })); }); diff --git a/test/matchers.js b/test/matchers.js index fe5792a9d1da..9cd582e17674 100644 --- a/test/matchers.js +++ b/test/matchers.js @@ -23,6 +23,13 @@ beforeEach(function() { }; } + function indexOf(array, obj) { + for ( var i = 0; i < array.length; i++) { + if (obj === array[i]) return i; + } + return -1; + } + this.addMatchers({ toBeInvalid: cssMatcher('ng-invalid', 'ng-valid'), toBeValid: cssMatcher('ng-valid', 'ng-invalid'), @@ -83,7 +90,17 @@ beforeEach(function() { toBeOneOf: function() { - return angular.Array.indexOf(arguments, this.actual) !== -1; + return indexOf(arguments, this.actual) !== -1; + }, + + toHaveClass: function(clazz) { + this.message = function() { + return "Expected '" + angular.module.ngMock.dump(this.actual) + "' to have class '" + clazz + "'."; + }; + return this.actual.hasClass ? + this.actual.hasClass(clazz) : + angular.element(this.actual).hasClass(clazz); } + }); }); diff --git a/test/mocks.js b/test/mocks.js deleted file mode 100644 index da0449acc1be..000000000000 --- a/test/mocks.js +++ /dev/null @@ -1,69 +0,0 @@ -'use strict'; - -/** - * Mock implementation of {@link angular.service.$log} that gathers all logged messages in arrays - * (one array per logging level). These arrays are exposed as `logs` property of each of the - * level-specific log function, e.g. for level `error` the array is exposed as - * `$logMock.error.logs` - * - * Please note that this is not a factory function, but rather the actual mock instance. This is - * important because it allows `beforeEach` and `afterEach` test hooks to clean up or check the - * state of `logs` arrays in between tests. - * - * Exposing the instance in this way makes this mock a singleton, which means that the instance - * becomes global state for tests. To mitigate the issue, each time the `$log` mock is registered - * with the injector, a check is performed to ensure that there are no pending logs in `logs` - * arrays. This means that if a message is logged via $log during a test, the `logs` array must be - * emptied before the test is finished. `Array#shift` method can be used for this purpose as - * follows: - * - *
                          - *   it('should do some good', function() {
                          - *     var scope = angular.scope(),
                          - *         $log = scope.$service('$log');
                          - *
                          - *     //do something that triggers a message to be logged
                          - *     expect($log.error.logs.shift()).toEqual(['message', 'arg1', 'arg2']);
                          - *   });
                          - * 
                          - * - * See {@link angular.mock} for more info on angular mocks. - */ -var $logMock = { - log: function() { $logMock.log.logs.push(concat([], arguments, 0)); }, - warn: function() { $logMock.warn.logs.push(concat([], arguments, 0)); }, - info: function() { $logMock.info.logs.push(concat([], arguments, 0)); }, - error: function() { $logMock.error.logs.push(concat([], arguments, 0)); } -}; -$logMock.log.logs = []; -$logMock.warn.logs = []; -$logMock.info.logs = []; -$logMock.error.logs = []; - -angular.service('$log', function() { - return $logMock; -}); - - -/** - * Factory that returns mock implementation of {@link angular.service.$exceptionHandler} that - * gathers all errors in an array. This array is exposed as `errors` property of the mock and can be - * accessed as `$exceptionHandler.errors`. - * - * Note that this factory is not registered with angular's injector by default (as opposed to - * `$logMock`). It is your responsibility to register this factory when you need it. Typically like - * this: - * - *
                          - *   var scope = angular.scope(null, {'$exceptionHandler': $exceptionHandlerMockFactory()});
                          - * 
                          - * - */ -function $exceptionHandlerMockFactory() { - var mockHandler = function(e) { - mockHandler.errors.push(e); - }; - mockHandler.errors = []; - - return mockHandler; -} diff --git a/test/scenario/ApplicationSpec.js b/test/scenario/ApplicationSpec.js index 8caf1651cca1..86023438ebfc 100644 --- a/test/scenario/ApplicationSpec.js +++ b/test/scenario/ApplicationSpec.js @@ -112,22 +112,20 @@ describe('angular.scenario.Application', function() { expect(called).toBeTruthy(); }); - it('should wait for pending requests in executeAction', function() { + it('should wait for pending requests in executeAction', inject(function($injector, $browser) { var called, polled; var handlers = []; var testWindow = { - document: _jQuery('
                          '), + document: jqLite('
                          '), angular: { + element: jqLite, service: {} } }; - testWindow.angular.service.$browser = function() { - return { - notifyWhenNoOutstandingRequests: function(fn) { - handlers.push(fn); - } - }; + $browser.notifyWhenNoOutstandingRequests = function(fn) { + handlers.push(fn); }; + testWindow.document.data('$injector', $injector); app.getWindow_ = function() { return testWindow; }; @@ -138,5 +136,6 @@ describe('angular.scenario.Application', function() { }); expect(handlers.length).toEqual(1); handlers[0](); - }); + dealoc(testWindow.document); + })); }); diff --git a/test/scenario/RunnerSpec.js b/test/scenario/RunnerSpec.js index 62d84fca0085..8d1f832dff5f 100644 --- a/test/scenario/RunnerSpec.js +++ b/test/scenario/RunnerSpec.js @@ -46,8 +46,8 @@ describe('angular.scenario.Runner', function() { runner.createSpecRunner_ = function(scope) { return scope.$new(MockSpecRunner); }; - runner.on('SpecError', rethrow); - runner.on('StepError', rethrow); + runner.on('SpecError', angular.module.ngMock.rethrow); + runner.on('StepError', angular.module.ngMock.rethrow); }); afterEach(function() { diff --git a/test/scenario/SpecRunnerSpec.js b/test/scenario/SpecRunnerSpec.js index 92f000bae233..4cffc63aa684 100644 --- a/test/scenario/SpecRunnerSpec.js +++ b/test/scenario/SpecRunnerSpec.js @@ -25,13 +25,13 @@ describe('angular.scenario.SpecRunner', function() { }; } - beforeEach(function() { + beforeEach(inject(function($rootScope) { log = []; $window = {}; $window.setTimeout = function(fn, timeout) { fn(); }; - $root = angular.scope(); + $root = $rootScope; $root.emit = function(eventName) { log.push(eventName); }; @@ -41,7 +41,7 @@ describe('angular.scenario.SpecRunner', function() { $root.application = new ApplicationMock($window); $root.$window = $window; runner = $root.$new(angular.scenario.SpecRunner); - }); + })); it('should bind futures to the spec', function() { runner.addFuture('test future', function(done) { diff --git a/test/scenario/dslSpec.js b/test/scenario/dslSpec.js index 32d7ebb637d5..1b0d613c9796 100644 --- a/test/scenario/dslSpec.js +++ b/test/scenario/dslSpec.js @@ -4,13 +4,14 @@ describe("angular.scenario.dsl", function() { var $window, $root; var application, eventLog; - beforeEach(function() { + beforeEach(inject(function($injector) { eventLog = []; $window = { - document: _jQuery("
                          "), + document: jqLite('
                          '), angular: new angular.scenario.testing.MockAngular() }; - $root = angular.scope(); + $window.document.data('$injector', $injector); + $root = $injector.get('$rootScope'); $root.emit = function(eventName) { eventLog.push(eventName); }; @@ -45,6 +46,10 @@ describe("angular.scenario.dsl", function() { // Just use the real one since it delegates to this.addFuture $root.addFutureAction = angular.scenario. SpecRunner.prototype.addFutureAction; + })); + + afterEach(function(){ + jqLite($window.document).removeData('$injector'); }); describe('Pause', function() { @@ -156,9 +161,9 @@ describe("angular.scenario.dsl", function() { describe('location', function() { beforeEach(function() { - $window.angular.scope = function() { + $window.angular.injector = function() { return { - $service: function(serviceId) { + get: function(serviceId) { if (serviceId == '$location') { return { url: function() {return '/path?search=a#hhh';}, @@ -203,11 +208,14 @@ describe("angular.scenario.dsl", function() { // ex. jQuery('#foo').find('[name="bar"]') // fails // ex. jQuery('#foo [name="bar"]') // works, wtf? // - beforeEach(function() { + beforeEach(inject(function($injector) { doc = _jQuery('
                          '); _jQuery(document.body).html('').append(doc); - $window.document = window.document; - }); + + dealoc($window.document); // we are about to override it + $window.document = window.document; + jqLite($window.document).data('$injector', $injector); + })); afterEach(function() { _jQuery(document.body). diff --git a/test/scenario/matchersSpec.js b/test/scenario/matchersSpec.js index 7ab41cf23ebf..7a5217d7e1eb 100644 --- a/test/scenario/matchersSpec.js +++ b/test/scenario/matchersSpec.js @@ -42,4 +42,10 @@ describe('angular.scenario.matchers', function () { expectMatcher(3, function() { matchers.toBeLessThan(10); }); expectMatcher(3, function() { matchers.toBeGreaterThan(-5); }); }); + + it('should have toHaveClass matcher', function(){ + var e = angular.element('
                          '); + expect(e).not.toHaveClass('none'); + expect(e).toHaveClass('abc'); + }); }); diff --git a/test/scenario/mocks.js b/test/scenario/mocks.js index 5b7f7fccbdce..e135390f039d 100644 --- a/test/scenario/mocks.js +++ b/test/scenario/mocks.js @@ -4,28 +4,18 @@ angular.scenario.testing = angular.scenario.testing || {}; angular.scenario.testing.MockAngular = function() { this.reset(); - this.service = this; + this.element = jqLite; }; angular.scenario.testing.MockAngular.prototype.reset = function() { this.log = []; }; -angular.scenario.testing.MockAngular.prototype.$browser = function() { - this.log.push('$brower()'); - return this; -}; - angular.scenario.testing.MockAngular.prototype.poll = function() { this.log.push('$brower.poll()'); return this; }; -angular.scenario.testing.MockAngular.prototype.notifyWhenNoOutstandingRequests = function(fn) { - this.log.push('$brower.notifyWhenNoOutstandingRequests()'); - fn(); -}; - angular.scenario.testing.MockRunner = function() { this.listeners = []; }; diff --git a/test/CompilerSpec.js b/test/service/compilerSpec.js similarity index 52% rename from test/CompilerSpec.js rename to test/service/compilerSpec.js index 860cea4a0159..ccf70aaff042 100644 --- a/test/CompilerSpec.js +++ b/test/service/compilerSpec.js @@ -1,10 +1,12 @@ 'use strict'; describe('compiler', function() { - var compiler, markup, attrMarkup, directives, widgets, compile, log, scope; + var compiler, textMmarkup, attrMarkup, directives, widgets, compile, log, $rootScope; - beforeEach(function() { - log = ""; + beforeEach(inject(function($provide){ + textMmarkup = []; + attrMarkup = []; + widgets = extensionMap({}, 'widget'); directives = { hello: function(expression, element){ log += "hello "; @@ -23,33 +25,25 @@ describe('compiler', function() { } }; - markup = []; - attrMarkup = []; - widgets = extensionMap({}, 'widget'); - compiler = new Compiler(markup, attrMarkup, directives, widgets); - compile = function(html){ - var e = jqLite("
                          " + html + "
                          "); - return scope = compiler.compile(e)(); - }; - }); - - - afterEach(function() { - dealoc(scope); - }); + log = ""; + $provide.value('$textMarkup', textMmarkup); + $provide.value('$attrMarkup', attrMarkup); + $provide.value('$directive', directives); + $provide.value('$widget', widgets); + })); - it('should not allow compilation of multiple roots', function() { + it('should not allow compilation of multiple roots', inject(function($rootScope, $compile) { expect(function() { - compiler.compile('
                          A
                          '); + $compile('
                          A
                          '); }).toThrow("Cannot compile multiple element roots: " + ie("
                          A
                          ")); function ie(text) { return msie < 9 ? uppercase(text) : text; } - }); + })); - it('should recognize a directive', function() { + it('should recognize a directive', inject(function($rootScope, $compile) { var e = jqLite('
                          '); directives.directive = function(expression, element){ log += "found"; @@ -59,79 +53,80 @@ describe('compiler', function() { log += ":init"; }; }; - var template = compiler.compile(e); + var linkFn = $compile(e); expect(log).toEqual("found"); - scope = template(angular.scope()); + linkFn($rootScope); expect(e.hasClass('ng-directive')).toEqual(true); expect(log).toEqual("found:init"); - }); + })); - it('should recurse to children', function() { - scope = compile('
                          '); + it('should recurse to children', inject(function($rootScope, $compile) { + $compile('
                          ')($rootScope); expect(log).toEqual("hello misko"); - }); + })); - it('should observe scope', function() { - scope = compile(''); + it('should observe scope', inject(function($rootScope, $compile) { + $compile('')($rootScope); expect(log).toEqual(""); - scope.$digest(); - scope.name = 'misko'; - scope.$digest(); - scope.$digest(); - scope.name = 'adam'; - scope.$digest(); - scope.$digest(); + $rootScope.$digest(); + $rootScope.name = 'misko'; + $rootScope.$digest(); + $rootScope.$digest(); + $rootScope.name = 'adam'; + $rootScope.$digest(); + $rootScope.$digest(); expect(log).toEqual(":misko:adam"); - }); + })); - it('should prevent descend', function() { + it('should prevent descend', inject(function($rootScope, $compile) { directives.stop = function() { this.descend(false); }; - scope = compile(''); + $compile('')($rootScope); expect(log).toEqual("hello misko"); - }); + })); - it('should allow creation of templates', function() { + it('should allow creation of templates', inject(function($rootScope, $compile) { directives.duplicate = function(expr, element){ element.replaceWith(document.createComment("marker")); element.removeAttr("duplicate"); var linker = this.compile(element); return function(marker) { this.$watch('value', function() { - var scope = linker(angular.scope(), noop); + var scope = $rootScope.$new; + linker(scope, noop); marker.after(scope.$element); }); }; }; - scope = compile('beforexafter'); - expect(sortedHtml(scope.$element)). + $compile('
                          beforexafter
                          ')($rootScope); + expect(sortedHtml($rootScope.$element)). toEqual('
                          ' + 'before<#comment>' + 'after' + '
                          '); - scope.value = 1; - scope.$digest(); - expect(sortedHtml(scope.$element)). + $rootScope.value = 1; + $rootScope.$digest(); + expect(sortedHtml($rootScope.$element)). toEqual('
                          ' + 'before<#comment>' + 'x' + 'after' + '
                          '); - scope.value = 2; - scope.$digest(); - expect(sortedHtml(scope.$element)). + $rootScope.value = 2; + $rootScope.$digest(); + expect(sortedHtml($rootScope.$element)). toEqual('
                          ' + 'before<#comment>' + 'x' + 'x' + 'after' + '
                          '); - scope.value = 3; - scope.$digest(); - expect(sortedHtml(scope.$element)). + $rootScope.value = 3; + $rootScope.$digest(); + expect(sortedHtml($rootScope.$element)). toEqual('
                          ' + 'before<#comment>' + 'x' + @@ -139,24 +134,25 @@ describe('compiler', function() { 'x' + 'after' + '
                          '); - }); + })); - it('should process markup before directives', function() { - markup.push(function(text, textNode, parentNode) { + it('should process markup before directives', inject(function($rootScope, $compile) { + textMmarkup.push(function(text, textNode, parentNode) { if (text == 'middle') { expect(textNode.text()).toEqual(text); parentNode.attr('hello', text); textNode[0].nodeValue = 'replaced'; } }); - scope = compile('beforemiddleafter'); - expect(sortedHtml(scope.$element[0], true)).toEqual('
                          beforereplacedafter
                          '); + $compile('
                          beforemiddleafter
                          ')($rootScope); + expect(sortedHtml($rootScope.$element[0], true)). + toEqual('
                          beforereplacedafter
                          '); expect(log).toEqual("hello middle"); - }); + })); - it('should replace widgets', function() { + it('should replace widgets', inject(function($rootScope, $compile) { widgets['NG:BUTTON'] = function(element) { expect(element.hasClass('ng-widget')).toEqual(true); element.replaceWith('
                          button
                          '); @@ -164,13 +160,13 @@ describe('compiler', function() { log += 'init'; }; }; - scope = compile('push me'); - expect(lowercase(scope.$element[0].innerHTML)).toEqual('
                          button
                          '); + $compile('
                          push me
                          ')($rootScope); + expect(lowercase($rootScope.$element[0].innerHTML)).toEqual('
                          button
                          '); expect(log).toEqual('init'); - }); + })); - it('should use the replaced element after calling widget', function() { + it('should use the replaced element after calling widget', inject(function($rootScope, $compile) { widgets['H1'] = function(element) { // HTML elements which are augmented by acting as widgets, should not be marked as so expect(element.hasClass('ng-widget')).toEqual(false); @@ -180,17 +176,17 @@ describe('compiler', function() { this.directives(true); return noop; }; - markup.push(function(text, textNode, parent){ + textMmarkup.push(function(text, textNode, parent){ if (text == '{{1+2}}') parent.text('3'); }); - scope = compile('

                          ignore me

                          '); - expect(scope.$element.text()).toEqual('3'); - }); + $compile('

                          ignore me

                          ')($rootScope); + expect($rootScope.$element.text()).toEqual('3'); + })); - it('should allow multiple markups per text element', function() { - markup.push(function(text, textNode, parent){ + it('should allow multiple markups per text element', inject(function($rootScope, $compile) { + textMmarkup.push(function(text, textNode, parent){ var index = text.indexOf('---'); if (index > -1) { textNode.after(text.substring(index + 3)); @@ -199,7 +195,7 @@ describe('compiler', function() { textNode.remove(); } }); - markup.push(function(text, textNode, parent){ + textMmarkup.push(function(text, textNode, parent){ var index = text.indexOf('==='); if (index > -1) { textNode.after(text.substring(index + 3)); @@ -208,14 +204,13 @@ describe('compiler', function() { textNode.remove(); } }); - scope = compile('A---B---C===D'); - expect(sortedHtml(scope.$element)).toEqual('
                          A
                          B
                          C

                          D
                          '); - }); + $compile('
                          A---B---C===D
                          ')($rootScope); + expect(sortedHtml($rootScope.$element)).toEqual('
                          A
                          B
                          C

                          D
                          '); + })); - it('should add class for namespace elements', function() { - scope = compile('abc'); - var space = jqLite(scope.$element[0].firstChild); - expect(space.hasClass('ng-space')).toEqual(true); - }); + it('should add class for namespace elements', inject(function($rootScope, $compile) { + var element = $compile('abc')($rootScope); + expect(element.hasClass('ng-space')).toEqual(true); + })); }); diff --git a/test/service/cookieStoreSpec.js b/test/service/cookieStoreSpec.js index 0bf7e99d90f2..50ac7797aaf4 100644 --- a/test/service/cookieStoreSpec.js +++ b/test/service/cookieStoreSpec.js @@ -1,41 +1,30 @@ 'use strict'; describe('$cookieStore', function() { - var scope, $browser, $cookieStore; - beforeEach(function() { - scope = angular.scope(); - $cookieStore = scope.$service('$cookieStore'); - $browser = scope.$service('$browser'); - }); - afterEach(function() { - dealoc(scope); - }); - - - it('should serialize objects to json', function() { + it('should serialize objects to json', inject(function($cookieStore, $browser, $rootScope) { $cookieStore.put('objectCookie', {id: 123, name: 'blah'}); - scope.$digest(); + $rootScope.$digest(); expect($browser.cookies()).toEqual({'objectCookie': '{"id":123,"name":"blah"}'}); - }); + })); - it('should deserialize json to object', function() { + it('should deserialize json to object', inject(function($cookieStore, $browser) { $browser.cookies('objectCookie', '{"id":123,"name":"blah"}'); $browser.poll(); expect($cookieStore.get('objectCookie')).toEqual({id: 123, name: 'blah'}); - }); + })); - it('should delete objects from the store when remove is called', function() { + it('should delete objects from the store when remove is called', inject(function($cookieStore, $browser, $rootScope) { $cookieStore.put('gonner', { "I'll":"Be Back"}); - scope.$digest(); //force eval in test + $rootScope.$digest(); //force eval in test $browser.poll(); expect($browser.cookies()).toEqual({'gonner': '{"I\'ll":"Be Back"}'}); $cookieStore.remove('gonner'); - scope.$digest(); + $rootScope.$digest(); expect($browser.cookies()).toEqual({}); - }); + })); }); diff --git a/test/service/cookiesSpec.js b/test/service/cookiesSpec.js index f078c20cabec..a4db9546ac50 100644 --- a/test/service/cookiesSpec.js +++ b/test/service/cookiesSpec.js @@ -1,82 +1,79 @@ 'use strict'; describe('$cookies', function() { - var scope, $browser; - - beforeEach(function() { - $browser = new MockBrowser(); - $browser.cookieHash['preexisting'] = 'oldCookie'; - scope = angular.scope(angular.service, {$browser: $browser}); - scope.$cookies = scope.$service('$cookies'); - }); - - afterEach(function() { - dealoc(scope); - }); - + beforeEach(inject(function($provide) { + $provide.factory('$browser', function(){ + return angular.extend(new angular.module.ngMock.$Browser(), {cookieHash: {preexisting:'oldCookie'}}); + }); + })); + it('should provide access to existing cookies via object properties and keep them in sync', - function() { - expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'}); + inject(function($cookies, $browser, $rootScope) { + expect($cookies).toEqual({'preexisting': 'oldCookie'}); // access internal cookie storage of the browser mock directly to simulate behavior of // document.cookie $browser.cookieHash['brandNew'] = 'cookie'; $browser.poll(); - expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie'}); + expect($cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie'}); $browser.cookieHash['brandNew'] = 'cookie2'; $browser.poll(); - expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie2'}); + expect($cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie2'}); delete $browser.cookieHash['brandNew']; $browser.poll(); - expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'}); - }); + expect($cookies).toEqual({'preexisting': 'oldCookie'}); + })); - it('should create or update a cookie when a value is assigned to a property', function() { - scope.$cookies.oatmealCookie = 'nom nom'; - scope.$digest(); + it('should create or update a cookie when a value is assigned to a property', + inject(function($cookies, $browser, $rootScope) { + $cookies.oatmealCookie = 'nom nom'; + $rootScope.$digest(); expect($browser.cookies()). toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'}); - scope.$cookies.oatmealCookie = 'gone'; - scope.$digest(); + $cookies.oatmealCookie = 'gone'; + $rootScope.$digest(); expect($browser.cookies()). toEqual({'preexisting': 'oldCookie', 'oatmealCookie': 'gone'}); - }); + })); - it('should drop or reset any cookie that was set to a non-string value', function() { - scope.$cookies.nonString = [1, 2, 3]; - scope.$cookies.nullVal = null; - scope.$cookies.undefVal = undefined; - scope.$cookies.preexisting = function() {}; - scope.$digest(); + it('should drop or reset any cookie that was set to a non-string value', + inject(function($cookies, $browser, $rootScope) { + $cookies.nonString = [1, 2, 3]; + $cookies.nullVal = null; + $cookies.undefVal = undefined; + $cookies.preexisting = function() {}; + $rootScope.$digest(); expect($browser.cookies()).toEqual({'preexisting': 'oldCookie'}); - expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'}); - }); + expect($cookies).toEqual({'preexisting': 'oldCookie'}); + })); - it('should remove a cookie when a $cookies property is deleted', function() { - scope.$cookies.oatmealCookie = 'nom nom'; - scope.$digest(); + it('should remove a cookie when a $cookies property is deleted', + inject(function($cookies, $browser, $rootScope) { + $cookies.oatmealCookie = 'nom nom'; + $rootScope.$digest(); $browser.poll(); expect($browser.cookies()). toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'}); - delete scope.$cookies.oatmealCookie; - scope.$digest(); + delete $cookies.oatmealCookie; + $rootScope.$digest(); expect($browser.cookies()).toEqual({'preexisting': 'oldCookie'}); - }); + })); - it('should drop or reset cookies that browser refused to store', function() { + it('should drop or reset cookies that browser refused to store', + inject(function($cookies, $browser, $rootScope) { var i, longVal; for (i=0; i<5000; i++) { @@ -84,17 +81,17 @@ describe('$cookies', function() { } //drop if no previous value - scope.$cookies.longCookie = longVal; - scope.$digest(); - expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'}); + $cookies.longCookie = longVal; + $rootScope.$digest(); + expect($cookies).toEqual({'preexisting': 'oldCookie'}); //reset if previous value existed - scope.$cookies.longCookie = 'shortVal'; - scope.$digest(); - expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'longCookie': 'shortVal'}); - scope.$cookies.longCookie = longVal; - scope.$digest(); - expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'longCookie': 'shortVal'}); - }); + $cookies.longCookie = 'shortVal'; + $rootScope.$digest(); + expect($cookies).toEqual({'preexisting': 'oldCookie', 'longCookie': 'shortVal'}); + $cookies.longCookie = longVal; + $rootScope.$digest(); + expect($cookies).toEqual({'preexisting': 'oldCookie', 'longCookie': 'shortVal'}); + })); }); diff --git a/test/service/deferSpec.js b/test/service/deferSpec.js index ff48c93ef05d..2468512d404e 100644 --- a/test/service/deferSpec.js +++ b/test/service/deferSpec.js @@ -1,22 +1,14 @@ 'use strict'; describe('$defer', function() { - var scope, $browser, $defer, $exceptionHandler; - - beforeEach(function() { - scope = angular.scope(angular.service, - {'$exceptionHandler': jasmine.createSpy('$exceptionHandler')}); - $browser = scope.$service('$browser'); - $defer = scope.$service('$defer'); - $exceptionHandler = scope.$service('$exceptionHandler'); - }); - - afterEach(function() { - dealoc(scope); - }); + beforeEach(inject(function($provide) { + $provide.factory('$exceptionHandler', function(){ + return jasmine.createSpy('$exceptionHandler'); + }); + })); - it('should delegate functions to $browser.defer', function() { + it('should delegate functions to $browser.defer', inject(function($defer, $browser, $exceptionHandler) { var counter = 0; $defer(function() { counter++; }); @@ -29,20 +21,20 @@ describe('$defer', function() { expect(counter).toBe(1); expect($exceptionHandler).not.toHaveBeenCalled(); - }); + })); - it('should delegate exception to the $exceptionHandler service', function() { + it('should delegate exception to the $exceptionHandler service', inject(function($defer, $browser, $exceptionHandler) { $defer(function() {throw "Test Error";}); expect($exceptionHandler).not.toHaveBeenCalled(); $browser.defer.flush(); expect($exceptionHandler).toHaveBeenCalledWith("Test Error"); - }); + })); - it('should call $apply after each callback is executed', function() { - var applySpy = this.spyOn(scope, '$apply').andCallThrough(); + it('should call $apply after each callback is executed', inject(function($defer, $browser, $rootScope) { + var applySpy = this.spyOn($rootScope, '$apply').andCallThrough(); $defer(function() {}); expect(applySpy).not.toHaveBeenCalled(); @@ -56,36 +48,36 @@ describe('$defer', function() { $defer(function() {}); $browser.defer.flush(); expect(applySpy.callCount).toBe(2); - }); + })); - it('should call $apply even if an exception is thrown in callback', function() { - var applySpy = this.spyOn(scope, '$apply').andCallThrough(); + it('should call $apply even if an exception is thrown in callback', inject(function($defer, $browser, $rootScope) { + var applySpy = this.spyOn($rootScope, '$apply').andCallThrough(); $defer(function() {throw "Test Error";}); expect(applySpy).not.toHaveBeenCalled(); $browser.defer.flush(); expect(applySpy).toHaveBeenCalled(); - }); + })); - it('should allow you to specify the delay time', function() { + it('should allow you to specify the delay time', inject(function($defer, $browser) { var defer = this.spyOn($browser, 'defer'); $defer(noop, 123); expect(defer.callCount).toEqual(1); expect(defer.mostRecentCall.args[1]).toEqual(123); - }); + })); - it('should return a cancelation token', function() { + it('should return a cancelation token', inject(function($defer, $browser) { var defer = this.spyOn($browser, 'defer').andReturn('xxx'); expect($defer(noop)).toEqual('xxx'); - }); + })); describe('cancel', function() { - it('should cancel tasks', function() { + it('should cancel tasks', inject(function($defer, $browser) { var task1 = jasmine.createSpy('task1'), task2 = jasmine.createSpy('task2'), task3 = jasmine.createSpy('task3'), @@ -102,10 +94,10 @@ describe('$defer', function() { expect(task1).not.toHaveBeenCalled(); expect(task2).toHaveBeenCalledOnce(); expect(task3).not.toHaveBeenCalled(); - }); + })); - it('should return true if a task was succesffuly canceled', function() { + it('should return true if a task was succesffuly canceled', inject(function($defer, $browser) { var task1 = jasmine.createSpy('task1'), task2 = jasmine.createSpy('task2'), token1, token2; @@ -116,6 +108,6 @@ describe('$defer', function() { expect($defer.cancel(token1)).toBe(false); expect($defer.cancel(token2)).toBe(true); - }); + })); }); }); diff --git a/test/service/documentSpec.js b/test/service/documentSpec.js index 885331e4728e..064904a26db0 100644 --- a/test/service/documentSpec.js +++ b/test/service/documentSpec.js @@ -1,19 +1,9 @@ 'use strict'; describe('$document', function() { - var scope; - beforeEach(function() { - scope = angular.scope(); - }); - - afterEach(function() { - dealoc(scope); - }); - - - it("should inject $document", function() { - expect(scope.$service('$document')).toEqual(jqLite(document)); - }); + it("should inject $document", inject(function($document) { + expect($document).toEqual(jqLite(document)); + })); }); diff --git a/test/service/exceptionHandlerSpec.js b/test/service/exceptionHandlerSpec.js index 61e652b5278e..00abff3012f6 100644 --- a/test/service/exceptionHandlerSpec.js +++ b/test/service/exceptionHandlerSpec.js @@ -1,26 +1,15 @@ 'use strict'; describe('$exceptionHandler', function() { - var scope; - beforeEach(function() { - scope = angular.scope(); - }); - - afterEach(function() { - dealoc(scope); - }); - - - it('should log errors', function() { - var scope = createScope({$exceptionHandler: $exceptionHandlerFactory}, - {$log: $logMock}), - $log = scope.$service('$log'), - $exceptionHandler = scope.$service('$exceptionHandler'); - - $log.error.rethrow = false; - $exceptionHandler('myError'); - expect($log.error.logs.shift()).toEqual(['myError']); - }); + it('should log errors', inject( + function($provide){ + $provide.service('$exceptionHandler', $ExceptionHandlerProvider); + }, + function($log, $exceptionHandler) { + $exceptionHandler('myError'); + expect($log.error.logs.shift()).toEqual(['myError']); + } + )); }); diff --git a/test/service/filter/filterSpec.js b/test/service/filter/filterSpec.js new file mode 100644 index 000000000000..9c43144c7435 --- /dev/null +++ b/test/service/filter/filterSpec.js @@ -0,0 +1,68 @@ +'use strict'; + +describe('Filter: filter', function() { + var filter; + + beforeEach(inject(function($filter){ + filter = $filter('filter'); + })); + + it('should filter by string', function() { + var items = ["MIsKO", {name:"shyam"}, ["adam"], 1234]; + assertEquals(4, filter(items, "").length); + assertEquals(4, filter(items, undefined).length); + + assertEquals(1, filter(items, 'iSk').length); + assertEquals("MIsKO", filter(items, 'isk')[0]); + + assertEquals(1, filter(items, 'yam').length); + assertEquals(items[1], filter(items, 'yam')[0]); + + assertEquals(1, filter(items, 'da').length); + assertEquals(items[2], filter(items, 'da')[0]); + + assertEquals(1, filter(items, '34').length); + assertEquals(1234, filter(items, '34')[0]); + + assertEquals(0, filter(items, "I don't exist").length); + }); + + it('should not read $ properties', function() { + assertEquals("", "".charAt(0)); // assumption + var items = [{$name:"misko"}]; + assertEquals(0, filter(items, "misko").length); + }); + + it('should filter on specific property', function() { + var items = [{ignore:"a", name:"a"}, {ignore:"a", name:"abc"}]; + assertEquals(2, filter(items, {}).length); + + assertEquals(2, filter(items, {name:'a'}).length); + + assertEquals(1, filter(items, {name:'b'}).length); + assertEquals("abc", filter(items, {name:'b'})[0].name); + }); + + it('should take function as predicate', function() { + var items = [{name:"a"}, {name:"abc", done:true}]; + assertEquals(1, filter(items, function(i) {return i.done;}).length); + }); + + it('should take object as perdicate', function() { + var items = [{first:"misko", last:"hevery"}, + {first:"adam", last:"abrons"}]; + + assertEquals(2, filter(items, {first:'', last:''}).length); + assertEquals(1, filter(items, {first:'', last:'hevery'}).length); + assertEquals(0, filter(items, {first:'adam', last:'hevery'}).length); + assertEquals(1, filter(items, {first:'misko', last:'hevery'}).length); + assertEquals(items[0], filter(items, {first:'misko', last:'hevery'})[0]); + }); + + it('should support negation operator', function() { + var items = ["misko", "adam"]; + + assertEquals(1, filter(items, '!isk').length); + assertEquals(items[1], filter(items, '!isk')[0]); + }); +}); diff --git a/test/FiltersSpec.js b/test/service/filter/filtersSpec.js similarity index 78% rename from test/FiltersSpec.js rename to test/service/filter/filtersSpec.js index df47ccc3602d..70497a615a4a 100644 --- a/test/FiltersSpec.js +++ b/test/service/filter/filtersSpec.js @@ -1,31 +1,20 @@ 'use strict'; -describe('filter', function() { +describe('filters', function() { - var filter = angular.filter; + var filter; - it('should called the filter when evaluating expression', function() { - var scope = createScope(); - filter.fakeFilter = function() {}; - spyOn(filter, 'fakeFilter'); + beforeEach(inject(function($filter){ + filter = $filter; + })); - scope.$eval('10|fakeFilter'); - expect(filter.fakeFilter).toHaveBeenCalledWith(10); - delete filter['fakeFilter']; - }); + it('should called the filter when evaluating expression', inject(function($rootScope, $filterProvider) { + var filter = jasmine.createSpy('myFilter'); + $filterProvider.register('myFilter', valueFn(filter)); - it('should call filter on scope context', function() { - var scope = createScope(); - scope.name = 'misko'; - filter.fakeFilter = function() { - expect(this.name).toEqual('misko'); - }; - spyOn(filter, 'fakeFilter').andCallThrough(); - - scope.$eval('10|fakeFilter'); - expect(filter.fakeFilter).toHaveBeenCalled(); - delete filter['fakeFilter']; - }); + $rootScope.$eval('10|myFilter'); + expect(filter).toHaveBeenCalledWith(10); + })); describe('formatNumber', function() { var pattern; @@ -83,46 +72,32 @@ describe('filter', function() { }); describe('currency', function() { - var currency, html, context; + var currency; beforeEach(function() { - html = jqLite(''); - context = createScope(); - context.$element = html; - currency = bind(context, filter.currency); - }); - - afterEach(function() { - dealoc(context); + currency = filter('currency'); }); - it('should do basic currency filtering', function() { expect(currency(0)).toEqual('$0.00'); - expect(html.hasClass('ng-format-negative')).toBeFalsy(); expect(currency(-999)).toEqual('($999.00)'); - expect(html.hasClass('ng-format-negative')).toBeTruthy(); expect(currency(1234.5678, "USD$")).toEqual('USD$1,234.57'); - expect(html.hasClass('ng-format-negative')).toBeFalsy(); }); it('should return empty string for non-numbers', function() { expect(currency()).toBe(''); - expect(html.hasClass('ng-format-negative')).toBeFalsy(); expect(currency('abc')).toBe(''); - expect(html.hasClass('ng-format-negative')).toBeFalsy(); }); }); describe('number', function() { - var context, number; + var number; - beforeEach(function() { - context = createScope(); - number = bind(context, filter.number); - }); + beforeEach(inject(function($rootScope) { + number = filter('number'); + })); it('should do basic filter', function() { @@ -158,34 +133,39 @@ describe('filter', function() { describe('json', function () { it('should do basic filter', function() { - expect(filter.json.call({$element:jqLite('
                          ')}, {a:"b"})).toEqual(toJson({a:"b"}, true)); + expect(filter('json')({a:"b"})).toEqual(toJson({a:"b"}, true)); }); }); describe('lowercase', function() { it('should do basic filter', function() { - expect(filter.lowercase('AbC')).toEqual('abc'); - expect(filter.lowercase(null)).toBeNull(); + expect(filter('lowercase')('AbC')).toEqual('abc'); + expect(filter('lowercase')(null)).toBeNull(); }); }); describe('uppercase', function() { it('should do basic filter', function() { - expect(filter.uppercase('AbC')).toEqual('ABC'); - expect(filter.uppercase(null)).toBeNull(); + expect(filter('uppercase')('AbC')).toEqual('ABC'); + expect(filter('uppercase')(null)).toBeNull(); }); }); describe('html', function() { it('should do basic filter', function() { - var html = filter.html("acd"); + var html = filter('html')("acd"); expect(html instanceof HTML).toBeTruthy(); expect(html.html).toEqual("acd"); }); }); describe('linky', function() { - var linky = filter.linky; + var linky; + + beforeEach(inject(function($filter){ + linky = $filter('linky') + })); + it('should do basic filter', function() { expect(linky("http://ab/%20(http://a/)%20%3Chttp://a/%3E%20http://1.2/v:~-123.%20c").html). toEqual('http://ab/ ' + @@ -207,17 +187,16 @@ describe('filter', function() { describe('date', function() { - var morning = new TzDate(+5, '2010-09-03T12:05:08.000Z'); //7am - var noon = new TzDate(+5, '2010-09-03T17:05:08.000Z'); //12pm - var midnight = new TzDate(+5, '2010-09-03T05:05:08.000Z'); //12am - var earlyDate = new TzDate(+5, '0001-09-03T05:05:08.000Z'); + var morning = new angular.module.ngMock.TzDate(+5, '2010-09-03T12:05:08.000Z'); //7am + var noon = new angular.module.ngMock.TzDate(+5, '2010-09-03T17:05:08.000Z'); //12pm + var midnight = new angular.module.ngMock.TzDate(+5, '2010-09-03T05:05:08.000Z'); //12am + var earlyDate = new angular.module.ngMock.TzDate(+5, '0001-09-03T05:05:08.000Z'); - var context, date; + var date; - beforeEach(function() { - context = createScope(); - date = bind(context, filter.date); - }); + beforeEach(inject(function($filter) { + date = $filter('date'); + })); it('should ignore falsy inputs', function() { expect(date(null)).toBeNull(); diff --git a/test/service/filter/limitToSpec.js b/test/service/filter/limitToSpec.js new file mode 100644 index 000000000000..b09772358281 --- /dev/null +++ b/test/service/filter/limitToSpec.js @@ -0,0 +1,52 @@ +'use strict'; + +describe('Filter: limitTo', function() { + var items; + var limitTo; + + beforeEach(inject(function($filter) { + items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; + limitTo = $filter('limitTo'); + })); + + + it('should return the first X items when X is positive', function() { + expect(limitTo(items, 3)).toEqual(['a', 'b', 'c']); + expect(limitTo(items, '3')).toEqual(['a', 'b', 'c']); + }); + + + it('should return the last X items when X is negative', function() { + expect(limitTo(items, -3)).toEqual(['f', 'g', 'h']); + expect(limitTo(items, '-3')).toEqual(['f', 'g', 'h']); + }); + + + it('should return an empty array when X cannot be parsed', function() { + expect(limitTo(items, 'bogus')).toEqual([]); + expect(limitTo(items, 'null')).toEqual([]); + expect(limitTo(items, 'undefined')).toEqual([]); + expect(limitTo(items, null)).toEqual([]); + expect(limitTo(items, undefined)).toEqual([]); + }); + + + it('should return an empty array when input is not Array type', function() { + expect(limitTo('bogus', 1)).toEqual('bogus'); + expect(limitTo(null, 1)).toEqual(null); + expect(limitTo(undefined, 1)).toEqual(undefined); + expect(limitTo(null, 1)).toEqual(null); + expect(limitTo(undefined, 1)).toEqual(undefined); + expect(limitTo({}, 1)).toEqual({}); + }); + + + it('should return a copy of input array if X is exceeds array length', function () { + expect(limitTo(items, 19)).toEqual(items); + expect(limitTo(items, '9')).toEqual(items); + expect(limitTo(items, -9)).toEqual(items); + expect(limitTo(items, '-9')).toEqual(items); + + expect(limitTo(items, 9)).not.toBe(items); + }); +}); diff --git a/test/service/filter/orderBySpec.js b/test/service/filter/orderBySpec.js new file mode 100644 index 000000000000..5c1178910255 --- /dev/null +++ b/test/service/filter/orderBySpec.js @@ -0,0 +1,34 @@ +'use strict'; + +describe('Filter: orderBy', function() { + var orderBy; + beforeEach(inject(function($filter) { + orderBy = $filter('orderBy'); + })); + + it('should return same array if predicate is falsy', function() { + var array = [1, 2, 3]; + expect(orderBy(array)).toBe(array); + }); + + it('shouldSortArrayInReverse', function() { + expect(orderBy([{a:15}, {a:2}], 'a', true)).toEqualData([{a:15}, {a:2}]); + expect(orderBy([{a:15}, {a:2}], 'a', "T")).toEqualData([{a:15}, {a:2}]); + expect(orderBy([{a:15}, {a:2}], 'a', "reverse")).toEqualData([{a:15}, {a:2}]); + }); + + it('should sort array by predicate', function() { + expect(orderBy([{a:15, b:1}, {a:2, b:1}], ['a', 'b'])).toEqualData([{a:2, b:1}, {a:15, b:1}]); + expect(orderBy([{a:15, b:1}, {a:2, b:1}], ['b', 'a'])).toEqualData([{a:2, b:1}, {a:15, b:1}]); + expect(orderBy([{a:15, b:1}, {a:2, b:1}], ['+b', '-a'])).toEqualData([{a:15, b:1}, {a:2, b:1}]); + }); + + it('should use function', function() { + expect( + orderBy( + [{a:15, b:1},{a:2, b:1}], + function(value) { return value.a; })). + toEqual([{a:2, b:1},{a:15, b:1}]); + }); + +}); diff --git a/test/service/formFactorySpec.js b/test/service/formFactorySpec.js index 23b8ae0a6d2d..fbe601c6ea03 100644 --- a/test/service/formFactorySpec.js +++ b/test/service/formFactorySpec.js @@ -2,19 +2,10 @@ describe('$formFactory', function() { - var rootScope; - var formFactory; - - beforeEach(function() { - rootScope = angular.scope(); - formFactory = rootScope.$service('$formFactory'); - }); - - - it('should have global form', function() { - expect(formFactory.rootForm).toBeTruthy(); - expect(formFactory.rootForm.$createWidget).toBeTruthy(); - }); + it('should have global form', inject(function($rootScope, $formFactory) { + expect($formFactory.rootForm).toBeTruthy(); + expect($formFactory.rootForm.$createWidget).toBeTruthy(); + })); describe('new form', function() { @@ -41,11 +32,11 @@ describe('$formFactory', function() { } }; - beforeEach(function() { + beforeEach(inject(function($rootScope, $formFactory) { log = ''; - scope = rootScope.$new(); - form = formFactory(scope); - }); + scope = $rootScope.$new(); + form = $formFactory(scope); + })); describe('$createWidget', function() { var widget; @@ -61,14 +52,14 @@ describe('$formFactory', function() { describe('data flow', function() { - it('should have status properties', function() { + it('should have status properties', inject(function($rootScope, $formFactory) { expect(widget.$error).toEqual({}); expect(widget.$valid).toBe(true); expect(widget.$invalid).toBe(false); - }); + })); - it('should update view when model changes', function() { + it('should update view when model changes', inject(function($rootScope, $formFactory) { scope.text = 'abc'; scope.$digest(); expect(log).toEqual('$validate();$render();'); @@ -78,17 +69,17 @@ describe('$formFactory', function() { scope.$digest(); expect(widget.$modelValue).toEqual('xyz'); - }); + })); - it('should have controller prototype methods', function() { - expect(widget.getFormFactory()).toEqual(formFactory); - }); + it('should have controller prototype methods', inject(function($rootScope, $formFactory) { + expect(widget.getFormFactory()).toEqual($formFactory); + })); }); describe('validation', function() { - it('should update state on error', function() { + it('should update state on error', inject(function($rootScope, $formFactory) { widget.$emit('$invalid', 'E'); expect(widget.$valid).toEqual(false); expect(widget.$invalid).toEqual(true); @@ -96,21 +87,21 @@ describe('$formFactory', function() { widget.$emit('$valid', 'E'); expect(widget.$valid).toEqual(true); expect(widget.$invalid).toEqual(false); - }); + })); - it('should have called the model setter before the validation', function() { + it('should have called the model setter before the validation', inject(function($rootScope, $formFactory) { var modelValue; widget.$on('$validate', function() { modelValue = scope.text; }); widget.$emit('$viewChange', 'abc'); expect(modelValue).toEqual('abc'); - }); + })); describe('form', function() { - it('should invalidate form when widget is invalid', function() { + it('should invalidate form when widget is invalid', inject(function($rootScope, $formFactory) { expect(form.$error).toEqual({}); expect(form.$valid).toEqual(true); expect(form.$invalid).toEqual(false); @@ -143,18 +134,18 @@ describe('$formFactory', function() { expect(form.$error).toEqual({}); expect(form.$valid).toEqual(true); expect(form.$invalid).toEqual(false); - }); + })); }); }); describe('id assignment', function() { - it('should default to name expression', function() { + it('should default to name expression', inject(function($rootScope, $formFactory) { expect(form.text).toEqual(widget); - }); + })); - it('should use ng:id', function() { + it('should use ng:id', inject(function($rootScope, $formFactory) { widget = form.$createWidget({ scope:scope, model:'text', @@ -162,10 +153,10 @@ describe('$formFactory', function() { controller:WidgetCtrl }); expect(form['my.id']).toEqual(widget); - }); + })); - it('should not override existing names', function() { + it('should not override existing names', inject(function($rootScope, $formFactory) { var widget2 = form.$createWidget({ scope:scope, model:'text', @@ -174,11 +165,11 @@ describe('$formFactory', function() { }); expect(form.text).toEqual(widget); expect(widget2).not.toEqual(widget); - }); + })); }); describe('dealocation', function() { - it('should dealocate', function() { + it('should dealocate', inject(function($rootScope, $formFactory) { var widget2 = form.$createWidget({ scope:scope, model:'text', @@ -199,10 +190,10 @@ describe('$formFactory', function() { widget2.$destroy(); expect(form.myId).toBeUndefined(); - }); + })); - it('should remove invalid fields from errors, when child widget removed', function() { + it('should remove invalid fields from errors, when child widget removed', inject(function($rootScope, $formFactory) { widget.$emit('$invalid', 'MyError'); expect(form.$error.MyError).toEqual([widget]); @@ -212,7 +203,7 @@ describe('$formFactory', function() { expect(form.$error.MyError).toBeUndefined(); expect(form.$invalid).toEqual(false); - }); + })); }); }); }); diff --git a/test/service/localeSpec.js b/test/service/localeSpec.js index 86bc7b0ed4ee..83c4eceefa87 100644 --- a/test/service/localeSpec.js +++ b/test/service/localeSpec.js @@ -2,7 +2,7 @@ describe('$locale', function() { - var $locale = angular.service('$locale')(); + var $locale = new $LocaleProvider().$get(); it('should have locale id set to en-us', function() { expect($locale.id).toBe('en-us'); diff --git a/test/service/locationSpec.js b/test/service/locationSpec.js index 9a7aa94306c9..7c075fc09983 100644 --- a/test/service/locationSpec.js +++ b/test/service/locationSpec.js @@ -95,6 +95,33 @@ describe('$location', function() { }); + it('url() should change only hash when no search and path specified', function() { + url.url('#some-hash'); + + expect(url.hash()).toBe('some-hash'); + expect(url.url()).toBe('/path/b?search=a&b=c&d#some-hash'); + expect(url.absUrl()).toBe('http://www.domain.com:9877/path/b?search=a&b=c&d#some-hash'); + }); + + + it('url() should change only search and hash when no path specified', function() { + url.url('https://github.com/?a=b'); + + expect(url.search()).toEqual({a: 'b'}); + expect(url.hash()).toBe(''); + expect(url.path()).toBe('/path/b'); + }); + + + it('url() should reset search and hash when only path specified', function() { + url.url('https://github.com/new/path'); + + expect(url.path()).toBe('/new/path'); + expect(url.search()).toEqual({}); + expect(url.hash()).toBe(''); + }); + + it('replace should set $$replace flag and return itself', function() { expect(url.$$replace).toBe(false); @@ -307,164 +334,184 @@ describe('$location', function() { }); - var $browser, $location, scope; - - function init(url, html5Mode, basePath, hashPrefix, supportHistory) { - scope = angular.scope(null, { - $locationConfig: {html5Mode: html5Mode, hashPrefix: hashPrefix}, - $sniffer: {history: supportHistory}}); - - $browser = scope.$service('$browser'); - $browser./service/https://github.com/url(url); - $browser.$$baseHref = basePath; - $location = scope.$service('$location'); + function initService(html5Mode, hashPrefix, supportHistory) { + return function($provide, $locationProvider){ + $locationProvider.html5Mode(html5Mode); + $locationProvider.hashPrefix(hashPrefix); + $provide.value('$sniffer', {history: supportHistory}); + }; } - - function dealocRootElement() { - dealoc(scope.$service('$document')); + function initBrowser(url, basePath) { + return function($browser){ + $browser./service/https://github.com/url(url); + $browser.$$baseHref = basePath; + }; } - describe('wiring', function() { - beforeEach(function() { - init('http://new.com/a/b#!', false, '/a/b', '!', true); - }); + beforeEach(inject(initService(false, '!', true), initBrowser('http://new.com/a/b#!', '/a/b'))); - it('should update $location when browser url changes', function() { + it('should update $location when browser url changes', inject(function($browser, $location) { spyOn($location, '$$parse').andCallThrough(); $browser.url('http://new.com/a/b#!/aaa'); $browser.poll(); expect($location.absUrl()).toBe('http://new.com/a/b#!/aaa'); expect($location.path()).toBe('/aaa'); expect($location.$$parse).toHaveBeenCalledOnce(); - }); + })); - it('should update browser when $location changes', function() { + it('should update browser when $location changes', inject(function($rootScope, $browser, $location) { var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough(); $location.path('/new/path'); expect($browserUrl).not.toHaveBeenCalled(); - scope.$apply(); + $rootScope.$apply(); expect($browserUrl).toHaveBeenCalledOnce(); expect($browser.url()).toBe('http://new.com/a/b#!/new/path'); - }); + })); - it('should update browser only once per $apply cycle', function() { + it('should update browser only once per $apply cycle', inject(function($rootScope, $browser, $location) { var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough(); $location.path('/new/path'); - scope.$watch(function() { + $rootScope.$watch(function() { $location.search('a=b'); }); - scope.$apply(); + $rootScope.$apply(); expect($browserUrl).toHaveBeenCalledOnce(); expect($browser.url()).toBe('http://new.com/a/b#!/new/path?a=b'); - }); + })); - it('should replace browser url when url was replaced at least once', function() { + it('should replace browser url when url was replaced at least once', + inject(function($rootScope, $location, $browser) { var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough(); $location.path('/n/url').replace(); - scope.$apply(); + $rootScope.$apply(); expect($browserUrl).toHaveBeenCalledOnce(); expect($browserUrl.mostRecentCall.args).toEqual(['http://new.com/a/b#!/n/url', true]); - }); + })); - it('should update the browser if changed from within a watcher', function() { - scope.$watch(function() { return true; }, function() { + it('should update the browser if changed from within a watcher', inject(function($rootScope, $location, $browser) { + $rootScope.$watch(function() { return true; }, function() { $location.path('/changed'); }); - scope.$digest(); + $rootScope.$digest(); expect($browser.url()).toBe('http://new.com/a/b#!/changed'); - }); + })); }); // html5 history is disabled describe('disabled history', function() { - it('should use hashbang url with hash prefix', function() { - init('http://domain.com/base/index.html#!/a/b', false, '/base/index.html', '!'); - expect($browser.url()).toBe('http://domain.com/base/index.html#!/a/b'); - $location.path('/new'); - $location.search({a: true}); - scope.$apply(); - expect($browser.url()).toBe('http://domain.com/base/index.html#!/new?a'); - }); - - - it('should use hashbang url without hash prefix', function() { - init('http://domain.com/base/index.html#/a/b', false, '/base/index.html', ''); - expect($browser.url()).toBe('http://domain.com/base/index.html#/a/b'); - $location.path('/new'); - $location.search({a: true}); - scope.$apply(); - expect($browser.url()).toBe('http://domain.com/base/index.html#/new?a'); - }); + it('should use hashbang url with hash prefix', inject( + initService(false, '!'), + initBrowser('http://domain.com/base/index.html#!/a/b', '/base/index.html'), + function($rootScope, $location, $browser) { + expect($browser.url()).toBe('http://domain.com/base/index.html#!/a/b'); + $location.path('/new'); + $location.search({a: true}); + $rootScope.$apply(); + expect($browser.url()).toBe('http://domain.com/base/index.html#!/new?a'); + }) + ); + + + it('should use hashbang url without hash prefix', inject( + initService(false, ''), + initBrowser('http://domain.com/base/index.html#/a/b', '/base/index.html'), + function($rootScope, $location, $browser) { + expect($browser.url()).toBe('http://domain.com/base/index.html#/a/b'); + $location.path('/new'); + $location.search({a: true}); + $rootScope.$apply(); + expect($browser.url()).toBe('http://domain.com/base/index.html#/new?a'); + }) + ); }); // html5 history enabled, but not supported by browser describe('history on old browser', function() { - afterEach(dealocRootElement); - - it('should use hashbang url with hash prefix', function() { - init('http://domain.com/base/index.html#!!/a/b', true, '/base/index.html', '!!', false); - expect($browser.url()).toBe('http://domain.com/base/index.html#!!/a/b'); - $location.path('/new'); - $location.search({a: true}); - scope.$apply(); - expect($browser.url()).toBe('http://domain.com/base/index.html#!!/new?a'); - }); - - - it('should redirect to hashbang url when new url given', function() { - init('http://domain.com/base/new-path/index.html', true, '/base/index.html', '!'); - expect($browser.url()).toBe('http://domain.com/base/index.html#!/new-path/index.html'); - }); + afterEach(inject(function($document){ + dealoc($document); + })); + + it('should use hashbang url with hash prefix', inject( + initService(true, '!!', false), + initBrowser('http://domain.com/base/index.html#!!/a/b', '/base/index.html'), + function($rootScope, $location, $browser) { + expect($browser.url()).toBe('http://domain.com/base/index.html#!!/a/b'); + $location.path('/new'); + $location.search({a: true}); + $rootScope.$apply(); + expect($browser.url()).toBe('http://domain.com/base/index.html#!!/new?a'); + }) + ); + + + it('should redirect to hashbang url when new url given', inject( + initService(true, '!'), + initBrowser('http://domain.com/base/new-path/index.html', '/base/index.html'), + function($browser, $location) { + expect($browser.url()).toBe('http://domain.com/base/index.html#!/new-path/index.html'); + }) + ); }); // html5 history enabled and supported by browser describe('history on new browser', function() { - afterEach(dealocRootElement); - - it('should use new url', function() { - init('http://domain.com/base/old/index.html#a', true, '/base/index.html', '', true); - expect($browser.url()).toBe('http://domain.com/base/old/index.html#a'); - $location.path('/new'); - $location.search({a: true}); - scope.$apply(); - expect($browser.url()).toBe('http://domain.com/base/new?a#a'); - }); - - - it('should rewrite when hashbang url given', function() { - init('http://domain.com/base/index.html#!/a/b', true, '/base/index.html', '!', true); - expect($browser.url()).toBe('http://domain.com/base/a/b'); - $location.path('/new'); - $location.hash('abc'); - scope.$apply(); - expect($browser.url()).toBe('http://domain.com/base/new#abc'); - expect($location.path()).toBe('/new'); - }); - - - it('should rewrite when hashbang url given (without hash prefix)', function() { - init('http://domain.com/base/index.html#/a/b', true, '/base/index.html', '', true); - expect($browser.url()).toBe('http://domain.com/base/a/b'); - expect($location.path()).toBe('/a/b'); - }); + afterEach(inject(function($document){ + dealoc($document); + })); + + it('should use new url', inject( + initService(true, '', true), + initBrowser('http://domain.com/base/old/index.html#a', '/base/index.html'), + function($rootScope, $location, $browser) { + expect($browser.url()).toBe('http://domain.com/base/old/index.html#a'); + $location.path('/new'); + $location.search({a: true}); + $rootScope.$apply(); + expect($browser.url()).toBe('http://domain.com/base/new?a#a'); + }) + ); + + + it('should rewrite when hashbang url given', inject( + initService(true, '!', true), + initBrowser('http://domain.com/base/index.html#!/a/b', '/base/index.html'), + function($rootScope, $location, $browser) { + expect($browser.url()).toBe('http://domain.com/base/a/b'); + $location.path('/new'); + $location.hash('abc'); + $rootScope.$apply(); + expect($browser.url()).toBe('http://domain.com/base/new#abc'); + expect($location.path()).toBe('/new'); + }) + ); + + + it('should rewrite when hashbang url given (without hash prefix)', inject( + initService(true, '', true), + initBrowser('http://domain.com/base/index.html#/a/b', '/base/index.html'), + function($rootScope, $location, $browser) { + expect($browser.url()).toBe('http://domain.com/base/a/b'); + expect($location.path()).toBe('/a/b'); + }) + ); }); @@ -554,43 +601,49 @@ describe('$location', function() { describe('link rewriting', function() { - var root, link, extLink, $browser, originalBrowser, lastEventPreventDefault; + var root, link, originalBrowser, lastEventPreventDefault; - function init(linkHref, html5Mode, supportHist, attrs, content) { - var jqRoot = jqLite('
                          '); - attrs = attrs ? ' ' + attrs + ' ' : ''; - content = content || 'link'; - link = jqLite('' + content + '')[0]; - root = jqRoot.append(link)[0]; + function configureService(linkHref, html5Mode, supportHist, attrs, content) { + return function($provide, $locationProvider){ + var jqRoot = jqLite('
                          '); + attrs = attrs ? ' ' + attrs + ' ' : ''; + link = jqLite('' + content + '')[0]; + root = jqRoot.append(link)[0]; - jqLite(document.body).append(jqRoot); + jqLite(document.body).append(jqRoot); - var scope = angular.scope(null, { - $document: jqRoot, - $sniffer: {history: supportHist}, - $locationConfig: {html5Mode: html5Mode, hashPrefix: '!'} - }); + $provide.value('$document', jqRoot); + $provide.value('$sniffer', {history: supportHist}); + $locationProvider.html5Mode(html5Mode); + $locationProvider.hashPrefix('!'); + }; + } - $browser = scope.$service('$browser'); - $browser.url('http://host.com/base'); - $browser.$$baseHref = '/base/index.html'; - var $location = scope.$service('$location'); - originalBrowser = $browser.url(); - - // we have to prevent the default operation, as we need to test absolute links (http://...) - // and navigating to these links would kill jstd - jqRoot.bind('click', function(e) { - lastEventPreventDefault = e.isDefaultPrevented(); - e.preventDefault(); - }); + function initBrowser() { + return function($browser){ + $browser.url('http://host.com/base'); + $browser.$$baseHref = '/base/index.html'; + }; } - function expectRewriteTo(url) { + function initLocation() { + return function($browser, $location, $document) { + originalBrowser = $browser.url(); + // we have to prevent the default operation, as we need to test absolute links (http://...) + // and navigating to these links would kill jstd + $document.bind('click', function(e) { + lastEventPreventDefault = e.isDefaultPrevented(); + e.preventDefault(); + }); + }; + } + + function expectRewriteTo($browser, url) { expect(lastEventPreventDefault).toBe(true); expect($browser.url()).toBe(url); } - function expectNoRewrite() { + function expectNoRewrite($browser) { expect(lastEventPreventDefault).toBe(false); expect($browser.url()).toBe(originalBrowser); } @@ -601,100 +654,152 @@ describe('$location', function() { }); - it('should rewrite rel link to new url when history enabled on new browser', function() { - init('link?a#b', true, true); - browserTrigger(link, 'click'); - expectRewriteTo('http://host.com/base/link?a#b'); - }); - - - it('should rewrite abs link to new url when history enabled on new browser', function() { - init('/base/link?a#b', true, true); - browserTrigger(link, 'click'); - expectRewriteTo('http://host.com/base/link?a#b'); - }); - - - it('should rewrite rel link to hashbang url when history enabled on old browser', function() { - init('link?a#b', true, false); - browserTrigger(link, 'click'); - expectRewriteTo('http://host.com/base/index.html#!/link?a#b'); - }); - - - it('should rewrite abs link to hashbang url when history enabled on old browser', function() { - init('/base/link?a#b', true, false); - browserTrigger(link, 'click'); - expectRewriteTo('http://host.com/base/index.html#!/link?a#b'); - }); - - - it('should not rewrite when history disabled', function() { - init('#new', false); - browserTrigger(link, 'click'); - expectNoRewrite(); - }); - - - it('should not rewrite ng:ext-link', function() { - init('#new', true, true, 'ng:ext-link'); - browserTrigger(link, 'click'); - expectNoRewrite(); - }); - - - it('should not rewrite full url links do different domain', function() { - init('http://www.dot.abc/a?b=c', true); - browserTrigger(link, 'click'); - expectNoRewrite(); - }); - - - it('should not rewrite links with target="_blank"', function() { - init('/a?b=c', true, true, 'target="_blank"'); - browserTrigger(link, 'click'); - expectNoRewrite(); - }); - - - it('should not rewrite links with target specified', function() { - init('/a?b=c', true, true, 'target="some-frame"'); - browserTrigger(link, 'click'); - expectNoRewrite(); - }); - - - it('should rewrite full url links to same domain and base path', function() { - init('http://host.com/base/new', true); - browserTrigger(link, 'click'); - expectRewriteTo('http://host.com/base/index.html#!/new'); - }); - - - it('should rewrite when clicked span inside link', function() { - init('some/link', true, true, '', 'link'); - var span = jqLite(link).find('span'); - - browserTrigger(span, 'click'); - expectRewriteTo('http://host.com/base/some/link'); - }); + it('should rewrite rel link to new url when history enabled on new browser', inject( + configureService('link?a#b', true, true), + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectRewriteTo($browser, 'http://host.com/base/link?a#b'); + }) + ); + + + it('should rewrite abs link to new url when history enabled on new browser', inject( + configureService('/base/link?a#b', true, true), + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectRewriteTo($browser, 'http://host.com/base/link?a#b'); + }) + ); + + + it('should rewrite rel link to hashbang url when history enabled on old browser', inject( + configureService('link?a#b', true, false), + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectRewriteTo($browser, 'http://host.com/base/index.html#!/link?a#b'); + }) + ); + + + it('should rewrite abs link to hashbang url when history enabled on old browser', inject( + configureService('/base/link?a#b', true, false), + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectRewriteTo($browser, 'http://host.com/base/index.html#!/link?a#b'); + }) + ); + + + it('should not rewrite when history disabled', inject( + configureService('#new', false), + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectNoRewrite($browser); + }) + ); + + + it('should not rewrite ng:ext-link', inject( + configureService('#new', true, true, 'ng:ext-link'), + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectNoRewrite($browser); + }) + ); + + + it('should not rewrite full url links do different domain', inject( + configureService('http://www.dot.abc/a?b=c', true), + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectNoRewrite($browser); + }) + ); + + + it('should not rewrite links with target="_blank"', inject( + configureService('/a?b=c', true, true, 'target="_blank"'), + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectNoRewrite($browser); + }) + ); + + + it('should not rewrite links with target specified', inject( + configureService('/a?b=c', true, true, 'target="some-frame"'), + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectNoRewrite($browser); + }) + ); + + + it('should rewrite full url links to same domain and base path', inject( + configureService('http://host.com/base/new', true), + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectRewriteTo($browser, 'http://host.com/base/index.html#!/new'); + }) + ); + + + it('should rewrite when clicked span inside link', inject( + configureService('some/link', true, true, '', 'link'), + initBrowser(), + initLocation(), + function($browser) { + var span = jqLite(link).find('span'); + + browserTrigger(span, 'click'); + expectRewriteTo($browser, 'http://host.com/base/some/link'); + }) + ); // don't run next tests on IE<9, as browserTrigger does not simulate pressed keys if (!(msie < 9)) { - it('should not rewrite when clicked with ctrl pressed', function() { - init('/a?b=c', true, true); - browserTrigger(link, 'click', ['ctrl']); - expectNoRewrite(); - }); - - - it('should not rewrite when clicked with meta pressed', function() { - init('/a?b=c', true, true); - browserTrigger(link, 'click', ['meta']); - expectNoRewrite(); - }); + it('should not rewrite when clicked with ctrl pressed', inject( + configureService('/a?b=c', true, true), + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click', ['ctrl']); + expectNoRewrite($browser); + }) + ); + + + it('should not rewrite when clicked with meta pressed', inject( + configureService('/a?b=c', true, true), + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click', ['meta']); + expectNoRewrite($browser); + }) + ); } }); }); diff --git a/test/service/logSpec.js b/test/service/logSpec.js index c4efb8c57200..a26e190f9308 100644 --- a/test/service/logSpec.js +++ b/test/service/logSpec.js @@ -1,65 +1,61 @@ 'use strict'; describe('$log', function() { - var scope; - - beforeEach(function() { - scope = angular.scope(); - }); - - - afterEach(function() { - dealoc(scope); - }); - - - it('should use console if present', function() { - var logger = ""; - function log() { logger+= 'log;'; } - function warn() { logger+= 'warn;'; } - function info() { logger+= 'info;'; } - function error() { logger+= 'error;'; } - var scope = createScope({$log: $logFactory}, - {$exceptionHandler: rethrow, - $window: {console: {log: log, - warn: warn, - info: info, - error: error}}}), - $log = scope.$service('$log'); - - $log.log(); - $log.warn(); - $log.info(); - $log.error(); - expect(logger).toEqual('log;warn;info;error;'); - }); - - - it('should use console.log() if other not present', function() { - var logger = ""; - function log() { logger+= 'log;'; } - var scope = createScope({$log: $logFactory}, - {$window: {console:{log:log}}, - $exceptionHandler: rethrow}); - var $log = scope.$service('$log'); - $log.log(); - $log.warn(); - $log.info(); - $log.error(); - expect(logger).toEqual('log;log;log;log;'); - }); - - - it('should use noop if no console', function() { - var scope = createScope({$log: $logFactory}, - {$window: {}, - $exceptionHandler: rethrow}), - $log = scope.$service('$log'); - $log.log(); - $log.warn(); - $log.info(); - $log.error(); - }); + var $window; + var logger; + + function log() { logger+= 'log;'; } + function warn() { logger+= 'warn;'; } + function info() { logger+= 'info;'; } + function error() { logger+= 'error;'; } + + beforeEach(inject(function($provide){ + $window = {}; + logger = ''; + $provide.service('$log', $LogProvider); + $provide.value('$exceptionHandler', angular.module.ngMock.rethrow); + $provide.value('$window', $window); + })); + + it('should use console if present', inject( + function(){ + $window.console = {log: log, + warn: warn, + info: info, + error: error}; + }, + function($log) { + $log.log(); + $log.warn(); + $log.info(); + $log.error(); + expect(logger).toEqual('log;warn;info;error;'); + } + )); + + + it('should use console.log() if other not present', inject( + function(){ + $window.console = {log: log}; + }, + function($log) { + $log.log(); + $log.warn(); + $log.info(); + $log.error(); + expect(logger).toEqual('log;log;log;log;'); + } + )); + + + it('should use noop if no console', inject( + function($log) { + $log.log(); + $log.warn(); + $log.info(); + $log.error(); + } + )); describe('$log.error', function() { @@ -72,7 +68,7 @@ describe('$log', function() { e.line = undefined; e.stack = undefined; - $log = $logFactory({console:{error:function() { + $log = new $LogProvider().$get[1]({console:{error:function() { errorArgs = arguments; }}}); }); diff --git a/test/ParserSpec.js b/test/service/parseSpec.js similarity index 91% rename from test/ParserSpec.js rename to test/service/parseSpec.js index 975cacc43a7f..2742f3810a22 100644 --- a/test/ParserSpec.js +++ b/test/service/parseSpec.js @@ -115,22 +115,22 @@ describe('parser', function() { expect(tokens[0].text).toEqual(0.5); }); - it('should tokenize negative number', function() { - var value = createScope().$eval("-0.5"); + it('should tokenize negative number', inject(function($rootScope) { + var value = $rootScope.$eval("-0.5"); expect(value).toEqual(-0.5); - value = createScope().$eval("{a:-0.5}"); + value = $rootScope.$eval("{a:-0.5}"); expect(value).toEqual({a:-0.5}); - }); + })); - it('should tokenize number with exponent', function() { + it('should tokenize number with exponent', inject(function($rootScope) { var tokens = lex("0.5E-10"); expect(tokens[0].text).toEqual(0.5E-10); - expect(createScope().$eval("0.5E-10")).toEqual(0.5E-10); + expect($rootScope.$eval("0.5E-10")).toEqual(0.5E-10); tokens = lex("0.5E+10"); expect(tokens[0].text).toEqual(0.5E+10); - }); + })); it('should throws exception for invalid exponent', function() { expect(function() { @@ -155,9 +155,9 @@ describe('parser', function() { }); var scope; - beforeEach(function () { - scope = createScope(); - }); + beforeEach(inject(function ($rootScope) { + scope = $rootScope; + })); it('should parse expressions', function() { expect(scope.$eval("-1")).toEqual(-1); @@ -191,24 +191,19 @@ describe('parser', function() { expect(scope.$eval("'a' + 'b c'")).toEqual("ab c"); }); - it('should parse filters', function() { - angular.filter.substring = function(input, start, end) { + it('should parse filters', inject(function($filterProvider) { + $filterProvider.register('substring', valueFn(function(input, start, end) { return input.substring(start, end); - }; - - angular.filter.upper = {_case: function(input) { - return input.toUpperCase(); - }}; + })); expect(function() { - scope.$eval("1|nonExistant"); - }).toThrow(new Error("Syntax Error: Token 'nonExistant' should be a function at column 3 of the expression [1|nonExistant] starting at [nonExistant].")); + scope.$eval("1|nonexistent"); + }).toThrow(new Error("Unknown provider for 'nonexistent$Filter'.")); scope.offset = 3; - expect(scope.$eval("'abcd'|upper._case")).toEqual("ABCD"); expect(scope.$eval("'abcd'|substring:1:offset")).toEqual("bc"); - expect(scope.$eval("'abcd'|substring:1:3|upper._case")).toEqual("BC"); - }); + expect(scope.$eval("'abcd'|substring:1:3|uppercase")).toEqual("BC"); + })); it('should access scope', function() { scope.a = 123; @@ -226,7 +221,6 @@ describe('parser', function() { expect(scope.$eval("a=12")).toEqual(12); expect(scope.a).toEqual(12); - scope = createScope(); expect(scope.$eval("x.y.z=123;")).toEqual(123); expect(scope.x.y.z).toEqual(123); @@ -392,7 +386,6 @@ describe('parser', function() { }); it('should allow assignment after array dereference', function() { - scope = angular.scope(); scope.obj = [{}]; scope.$eval('obj[0].name=1'); expect(scope.obj.name).toBeUndefined(); @@ -400,7 +393,6 @@ describe('parser', function() { }); it('should short-circuit AND operator', function() { - var scope = angular.scope(); scope.run = function() { throw "IT SHOULD NOT HAVE RUN"; }; @@ -408,7 +400,6 @@ describe('parser', function() { }); it('should short-circuit OR operator', function() { - var scope = angular.scope(); scope.run = function() { throw "IT SHOULD NOT HAVE RUN"; }; @@ -417,12 +408,12 @@ describe('parser', function() { describe('assignable', function() { - it('should expose assignment function', function() { - var fn = parser('a').assignable(); + it('should expose assignment function', inject(function($parse) { + var fn = $parse('a'); expect(fn.assign).toBeTruthy(); var scope = {}; fn.assign(scope, 123); expect(scope).toEqual({a:123}); - }); + })); }); }); diff --git a/test/service/routeParamsSpec.js b/test/service/routeParamsSpec.js index 972e4314cce5..d4088767ae4b 100644 --- a/test/service/routeParamsSpec.js +++ b/test/service/routeParamsSpec.js @@ -1,41 +1,16 @@ 'use strict'; describe('$routeParams', function() { - it('should publish the params into a service', function() { - var scope = angular.scope(), - $location = scope.$service('$location'), - $route = scope.$service('$route'), - $routeParams = scope.$service('$routeParams'); - + it('should publish the params into a service', inject(function($rootScope, $route, $location, $routeParams) { $route.when('/foo'); $route.when('/bar/:barId'); $location.path('/foo').search('a=b'); - scope.$digest(); + $rootScope.$digest(); expect($routeParams).toEqual({a:'b'}); $location.path('/bar/123').search('x=abc'); - scope.$digest(); + $rootScope.$digest(); expect($routeParams).toEqual({barId:'123', x:'abc'}); - }); - - - it('should preserve object identity during route reloads', function() { - var scope = angular.scope(), - $location = scope.$service('$location'), - $route = scope.$service('$route'), - $routeParams = scope.$service('$routeParams'), - firstRouteParams = $routeParams; - - $route.when('/foo'); - $route.when('/bar/:barId'); - - $location.path('/foo').search('a=b'); - scope.$digest(); - expect(scope.$service('$routeParams')).toBe(firstRouteParams); - - $location.path('/bar/123').search('x=abc'); - scope.$digest(); - expect(scope.$service('$routeParams')).toBe(firstRouteParams); - }); + })); }); diff --git a/test/service/routeSpec.js b/test/service/routeSpec.js index 5aba2a1f3ea0..fed3faef363d 100644 --- a/test/service/routeSpec.js +++ b/test/service/routeSpec.js @@ -1,16 +1,7 @@ 'use strict'; describe('$route', function() { - var scope, $route, $location; - - beforeEach(function() { - scope = angular.scope(); - $location = scope.$service('$location'); - $route = scope.$service('$route'); - }); - - - it('should route and fire change event', function() { + it('should route and fire change event', inject(function($route, $location, $rootScope) { var log = '', lastRoute, nextRoute; @@ -19,15 +10,16 @@ describe('$route', function() { log += ';'; } - $route.when('/Book/:book/Chapter/:chapter', {controller: BookChapter, template: 'Chapter.html'}); + $route.when('/Book/:book/Chapter/:chapter', + {controller: BookChapter, template: 'Chapter.html'}); $route.when('/Blank'); - scope.$on('$beforeRouteChange', function(event, next, current) { + $rootScope.$on('$beforeRouteChange', function(event, next, current) { log += 'before();'; expect(current).toBe($route.current); lastRoute = current; nextRoute = next; }); - scope.$on('$afterRouteChange', function(event, current, last) { + $rootScope.$on('$afterRouteChange', function(event, current, last) { log += 'after();'; expect(current).toBe($route.current); expect(lastRoute).toBe(last); @@ -35,97 +27,101 @@ describe('$route', function() { }); $location.path('/Book/Moby/Chapter/Intro').search('p=123'); - scope.$digest(); + $rootScope.$digest(); expect(log).toEqual('before();;after();'); expect($route.current.params).toEqual({book:'Moby', chapter:'Intro', p:'123'}); var lastId = $route.current.scope.$id; log = ''; $location.path('/Blank').search('ignore'); - scope.$digest(); + $rootScope.$digest(); expect(log).toEqual('before();after();'); expect($route.current.params).toEqual({ignore:true}); expect($route.current.scope.$id).not.toEqual(lastId); log = ''; $location.path('/NONE'); - scope.$digest(); + $rootScope.$digest(); expect(log).toEqual('before();after();'); expect($route.current).toEqual(null); $route.when('/NONE', {template:'instant update'}); - scope.$digest(); + $rootScope.$digest(); expect($route.current.template).toEqual('instant update'); - }); + })); - it('should match a route that contains special chars in the path', function() { + it('should match a route that contains special chars in the path', + inject(function($route, $location, $rootScope) { $route.when('/$test.23/foo(bar)/:baz', {template: 'test.html'}); $location.path('/test'); - scope.$digest(); + $rootScope.$digest(); expect($route.current).toBeUndefined(); $location.path('/$testX23/foo(bar)/222'); - scope.$digest(); + $rootScope.$digest(); expect($route.current).toBeUndefined(); $location.path('/$test.23/foo(bar)/222'); - scope.$digest(); + $rootScope.$digest(); expect($route.current).toBeDefined(); $location.path('/$test.23/foo\\(bar)/222'); - scope.$digest(); + $rootScope.$digest(); expect($route.current).toBeUndefined(); - }); + })); - it('should change route even when only search param changes', function() { + it('should change route even when only search param changes', + inject(function($route, $location, $rootScope) { var callback = jasmine.createSpy('onRouteChange'); $route.when('/test', {template: 'test.html'}); - scope.$on('$beforeRouteChange', callback); + $rootScope.$on('$beforeRouteChange', callback); $location.path('/test'); - scope.$digest(); + $rootScope.$digest(); callback.reset(); $location.search({any: true}); - scope.$digest(); + $rootScope.$digest(); expect(callback).toHaveBeenCalled(); - }); + })); - it('should allow routes to be defined with just templates without controllers', function() { + it('should allow routes to be defined with just templates without controllers', + inject(function($route, $location, $rootScope) { var onChangeSpy = jasmine.createSpy('onChange'); $route.when('/foo', {template: 'foo.html'}); - scope.$on('$beforeRouteChange', onChangeSpy); + $rootScope.$on('$beforeRouteChange', onChangeSpy); expect($route.current).toBeUndefined(); expect(onChangeSpy).not.toHaveBeenCalled(); $location.path('/foo'); - scope.$digest(); + $rootScope.$digest(); expect($route.current.template).toEqual('foo.html'); expect($route.current.controller).toBeUndefined(); expect(onChangeSpy).toHaveBeenCalled(); - }); + })); - it('should handle unknown routes with "otherwise" route definition', function() { + it('should handle unknown routes with "otherwise" route definition', + inject(function($route, $location, $rootScope) { var onChangeSpy = jasmine.createSpy('onChange'); function NotFoundCtrl() {this.notFoundProp = 'not found!';} $route.when('/foo', {template: 'foo.html'}); $route.otherwise({template: '404.html', controller: NotFoundCtrl}); - scope.$on('$beforeRouteChange', onChangeSpy); + $rootScope.$on('$beforeRouteChange', onChangeSpy); expect($route.current).toBeUndefined(); expect(onChangeSpy).not.toHaveBeenCalled(); $location.path('/unknownRoute'); - scope.$digest(); + $rootScope.$digest(); expect($route.current.template).toBe('404.html'); expect($route.current.controller).toBe(NotFoundCtrl); @@ -134,54 +130,55 @@ describe('$route', function() { onChangeSpy.reset(); $location.path('/foo'); - scope.$digest(); + $rootScope.$digest(); expect($route.current.template).toEqual('foo.html'); expect($route.current.controller).toBeUndefined(); expect($route.current.scope.notFoundProp).toBeUndefined(); expect(onChangeSpy).toHaveBeenCalled(); - }); + })); - it('should $destroy old routes', function() { + it('should $destroy old routes', inject(function($route, $location, $rootScope) { $route.when('/foo', {template: 'foo.html', controller: function() {this.name = 'FOO';}}); $route.when('/bar', {template: 'bar.html', controller: function() {this.name = 'BAR';}}); $route.when('/baz', {template: 'baz.html'}); - expect(scope.$childHead).toEqual(null); + expect($rootScope.$childHead).toEqual(null); $location.path('/foo'); - scope.$digest(); - expect(scope.$$childHead.$id).toBeTruthy(); - expect(scope.$$childHead.$id).toEqual(scope.$$childTail.$id); + $rootScope.$digest(); + expect($rootScope.$$childHead.$id).toBeTruthy(); + expect($rootScope.$$childHead.$id).toEqual($rootScope.$$childTail.$id); $location.path('/bar'); - scope.$digest(); - expect(scope.$$childHead.$id).toBeTruthy(); - expect(scope.$$childHead.$id).toEqual(scope.$$childTail.$id); + $rootScope.$digest(); + expect($rootScope.$$childHead.$id).toBeTruthy(); + expect($rootScope.$$childHead.$id).toEqual($rootScope.$$childTail.$id); $location.path('/baz'); - scope.$digest(); - expect(scope.$$childHead.$id).toBeTruthy(); - expect(scope.$$childHead.$id).toEqual(scope.$$childTail.$id); + $rootScope.$digest(); + expect($rootScope.$$childHead.$id).toBeTruthy(); + expect($rootScope.$$childHead.$id).toEqual($rootScope.$$childTail.$id); $location.path('/'); - scope.$digest(); - expect(scope.$$childHead).toEqual(null); - expect(scope.$$childTail).toEqual(null); - }); + $rootScope.$digest(); + expect($rootScope.$$childHead).toEqual(null); + expect($rootScope.$$childTail).toEqual(null); + })); - it('should infer arguments in injection', function() { + it('should infer arguments in injection', inject(function($route, $location, $rootScope) { $route.when('/test', {controller: function($route){ this.$route = $route; }}); $location.path('/test'); - scope.$digest(); + $rootScope.$digest(); expect($route.current.scope.$route).toBe($route); - }); + })); describe('redirection', function() { - it('should support redirection via redirectTo property by updating $location', function() { + it('should support redirection via redirectTo property by updating $location', + inject(function($route, $location, $rootScope) { var onChangeSpy = jasmine.createSpy('onChange'); $route.when('/', {redirectTo: '/foo'}); @@ -189,57 +186,60 @@ describe('$route', function() { $route.when('/bar', {template: 'bar.html'}); $route.when('/baz', {redirectTo: '/bar'}); $route.otherwise({template: '404.html'}); - scope.$on('$beforeRouteChange', onChangeSpy); + $rootScope.$on('$beforeRouteChange', onChangeSpy); expect($route.current).toBeUndefined(); expect(onChangeSpy).not.toHaveBeenCalled(); $location.path('/'); - scope.$digest(); + $rootScope.$digest(); expect($location.path()).toBe('/foo'); expect($route.current.template).toBe('foo.html'); expect(onChangeSpy.callCount).toBe(2); onChangeSpy.reset(); $location.path('/baz'); - scope.$digest(); + $rootScope.$digest(); expect($location.path()).toBe('/bar'); expect($route.current.template).toBe('bar.html'); expect(onChangeSpy.callCount).toBe(2); - }); + })); - it('should interpolate route vars in the redirected path from original path', function() { + it('should interpolate route vars in the redirected path from original path', + inject(function($route, $location, $rootScope) { $route.when('/foo/:id/foo/:subid/:extraId', {redirectTo: '/bar/:id/:subid/23'}); $route.when('/bar/:id/:subid/:subsubid', {template: 'bar.html'}); $location.path('/foo/id1/foo/subid3/gah'); - scope.$digest(); + $rootScope.$digest(); expect($location.path()).toEqual('/bar/id1/subid3/23'); expect($location.search()).toEqual({extraId: 'gah'}); expect($route.current.template).toEqual('bar.html'); - }); + })); - it('should interpolate route vars in the redirected path from original search', function() { + it('should interpolate route vars in the redirected path from original search', + inject(function($route, $location, $rootScope) { $route.when('/bar/:id/:subid/:subsubid', {template: 'bar.html'}); $route.when('/foo/:id/:extra', {redirectTo: '/bar/:id/:subid/99'}); $location.path('/foo/id3/eId').search('subid=sid1&appended=true'); - scope.$digest(); + $rootScope.$digest(); expect($location.path()).toEqual('/bar/id3/sid1/99'); expect($location.search()).toEqual({appended: 'true', extra: 'eId'}); expect($route.current.template).toEqual('bar.html'); - }); + })); - it('should allow custom redirectTo function to be used', function() { + it('should allow custom redirectTo function to be used', + inject(function($route, $location, $rootScope) { $route.when('/bar/:id/:subid/:subsubid', {template: 'bar.html'}); $route.when('/foo/:id', {redirectTo: customRedirectFn}); $location.path('/foo/id3').search('subid=sid1&appended=true'); - scope.$digest(); + $rootScope.$digest(); expect($location.path()).toEqual('/custom'); @@ -249,60 +249,60 @@ describe('$route', function() { expect(search).toEqual($location.search()); return '/custom'; } - }); + })); - it('should replace the url when redirecting', function() { + it('should replace the url when redirecting', inject(function($route, $location, $rootScope) { $route.when('/bar/:id', {template: 'bar.html'}); $route.when('/foo/:id/:extra', {redirectTo: '/bar/:id'}); var replace; - scope.$watch(function() { + $rootScope.$watch(function() { if (isUndefined(replace)) replace = $location.$$replace; }); $location.path('/foo/id3/eId'); - scope.$digest(); + $rootScope.$digest(); expect($location.path()).toEqual('/bar/id3'); expect(replace).toBe(true); - }); + })); }); describe('reloadOnSearch', function() { - it('should reload a route when reloadOnSearch is enabled and .search() changes', function() { - var $routeParams = scope.$service('$routeParams'), - reloaded = jasmine.createSpy('route reload'); + it('should reload a route when reloadOnSearch is enabled and .search() changes', + inject(function($route, $location, $rootScope, $routeParams) { + var reloaded = jasmine.createSpy('route reload'); $route.when('/foo', {controller: FooCtrl}); - scope.$on('$beforeRouteChange', reloaded); + $rootScope.$on('$beforeRouteChange', reloaded); function FooCtrl() { reloaded(); } $location.path('/foo'); - scope.$digest(); + $rootScope.$digest(); expect(reloaded).toHaveBeenCalled(); expect($routeParams).toEqual({}); reloaded.reset(); // trigger reload $location.search({foo: 'bar'}); - scope.$digest(); + $rootScope.$digest(); expect(reloaded).toHaveBeenCalled(); expect($routeParams).toEqual({foo:'bar'}); - }); + })); it('should not reload a route when reloadOnSearch is disabled and only .search() changes', - function() { + inject(function($route, $location, $rootScope) { var reloaded = jasmine.createSpy('route reload'), routeUpdateEvent = jasmine.createSpy('route reload'); $route.when('/foo', {controller: FooCtrl, reloadOnSearch: false}); - scope.$on('$beforeRouteChange', reloaded); + $rootScope.$on('$beforeRouteChange', reloaded); function FooCtrl() { reloaded(); @@ -312,25 +312,26 @@ describe('$route', function() { expect(reloaded).not.toHaveBeenCalled(); $location.path('/foo'); - scope.$digest(); + $rootScope.$digest(); expect(reloaded).toHaveBeenCalled(); expect(routeUpdateEvent).not.toHaveBeenCalled(); reloaded.reset(); // don't trigger reload $location.search({foo: 'bar'}); - scope.$digest(); + $rootScope.$digest(); expect(reloaded).not.toHaveBeenCalled(); expect(routeUpdateEvent).toHaveBeenCalled(); - }); + })); - it('should reload reloadOnSearch route when url differs only in route path param', function() { + it('should reload reloadOnSearch route when url differs only in route path param', + inject(function($route, $location, $rootScope) { var reloaded = jasmine.createSpy('routeReload'), onRouteChange = jasmine.createSpy('onRouteChange'); $route.when('/foo/:fooId', {controller: FooCtrl, reloadOnSearch: false}); - scope.$on('$beforeRouteChange', onRouteChange); + $rootScope.$on('$beforeRouteChange', onRouteChange); function FooCtrl() { reloaded(); @@ -340,27 +341,28 @@ describe('$route', function() { expect(onRouteChange).not.toHaveBeenCalled(); $location.path('/foo/aaa'); - scope.$digest(); + $rootScope.$digest(); expect(reloaded).toHaveBeenCalled(); expect(onRouteChange).toHaveBeenCalled(); reloaded.reset(); onRouteChange.reset(); $location.path('/foo/bbb'); - scope.$digest(); + $rootScope.$digest(); expect(reloaded).toHaveBeenCalled(); expect(onRouteChange).toHaveBeenCalled(); reloaded.reset(); onRouteChange.reset(); $location.search({foo: 'bar'}); - scope.$digest(); + $rootScope.$digest(); expect(reloaded).not.toHaveBeenCalled(); expect(onRouteChange).not.toHaveBeenCalled(); - }); + })); - it('should update params when reloadOnSearch is disabled and .search() changes', function() { + it('should update params when reloadOnSearch is disabled and .search() changes', + inject(function($route, $location, $rootScope) { var routeParams = jasmine.createSpy('routeParams'); $route.when('/foo', {controller: FooCtrl}); @@ -377,53 +379,53 @@ describe('$route', function() { expect(routeParams).not.toHaveBeenCalled(); $location.path('/foo'); - scope.$digest(); + $rootScope.$digest(); expect(routeParams).toHaveBeenCalledWith({}); routeParams.reset(); // trigger reload $location.search({foo: 'bar'}); - scope.$digest(); + $rootScope.$digest(); expect(routeParams).toHaveBeenCalledWith({foo: 'bar'}); routeParams.reset(); $location.path('/bar/123').search({}); - scope.$digest(); + $rootScope.$digest(); expect(routeParams).toHaveBeenCalledWith({barId: '123'}); routeParams.reset(); // don't trigger reload $location.search({foo: 'bar'}); - scope.$digest(); + $rootScope.$digest(); expect(routeParams).toHaveBeenCalledWith({barId: '123', foo: 'bar'}); - }); + })); describe('reload', function() { - it('should reload even if reloadOnSearch is false', function() { - var $routeParams = scope.$service('$routeParams'), - count = 0; + it('should reload even if reloadOnSearch is false', + inject(function($route, $location, $rootScope, $routeParams) { + var count = 0; $route.when('/bar/:barId', {controller: FooCtrl, reloadOnSearch: false}); function FooCtrl() { count ++; } $location.path('/bar/123'); - scope.$digest(); + $rootScope.$digest(); expect($routeParams).toEqual({barId:'123'}); expect(count).toEqual(1); $location.path('/bar/123').search('a=b'); - scope.$digest(); + $rootScope.$digest(); expect($routeParams).toEqual({barId:'123', a:'b'}); expect(count).toEqual(1); $route.reload(); - scope.$digest(); + $rootScope.$digest(); expect($routeParams).toEqual({barId:'123', a:'b'}); expect(count).toEqual(2); - }); + })); }); }); }); diff --git a/test/ScopeSpec.js b/test/service/scopeSpec.js similarity index 50% rename from test/ScopeSpec.js rename to test/service/scopeSpec.js index d3f5891880f6..71a27b335a73 100644 --- a/test/ScopeSpec.js +++ b/test/service/scopeSpec.js @@ -1,76 +1,72 @@ 'use strict'; describe('Scope', function() { - var root = null, mockHandler = null; - beforeEach(function() { - root = createScope(angular.service, { - '$exceptionHandler': $exceptionHandlerMockFactory() - }); - mockHandler = root.$service('$exceptionHandler'); - }); + beforeEach(inject(function($exceptionHandlerProvider) { + $exceptionHandlerProvider.mode('log'); + })); describe('$root', function() { - it('should point to itself', function() { - expect(root.$root).toEqual(root); - expect(root.hasOwnProperty('$root')).toBeTruthy(); - }); + it('should point to itself', inject(function($rootScope) { + expect($rootScope.$root).toEqual($rootScope); + expect($rootScope.hasOwnProperty('$root')).toBeTruthy(); + })); - it('should not have $root on children, but should inherit', function() { - var child = root.$new(); - expect(child.$root).toEqual(root); + it('should not have $root on children, but should inherit', inject(function($rootScope) { + var child = $rootScope.$new(); + expect(child.$root).toEqual($rootScope); expect(child.hasOwnProperty('$root')).toBeFalsy(); - }); + })); }); describe('$parent', function() { - it('should point to itself in root', function() { - expect(root.$root).toEqual(root); - }); + it('should point to itself in root', inject(function($rootScope) { + expect($rootScope.$root).toEqual($rootScope); + })); - it('should point to parent', function() { - var child = root.$new(); - expect(root.$parent).toEqual(null); - expect(child.$parent).toEqual(root); + it('should point to parent', inject(function($rootScope) { + var child = $rootScope.$new(); + expect($rootScope.$parent).toEqual(null); + expect(child.$parent).toEqual($rootScope); expect(child.$new().$parent).toEqual(child); - }); + })); }); describe('$id', function() { - it('should have a unique id', function() { - expect(root.$id < root.$new().$id).toBeTruthy(); - }); + it('should have a unique id', inject(function($rootScope) { + expect($rootScope.$id < $rootScope.$new().$id).toBeTruthy(); + })); }); describe('this', function() { - it('should have a \'this\'', function() { - expect(root['this']).toEqual(root); - }); + it('should have a \'this\'', inject(function($rootScope) { + expect($rootScope['this']).toEqual($rootScope); + })); }); describe('$new()', function() { - it('should create a child scope', function() { - var child = root.$new(); - root.a = 123; + it('should create a child scope', inject(function($rootScope) { + var child = $rootScope.$new(); + $rootScope.a = 123; expect(child.a).toEqual(123); - }); + })); - it('should instantiate controller and bind functions', function() { + it('should instantiate controller and bind functions', inject(function($rootScope) { function Cntl($browser, name){ this.$browser = $browser; this.callCount = 0; this.name = name; } - Cntl.$inject = ['$browser']; + Cntl.$inject = ['$browser', 'name']; Cntl.prototype = { myFn: function() { @@ -79,10 +75,10 @@ describe('Scope', function() { } }; - var cntl = root.$new(Cntl, ['misko']); + var cntl = $rootScope.$new(Cntl, {name:'misko'}); - expect(root.$browser).toBeUndefined(); - expect(root.myFn).toBeUndefined(); + expect($rootScope.$browser).toBeUndefined(); + expect($rootScope.myFn).toBeUndefined(); expect(cntl.$browser).toBeDefined(); expect(cntl.name).toEqual('misko'); @@ -90,96 +86,89 @@ describe('Scope', function() { cntl.myFn(); cntl.$new().myFn(); expect(cntl.callCount).toEqual(2); - }); - }); - - - describe('$service', function() { - it('should have it on root', function() { - expect(root.hasOwnProperty('$service')).toBeTruthy(); - }); + })); }); describe('$watch/$digest', function() { - it('should watch and fire on simple property change', function() { + it('should watch and fire on simple property change', inject(function($rootScope) { var spy = jasmine.createSpy(); - root.$watch('name', spy); - root.$digest(); + $rootScope.$watch('name', spy); + $rootScope.$digest(); spy.reset(); expect(spy).not.wasCalled(); - root.$digest(); + $rootScope.$digest(); expect(spy).not.wasCalled(); - root.name = 'misko'; - root.$digest(); - expect(spy).wasCalledWith(root, 'misko', undefined); - }); + $rootScope.name = 'misko'; + $rootScope.$digest(); + expect(spy).wasCalledWith($rootScope, 'misko', undefined); + })); - it('should watch and fire on expression change', function() { + it('should watch and fire on expression change', inject(function($rootScope) { var spy = jasmine.createSpy(); - root.$watch('name.first', spy); - root.$digest(); + $rootScope.$watch('name.first', spy); + $rootScope.$digest(); spy.reset(); - root.name = {}; + $rootScope.name = {}; expect(spy).not.wasCalled(); - root.$digest(); + $rootScope.$digest(); expect(spy).not.wasCalled(); - root.name.first = 'misko'; - root.$digest(); + $rootScope.name.first = 'misko'; + $rootScope.$digest(); expect(spy).wasCalled(); - }); + })); - it('should delegate exceptions', function() { - root.$watch('a', function() {throw new Error('abc');}); - root.a = 1; - root.$digest(); - expect(mockHandler.errors[0].message).toEqual('abc'); - $logMock.error.logs.length = 0; - }); + it('should delegate exceptions', inject(function($rootScope, $exceptionHandler, $log) { + $rootScope.$watch('a', function() {throw new Error('abc');}); + $rootScope.a = 1; + $rootScope.$digest(); + expect($exceptionHandler.errors[0].message).toEqual('abc'); + $log.assertEmpty(); + })); - it('should fire watches in order of addition', function() { + it('should fire watches in order of addition', inject(function($rootScope) { // this is not an external guarantee, just our own sanity var log = ''; - root.$watch('a', function() { log += 'a'; }); - root.$watch('b', function() { log += 'b'; }); - root.$watch('c', function() { log += 'c'; }); - root.a = root.b = root.c = 1; - root.$digest(); + $rootScope.$watch('a', function() { log += 'a'; }); + $rootScope.$watch('b', function() { log += 'b'; }); + $rootScope.$watch('c', function() { log += 'c'; }); + $rootScope.a = $rootScope.b = $rootScope.c = 1; + $rootScope.$digest(); expect(log).toEqual('abc'); - }); + })); - it('should call child $watchers in addition order', function() { + it('should call child $watchers in addition order', inject(function($rootScope) { // this is not an external guarantee, just our own sanity var log = ''; - var childA = root.$new(); - var childB = root.$new(); - var childC = root.$new(); + var childA = $rootScope.$new(); + var childB = $rootScope.$new(); + var childC = $rootScope.$new(); childA.$watch('a', function() { log += 'a'; }); childB.$watch('b', function() { log += 'b'; }); childC.$watch('c', function() { log += 'c'; }); childA.a = childB.b = childC.c = 1; - root.$digest(); + $rootScope.$digest(); expect(log).toEqual('abc'); - }); + })); - it('should allow $digest on a child scope with and without a right sibling', function() { + it('should allow $digest on a child scope with and without a right sibling', inject(function($rootScope) { // tests a traversal edge case which we originally missed var log = '', - childA = root.$new(), - childB = root.$new(); + childA = $rootScope.$new(), + childB = $rootScope.$new(); - root.$watch(function() { log += 'r'; }); + $rootScope.$watch(function() { log += 'r'; }); childA.$watch(function() { log += 'a'; }); childB.$watch(function() { log += 'b'; }); // init - root.$digest(); + $rootScope.$digest(); expect(log).toBe('rabrab'); log = ''; @@ -189,114 +178,114 @@ describe('Scope', function() { log = ''; childB.$digest(); expect(log).toBe('b'); - }); + })); - it('should repeat watch cycle while model changes are identified', function() { + it('should repeat watch cycle while model changes are identified', inject(function($rootScope) { var log = ''; - root.$watch('c', function(self, v){self.d = v; log+='c'; }); - root.$watch('b', function(self, v){self.c = v; log+='b'; }); - root.$watch('a', function(self, v){self.b = v; log+='a'; }); - root.$digest(); + $rootScope.$watch('c', function(self, v){self.d = v; log+='c'; }); + $rootScope.$watch('b', function(self, v){self.c = v; log+='b'; }); + $rootScope.$watch('a', function(self, v){self.b = v; log+='a'; }); + $rootScope.$digest(); log = ''; - root.a = 1; - root.$digest(); - expect(root.b).toEqual(1); - expect(root.c).toEqual(1); - expect(root.d).toEqual(1); + $rootScope.a = 1; + $rootScope.$digest(); + expect($rootScope.b).toEqual(1); + expect($rootScope.c).toEqual(1); + expect($rootScope.d).toEqual(1); expect(log).toEqual('abc'); - }); + })); - it('should repeat watch cycle from the root elemnt', function() { + it('should repeat watch cycle from the root elemnt', inject(function($rootScope) { var log = ''; - var child = root.$new(); - root.$watch(function() { log += 'a'; }); + var child = $rootScope.$new(); + $rootScope.$watch(function() { log += 'a'; }); child.$watch(function() { log += 'b'; }); - root.$digest(); + $rootScope.$digest(); expect(log).toEqual('abab'); - }); + })); - it('should prevent infinite recursion and print watcher expression', function() { - root.$watch('a', function(self){self.b++;}); - root.$watch('b', function(self){self.a++;}); - root.a = root.b = 0; + it('should prevent infinite recursion and print watcher expression',inject(function($rootScope) { + $rootScope.$watch('a', function(self){self.b++;}); + $rootScope.$watch('b', function(self){self.a++;}); + $rootScope.a = $rootScope.b = 0; expect(function() { - root.$digest(); + $rootScope.$digest(); }).toThrow('100 $digest() iterations reached. Aborting!\n'+ 'Watchers fired in the last 5 iterations: ' + '[["a","b"],["a","b"],["a","b"],["a","b"],["a","b"]]'); - }); + })); it('should prevent infinite recurcion and print print watcher function name or body', - function() { - root.$watch(function watcherA() {return root.a;}, function(self){self.b++;}); - root.$watch(function() {return root.b;}, function(self){self.a++;}); - root.a = root.b = 0; + inject(function($rootScope) { + $rootScope.$watch(function watcherA() {return $rootScope.a;}, function(self){self.b++;}); + $rootScope.$watch(function() {return $rootScope.b;}, function(self){self.a++;}); + $rootScope.a = $rootScope.b = 0; try { - root.$digest(); + $rootScope.$digest(); throw Error('Should have thrown exception'); } catch(e) { expect(e.message.match(/"fn: (watcherA|function)/g).length).toBe(10); } - }); + })); - it('should not fire upon $watch registration on initial $digest', function() { + it('should not fire upon $watch registration on initial $digest', inject(function($rootScope) { var log = ''; - root.a = 1; - root.$watch('a', function() { log += 'a'; }); - root.$watch('b', function() { log += 'b'; }); - root.$digest(); + $rootScope.a = 1; + $rootScope.$watch('a', function() { log += 'a'; }); + $rootScope.$watch('b', function() { log += 'b'; }); + $rootScope.$digest(); log = ''; - root.$digest(); + $rootScope.$digest(); expect(log).toEqual(''); - }); + })); - it('should watch objects', function() { + it('should watch objects', inject(function($rootScope) { var log = ''; - root.a = []; - root.b = {}; - root.$watch('a', function(scope, value){ + $rootScope.a = []; + $rootScope.b = {}; + $rootScope.$watch('a', function(scope, value){ log +='.'; - expect(value).toBe(root.a); + expect(value).toBe($rootScope.a); }); - root.$watch('b', function(scope, value){ + $rootScope.$watch('b', function(scope, value){ log +='!'; - expect(value).toBe(root.b); + expect(value).toBe($rootScope.b); }); - root.$digest(); + $rootScope.$digest(); log = ''; - root.a.push({}); - root.b.name = ''; + $rootScope.a.push({}); + $rootScope.b.name = ''; - root.$digest(); + $rootScope.$digest(); expect(log).toEqual('.!'); - }); + })); - it('should prevent recursion', function() { + it('should prevent recursion', inject(function($rootScope) { var callCount = 0; - root.$watch('name', function() { + $rootScope.$watch('name', function() { expect(function() { - root.$digest(); + $rootScope.$digest(); }).toThrow('$digest already in progress'); callCount++; }); - root.name = 'a'; - root.$digest(); + $rootScope.name = 'a'; + $rootScope.$digest(); expect(callCount).toEqual(1); - }); + })); - it('should return a function that allows listeners to be unregistered', function() { - var root = angular.scope(), + it('should return a function that allows listeners to be unregistered', inject(function($rootScope) { + var root = angular.injector('ng').get('$rootScope'), listener = jasmine.createSpy('watch listener'), listenerRemove; @@ -315,166 +304,162 @@ describe('Scope', function() { listenerRemove(); root.$digest(); //trigger expect(listener).not.toHaveBeenCalled(); - }); + })); }); describe('$destroy', function() { var first = null, middle = null, last = null, log = null; - beforeEach(function() { + beforeEach(inject(function($rootScope) { log = ''; - first = root.$new(); - middle = root.$new(); - last = root.$new(); + first = $rootScope.$new(); + middle = $rootScope.$new(); + last = $rootScope.$new(); first.$watch(function() { log += '1';}); middle.$watch(function() { log += '2';}); last.$watch(function() { log += '3';}); - root.$digest(); + $rootScope.$digest(); log = ''; - }); + })); - it('should ignore remove on root', function() { - root.$destroy(); - root.$digest(); + it('should ignore remove on root', inject(function($rootScope) { + $rootScope.$destroy(); + $rootScope.$digest(); expect(log).toEqual('123'); - }); + })); - it('should remove first', function() { + it('should remove first', inject(function($rootScope) { first.$destroy(); - root.$digest(); + $rootScope.$digest(); expect(log).toEqual('23'); - }); + })); - it('should remove middle', function() { + it('should remove middle', inject(function($rootScope) { middle.$destroy(); - root.$digest(); + $rootScope.$digest(); expect(log).toEqual('13'); - }); + })); - it('should remove last', function() { + it('should remove last', inject(function($rootScope) { last.$destroy(); - root.$digest(); + $rootScope.$digest(); expect(log).toEqual('12'); - }); + })); - it('should fire a $destroy event', function() { + it('should fire a $destroy event', inject(function($rootScope) { var destructedScopes = []; middle.$on('$destroy', function(event) { destructedScopes.push(event.currentScope); }); middle.$destroy(); expect(destructedScopes).toEqual([middle]); - }); + })); }); describe('$eval', function() { - it('should eval an expression', function() { - expect(root.$eval('a=1')).toEqual(1); - expect(root.a).toEqual(1); + it('should eval an expression', inject(function($rootScope) { + expect($rootScope.$eval('a=1')).toEqual(1); + expect($rootScope.a).toEqual(1); - root.$eval(function(self){self.b=2;}); - expect(root.b).toEqual(2); - }); + $rootScope.$eval(function(self){self.b=2;}); + expect($rootScope.b).toEqual(2); + })); }); describe('$evalAsync', function() { - it('should run callback before $watch', function() { + it('should run callback before $watch', inject(function($rootScope) { var log = ''; - var child = root.$new(); - root.$evalAsync(function(scope){ log += 'parent.async;'; }); - root.$watch('value', function() { log += 'parent.$digest;'; }); + var child = $rootScope.$new(); + $rootScope.$evalAsync(function(scope){ log += 'parent.async;'; }); + $rootScope.$watch('value', function() { log += 'parent.$digest;'; }); child.$evalAsync(function(scope){ log += 'child.async;'; }); child.$watch('value', function() { log += 'child.$digest;'; }); - root.$digest(); + $rootScope.$digest(); expect(log).toEqual('parent.async;parent.$digest;child.async;child.$digest;'); - }); - - it('should cause a $digest rerun', function() { - root.log = ''; - root.value = 0; - root.$watch('value', 'log = log + ".";'); - root.$watch('init', function() { - root.$evalAsync('value = 123; log = log + "=" '); - expect(root.value).toEqual(0); + })); + + it('should cause a $digest rerun', inject(function($rootScope) { + $rootScope.log = ''; + $rootScope.value = 0; + $rootScope.$watch('value', 'log = log + ".";'); + $rootScope.$watch('init', function() { + $rootScope.$evalAsync('value = 123; log = log + "=" '); + expect($rootScope.value).toEqual(0); }); - root.$digest(); - expect(root.log).toEqual('.=.'); - }); - - it('should run async in the same order as added', function() { - root.log = ''; - root.$evalAsync("log = log + 1"); - root.$evalAsync("log = log + 2"); - root.$digest(); - expect(root.log).toBe('12'); - }); + $rootScope.$digest(); + expect($rootScope.log).toEqual('.=.'); + })); + + it('should run async in the same order as added', inject(function($rootScope) { + $rootScope.log = ''; + $rootScope.$evalAsync("log = log + 1"); + $rootScope.$evalAsync("log = log + 2"); + $rootScope.$digest(); + expect($rootScope.log).toBe('12'); + })); }); describe('$apply', function() { - it('should apply expression with full lifecycle', function() { + it('should apply expression with full lifecycle', inject(function($rootScope) { var log = ''; - var child = root.$new(); - root.$watch('a', function(scope, a){ log += '1'; }); + var child = $rootScope.$new(); + $rootScope.$watch('a', function(scope, a){ log += '1'; }); child.$apply('$parent.a=0'); expect(log).toEqual('1'); - }); + })); - it('should catch exceptions', function() { + it('should catch exceptions', inject(function($rootScope, $exceptionHandler, $log) { var log = ''; - var child = root.$new(); - root.$watch('a', function(scope, a){ log += '1'; }); - root.a = 0; + var child = $rootScope.$new(); + $rootScope.$watch('a', function(scope, a){ log += '1'; }); + $rootScope.a = 0; child.$apply(function() { throw new Error('MyError'); }); expect(log).toEqual('1'); - expect(mockHandler.errors[0].message).toEqual('MyError'); - $logMock.error.logs.shift(); - }); + expect($exceptionHandler.errors[0].message).toEqual('MyError'); + $log.error.logs.shift(); + })); describe('exceptions', function() { - var $exceptionHandler, log; - beforeEach(function() { + var log; + beforeEach(inject(function($rootScope) { log = ''; - $exceptionHandler = jasmine.createSpy('$exceptionHandler'); - root.$service = function(name) { - return {$exceptionHandler:$exceptionHandler}[name]; - }; - root.$watch(function() { log += '$digest;'; }); - root.$digest(); + $rootScope.$watch(function() { log += '$digest;'; }); + $rootScope.$digest(); log = ''; - }); + })); - it('should execute and return value and update', function() { - root.name = 'abc'; - expect(root.$apply(function(scope){ + it('should execute and return value and update', inject(function($rootScope, $exceptionHandler) { + $rootScope.name = 'abc'; + expect($rootScope.$apply(function(scope){ return scope.name; })).toEqual('abc'); expect(log).toEqual('$digest;'); - expect($exceptionHandler).not.wasCalled(); - }); + expect($exceptionHandler.errors).toEqual([]); + })); - it('should catch exception and update', function() { + it('should catch exception and update', inject(function($rootScope, $exceptionHandler) { var error = new Error('MyError'); - root.$apply(function() { throw error; }); + $rootScope.$apply(function() { throw error; }); expect(log).toEqual('$digest;'); - expect($exceptionHandler).wasCalledWith(error); - }); + expect($exceptionHandler.errors).toEqual([error]); + })); }); }); @@ -483,9 +468,9 @@ describe('Scope', function() { describe('$on', function() { - it('should add listener for both $emit and $broadcast events', function() { + it('should add listener for both $emit and $broadcast events', inject(function($rootScope) { var log = '', - root = angular.scope(), + root = angular.injector('ng').get('$rootScope'), child = root.$new(); function eventFn() { @@ -500,12 +485,12 @@ describe('Scope', function() { child.$broadcast('abc'); expect(log).toEqual('XX'); - }); + })); - it('should return a function that deregisters the listener', function() { + it('should return a function that deregisters the listener', inject(function($rootScope) { var log = '', - root = angular.scope(), + root = angular.injector('ng').get('$rootScope'), child = root.$new(), listenerRemove; @@ -526,7 +511,7 @@ describe('Scope', function() { child.$emit('abc'); child.$broadcast('abc'); expect(log).toEqual(''); - }); + })); }); @@ -537,55 +522,56 @@ describe('Scope', function() { log += event.currentScope.id + '>'; } - beforeEach(function() { + beforeEach(inject(function($rootScope) { log = ''; - child = root.$new(); + child = $rootScope.$new(); grandChild = child.$new(); greatGrandChild = grandChild.$new(); - root.id = 0; + $rootScope.id = 0; child.id = 1; grandChild.id = 2; greatGrandChild.id = 3; - root.$on('myEvent', logger); + $rootScope.$on('myEvent', logger); child.$on('myEvent', logger); grandChild.$on('myEvent', logger); greatGrandChild.$on('myEvent', logger); - }); + })); - it('should bubble event up to the root scope', function() { + it('should bubble event up to the root scope', inject(function($rootScope) { grandChild.$emit('myEvent'); expect(log).toEqual('2>1>0>'); - }); + })); - it('should dispatch exceptions to the $exceptionHandler', function() { + it('should dispatch exceptions to the $exceptionHandler', + inject(function($rootScope, $exceptionHandler) { child.$on('myEvent', function() { throw 'bubbleException'; }); grandChild.$emit('myEvent'); expect(log).toEqual('2>1>0>'); - expect(mockHandler.errors).toEqual(['bubbleException']); - }); + expect($exceptionHandler.errors).toEqual(['bubbleException']); + })); - it('should allow cancelation of event propagation', function() { + it('should allow cancelation of event propagation', inject(function($rootScope) { child.$on('myEvent', function(event){ event.cancel(); }); grandChild.$emit('myEvent'); expect(log).toEqual('2>1>'); - }); + })); - it('should forward method arguments', function() { + it('should forward method arguments', inject(function($rootScope) { child.$on('abc', function(event, arg1, arg2){ expect(event.name).toBe('abc'); expect(arg1).toBe('arg1'); expect(arg2).toBe('arg2'); }); child.$emit('abc', 'arg1', 'arg2'); - }); + })); describe('event object', function() { - it('should have methods/properties', function() { + it('should have methods/properties', inject(function($rootScope) { var event; child.$on('myEvent', function(e){ expect(e.targetScope).toBe(grandChild); @@ -595,7 +581,7 @@ describe('Scope', function() { }); grandChild.$emit('myEvent'); expect(event).toBeDefined(); - }); + })); }); }); @@ -609,18 +595,18 @@ describe('Scope', function() { log += event.currentScope.id + '>'; } - beforeEach(function() { + beforeEach(inject(function($rootScope) { log = ''; - child1 = root.$new(); - child2 = root.$new(); - child3 = root.$new(); + child1 = $rootScope.$new(); + child2 = $rootScope.$new(); + child3 = $rootScope.$new(); grandChild11 = child1.$new(); grandChild21 = child2.$new(); grandChild22 = child2.$new(); grandChild23 = child2.$new(); greatGrandChild211 = grandChild21.$new(); - root.id = 0; + $rootScope.id = 0; child1.id = 1; child2.id = 2; child3.id = 3; @@ -630,7 +616,7 @@ describe('Scope', function() { grandChild23.id = 23; greatGrandChild211.id = 211; - root.$on('myEvent', logger); + $rootScope.$on('myEvent', logger); child1.$on('myEvent', logger); child2.$on('myEvent', logger); child3.$on('myEvent', logger); @@ -647,43 +633,43 @@ describe('Scope', function() { // 11 21 22 23 // | // 211 - }); + })); - it('should broadcast an event from the root scope', function() { - root.$broadcast('myEvent'); + it('should broadcast an event from the root scope', inject(function($rootScope) { + $rootScope.$broadcast('myEvent'); expect(log).toBe('0>1>11>2>21>211>22>23>3>'); - }); + })); - it('should broadcast an event from a child scope', function() { + it('should broadcast an event from a child scope', inject(function($rootScope) { child2.$broadcast('myEvent'); expect(log).toBe('2>21>211>22>23>'); - }); + })); - it('should broadcast an event from a leaf scope with a sibling', function() { + it('should broadcast an event from a leaf scope with a sibling', inject(function($rootScope) { grandChild22.$broadcast('myEvent'); expect(log).toBe('22>'); - }); + })); - it('should broadcast an event from a leaf scope without a sibling', function() { + it('should broadcast an event from a leaf scope without a sibling', inject(function($rootScope) { grandChild23.$broadcast('myEvent'); expect(log).toBe('23>'); - }); + })); - it('should not not fire any listeners for other events', function() { - root.$broadcast('fooEvent'); + it('should not not fire any listeners for other events', inject(function($rootScope) { + $rootScope.$broadcast('fooEvent'); expect(log).toBe(''); - }); + })); }); describe('listener', function() { - it('should receive event object', function() { - var scope = angular.scope(), + it('should receive event object', inject(function($rootScope) { + var scope = angular.injector('ng').get('$rootScope'), child = scope.$new(), event; @@ -695,11 +681,11 @@ describe('Scope', function() { expect(event.name).toBe('fooEvent'); expect(event.targetScope).toBe(scope); expect(event.currentScope).toBe(child); - }); + })); - it('should support passing messages as varargs', function() { - var scope = angular.scope(), + it('should support passing messages as varargs', inject(function($rootScope) { + var scope = angular.injector('ng').get('$rootScope'), child = scope.$new(), args; @@ -710,7 +696,7 @@ describe('Scope', function() { expect(args.length).toBe(5); expect(sliceArgs(args, 1)).toEqual(['do', 're', 'me', 'fa']); - }); + })); }); }); }); diff --git a/test/service/snifferSpec.js b/test/service/snifferSpec.js index 72c3204615dc..7ec1dc8d2adf 100644 --- a/test/service/snifferSpec.js +++ b/test/service/snifferSpec.js @@ -3,7 +3,7 @@ describe('$sniffer', function() { function sniffer($window) { - return angular.service('$sniffer')($window); + return new $SnifferProvider().$get[1]($window); } describe('history', function() { diff --git a/test/service/windowSpec.js b/test/service/windowSpec.js index c539e2853f37..3b8471469b3d 100644 --- a/test/service/windowSpec.js +++ b/test/service/windowSpec.js @@ -1,19 +1,7 @@ 'use strict'; describe('$window', function() { - var scope; - - beforeEach(function() { - scope = angular.scope(); - }); - - - afterEach(function() { - dealoc(scope); - }); - - - it("should inject $window", function() { - expect(scope.$service('$window')).toBe(window); - }); + it("should inject $window", inject(function($window) { + expect($window).toBe(window); + })); }); diff --git a/test/service/xhr.bulkSpec.js b/test/service/xhr.bulkSpec.js index 6b99fbba3ca7..6e55b3877dd2 100644 --- a/test/service/xhr.bulkSpec.js +++ b/test/service/xhr.bulkSpec.js @@ -1,24 +1,14 @@ 'use strict'; describe('$xhr.bulk', function() { - var scope, $browser, $browserXhr, $log, $xhrBulk, $xhrError, log; - - beforeEach(function() { - scope = angular.scope(angular.service, { - '$xhr.error': $xhrError = jasmine.createSpy('$xhr.error'), - '$log': $log = {} - }); - $browser = scope.$service('$browser'); - $browserXhr = $browser.xhr; - $xhrBulk = scope.$service('$xhr.bulk'); - $log = scope.$service('$log'); - log = ''; - }); - + var log; - afterEach(function() { - dealoc(scope); - }); + beforeEach(inject(function($provide) { + $provide.value('$xhr.error', jasmine.createSpy('$xhr.error')); + $provide.factory('$xhrError', ['$xhr.error', identity]); + $provide.factory('$xhrBulk', ['$xhr.bulk', identity]); + log = ''; + })); function callback(code, response) { @@ -27,12 +17,12 @@ describe('$xhr.bulk', function() { } - it('should collect requests', function() { + it('should collect requests', inject(function($browser, $xhrBulk) { $xhrBulk.urls["/"] = {match:/.*/}; $xhrBulk('GET', '/req1', null, callback); $xhrBulk('POST', '/req2', {post:'data'}, callback); - $browserXhr.expectPOST('/', { + $browser.xhr.expectPOST('/', { requests:[{method:'GET', url:'/req1', data: null}, {method:'POST', url:'/req2', data:{post:'data'} }] }).respond([ @@ -40,17 +30,18 @@ describe('$xhr.bulk', function() { {status:200, response:'second'} ]); $xhrBulk.flush(function() { log += 'DONE';}); - $browserXhr.flush(); + $browser.xhr.flush(); expect(log).toEqual('"first";"second";DONE'); - }); + })); - it('should handle non 200 status code by forwarding to error handler', function() { + it('should handle non 200 status code by forwarding to error handler', + inject(function($browser, $xhrBulk, $xhrError) { $xhrBulk.urls['/'] = {match:/.*/}; $xhrBulk('GET', '/req1', null, callback); $xhrBulk('POST', '/req2', {post:'data'}, callback); - $browserXhr.expectPOST('/', { + $browser.xhr.expectPOST('/', { requests:[{method:'GET', url:'/req1', data: null}, {method:'POST', url:'/req2', data:{post:'data'} }] }).respond([ @@ -58,7 +49,7 @@ describe('$xhr.bulk', function() { {status:200, response:'second'} ]); $xhrBulk.flush(function() { log += 'DONE';}); - $browserXhr.flush(); + $browser.xhr.flush(); expect($xhrError).toHaveBeenCalled(); var cb = $xhrError.mostRecentCall.args[0].success; @@ -68,22 +59,23 @@ describe('$xhr.bulk', function() { {status: 404, response: 'NotFound'}); expect(log).toEqual('"second";DONE'); - }); + })); - it('should handle non 200 status code by calling error callback if provided', function() { + it('should handle non 200 status code by calling error callback if provided', + inject(function($browser, $xhrBulk, $xhrError) { var callback = jasmine.createSpy('error'); $xhrBulk.urls['/'] = {match: /.*/}; $xhrBulk('GET', '/req1', null, noop, callback); - $browserXhr.expectPOST('/', { + $browser.xhr.expectPOST('/', { requests:[{method: 'GET', url: '/req1', data: null}] }).respond([{status: 404, response: 'NotFound'}]); $xhrBulk.flush(); - $browserXhr.flush(); + $browser.xhr.flush(); expect($xhrError).not.toHaveBeenCalled(); expect(callback).toHaveBeenCalledWith(404, 'NotFound'); - }); + })); }); diff --git a/test/service/xhr.cacheSpec.js b/test/service/xhr.cacheSpec.js index 0c77e629d571..b6eeb6aa128d 100644 --- a/test/service/xhr.cacheSpec.js +++ b/test/service/xhr.cacheSpec.js @@ -1,20 +1,15 @@ 'use strict'; describe('$xhr.cache', function() { - var scope, $browser, $browserXhr, $xhrErr, cache, log; + var log; - beforeEach(function() { - scope = angular.scope(angularService, {'$xhr.error': $xhrErr = jasmine.createSpy('$xhr.error')}); - $browser = scope.$service('$browser'); - $browserXhr = $browser.xhr; - cache = scope.$service('$xhr.cache'); + beforeEach(inject(function($provide) { + $provide.value('$xhr.error', jasmine.createSpy('$xhr.error')); + $provide.factory('$xhrError', ['$xhr.error', identity]); + $provide.factory('$xhrBulk', ['$xhr.bulk', identity]); + $provide.factory('$xhrCache', ['$xhr.cache', identity]); log = ''; - }); - - - afterEach(function() { - dealoc(scope); - }); + })); function callback(code, response) { @@ -23,156 +18,158 @@ describe('$xhr.cache', function() { } - it('should cache requests', function() { - $browserXhr.expectGET('/url').respond('first'); - cache('GET', '/url', null, callback); - $browserXhr.flush(); + it('should cache requests', inject(function($browser, $xhrCache) { + $browser.xhr.expectGET('/url').respond('first'); + $xhrCache('GET', '/url', null, callback); + $browser.xhr.flush(); - $browserXhr.expectGET('/url').respond('ERROR'); - cache('GET', '/url', null, callback); + $browser.xhr.expectGET('/url').respond('ERROR'); + $xhrCache('GET', '/url', null, callback); $browser.defer.flush(); expect(log).toEqual('"first";"first";'); - cache('GET', '/url', null, callback, false); + $xhrCache('GET', '/url', null, callback, false); $browser.defer.flush(); expect(log).toEqual('"first";"first";"first";'); - }); + })); - it('should first return cache request, then return server request', function() { - $browserXhr.expectGET('/url').respond('first'); - cache('GET', '/url', null, callback, true); - $browserXhr.flush(); + it('should first return cache request, then return server request', inject(function($browser, $xhrCache) { + $browser.xhr.expectGET('/url').respond('first'); + $xhrCache('GET', '/url', null, callback, true); + $browser.xhr.flush(); - $browserXhr.expectGET('/url').respond('ERROR'); - cache('GET', '/url', null, callback, true); + $browser.xhr.expectGET('/url').respond('ERROR'); + $xhrCache('GET', '/url', null, callback, true); $browser.defer.flush(); expect(log).toEqual('"first";"first";'); - $browserXhr.flush(); + $browser.xhr.flush(); expect(log).toEqual('"first";"first";"ERROR";'); - }); + })); - it('should serve requests from cache', function() { - cache.data.url = {value:'123'}; - cache('GET', 'url', null, callback); + it('should serve requests from cache', inject(function($browser, $xhrCache) { + $xhrCache.data.url = {value:'123'}; + $xhrCache('GET', 'url', null, callback); $browser.defer.flush(); expect(log).toEqual('"123";'); - cache('GET', 'url', null, callback, false); + $xhrCache('GET', 'url', null, callback, false); $browser.defer.flush(); expect(log).toEqual('"123";"123";'); - }); + })); - it('should keep track of in flight requests and request only once', function() { - scope.$service('$xhr.bulk').urls['/bulk'] = { + it('should keep track of in flight requests and request only once', inject(function($browser, $xhrCache, $xhrBulk) { + $xhrBulk.urls['/bulk'] = { match:function(url){ return url == '/url'; } }; - $browserXhr.expectPOST('/bulk', { + $browser.xhr.expectPOST('/bulk', { requests:[{method:'GET', url:'/url', data: null}] }).respond([ {status:200, response:'123'} ]); - cache('GET', '/url', null, callback); - cache('GET', '/url', null, callback); - cache.delegate.flush(); - $browserXhr.flush(); + $xhrCache('GET', '/url', null, callback); + $xhrCache('GET', '/url', null, callback); + $xhrCache.delegate.flush(); + $browser.xhr.flush(); expect(log).toEqual('"123";"123";'); - }); + })); - it('should clear cache on non GET', function() { - $browserXhr.expectPOST('abc', {}).respond({}); - cache.data.url = {value:123}; - cache('POST', 'abc', {}); - expect(cache.data.url).toBeUndefined(); - }); + it('should clear cache on non GET', inject(function($browser, $xhrCache) { + $browser.xhr.expectPOST('abc', {}).respond({}); + $xhrCache.data.url = {value:123}; + $xhrCache('POST', 'abc', {}); + expect($xhrCache.data.url).toBeUndefined(); + })); - it('should call callback asynchronously for both cache hit and cache miss', function() { - $browserXhr.expectGET('/url').respond('+'); - cache('GET', '/url', null, callback); + it('should call callback asynchronously for both cache hit and cache miss', inject(function($browser, $xhrCache) { + $browser.xhr.expectGET('/url').respond('+'); + $xhrCache('GET', '/url', null, callback); expect(log).toEqual(''); //callback hasn't executed - $browserXhr.flush(); + $browser.xhr.flush(); expect(log).toEqual('"+";'); //callback has executed - cache('GET', '/url', null, callback); + $xhrCache('GET', '/url', null, callback); expect(log).toEqual('"+";'); //callback hasn't executed $browser.defer.flush(); expect(log).toEqual('"+";"+";'); //callback has executed - }); + })); - it('should call callback synchronously when sync flag is on', function() { - $browserXhr.expectGET('/url').respond('+'); - cache('GET', '/url', null, callback, false, true); + it('should call callback synchronously when sync flag is on', inject(function($browser, $xhrCache) { + $browser.xhr.expectGET('/url').respond('+'); + $xhrCache('GET', '/url', null, callback, false, true); expect(log).toEqual(''); //callback hasn't executed - $browserXhr.flush(); + $browser.xhr.flush(); expect(log).toEqual('"+";'); //callback has executed - cache('GET', '/url', null, callback, false, true); + $xhrCache('GET', '/url', null, callback, false, true); expect(log).toEqual('"+";"+";'); //callback has executed $browser.defer.flush(); expect(log).toEqual('"+";"+";'); //callback was not called again any more - }); + })); - it('should call eval after callbacks for both cache hit and cache miss execute', function() { - var flushSpy = this.spyOn(scope, '$digest').andCallThrough(); + it('should call eval after callbacks for both cache hit and cache miss execute', + inject(function($browser, $xhrCache, $rootScope) { + var flushSpy = this.spyOn($rootScope, '$digest').andCallThrough(); - $browserXhr.expectGET('/url').respond('+'); - cache('GET', '/url', null, callback); + $browser.xhr.expectGET('/url').respond('+'); + $xhrCache('GET', '/url', null, callback); expect(flushSpy).not.toHaveBeenCalled(); - $browserXhr.flush(); + $browser.xhr.flush(); expect(flushSpy).toHaveBeenCalled(); flushSpy.reset(); //reset the spy - cache('GET', '/url', null, callback); + $xhrCache('GET', '/url', null, callback); expect(flushSpy).not.toHaveBeenCalled(); $browser.defer.flush(); expect(flushSpy).toHaveBeenCalled(); - }); + })); - it('should call the error callback on error if provided', function() { + it('should call the error callback on error if provided', inject(function($browser, $xhrCache) { var errorSpy = jasmine.createSpy('error'), successSpy = jasmine.createSpy('success'); - $browserXhr.expectGET('/url').respond(500, 'error'); + $browser.xhr.expectGET('/url').respond(500, 'error'); - cache('GET', '/url', null, successSpy, errorSpy, false, true); - $browserXhr.flush(); + $xhrCache('GET', '/url', null, successSpy, errorSpy, false, true); + $browser.xhr.flush(); expect(errorSpy).toHaveBeenCalledWith(500, 'error'); expect(successSpy).not.toHaveBeenCalled(); errorSpy.reset(); - cache('GET', '/url', successSpy, errorSpy, false, true); - $browserXhr.flush(); + $xhrCache('GET', '/url', successSpy, errorSpy, false, true); + $browser.xhr.flush(); expect(errorSpy).toHaveBeenCalledWith(500, 'error'); expect(successSpy).not.toHaveBeenCalled(); - }); + })); - it('should call the $xhr.error on error if error callback not provided', function() { + it('should call the $xhr.error on error if error callback not provided', + inject(function($browser, $xhrCache, $xhrError) { var errorSpy = jasmine.createSpy('error'), successSpy = jasmine.createSpy('success'); - $browserXhr.expectGET('/url').respond(500, 'error'); - cache('GET', '/url', null, successSpy, false, true); - $browserXhr.flush(); + $browser.xhr.expectGET('/url').respond(500, 'error'); + $xhrCache('GET', '/url', null, successSpy, false, true); + $browser.xhr.flush(); expect(successSpy).not.toHaveBeenCalled(); - expect($xhrErr).toHaveBeenCalledWith( + expect($xhrError).toHaveBeenCalledWith( {method: 'GET', url: '/url', data: null, success: successSpy}, {status: 500, body: 'error'}); - }); + })); }); diff --git a/test/service/xhr.errorSpec.js b/test/service/xhr.errorSpec.js index 49b63fd00bb5..f9ce2b72e729 100644 --- a/test/service/xhr.errorSpec.js +++ b/test/service/xhr.errorSpec.js @@ -1,22 +1,13 @@ 'use strict'; describe('$xhr.error', function() { - var scope, $browser, $browserXhr, $xhr, $xhrError, log; + var log; - beforeEach(function() { - scope = angular.scope(angular.service, { - '$xhr.error': $xhrError = jasmine.createSpy('$xhr.error') - }); - $browser = scope.$service('$browser'); - $browserXhr = $browser.xhr; - $xhr = scope.$service('$xhr'); + beforeEach(inject(function($provide) { + $provide.value('$xhr.error', jasmine.createSpy('$xhr.error')); + $provide.factory('$xhrError', ['$xhr.error', identity]); log = ''; - }); - - - afterEach(function() { - dealoc(scope); - }); + })); function callback(code, response) { @@ -25,14 +16,14 @@ describe('$xhr.error', function() { } - it('should handle non 200 status codes by forwarding to error handler', function() { - $browserXhr.expectPOST('/req', 'MyData').respond(500, 'MyError'); + it('should handle non 200 status codes by forwarding to error handler', inject(function($browser, $xhr, $xhrError) { + $browser.xhr.expectPOST('/req', 'MyData').respond(500, 'MyError'); $xhr('POST', '/req', 'MyData', callback); - $browserXhr.flush(); + $browser.xhr.flush(); var cb = $xhrError.mostRecentCall.args[0].success; expect(typeof cb).toEqual('function'); expect($xhrError).toHaveBeenCalledWith( {url: '/req', method: 'POST', data: 'MyData', success: cb}, {status: 500, body: 'MyError'}); - }); + })); }); diff --git a/test/service/xhrSpec.js b/test/service/xhrSpec.js index 2a552403d5c8..83c5f93fd24f 100644 --- a/test/service/xhrSpec.js +++ b/test/service/xhrSpec.js @@ -1,22 +1,14 @@ 'use strict'; describe('$xhr', function() { - var scope, $browser, $browserXhr, $log, $xhr, $xhrErr, log; - - beforeEach(function() { - var scope = angular.scope(angular.service, { - '$xhr.error': $xhrErr = jasmine.createSpy('xhr.error')}); - $log = scope.$service('$log'); - $browser = scope.$service('$browser'); - $browserXhr = $browser.xhr; - $xhr = scope.$service('$xhr'); - log = ''; - }); + var log; - afterEach(function() { - dealoc(scope); - }); + beforeEach(inject(function($provide) { + log = ''; + $provide.value('$xhr.error', jasmine.createSpy('xhr.error')); + $provide.factory('$xhrError', ['$xhr.error', identity]); + })); function callback(code, response) { @@ -24,246 +16,246 @@ describe('$xhr', function() { } - it('should forward the request to $browser and decode JSON', function() { - $browserXhr.expectGET('/reqGET').respond('first'); - $browserXhr.expectGET('/reqGETjson').respond('["second"]'); - $browserXhr.expectPOST('/reqPOST', {post:'data'}).respond('third'); + it('should forward the request to $browser and decode JSON', inject(function($browser, $xhr) { + $browser.xhr.expectGET('/reqGET').respond('first'); + $browser.xhr.expectGET('/reqGETjson').respond('["second"]'); + $browser.xhr.expectPOST('/reqPOST', {post:'data'}).respond('third'); $xhr('GET', '/reqGET', null, callback); $xhr('GET', '/reqGETjson', null, callback); $xhr('POST', '/reqPOST', {post:'data'}, callback); - $browserXhr.flush(); + $browser.xhr.flush(); expect(log).toEqual( '{code=200; response="third"}' + '{code=200; response=["second"]}' + '{code=200; response="first"}'); - }); + })); - it('should allow all 2xx requests', function() { - $browserXhr.expectGET('/req1').respond(200, '1'); + it('should allow all 2xx requests', inject(function($browser, $xhr) { + $browser.xhr.expectGET('/req1').respond(200, '1'); $xhr('GET', '/req1', null, callback); - $browserXhr.flush(); + $browser.xhr.flush(); - $browserXhr.expectGET('/req2').respond(299, '2'); + $browser.xhr.expectGET('/req2').respond(299, '2'); $xhr('GET', '/req2', null, callback); - $browserXhr.flush(); + $browser.xhr.flush(); expect(log).toEqual( '{code=200; response="1"}' + '{code=299; response="2"}'); - }); + })); - it('should handle exceptions in callback', function() { - $browserXhr.expectGET('/reqGET').respond('first'); + it('should handle exceptions in callback', inject(function($browser, $xhr, $log) { + $browser.xhr.expectGET('/reqGET').respond('first'); $xhr('GET', '/reqGET', null, function() { throw "MyException"; }); - $browserXhr.flush(); + $browser.xhr.flush(); expect($log.error.logs.shift()).toContain('MyException'); - }); + })); - it('should automatically deserialize json objects', function() { + it('should automatically deserialize json objects', inject(function($browser, $xhr) { var response; - $browserXhr.expectGET('/foo').respond('{"foo":"bar","baz":23}'); + $browser.xhr.expectGET('/foo').respond('{"foo":"bar","baz":23}'); $xhr('GET', '/foo', function(code, resp) { response = resp; }); - $browserXhr.flush(); + $browser.xhr.flush(); expect(response).toEqual({foo:'bar', baz:23}); - }); + })); - it('should automatically deserialize json arrays', function() { + it('should automatically deserialize json arrays', inject(function($browser, $xhr) { var response; - $browserXhr.expectGET('/foo').respond('[1, "abc", {"foo":"bar"}]'); + $browser.xhr.expectGET('/foo').respond('[1, "abc", {"foo":"bar"}]'); $xhr('GET', '/foo', function(code, resp) { response = resp; }); - $browserXhr.flush(); + $browser.xhr.flush(); expect(response).toEqual([1, 'abc', {foo:'bar'}]); - }); + })); - it('should automatically deserialize json with security prefix', function() { + it('should automatically deserialize json with security prefix', inject(function($browser, $xhr) { var response; - $browserXhr.expectGET('/foo').respond(')]}\',\n[1, "abc", {"foo":"bar"}]'); + $browser.xhr.expectGET('/foo').respond(')]}\',\n[1, "abc", {"foo":"bar"}]'); $xhr('GET', '/foo', function(code, resp) { response = resp; }); - $browserXhr.flush(); + $browser.xhr.flush(); expect(response).toEqual([1, 'abc', {foo:'bar'}]); - }); + })); - it('should call $xhr.error on error if no error callback provided', function() { + it('should call $xhr.error on error if no error callback provided', inject(function($browser, $xhr, $xhrError) { var successSpy = jasmine.createSpy('success'); - $browserXhr.expectGET('/url').respond(500, 'error'); + $browser.xhr.expectGET('/url').respond(500, 'error'); $xhr('GET', '/url', null, successSpy); - $browserXhr.flush(); + $browser.xhr.flush(); expect(successSpy).not.toHaveBeenCalled(); - expect($xhrErr).toHaveBeenCalledWith( + expect($xhrError).toHaveBeenCalledWith( {method: 'GET', url: '/url', data: null, success: successSpy}, {status: 500, body: 'error'} ); - }); + })); - it('should call the error callback on error if provided', function() { + it('should call the error callback on error if provided', inject(function($browser, $xhr) { var errorSpy = jasmine.createSpy('error'), successSpy = jasmine.createSpy('success'); - $browserXhr.expectGET('/url').respond(500, 'error'); + $browser.xhr.expectGET('/url').respond(500, 'error'); $xhr('GET', '/url', null, successSpy, errorSpy); - $browserXhr.flush(); + $browser.xhr.flush(); expect(errorSpy).toHaveBeenCalledWith(500, 'error'); expect(successSpy).not.toHaveBeenCalled(); errorSpy.reset(); $xhr('GET', '/url', successSpy, errorSpy); - $browserXhr.flush(); + $browser.xhr.flush(); expect(errorSpy).toHaveBeenCalledWith(500, 'error'); expect(successSpy).not.toHaveBeenCalled(); - }); + })); describe('http headers', function() { describe('default headers', function() { - it('should set default headers for GET request', function() { + it('should set default headers for GET request', inject(function($browser, $xhr) { var callback = jasmine.createSpy('callback'); - $browserXhr.expectGET('URL', '', {'Accept': 'application/json, text/plain, */*', + $browser.xhr.expectGET('URL', '', {'Accept': 'application/json, text/plain, */*', 'X-Requested-With': 'XMLHttpRequest'}). respond(234, 'OK'); $xhr('GET', 'URL', callback); - $browserXhr.flush(); + $browser.xhr.flush(); expect(callback).toHaveBeenCalled(); - }); + })); - it('should set default headers for POST request', function() { + it('should set default headers for POST request', inject(function($browser, $xhr) { var callback = jasmine.createSpy('callback'); - $browserXhr.expectPOST('URL', 'xx', {'Accept': 'application/json, text/plain, */*', + $browser.xhr.expectPOST('URL', 'xx', {'Accept': 'application/json, text/plain, */*', 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded'}). respond(200, 'OK'); $xhr('POST', 'URL', 'xx', callback); - $browserXhr.flush(); + $browser.xhr.flush(); expect(callback).toHaveBeenCalled(); - }); + })); - it('should set default headers for custom HTTP method', function() { + it('should set default headers for custom HTTP method', inject(function($browser, $xhr) { var callback = jasmine.createSpy('callback'); - $browserXhr.expect('FOO', 'URL', '', {'Accept': 'application/json, text/plain, */*', + $browser.xhr.expect('FOO', 'URL', '', {'Accept': 'application/json, text/plain, */*', 'X-Requested-With': 'XMLHttpRequest'}). respond(200, 'OK'); $xhr('FOO', 'URL', callback); - $browserXhr.flush(); + $browser.xhr.flush(); expect(callback).toHaveBeenCalled(); - }); + })); describe('custom headers', function() { - it('should allow appending a new header to the common defaults', function() { + it('should allow appending a new header to the common defaults', inject(function($browser, $xhr) { var callback = jasmine.createSpy('callback'); - $browserXhr.expectGET('URL', '', {'Accept': 'application/json, text/plain, */*', + $browser.xhr.expectGET('URL', '', {'Accept': 'application/json, text/plain, */*', 'X-Requested-With': 'XMLHttpRequest', 'Custom-Header': 'value'}). respond(200, 'OK'); $xhr.defaults.headers.common['Custom-Header'] = 'value'; $xhr('GET', 'URL', callback); - $browserXhr.flush(); + $browser.xhr.flush(); expect(callback).toHaveBeenCalled(); callback.reset(); - $browserXhr.expectPOST('URL', 'xx', {'Accept': 'application/json, text/plain, */*', + $browser.xhr.expectPOST('URL', 'xx', {'Accept': 'application/json, text/plain, */*', 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded', 'Custom-Header': 'value'}). respond(200, 'OK'); $xhr('POST', 'URL', 'xx', callback); - $browserXhr.flush(); + $browser.xhr.flush(); expect(callback).toHaveBeenCalled(); - }); + })); - it('should allow appending a new header to a method specific defaults', function() { + it('should allow appending a new header to a method specific defaults', inject(function($browser, $xhr) { var callback = jasmine.createSpy('callback'); - $browserXhr.expectGET('URL', '', {'Accept': 'application/json, text/plain, */*', + $browser.xhr.expectGET('URL', '', {'Accept': 'application/json, text/plain, */*', 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/json'}). respond(200, 'OK'); $xhr.defaults.headers.get['Content-Type'] = 'application/json'; $xhr('GET', 'URL', callback); - $browserXhr.flush(); + $browser.xhr.flush(); expect(callback).toHaveBeenCalled(); callback.reset(); - $browserXhr.expectPOST('URL', 'x', {'Accept': 'application/json, text/plain, */*', + $browser.xhr.expectPOST('URL', 'x', {'Accept': 'application/json, text/plain, */*', 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded'}). respond(200, 'OK'); $xhr('POST', 'URL', 'x', callback); - $browserXhr.flush(); + $browser.xhr.flush(); expect(callback).toHaveBeenCalled(); - }); + })); - it('should support overwriting and deleting default headers', function() { + it('should support overwriting and deleting default headers', inject(function($browser, $xhr) { var callback = jasmine.createSpy('callback'); - $browserXhr.expectGET('URL', '', {'Accept': 'application/json, text/plain, */*'}). + $browser.xhr.expectGET('URL', '', {'Accept': 'application/json, text/plain, */*'}). respond(200, 'OK'); //delete a default header delete $xhr.defaults.headers.common['X-Requested-With']; $xhr('GET', 'URL', callback); - $browserXhr.flush(); + $browser.xhr.flush(); expect(callback).toHaveBeenCalled(); callback.reset(); - $browserXhr.expectPOST('URL', 'xx', {'Accept': 'application/json, text/plain, */*', + $browser.xhr.expectPOST('URL', 'xx', {'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json'}). respond(200, 'OK'); //overwrite a default header $xhr.defaults.headers.post['Content-Type'] = 'application/json'; $xhr('POST', 'URL', 'xx', callback); - $browserXhr.flush(); + $browser.xhr.flush(); expect(callback).toHaveBeenCalled(); - }); + })); }); }); }); describe('xsrf', function() { - it('should copy the XSRF cookie into a XSRF Header', function() { + it('should copy the XSRF cookie into a XSRF Header', inject(function($browser, $xhr) { var code, response; - $browserXhr + $browser.xhr .expectPOST('URL', 'DATA', {'X-XSRF-TOKEN': 'secret'}) .respond(234, 'OK'); $browser.cookies('XSRF-TOKEN', 'secret'); @@ -271,9 +263,9 @@ describe('$xhr', function() { code = c; response = r; }); - $browserXhr.flush(); + $browser.xhr.flush(); expect(code).toEqual(234); expect(response).toEqual('OK'); - }); + })); }); }); diff --git a/test/testabilityPatch.js b/test/testabilityPatch.js index a8b1c06b6a2b..8150a0a33aae 100644 --- a/test/testabilityPatch.js +++ b/test/testabilityPatch.js @@ -9,46 +9,10 @@ _jQuery.event.special.change = undefined; -if (window.jstestdriver) { - window.jstd = jstestdriver; - window.dump = function dump() { - var args = []; - forEach(arguments, function(arg){ - if (isElement(arg)) { - arg = sortedHtml(arg); - } else if (isObject(arg)) { - if (arg.$eval == Scope.prototype.$eval) { - arg = dumpScope(arg); - } else { - arg = toJson(arg, true); - } - } - args.push(arg); - }); - jstd.console.log.apply(jstd.console, args); - }; -} - -function dumpScope(scope, offset) { - offset = offset || ' '; - var log = [offset + 'Scope(' + scope.$id + '): {']; - for ( var key in scope ) { - if (scope.hasOwnProperty(key) && !key.match(/^(\$|this)/)) { - log.push(' ' + key + ': ' + toJson(scope[key])); - } - } - var child = scope.$$childHead; - while(child) { - log.push(dumpScope(child, offset + ' ')); - child = child.$$nextSibling; - } - log.push('}'); - return log.join('\n' + offset); -} - +publishExternalAPI(angular); +bindJQuery(); beforeEach(function() { - // This is to reset parsers global cache of expressions. - compileCache = {}; + publishExternalAPI(angular); // workaround for IE bug https://plus.google.com/104744871076396904202/posts/Kqjuj6RSbbT // IE overwrite window.jQuery with undefined because of empty jQuery var statement, so we have to @@ -63,50 +27,20 @@ beforeEach(function() { // reset to jQuery or default to us. bindJQuery(); jqLite(document.body).html(''); - - this.addMatchers({ - toHaveClass: function(clazz) { - this.message = function() { - return "Expected '" + sortedHtml(this.actual) + "' to have class '" + clazz + "'."; - }; - return this.actual.hasClass ? - this.actual.hasClass(clazz) : - jqLite(this.actual).hasClass(clazz); - } - }); - - $logMock.log.logs = []; - $logMock.warn.logs = []; - $logMock.info.logs = []; - $logMock.error.logs = []; }); afterEach(function() { - // check $log mock - forEach(['error', 'warn', 'info', 'log'], function(logLevel) { - if ($logMock[logLevel].logs.length) { - forEach($logMock[logLevel].logs, function(log) { - forEach(log, function deleteStack(logItem) { - if (logItem instanceof Error) { - dump(logItem.stack); - delete logItem.stack; - delete logItem.arguments; - } else { - dump(logItem); - } - }); - }); - - throw new Error("Exprected $log." + logLevel + ".logs array to be empty. " + - "Either a message was logged unexpectedly, or an expected log message was not checked " + - "and removed. Array contents: " + toJson($logMock[logLevel].logs)); - } - }); - - clearJqCache(); -}); + if (this.$injector) { + var $rootScope = this.$injector.get('$rootScope'); + var $log = this.$injector.get('$log'); + // release the injector + dealoc($rootScope); + + // check $log mock + $log.assertEmpty && $log.assertEmpty(); + } -function clearJqCache() { + // complain about uncleared jqCache references var count = 0; forEachSorted(jqCache, function(value, key){ count ++; @@ -122,15 +56,8 @@ function clearJqCache() { if (count) { fail('Found jqCache references that were not deallocated!'); } -} - -function nakedExpect(obj) { - return expect(angular.fromJson(angular.toJson(obj))); -} +}); -function childNode(element, index) { - return jqLite(element[0].childNodes[index]); -} function dealoc(obj) { if (obj) { @@ -140,29 +67,6 @@ function dealoc(obj) { } } -extend(angular, { - 'element': jqLite, - 'compile': compile, - 'scope': createScope, - 'copy': copy, - 'extend': extend, - 'equals': equals, - 'forEach': forEach, - 'noop':noop, - 'bind':bind, - 'toJson': toJson, - 'fromJson': fromJson, - 'identity':identity, - 'injector': createInjector, - 'isUndefined': isUndefined, - 'isDefined': isDefined, - 'isString': isString, - 'isFunction': isFunction, - 'isObject': isObject, - 'isNumber': isNumber, - 'isArray': isArray -}); - function sortedHtml(element, showNgClass) { var html = ""; @@ -260,7 +164,7 @@ function sortedHtml(element, showNgClass) { // TODO(vojta): migrate these helpers into jasmine matchers -/** +/**a * This method is a cheap way of testing if css for a given node is not set to 'none'. It doesn't * actually test if an element is displayed by the browser. Be aware!!! */ @@ -270,43 +174,12 @@ function isCssVisible(node) { } function assertHidden(node) { - assertFalse("Node should be hidden but vas visible: " + sortedHtml(node), isCssVisible(node)); + assertFalse("Node should be hidden but vas visible: " + + angular.module.ngMock.dump(node), isCssVisible(node)); } function assertVisible(node) { - assertTrue("Node should be visible but vas hidden: " + sortedHtml(node), isCssVisible(node)); + assertTrue("Node should be visible but vas hidden: " + + angular.module.ngMock.dump(node), isCssVisible(node)); } -function assertJsonEquals(expected, actual) { - assertEquals(toJson(expected), toJson(actual)); -} - -function assertUndefined(value) { - assertEquals('undefined', typeof value); -} - -function assertDefined(value) { - assertTrue(toJson(value), !!value); -} - -function assertThrows(error, fn){ - var exception = null; - try { - fn(); - } catch(e) { - exception = e; - } - if (!exception) { - fail("Expecting exception, none thrown"); - } - assertEquals(error, exception); -} - -window.log = noop; -window.error = noop; - -function rethrow(e) { - if(e) { - throw e; - } -} diff --git a/test/widget/formSpec.js b/test/widget/formSpec.js index 4f5630ba1492..7a92dbf43443 100644 --- a/test/widget/formSpec.js +++ b/test/widget/formSpec.js @@ -8,17 +8,17 @@ describe('form', function() { }); - it('should attach form to DOM', function() { + it('should attach form to DOM', inject(function($rootScope, $compile) { doc = angular.element('
                          '); - var scope = angular.compile(doc)(); + $compile(doc)($rootScope); expect(doc.data('$form')).toBeTruthy(); - }); + })); - it('should prevent form submission', function() { + it('should prevent form submission', inject(function($rootScope, $compile) { var startingUrl = '' + window.location; doc = angular.element(''); - var scope = angular.compile(doc)(); + $compile(doc)($rootScope); browserTrigger(doc.find('input')); waitsFor( function() { return true; }, @@ -26,44 +26,44 @@ describe('form', function() { runs(function() { expect('' + window.location).toEqual(startingUrl); }); - }); + })); - it('should publish form to scope', function() { + it('should publish form to scope', inject(function($rootScope, $compile) { doc = angular.element('
                          '); - var scope = angular.compile(doc)(); - expect(scope.myForm).toBeTruthy(); + $compile(doc)($rootScope); + expect($rootScope.myForm).toBeTruthy(); expect(doc.data('$form')).toBeTruthy(); - expect(doc.data('$form')).toEqual(scope.myForm); - }); + expect(doc.data('$form')).toEqual($rootScope.myForm); + })); - it('should have ng-valide/ng-invalid style', function() { + it('should have ng-valide/ng-invalid style', inject(function($rootScope, $compile) { doc = angular.element('
                          '); - var scope = angular.compile(doc)(); - scope.text = 'misko'; - scope.$digest(); + $compile(doc)($rootScope); + $rootScope.text = 'misko'; + $rootScope.$digest(); expect(doc.hasClass('ng-valid')).toBe(true); expect(doc.hasClass('ng-invalid')).toBe(false); - scope.text = ''; - scope.$digest(); + $rootScope.text = ''; + $rootScope.$digest(); expect(doc.hasClass('ng-valid')).toBe(false); expect(doc.hasClass('ng-invalid')).toBe(true); - }); + })); - it('should chain nested forms', function() { + it('should chain nested forms', inject(function($rootScope, $compile) { doc = angular.element( '' + '' + '' + '' + ''); - var scope = angular.compile(doc)(); - var parent = scope.parent; - var child = scope.child; + $compile(doc)($rootScope); + var parent = $rootScope.parent; + var child = $rootScope.child; var input = child.text; input.$emit('$invalid', 'MyError'); @@ -73,21 +73,21 @@ describe('form', function() { input.$emit('$valid', 'MyError'); expect(parent.$error.MyError).toBeUndefined(); expect(child.$error.MyError).toBeUndefined(); - }); + })); - it('should chain nested forms in repeater', function() { + it('should chain nested forms in repeater', inject(function($rootScope, $compile) { doc = angular.element( '' + '' + '' + '' + ''); - var scope = angular.compile(doc)(); - scope.forms = [1]; - scope.$digest(); + $compile(doc)($rootScope); + $rootScope.forms = [1]; + $rootScope.$digest(); - var parent = scope.parent; + var parent = $rootScope.parent; var child = doc.find('input').scope().child; var input = child.text; expect(parent).toBeDefined(); @@ -102,5 +102,5 @@ describe('form', function() { input.$emit('$valid', 'myRule'); expect(parent.$error.myRule).toBeUndefined(); expect(child.$error.myRule).toBeUndefined(); - }); + })); }); diff --git a/test/widget/inputSpec.js b/test/widget/inputSpec.js index 179f8156e47b..8a35407bbd82 100644 --- a/test/widget/inputSpec.js +++ b/test/widget/inputSpec.js @@ -2,10 +2,13 @@ describe('widget: input', function() { var compile = null, element = null, scope = null, defer = null; + var $compile = null; var doc = null; - beforeEach(function() { - scope = null; + beforeEach(inject(function($rootScope, $compile, $browser) { + scope = $rootScope; + defer = $browser.defer; + set$compile($compile); element = null; compile = function(html, parent) { if (parent) { @@ -14,12 +17,13 @@ describe('widget: input', function() { } else { element = jqLite(html); } - scope = angular.compile(element)(); + $compile(element)(scope); scope.$apply(); - defer = scope.$service('$browser').defer; return scope; }; - }); + })); + + function set$compile(c) { $compile = c; } afterEach(function() { dealoc(element); @@ -28,8 +32,7 @@ describe('widget: input', function() { describe('text', function() { - var scope = null, - form = null, + var form = null, formElement = null, inputElement = null; @@ -41,7 +44,7 @@ describe('widget: input', function() { formElement = doc = angular.element('
                          '); inputElement = formElement.find('input'); - scope = angular.compile(doc)(); + $compile(doc)(scope); form = formElement.inheritedData('$form'); }; @@ -85,24 +88,24 @@ describe('widget: input', function() { }; inputElement.val(' a '); browserTrigger(inputElement); - scope.$service('$browser').defer.flush(); + defer.flush(); expect(scope.name).toEqual('a'); expect(log).toEqual('change();'); }); - it('should change non-html5 types to text', function() { + it('should change non-html5 types to text', inject(function($rootScope, $compile) { doc = angular.element('
                          '); - scope = angular.compile(doc)(); + $compile(doc)($rootScope); expect(doc.find('input').attr('type')).toEqual('text'); - }); + })); - it('should not change html5 types to text', function() { + it('should not change html5 types to text', inject(function($rootScope, $compile) { doc = angular.element('
                          '); - scope = angular.compile(doc)(); + $compile(doc)($rootScope); expect(doc.find('input')[0].getAttribute('type')).toEqual('number'); - }); + })); }); @@ -125,7 +128,7 @@ describe('widget: input', function() { element.val('Kai'); browserTrigger(element, 'change'); - scope.$service('$browser').defer.flush(); + defer.flush(); expect(scope.name).toEqual('Kai'); }); @@ -137,7 +140,7 @@ describe('widget: input', function() { expect(scope.name).toEqual("Misko"); expect(scope.count).toEqual(0); browserTrigger(element, 'keydown'); - scope.$service('$browser').defer.flush(); + defer.flush(); expect(scope.name).toEqual("Misko"); expect(scope.count).toEqual(0); }); @@ -163,7 +166,7 @@ describe('widget: input', function() { element.val('1, 2, 3'); browserTrigger(element); - scope.$service('$browser').defer.flush(); + defer.flush(); expect(scope.list).toEqual(['1', '2', '3']); }); @@ -188,7 +191,7 @@ describe('widget: input', function() { } catch (e){} scope.$element.val('123X'); browserTrigger(scope.$element, 'change'); - scope.$service('$browser').defer.flush(); + defer.flush(); expect(scope.$element.val()).toEqual('123X'); expect(scope.age).toEqual(123); expect(scope.$element).toBeInvalid(); @@ -203,25 +206,25 @@ describe('widget: input', function() { scope.$element.val('a '); browserTrigger(scope.$element, 'change'); - scope.$service('$browser').defer.flush(); + defer.flush(); expect(scope.$element.val()).toEqual('a '); expect(scope.list).toEqual(['a']); scope.$element.val('a ,'); browserTrigger(scope.$element, 'change'); - scope.$service('$browser').defer.flush(); + defer.flush(); expect(scope.$element.val()).toEqual('a ,'); expect(scope.list).toEqual(['a']); scope.$element.val('a , '); browserTrigger(scope.$element, 'change'); - scope.$service('$browser').defer.flush(); + defer.flush(); expect(scope.$element.val()).toEqual('a , '); expect(scope.list).toEqual(['a']); scope.$element.val('a , b'); browserTrigger(scope.$element, 'change'); - scope.$service('$browser').defer.flush(); + defer.flush(); expect(scope.$element.val()).toEqual('a , b'); expect(scope.list).toEqual(['a', 'b']); }); @@ -290,9 +293,9 @@ describe('widget: input', function() { }); - it("should process required", function() { + it("should process required", inject(function($formFactory) { compile('', jqLite(document.body)); - expect(scope.$service('$formFactory').rootForm.p.$required).toBe(true); + expect($formFactory.rootForm.p.$required).toBe(true); expect(element.hasClass('ng-invalid')).toBeTruthy(); scope.price = 'xxx'; @@ -301,9 +304,9 @@ describe('widget: input', function() { element.val(''); browserTrigger(element); - scope.$service('$browser').defer.flush(); + defer.flush(); expect(element.hasClass('ng-invalid')).toBeTruthy(); - }); + })); it('should allow bindings on ng:required', function() { @@ -325,7 +328,7 @@ describe('widget: input', function() { element.val('abc'); browserTrigger(element); - scope.$service('$browser').defer.flush(); + defer.flush(); expect(element).toBeValid(); }); @@ -445,45 +448,43 @@ describe('widget: input', function() { }); - it('should report error on assignment error', function() { + it('should report error on assignment error', inject(function($log) { expect(function() { compile(''); }).toThrow("Syntax Error: Token '''' is an unexpected token at column 7 of the expression [throw ''] starting at ['']."); - $logMock.error.logs.shift(); - }); + $log.error.logs.shift(); + })); }); describe('scope declaration', function() { - it('should read the declaration from scope', function() { - var input, $formFactory; - element = angular.element(''); - scope = angular.scope(); - scope.MyType = function($f, i) { + it('should read the declaration from scope', inject(function($rootScope, $compile, $formFactory) { + var input, formFactory; + var element = angular.element(''); + $rootScope.MyType = function($f, i) { input = i; - $formFactory = $f; + formFactory = $f; }; - scope.MyType.$inject = ['$formFactory']; + $rootScope.MyType.$inject = ['$formFactory', '$element']; - angular.compile(element)(scope); + $compile(element)($rootScope); - expect($formFactory).toBe(scope.$service('$formFactory')); + expect(formFactory).toBe($formFactory); expect(input[0]).toBe(element[0]); - }); + })); - it('should throw an error of Cntoroller not declared in scope', function() { + it('should throw an error of Controller not declared in scope', inject(function($rootScope, $compile) { var input, $formFactory; - element = angular.element(''); + var element = angular.element(''); var error; try { - scope = angular.scope(); - angular.compile(element)(scope); + $compile(element)($rootScope); error = 'no error thrown'; } catch (e) { error = e; } expect(error.message).toEqual("Argument 'DontExist' is not a function, got undefined"); - }); + })); }); @@ -522,7 +523,7 @@ describe('widget: input', function() { if (value != undefined) { scope.$element.val(value); browserTrigger(element, 'keydown'); - scope.$service('$browser').defer.flush(); + defer.flush(); } scope.$digest(); } @@ -580,16 +581,16 @@ describe('widget: input', function() { {'ng:maxlength': 3}); - it('should throw an error when scope pattern can\'t be found', function() { - var el = jqLite(''), - scope = angular.compile(el)(); + it('should throw an error when scope pattern can\'t be found', inject(function($rootScope, $compile) { + var el = jqLite(''); + $compile(el)($rootScope); el.val('xx'); browserTrigger(el, 'keydown'); - expect(function() { scope.$service('$browser').defer.flush(); }). + expect(function() { defer.flush(); }). toThrow('Expected fooRegexp to be a RegExp but was undefined'); dealoc(el); - }); + })); }); }); diff --git a/test/widget/selectSpec.js b/test/widget/selectSpec.js index c3fdc2e6fc83..5d92e674a693 100644 --- a/test/widget/selectSpec.js +++ b/test/widget/selectSpec.js @@ -1,10 +1,10 @@ 'use strict'; describe('select', function() { - var compile = null, element = null, scope = null, $formFactory = null; + var compile = null, element = null, scope = null; - beforeEach(function() { - scope = null; + beforeEach(inject(function($compile, $rootScope) { + scope = $rootScope; element = null; compile = function(html, parent) { if (parent) { @@ -13,12 +13,11 @@ describe('select', function() { } else { element = jqLite(html); } - scope = angular.compile(element)(); + $compile(element)($rootScope); scope.$apply(); - $formFactory = scope.$service('$formFactory'); return scope; }; - }); + })); afterEach(function() { dealoc(element); @@ -41,7 +40,7 @@ describe('select', function() { expect(scope.$element.text()).toBe('foobarC'); }); - it('should require', function() { + it('should require', inject(function($formFactory) { compile('' + @@ -91,7 +90,7 @@ describe('select', function() { expect(element[0].childNodes[0].selected).toEqual(true); }); - it('should require', function() { + it('should require', inject(function($formFactory) { compile(''); }).toThrow("Expected ng:options in form of '_select_ (as _label_)? for (_key_,)?_value_ in" + " _collection_' but got 'i dont parse'."); - }); + })); it('should render a list', function() { createSingleSelect(); diff --git a/test/widgetsSpec.js b/test/widgetsSpec.js index e75b2592543b..82aa4956c519 100644 --- a/test/widgetsSpec.js +++ b/test/widgetsSpec.js @@ -1,165 +1,153 @@ 'use strict'; describe("widget", function() { - var compile = null, element = null, scope = null; - - beforeEach(function() { - scope = null; - element = null; - compile = function(html, parent) { - if (parent) { - parent.html(html); - element = parent.children(); - } else { - element = jqLite(html); - } - scope = angular.compile(element)(); - scope.$apply(); - return scope; - }; - }); - - afterEach(function() { - dealoc(element); - }); - - - describe('ng:switch', function() { - it('should switch on value change', function() { - compile('' + + beforeEach(inject(function($provide){ + $provide.factory('$xhrCache', ['$xhr.cache', identity]); + })); + + describe('ng:switch', inject(function($rootScope, $compile) { + it('should switch on value change', inject(function($rootScope, $compile) { + var element = $compile( + '' + '
                          first:{{name}}
                          ' + '
                          second:{{name}}
                          ' + '
                          true:{{name}}
                          ' + - '
                          '); + '
                          ')($rootScope); expect(element.html()).toEqual(''); - scope.select = 1; - scope.$apply(); + $rootScope.select = 1; + $rootScope.$apply(); expect(element.text()).toEqual('first:'); - scope.name="shyam"; - scope.$apply(); + $rootScope.name="shyam"; + $rootScope.$apply(); expect(element.text()).toEqual('first:shyam'); - scope.select = 2; - scope.$apply(); + $rootScope.select = 2; + $rootScope.$apply(); expect(element.text()).toEqual('second:shyam'); - scope.name = 'misko'; - scope.$apply(); + $rootScope.name = 'misko'; + $rootScope.$apply(); expect(element.text()).toEqual('second:misko'); - scope.select = true; - scope.$apply(); + $rootScope.select = true; + $rootScope.$apply(); expect(element.text()).toEqual('true:misko'); - }); - - it('should switch on switch-when-default', function() { - compile('' + - '
                          one
                          ' + - '
                          other
                          ' + - '
                          '); - scope.$apply(); + })); + + + it('should switch on switch-when-default', inject(function($rootScope, $compile) { + var element = $compile( + '' + + '
                          one
                          ' + + '
                          other
                          ' + + '
                          ')($rootScope); + $rootScope.$apply(); expect(element.text()).toEqual('other'); - scope.select = 1; - scope.$apply(); + $rootScope.select = 1; + $rootScope.$apply(); expect(element.text()).toEqual('one'); - }); - - it('should call change on switch', function() { - var scope = angular.compile('
                          {{name}}
                          ')(); - scope.url = 'a'; - scope.$apply(); - expect(scope.name).toEqual(undefined); - expect(scope.$element.text()).toEqual('works'); - dealoc(scope); - }); - - }); - - - describe('ng:include', function() { - it('should include on external file', function() { + })); + + + it('should call change on switch', inject(function($rootScope, $compile) { + var element = $compile( + '' + + '
                          {{name}}
                          ' + + '
                          ')($rootScope); + $rootScope.url = 'a'; + $rootScope.$apply(); + expect($rootScope.name).toEqual(undefined); + expect(element.text()).toEqual('works'); + })); + })); + + + describe('ng:include', inject(function($rootScope, $compile) { + it('should include on external file', inject(function($rootScope, $compile, $xhrCache) { var element = jqLite(''); - var scope = angular.compile(element)(); - scope.childScope = scope.$new(); - scope.childScope.name = 'misko'; - scope.url = 'myUrl'; - scope.$service('$xhr.cache').data.myUrl = {value:'{{name}}'}; - scope.$digest(); + var element = $compile(element)($rootScope); + $rootScope.childScope = $rootScope.$new(); + $rootScope.childScope.name = 'misko'; + $rootScope.url = 'myUrl'; + $xhrCache.data.myUrl = {value:'{{name}}'}; + $rootScope.$digest(); expect(element.text()).toEqual('misko'); - dealoc(scope); - }); + })); - it('should remove previously included text if a falsy value is bound to src', function() { + + it('should remove previously included text if a falsy value is bound to src', + inject(function($rootScope, $compile, $xhrCache) { var element = jqLite(''); - var scope = angular.compile(element)(); - scope.childScope = scope.$new(); - scope.childScope.name = 'igor'; - scope.url = 'myUrl'; - scope.$service('$xhr.cache').data.myUrl = {value:'{{name}}'}; - scope.$digest(); + var element = $compile(element)($rootScope); + $rootScope.childScope = $rootScope.$new(); + $rootScope.childScope.name = 'igor'; + $rootScope.url = 'myUrl'; + $xhrCache.data.myUrl = {value:'{{name}}'}; + $rootScope.$digest(); expect(element.text()).toEqual('igor'); - scope.url = undefined; - scope.$digest(); + $rootScope.url = undefined; + $rootScope.$digest(); expect(element.text()).toEqual(''); - dealoc(scope); - }); + })); - it('should allow this for scope', function() { + + it('should allow this for scope', inject(function($rootScope, $compile, $xhrCache) { var element = jqLite(''); - var scope = angular.compile(element)(); - scope.url = 'myUrl'; - scope.$service('$xhr.cache').data.myUrl = {value:'{{"abc"}}'}; - scope.$digest(); + var element = $compile(element)($rootScope); + $rootScope.url = 'myUrl'; + $xhrCache.data.myUrl = {value:'{{"abc"}}'}; + $rootScope.$digest(); // TODO(misko): because we are using scope==this, the eval gets registered // during the flush phase and hence does not get called. // I don't think passing 'this' makes sense. Does having scope on ng:include makes sense? - // should we make scope="this" ilegal? - scope.$digest(); + // should we make scope="this" illegal? + $rootScope.$digest(); expect(element.text()).toEqual('abc'); - dealoc(element); - }); + })); - it('should evaluate onload expression when a partial is loaded', function() { + + it('should evaluate onload expression when a partial is loaded', + inject(function($rootScope, $compile, $xhrCache) { var element = jqLite(''); - var scope = angular.compile(element)(); + var element = $compile(element)($rootScope); - expect(scope.loaded).not.toBeDefined(); + expect($rootScope.loaded).not.toBeDefined(); - scope.url = 'myUrl'; - scope.$service('$xhr.cache').data.myUrl = {value:'my partial'}; - scope.$digest(); + $rootScope.url = 'myUrl'; + $xhrCache.data.myUrl = {value:'my partial'}; + $rootScope.$digest(); expect(element.text()).toEqual('my partial'); - expect(scope.loaded).toBe(true); - dealoc(element); - }); + expect($rootScope.loaded).toBe(true); + })); - it('should destroy old scope', function() { + + it('should destroy old scope', inject(function($rootScope, $compile, $xhrCache) { var element = jqLite(''); - var scope = angular.compile(element)(); + var element = $compile(element)($rootScope); - expect(scope.$$childHead).toBeFalsy(); + expect($rootScope.$$childHead).toBeFalsy(); - scope.url = 'myUrl'; - scope.$service('$xhr.cache').data.myUrl = {value:'my partial'}; - scope.$digest(); - expect(scope.$$childHead).toBeTruthy(); + $rootScope.url = 'myUrl'; + $xhrCache.data.myUrl = {value:'my partial'}; + $rootScope.$digest(); + expect($rootScope.$$childHead).toBeTruthy(); - scope.url = null; - scope.$digest(); - expect(scope.$$childHead).toBeFalsy(); - dealoc(element); - }); - }); + $rootScope.url = null; + $rootScope.$digest(); + expect($rootScope.$$childHead).toBeFalsy(); + })); + })); - describe('a', function() { - it('should prevent default action to be executed when href is empty', function() { + describe('a', inject(function($rootScope, $compile) { + it('should prevent default action to be executed when href is empty', + inject(function($rootScope, $compile) { var orgLocation = document.location.href, preventDefaultCalled = false, event; - compile('empty link'); + var element = $compile('empty link')($rootScope); if (msie < 9) { @@ -171,7 +159,8 @@ describe("widget", function() { } else { event = document.createEvent('MouseEvent'); - event.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + event.initMouseEvent( + 'click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); event.preventDefaultOrg = event.preventDefault; event.preventDefault = function() { @@ -185,185 +174,206 @@ describe("widget", function() { } expect(document.location.href).toEqual(orgLocation); - }); - }); + })); + })); - describe('@ng:repeat', function() { - it('should ng:repeat over array', function() { - var scope = compile('
                          '); + describe('@ng:repeat', inject(function($rootScope, $compile) { + it('should ng:repeat over array', inject(function($rootScope, $compile) { + var element = $compile( + '
                            ' + + '
                          • ' + + '
                          ')($rootScope); Array.prototype.extraProperty = "should be ignored"; // INIT - scope.items = ['misko', 'shyam']; - scope.$digest(); + $rootScope.items = ['misko', 'shyam']; + $rootScope.$digest(); expect(element.find('li').length).toEqual(2); expect(element.text()).toEqual('misko;shyam;'); delete Array.prototype.extraProperty; // GROW - scope.items = ['adam', 'kai', 'brad']; - scope.$digest(); + $rootScope.items = ['adam', 'kai', 'brad']; + $rootScope.$digest(); expect(element.find('li').length).toEqual(3); expect(element.text()).toEqual('adam;kai;brad;'); // SHRINK - scope.items = ['brad']; - scope.$digest(); + $rootScope.items = ['brad']; + $rootScope.$digest(); expect(element.find('li').length).toEqual(1); expect(element.text()).toEqual('brad;'); - }); + })); - it('should ng:repeat over object', function() { - var scope = compile('
                          '); - scope.items = {misko:'swe', shyam:'set'}; - scope.$digest(); + it('should ng:repeat over object', inject(function($rootScope, $compile) { + var element = $compile( + '
                            ' + + '
                          • ' + + '
                          ')($rootScope); + $rootScope.items = {misko:'swe', shyam:'set'}; + $rootScope.$digest(); expect(element.text()).toEqual('misko:swe;shyam:set;'); - }); + })); - it('should not ng:repeat over parent properties', function() { + it('should not ng:repeat over parent properties', inject(function($rootScope, $compile) { var Class = function() {}; Class.prototype.abc = function() {}; Class.prototype.value = 'abc'; - var scope = compile('
                          '); - scope.items = new Class(); - scope.items.name = 'value'; - scope.$digest(); + var element = $compile( + '
                            ' + + '
                          • ' + + '
                          ')($rootScope); + $rootScope.items = new Class(); + $rootScope.items.name = 'value'; + $rootScope.$digest(); expect(element.text()).toEqual('name:value;'); - }); + })); - it('should error on wrong parsing of ng:repeat', function() { + it('should error on wrong parsing of ng:repeat', inject(function($rootScope, $compile, $log) { expect(function() { - compile('
                          '); + var element = $compile('
                          ')($rootScope); }).toThrow("Expected ng:repeat in form of '_item_ in _collection_' but got 'i dont parse'."); - $logMock.error.logs.shift(); - }); + $log.error.logs.shift(); + })); - it('should expose iterator offset as $index when iterating over arrays', function() { - var scope = compile('
                          '); - scope.items = ['misko', 'shyam', 'frodo']; - scope.$digest(); + it('should expose iterator offset as $index when iterating over arrays', + inject(function($rootScope, $compile) { + var element = $compile( + '
                            ' + + '
                          • ' + + '
                          ')($rootScope); + $rootScope.items = ['misko', 'shyam', 'frodo']; + $rootScope.$digest(); expect(element.text()).toEqual('misko0|shyam1|frodo2|'); - }); + })); - it('should expose iterator offset as $index when iterating over objects', function() { - var scope = compile('
                          '); - scope.items = {'misko':'m', 'shyam':'s', 'frodo':'f'}; - scope.$digest(); + it('should expose iterator offset as $index when iterating over objects', + inject(function($rootScope, $compile) { + var element = $compile( + '
                            ' + + '
                          • ' + + '
                          ')($rootScope); + $rootScope.items = {'misko':'m', 'shyam':'s', 'frodo':'f'}; + $rootScope.$digest(); expect(element.text()).toEqual('frodo:f0|misko:m1|shyam:s2|'); - }); + })); - it('should expose iterator position as $position when iterating over arrays', function() { - var scope = compile('
                          '); - scope.items = ['misko', 'shyam', 'doug']; - scope.$digest(); + it('should expose iterator position as $position when iterating over arrays', + inject(function($rootScope, $compile) { + var element = $compile( + '
                            ' + + '
                          • ' + + '
                          ')($rootScope); + $rootScope.items = ['misko', 'shyam', 'doug']; + $rootScope.$digest(); expect(element.text()).toEqual('misko:first|shyam:middle|doug:last|'); - scope.items.push('frodo'); - scope.$digest(); + $rootScope.items.push('frodo'); + $rootScope.$digest(); expect(element.text()).toEqual('misko:first|shyam:middle|doug:middle|frodo:last|'); - scope.items.pop(); - scope.items.pop(); - scope.$digest(); + $rootScope.items.pop(); + $rootScope.items.pop(); + $rootScope.$digest(); expect(element.text()).toEqual('misko:first|shyam:last|'); - }); + })); - it('should expose iterator position as $position when iterating over objects', function() { - var scope = compile( + it('should expose iterator position as $position when iterating over objects', + inject(function($rootScope, $compile) { + var element = $compile( '
                            ' + '
                          • ' + '
                          • ' + - '
                          '); - scope.items = {'misko':'m', 'shyam':'s', 'doug':'d', 'frodo':'f'}; - scope.$digest(); + '
                        ')($rootScope); + $rootScope.items = {'misko':'m', 'shyam':'s', 'doug':'d', 'frodo':'f'}; + $rootScope.$digest(); expect(element.text()).toEqual('doug:d:first|frodo:f:middle|misko:m:middle|shyam:s:last|'); - delete scope.items.doug; - delete scope.items.frodo; - scope.$digest(); + delete $rootScope.items.doug; + delete $rootScope.items.frodo; + $rootScope.$digest(); expect(element.text()).toEqual('misko:m:first|shyam:s:last|'); - }); + })); - it('should ignore $ and $$ properties', function() { - var scope = compile('
                        • {{i}}|
                        '); - scope.items = ['a', 'b', 'c']; - scope.items.$$hashkey = 'xxx'; - scope.items.$root = 'yyy'; - scope.$digest(); + it('should ignore $ and $$ properties', inject(function($rootScope, $compile) { + var element = $compile('
                        • {{i}}|
                        ')($rootScope); + $rootScope.items = ['a', 'b', 'c']; + $rootScope.items.$$hashkey = 'xxx'; + $rootScope.items.$root = 'yyy'; + $rootScope.$digest(); expect(element.text()).toEqual('a|b|c|'); - }); + })); - it('should repeat over nested arrays', function() { - var scope = compile('
                          ' + - '
                        • ' + - '
                          {{group}}|
                          X' + - '
                        • ' + - '
                        '); - scope.groups = [['a', 'b'], ['c','d']]; - scope.$digest(); + it('should repeat over nested arrays', inject(function($rootScope, $compile) { + var element = $compile( + '
                          ' + + '
                        • ' + + '
                          {{group}}|
                          X' + + '
                        • ' + + '
                        ')($rootScope); + $rootScope.groups = [['a', 'b'], ['c','d']]; + $rootScope.$digest(); expect(element.text()).toEqual('a|b|Xc|d|X'); - }); + })); - it('should ignore non-array element properties when iterating over an array', function() { - var scope = compile('
                        • {{item}}|
                        '); - scope.array = ['a', 'b', 'c']; - scope.array.foo = '23'; - scope.array.bar = function() {}; - scope.$digest(); + it('should ignore non-array element properties when iterating over an array', + inject(function($rootScope, $compile) { + var element = $compile('
                        • {{item}}|
                        ')($rootScope); + $rootScope.array = ['a', 'b', 'c']; + $rootScope.array.foo = '23'; + $rootScope.array.bar = function() {}; + $rootScope.$digest(); expect(element.text()).toBe('a|b|c|'); - }); + })); - it('should iterate over non-existent elements of a sparse array', function() { - var scope = compile('
                        • {{item}}|
                        '); - scope.array = ['a', 'b']; - scope.array[4] = 'c'; - scope.array[6] = 'd'; - scope.$digest(); + it('should iterate over non-existent elements of a sparse array', + inject(function($rootScope, $compile) { + var element = $compile('
                        • {{item}}|
                        ')($rootScope); + $rootScope.array = ['a', 'b']; + $rootScope.array[4] = 'c'; + $rootScope.array[6] = 'd'; + $rootScope.$digest(); expect(element.text()).toBe('a|b|||c||d|'); - }); + })); describe('stability', function() { - var a, b, c, d, scope, lis; + var a, b, c, d, lis, element; - beforeEach(function() { - scope = compile( + beforeEach(inject(function($rootScope, $compile) { + element = $compile( '
                          ' + - '
                        • ' + - '
                        • ' + - '
                        '); + '
                      • ' + + '
                      ')($rootScope); a = {}; b = {}; c = {}; d = {}; - scope.items = [a, b, c]; - scope.$digest(); + $rootScope.items = [a, b, c]; + $rootScope.$digest(); lis = element.find('li'); - }); + })); - it('should preserve the order of elements', function() { - scope.items = [a, c, d]; - scope.$digest(); + it('should preserve the order of elements', inject(function($rootScope, $compile) { + $rootScope.items = [a, c, d]; + $rootScope.$digest(); var newElements = element.find('li'); expect(newElements[0]).toEqual(lis[0]); expect(newElements[1]).toEqual(lis[2]); expect(newElements[2]).not.toEqual(lis[1]); - }); + })); - it('should support duplicates', function() { - scope.items = [a, a, b, c]; - scope.$digest(); + it('should support duplicates', inject(function($rootScope, $compile) { + $rootScope.items = [a, a, b, c]; + $rootScope.$digest(); var newElements = element.find('li'); expect(newElements[0]).toEqual(lis[0]); expect(newElements[1]).not.toEqual(lis[0]); @@ -371,170 +381,168 @@ describe("widget", function() { expect(newElements[3]).toEqual(lis[2]); lis = newElements; - scope.$digest(); + $rootScope.$digest(); newElements = element.find('li'); expect(newElements[0]).toEqual(lis[0]); expect(newElements[1]).toEqual(lis[1]); expect(newElements[2]).toEqual(lis[2]); expect(newElements[3]).toEqual(lis[3]); - scope.$digest(); + $rootScope.$digest(); newElements = element.find('li'); expect(newElements[0]).toEqual(lis[0]); expect(newElements[1]).toEqual(lis[1]); expect(newElements[2]).toEqual(lis[2]); expect(newElements[3]).toEqual(lis[3]); - }); + })); - it('should remove last item when one duplicate instance is removed', function() { - scope.items = [a, a, a]; - scope.$digest(); + it('should remove last item when one duplicate instance is removed', + inject(function($rootScope, $compile) { + $rootScope.items = [a, a, a]; + $rootScope.$digest(); lis = element.find('li'); - scope.items = [a, a]; - scope.$digest(); + $rootScope.items = [a, a]; + $rootScope.$digest(); var newElements = element.find('li'); expect(newElements.length).toEqual(2); expect(newElements[0]).toEqual(lis[0]); expect(newElements[1]).toEqual(lis[1]); - }); + })); - it('should reverse items when the collection is reversed', function() { - scope.items = [a, b, c]; - scope.$digest(); + it('should reverse items when the collection is reversed', + inject(function($rootScope, $compile) { + $rootScope.items = [a, b, c]; + $rootScope.$digest(); lis = element.find('li'); - scope.items = [c, b, a]; - scope.$digest(); + $rootScope.items = [c, b, a]; + $rootScope.$digest(); var newElements = element.find('li'); expect(newElements.length).toEqual(3); expect(newElements[0]).toEqual(lis[2]); expect(newElements[1]).toEqual(lis[1]); expect(newElements[2]).toEqual(lis[0]); - }); + })); }); - }); + })); describe('@ng:non-bindable', function() { - it('should prevent compilation of the owning element and its children', function() { - var scope = compile('
                      '); - scope.name = 'misko'; - scope.$digest(); + it('should prevent compilation of the owning element and its children', + inject(function($rootScope, $compile) { + var element = $compile('
                      ')($rootScope); + $rootScope.name = 'misko'; + $rootScope.$digest(); expect(element.text()).toEqual(''); - }); + })); }); describe('ng:view', function() { - var rootScope, $route, $location, $browser; - - beforeEach(function() { - rootScope = angular.compile('')(); - $route = rootScope.$service('$route'); - $location = rootScope.$service('$location'); - $browser = rootScope.$service('$browser'); - }); - - afterEach(function() { - dealoc(rootScope); - }); + var element; + beforeEach(inject(function($rootScope, $compile) { + element = $compile('')($rootScope); + })); - it('should do nothing when no routes are defined', function() { + it('should do nothing when no routes are defined', + inject(function($rootScope, $compile, $location) { $location.path('/unknown'); - rootScope.$digest(); - expect(rootScope.$element.text()).toEqual(''); - }); + $rootScope.$digest(); + expect(element.text()).toEqual(''); + })); - it('should load content via xhr when route changes', function() { + it('should load content via xhr when route changes', + inject(function($rootScope, $compile, $browser, $location, $route) { $route.when('/foo', {template: 'myUrl1'}); $route.when('/bar', {template: 'myUrl2'}); - expect(rootScope.$element.text()).toEqual(''); + expect(element.text()).toEqual(''); $location.path('/foo'); $browser.xhr.expectGET('myUrl1').respond('
                      {{1+3}}
                      '); - rootScope.$digest(); + $rootScope.$digest(); $browser.xhr.flush(); - expect(rootScope.$element.text()).toEqual('4'); + expect(element.text()).toEqual('4'); $location.path('/bar'); $browser.xhr.expectGET('myUrl2').respond('angular is da best'); - rootScope.$digest(); + $rootScope.$digest(); $browser.xhr.flush(); - expect(rootScope.$element.text()).toEqual('angular is da best'); - }); + expect(element.text()).toEqual('angular is da best'); + })); - it('should remove all content when location changes to an unknown route', function() { + it('should remove all content when location changes to an unknown route', + inject(function($rootScope, $compile, $location, $browser, $route) { $route.when('/foo', {template: 'myUrl1'}); $location.path('/foo'); $browser.xhr.expectGET('myUrl1').respond('
                      {{1+3}}
                      '); - rootScope.$digest(); + $rootScope.$digest(); $browser.xhr.flush(); - expect(rootScope.$element.text()).toEqual('4'); + expect(element.text()).toEqual('4'); $location.path('/unknown'); - rootScope.$digest(); - expect(rootScope.$element.text()).toEqual(''); - }); + $rootScope.$digest(); + expect($rootScope.$element.text()).toEqual(''); + })); - it('should chain scopes and propagate evals to the child scope', function() { + it('should chain scopes and propagate evals to the child scope', + inject(function($rootScope, $compile, $location, $browser, $route) { $route.when('/foo', {template: 'myUrl1'}); - rootScope.parentVar = 'parent'; + $rootScope.parentVar = 'parent'; $location.path('/foo'); $browser.xhr.expectGET('myUrl1').respond('
                      {{parentVar}}
                      '); - rootScope.$digest(); + $rootScope.$digest(); $browser.xhr.flush(); - expect(rootScope.$element.text()).toEqual('parent'); - - rootScope.parentVar = 'new parent'; - rootScope.$digest(); - expect(rootScope.$element.text()).toEqual('new parent'); - }); + expect(element.text()).toEqual('parent'); - it('should be possible to nest ng:view in ng:include', function() { - dealoc(rootScope); // we are about to override it. + $rootScope.parentVar = 'new parent'; + $rootScope.$digest(); + expect($rootScope.$element.text()).toEqual('new parent'); + })); - var myApp = angular.scope(); - var $browser = myApp.$service('$browser'); + it('should be possible to nest ng:view in ng:include', inject(function() { + var injector = angular.injector('ng', 'ngMock'); + var myApp = injector.get('$rootScope'); + var $browser = injector.get('$browser'); $browser.xhr.expectGET('includePartial.html').respond('view: '); - myApp.$service('$location').path('/foo'); + injector.get('$location').path('/foo'); - var $route = myApp.$service('$route'); + var $route = injector.get('$route'); $route.when('/foo', {controller: angular.noop, template: 'viewPartial.html'}); - rootScope = angular.compile( + var element = injector.get('$compile')( '
                      ' + - 'include: ' + - '
                      ')(myApp); - rootScope.$apply(); + 'include: ' + + '
')(myApp); + myApp.$apply(); $browser.xhr.expectGET('viewPartial.html').respond('content'); - rootScope.$digest(); + myApp.$digest(); $browser.xhr.flush(); - expect(rootScope.$element.text()).toEqual('include: view: content'); + expect(myApp.$element.text()).toEqual('include: view: content'); expect($route.current.template).toEqual('viewPartial.html'); - dealoc($route.current.scope); - }); + dealoc(myApp); + })); it('should initialize view template after the view controller was initialized even when ' + - 'templates were cached', function() { - // this is a test for a regression that was introduced by making the ng:view cache sync + 'templates were cached', inject(function($rootScope, $compile, $location, $browser, $route) { + //this is a test for a regression that was introduced by making the ng:view cache sync $route.when('/foo', {controller: ParentCtrl, template: 'viewPartial.html'}); - rootScope.log = []; + $rootScope.log = []; function ParentCtrl() { this.log.push('parent'); } - rootScope.ChildCtrl = function() { + $rootScope.ChildCtrl = function() { this.log.push('child'); }; @@ -543,42 +551,42 @@ describe("widget", function() { respond('
' + '
' + '
'); - rootScope.$apply(); + $rootScope.$apply(); $browser.xhr.flush(); - expect(rootScope.log).toEqual(['parent', 'init', 'child']); + expect($rootScope.log).toEqual(['parent', 'init', 'child']); $location.path('/'); - rootScope.$apply(); - expect(rootScope.log).toEqual(['parent', 'init', 'child']); + $rootScope.$apply(); + expect($rootScope.log).toEqual(['parent', 'init', 'child']); - rootScope.log = []; + $rootScope.log = []; $location.path('/foo'); - rootScope.$apply(); + $rootScope.$apply(); $browser.defer.flush(); - expect(rootScope.log).toEqual(['parent', 'init', 'child']); - }); + expect($rootScope.log).toEqual(['parent', 'init', 'child']); + })); it('should discard pending xhr callbacks if a new route is requested before the current ' + - 'finished loading', function() { + 'finished loading', inject(function($route, $rootScope, $location, $browser) { // this is a test for a bad race condition that affected feedback $route.when('/foo', {template: 'myUrl1'}); $route.when('/bar', {template: 'myUrl2'}); - expect(rootScope.$element.text()).toEqual(''); + expect($rootScope.$element.text()).toEqual(''); $location.path('/foo'); $browser.xhr.expectGET('myUrl1').respond('
{{1+3}}
'); - rootScope.$digest(); + $rootScope.$digest(); $location.path('/bar'); $browser.xhr.expectGET('myUrl2').respond('
{{1+1}}
'); - rootScope.$digest(); + $rootScope.$digest(); $browser.xhr.flush(); // now that we have to requests pending, flush! - expect(rootScope.$element.text()).toEqual('2'); - }); + expect($rootScope.$element.text()).toEqual('2'); + })); }); @@ -586,125 +594,129 @@ describe("widget", function() { describe('deal with pluralized strings without offset', function() { - beforeEach(function() { - compile('" + - ''); - }); - - it('should show single/plural strings', function() { - scope.email = 0; - scope.$digest(); + var element; + beforeEach(inject(function($rootScope, $compile) { + element = $compile( + '" + + '')($rootScope); + })); + + it('should show single/plural strings', inject(function($rootScope, $compile) { + $rootScope.email = 0; + $rootScope.$digest(); expect(element.text()).toBe('You have no new email'); - scope.email = '0'; - scope.$digest(); + $rootScope.email = '0'; + $rootScope.$digest(); expect(element.text()).toBe('You have no new email'); - scope.email = 1; - scope.$digest(); + $rootScope.email = 1; + $rootScope.$digest(); expect(element.text()).toBe('You have one new email'); - scope.email = 0.01; - scope.$digest(); + $rootScope.email = 0.01; + $rootScope.$digest(); expect(element.text()).toBe('You have 0.01 new emails'); - scope.email = '0.1'; - scope.$digest(); + $rootScope.email = '0.1'; + $rootScope.$digest(); expect(element.text()).toBe('You have 0.1 new emails'); - scope.email = 2; - scope.$digest(); + $rootScope.email = 2; + $rootScope.$digest(); expect(element.text()).toBe('You have 2 new emails'); - scope.email = -0.1; - scope.$digest(); + $rootScope.email = -0.1; + $rootScope.$digest(); expect(element.text()).toBe('You have -0.1 new emails'); - scope.email = '-0.01'; - scope.$digest(); + $rootScope.email = '-0.01'; + $rootScope.$digest(); expect(element.text()).toBe('You have -0.01 new emails'); - scope.email = -2; - scope.$digest(); + $rootScope.email = -2; + $rootScope.$digest(); expect(element.text()).toBe('You have -2 new emails'); - }); + })); - it('should show single/plural strings with mal-formed inputs', function() { - scope.email = ''; - scope.$digest(); + it('should show single/plural strings with mal-formed inputs', + inject(function($rootScope, $compile) { + $rootScope.email = ''; + $rootScope.$digest(); expect(element.text()).toBe(''); - scope.email = null; - scope.$digest(); + $rootScope.email = null; + $rootScope.$digest(); expect(element.text()).toBe(''); - scope.email = undefined; - scope.$digest(); + $rootScope.email = undefined; + $rootScope.$digest(); expect(element.text()).toBe(''); - scope.email = 'a3'; - scope.$digest(); + $rootScope.email = 'a3'; + $rootScope.$digest(); expect(element.text()).toBe(''); - scope.email = '011'; - scope.$digest(); + $rootScope.email = '011'; + $rootScope.$digest(); expect(element.text()).toBe('You have 11 new emails'); - scope.email = '-011'; - scope.$digest(); + $rootScope.email = '-011'; + $rootScope.$digest(); expect(element.text()).toBe('You have -11 new emails'); - scope.email = '1fff'; - scope.$digest(); + $rootScope.email = '1fff'; + $rootScope.$digest(); expect(element.text()).toBe('You have one new email'); - scope.email = '0aa22'; - scope.$digest(); + $rootScope.email = '0aa22'; + $rootScope.$digest(); expect(element.text()).toBe('You have no new email'); - scope.email = '000001'; - scope.$digest(); + $rootScope.email = '000001'; + $rootScope.$digest(); expect(element.text()).toBe('You have one new email'); - }); + })); }); describe('deal with pluralized strings with offset', function() { - it('should show single/plural strings with offset', function() { - compile("" + - ""); - scope.p1 = 'Igor'; - scope.p2 = 'Misko'; - - scope.viewCount = 0; - scope.$digest(); + it('should show single/plural strings with offset', inject(function($rootScope, $compile) { + var element = $compile( + "" + + "")($rootScope); + $rootScope.p1 = 'Igor'; + $rootScope.p2 = 'Misko'; + + $rootScope.viewCount = 0; + $rootScope.$digest(); expect(element.text()).toBe('Nobody is viewing.'); - scope.viewCount = 1; - scope.$digest(); + $rootScope.viewCount = 1; + $rootScope.$digest(); expect(element.text()).toBe('Igor is viewing.'); - scope.viewCount = 2; - scope.$digest(); + $rootScope.viewCount = 2; + $rootScope.$digest(); expect(element.text()).toBe('Igor and Misko are viewing.'); - scope.viewCount = 3; - scope.$digest(); + $rootScope.viewCount = 3; + $rootScope.$digest(); expect(element.text()).toBe('Igor, Misko and one other person are viewing.'); - scope.viewCount = 4; - scope.$digest(); + $rootScope.viewCount = 4; + $rootScope.$digest(); expect(element.text()).toBe('Igor, Misko and 2 other people are viewing.'); - }); + })); }); }); });